blob: 3e8c09f13d6a7c7fe175ef9b8b10e453b98c132b [file] [log] [blame]
Tim Windelschmidt12240f92025-04-28 14:59:33 +02001# Copyright The Monogon Project Authors.
2# SPDX-License-Identifier: Apache-2.0
3
4load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cpp_toolchain", "use_cc_toolchain")
5load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
6load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
7load("//build/utils:detect_root.bzl", "detect_root", "detect_roots")
8load("//build/utils:foreign_build.bzl", "generate_foreign_build_env", "merge_env")
9load("//build/utils:target_info.bzl", "TargetInfo")
Tim Windelschmidt12240f92025-04-28 14:59:33 +020010
11TOOLCHAINS = [
12 "//build/toolchain/toolchain-bundle:make_toolchain",
13 "//build/toolchain/toolchain-bundle:nasm_toolchain",
14 "//build/toolchain/toolchain-bundle:iasl_toolchain",
Tim Windelschmidt9a063ae2025-07-09 18:35:34 +020015 "//build/toolchain/toolchain-bundle:busybox_toolchain",
Tim Windelschmidt12240f92025-04-28 14:59:33 +020016]
17
18def _edk2_impl(ctx):
19 _, libuuid_gen = detect_roots(ctx.attr._libuuid[CcInfo].compilation_context.direct_public_headers)
20 extra_env = {
21 "HOSTLDFLAGS": " -L ".join(
22 [
23 "", # First element empty, for force a the join prefix
24 detect_root(ctx.attr._libuuid.files.to_list()).rsplit("/", 1)[0],
25 ],
26 ),
27 "HOSTCFLAGS": " -I ".join(
28 [
29 "", # First element empty, for force a the join prefix
30 libuuid_gen,
31 ],
32 ),
33 "CROSS_LIB_UUID_INC": libuuid_gen.rsplit("/", 1)[0],
34 "CROSS_LIB_UUID": detect_root(ctx.attr._libuuid.files.to_list()).rsplit("/", 1)[0],
35 }
36
37 inputs = depset(
38 ctx.files.src +
39 ctx.files._libuuid +
40 ctx.attr._libuuid[CcInfo].compilation_context.direct_public_headers,
41 )
42
43 # Setup the environment for the foreign build.
44 toolchain_env, toolchain_inputs, toolchain_cmd = generate_foreign_build_env(
45 ctx = ctx,
46 target_toolchain = find_cpp_toolchain(ctx),
47 exec_toolchain = ctx.attr._exec_toolchain[cc_common.CcToolchainInfo],
48 toolchain_bundle_tools = TOOLCHAINS,
49 )
50
51 target_arch = ctx.attr._target_arch[TargetInfo].value
52 target_path = None
53 export_script = None
54 if target_arch == "X64":
55 target_path = "OvmfPkg/OvmfPkgX64.dsc"
56 export_script = """
57 cp {src}/Build/OvmfX64/{release_type}_"$TOOLCHAIN"/FV/OVMF_CODE.fd {code}
58 cp {src}/Build/OvmfX64/{release_type}_"$TOOLCHAIN"/FV/OVMF_VARS.fd {vars}
59 """
60 elif target_arch == "AARCH64":
61 target_path = "ArmVirtPkg/ArmVirtQemu.dsc"
62 export_script = """
63 dd of="{code}" if=/dev/zero bs=1M count=64
64 dd of="{code}" if={src}/Build/ArmVirtQemu-AARCH64/{release_type}_"$TOOLCHAIN"/FV/QEMU_EFI.fd conv=notrunc
65 dd of="{vars}" if=/dev/zero bs=1M count=64
66 dd of="{vars}" if={src}/Build/ArmVirtQemu-AARCH64/{release_type}_"$TOOLCHAIN"/FV/QEMU_VARS.fd conv=notrunc
67 """
68 else:
69 fail("Unsupported target architecture: %s" % target_arch)
70
71 code = ctx.actions.declare_file("CODE.fd")
72 vars = ctx.actions.declare_file("VARS.fd")
73 ctx.actions.run_shell(
74 outputs = [code, vars],
75 inputs = depset(transitive = [inputs, toolchain_inputs]),
76 env = merge_env(toolchain_env, extra_env),
77 progress_message = "Building EDK2 firmware",
78 mnemonic = "BuildEDK2Firmware",
79 command = toolchain_cmd + ("""
80 TOOLCHAIN=CLANGDWARF
81 export CLANG_BIN="$CC_PATH/"
82
83 (
84 cd {src}
85 . edksetup.sh
86 make \
87 BUILD_OPTFLAGS="$HOSTCFLAGS" EXTRA_LDFLAGS="$HOSTLDFLAGS" \
88 -C BaseTools/Source/C
89
90 build -DTPM2_ENABLE -DSECURE_BOOT_ENABLE \
91 -t $TOOLCHAIN -a {target_arch} -b {release_type} \
92 -p $PWD/{target_path}
93 ) > /dev/null
94 """ + export_script).format(
95 src = detect_root(ctx.attr.src.files.to_list()),
96 code = code.path,
97 vars = vars.path,
98 target_arch = target_arch,
99 target_path = target_path,
100 release_type = ctx.attr._compilation_mode[TargetInfo].value,
101 ),
102 use_default_shell_env = True,
103 )
104
105 return [
106 DefaultInfo(
107 files = depset([code, vars]),
108 runfiles = ctx.runfiles(files = [code, vars]),
109 ),
110 ]
111
112edk2 = rule(
113 doc = """
114 Build EDK2 hermetically.
115 """,
116 implementation = _edk2_impl,
Tim Windelschmidt12240f92025-04-28 14:59:33 +0200117 attrs = {
118 "src": attr.label(
119 doc = """
120 Filegroup containing EDK2 sources.
121 """,
122 ),
123 "_libuuid": attr.label(
124 default = "@libuuid//:uuid",
125 ),
126 "_exec_toolchain": attr.label(
127 default = "@rules_cc//cc:current_cc_toolchain",
128 cfg = "exec",
129 ),
130 "_target_arch": attr.label(
131 default = "//third_party/edk2:target_arch",
132 ),
133 "_compilation_mode": attr.label(
134 default = "//third_party/edk2:compilation_mode",
135 ),
136 },
137 fragments = ["cpp"],
138 toolchains = TOOLCHAINS + use_cc_toolchain(),
139)