blob: 1bd00e66c2d3ac991506e29c85913ea40da63922 [file] [log] [blame]
Tim Windelschmidt6d33a432025-02-04 14:34:25 +01001// Copyright The Monogon Project Authors.
2// SPDX-License-Identifier: Apache-2.0
3
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +01004package main
5
6import (
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +01007 _ "embed"
8 "fmt"
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +01009 "os"
10 "path/filepath"
11
12 "source.monogon.dev/go/logging"
13 "source.monogon.dev/osbase/blockdev"
14 "source.monogon.dev/osbase/build/mkimage/osimage"
15 "source.monogon.dev/osbase/efivarfs"
Jan Schär5fdca562025-04-14 11:33:29 +000016 "source.monogon.dev/osbase/oci"
17 ociosimage "source.monogon.dev/osbase/oci/osimage"
Jan Schärc1b6df42025-03-20 08:52:18 +000018 "source.monogon.dev/osbase/structfs"
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010019)
20
Jan Schär69b76872025-05-14 16:39:47 +000021//go:embed metropolis/node/abloader/abloader_bin.efi
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010022var abloader []byte
23
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010024// EnvInstallTarget environment variable which tells the takeover binary where
25// to install to
26const EnvInstallTarget = "TAKEOVER_INSTALL_TARGET"
27
28func installMetropolis(l logging.Leveled) error {
29 // Validate we are running via EFI.
30 if _, err := os.Stat("/sys/firmware/efi"); os.IsNotExist(err) {
Tim Windelschmidt1f51cf42024-10-01 17:04:28 +020031 // nolint:ST1005
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010032 return fmt.Errorf("Monogon OS can only be installed on EFI-booted machines, this one is not")
33 }
34
35 metropolisSpecRaw, err := os.ReadFile("/params.pb")
36 if err != nil {
37 return err
38 }
39
Jan Schär5fdca562025-04-14 11:33:29 +000040 image, err := oci.ReadLayout("/osimage")
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010041 if err != nil {
Jan Schär5fdca562025-04-14 11:33:29 +000042 return fmt.Errorf("failed to read OS image: %w", err)
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010043 }
44
Jan Schär5fdca562025-04-14 11:33:29 +000045 installParams, err := setupOSImageParams(image, metropolisSpecRaw, os.Getenv(EnvInstallTarget))
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010046 if err != nil {
47 return err
48 }
49
50 be, err := osimage.Write(installParams)
51 if err != nil {
52 return fmt.Errorf("failed to apply installation: %w", err)
53 }
54 bootEntryIdx, err := efivarfs.AddBootEntry(be)
55 if err != nil {
56 return fmt.Errorf("error creating EFI boot entry: %w", err)
57 }
58 if err := efivarfs.SetBootOrder(efivarfs.BootOrder{uint16(bootEntryIdx)}); err != nil {
59 return fmt.Errorf("error setting EFI boot order: %w", err)
60 }
61 l.Info("Metropolis installation completed")
62 return nil
63}
64
Jan Schär5fdca562025-04-14 11:33:29 +000065func setupOSImageParams(image *oci.Image, metropolisSpecRaw []byte, installTarget string) (*osimage.Params, error) {
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010066 rootDev, err := blockdev.Open(filepath.Join("/dev", installTarget))
67 if err != nil {
68 return nil, fmt.Errorf("failed to open root device: %w", err)
69 }
70
Jan Schär5fdca562025-04-14 11:33:29 +000071 osImage, err := ociosimage.Read(image)
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010072 if err != nil {
Jan Schär5fdca562025-04-14 11:33:29 +000073 return nil, fmt.Errorf("failed to read OS image: %w", err)
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010074 }
75
Jan Schär5fdca562025-04-14 11:33:29 +000076 efiPayload, err := osImage.Payload("kernel.efi")
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010077 if err != nil {
Jan Schär5fdca562025-04-14 11:33:29 +000078 return nil, fmt.Errorf("cannot open EFI payload in OS image: %w", err)
79 }
80 systemImage, err := osImage.Payload("system")
81 if err != nil {
82 return nil, fmt.Errorf("cannot open system image in OS image: %w", err)
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010083 }
84
85 return &osimage.Params{
86 PartitionSize: osimage.PartitionSizeInfo{
87 ESP: 384,
88 System: 4096,
89 Data: 128,
90 },
91 SystemImage: systemImage,
Jan Schärc1b6df42025-03-20 08:52:18 +000092 EFIPayload: efiPayload,
93 ABLoader: structfs.Bytes(abloader),
94 NodeParameters: structfs.Bytes(metropolisSpecRaw),
Tim Windelschmidt7a1b27d2024-02-22 23:54:58 +010095 Output: rootDev,
96 }, nil
97}