blob: 7bbfa7cc4d824f2d3675c26aecbc9734f51a60e9 [file] [log] [blame] [edit]
"""Logic needed for generating kernel artifacts for MTK based GKI devices.
"""
load(
"@bazel_skylib//lib:paths.bzl",
"paths",
)
load(
"@bazel_skylib//rules:write_file.bzl",
"write_file",
)
load(
"//build/bazel_common_rules/dist:dist.bzl",
"copy_to_dist_dir",
)
load(
"//build/kernel/kleaf:hermetic_tools.bzl",
"hermetic_genrule",
"hermetic_toolchain",
)
load(
"//build/kernel/kleaf:kernel.bzl",
"kernel_build",
"kernel_build_config",
"kernel_images",
"kernel_module",
"kernel_module_group",
"kernel_modules_install",
"kernel_unstripped_modules_archive",
)
common_kernel_dir = "kernel-5.15"
device_modules_dir = "kernel_device_modules-5.15"
def _extracted_gki_artifacts_impl(ctx):
hermetic_tools = hermetic_toolchain.get(ctx)
inputs = []
system_dlkm_archive = None
kernel_images = ["boot.img", "boot-lz4.img", "boot-gz.img", "Image", "Image.lz4", "Image.gz",
"vmlinux"]
gki_artifacts = kernel_images + ctx.attr.gki_modules
for f in ctx.files.images:
if f.basename == "system_dlkm_staging_archive.tar.gz":
inputs.append(f)
system_dlkm_archive = f
elif f.basename in kernel_images:
inputs.append(f)
outs = [ctx.actions.declare_file("gki_artifacts/" + artifact) for artifact in gki_artifacts]
common_outs = outs[0].dirname
intermediates_dir = paths.join(
ctx.bin_dir.path,
paths.dirname(ctx.build_file_path),
ctx.attr.name + "_intermediates",
)
command = hermetic_tools.setup
command += """
# Extract kernel images
kernel_images=({kernel_images})
for image in "${{kernel_images[@]}}"; do
cp "${{image}}" {common_outs}
done
# Extract GKI modules
mkdir -p {intermediates_dir}
tar xf {system_dlkm_archive} -C {intermediates_dir}
find {intermediates_dir} -name '*.ko' -exec cp -t {common_outs} {{}} \\+
# Verify the outputs. We don't care if there are more modules extracted
# than used. For example, we don't use zram.ko.
all_artifacts=({all_artifacts})
for artifact in "${{all_artifacts[@]}}"; do
if ! [[ -f "{common_outs}/${{artifact}}" ]]; then
echo "${{artifact}} is missing from inputs" >&2
exit 1
fi
done
""".format(
kernel_images = " ".join([img.path for img in inputs if img.basename in kernel_images]),
all_artifacts = " ".join([artifact.basename for artifact in outs]),
common_outs = common_outs,
system_dlkm_archive = system_dlkm_archive.path,
intermediates_dir = intermediates_dir,
)
ctx.actions.run_shell(
mnemonic = "ExtractedGKIArtifacts",
inputs = inputs,
outputs = outs,
tools = hermetic_tools.deps,
progress_message = "Extracting GKI modules and artifacts",
command = command,
)
return [DefaultInfo(files = depset(outs))]
extracted_gki_artifacts = rule(
doc = """
Extracts the system_dlkm archive, boot images, and kernel images (e.g. Image)
so they can be copied to the dist dir.
""",
implementation = _extracted_gki_artifacts_impl,
attrs = {
"images": attr.label_list(
doc = "The kernel_images targets that contains the GKI artifacts.",
allow_files = True,
mandatory = True,
),
"gki_modules": attr.string_list(
doc = "A list of GKI modules",
allow_empty = False,
mandatory = True,
),
},
toolchains = [hermetic_toolchain.type],
)
def _filter_kleaf_modules_list(kleaf_modules):
kleaf_switch = {}
for m in kleaf_modules:
p = m.partition(":")[2]
if p.endswith("_cus"):
k = p[:-4]
kleaf_switch[k] = m
kleaf_internal = []
kleaf_customer = []
for m in kleaf_modules:
p = m.partition(":")[2]
is_cus = 0
if p in kleaf_switch:
is_cus = -1
elif m.startswith("//vendor/mediatek/kernel_modules/msync2_frd_cus"):
continue
elif m.startswith("//vendor/mediatek/kernel_modules/cpufreq_"):
is_cus = -1
elif p.endswith("_cus"):
is_cus = 1
elif p.endswith("_int"):
is_cus = -1
elif p.startswith("met_drv_secure"):
is_cus = -1
elif m.startswith("//vendor/mediatek/kernel_modules/mtk_input/"):
is_cus = -1
elif m.startswith("//vendor/mediatek/tests/"):
is_cus = -1
if is_cus == 0:
kleaf_internal.append(m)
kleaf_customer.append(m)
elif is_cus == 1:
kleaf_customer.append(m)
elif is_cus == -1:
kleaf_internal.append(m)
return kleaf_internal, kleaf_customer
def _generate_system_dlkm_insmod_cfg(gki_modules):
hdr = "# Auto-generated file. Please edit GKI modules list in mgk_modules.bzl instead.\n"
insmod_cfg_strs = [hdr]
for module in gki_modules:
name = paths.basename(module).removesuffix(".ko")
insmod_cfg_strs += ["modprobe|system {}".format(name)]
return insmod_cfg_strs
def define_mgk(
name,
device_build_config,
device_modules,
dtb_name,
dtbo_names,
gki_modules,
in_tree_modules,
in_tree_modules_discard,
kleaf_modules,
insmod_cfgs = None):
"""Generates rules for building the kernel artifacts for a device.
Args:
name: The name of the device to build the kernel artifacts for.
device_build_config: The device specific build.config file.
device_modules: A list of external modules that are required for the
device.
dtb_name: The name of the main/base devicetree binary for the device.
dtbo_names: A list of the names of the devicetree overlays for the
device.
gki_modules: A list of GKI modules that are required for the device.
in_tree_modules: A list of in-tree modules that are required for the
device. These modules are built from the AOSP source tree. This list
should not include the GKI modules required for the device.
in_tree_modules_discard: A list of in-tree modules that will be built
but are not required for the device and should be discarded.
kleaf_modules: A list of labels referring to additional external
modules that are required for the device.
insmod_cfgs: Optional; A list of files referring to insmod_cfg
files. These files will be packaged into vendor_dlkm/etc/
"""
# get kleaf modules for internal and customer
kleaf_internal, kleaf_customer = _filter_kleaf_modules_list(kleaf_modules)
kernel_build_config(
name = "build.config.{}.generated".format(name),
srcs = [
# do not sort
"//{}:build.config.mgk.common".format(device_modules_dir),
"//{}:build.config.common".format(common_kernel_dir),
"//{}:build.config.aarch64".format(common_kernel_dir),
device_build_config,
],
)
kernel_build(
name = "{}".format(name),
srcs = [
"//{}:kernel_aarch64_sources".format(common_kernel_dir),
"arch/arm64/configs/{}_defconfig".format(name),
] + native.glob([
"arch/arm64/boot/dts/**",
"build.config.*",
"**/Kconfig*",
"net/**",
]),
outs = [
"{}.dtb".format(dtb_name),
] + ["{}.dtbo".format(dtbo) for dtbo in dtbo_names],
base_kernel = "//{}:kernel_aarch64_download_or_build".format(common_kernel_dir),
collect_unstripped_modules = True,
build_config = ":build.config.{}.generated".format(name),
defconfig_fragments = [
# do not sort
"arch/arm64/configs/{}_defconfig".format(name),
],
module_outs = in_tree_modules,
module_implicit_outs = in_tree_modules_discard,
kconfig_ext = "Kconfig.ext",
dtstree = "//kernel_device_modules-5.15/arch/arm64/boot/dts/mediatek:{}.dt".format(dtb_name),
make_goals = [
"modules",
"dtbs",
],
strip_modules = True,
)
native.filegroup(
name = "device_sources",
srcs = native.glob(
["**"],
exclude = [
".*",
".*/**",
".git/**",
],
),
)
kernel_module(
name = "{}_device_modules".format(name),
srcs = [
":device_sources",
],
outs = device_modules,
kernel_build = ":{}".format(name),
)
kernel_module_group(
name = "{}_ext_modules".format(name),
srcs = [
":{}_device_modules".format(name),
] + select({
":internal_build_is_true": kleaf_internal,
"//conditions:default": kleaf_customer,
}),
)
kernel_modules_install(
name = "{}_modules_install".format(name),
kernel_modules = [":{}_ext_modules".format(name)],
kernel_build = ":{}".format(name),
)
kernel_unstripped_modules_archive(
name = "{}_unstripped_modules_archive".format(name),
kernel_build = ":{}".format(name),
kernel_modules = [":{}_ext_modules".format(name)],
)
hermetic_genrule(
name = "{}_vendor_modules_lists".format(name),
srcs = [
"ko_order_table.csv",
],
cmd = """
VENDOR_DLKM_MODULES_LIST=()
VENDOR_DLKM_MODULES_BLOCKLIST=()
MODULES_LIST=()
MODULES_RECOVERY_LIST=()
while IFS= read -r LINE; do
if [[ $${LINE} =~ ^.*\\.ko,.* ]]; then
NAME=$$(echo $${LINE} | cut -d ',' -f1)
PARTITION=$$(echo $${LINE} | cut -d ',' -f3)
LOADED=$$(echo $${LINE} | cut -d ',' -f4)
RECOVERY=$$(echo $${LINE} | cut -d ',' -f5)
if [[ "$${PARTITION}" == "vendor" ]]; then
VENDOR_DLKM_MODULES_LIST+=($${NAME})
if [[ "$${LOADED}" == "N" ]]; then
BASENAME="$${NAME%.*}"
VENDOR_DLKM_MODULES_BLOCKLIST+=("blocklist $${BASENAME}")
fi
fi
if [[ "$${PARTITION}" == "ramdisk" ]]; then
MODULES_LIST+=($${NAME})
fi
if [[ "$${RECOVERY}" == "Y" ]]; then
MODULES_RECOVERY_LIST+=($${NAME})
fi
fi
done < $(location ko_order_table.csv)
printf "%s\\n" "$${MODULES_LIST[@]}" > $(location vendor_boot_modules)
printf "%s\\n" "$${MODULES_RECOVERY_LIST[@]}" > $(location vendor_boot_recovery_modules)
printf "%s\\n" "$${VENDOR_DLKM_MODULES_LIST[@]}" > $(location vendor_dlkm_modules)
printf "%s\\n" "$${VENDOR_DLKM_MODULES_BLOCKLIST[@]}" > $(location vendor_dlkm_blocklist)
""",
outs = [
"vendor_boot_modules",
"vendor_boot_recovery_modules",
"vendor_dlkm_modules",
"vendor_dlkm_blocklist",
],
)
write_file(
name = "system_dlkm_modules_list",
out = "system_dlkm_modules_list.{}".format(name),
content = gki_modules,
)
# Add an empty string at the end of the list of strings so that
# all lines are terminated by a new-line
write_file(
name = "system_dlkm_insmod_cfg",
out = "init.insmod.system_dlkm.cfg",
content = _generate_system_dlkm_insmod_cfg(gki_modules) + [""],
)
kernel_images(
name = "{}_images".format(name),
build_boot = False,
build_dtbo = True,
dtbo_srcs = [":{}/".format(name) + file + ".dtbo" for file in dtbo_names],
build_initramfs = True,
build_vendor_boot = True,
vendor_ramdisk_binaries = ["//{}:vendor_ramdisk-{}.img".format(device_modules_dir, name)],
build_system_dlkm = True,
base_kernel_images = "//{}:kernel_aarch64_images_download_or_build".format(common_kernel_dir),
system_dlkm_props = "//{}:system_dlkm.props".format(device_modules_dir),
dedup_dlkm_modules = True,
kernel_build = ":{}".format(name),
kernel_modules_install = ":{}_modules_install".format(name),
modules_list = ":vendor_boot_modules",
modules_recovery_list = ":vendor_boot_recovery_modules",
system_dlkm_modules_list = ":system_dlkm_modules_list",
build_vendor_dlkm = True,
vendor_dlkm_modules_blocklist = ":vendor_dlkm_blocklist",
vendor_dlkm_modules_list = ":vendor_dlkm_modules",
vendor_dlkm_props = "//{}:vendor_dlkm.props".format(device_modules_dir),
vendor_dlkm_etc_files = insmod_cfgs + [":system_dlkm_insmod_cfg"],
deps = [
"//{}:vendor_dlkm_file_contexts".format(device_modules_dir),
"//{}:system_dlkm_file_contexts".format(device_modules_dir),
],
)
dist_targets = [
":{}".format(name),
":{}_ext_modules".format(name),
":{}_modules_install".format(name),
":{}_unstripped_modules_archive".format(name),
":gki_kernel_artifacts",
":{}_images".format(name),
":system_dlkm_insmod_cfg",
]
copy_to_dist_dir(
name = "{}_dist".format(name),
data = dist_targets,
dist_dir = "../out/target/product/kirkwood/kernel/{}/dist".format(name),
flat = False,
log = "info",
)
extracted_gki_artifacts(
name = "gki_kernel_artifacts",
gki_modules = [paths.basename(m) for m in gki_modules],
images = [
"//{}:kernel_aarch64_download_or_build".format(common_kernel_dir),
"//{}:kernel_aarch64_images_download_or_build".format(common_kernel_dir),
"//{}:kernel_aarch64_gki_artifacts_download_or_build".format(common_kernel_dir),
],
)