| """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), |
| ], |
| ) |