From ecb7a2f68a9c2dfc4460af2d1fa7ed8d6354b397 Mon Sep 17 00:00:00 2001 From: Aaron Kling Date: Thu, 10 Aug 2023 16:20:52 -0500 Subject: [PATCH 1/8] kernel: Support copying modules to recovery Change-Id: Iac275cfbea368d47f9cc8e756649ab094d9c57c5 --- build/tasks/kernel.mk | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk index 52319db74..e315b38f8 100644 --- a/build/tasks/kernel.mk +++ b/build/tasks/kernel.mk @@ -401,6 +401,12 @@ KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call int $(INTERNAL_VENDOR_RAMDISK_TARGET): $(TARGET_PREBUILT_INT_KERNEL) endif +ifneq ($(RECOVERY_KERNEL_MODULES),) +KERNEL_RECOVERY_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_recovery) +KERNEL_RECOVERY_MODULES_OUT := $(TARGET_RECOVERY_ROOT_OUT) +$(recovery_uncompressed_ramdisk): $(TARGET_PREBUILT_INT_KERNEL) +endif + $(KERNEL_OUT): mkdir -p $(KERNEL_OUT) @@ -443,6 +449,14 @@ $(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_CONFIG) $(DEPMOD) $(DTC) $(PAHOLE) [ $$? -ne 0 ] && exit 1; \ ($(call build-image-kernel-modules-lineage,$$vendor_boot_modules,$(KERNEL_VENDOR_RAMDISK_MODULES_OUT),/,$(KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR),$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD))); \ ) \ + $(if $(RECOVERY_KERNEL_MODULES),\ + recovery_modules=$$(for m in $(RECOVERY_KERNEL_MODULES); do \ + p=$$(find $$kernel_modules_dir -type f -name $$m); \ + if [ -n "$$p" ]; then echo $$p; else echo "ERROR: $$m from RECOVERY_KERNEL_MODULES was not found" 1>&2 && exit 1; fi; \ + done); \ + [ $$? -ne 0 ] && exit 1; \ + ($(call build-image-kernel-modules-lineage,$$recovery_modules,$(KERNEL_RECOVERY_MODULES_OUT),/,$(KERNEL_RECOVERY_DEPMOD_STAGING_DIR),$(BOARD_RECOVERY_RAMDISK_KERNEL_MODULES_LOAD))); \ + ) \ fi .PHONY: kerneltags From e80da6b7be7abf821252c2685b3f3609b2eec90a Mon Sep 17 00:00:00 2001 From: Bruno Martins Date: Sat, 9 Sep 2023 15:56:40 +0100 Subject: [PATCH 2/8] kernel: Handle GKI modules All devices lauching with Android 13 (and above) must include a system_dlkm partition, where GKI modules should reside. Android 13 build system only supports providing prebuilt modules, by pointing BOARD_SYSTEM_DLKM_SRC to the modules source folder. Google will introduce BOARD_SYSTEM_KERNEL_MODULES for Android 14, so take a step forward and use that macro to exclude the listed modules from the usual vendor DLKM partition and place them into the GKI module partition. Note that the GKI modules are placed into lib/modules/androidX-Y.Z, as defined by Google and observed in system_dlkm_modprobe script. Change-Id: I2b1644479788cb5c9568cac738202b1d55fc28d7 --- build/tasks/kernel.mk | 49 +++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk index e315b38f8..f5f00f50a 100644 --- a/build/tasks/kernel.mk +++ b/build/tasks/kernel.mk @@ -90,6 +90,7 @@ KERNEL_CONFIG := $(KERNEL_OUT)/.config KERNEL_RELEASE := $(KERNEL_OUT)/include/config/kernel.release RECOVERY_KERNEL_CONFIG := $(RECOVERY_KERNEL_OUT)/.config RECOVERY_KERNEL_RELEASE := $(RECOVERY_KERNEL_OUT)/include/config/kernel.release +GKI_SUFFIX := $(shell echo android$(PLATFORM_VERSION)-$(TARGET_KERNEL_VERSION)) ifeq ($(KERNEL_ARCH),x86_64) KERNEL_DEFCONFIG_ARCH := x86 @@ -339,20 +340,21 @@ endef # $(3): mount point # $(4): staging dir # $(5): module load list +# $(6): suffix for output dir, needed for GKI modules usecase, empty otherwise # Depmod requires a well-formed kernel version so 0.0 is used as a placeholder. define build-image-kernel-modules-lineage - mkdir -p $(2)/lib/modules - cp $(1) $(2)/lib/modules/ + mkdir -p $(2)/lib/modules$(6) + cp $(1) $(2)/lib/modules$(6) rm -rf $(4) - mkdir -p $(4)/lib/modules/0.0/$(3)lib/modules - cp $(1) $(4)/lib/modules/0.0/$(3)lib/modules + mkdir -p $(4)/lib/modules/0.0/$(3)lib/modules$(6) + cp $(1) $(4)/lib/modules/0.0/$(3)lib/modules$(6) $(DEPMOD) -b $(4) 0.0 - sed -e 's/\(.*modules.*\):/\/\1:/g' -e 's/ \([^ ]*modules[^ ]*\)/ \/\1/g' $(4)/lib/modules/0.0/modules.dep > $(2)/lib/modules/modules.dep - cp $(4)/lib/modules/0.0/modules.softdep $(2)/lib/modules - cp $(4)/lib/modules/0.0/modules.alias $(2)/lib/modules - rm -f $(2)/lib/modules/modules.load + sed -e 's/\(.*modules.*\):/\/\1:/g' -e 's/ \([^ ]*modules[^ ]*\)/ \/\1/g' $(4)/lib/modules/0.0/modules.dep > $(2)/lib/modules$(6)/modules.dep + cp $(4)/lib/modules/0.0/modules.softdep $(2)/lib/modules$(6) + cp $(4)/lib/modules/0.0/modules.alias $(2)/lib/modules$(6) + rm -f $(2)/lib/modules$(6)/modules.load for MODULE in $(5); do \ - basename $$MODULE >> $(2)/lib/modules/modules.load; \ + basename $$MODULE >> $(2)/lib/modules$(6)/modules.load; \ done endef @@ -385,6 +387,12 @@ KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir- KERNEL_MODULE_MOUNTPOINT := vendor $(INSTALLED_VENDORIMAGE_TARGET): $(TARGET_PREBUILT_INT_KERNEL) endif +ifeq ($(BOARD_USES_SYSTEM_DLKMIMAGE),true) +SYSTEM_KERNEL_MODULES_OUT := $(TARGET_OUT_SYSTEM_DLKM) +SYSTEM_KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_system_dlkm) +SYSTEM_KERNEL_MODULE_MOUNTPOINT := system_dlkm +$(INSTALLED_SYSTEM_DLKMIMAGE_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +endif MODULES_INTERMEDIATES := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,kernel_modules) ifneq (,$(filter dlkm,$(BOARD_VENDOR_RAMDISK_FRAGMENTS))) @@ -439,15 +447,30 @@ $(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_CONFIG) $(DEPMOD) $(DTC) $(PAHOLE) $(foreach s, $(TARGET_MODULE_ALIASES),\ $(eval p := $(subst :,$(space),$(s))) \ ; mv $$(find $$kernel_modules_dir -name $(word 1,$(p))) $$kernel_modules_dir/$(word 2,$(p))); \ - modules=$$(find $$kernel_modules_dir -type f -name '*.ko'); \ - ($(call build-image-kernel-modules-lineage,$$modules,$(KERNEL_MODULES_OUT),$(KERNEL_MODULE_MOUNTPOINT)/,$(KERNEL_DEPMOD_STAGING_DIR),$(BOARD_VENDOR_KERNEL_MODULES_LOAD))); \ + all_modules=$$(find $$kernel_modules_dir -type f -name '*.ko'); \ + filtered_modules=""; \ + $(if $(BOARD_SYSTEM_KERNEL_MODULES),\ + gki_modules=$$(for m in $(BOARD_SYSTEM_KERNEL_MODULES); do \ + p=$$(find $$kernel_modules_dir -type f -name $$m); \ + if [ -n "$$p" ]; then echo $$p; else echo "ERROR: $$m from BOARD_SYSTEM_KERNEL_MODULES was not found" 1>&2 && exit 1; fi; \ + done); \ + [ $$? -ne 0 ] && exit 1; \ + ($(call build-image-kernel-modules-lineage,$$gki_modules,$(SYSTEM_KERNEL_MODULES_OUT),$(SYSTEM_KERNEL_MODULE_MOUNTPOINT)/,$(SYSTEM_KERNEL_DEPMOD_STAGING_DIR),$(BOARD_SYSTEM_KERNEL_MODULES_LOAD),/$(GKI_SUFFIX))); \ + filtered_modules=$$(for n in $$all_modules; do \ + module_name=$$(basename $$n); \ + if [[ ! "$(BOARD_SYSTEM_KERNEL_MODULES)" =~ "$$module_name" ]]; then echo $$n; fi; \ + done); \ + ($(call build-image-kernel-modules-lineage,$$filtered_modules,$(KERNEL_MODULES_OUT),$(KERNEL_MODULE_MOUNTPOINT)/,$(KERNEL_DEPMOD_STAGING_DIR),$(BOARD_VENDOR_KERNEL_MODULES_LOAD),/)); \ + ,\ + ($(call build-image-kernel-modules-lineage,$$all_modules,$(KERNEL_MODULES_OUT),$(KERNEL_MODULE_MOUNTPOINT)/,$(KERNEL_DEPMOD_STAGING_DIR),$(BOARD_VENDOR_KERNEL_MODULES_LOAD),/)); \ + ) \ $(if $(BOOT_KERNEL_MODULES),\ vendor_boot_modules=$$(for m in $(BOOT_KERNEL_MODULES); do \ p=$$(find $$kernel_modules_dir -type f -name $$m); \ if [ -n "$$p" ]; then echo $$p; else echo "ERROR: $$m from BOOT_KERNEL_MODULES was not found" 1>&2 && exit 1; fi; \ done); \ [ $$? -ne 0 ] && exit 1; \ - ($(call build-image-kernel-modules-lineage,$$vendor_boot_modules,$(KERNEL_VENDOR_RAMDISK_MODULES_OUT),/,$(KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR),$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD))); \ + ($(call build-image-kernel-modules-lineage,$$vendor_boot_modules,$(KERNEL_VENDOR_RAMDISK_MODULES_OUT),/,$(KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR),$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD),/)); \ ) \ $(if $(RECOVERY_KERNEL_MODULES),\ recovery_modules=$$(for m in $(RECOVERY_KERNEL_MODULES); do \ @@ -455,7 +478,7 @@ $(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_CONFIG) $(DEPMOD) $(DTC) $(PAHOLE) if [ -n "$$p" ]; then echo $$p; else echo "ERROR: $$m from RECOVERY_KERNEL_MODULES was not found" 1>&2 && exit 1; fi; \ done); \ [ $$? -ne 0 ] && exit 1; \ - ($(call build-image-kernel-modules-lineage,$$recovery_modules,$(KERNEL_RECOVERY_MODULES_OUT),/,$(KERNEL_RECOVERY_DEPMOD_STAGING_DIR),$(BOARD_RECOVERY_RAMDISK_KERNEL_MODULES_LOAD))); \ + ($(call build-image-kernel-modules-lineage,$$recovery_modules,$(KERNEL_RECOVERY_MODULES_OUT),/,$(KERNEL_RECOVERY_DEPMOD_STAGING_DIR),$(BOARD_RECOVERY_RAMDISK_KERNEL_MODULES_LOAD),/)); \ ) \ fi From e3a0712799261b8f88d25e97d4dbb3469c7de672 Mon Sep 17 00:00:00 2001 From: Aaron Kling Date: Sun, 20 Aug 2023 15:32:58 -0500 Subject: [PATCH 3/8] kernel: Support Qualcomm merge_dtbs script Script from clo kernel/build at kernel.lnx.5.10.r1-rel Change-Id: Ia90975c895644b86d9f861ddd5a18b7cf6ce1470 --- build/tasks/kernel.mk | 34 ++- build/tools/merge_dtbs.py | 436 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 468 insertions(+), 2 deletions(-) create mode 100755 build/tools/merge_dtbs.py diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk index f5f00f50a..cb441899e 100644 --- a/build/tasks/kernel.mk +++ b/build/tasks/kernel.mk @@ -1,5 +1,5 @@ # Copyright (C) 2012 The CyanogenMod Project -# (C) 2017-2022 The LineageOS Project +# (C) 2017-2023 The LineageOS Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -86,6 +86,10 @@ KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ RECOVERY_KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/RECOVERY_KERNEL_OBJ DTBO_OUT := $(TARGET_OUT_INTERMEDIATES)/DTBO_OBJ DTB_OUT := $(TARGET_OUT_INTERMEDIATES)/DTB_OBJ +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) +DTBS_BASE := $(DTB_OUT)/base +DTBS_OUT := $(DTB_OUT)/out +endif KERNEL_CONFIG := $(KERNEL_OUT)/.config KERNEL_RELEASE := $(KERNEL_OUT)/include/config/kernel.release RECOVERY_KERNEL_CONFIG := $(RECOVERY_KERNEL_OUT)/.config @@ -507,9 +511,17 @@ MKDTBOIMG := $(HOST_OUT_EXECUTABLES)/mkdtboimg$(HOST_EXECUTABLE_SUFFIX) $(DTBO_OUT): mkdir -p $(DTBO_OUT) -$(BOARD_PREBUILT_DTBOIMAGE): $(DTC) $(MKDTIMG) $(MKDTBOIMG) $(DTBO_OUT) +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) +$(BOARD_PREBUILT_DTBOIMAGE): $(INSTALLED_DTBIMAGE_TARGET) +else +$(BOARD_PREBUILT_DTBOIMAGE): $(DTBO_OUT) +endif +$(BOARD_PREBUILT_DTBOIMAGE): $(DTC) $(MKDTIMG) $(MKDTBOIMG) $(BOARD_PREBUILT_DTBOIMAGE): @echo "Building dtbo.img" +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) + $(MKDTBOIMG) create $@ --page_size=$(BOARD_KERNEL_PAGESIZE) $(shell find $(DTBS_OUT) -type f -name "*.dtbo" | sort) +else $(hide) find $(DTBO_OUT)/arch/$(KERNEL_ARCH)/boot/dts -type f -name "*.dtbo" | xargs rm -f $(call make-dtbo-target,$(KERNEL_DEFCONFIG)) $(call make-dtbo-target,$(TARGET_KERNEL_DTB)) @@ -523,6 +535,7 @@ else $(call make-dtbo-target,$(TARGET_KERNEL_DTBO)) endif # BOARD_KERNEL_SEPARATED_DTBO $(hide) touch -c $(DTBO_OUT) +endif # BOARD_USES_QCOM_MERGE_DTBS_SCRIPT endif # BOARD_CUSTOM_DTBOIMG_MK endif # TARGET_NEEDS_DTBOIMAGE/BOARD_KERNEL_SEPARATED_DTBO @@ -533,11 +546,20 @@ else ifeq ($(BOARD_PREBUILT_DTBIMAGE_DIR),) $(DTB_OUT): mkdir -p $(DTB_OUT) +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) +$(DTBS_BASE): + mkdir -p $(DTBS_BASE) +$(DTBS_OUT): + mkdir -p $(DTBS_OUT) +endif ifdef BOARD_DTB_CFG MKDTBOIMG := $(HOST_OUT_EXECUTABLES)/mkdtboimg.py$(HOST_EXECUTABLE_SUFFIX) $(INSTALLED_DTBIMAGE_TARGET): $(MKDTBOIMG) endif +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) +$(INSTALLED_DTBIMAGE_TARGET): $(HOST_OUT_EXECUTABLES)/fdtget $(HOST_OUT_EXECUTABLES)/fdtput $(HOST_OUT_EXECUTABLES)/fdtoverlay $(HOST_OUT_EXECUTABLES)/fdtoverlaymerge $(HOST_OUT_EXECUTABLES)/ufdt_apply_overlay $(DTBS_BASE) $(DTBS_OUT) +endif $(INSTALLED_DTBIMAGE_TARGET): $(DTC) $(DTB_OUT) ifeq ($(TARGET_WANTS_EMPTY_DTB),true) @rm -f $@ @@ -549,8 +571,16 @@ else $(call make-dtb-target,$(TARGET_KERNEL_DTB)) ifdef BOARD_DTB_CFG $(MKDTBOIMG) cfg_create $@ $(BOARD_DTB_CFG) -d $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts +else +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) + $(hide) find $(DTBS_BASE) -type f -name "*.dtb*" | xargs rm -f + $(hide) find $(DTBS_OUT) -type f -name "*.dtb*" | xargs rm -f + mv $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/qcom/*.dtb $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/qcom/*.dtbo $(DTBS_BASE)/ + PATH=$(abspath $(HOST_OUT_EXECUTABLES)):$${PATH} python3 $(BUILD_TOP)/vendor/lineage/build/tools/merge_dtbs.py $(DTBS_BASE) $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/qcom $(DTBS_OUT) + cat $(shell find $(DTB_OUT)/out -type f -name "*.dtb" | sort) > $@ else cat $(shell find $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts -type f -name "*.dtb" | sort) > $@ +endif # BOARD_USES_QCOM_MERGE_DTBS_SCRIPT endif # BOARD_DTB_CFG $(hide) touch -c $(DTB_OUT) endif # !TARGET_WANTS_EMPTY_DTB diff --git a/build/tools/merge_dtbs.py b/build/tools/merge_dtbs.py new file mode 100755 index 000000000..898be4ccc --- /dev/null +++ b/build/tools/merge_dtbs.py @@ -0,0 +1,436 @@ +#! /usr/bin/env python3 + +# Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import copy +import os +import sys +import subprocess +import shutil +from itertools import product, combinations_with_replacement, chain + +def split_array(array, cells): + """ + Helper function for parsing fdtget output + """ + if array is None: + return None + assert (len(array) % cells) == 0 + return frozenset(tuple(array[i*cells:(i*cells)+cells]) for i in range(len(array) // cells)) + +class DeviceTreeInfo(object): + def __init__(self, plat, board, pmic): + self.plat_id = plat + self.board_id = board + self.pmic_id = pmic + + def __str__(self): + s = "" + if self.plat_id is not None: + s += " msm-id = <{}>;".format(" ".join(map(str, self.plat_id))) + if self.board_id is not None: + s += " board-id = <{}>;".format(" ".join(map(str, self.board_id))) + if self.pmic_id is not None: + s += " pmic-id = <{}>;".format(" ".join(map(str, self.pmic_id))) + return s.strip() + + def __repr__(self): + return "<{} {}>".format(self.__class__.__name__, str(self)) + + def has_any_properties(self): + return self.plat_id is not None or self.board_id is not None or self.pmic_id is not None + + def __sub__(self, other): + """ + This devicetree has plat, board, and pmic id described like this: + msm-id = , + board-id = , + pmic-id = <0, 1> + + Other has plat, board, pmic are: + msm-id = , + board-id = + pmic-id = <0> + + (self - other) will split self into a set of devicetrees with different identifers + and meets the following requirements: + - One of the devicetrees matches the IDs supported by other + - The devices which self matches are still supported (through 1 or more extra devicetrees) + by creating new devicetrees with different plat/board/pmic IDs + """ + assert self.plat_id is None or isinstance(self.plat_id, (set, frozenset)) + assert self.board_id is None or isinstance(self.board_id, (set, frozenset)) + assert self.pmic_id is None or isinstance(self.pmic_id, (set, frozenset)) + assert other in self + + new_plat = other.plat_id is not None and self.plat_id != other.plat_id + new_board = other.board_id is not None and self.board_id != other.board_id + new_pmic = other.pmic_id is not None and self.pmic_id != other.pmic_id + + res = set() + # Create the devicetree that matches other exactly + s = copy.deepcopy(self) + if new_plat: + s.plat_id = other.plat_id + if new_board: + s.board_id = other.board_id + if new_pmic: + s.pmic_id = other.pmic_id + res.add(s) + + # now create the other possibilities by removing any combination of + # other's plat, board, and/or pmic. Set logic (unique elemnts) handles + # duplicate devicetrees IDs spit out by this loop + for combo in combinations_with_replacement([True, False], 3): + if not any((c and n) for (c, n) in zip(combo, (new_plat, new_board, new_pmic))): + continue + s = copy.deepcopy(self) + if combo[0] and new_plat: + s.plat_id -= other.plat_id + if combo[1] and new_board: + s.board_id -= other.board_id + if combo[2] and new_pmic: + s.pmic_id -= other.pmic_id + res.add(s) + return res + + def __hash__(self): + # Hash should only consider msm-id/board-id/pmic-id + return hash((self.plat_id, self.board_id, self.pmic_id)) + + def __and__(self, other): + s = copy.deepcopy(self) + for prop in ['plat_id', 'board_id', 'pmic_id']: + if getattr(self, prop) is None or getattr(other, prop) is None: + setattr(s, prop, None) + else: + setattr(s, prop, getattr(self, prop) & getattr(other, prop)) + return s + + def _do_equivalent(self, other, property): + other_prop = getattr(other, property) + self_prop = getattr(self, property) + if other_prop is None: + return True + return self_prop == other_prop + + def __eq__(self, other): + """ + Checks whether other plat_id, board_id, pmic_id matches either identically + or because the property is none + """ + if not isinstance(other, DeviceTreeInfo): + return False + if not other.has_any_properties(): + return False + return all(map(lambda p: self._do_equivalent(other, p), ['plat_id', 'board_id', 'pmic_id'])) + + + def _do_gt(self, other, property): + other_prop = getattr(other, property) + self_prop = getattr(self, property) + # if either property doesn't exist, it could merge in ABL + if self_prop is None or other_prop is None: + return True + # convert to iterable for convenience of below check + if isinstance(other_prop, tuple): + # if this property is all 0s, ABL coud match with anything on other + other_prop = [other_prop] + assert hasattr(other_prop, '__iter__') + if len(other_prop) == 1 and all(p == 0 for p in next(iter(other_prop))): + return True + # Test if this property intersects with other property + if hasattr(self_prop, '__contains__') and not isinstance(self_prop, tuple): + return any(p in self_prop for p in other_prop) + else: + return self_prop in other_prop + + def __gt__(self, other): + """ + Test if other is a more specific devicetree for self + + This is used to test whether other devicetree applies to self by ABL matching rules + """ + if not isinstance(other, DeviceTreeInfo): + return False + if not other.has_any_properties(): + return False + return all(map(lambda p: self._do_gt(other, p), ['plat_id', 'board_id', 'pmic_id'])) + + + def _do_contains(self, other, property): + other_prop = getattr(other, property) + self_prop = getattr(self, property) + # if other property doesn't exist, it can apply here + if other_prop is None: + return True + # if self and other are sets, use "issubset". Handle special case where other set is + # empty, in which case they aren't compatible because other_prop should be None + if isinstance(self_prop, (set, frozenset)) and isinstance(other_prop, (set, frozenset)): + return len(other_prop) > 0 and other_prop.issubset(self_prop) + # unpack to one item for convience of below check + if hasattr(other_prop, '__len__') and not isinstance(other_prop, tuple): + if len(other_prop) == 1: + other_prop = next(iter(other_prop)) + # if this is a single value (tuple), not a list of them, other needs to match exactly + if isinstance(self_prop, tuple): + return self_prop == other_prop + # otherwise, use contains if possible (e.g. list or set of tuples) + if hasattr(self_prop, '__contains__'): + return other_prop in self_prop + return False + + def __contains__(self, other): + """ + Test if other devicetree covers this devicetree. That is, the devices other devicetree + matches is a subset of the devices this devicetree matches + """ + if not isinstance(other, DeviceTreeInfo): + return False + if not other.has_any_properties(): + return False + return all(map(lambda p: self._do_contains(other, p), ['plat_id', 'board_id', 'pmic_id'])) + +class DeviceTree(DeviceTreeInfo): + def __init__(self, filename): + self.filename = filename + msm_id = split_array(self.get_prop('/', 'qcom,msm-id', check_output=False), 2) + board_id = split_array(self.get_prop('/', 'qcom,board-id', check_output=False), 2) + # default pmic-id-size is 4 + pmic_id_size = self.get_prop('/', 'qcom,pmic-id-size', check_output=False) or 4 + pmic_id = split_array(self.get_prop('/', 'qcom,pmic-id', check_output=False), pmic_id_size) + super().__init__(msm_id, board_id, pmic_id) + + if not self.has_any_properties(): + print('WARNING! {} has no properties and may match with any other devicetree'.format(self.filename)) + + def get_prop(self, node, property, prop_type='i', check_output=True): + r = subprocess.run(["fdtget", "-t", prop_type, self.filename, node, property], + check=check_output, stdout=subprocess.PIPE, + stderr=None if check_output else subprocess.DEVNULL) + if r.returncode != 0: + return None + out = r.stdout.decode("utf-8").strip() + + out_array = None + if prop_type[-1] == 'i' or prop_type[-1] == 'u': + out_array = [int(e) for e in out.split(' ')] + if prop_type[-1] == 'x': + out_array = [int(e, 16) for e in out.split(' ')] + if out_array is not None: + if len(out_array) == 0: + return None + if len(out_array) == 1: + return out_array[0] + return out_array + + return out + + def __str__(self): + return "{} [{}]".format(super().__str__(), self.filename) + +class InnerMergedDeviceTree(DeviceTreeInfo): + """ + InnerMergedDeviceTree is an actual representation of a merged devicetree. + It has a platform, board, and pmic ID, the "base" devicetree, and some set of add-on + devicetrees + """ + def __init__(self, filename, plat_id, board_id, pmic_id, techpacks=None): + self.base = filename + self.techpacks = techpacks or [] + super().__init__(plat_id, board_id, pmic_id) + + def try_add(self, techpack): + if not isinstance(techpack, DeviceTree): + raise TypeError("{} is not a DeviceTree object".format(repr(techpack))) + intersection = techpack & self + if intersection in self: + self.techpacks.append(intersection) + return True + return False + + def save(self, name=None, out_dir='.'): + if name is None: + name = self.get_name() + + out_file = os.path.join(out_dir, name) + ext = os.path.splitext(os.path.basename(self.base))[1] + + # This check might fail in future if we get into an edge case + # when splitting the base devicetree into multiple merged DTs + assert not os.path.exists(out_file) + + if len(self.techpacks) == 0: + cmd = ['cp', self.base, out_file] + else: + if ext == '.dtb': + cmd = ['fdtoverlay'] + else: + cmd = ['fdtoverlaymerge'] + cmd.extend(['-i', self.base]) + cmd.extend([tp.filename for tp in self.techpacks]) + cmd.extend(['-o', out_file]) + + print(' {}'.format(' '.join(cmd))) + subprocess.run(cmd, check=True) + + if self.plat_id: + plat_iter = self.plat_id if isinstance(self.plat_id, tuple) else chain.from_iterable(self.plat_id) + cmd = ['fdtput', '-t', 'i', out_file, '/', 'qcom,msm-id'] + list(map(str, plat_iter)) + print(' {}'.format(' '.join(cmd))) + subprocess.run(cmd, check=True) + + if self.board_id: + board_iter = self.board_id if isinstance(self.board_id, tuple) else chain.from_iterable(self.board_id) + cmd = ['fdtput', '-t', 'i', out_file, '/', 'qcom,board-id'] + list(map(str, board_iter)) + print(' {}'.format(' '.join(cmd))) + subprocess.run(cmd, check=True) + + if self.pmic_id: + pmic_iter = self.pmic_id if isinstance(self.pmic_id, tuple) else chain.from_iterable(self.pmic_id) + cmd = ['fdtput', '-t', 'i', out_file, '/', 'qcom,pmic-id'] + list(map(str, pmic_iter)) + print(' {}'.format(' '.join(cmd))) + subprocess.run(cmd, check=True) + + return DeviceTree(out_file) + + def get_name(self): + ext = os.path.splitext(os.path.basename(self.base))[1] + base_parts = self.filename_to_parts(self.base) + return '-'.join(chain.from_iterable([base_parts] + [self.filename_to_parts(tp.filename, ignored_parts=base_parts) for tp in self.techpacks])) + ext + + @staticmethod + def filename_to_parts(name, ignored_parts=[]): + # Extract just the basename, with no suffix + filename = os.path.splitext(os.path.basename(name))[0] + parts = filename.split('-') + return [part for part in parts if part not in ignored_parts] + + def __str__(self): + return "{} [{} + {{{}}}]".format(super().__str__(), self.base, " ".join(t.filename for t in self.techpacks)) + +class MergedDeviceTree(object): + def __init__(self, other): + self.merged_devicetrees = {InnerMergedDeviceTree(other.filename, other.plat_id, other.board_id, other.pmic_id)} + + def try_add(self, techpack): + did_add = False + for mdt in self.merged_devicetrees.copy(): + # techpack and kernel devicetree need only to overlap in order to merge, + # and not match exactly. Think: venn diagram. + # Need 2 things: The devicetree part that applies to + # both kernel and techpack intersection = (techpack & mdt) + # and the part that applies only to kernel difference = (mdt - intersection) + # Note that because devicetrees are "multi-dimensional", doing (mdt - intersection) + # may result in *multiple* devicetrees + + # techpack may apply to a superset of devices the mdt applies to + # reduce the techpack to just the things mdt has: + intersection = techpack & mdt + if intersection not in mdt: + continue + # mdt may apply to a superset of devices the techpack DT applies to + # (mdt - intersection) splits mdt into appropriate number of devicetrees + # such that we can apply techpack onto one of the resulting DTs in the + # difference + difference = mdt - intersection + if len(difference) > 1: + print('Splitting {}'.format(mdt)) + print(' because {}'.format(techpack)) + self.merged_devicetrees.remove(mdt) + self.merged_devicetrees.update(difference) + + for mdt in self.merged_devicetrees: + if mdt.try_add(techpack): + did_add = True + return did_add + + + def save(self, out_dir): + assert len(self.merged_devicetrees) > 0 + if len(self.merged_devicetrees) == 1: + name = os.path.basename(next(iter(self.merged_devicetrees)).base) + else: + name = None + for mdt in self.merged_devicetrees: + print() + yield mdt.save(name, out_dir) + +def parse_dt_files(dt_folder): + for root, dirs, files in os.walk(dt_folder): + for filename in files: + if os.path.splitext(filename)[1] not in ['.dtb', '.dtbo']: + continue + filepath = os.path.join(root, filename) + yield DeviceTree(filepath) + +def main(): + if len(sys.argv) != 4: + print("Usage: {} " + .format(sys.argv[0])) + sys.exit(1) + + # 1. Parse the devicetrees -- extract the device info (msm-id, board-id, pmic-id) + bases = parse_dt_files(sys.argv[1]) + techpacks = parse_dt_files(sys.argv[2]) + + # 2.1: Create an intermediate representation of the merged devicetrees, starting with the base + merged_devicetrees = list(map(lambda dt: MergedDeviceTree(dt), bases)) + # 2.2: Try to add techpack devicetree to each base DT + for techpack in techpacks: + did_add = False + for dt in merged_devicetrees: + if dt.try_add(techpack): + did_add = True + if not did_add: + print('WARNING! Could not apply {} to any devicetrees'.format(techpack)) + + print() + print('==================================') + created = [] + # 3. Save the deviectrees to real files + for dt in merged_devicetrees: + created.extend(dt.save(sys.argv[3])) + + print() + print('==================================') + # 4. Try to apply merged DTBOs onto merged DTBs, when appropriate + # This checks that DTBOs and DTBs generated by merge_dtbs.py can be merged by bootloader + # at runtime. + for base, dtbo in product(created, created): + if os.path.splitext(base.filename)[1] != '.dtb' or os.path.splitext(dtbo.filename)[1] != '.dtbo': + continue + # See DeviceTreeInfo.__gt__; this checks whether dtbo is more specific than the base + if dtbo > base: + cmd = ['ufdt_apply_overlay', base.filename, dtbo.filename, '/dev/null'] + print(' '.join(cmd)) + subprocess.run(cmd, check=True) + + +if __name__ == "__main__": + main() From fb076500d3897d8656800d786fc9eb914214eaca Mon Sep 17 00:00:00 2001 From: Bruno Martins Date: Thu, 14 Sep 2023 18:21:31 +0100 Subject: [PATCH 4/8] kernel: Include DTBOs from OEM/ODM folder in base DTB It can be the case where OEM/ODM decided to put the main DTBOs outside vendor/qcom (e.g. vendor/oplus). Support such usecase by generically allowing all .dtbo files found in all first-level subdirs to be moved to base DTB folder. Change-Id: I154d401b560535d1fa8cd7ed4965dd34a4cf75f2 --- build/tasks/kernel.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk index cb441899e..f1d5f5914 100644 --- a/build/tasks/kernel.mk +++ b/build/tasks/kernel.mk @@ -575,7 +575,7 @@ else ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) $(hide) find $(DTBS_BASE) -type f -name "*.dtb*" | xargs rm -f $(hide) find $(DTBS_OUT) -type f -name "*.dtb*" | xargs rm -f - mv $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/qcom/*.dtb $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/qcom/*.dtbo $(DTBS_BASE)/ + mv $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/qcom/*.dtb $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/*/*.dtbo $(DTBS_BASE)/ PATH=$(abspath $(HOST_OUT_EXECUTABLES)):$${PATH} python3 $(BUILD_TOP)/vendor/lineage/build/tools/merge_dtbs.py $(DTBS_BASE) $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/qcom $(DTBS_OUT) cat $(shell find $(DTB_OUT)/out -type f -name "*.dtb" | sort) > $@ else From f19fc9a0dd8e518c5b9d08a05f47b5d0e80ea8df Mon Sep 17 00:00:00 2001 From: SGCMarkus Date: Fri, 15 Sep 2023 19:08:00 +0200 Subject: [PATCH 5/8] kernel: Allow to limit the used .dtb files for the final DTB image On some devices too many .dtb files are generated. Instead of taking all of them, allow to only take selected .dtb files for the final DTB image. Example: Motorola Edge 40 Pro (rtwo, sm8550) generates the following: obj/DTB_OBJ/out/kaka-rumi.dtb obj/DTB_OBJ/out/kalama-rtwo-base-kalama-rtwo-evb1-overlay.dtb obj/DTB_OBJ/out/kalama-rtwo-base-kalama-rtwo-evt1-overlay.dtb obj/DTB_OBJ/out/kalama-rtwo-base-kalama-rtwo-na-vzw-evt2-overlay.dtb obj/DTB_OBJ/out/kalama-rtwo-base-kalama-rtwo-prc-dvt1b-overlay.dtb obj/DTB_OBJ/out/kalama-rtwo-base-kalama-rtwo-prc-pvt-overlay.dtb obj/DTB_OBJ/out/kalama-rtwo-base-kalama-rtwo-row-dvt1b-overlay.dtb obj/DTB_OBJ/out/kalama-rtwo-base.dtb obj/DTB_OBJ/out/kalama-v2-rtwo-base-kalama-rtwo-evb1-overlay.dtb obj/DTB_OBJ/out/kalama-v2-rtwo-base-kalama-rtwo-evt1-overlay.dtb obj/DTB_OBJ/out/kalama-v2-rtwo-base-kalama-rtwo-na-vzw-evt2-overlay.dtb obj/DTB_OBJ/out/kalama-v2-rtwo-base-kalama-rtwo-prc-dvt1b-overlay.dtb obj/DTB_OBJ/out/kalama-v2-rtwo-base-kalama-rtwo-prc-pvt-overlay.dtb obj/DTB_OBJ/out/kalama-v2-rtwo-base-kalama-rtwo-row-dvt1b-overlay.dtb obj/DTB_OBJ/out/kalama-v2-rtwo-base.dtb with only kalama-rtwo-base.dtb and kalama-v2-rtwo-base.dtb needed. Disabling compilation of the other kalama.dtb isn't possible, as this would also disable the compilation of the needed .dtbo files. Because they are earlier in alphabetical order, and the matching board ids, the bootloader ends up selecting those, instead of the correct ones. This results in USB (and possible other things) to not work. Change-Id: I486b6ec538a3e4906b5b8aa5ecb355b480b60de7 --- build/tasks/kernel.mk | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk index f1d5f5914..5d7c1ff1f 100644 --- a/build/tasks/kernel.mk +++ b/build/tasks/kernel.mk @@ -67,6 +67,9 @@ # # TARGET_FORCE_PREBUILT_KERNEL = Optional, use TARGET_PREBUILT_KERNEL even if # kernel sources are present +# +# TARGET_MERGE_DTBS_WILDCARD = Optional, limits the .dtb files used to generate the +# final DTB image when using QCOM's merge_dtbs script. ifneq ($(TARGET_NO_KERNEL),true) ifneq ($(TARGET_NO_KERNEL_OVERRIDE),true) @@ -78,6 +81,8 @@ KERNEL_DEFCONFIG := $(TARGET_KERNEL_CONFIG) RECOVERY_DEFCONFIG := $(TARGET_KERNEL_RECOVERY_CONFIG) VARIANT_DEFCONFIG := $(TARGET_KERNEL_VARIANT_CONFIG) SELINUX_DEFCONFIG := $(TARGET_KERNEL_SELINUX_CONFIG) +# dtb generation - optional +TARGET_MERGE_DTBS_WILDCARD ?= * ## Internal variables DTC := $(HOST_OUT_EXECUTABLES)/dtc @@ -577,7 +582,7 @@ ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) $(hide) find $(DTBS_OUT) -type f -name "*.dtb*" | xargs rm -f mv $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/qcom/*.dtb $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/*/*.dtbo $(DTBS_BASE)/ PATH=$(abspath $(HOST_OUT_EXECUTABLES)):$${PATH} python3 $(BUILD_TOP)/vendor/lineage/build/tools/merge_dtbs.py $(DTBS_BASE) $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/qcom $(DTBS_OUT) - cat $(shell find $(DTB_OUT)/out -type f -name "*.dtb" | sort) > $@ + cat $(shell find $(DTB_OUT)/out -type f -name "${TARGET_MERGE_DTBS_WILDCARD}.dtb" | sort) > $@ else cat $(shell find $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts -type f -name "*.dtb" | sort) > $@ endif # BOARD_USES_QCOM_MERGE_DTBS_SCRIPT From d8a92c0662588c0c68b6eac6d3f55f8894d4e423 Mon Sep 17 00:00:00 2001 From: Bruno Martins Date: Tue, 19 Sep 2023 15:59:00 +0100 Subject: [PATCH 6/8] kernel: Use pahole from Google prebuilts This fixes the following warnings: 13:04:54 Disallowed PATH tool "pahole" used: []string{"pahole", "--version"} 13:04:54 See https://android.googlesource.com/platform/build/+/master/Changes.md#PATH_Tools for more information. "pahole" is not allowed to be used. See https://android.googlesource.com/platform/build/+/master/Changes.md#PATH_Tools for more information. /home/bgcngm/android/lineage/kernel/oneplus/sm8550/scripts/pahole-flags.sh: 12: [: Illegal number: /home/bgcngm/android/lineage/kernel/oneplus/sm8550/scripts/pahole-flags.sh: 16: [: Illegal number: /home/bgcngm/android/lineage/kernel/oneplus/sm8550/scripts/pahole-flags.sh: 20: [: Illegal number: Change-Id: Ice2a3753301a7b7782037fd35544e2831b258650 --- build/tasks/kernel.mk | 5 ++--- config/BoardConfigKernel.mk | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk index 5d7c1ff1f..3188e0ab2 100644 --- a/build/tasks/kernel.mk +++ b/build/tasks/kernel.mk @@ -86,7 +86,6 @@ TARGET_MERGE_DTBS_WILDCARD ?= * ## Internal variables DTC := $(HOST_OUT_EXECUTABLES)/dtc -PAHOLE := $(HOST_OUT_EXECUTABLES)/pahole KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ RECOVERY_KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/RECOVERY_KERNEL_OBJ DTBO_OUT := $(TARGET_OUT_INTERMEDIATES)/DTBO_OBJ @@ -431,7 +430,7 @@ $(KERNEL_CONFIG): $(KERNEL_OUT) $(ALL_KERNEL_DEFCONFIG_SRCS) @echo "Building Kernel Config" $(call make-kernel-config,$(KERNEL_OUT),$(KERNEL_DEFCONFIG)) -$(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_CONFIG) $(DEPMOD) $(DTC) $(PAHOLE) +$(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_CONFIG) $(DEPMOD) $(DTC) @echo "Building Kernel Image ($(BOARD_KERNEL_IMAGE_NAME))" $(call make-kernel-target,$(BOARD_KERNEL_IMAGE_NAME)) $(hide) if grep -q '^CONFIG_OF=y' $(KERNEL_CONFIG); then \ @@ -605,7 +604,7 @@ $(RECOVERY_KERNEL_CONFIG): $(ALL_RECOVERY_KERNEL_DEFCONFIG_SRCS) @echo "Building Recovery Kernel Config" $(call make-kernel-config,$(RECOVERY_KERNEL_OUT),$(RECOVERY_DEFCONFIG)) -$(TARGET_PREBUILT_INT_RECOVERY_KERNEL): $(RECOVERY_KERNEL_CONFIG) $(DEPMOD) $(DTC) $(PAHOLE) +$(TARGET_PREBUILT_INT_RECOVERY_KERNEL): $(RECOVERY_KERNEL_CONFIG) $(DEPMOD) $(DTC) @echo "Building Recovery Kernel Image ($(BOARD_KERNEL_IMAGE_NAME))" $(call make-recovery-kernel-target,$(BOARD_KERNEL_IMAGE_NAME)) diff --git a/config/BoardConfigKernel.mk b/config/BoardConfigKernel.mk index d9447c743..c70030597 100644 --- a/config/BoardConfigKernel.mk +++ b/config/BoardConfigKernel.mk @@ -215,6 +215,9 @@ KERNEL_MAKE_FLAGS += YACC=$(BUILD_TOP)/prebuilts/build-tools/$(HOST_PREBUILT_TAG KERNEL_MAKE_FLAGS += M4=$(BUILD_TOP)/prebuilts/build-tools/$(HOST_PREBUILT_TAG)/bin/m4 TOOLS_PATH_OVERRIDE += BISON_PKGDATADIR=$(BUILD_TOP)/prebuilts/build-tools/common/bison +# Since Linux 5.10, pahole is required +KERNEL_MAKE_FLAGS += PAHOLE=$(BUILD_TOP)/prebuilts/kernel-build-tools/linux-x86/bin/pahole + # Set the out dir for the kernel's O= arg # This needs to be an absolute path, so only set this if the standard out dir isn't used OUT_DIR_PREFIX := $(shell echo $(OUT_DIR) | sed -e 's|/target/.*$$||g') From 5e34bd23aa0199ca020aa85a9ad2d33f51ce06ef Mon Sep 17 00:00:00 2001 From: Tim Zimmermann Date: Wed, 6 Sep 2023 13:09:51 +0200 Subject: [PATCH 7/8] kernel: Use correct variable name for vendor_kernel_boot modules * This was missed in bdfc913935c2a8c38ed999a4c84bb96492e0e5fe * Aligns the variable name for vendor_kernel_boot modules with AOSP Change-Id: I8d59f7b5d62e29a0484ca36fadcb74acab4f1859 --- build/tasks/kernel.mk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk index 3188e0ab2..32cf7dead 100644 --- a/build/tasks/kernel.mk +++ b/build/tasks/kernel.mk @@ -404,14 +404,17 @@ endif MODULES_INTERMEDIATES := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,kernel_modules) ifneq (,$(filter dlkm,$(BOARD_VENDOR_RAMDISK_FRAGMENTS))) +KERNEL_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD) KERNEL_VENDOR_RAMDISK_MODULES_OUT := $(VENDOR_RAMDISK_FRAGMENT.dlkm.STAGING_DIR) KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_vendor_ramdisk_fragment-stage-dlkm) $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_TARGETS): $(TARGET_PREBUILT_INT_KERNEL) else ifeq ($(PRODUCT_BUILD_VENDOR_KERNEL_BOOT_IMAGE),true) +KERNEL_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_KERNEL_RAMDISK_KERNEL_MODULES_LOAD) KERNEL_VENDOR_RAMDISK_MODULES_OUT := $(TARGET_VENDOR_KERNEL_RAMDISK_OUT) KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_vendor_kernel_ramdisk) $(INTERNAL_VENDOR_KERNEL_RAMDISK_TARGET): $(TARGET_PREBUILT_INT_KERNEL) else +KERNEL_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD) KERNEL_VENDOR_RAMDISK_MODULES_OUT := $(TARGET_VENDOR_RAMDISK_OUT) KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_vendor_ramdisk) $(INTERNAL_VENDOR_RAMDISK_TARGET): $(TARGET_PREBUILT_INT_KERNEL) @@ -478,7 +481,7 @@ $(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_CONFIG) $(DEPMOD) $(DTC) if [ -n "$$p" ]; then echo $$p; else echo "ERROR: $$m from BOOT_KERNEL_MODULES was not found" 1>&2 && exit 1; fi; \ done); \ [ $$? -ne 0 ] && exit 1; \ - ($(call build-image-kernel-modules-lineage,$$vendor_boot_modules,$(KERNEL_VENDOR_RAMDISK_MODULES_OUT),/,$(KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR),$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD),/)); \ + ($(call build-image-kernel-modules-lineage,$$vendor_boot_modules,$(KERNEL_VENDOR_RAMDISK_MODULES_OUT),/,$(KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR),$(KERNEL_VENDOR_RAMDISK_KERNEL_MODULES_LOAD),/)); \ ) \ $(if $(RECOVERY_KERNEL_MODULES),\ recovery_modules=$$(for m in $(RECOVERY_KERNEL_MODULES); do \ From 7397fd7c15a11f5acb38a65ffe113110d8c86817 Mon Sep 17 00:00:00 2001 From: pppig236 Date: Mon, 16 Oct 2023 09:49:18 -0400 Subject: [PATCH 8/8] kernel: Halt build process if an external module fails to compile Before: mka bootimage qcacld failed to compile, but boot.img is generated After: mka bootimage qcacld failed to compile and no boot.img is generated Commit fadfdbf introduced the idea of building external modules, but it didn't account for the scenario where compilation could fail while the boot.img is still being built. Fix this by properly stopping the build process as soon as the external module fails to compile. Change-Id: Ifed28825f8e4b78d304fe62a47908e208edfb886 --- build/tasks/kernel.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk index 32cf7dead..9b661e463 100644 --- a/build/tasks/kernel.mk +++ b/build/tasks/kernel.mk @@ -450,8 +450,8 @@ $(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_CONFIG) $(DEPMOD) $(DTC) rpath=$$(python3 -c 'import os,sys;print(os.path.relpath(*(sys.argv[1:])))' $(TARGET_KERNEL_EXT_MODULE_ROOT) $(KERNEL_SRC)); \ $(foreach p, $(TARGET_KERNEL_EXT_MODULES),\ $$pwd; \ - $(call make-external-module-target,$(p),$$rpath,); \ - $(call make-external-module-target,$(p),$$rpath,INSTALL_MOD_PATH=$(MODULES_INTERMEDIATES) INSTALL_MOD_STRIP=1 KERNEL_UAPI_HEADERS_DIR=$(KERNEL_OUT) modules_install)); \ + $(call make-external-module-target,$(p),$$rpath,) || exit "$$?"; \ + $(call make-external-module-target,$(p),$$rpath,INSTALL_MOD_PATH=$(MODULES_INTERMEDIATES) INSTALL_MOD_STRIP=1 KERNEL_UAPI_HEADERS_DIR=$(KERNEL_OUT) modules_install)) || exit "$$?"; \ ) \ kernel_release=$$(cat $(KERNEL_RELEASE)) \ kernel_modules_dir=$(MODULES_INTERMEDIATES)/lib/modules/$$kernel_release \