| """Rules for generating EFI unified kernel images. These are EFI-bootable PE/COFF files containing a stub loader, | 
 | a kernel, and optional commandline and initramfs in one file. | 
 | See https://systemd.io/BOOT_LOADER_SPECIFICATION/#type-2-efi-unified-kernel-images for more information. | 
 | """ | 
 |  | 
 | load("//build/toolchain/llvm-efi:transition.bzl", "build_efi_transition") | 
 | load("//metropolis/node/build:def.bzl", "VerityConfig") | 
 |  | 
 | def _efi_unified_kernel_image_impl(ctx): | 
 |     # Find the dependency paths to be passed to mkpayload. | 
 |     deps = { | 
 |         "linux": ctx.file.kernel, | 
 |         "osrel": ctx.file.os_release, | 
 |         "splash": ctx.file.splash, | 
 |         "stub": ctx.file.stub, | 
 |     } | 
 |  | 
 |     # Since cmdline is a string attribute, put it into a file, then append | 
 |     # that file to deps. | 
 |     if ctx.attr.cmdline and ctx.attr.cmdline != "": | 
 |         cmdline = ctx.actions.declare_file("cmdline") | 
 |         ctx.actions.write( | 
 |             output = cmdline, | 
 |             content = ctx.attr.cmdline, | 
 |         ) | 
 |         deps["cmdline"] = cmdline | 
 |  | 
 |     # Get the dm-verity target table from VerityConfig provider. | 
 |     if ctx.attr.verity: | 
 |         deps["rootfs_dm_table"] = ctx.attr.verity[VerityConfig].table | 
 |  | 
 |     # Format deps into command line arguments while keeping track of mkpayload | 
 |     # runtime inputs. | 
 |     args = [] | 
 |     inputs = [] | 
 |     for name, file in deps.items(): | 
 |         if file: | 
 |             args.append("-{}={}".format(name, file.path)) | 
 |             inputs.append(file) | 
 |  | 
 |     for file in ctx.files.initrd: | 
 |         args.append("-initrd={}".format(file.path)) | 
 |         inputs.append(file) | 
 |  | 
 |     # Append the output parameter separately, as it doesn't belong with the | 
 |     # runtime inputs. | 
 |     image = ctx.actions.declare_file(ctx.attr.name + ".efi") | 
 |     args.append("-output={}".format(image.path)) | 
 |  | 
 |     # Append the objcopy parameter separately, as it's not of File type, and | 
 |     # it does not constitute an input, since it's part of the toolchain. | 
 |     objcopy = ctx.toolchains["@bazel_tools//tools/cpp:toolchain_type"].cc.objcopy_executable | 
 |     args.append("-objcopy={}".format(objcopy)) | 
 |  | 
 |     # Run mkpayload. | 
 |     ctx.actions.run( | 
 |         mnemonic = "GenEFIKernelImage", | 
 |         progress_message = "Generating EFI unified kernel image", | 
 |         inputs = inputs, | 
 |         outputs = [image], | 
 |         executable = ctx.file._mkpayload, | 
 |         arguments = args, | 
 |     ) | 
 |  | 
 |     # Return the unified kernel image file. | 
 |     return [DefaultInfo(files = depset([image]), runfiles = ctx.runfiles(files = [image]))] | 
 |  | 
 | efi_unified_kernel_image = rule( | 
 |     implementation = _efi_unified_kernel_image_impl, | 
 |     attrs = { | 
 |         "kernel": attr.label( | 
 |             doc = "The Linux kernel executable bzImage. Needs to have EFI handover and EFI stub enabled.", | 
 |             mandatory = True, | 
 |             allow_single_file = True, | 
 |         ), | 
 |         "cmdline": attr.string( | 
 |             doc = "The kernel commandline to be embedded.", | 
 |         ), | 
 |         "initrd": attr.label_list( | 
 |             doc = """ | 
 |                 List of payloads to concatenate and supply as the initrd parameter to Linux when it boots. | 
 |                 The name stems from the time Linux booted from an initial ram disk (initrd), but it's now | 
 |                 a catch-all for a bunch of different larger payload for early Linux initialization. | 
 |  | 
 |                 In Linux 5.15 this can first contain an arbitrary amount of uncompressed cpio archives | 
 |                 with directories being optional which is accessed by earlycpio. This is used for both | 
 |                 early microcode loading and ACPI table overrides. This can then be followed by an arbitrary | 
 |                 amount of compressed cpio archives (even with different compression methods) which will | 
 |                 together make up the initramfs. The initramfs is only booted into if it contains either | 
 |                 /init or whatever file is specified as init= in cmdline. Technically depending on kernel | 
 |                 flags you might be able to supply an actual initrd, i.e. an image of a disk loaded into | 
 |                 RAM, but that has been deprecated for nearly 2 decades and should really not be used. | 
 |  | 
 |                 For kernels designed to run on physical machines this should at least contain microcode, | 
 |                 optionally followed by a compressed initramfs. For kernels only used in virtualized | 
 |                 setups the microcode can be left out and if no initramfs is needed this option can | 
 |                 be omitted completely. | 
 |                 """, | 
 |             allow_files = True, | 
 |         ), | 
 |         "os_release": attr.label( | 
 |             doc = """ | 
 |                 The os-release file identifying the operating system. | 
 |                 See https://www.freedesktop.org/software/systemd/man/os-release.html for format. | 
 |             """, | 
 |             allow_single_file = True, | 
 |         ), | 
 |         "splash": attr.label( | 
 |             doc = "An image in BMP format which will be displayed as a splash screen until the kernel takes over.", | 
 |             allow_single_file = True, | 
 |         ), | 
 |         "stub": attr.label( | 
 |             doc = "The stub executable itself as a PE/COFF executable.", | 
 |             default = "@efistub//:efistub", | 
 |             allow_single_file = True, | 
 |             executable = True, | 
 |             cfg = build_efi_transition, | 
 |         ), | 
 |         "verity": attr.label( | 
 |             doc = "The DeviceMapper Verity rootfs target table.", | 
 |             allow_single_file = True, | 
 |             providers = [DefaultInfo, VerityConfig], | 
 |         ), | 
 |         "_mkpayload": attr.label( | 
 |             doc = "The mkpayload executable.", | 
 |             default = "//metropolis/node/build/mkpayload", | 
 |             allow_single_file = True, | 
 |             executable = True, | 
 |             cfg = "exec", | 
 |         ), | 
 |         # Allow for transitions to be attached to this rule. | 
 |         "_whitelist_function_transition": attr.label( | 
 |             default = "@bazel_tools//tools/whitelists/function_transition_whitelist", | 
 |         ), | 
 |     }, | 
 |     toolchains = [ | 
 |         "@bazel_tools//tools/cpp:toolchain_type" | 
 |     ], | 
 | ) |