blob: 5f6bfd61c1a855dc0034a8818f07cec6d9741781 [file] [log] [blame]
Lorenz Brun2f9f3872021-09-29 19:48:08 +02001"""Rules for generating EFI unified kernel images. These are EFI-bootable PE/COFF files containing a stub loader,
2a kernel, and optional commandline and initramfs in one file.
3See https://systemd.io/BOOT_LOADER_SPECIFICATION/#type-2-efi-unified-kernel-images for more information.
4"""
5
6load("//build/toolchain/llvm-efi:transition.bzl", "build_efi_transition")
Mateusz Zalega8c2c7712022-01-25 19:42:21 +01007load("//metropolis/node/build:def.bzl", "VerityConfig")
Lorenz Brun2f9f3872021-09-29 19:48:08 +02008
9def _efi_unified_kernel_image_impl(ctx):
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010010 # Find the dependency paths to be passed to mkpayload.
11 deps = {
Lorenz Brunf099c092022-02-24 17:22:26 +010012 "linux": ctx.file.kernel,
Lorenz Brunf099c092022-02-24 17:22:26 +010013 "osrel": ctx.file.os_release,
14 "splash": ctx.file.splash,
15 "stub": ctx.file.stub,
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010016 }
Lorenz Brunf099c092022-02-24 17:22:26 +010017
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010018 # Since cmdline is a string attribute, put it into a file, then append
19 # that file to deps.
20 if ctx.attr.cmdline and ctx.attr.cmdline != "":
21 cmdline = ctx.actions.declare_file("cmdline")
Lorenz Brun2f9f3872021-09-29 19:48:08 +020022 ctx.actions.write(
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010023 output = cmdline,
Lorenz Brun2f9f3872021-09-29 19:48:08 +020024 content = ctx.attr.cmdline,
25 )
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010026 deps["cmdline"] = cmdline
Lorenz Brunf099c092022-02-24 17:22:26 +010027
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010028 # Get the dm-verity target table from VerityConfig provider.
29 if ctx.attr.verity:
Lorenz Brunf099c092022-02-24 17:22:26 +010030 deps["rootfs_dm_table"] = ctx.attr.verity[VerityConfig].table
31
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010032 # Format deps into command line arguments while keeping track of mkpayload
33 # runtime inputs.
Lorenz Brun2f9f3872021-09-29 19:48:08 +020034 args = []
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010035 inputs = []
36 for name, file in deps.items():
Lorenz Brunf099c092022-02-24 17:22:26 +010037 if file:
38 args.append("-{}={}".format(name, file.path))
39 inputs.append(file)
40
Lorenz Brun304d42c2022-02-24 17:53:08 +010041 for file in ctx.files.initrd:
42 args.append("-initrd={}".format(file.path))
43 inputs.append(file)
44
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010045 # Append the output parameter separately, as it doesn't belong with the
46 # runtime inputs.
47 image = ctx.actions.declare_file(ctx.attr.name + ".efi")
48 args.append("-output={}".format(image.path))
Lorenz Brunf099c092022-02-24 17:22:26 +010049
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010050 # Append the objcopy parameter separately, as it's not of File type, and
51 # it does not constitute an input, since it's part of the toolchain.
52 objcopy = ctx.attr._toolchain[platform_common.ToolchainInfo].objcopy_executable
53 args.append("-objcopy={}".format(objcopy))
Lorenz Brunf099c092022-02-24 17:22:26 +010054
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010055 # Run mkpayload.
Lorenz Brun2f9f3872021-09-29 19:48:08 +020056 ctx.actions.run(
Lorenz Brunf099c092022-02-24 17:22:26 +010057 mnemonic = "GenEFIKernelImage",
58 progress_message = "Generating EFI unified kernel image",
59 inputs = inputs,
60 outputs = [image],
61 executable = ctx.file._mkpayload,
62 arguments = args,
Lorenz Brun2f9f3872021-09-29 19:48:08 +020063 )
Lorenz Brunf099c092022-02-24 17:22:26 +010064
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010065 # Return the unified kernel image file.
66 return [DefaultInfo(files = depset([image]), runfiles = ctx.runfiles(files = [image]))]
Lorenz Brun2f9f3872021-09-29 19:48:08 +020067
68efi_unified_kernel_image = rule(
69 implementation = _efi_unified_kernel_image_impl,
70 attrs = {
71 "kernel": attr.label(
72 doc = "The Linux kernel executable bzImage. Needs to have EFI handover and EFI stub enabled.",
73 mandatory = True,
74 allow_single_file = True,
75 ),
76 "cmdline": attr.string(
77 doc = "The kernel commandline to be embedded.",
78 ),
Lorenz Brun304d42c2022-02-24 17:53:08 +010079 "initrd": attr.label_list(
80 doc = """
81 List of payloads to concatenate and supply as the initrd parameter to Linux when it boots.
82 The name stems from the time Linux booted from an initial ram disk (initrd), but it's now
83 a catch-all for a bunch of different larger payload for early Linux initialization.
84
85 In Linux 5.15 this can first contain an arbitrary amount of uncompressed cpio archives
86 with directories being optional which is accessed by earlycpio. This is used for both
87 early microcode loading and ACPI table overrides. This can then be followed by an arbitrary
88 amount of compressed cpio archives (even with different compression methods) which will
89 together make up the initramfs. The initramfs is only booted into if it contains either
90 /init or whatever file is specified as init= in cmdline. Technically depending on kernel
91 flags you might be able to supply an actual initrd, i.e. an image of a disk loaded into
92 RAM, but that has been deprecated for nearly 2 decades and should really not be used.
93
94 For kernels designed to run on physical machines this should at least contain microcode,
95 optionally followed by a compressed initramfs. For kernels only used in virtualized
96 setups the microcode can be left out and if no initramfs is needed this option can
97 be omitted completely.
98 """,
99 allow_files = True,
Lorenz Brun2f9f3872021-09-29 19:48:08 +0200100 ),
101 "os_release": attr.label(
102 doc = """
103 The os-release file identifying the operating system.
104 See https://www.freedesktop.org/software/systemd/man/os-release.html for format.
105 """,
106 allow_single_file = True,
107 ),
108 "splash": attr.label(
109 doc = "An image in BMP format which will be displayed as a splash screen until the kernel takes over.",
110 allow_single_file = True,
111 ),
112 "stub": attr.label(
113 doc = "The stub executable itself as a PE/COFF executable.",
114 default = "@efistub//:efistub",
115 allow_single_file = True,
116 executable = True,
117 cfg = build_efi_transition,
118 ),
Mateusz Zalega8c2c7712022-01-25 19:42:21 +0100119 "verity": attr.label(
120 doc = "The DeviceMapper Verity rootfs target table.",
121 allow_single_file = True,
122 providers = [DefaultInfo, VerityConfig],
123 ),
124 "_mkpayload": attr.label(
125 doc = "The mkpayload executable.",
126 default = "//metropolis/node/build/mkpayload",
127 allow_single_file = True,
128 executable = True,
129 cfg = "exec",
130 ),
Lorenz Brun2f9f3872021-09-29 19:48:08 +0200131 "_toolchain": attr.label(
132 doc = "The toolchain used for objcopy.",
133 default = "//build/toolchain/llvm-efi:efi_cc_suite",
134 providers = [platform_common.ToolchainInfo],
135 ),
136 # Allow for transitions to be attached to this rule.
137 "_whitelist_function_transition": attr.label(
138 default = "@bazel_tools//tools/whitelists/function_transition_whitelist",
139 ),
140 },
141)