1 // 2 // Copyright (C) 2022 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #pragma once 17 18 #include <utility> 19 #include <optional> 20 #include <string> 21 #include <vector> 22 23 #include "host/libs/config/cuttlefish_config.h" 24 #include "common/libs/utils/environment.h" 25 26 namespace cuttlefish { 27 28 // For licensing and build reproducibility reasons, pick up the bootloaders 29 // from the host Linux distribution (if present) and pack them into the 30 // automatically generated ESP. If the user wants their own bootloaders, 31 // they can use -esp_image=/path/to/esp.img to override, so we don't need 32 // to accommodate customizations of this packing process. 33 34 // Currently we only support Debian based distributions, and GRUB is built 35 // for those distros to always load grub.cfg from EFI/debian/grub.cfg, and 36 // nowhere else. If you want to add support for other distros, make the 37 // extra directories below and copy the initial grub.cfg there as well 38 // 39 // Currently the Cuttlefish bootloaders are built only for x86 (32-bit), 40 // ARM (QEMU only, 32-bit) and AArch64 (64-bit), and U-Boot will hard-code 41 // these search paths. Install all bootloaders to one of these paths. 42 // NOTE: For now, just ignore the 32-bit ARM version, as Debian doesn't 43 // build an EFI monolith for this architecture. 44 // These are the paths Debian installs the monoliths to. If another distro 45 // uses an alternative monolith path, add it to this table 46 static constexpr char kBootSrcPathIA32[] = "/usr/lib/grub/i386-efi/monolithic/grubia32.efi"; 47 static constexpr char kBootDestPathIA32[] = "/EFI/BOOT/BOOTIA32.EFI"; 48 49 static constexpr char kBootSrcPathAA64[] = "/usr/lib/grub/arm64-efi/monolithic/grubaa64.efi"; 50 static constexpr char kBootDestPathAA64[] = "/EFI/BOOT/BOOTAA64.EFI"; 51 52 static constexpr char kMultibootModuleSrcPathIA32[] = "/usr/lib/grub/i386-efi/multiboot.mod"; 53 static constexpr char kMultibootModuleDestPathIA32[] = "/EFI/modules/multiboot.mod"; 54 55 static constexpr char kMultibootModuleSrcPathAA64[] = "/usr/lib/grub/arm64-efi/multiboot.mod"; 56 static constexpr char kMultibootModuleDestPathAA64[] = "/EFI/modules/multiboot.mod"; 57 58 static constexpr char kKernelDestPath[] = "/vmlinuz"; 59 static constexpr char kInitrdDestPath[] = "/initrd"; 60 static constexpr char kZedbootDestPath[] = "/zedboot.zbi"; 61 static constexpr char kMultibootBinDestPath[] = "/multiboot.bin"; 62 63 // TODO(b/260338443, b/260337906) remove ubuntu and debian variations 64 // after migrating to grub-mkimage or adding grub binaries as a prebuilt 65 static constexpr char kGrubDebianConfigDestPath[] = "/EFI/debian/grub.cfg"; 66 static constexpr char kGrubUbuntuConfigDestPath[] = "/EFI/ubuntu/grub.cfg"; 67 static constexpr char kGrubConfigDestDirectoryPath[] = "/boot/grub"; 68 static constexpr char kGrubConfigDestPath[] = "/boot/grub/grub.cfg"; 69 70 const std::vector<std::string> kGrubModulesX86 = 71 {"normal", "configfile", "linux", "linuxefi", "multiboot", 72 "ls", "cat", "help", "fat", "part_msdos", "part_gpt"}; 73 static constexpr char kGrubModulesPath[] = "/usr/lib/grub/"; 74 static constexpr char kGrubModulesX86Name[] = "i386-efi"; 75 static constexpr char kGrubModulesArm64Name[] = "arm64-efi"; 76 77 class LinuxEspBuilder final { 78 public: 79 LinuxEspBuilder() = delete; LinuxEspBuilder(std::string image_path)80 LinuxEspBuilder(std::string image_path): image_path_(std::move(image_path)) {} 81 82 LinuxEspBuilder& Argument(std::string key, std::string value) &; 83 LinuxEspBuilder& Argument(std::string value) &; 84 LinuxEspBuilder& Root(std::string root) &; 85 LinuxEspBuilder& Kernel(std::string kernel) &; 86 LinuxEspBuilder& Initrd(std::string initrd) &; 87 LinuxEspBuilder& Architecture(Arch arch) &; 88 89 bool Build() const; 90 91 private: 92 std::string DumpConfig() const; 93 94 const std::string image_path_; 95 std::vector<std::pair<std::string, std::string>> arguments_; 96 std::vector<std::string> single_arguments_; 97 std::string root_; 98 std::string kernel_; 99 std::string initrd_; 100 std::optional<Arch> arch_; 101 }; 102 103 class FuchsiaEspBuilder { 104 public: 105 FuchsiaEspBuilder() = delete; FuchsiaEspBuilder(std::string image_path)106 FuchsiaEspBuilder(std::string image_path): image_path_(std::move(image_path)) {} 107 108 FuchsiaEspBuilder& MultibootBinary(std::string multiboot) &; 109 FuchsiaEspBuilder& Zedboot(std::string zedboot) &; 110 FuchsiaEspBuilder& Architecture(Arch arch) &; 111 112 bool Build() const; 113 114 private: 115 std::string DumpConfig() const; 116 117 const std::string image_path_; 118 std::string multiboot_bin_; 119 std::string zedboot_; 120 std::optional<Arch> arch_; 121 }; 122 123 bool NewfsMsdos(const std::string& data_image, int data_image_mb, 124 int offset_num_mb); 125 126 bool CanGenerateEsp(Arch arch); 127 128 } // namespace cuttlefish 129