| #!/bin/bash |
| |
| # Copyright (C) 2019 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| # Usage: |
| # build/build.sh <make options>* |
| # or: |
| # To define custom out and dist directories: |
| # OUT_DIR=<out dir> DIST_DIR=<dist dir> build/build.sh <make options>* |
| # To use a custom build config: |
| # BUILD_CONFIG=<path to the build.config> <make options>* |
| # |
| # Examples: |
| # To define custom out and dist directories: |
| # OUT_DIR=output DIST_DIR=dist build/build.sh -j24 V=1 |
| # To use a custom build config: |
| # BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh -j24 V=1 |
| # |
| # The following environment variables are considered during execution: |
| # |
| # BUILD_CONFIG |
| # Build config file to initialize the build environment from. The location |
| # is to be defined relative to the repo root directory. |
| # Defaults to 'build.config'. |
| # |
| # BUILD_CONFIG_FRAGMENTS |
| # A whitespace-separated list of additional build config fragments to be |
| # sourced after the main build config file. Typically used for sanitizers or |
| # other special builds. |
| # |
| # OUT_DIR |
| # Base output directory for the kernel build. |
| # Defaults to <REPO_ROOT>/out/<BRANCH>. |
| # |
| # DIST_DIR |
| # Base output directory for the kernel distribution. |
| # Defaults to <OUT_DIR>/dist |
| # |
| # MAKE_GOALS |
| # List of targets passed to Make when compiling the kernel. |
| # Typically: Image, modules, and a DTB (if applicable). |
| # |
| # EXT_MODULES |
| # Space separated list of external kernel modules to be build. |
| # |
| # UNSTRIPPED_MODULES |
| # Space separated list of modules to be copied to <DIST_DIR>/unstripped |
| # for debugging purposes. |
| # |
| # COMPRESS_UNSTRIPPED_MODULES |
| # If set to "1", then compress the unstripped modules into a tarball. |
| # |
| # CC |
| # Override compiler to be used. (e.g. CC=clang) Specifying CC=gcc |
| # effectively unsets CC to fall back to the default gcc detected by kbuild |
| # (including any target triplet). To use a custom 'gcc' from PATH, use an |
| # absolute path, e.g. CC=/usr/local/bin/gcc |
| # |
| # LD |
| # Override linker (flags) to be used. |
| # |
| # HERMETIC_TOOLCHAIN |
| # When set, the PATH during kernel build will be restricted to a set of |
| # known prebuilt directories and selected host tools that are usually not |
| # provided by prebuilt toolchains. |
| # |
| # ADDITIONAL_HOST_TOOLS |
| # A whitespace separated set of tools that will be allowed to be used from |
| # the host when running the build with HERMETIC_TOOLCHAIN=1. |
| # |
| # ABI_DEFINITION |
| # Location of the abi definition file relative to <REPO_ROOT>/KERNEL_DIR |
| # If defined (usually in build.config), also copy that abi definition to |
| # <OUT_DIR>/dist/abi.xml when creating the distribution. |
| # |
| # KMI_SYMBOL_LIST |
| # Location of the main KMI symbol list file relative to |
| # <REPO_ROOT>/KERNEL_DIR If defined (usually in build.config), also copy |
| # that symbol list definition to <OUT_DIR>/dist/abi_symbollist when |
| # creating the distribution. |
| # |
| # ADDITIONAL_KMI_SYMBOL_LISTS |
| # Location of secondary KMI symbol list files relative to |
| # <REPO_ROOT>/KERNEL_DIR. If defined, these additional symbol lists will be |
| # appended to the main one before proceeding to the distribution creation. |
| # |
| # KMI_ENFORCED |
| # This is an indicative option to signal that KMI is enforced in this build |
| # config. If set to "1", downstream KMI checking tools might respect it and |
| # react to it by failing if KMI differences are detected. |
| # |
| # GENERATE_VMLINUX_BTF |
| # If set to "1", generate a vmlinux.btf that is stripped off any debug |
| # symbols, but contains type and symbol information within a .BTF section. |
| # This is suitable for ABI analysis through BTF. |
| # |
| # Environment variables to influence the stages of the kernel build. |
| # |
| # SKIP_MRPROPER |
| # if set to "1", skip `make mrproper` |
| # |
| # SKIP_DEFCONFIG |
| # if set to "1", skip `make defconfig` |
| # |
| # SKIP_IF_VERSION_MATCHES |
| # if defined, skip compiling anything if the kernel version in vmlinux |
| # matches the expected kernel version. This is useful for mixed build, where |
| # GKI kernel does not change frequently and we can simply skip everything |
| # in build.sh. Note: if the expected version string contains "dirty", then |
| # this flag would have not cause build.sh to exit early. |
| # |
| # PRE_DEFCONFIG_CMDS |
| # Command evaluated before `make defconfig` |
| # |
| # POST_DEFCONFIG_CMDS |
| # Command evaluated after `make defconfig` and before `make`. |
| # |
| # POST_KERNEL_BUILD_CMDS |
| # Command evaluated after `make`. |
| # |
| # LTO=[full|thin|none] |
| # If set to "full", force any kernel with LTO_CLANG support to be built |
| # with full LTO, which is the most optimized method. This is the default, |
| # but can result in very slow build times, especially when building |
| # incrementally. (This mode does not require CFI to be disabled.) |
| # If set to "thin", force any kernel with LTO_CLANG support to be built |
| # with ThinLTO, which trades off some optimizations for incremental build |
| # speed. This is nearly always what you want for local development. (This |
| # mode does not require CFI to be disabled.) |
| # If set to "none", force any kernel with LTO_CLANG support to be built |
| # without any LTO (upstream default), which results in no optimizations |
| # and also disables LTO-dependent features like CFI. This mode is not |
| # recommended because CFI will not be able to catch bugs if it is |
| # disabled. |
| # |
| # TAGS_CONFIG |
| # if defined, calls ./scripts/tags.sh utility with TAGS_CONFIG as argument |
| # and exit once tags have been generated |
| # |
| # IN_KERNEL_MODULES |
| # if defined, install kernel modules |
| # |
| # SKIP_EXT_MODULES |
| # if defined, skip building and installing of external modules |
| # |
| # DO_NOT_STRIP_MODULES |
| # if set to "1", keep debug information for distributed modules. |
| # Note, modules will still be stripped when copied into the ramdisk. |
| # |
| # EXTRA_CMDS |
| # Command evaluated after building and installing kernel and modules. |
| # |
| # DIST_CMDS |
| # Command evaluated after copying files to DIST_DIR |
| # |
| # SKIP_CP_KERNEL_HDR |
| # if defined, skip installing kernel headers. |
| # |
| # BUILD_BOOT_IMG |
| # if defined, build a boot.img binary that can be flashed into the 'boot' |
| # partition of an Android device. The boot image contains a header as per the |
| # format defined by https://source.android.com/devices/bootloader/boot-image-header |
| # followed by several components like kernel, ramdisk, DTB etc. The ramdisk |
| # component comprises of a GKI ramdisk cpio archive concatenated with a |
| # vendor ramdisk cpio archive which is then gzipped. It is expected that |
| # all components are present in ${DIST_DIR}. |
| # |
| # When the BUILD_BOOT_IMG flag is defined, the following flags that point to the |
| # various components needed to build a boot.img also need to be defined. |
| # - MKBOOTIMG_PATH=<path to the mkbootimg.py script which builds boot.img> |
| # (defaults to tools/mkbootimg/mkbootimg.py) |
| # - GKI_RAMDISK_PREBUILT_BINARY=<Name of the GKI ramdisk prebuilt which includes |
| # the generic ramdisk components like init and the non-device-specific rc files> |
| # - VENDOR_RAMDISK_BINARY=<Space separated list of vendor ramdisk binaries |
| # which includes the device-specific components of ramdisk like the fstab |
| # file and the device-specific rc files. If specifying multiple vendor ramdisks |
| # and identical file paths exist in the ramdisks, the file from last ramdisk is used.> |
| # - KERNEL_BINARY=<name of kernel binary, eg. Image.lz4, Image.gz etc> |
| # - BOOT_IMAGE_HEADER_VERSION=<version of the boot image header> |
| # (defaults to 3) |
| # - KERNEL_CMDLINE=<string of kernel parameters for boot> |
| # - KERNEL_VENDOR_CMDLINE=<string of kernel parameters for vendor boot image, |
| # vendor_boot when BOOT_IMAGE_HEADER_VERSION >= 3; boot otherwise> |
| # - VENDOR_FSTAB=<Path to the vendor fstab to be included in the vendor |
| # ramdisk> |
| # - TAGS_OFFSET=<physical address for kernel tags> |
| # - RAMDISK_OFFSET=<ramdisk physical load address> |
| # If the BOOT_IMAGE_HEADER_VERSION is less than 3, two additional variables must |
| # be defined: |
| # - BASE_ADDRESS=<base address to load the kernel at> |
| # - PAGE_SIZE=<flash page size> |
| # If BOOT_IMAGE_HEADER_VERSION >= 3, a vendor_boot image will be built |
| # unless SKIP_VENDOR_BOOT is defined. |
| # - MODULES_LIST=<file to list of modules> list of modules to use for |
| # vendor_boot.modules.load. If this property is not set, then the default |
| # modules.load is used. |
| # - TRIM_UNUSED_MODULES. If set, then modules not mentioned in |
| # modules.load are removed from initramfs. If MODULES_LIST is unset, then |
| # having this variable set effectively becomes a no-op. |
| # - MODULES_BLOCKLIST=<modules.blocklist file> A list of modules which are |
| # blocked from being loaded. This file is copied directly to staging directory, |
| # and should be in the format: |
| # blocklist module_name |
| # - MKBOOTIMG_EXTRA_ARGS=<space-delimited mkbootimg arguments> |
| # Refer to: ./mkbootimg.py --help |
| # If BOOT_IMAGE_HEADER_VERSION >= 4, the following variable can be defined: |
| # - VENDOR_BOOTCONFIG=<string of bootconfig parameters> |
| # - INITRAMFS_VENDOR_RAMDISK_FRAGMENT_NAME=<name of the ramdisk fragment> |
| # If BUILD_INITRAMFS is specified, then build the .ko and depmod files as |
| # a standalone vendor ramdisk fragment named as the given string. |
| # - INITRAMFS_VENDOR_RAMDISK_FRAGMENT_MKBOOTIMG_ARGS=<mkbootimg arguments> |
| # Refer to: https://source.android.com/devices/bootloader/partitions/vendor-boot-partitions#mkbootimg-arguments |
| # |
| # VENDOR_RAMDISK_CMDS |
| # When building vendor boot image, VENDOR_RAMDISK_CMDS enables the build |
| # config file to specify command(s) for further altering the prebuilt vendor |
| # ramdisk binary. For example, the build config file could add firmware files |
| # on the vendor ramdisk (lib/firmware) for testing purposes. |
| # |
| # AVB_SIGN_BOOT_IMG |
| # if defined, sign the boot image using the AVB_BOOT_KEY. Refer to |
| # https://android.googlesource.com/platform/external/avb/+/master/README.md |
| # for details on what Android Verified Boot is and how it works. The kernel |
| # prebuilt tool `avbtool` is used for signing. |
| # |
| # When AVB_SIGN_BOOT_IMG is defined, the following flags need to be |
| # defined: |
| # - AVB_BOOT_PARTITION_SIZE=<size of the boot partition in bytes> |
| # - AVB_BOOT_KEY=<absolute path to the key used for signing> The Android test |
| # key has been uploaded to the kernel/prebuilts/build-tools project here: |
| # https://android.googlesource.com/kernel/prebuilts/build-tools/+/refs/heads/master/linux-x86/share/avb |
| # - AVB_BOOT_ALGORITHM=<AVB_BOOT_KEY algorithm used> e.g. SHA256_RSA2048. For the |
| # full list of supported algorithms, refer to the enum AvbAlgorithmType in |
| # https://android.googlesource.com/platform/external/avb/+/refs/heads/master/libavb/avb_crypto.h |
| # |
| # BUILD_INITRAMFS |
| # if set to "1", build a ramdisk containing all .ko files and resulting |
| # depmod artifacts |
| # |
| # MODULES_OPTIONS |
| # A /lib/modules/modules.options file is created on the ramdisk containing |
| # the contents of this variable, lines should be of the form: options |
| # <modulename> <param1>=<val> <param2>=<val> ... |
| # |
| # MODULES_ORDER |
| # location of an optional file containing the list of modules that are |
| # expected to be built for the current configuration, in the modules.order |
| # format, relative to the kernel source tree. |
| # |
| # GKI_MODULES_LIST |
| # location of an optional file containing the list of GKI modules, relative |
| # to the kernel source tree. This should be set in downstream builds to |
| # ensure the ABI tooling correctly differentiates vendor/OEM modules and GKI |
| # modules. This should not be set in the upstream GKI build.config. |
| # |
| # VENDOR_DLKM_MODULES_LIST |
| # location (relative to the repo root directory) of an optional file |
| # containing the list of kernel modules which shall be copied into a |
| # vendor_dlkm partition image. Any modules passed into MODULES_LIST which |
| # become part of the vendor_boot.modules.load will be trimmed from the |
| # vendor_dlkm.modules.load. |
| # |
| # VENDOR_DLKM_MODULES_BLOCKLIST |
| # location (relative to the repo root directory) of an optional file |
| # containing a list of modules which are blocked from being loaded. This |
| # file is copied directly to the staging directory and should be in the |
| # format: blocklist module_name |
| # |
| # VENDOR_DLKM_PROPS |
| # location (relative to the repo root directory) of a text file containing |
| # the properties to be used for creation of a vendor_dlkm image |
| # (filesystem, partition size, etc). If this is not set (and |
| # VENDOR_DLKM_MODULES_LIST is), a default set of properties will be used |
| # which assumes an ext4 filesystem and a dynamic partition. |
| # |
| # LZ4_RAMDISK |
| # if set to "1", any ramdisks generated will be lz4 compressed instead of |
| # gzip compressed. |
| # |
| # TRIM_NONLISTED_KMI |
| # if set to "1", enable the CONFIG_UNUSED_KSYMS_WHITELIST kernel config |
| # option to un-export from the build any un-used and non-symbol-listed |
| # (as per KMI_SYMBOL_LIST) symbol. |
| # |
| # KMI_SYMBOL_LIST_STRICT_MODE |
| # if set to "1", add a build-time check between the KMI_SYMBOL_LIST and the |
| # KMI resulting from the build, to ensure they match 1-1. |
| # |
| # KMI_STRICT_MODE_OBJECTS |
| # optional list of objects to consider for the KMI_SYMBOL_LIST_STRICT_MODE |
| # check. Defaults to 'vmlinux'. |
| # |
| # GKI_DIST_DIR |
| # optional directory from which to copy GKI artifacts into DIST_DIR |
| # |
| # GKI_BUILD_CONFIG |
| # If set, builds a second set of kernel images using GKI_BUILD_CONFIG to |
| # perform a "mixed build." Mixed builds creates "GKI kernel" and "vendor |
| # modules" from two different trees. The GKI kernel tree can be the Android |
| # Common Kernel and the vendor modules tree can be a complete vendor kernel |
| # tree. GKI_DIST_DIR (above) is set and the GKI kernel's DIST output is |
| # copied to this DIST output. This allows a vendor tree kernel image to be |
| # effectively discarded and a GKI kernel Image used from an Android Common |
| # Kernel. Any variables prefixed with GKI_ are passed into into the GKI |
| # kernel's build.sh invocation. |
| # |
| # Note: For historic reasons, internally, OUT_DIR will be copied into |
| # COMMON_OUT_DIR, and OUT_DIR will be then set to |
| # ${COMMON_OUT_DIR}/${KERNEL_DIR}. This has been done to accommodate existing |
| # build.config files that expect ${OUT_DIR} to point to the output directory of |
| # the kernel build. |
| # |
| # The kernel is built in ${COMMON_OUT_DIR}/${KERNEL_DIR}. |
| # Out-of-tree modules are built in ${COMMON_OUT_DIR}/${EXT_MOD} where |
| # ${EXT_MOD} is the path to the module source code. |
| |
| set -e |
| |
| # Save environment for mixed build support. |
| OLD_ENVIRONMENT=$(mktemp) |
| export -p > ${OLD_ENVIRONMENT} |
| |
| # rel_path <to> <from> |
| # Generate relative directory path to reach directory <to> from <from> |
| function rel_path() { |
| local to=$1 |
| local from=$2 |
| local path= |
| local stem= |
| local prevstem= |
| [ -n "$to" ] || return 1 |
| [ -n "$from" ] || return 1 |
| to=$(readlink -e "$to") |
| from=$(readlink -e "$from") |
| [ -n "$to" ] || return 1 |
| [ -n "$from" ] || return 1 |
| stem=${from}/ |
| while [ "${to#$stem}" == "${to}" -a "${stem}" != "${prevstem}" ]; do |
| prevstem=$stem |
| stem=$(readlink -e "${stem}/..") |
| [ "${stem%/}" == "${stem}" ] && stem=${stem}/ |
| path=${path}../ |
| done |
| echo ${path}${to#$stem} |
| } |
| |
| # $1 directory of kernel modules ($1/lib/modules/x.y) |
| # $2 flags to pass to depmod |
| # $3 kernel version |
| function run_depmod() { |
| ( |
| local ramdisk_dir=$1 |
| local DEPMOD_OUTPUT |
| |
| cd ${ramdisk_dir} |
| if ! DEPMOD_OUTPUT="$(depmod $2 -F ${DIST_DIR}/System.map -b . $3 2>&1)"; then |
| echo "$DEPMOD_OUTPUT" >&2 |
| exit 1 |
| fi |
| echo "$DEPMOD_OUTPUT" |
| if { echo "$DEPMOD_OUTPUT" | grep -q "needs unknown symbol"; }; then |
| echo "ERROR: kernel module(s) need unknown symbol(s)" >&2 |
| exit 1 |
| fi |
| ) |
| } |
| |
| # $1 MODULES_LIST, <File contains the list of modules that should go in the ramdisk> |
| # $2 MODULES_STAGING_DIR <The directory to look for all the compiled modules> |
| # $3 IMAGE_STAGING_DIR <The destination directory in which MODULES_LIST is |
| # expected, and it's corresponding modules.* files> |
| # $4 MODULES_BLOCKLIST, <File contains the list of modules to prevent from loading> |
| # $5 flags to pass to depmod |
| function create_modules_staging() { |
| local modules_list_file=$1 |
| local src_dir=$(echo $2/lib/modules/*) |
| local version=$(basename "${src_dir}") |
| local dest_dir=$3/lib/modules/${version} |
| local dest_stage=$3 |
| local modules_blocklist_file=$4 |
| local depmod_flags=$5 |
| |
| rm -rf ${dest_dir} |
| mkdir -p ${dest_dir}/kernel |
| find ${src_dir}/kernel/ -maxdepth 1 -mindepth 1 \ |
| -exec cp -r {} ${dest_dir}/kernel/ \; |
| # The other modules.* files will be generated by depmod |
| cp ${src_dir}/modules.order ${dest_dir}/modules.order |
| cp ${src_dir}/modules.builtin ${dest_dir}/modules.builtin |
| |
| if [ -n "${EXT_MODULES}" ]; then |
| mkdir -p ${dest_dir}/extra/ |
| cp -r ${src_dir}/extra/* ${dest_dir}/extra/ |
| (cd ${dest_dir}/ && \ |
| find extra -type f -name "*.ko" | sort >> modules.order) |
| fi |
| |
| if [ "${DO_NOT_STRIP_MODULES}" = "1" ]; then |
| # strip debug symbols off initramfs modules |
| find ${dest_dir} -type f -name "*.ko" \ |
| -exec ${OBJCOPY:-${CROSS_COMPILE}objcopy} --strip-debug {} \; |
| fi |
| |
| if [ -n "${modules_list_file}" ]; then |
| echo "========================================================" |
| echo " Reducing modules.order to:" |
| # Need to make sure we can find modules_list_file from the staging dir |
| if [[ -f "${ROOT_DIR}/${modules_list_file}" ]]; then |
| modules_list_file="${ROOT_DIR}/${modules_list_file}" |
| elif [[ "${modules_list_file}" != /* ]]; then |
| echo "modules list must be an absolute path or relative to ${ROOT_DIR}: ${modules_list_file}" |
| exit 1 |
| elif [[ ! -f "${modules_list_file}" ]]; then |
| echo "Failed to find modules list: ${modules_list_file}" |
| exit 1 |
| fi |
| |
| local modules_list_filter=$(mktemp) |
| local old_modules_list=$(mktemp) |
| |
| # Remove all lines starting with "#" (comments) |
| # Exclamation point makes interpreter ignore the exit code under set -e |
| ! grep -v "^\#" ${modules_list_file} > ${modules_list_filter} |
| |
| # grep the modules.order for any KOs in the modules list |
| cp ${dest_dir}/modules.order ${old_modules_list} |
| ! grep -w -f ${modules_list_filter} ${old_modules_list} > ${dest_dir}/modules.order |
| rm -f ${modules_list_filter} ${old_modules_list} |
| cat ${dest_dir}/modules.order | sed -e "s/^/ /" |
| fi |
| |
| if [ -n "${modules_blocklist_file}" ]; then |
| # Need to make sure we can find modules_blocklist_file from the staging dir |
| if [[ -f "${ROOT_DIR}/${modules_blocklist_file}" ]]; then |
| modules_blocklist_file="${ROOT_DIR}/${modules_blocklist_file}" |
| elif [[ "${modules_blocklist_file}" != /* ]]; then |
| echo "modules blocklist must be an absolute path or relative to ${ROOT_DIR}: ${modules_blocklist_file}" |
| exit 1 |
| elif [[ ! -f "${modules_blocklist_file}" ]]; then |
| echo "Failed to find modules blocklist: ${modules_blocklist_file}" |
| exit 1 |
| fi |
| |
| cp ${modules_blocklist_file} ${dest_dir}/modules.blocklist |
| fi |
| |
| if [ -n "${TRIM_UNUSED_MODULES}" ]; then |
| echo "========================================================" |
| echo " Trimming unused modules" |
| local used_blocklist_modules=$(mktemp) |
| if [ -f ${dest_dir}/modules.blocklist ]; then |
| # TODO: the modules blocklist could contain module aliases instead of the filename |
| sed -n -E -e 's/blocklist (.+)/\1/p' ${dest_dir}/modules.blocklist > $used_blocklist_modules |
| fi |
| |
| # Trim modules from tree that aren't mentioned in modules.order |
| ( |
| cd ${dest_dir} |
| find * -type f -name "*.ko" | grep -v -w -f modules.order -f $used_blocklist_modules - | xargs -r rm |
| ) |
| rm $used_blocklist_modules |
| fi |
| |
| # Re-run depmod to detect any dependencies between in-kernel and external |
| # modules. Then, create modules.order based on all the modules compiled. |
| run_depmod ${dest_stage} "${depmod_flags}" "${version}" |
| cp ${dest_dir}/modules.order ${dest_dir}/modules.load |
| } |
| |
| function build_vendor_dlkm() { |
| echo "========================================================" |
| echo " Creating vendor_dlkm image" |
| |
| create_modules_staging "${VENDOR_DLKM_MODULES_LIST}" "${MODULES_STAGING_DIR}" \ |
| "${VENDOR_DLKM_STAGING_DIR}" "${VENDOR_DLKM_MODULES_BLOCKLIST}" |
| |
| local vendor_dlkm_modules_root_dir=$(echo ${VENDOR_DLKM_STAGING_DIR}/lib/modules/*) |
| local vendor_dlkm_modules_load=${vendor_dlkm_modules_root_dir}/modules.load |
| |
| # Modules loaded in vendor_boot should not be loaded in vendor_dlkm. |
| if [ -f ${DIST_DIR}/vendor_boot.modules.load ]; then |
| local stripped_modules_load="$(mktemp)" |
| ! grep -x -v -F -f ${DIST_DIR}/vendor_boot.modules.load \ |
| ${vendor_dlkm_modules_load} > ${stripped_modules_load} |
| mv -f ${stripped_modules_load} ${vendor_dlkm_modules_load} |
| fi |
| |
| cp ${vendor_dlkm_modules_load} ${DIST_DIR}/vendor_dlkm.modules.load |
| local vendor_dlkm_props_file |
| |
| if [ -z "${VENDOR_DLKM_PROPS}" ]; then |
| vendor_dlkm_props_file="$(mktemp)" |
| echo -e "vendor_dlkm_fs_type=ext4\n" >> ${vendor_dlkm_props_file} |
| echo -e "use_dynamic_partition_size=true\n" >> ${vendor_dlkm_props_file} |
| echo -e "ext_mkuserimg=mkuserimg_mke2fs\n" >> ${vendor_dlkm_props_file} |
| echo -e "ext4_share_dup_blocks=true\n" >> ${vendor_dlkm_props_file} |
| else |
| vendor_dlkm_props_file="${VENDOR_DLKM_PROPS}" |
| if [[ -f "${ROOT_DIR}/${vendor_dlkm_props_file}" ]]; then |
| vendor_dlkm_props_file="${ROOT_DIR}/${vendor_dlkm_props_file}" |
| elif [[ "${vendor_dlkm_props_file}" != /* ]]; then |
| echo "VENDOR_DLKM_PROPS must be an absolute path or relative to ${ROOT_DIR}: ${vendor_dlkm_props_file}" |
| exit 1 |
| elif [[ ! -f "${vendor_dlkm_props_file}" ]]; then |
| echo "Failed to find VENDOR_DLKM_PROPS: ${vendor_dlkm_props_file}" |
| exit 1 |
| fi |
| fi |
| build_image "${VENDOR_DLKM_STAGING_DIR}" "${vendor_dlkm_props_file}" \ |
| "${DIST_DIR}/vendor_dlkm.img" /dev/null |
| } |
| |
| export ROOT_DIR=$(readlink -f $(dirname $0)/..) |
| |
| # For module file Signing with the kernel (if needed) |
| FILE_SIGN_BIN=scripts/sign-file |
| SIGN_SEC=certs/signing_key.pem |
| SIGN_CERT=certs/signing_key.x509 |
| SIGN_ALGO=sha512 |
| |
| # Save environment parameters before being overwritten by sourcing |
| # BUILD_CONFIG. |
| CC_ARG="${CC}" |
| |
| source "${ROOT_DIR}/build/_setup_env.sh" |
| |
| MAKE_ARGS=( "$@" ) |
| export MAKEFLAGS="-j$(nproc) ${MAKEFLAGS}" |
| export MODULES_STAGING_DIR=$(readlink -m ${COMMON_OUT_DIR}/staging) |
| export MODULES_PRIVATE_DIR=$(readlink -m ${COMMON_OUT_DIR}/private) |
| export KERNEL_UAPI_HEADERS_DIR=$(readlink -m ${COMMON_OUT_DIR}/kernel_uapi_headers) |
| export INITRAMFS_STAGING_DIR=${MODULES_STAGING_DIR}/initramfs_staging |
| export VENDOR_DLKM_STAGING_DIR=${MODULES_STAGING_DIR}/vendor_dlkm_staging |
| export MKBOOTIMG_STAGING_DIR="${MODULES_STAGING_DIR}/mkbootimg_staging" |
| |
| if [ -n "${GKI_BUILD_CONFIG}" ]; then |
| GKI_OUT_DIR=${GKI_OUT_DIR:-${COMMON_OUT_DIR}/gki_kernel} |
| GKI_DIST_DIR=${GKI_DIST_DIR:-${GKI_OUT_DIR}/dist} |
| |
| if [[ "${MAKE_GOALS}" =~ image|Image|vmlinux ]]; then |
| echo " Compiling Image and vmlinux in device kernel is not supported in mixed build mode" |
| exit 1 |
| fi |
| |
| # Inherit SKIP_MRPROPER, LTO, SKIP_DEFCONFIG unless overridden by corresponding GKI_* variables |
| GKI_ENVIRON=("SKIP_MRPROPER=${SKIP_MRPROPER}" "LTO=${LTO}" "SKIP_DEFCONFIG=${SKIP_DEFCONFIG}" "SKIP_IF_VERSION_MATCHES=${SKIP_IF_VERSION_MATCHES}") |
| # Explicitly unset EXT_MODULES since they should be compiled against the device kernel |
| GKI_ENVIRON+=("EXT_MODULES=") |
| # Explicitly unset GKI_BUILD_CONFIG in case it was set by in the old environment |
| # e.g. GKI_BUILD_CONFIG=common/build.config.gki.x86 ./build/build.sh would cause |
| # gki build recursively |
| GKI_ENVIRON+=("GKI_BUILD_CONFIG=") |
| # Any variables prefixed with GKI_ get set without that prefix in the GKI build environment |
| # e.g. GKI_BUILD_CONFIG=common/build.config.gki.aarch64 -> BUILD_CONFIG=common/build.config.gki.aarch64 |
| GKI_ENVIRON+=($(export -p | sed -n -E -e 's/.* GKI_([^=]+=.*)$/\1/p' | tr '\n' ' ')) |
| GKI_ENVIRON+=("OUT_DIR=${GKI_OUT_DIR}") |
| GKI_ENVIRON+=("DIST_DIR=${GKI_DIST_DIR}") |
| ( env -i bash -c "source ${OLD_ENVIRONMENT}; rm -f ${OLD_ENVIRONMENT}; export ${GKI_ENVIRON[*]} ; ./build/build.sh" ) || exit 1 |
| |
| # Dist dir must have vmlinux.symvers, modules.builtin.modinfo, modules.builtin |
| MAKE_ARGS+=("KBUILD_MIXED_TREE=${GKI_DIST_DIR}") |
| else |
| rm -f ${OLD_ENVIRONMENT} |
| fi |
| |
| BOOT_IMAGE_HEADER_VERSION=${BOOT_IMAGE_HEADER_VERSION:-3} |
| |
| cd ${ROOT_DIR} |
| |
| export CLANG_TRIPLE CROSS_COMPILE CROSS_COMPILE_COMPAT CROSS_COMPILE_ARM32 ARCH SUBARCH MAKE_GOALS |
| |
| # Restore the previously saved CC argument that might have been overridden by |
| # the BUILD_CONFIG. |
| [ -n "${CC_ARG}" ] && CC="${CC_ARG}" |
| |
| # CC=gcc is effectively a fallback to the default gcc including any target |
| # triplets. An absolute path (e.g., CC=/usr/bin/gcc) must be specified to use a |
| # custom compiler. |
| [ "${CC}" == "gcc" ] && unset CC && unset CC_ARG |
| |
| TOOL_ARGS=() |
| |
| # LLVM=1 implies what is otherwise set below; it is a more concise way of |
| # specifying CC=clang LD=ld.lld NM=llvm-nm OBJCOPY=llvm-objcopy <etc>, for |
| # newer kernel versions. |
| if [[ -n "${LLVM}" ]]; then |
| TOOL_ARGS+=("LLVM=1") |
| # Reset a bunch of variables that the kernel's top level Makefile does, just |
| # in case someone tries to use these binaries in this script such as in |
| # initramfs generation below. |
| HOSTCC=clang |
| HOSTCXX=clang++ |
| CC=clang |
| LD=ld.lld |
| AR=llvm-ar |
| NM=llvm-nm |
| OBJCOPY=llvm-objcopy |
| OBJDUMP=llvm-objdump |
| READELF=llvm-readelf |
| OBJSIZE=llvm-size |
| STRIP=llvm-strip |
| else |
| if [ -n "${HOSTCC}" ]; then |
| TOOL_ARGS+=("HOSTCC=${HOSTCC}") |
| fi |
| |
| if [ -n "${CC}" ]; then |
| TOOL_ARGS+=("CC=${CC}") |
| if [ -z "${HOSTCC}" ]; then |
| TOOL_ARGS+=("HOSTCC=${CC}") |
| fi |
| fi |
| |
| if [ -n "${LD}" ]; then |
| TOOL_ARGS+=("LD=${LD}" "HOSTLD=${LD}") |
| fi |
| |
| if [ -n "${NM}" ]; then |
| TOOL_ARGS+=("NM=${NM}") |
| fi |
| |
| if [ -n "${OBJCOPY}" ]; then |
| TOOL_ARGS+=("OBJCOPY=${OBJCOPY}") |
| fi |
| fi |
| |
| if [ -n "${LLVM_IAS}" ]; then |
| TOOL_ARGS+=("LLVM_IAS=${LLVM_IAS}") |
| # Reset $AS for the same reason that we reset $CC etc above. |
| AS=clang |
| fi |
| |
| if [ -n "${DEPMOD}" ]; then |
| TOOL_ARGS+=("DEPMOD=${DEPMOD}") |
| fi |
| |
| if [ -n "${DTC}" ]; then |
| TOOL_ARGS+=("DTC=${DTC}") |
| fi |
| |
| # Allow hooks that refer to $CC_LD_ARG to keep working until they can be |
| # updated. |
| CC_LD_ARG="${TOOL_ARGS[@]}" |
| |
| DECOMPRESS_GZIP="gzip -c -d" |
| DECOMPRESS_LZ4="lz4 -c -d -l" |
| if [ -z "${LZ4_RAMDISK}" ] ; then |
| RAMDISK_COMPRESS="gzip -c -f" |
| RAMDISK_DECOMPRESS="${DECOMPRESS_GZIP}" |
| RAMDISK_EXT="gz" |
| else |
| RAMDISK_COMPRESS="lz4 -c -l -12 --favor-decSpeed" |
| RAMDISK_DECOMPRESS="${DECOMPRESS_LZ4}" |
| RAMDISK_EXT="lz4" |
| fi |
| |
| if [ -n "${SKIP_IF_VERSION_MATCHES}" ]; then |
| if [ -f "${DIST_DIR}/vmlinux" ]; then |
| kernelversion="$(cd ${KERNEL_DIR} && make -s "${TOOL_ARGS[@]}" O=${OUT_DIR} kernelrelease)" |
| # Split grep into 2 steps. "Linux version" will always be towards top and fast to find. Don't |
| # need to search the entire vmlinux for it |
| if [[ ! "$kernelversion" =~ .*dirty.* ]] && \ |
| grep -o -a -m1 "Linux version [^ ]* " ${DIST_DIR}/vmlinux | grep -q " ${kernelversion} " ; then |
| echo "========================================================" |
| echo " Skipping build because kernel version matches ${kernelversion}" |
| exit 0 |
| fi |
| fi |
| fi |
| |
| mkdir -p ${OUT_DIR} ${DIST_DIR} |
| |
| echo "========================================================" |
| echo " Setting up for build" |
| if [ "${SKIP_MRPROPER}" != "1" ] ; then |
| set -x |
| (cd ${KERNEL_DIR} && make "${TOOL_ARGS[@]}" O=${OUT_DIR} "${MAKE_ARGS[@]}" mrproper) |
| set +x |
| fi |
| |
| if [ -n "${PRE_DEFCONFIG_CMDS}" ]; then |
| echo "========================================================" |
| echo " Running pre-defconfig command(s):" |
| set -x |
| eval ${PRE_DEFCONFIG_CMDS} |
| set +x |
| fi |
| |
| if [ "${SKIP_DEFCONFIG}" != "1" ] ; then |
| set -x |
| (cd ${KERNEL_DIR} && make "${TOOL_ARGS[@]}" O=${OUT_DIR} "${MAKE_ARGS[@]}" ${DEFCONFIG}) |
| set +x |
| |
| if [ -n "${POST_DEFCONFIG_CMDS}" ]; then |
| echo "========================================================" |
| echo " Running pre-make command(s):" |
| set -x |
| eval ${POST_DEFCONFIG_CMDS} |
| set +x |
| fi |
| fi |
| |
| if [ "${LTO}" = "none" -o "${LTO}" = "thin" -o "${LTO}" = "full" ]; then |
| echo "========================================================" |
| echo " Modifying LTO mode to '${LTO}'" |
| |
| set -x |
| if [ "${LTO}" = "none" ]; then |
| ${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \ |
| -d LTO_CLANG \ |
| -e LTO_NONE \ |
| -d LTO_CLANG_THIN \ |
| -d LTO_CLANG_FULL \ |
| -d THINLTO |
| elif [ "${LTO}" = "thin" ]; then |
| # This is best-effort; some kernels don't support LTO_THIN mode |
| # THINLTO was the old name for LTO_THIN, and it was 'default y' |
| ${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \ |
| -e LTO_CLANG \ |
| -d LTO_NONE \ |
| -e LTO_CLANG_THIN \ |
| -d LTO_CLANG_FULL \ |
| -e THINLTO |
| elif [ "${LTO}" = "full" ]; then |
| # THINLTO was the old name for LTO_THIN, and it was 'default y' |
| ${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \ |
| -e LTO_CLANG \ |
| -d LTO_NONE \ |
| -d LTO_CLANG_THIN \ |
| -e LTO_CLANG_FULL \ |
| -d THINLTO |
| fi |
| (cd ${OUT_DIR} && make "${TOOL_ARGS[@]}" O=${OUT_DIR} "${MAKE_ARGS[@]}" olddefconfig) |
| set +x |
| elif [ -n "${LTO}" ]; then |
| echo "LTO= must be one of 'none', 'thin' or 'full'." |
| exit 1 |
| fi |
| |
| if [ -n "${TAGS_CONFIG}" ]; then |
| echo "========================================================" |
| echo " Running tags command:" |
| set -x |
| (cd ${KERNEL_DIR} && SRCARCH=${ARCH} ./scripts/tags.sh ${TAGS_CONFIG}) |
| set +x |
| exit 0 |
| fi |
| |
| # Truncate abi.prop file |
| ABI_PROP=${DIST_DIR}/abi.prop |
| : > ${ABI_PROP} |
| |
| if [ -n "${ABI_DEFINITION}" ]; then |
| |
| ABI_XML=${DIST_DIR}/abi.xml |
| |
| echo "KMI_DEFINITION=abi.xml" >> ${ABI_PROP} |
| echo "KMI_MONITORED=1" >> ${ABI_PROP} |
| |
| if [ "${KMI_ENFORCED}" = "1" ]; then |
| echo "KMI_ENFORCED=1" >> ${ABI_PROP} |
| fi |
| fi |
| |
| if [ -n "${KMI_SYMBOL_LIST}" ]; then |
| ABI_SL=${DIST_DIR}/abi_symbollist |
| echo "KMI_SYMBOL_LIST=abi_symbollist" >> ${ABI_PROP} |
| fi |
| |
| # define the kernel binary and modules archive in the $ABI_PROP |
| echo "KERNEL_BINARY=vmlinux" >> ${ABI_PROP} |
| if [ "${COMPRESS_UNSTRIPPED_MODULES}" = "1" ]; then |
| echo "MODULES_ARCHIVE=${UNSTRIPPED_MODULES_ARCHIVE}" >> ${ABI_PROP} |
| fi |
| |
| # Copy the abi_${arch}.xml file from the sources into the dist dir |
| if [ -n "${ABI_DEFINITION}" ]; then |
| echo "========================================================" |
| echo " Copying abi definition to ${ABI_XML}" |
| pushd $ROOT_DIR/$KERNEL_DIR |
| cp "${ABI_DEFINITION}" ${ABI_XML} |
| popd |
| fi |
| |
| # Copy the abi symbol list file from the sources into the dist dir |
| if [ -n "${KMI_SYMBOL_LIST}" ]; then |
| echo "========================================================" |
| echo " Generating abi symbol list definition to ${ABI_SL}" |
| pushd $ROOT_DIR/$KERNEL_DIR |
| cp "${KMI_SYMBOL_LIST}" ${ABI_SL} |
| |
| # If there are additional symbol lists specified, append them |
| if [ -n "${ADDITIONAL_KMI_SYMBOL_LISTS}" ]; then |
| for symbol_list in ${ADDITIONAL_KMI_SYMBOL_LISTS}; do |
| echo >> ${ABI_SL} |
| cat "${symbol_list}" >> ${ABI_SL} |
| done |
| fi |
| if [ "${TRIM_NONLISTED_KMI}" = "1" ]; then |
| # Create the raw symbol list |
| cat ${ABI_SL} | \ |
| ${ROOT_DIR}/build/abi/flatten_symbol_list > \ |
| ${OUT_DIR}/abi_symbollist.raw |
| |
| # Update the kernel configuration |
| ./scripts/config --file ${OUT_DIR}/.config \ |
| -d UNUSED_SYMBOLS -e TRIM_UNUSED_KSYMS \ |
| --set-str UNUSED_KSYMS_WHITELIST ${OUT_DIR}/abi_symbollist.raw |
| (cd ${OUT_DIR} && \ |
| make O=${OUT_DIR} "${TOOL_ARGS[@]}" "${MAKE_ARGS[@]}" olddefconfig) |
| # Make sure the config is applied |
| grep CONFIG_UNUSED_KSYMS_WHITELIST ${OUT_DIR}/.config > /dev/null || { |
| echo "ERROR: Failed to apply TRIM_NONLISTED_KMI kernel configuration" >&2 |
| echo "Does your kernel support CONFIG_UNUSED_KSYMS_WHITELIST?" >&2 |
| exit 1 |
| } |
| |
| elif [ "${KMI_SYMBOL_LIST_STRICT_MODE}" = "1" ]; then |
| echo "ERROR: KMI_SYMBOL_LIST_STRICT_MODE requires TRIM_NONLISTED_KMI=1" >&2 |
| exit 1 |
| fi |
| popd # $ROOT_DIR/$KERNEL_DIR |
| elif [ "${TRIM_NONLISTED_KMI}" = "1" ]; then |
| echo "ERROR: TRIM_NONLISTED_KMI requires a KMI_SYMBOL_LIST" >&2 |
| exit 1 |
| elif [ "${KMI_SYMBOL_LIST_STRICT_MODE}" = "1" ]; then |
| echo "ERROR: KMI_SYMBOL_LIST_STRICT_MODE requires a KMI_SYMBOL_LIST" >&2 |
| exit 1 |
| fi |
| |
| echo "========================================================" |
| echo " Building kernel" |
| |
| set -x |
| (cd ${OUT_DIR} && make O=${OUT_DIR} "${TOOL_ARGS[@]}" "${MAKE_ARGS[@]}" ${MAKE_GOALS}) |
| set +x |
| |
| if [ -n "${POST_KERNEL_BUILD_CMDS}" ]; then |
| echo "========================================================" |
| echo " Running post-kernel-build command(s):" |
| set -x |
| eval ${POST_KERNEL_BUILD_CMDS} |
| set +x |
| fi |
| |
| if [ -n "${MODULES_ORDER}" ]; then |
| echo "========================================================" |
| echo " Checking the list of modules:" |
| if ! diff -u "${KERNEL_DIR}/${MODULES_ORDER}" "${OUT_DIR}/modules.order"; then |
| echo "ERROR: modules list out of date" >&2 |
| echo "Update it with:" >&2 |
| echo "cp ${OUT_DIR}/modules.order ${KERNEL_DIR}/${MODULES_ORDER}" >&2 |
| exit 1 |
| fi |
| fi |
| |
| if [ "${KMI_SYMBOL_LIST_STRICT_MODE}" = "1" ]; then |
| echo "========================================================" |
| echo " Comparing the KMI and the symbol lists:" |
| set -x |
| ${ROOT_DIR}/build/abi/compare_to_symbol_list "${OUT_DIR}/Module.symvers" \ |
| "${OUT_DIR}/abi_symbollist.raw" |
| set +x |
| fi |
| |
| rm -rf ${MODULES_STAGING_DIR} |
| mkdir -p ${MODULES_STAGING_DIR} |
| |
| if [ "${DO_NOT_STRIP_MODULES}" != "1" ]; then |
| MODULE_STRIP_FLAG="INSTALL_MOD_STRIP=1" |
| fi |
| |
| if [ "${BUILD_INITRAMFS}" = "1" -o -n "${IN_KERNEL_MODULES}" ]; then |
| echo "========================================================" |
| echo " Installing kernel modules into staging directory" |
| |
| (cd ${OUT_DIR} && \ |
| make O=${OUT_DIR} "${TOOL_ARGS[@]}" ${MODULE_STRIP_FLAG} \ |
| INSTALL_MOD_PATH=${MODULES_STAGING_DIR} "${MAKE_ARGS[@]}" modules_install) |
| fi |
| |
| if [[ -z "${SKIP_EXT_MODULES}" ]] && [[ -n "${EXT_MODULES}" ]]; then |
| echo "========================================================" |
| echo " Building external modules and installing them into staging directory" |
| |
| for EXT_MOD in ${EXT_MODULES}; do |
| # The path that we pass in via the variable M needs to be a relative path |
| # relative to the kernel source directory. The source files will then be |
| # looked for in ${KERNEL_DIR}/${EXT_MOD_REL} and the object files (i.e. .o |
| # and .ko) files will be stored in ${OUT_DIR}/${EXT_MOD_REL}. If we |
| # instead set M to an absolute path, then object (i.e. .o and .ko) files |
| # are stored in the module source directory which is not what we want. |
| EXT_MOD_REL=$(rel_path ${ROOT_DIR}/${EXT_MOD} ${KERNEL_DIR}) |
| # The output directory must exist before we invoke make. Otherwise, the |
| # build system behaves horribly wrong. |
| mkdir -p ${OUT_DIR}/${EXT_MOD_REL} |
| set -x |
| make -C ${EXT_MOD} M=${EXT_MOD_REL} KERNEL_SRC=${ROOT_DIR}/${KERNEL_DIR} \ |
| O=${OUT_DIR} "${TOOL_ARGS[@]}" "${MAKE_ARGS[@]}" |
| make -C ${EXT_MOD} M=${EXT_MOD_REL} KERNEL_SRC=${ROOT_DIR}/${KERNEL_DIR} \ |
| O=${OUT_DIR} "${TOOL_ARGS[@]}" ${MODULE_STRIP_FLAG} \ |
| INSTALL_MOD_PATH=${MODULES_STAGING_DIR} \ |
| "${MAKE_ARGS[@]}" modules_install |
| set +x |
| done |
| |
| fi |
| |
| if [ -n "${EXTRA_CMDS}" ]; then |
| echo "========================================================" |
| echo " Running extra build command(s):" |
| set -x |
| eval ${EXTRA_CMDS} |
| set +x |
| fi |
| |
| OVERLAYS_OUT="" |
| for ODM_DIR in ${ODM_DIRS}; do |
| OVERLAY_DIR=${ROOT_DIR}/device/${ODM_DIR}/overlays |
| |
| if [ -d ${OVERLAY_DIR} ]; then |
| OVERLAY_OUT_DIR=${OUT_DIR}/overlays/${ODM_DIR} |
| mkdir -p ${OVERLAY_OUT_DIR} |
| make -C ${OVERLAY_DIR} DTC=${OUT_DIR}/scripts/dtc/dtc \ |
| OUT_DIR=${OVERLAY_OUT_DIR} "${MAKE_ARGS[@]}" |
| OVERLAYS=$(find ${OVERLAY_OUT_DIR} -name "*.dtbo") |
| OVERLAYS_OUT="$OVERLAYS_OUT $OVERLAYS" |
| fi |
| done |
| |
| echo "========================================================" |
| echo " Copying files" |
| for FILE in $(cd ${OUT_DIR} && ls -1 ${FILES}); do |
| if [ -f ${OUT_DIR}/${FILE} ]; then |
| echo " $FILE" |
| cp -p ${OUT_DIR}/${FILE} ${DIST_DIR}/ |
| else |
| echo " $FILE is not a file, skipping" |
| fi |
| done |
| |
| for FILE in ${OVERLAYS_OUT}; do |
| OVERLAY_DIST_DIR=${DIST_DIR}/$(dirname ${FILE#${OUT_DIR}/overlays/}) |
| echo " ${FILE#${OUT_DIR}/}" |
| mkdir -p ${OVERLAY_DIST_DIR} |
| cp ${FILE} ${OVERLAY_DIST_DIR}/ |
| done |
| |
| if [ -z "${SKIP_CP_KERNEL_HDR}" ]; then |
| echo "========================================================" |
| echo " Installing UAPI kernel headers:" |
| mkdir -p "${KERNEL_UAPI_HEADERS_DIR}/usr" |
| make -C ${OUT_DIR} O=${OUT_DIR} "${TOOL_ARGS[@]}" \ |
| INSTALL_HDR_PATH="${KERNEL_UAPI_HEADERS_DIR}/usr" "${MAKE_ARGS[@]}" \ |
| headers_install |
| # The kernel makefiles create files named ..install.cmd and .install which |
| # are only side products. We don't want those. Let's delete them. |
| find ${KERNEL_UAPI_HEADERS_DIR} \( -name ..install.cmd -o -name .install \) -exec rm '{}' + |
| KERNEL_UAPI_HEADERS_TAR=${DIST_DIR}/kernel-uapi-headers.tar.gz |
| echo " Copying kernel UAPI headers to ${KERNEL_UAPI_HEADERS_TAR}" |
| tar -czf ${KERNEL_UAPI_HEADERS_TAR} --directory=${KERNEL_UAPI_HEADERS_DIR} usr/ |
| fi |
| |
| if [ -z "${SKIP_CP_KERNEL_HDR}" ] ; then |
| echo "========================================================" |
| KERNEL_HEADERS_TAR=${DIST_DIR}/kernel-headers.tar.gz |
| echo " Copying kernel headers to ${KERNEL_HEADERS_TAR}" |
| pushd $ROOT_DIR/$KERNEL_DIR |
| find arch include $OUT_DIR -name *.h -print0 \ |
| | tar -czf $KERNEL_HEADERS_TAR \ |
| --absolute-names \ |
| --dereference \ |
| --transform "s,.*$OUT_DIR,," \ |
| --transform "s,^,kernel-headers/," \ |
| --null -T - |
| popd |
| fi |
| |
| if [ "${GENERATE_VMLINUX_BTF}" = "1" ]; then |
| echo "========================================================" |
| echo " Generating ${DIST_DIR}/vmlinux.btf" |
| |
| ( |
| cd ${DIST_DIR} |
| cp -a vmlinux vmlinux.btf |
| pahole -J vmlinux.btf |
| llvm-strip --strip-debug vmlinux.btf |
| ) |
| |
| fi |
| |
| if [ -n "${GKI_DIST_DIR}" ]; then |
| echo "========================================================" |
| echo " Copying files from GKI kernel" |
| cp -rv ${GKI_DIST_DIR}/* ${DIST_DIR}/ |
| fi |
| |
| if [ -n "${DIST_CMDS}" ]; then |
| echo "========================================================" |
| echo " Running extra dist command(s):" |
| # if DIST_CMDS requires UAPI headers, make sure a warning appears! |
| if [ ! -d "${KERNEL_UAPI_HEADERS_DIR}/usr" ]; then |
| echo "WARN: running without UAPI headers" |
| fi |
| set -x |
| eval ${DIST_CMDS} |
| set +x |
| fi |
| |
| MODULES=$(find ${MODULES_STAGING_DIR} -type f -name "*.ko") |
| if [ -n "${MODULES}" ]; then |
| if [ -n "${IN_KERNEL_MODULES}" -o -n "${EXT_MODULES}" ]; then |
| echo "========================================================" |
| echo " Copying modules files" |
| for FILE in ${MODULES}; do |
| echo " ${FILE#${MODULES_STAGING_DIR}/}" |
| cp -p ${FILE} ${DIST_DIR} |
| done |
| fi |
| if [ "${BUILD_INITRAMFS}" = "1" ]; then |
| echo "========================================================" |
| echo " Creating initramfs" |
| rm -rf ${INITRAMFS_STAGING_DIR} |
| create_modules_staging "${MODULES_LIST}" ${MODULES_STAGING_DIR} \ |
| ${INITRAMFS_STAGING_DIR} "${MODULES_BLOCKLIST}" "-e" |
| |
| MODULES_ROOT_DIR=$(echo ${INITRAMFS_STAGING_DIR}/lib/modules/*) |
| cp ${MODULES_ROOT_DIR}/modules.load ${DIST_DIR}/modules.load |
| cp ${MODULES_ROOT_DIR}/modules.load ${DIST_DIR}/vendor_boot.modules.load |
| echo "${MODULES_OPTIONS}" > ${MODULES_ROOT_DIR}/modules.options |
| |
| mkbootfs "${INITRAMFS_STAGING_DIR}" >"${MODULES_STAGING_DIR}/initramfs.cpio" |
| ${RAMDISK_COMPRESS} "${MODULES_STAGING_DIR}/initramfs.cpio" >"${DIST_DIR}/initramfs.img" |
| fi |
| fi |
| |
| if [ -n "${VENDOR_DLKM_MODULES_LIST}" ]; then |
| build_vendor_dlkm |
| fi |
| |
| if [ -n "${UNSTRIPPED_MODULES}" ]; then |
| echo "========================================================" |
| echo " Copying unstripped module files for debugging purposes (not loaded on device)" |
| mkdir -p ${UNSTRIPPED_DIR} |
| for MODULE in ${UNSTRIPPED_MODULES}; do |
| find ${MODULES_PRIVATE_DIR} -name ${MODULE} -exec cp {} ${UNSTRIPPED_DIR} \; |
| done |
| if [ "${COMPRESS_UNSTRIPPED_MODULES}" = "1" ]; then |
| tar -czf ${DIST_DIR}/${UNSTRIPPED_MODULES_ARCHIVE} -C $(dirname ${UNSTRIPPED_DIR}) $(basename ${UNSTRIPPED_DIR}) |
| rm -rf ${UNSTRIPPED_DIR} |
| fi |
| fi |
| |
| [ -n "${GKI_MODULES_LIST}" ] && cp ${KERNEL_DIR}/${GKI_MODULES_LIST} ${DIST_DIR}/ |
| |
| echo "========================================================" |
| echo " Files copied to ${DIST_DIR}" |
| |
| if [ ! -z "${BUILD_BOOT_IMG}" ] ; then |
| if [ -z "${MKBOOTIMG_PATH}" ]; then |
| MKBOOTIMG_PATH="tools/mkbootimg/mkbootimg.py" |
| fi |
| if [ ! -f "${MKBOOTIMG_PATH}" ]; then |
| echo "mkbootimg.py script not found. MKBOOTIMG_PATH = ${MKBOOTIMG_PATH}" |
| exit 1 |
| fi |
| |
| MKBOOTIMG_ARGS=("--header_version" "${BOOT_IMAGE_HEADER_VERSION}") |
| if [ -n "${BASE_ADDRESS}" ]; then |
| MKBOOTIMG_ARGS+=("--base" "${BASE_ADDRESS}") |
| fi |
| if [ -n "${PAGE_SIZE}" ]; then |
| MKBOOTIMG_ARGS+=("--pagesize" "${PAGE_SIZE}") |
| fi |
| if [ -n "${KERNEL_VENDOR_CMDLINE}" -a "${BOOT_IMAGE_HEADER_VERSION}" -lt "3" ]; then |
| KERNEL_CMDLINE+=" ${KERNEL_VENDOR_CMDLINE}" |
| fi |
| if [ -n "${KERNEL_CMDLINE}" ]; then |
| MKBOOTIMG_ARGS+=("--cmdline" "${KERNEL_CMDLINE}") |
| fi |
| if [ -n "${TAGS_OFFSET}" ]; then |
| MKBOOTIMG_ARGS+=("--tags_offset" "${TAGS_OFFSET}") |
| fi |
| if [ -n "${RAMDISK_OFFSET}" ]; then |
| MKBOOTIMG_ARGS+=("--ramdisk_offset" "${RAMDISK_OFFSET}") |
| fi |
| |
| DTB_FILE_LIST=$(find ${DIST_DIR} -name "*.dtb" | sort) |
| if [ -z "${DTB_FILE_LIST}" ]; then |
| if [ -z "${SKIP_VENDOR_BOOT}" ]; then |
| echo "No *.dtb files found in ${DIST_DIR}" |
| exit 1 |
| fi |
| else |
| cat $DTB_FILE_LIST > ${DIST_DIR}/dtb.img |
| MKBOOTIMG_ARGS+=("--dtb" "${DIST_DIR}/dtb.img") |
| fi |
| |
| rm -rf "${MKBOOTIMG_STAGING_DIR}" |
| MKBOOTIMG_RAMDISK_STAGING_DIR="${MKBOOTIMG_STAGING_DIR}/ramdisk_root" |
| mkdir -p "${MKBOOTIMG_RAMDISK_STAGING_DIR}" |
| |
| if [ -n "${VENDOR_RAMDISK_BINARY}" ]; then |
| VENDOR_RAMDISK_CPIO="${MKBOOTIMG_STAGING_DIR}/vendor_ramdisk_binary.cpio" |
| rm -f "${VENDOR_RAMDISK_CPIO}" |
| for vendor_ramdisk_binary in ${VENDOR_RAMDISK_BINARY}; do |
| if ! [ -f "${vendor_ramdisk_binary}" ]; then |
| echo "Unable to locate vendor ramdisk ${vendor_ramdisk_binary}." |
| exit 1 |
| fi |
| if ${DECOMPRESS_GZIP} "${vendor_ramdisk_binary}" 2>/dev/null >> "${VENDOR_RAMDISK_CPIO}"; then |
| echo "${vendor_ramdisk_binary} is GZIP compressed" |
| elif ${DECOMPRESS_LZ4} "${vendor_ramdisk_binary}" 2>/dev/null >> "${VENDOR_RAMDISK_CPIO}"; then |
| echo "${vendor_ramdisk_binary} is LZ4 compressed" |
| elif cpio -t < "${vendor_ramdisk_binary}" &>/dev/null; then |
| echo "${vendor_ramdisk_binary} is plain CPIO archive" |
| cat "${vendor_ramdisk_binary}" >> "${VENDOR_RAMDISK_CPIO}" |
| else |
| echo "Unable to identify type of vendor ramdisk ${vendor_ramdisk_binary}" |
| rm -f "${VENDOR_RAMDISK_CPIO}" |
| exit 1 |
| fi |
| done |
| |
| # Remove lib/modules from the vendor ramdisk binary |
| # Also execute ${VENDOR_RAMDISK_CMDS} for further modifications |
| ( cd "${MKBOOTIMG_RAMDISK_STAGING_DIR}" |
| cpio -idu --quiet <"${VENDOR_RAMDISK_CPIO}" |
| rm -rf lib/modules |
| eval ${VENDOR_RAMDISK_CMDS} |
| ) |
| fi |
| |
| if [ -f "${VENDOR_FSTAB}" ]; then |
| mkdir -p "${MKBOOTIMG_RAMDISK_STAGING_DIR}/first_stage_ramdisk" |
| cp "${VENDOR_FSTAB}" "${MKBOOTIMG_RAMDISK_STAGING_DIR}/first_stage_ramdisk/" |
| fi |
| |
| HAS_RAMDISK= |
| MKBOOTIMG_RAMDISK_DIRS=() |
| if [ -n "${VENDOR_RAMDISK_BINARY}" ] || [ -f "${VENDOR_FSTAB}" ]; then |
| HAS_RAMDISK="1" |
| MKBOOTIMG_RAMDISK_DIRS+=("${MKBOOTIMG_RAMDISK_STAGING_DIR}") |
| fi |
| |
| if [ "${BUILD_INITRAMFS}" = "1" ]; then |
| HAS_RAMDISK="1" |
| if [ -z "${INITRAMFS_VENDOR_RAMDISK_FRAGMENT_NAME}" ]; then |
| MKBOOTIMG_RAMDISK_DIRS+=("${INITRAMFS_STAGING_DIR}") |
| fi |
| fi |
| |
| if [ -z "${HAS_RAMDISK}" ] && [ -z "${SKIP_VENDOR_BOOT}" ]; then |
| echo "No ramdisk found. Please provide a GKI and/or a vendor ramdisk." |
| exit 1 |
| fi |
| |
| if [ "${#MKBOOTIMG_RAMDISK_DIRS[@]}" -gt 0 ]; then |
| MKBOOTIMG_RAMDISK_CPIO="${MKBOOTIMG_STAGING_DIR}/ramdisk.cpio" |
| mkbootfs "${MKBOOTIMG_RAMDISK_DIRS[@]}" >"${MKBOOTIMG_RAMDISK_CPIO}" |
| ${RAMDISK_COMPRESS} "${MKBOOTIMG_RAMDISK_CPIO}" >"${DIST_DIR}/ramdisk.${RAMDISK_EXT}" |
| fi |
| |
| if [ ! -f "${DIST_DIR}/$KERNEL_BINARY" ]; then |
| echo "kernel binary(KERNEL_BINARY = $KERNEL_BINARY) not present in ${DIST_DIR}" |
| exit 1 |
| fi |
| MKBOOTIMG_ARGS+=("--kernel" "${DIST_DIR}/${KERNEL_BINARY}") |
| |
| if [ "${BOOT_IMAGE_HEADER_VERSION}" -ge "4" ]; then |
| if [ -n "${VENDOR_BOOTCONFIG}" ]; then |
| for PARAM in ${VENDOR_BOOTCONFIG}; do |
| echo "${PARAM}" |
| done >"${DIST_DIR}/vendor-bootconfig.img" |
| MKBOOTIMG_ARGS+=("--vendor_bootconfig" "${DIST_DIR}/vendor-bootconfig.img") |
| KERNEL_VENDOR_CMDLINE+=" bootconfig" |
| fi |
| fi |
| |
| if [ "${BOOT_IMAGE_HEADER_VERSION}" -ge "3" ]; then |
| if [ -f "${GKI_RAMDISK_PREBUILT_BINARY}" ]; then |
| MKBOOTIMG_ARGS+=("--ramdisk" "${GKI_RAMDISK_PREBUILT_BINARY}") |
| fi |
| |
| if [ -z "${SKIP_VENDOR_BOOT}" ]; then |
| MKBOOTIMG_ARGS+=("--vendor_boot" "${DIST_DIR}/vendor_boot.img") |
| if [ -n "${KERNEL_VENDOR_CMDLINE}" ]; then |
| MKBOOTIMG_ARGS+=("--vendor_cmdline" "${KERNEL_VENDOR_CMDLINE}") |
| fi |
| if [ -f "${DIST_DIR}/ramdisk.${RAMDISK_EXT}" ]; then |
| MKBOOTIMG_ARGS+=("--vendor_ramdisk" "${DIST_DIR}/ramdisk.${RAMDISK_EXT}") |
| fi |
| if [ "${BUILD_INITRAMFS}" = "1" ] \ |
| && [ -n "${INITRAMFS_VENDOR_RAMDISK_FRAGMENT_NAME}" ]; then |
| MKBOOTIMG_ARGS+=("--ramdisk_type" "DLKM") |
| for MKBOOTIMG_ARG in ${INITRAMFS_VENDOR_RAMDISK_FRAGMENT_MKBOOTIMG_ARGS}; do |
| MKBOOTIMG_ARGS+=("${MKBOOTIMG_ARG}") |
| done |
| MKBOOTIMG_ARGS+=("--ramdisk_name" "${INITRAMFS_VENDOR_RAMDISK_FRAGMENT_NAME}") |
| MKBOOTIMG_ARGS+=("--vendor_ramdisk_fragment" "${DIST_DIR}/initramfs.img") |
| fi |
| fi |
| else |
| if [ -f "${DIST_DIR}/ramdisk.${RAMDISK_EXT}" ]; then |
| MKBOOTIMG_ARGS+=("--ramdisk" "${DIST_DIR}/ramdisk.${RAMDISK_EXT}") |
| fi |
| fi |
| |
| MKBOOTIMG_ARGS+=("--output" "${DIST_DIR}/boot.img") |
| for MKBOOTIMG_ARG in ${MKBOOTIMG_EXTRA_ARGS}; do |
| MKBOOTIMG_ARGS+=("${MKBOOTIMG_ARG}") |
| done |
| "${MKBOOTIMG_PATH}" "${MKBOOTIMG_ARGS[@]}" |
| |
| if [ -f "${DIST_DIR}/boot.img" ]; then |
| echo "boot image created at ${DIST_DIR}/boot.img" |
| |
| if [ -n "${AVB_SIGN_BOOT_IMG}" ]; then |
| if [ -n "${AVB_BOOT_PARTITION_SIZE}" ] \ |
| && [ -n "${AVB_BOOT_KEY}" ] \ |
| && [ -n "${AVB_BOOT_ALGORITHM}" ]; then |
| echo "Signing the boot.img..." |
| avbtool add_hash_footer --partition_name boot \ |
| --partition_size ${AVB_BOOT_PARTITION_SIZE} \ |
| --image ${DIST_DIR}/boot.img \ |
| --algorithm ${AVB_BOOT_ALGORITHM} \ |
| --key ${AVB_BOOT_KEY} |
| else |
| echo "Missing the AVB_* flags. Failed to sign the boot image" 1>&2 |
| exit 1 |
| fi |
| fi |
| fi |
| |
| [ -z "${SKIP_VENDOR_BOOT}" ] \ |
| && [ "${BOOT_IMAGE_HEADER_VERSION}" -ge "3" ] \ |
| && [ -f "${DIST_DIR}/vendor_boot.img" ] \ |
| && echo "vendor boot image created at ${DIST_DIR}/vendor_boot.img" |
| fi |
| |
| |
| # No trace_printk use on build server build |
| if readelf -a ${DIST_DIR}/vmlinux 2>&1 | grep -q trace_printk_fmt; then |
| echo "========================================================" |
| echo "WARN: Found trace_printk usage in vmlinux." |
| echo "" |
| echo "trace_printk will cause trace_printk_init_buffers executed in kernel" |
| echo "start, which will increase memory and lead warning shown during boot." |
| echo "We should not carry trace_printk in production kernel." |
| echo "" |
| if [ ! -z "${STOP_SHIP_TRACEPRINTK}" ]; then |
| echo "ERROR: stop ship on trace_printk usage." 1>&2 |
| exit 1 |
| fi |
| fi |