blob: fa10e831c1ea665272ed517331381884403de7d3 [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
Tim Windelschmidtbed76d92025-02-18 03:04:14 +01006load("//osbase/build/mkverity:def.bzl", "VerityInfo")
Lorenz Brun2f9f3872021-09-29 19:48:08 +02007
8def _efi_unified_kernel_image_impl(ctx):
Mateusz Zalega8c2c7712022-01-25 19:42:21 +01009 # Find the dependency paths to be passed to mkpayload.
10 deps = {
Lorenz Brunf099c092022-02-24 17:22:26 +010011 "linux": ctx.file.kernel,
Lorenz Brunf099c092022-02-24 17:22:26 +010012 "osrel": ctx.file.os_release,
13 "splash": ctx.file.splash,
14 "stub": ctx.file.stub,
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010015 }
Lorenz Brunf099c092022-02-24 17:22:26 +010016
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010017 # Since cmdline is a string attribute, put it into a file, then append
18 # that file to deps.
19 if ctx.attr.cmdline and ctx.attr.cmdline != "":
20 cmdline = ctx.actions.declare_file("cmdline")
Lorenz Brun2f9f3872021-09-29 19:48:08 +020021 ctx.actions.write(
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010022 output = cmdline,
Lorenz Brun2f9f3872021-09-29 19:48:08 +020023 content = ctx.attr.cmdline,
24 )
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010025 deps["cmdline"] = cmdline
Lorenz Brunf099c092022-02-24 17:22:26 +010026
Tim Windelschmidt156248b2025-01-10 00:27:45 +010027 # Get the dm-verity target table from VerityInfo provider.
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010028 if ctx.attr.verity:
Tim Windelschmidt156248b2025-01-10 00:27:45 +010029 deps["rootfs_dm_table"] = ctx.attr.verity[VerityInfo].table
Lorenz Brunf099c092022-02-24 17:22:26 +010030
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010031 # Format deps into command line arguments while keeping track of mkpayload
32 # runtime inputs.
Lorenz Brun2f9f3872021-09-29 19:48:08 +020033 args = []
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010034 inputs = []
35 for name, file in deps.items():
Lorenz Brunf099c092022-02-24 17:22:26 +010036 if file:
37 args.append("-{}={}".format(name, file.path))
38 inputs.append(file)
39
Lorenz Brun304d42c2022-02-24 17:53:08 +010040 for file in ctx.files.initrd:
41 args.append("-initrd={}".format(file.path))
42 inputs.append(file)
43
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010044 # Append the output parameter separately, as it doesn't belong with the
45 # runtime inputs.
46 image = ctx.actions.declare_file(ctx.attr.name + ".efi")
47 args.append("-output={}".format(image.path))
Lorenz Brunf099c092022-02-24 17:22:26 +010048
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010049 # Append the objcopy parameter separately, as it's not of File type, and
50 # it does not constitute an input, since it's part of the toolchain.
Leopoldbc93c2b2023-01-14 13:12:23 +010051 objcopy = ctx.toolchains["@bazel_tools//tools/cpp:toolchain_type"].cc.objcopy_executable
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010052 args.append("-objcopy={}".format(objcopy))
Lorenz Brunf099c092022-02-24 17:22:26 +010053
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010054 # Run mkpayload.
Lorenz Brun2f9f3872021-09-29 19:48:08 +020055 ctx.actions.run(
Lorenz Brunf099c092022-02-24 17:22:26 +010056 mnemonic = "GenEFIKernelImage",
Tim Windelschmidt83f0aa42024-12-09 20:34:33 +010057 progress_message = "Generating EFI unified kernel image: {}".format(image.short_path),
Lorenz Brunf099c092022-02-24 17:22:26 +010058 inputs = inputs,
59 outputs = [image],
60 executable = ctx.file._mkpayload,
61 arguments = args,
Lorenz Brun2f9f3872021-09-29 19:48:08 +020062 )
Lorenz Brunf099c092022-02-24 17:22:26 +010063
Mateusz Zalega8c2c7712022-01-25 19:42:21 +010064 # Return the unified kernel image file.
65 return [DefaultInfo(files = depset([image]), runfiles = ctx.runfiles(files = [image]))]
Lorenz Brun2f9f3872021-09-29 19:48:08 +020066
67efi_unified_kernel_image = rule(
68 implementation = _efi_unified_kernel_image_impl,
69 attrs = {
70 "kernel": attr.label(
71 doc = "The Linux kernel executable bzImage. Needs to have EFI handover and EFI stub enabled.",
72 mandatory = True,
73 allow_single_file = True,
74 ),
75 "cmdline": attr.string(
76 doc = "The kernel commandline to be embedded.",
77 ),
Lorenz Brun304d42c2022-02-24 17:53:08 +010078 "initrd": attr.label_list(
79 doc = """
80 List of payloads to concatenate and supply as the initrd parameter to Linux when it boots.
81 The name stems from the time Linux booted from an initial ram disk (initrd), but it's now
82 a catch-all for a bunch of different larger payload for early Linux initialization.
83
84 In Linux 5.15 this can first contain an arbitrary amount of uncompressed cpio archives
85 with directories being optional which is accessed by earlycpio. This is used for both
86 early microcode loading and ACPI table overrides. This can then be followed by an arbitrary
87 amount of compressed cpio archives (even with different compression methods) which will
88 together make up the initramfs. The initramfs is only booted into if it contains either
89 /init or whatever file is specified as init= in cmdline. Technically depending on kernel
90 flags you might be able to supply an actual initrd, i.e. an image of a disk loaded into
91 RAM, but that has been deprecated for nearly 2 decades and should really not be used.
92
93 For kernels designed to run on physical machines this should at least contain microcode,
94 optionally followed by a compressed initramfs. For kernels only used in virtualized
95 setups the microcode can be left out and if no initramfs is needed this option can
96 be omitted completely.
97 """,
98 allow_files = True,
Lorenz Brun2f9f3872021-09-29 19:48:08 +020099 ),
100 "os_release": attr.label(
101 doc = """
102 The os-release file identifying the operating system.
103 See https://www.freedesktop.org/software/systemd/man/os-release.html for format.
104 """,
105 allow_single_file = True,
106 ),
107 "splash": attr.label(
108 doc = "An image in BMP format which will be displayed as a splash screen until the kernel takes over.",
109 allow_single_file = True,
110 ),
111 "stub": attr.label(
112 doc = "The stub executable itself as a PE/COFF executable.",
113 default = "@efistub//:efistub",
114 allow_single_file = True,
Lorenz Brun2f9f3872021-09-29 19:48:08 +0200115 ),
Mateusz Zalega8c2c7712022-01-25 19:42:21 +0100116 "verity": attr.label(
117 doc = "The DeviceMapper Verity rootfs target table.",
118 allow_single_file = True,
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100119 providers = [DefaultInfo, VerityInfo],
Mateusz Zalega8c2c7712022-01-25 19:42:21 +0100120 ),
121 "_mkpayload": attr.label(
122 doc = "The mkpayload executable.",
Tim Windelschmidtc2290c22024-08-15 19:56:00 +0200123 default = "//osbase/build/mkpayload",
Mateusz Zalega8c2c7712022-01-25 19:42:21 +0100124 allow_single_file = True,
125 executable = True,
126 cfg = "exec",
127 ),
Lorenz Brun2f9f3872021-09-29 19:48:08 +0200128 },
Leopoldbc93c2b2023-01-14 13:12:23 +0100129 toolchains = [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100130 "@bazel_tools//tools/cpp:toolchain_type",
Leopoldbc93c2b2023-01-14 13:12:23 +0100131 ],
Lorenz Brun2f9f3872021-09-29 19:48:08 +0200132)