blob: 287f94d67a945a9df348e3430bb805952b33df15 [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
Lorenz Brun163525e2025-05-22 15:30:14 +02006load("@rules_cc//cc:action_names.bzl", "OBJ_COPY_ACTION_NAME")
7load("@rules_cc//cc:find_cc_toolchain.bzl", "CC_TOOLCHAIN_ATTRS", "find_cpp_toolchain", "use_cc_toolchain")
Tim Windelschmidtd4817492025-06-16 15:03:12 +02008load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
Lorenz Brun163525e2025-05-22 15:30:14 +02009load("//osbase/build:def.bzl", "build_static_transition")
Tim Windelschmidtbed76d92025-02-18 03:04:14 +010010load("//osbase/build/mkverity:def.bzl", "VerityInfo")
Lorenz Brun2f9f3872021-09-29 19:48:08 +020011
12def _efi_unified_kernel_image_impl(ctx):
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010013 # Find the dependency paths to be passed to mkpayload.
14 deps = {
Lorenz Brunf099c092022-02-24 17:22:26 +010015 "linux": ctx.file.kernel,
Lorenz Brunf099c092022-02-24 17:22:26 +010016 "osrel": ctx.file.os_release,
17 "splash": ctx.file.splash,
18 "stub": ctx.file.stub,
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010019 }
Lorenz Brunf099c092022-02-24 17:22:26 +010020
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010021 # Since cmdline is a string attribute, put it into a file, then append
22 # that file to deps.
23 if ctx.attr.cmdline and ctx.attr.cmdline != "":
24 cmdline = ctx.actions.declare_file("cmdline")
Lorenz Brun2f9f3872021-09-29 19:48:08 +020025 ctx.actions.write(
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010026 output = cmdline,
Lorenz Brun2f9f3872021-09-29 19:48:08 +020027 content = ctx.attr.cmdline,
28 )
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010029 deps["cmdline"] = cmdline
Lorenz Brunf099c092022-02-24 17:22:26 +010030
Tim Windelschmidt156248b2025-01-10 00:27:45 +010031 # Get the dm-verity target table from VerityInfo provider.
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010032 if ctx.attr.verity:
Tim Windelschmidt156248b2025-01-10 00:27:45 +010033 deps["rootfs_dm_table"] = ctx.attr.verity[VerityInfo].table
Lorenz Brunf099c092022-02-24 17:22:26 +010034
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010035 # Format deps into command line arguments while keeping track of mkpayload
36 # runtime inputs.
Lorenz Brun2f9f3872021-09-29 19:48:08 +020037 args = []
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010038 inputs = []
39 for name, file in deps.items():
Lorenz Brunf099c092022-02-24 17:22:26 +010040 if file:
41 args.append("-{}={}".format(name, file.path))
42 inputs.append(file)
43
Lorenz Brun304d42c2022-02-24 17:53:08 +010044 for file in ctx.files.initrd:
45 args.append("-initrd={}".format(file.path))
46 inputs.append(file)
47
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010048 # Append the output parameter separately, as it doesn't belong with the
49 # runtime inputs.
50 image = ctx.actions.declare_file(ctx.attr.name + ".efi")
51 args.append("-output={}".format(image.path))
Lorenz Brunf099c092022-02-24 17:22:26 +010052
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010053 # Append the objcopy parameter separately, as it's not of File type, and
54 # it does not constitute an input, since it's part of the toolchain.
Lorenz Brun163525e2025-05-22 15:30:14 +020055 cc_toolchain = find_cpp_toolchain(ctx)
56 feature_configuration = cc_common.configure_features(
57 ctx = ctx,
58 cc_toolchain = cc_toolchain,
59 requested_features = ctx.features,
60 unsupported_features = ctx.disabled_features,
61 )
62 objcopy = cc_common.get_tool_for_action(
63 feature_configuration = feature_configuration,
64 action_name = OBJ_COPY_ACTION_NAME,
65 )
66
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010067 args.append("-objcopy={}".format(objcopy))
Lorenz Brunf099c092022-02-24 17:22:26 +010068
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010069 # Run mkpayload.
Lorenz Brun2f9f3872021-09-29 19:48:08 +020070 ctx.actions.run(
Lorenz Brunf099c092022-02-24 17:22:26 +010071 mnemonic = "GenEFIKernelImage",
Tim Windelschmidt83f0aa42024-12-09 20:34:33 +010072 progress_message = "Generating EFI unified kernel image: {}".format(image.short_path),
Lorenz Brun163525e2025-05-22 15:30:14 +020073 inputs = depset(inputs, transitive = [cc_toolchain.all_files]),
Lorenz Brunf099c092022-02-24 17:22:26 +010074 outputs = [image],
75 executable = ctx.file._mkpayload,
76 arguments = args,
Lorenz Brun2f9f3872021-09-29 19:48:08 +020077 )
Lorenz Brunf099c092022-02-24 17:22:26 +010078
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010079 # Return the unified kernel image file.
80 return [DefaultInfo(files = depset([image]), runfiles = ctx.runfiles(files = [image]))]
Lorenz Brun2f9f3872021-09-29 19:48:08 +020081
82efi_unified_kernel_image = rule(
Lorenz Brun163525e2025-05-22 15:30:14 +020083 cfg = build_static_transition,
Lorenz Brun2f9f3872021-09-29 19:48:08 +020084 implementation = _efi_unified_kernel_image_impl,
85 attrs = {
86 "kernel": attr.label(
Lorenz Brun163525e2025-05-22 15:30:14 +020087 doc = "The Linux kernel executable Image. Needs to have EFI stub enabled.",
Lorenz Brun2f9f3872021-09-29 19:48:08 +020088 mandatory = True,
89 allow_single_file = True,
90 ),
91 "cmdline": attr.string(
92 doc = "The kernel commandline to be embedded.",
93 ),
Lorenz Brun304d42c2022-02-24 17:53:08 +010094 "initrd": attr.label_list(
95 doc = """
96 List of payloads to concatenate and supply as the initrd parameter to Linux when it boots.
97 The name stems from the time Linux booted from an initial ram disk (initrd), but it's now
98 a catch-all for a bunch of different larger payload for early Linux initialization.
99
100 In Linux 5.15 this can first contain an arbitrary amount of uncompressed cpio archives
101 with directories being optional which is accessed by earlycpio. This is used for both
102 early microcode loading and ACPI table overrides. This can then be followed by an arbitrary
103 amount of compressed cpio archives (even with different compression methods) which will
104 together make up the initramfs. The initramfs is only booted into if it contains either
105 /init or whatever file is specified as init= in cmdline. Technically depending on kernel
106 flags you might be able to supply an actual initrd, i.e. an image of a disk loaded into
107 RAM, but that has been deprecated for nearly 2 decades and should really not be used.
108
109 For kernels designed to run on physical machines this should at least contain microcode,
110 optionally followed by a compressed initramfs. For kernels only used in virtualized
111 setups the microcode can be left out and if no initramfs is needed this option can
112 be omitted completely.
113 """,
114 allow_files = True,
Lorenz Brun2f9f3872021-09-29 19:48:08 +0200115 ),
116 "os_release": attr.label(
117 doc = """
118 The os-release file identifying the operating system.
119 See https://www.freedesktop.org/software/systemd/man/os-release.html for format.
120 """,
121 allow_single_file = True,
122 ),
123 "splash": attr.label(
124 doc = "An image in BMP format which will be displayed as a splash screen until the kernel takes over.",
125 allow_single_file = True,
126 ),
127 "stub": attr.label(
128 doc = "The stub executable itself as a PE/COFF executable.",
129 default = "@efistub//:efistub",
130 allow_single_file = True,
Lorenz Brun2f9f3872021-09-29 19:48:08 +0200131 ),
Mateusz Zalega8c2c7712022-01-25 19:42:21 +0100132 "verity": attr.label(
133 doc = "The DeviceMapper Verity rootfs target table.",
134 allow_single_file = True,
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100135 providers = [DefaultInfo, VerityInfo],
Mateusz Zalega8c2c7712022-01-25 19:42:21 +0100136 ),
137 "_mkpayload": attr.label(
138 doc = "The mkpayload executable.",
Tim Windelschmidtc2290c22024-08-15 19:56:00 +0200139 default = "//osbase/build/mkpayload",
Mateusz Zalega8c2c7712022-01-25 19:42:21 +0100140 allow_single_file = True,
141 executable = True,
142 cfg = "exec",
143 ),
Lorenz Brun163525e2025-05-22 15:30:14 +0200144 } | CC_TOOLCHAIN_ATTRS,
145 toolchains = use_cc_toolchain(),
146 fragments = ["cpp"],
Lorenz Brun2f9f3872021-09-29 19:48:08 +0200147)