#!/bin/bash # # Copyright (C) 2013 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: generate_uapi_headers.sh [] ### ### This script is used to get a copy of the uapi kernel headers ### from an android kernel tree and copies them into an android source ### tree without any processing. The script also creates all of the ### generated headers and copies them into the android source tree. ### ### Options: ### --skip-generation ### Skip the step that generates all of the include files. ### --download-kernel ### Automatically create a temporary git repository and check out the ### linux kernel source code at TOT. ### --use-kernel-dir ### Do not check out the kernel source, use the kernel directory ### pointed to by . ### --verify-modified-headers-only ### Do not build anything, simply verify that the set of modified ### kernel headers have not changed. # Terminate the script if any command fails. set -eE TMPDIR="" ANDROID_DIR="" ANDROID_KERNEL_REPO="https://android.googlesource.com/kernel/common/" ANDROID_KERNEL_BRANCH="android-mainline" KERNEL_DIR="" KERNEL_DOWNLOAD=0 ARCH_LIST=("arm" "arm64" "riscv" "x86") ANDROID_KERNEL_DIR="external/kernel-headers/original" SKIP_GENERATION=0 VERIFY_HEADERS_ONLY=0 function cleanup () { if [[ "${TMPDIR}" =~ /tmp ]] && [[ -d "${TMPDIR}" ]]; then echo "Removing temporary directory ${TMPDIR}" rm -rf "${TMPDIR}" TMPDIR="" fi } function usage () { grep '^###' $0 | sed -e 's/^###//' } function copy_hdrs () { local src_dir=$1 local tgt_dir=$2 local dont_copy_dirs=$3 mkdir -p ${tgt_dir} local search_dirs=() # This only works if none of the filenames have spaces. for file in $(ls -d ${src_dir}/* 2> /dev/null); do if [[ -d "${file}" ]]; then search_dirs+=("${file}") elif [[ -f "${file}" ]] && [[ "${file}" =~ .h$ ]]; then cp ${file} ${tgt_dir} fi done if [[ "${dont_copy_dirs}" == "" ]]; then for dir in "${search_dirs[@]}"; do copy_hdrs "${dir}" ${tgt_dir}/$(basename ${dir}) done fi } function copy_if_exists () { local check_dir=$1 local src_dir=$2 local tgt_dir=$3 mkdir -p ${tgt_dir} # This only works if none of the filenames have spaces. for file in $(ls -d ${src_dir}/* 2> /dev/null); do if [[ -f "${file}" ]] && [[ "${file}" =~ .h$ ]]; then # Check that this file exists in check_dir. header=$(basename ${file}) if [[ -f "${check_dir}/${header}" ]]; then cp ${file} ${tgt_dir} fi fi done } function verify_modified_hdrs () { local src_dir=$1 local tgt_dir=$2 local kernel_dir=$3 local search_dirs=() # This only works if none of the filenames have spaces. for file in $(ls -d ${src_dir}/* 2> /dev/null); do if [[ -d "${file}" ]]; then search_dirs+=("${file}") elif [[ -f "${file}" ]] && [[ "${file}" =~ .h$ ]]; then tgt_file=${tgt_dir}/$(basename ${file}) if [[ -e ${tgt_file} ]] && ! diff "${file}" "${tgt_file}" > /dev/null; then if [[ ${file} =~ ${kernel_dir}/*(.+) ]]; then echo "New version of ${BASH_REMATCH[1]} found in kernel headers." else echo "New version of ${file} found in kernel headers." fi echo "This file needs to be updated manually." fi fi done for dir in "${search_dirs[@]}"; do verify_modified_hdrs "${dir}" ${tgt_dir}/$(basename ${dir}) "${kernel_dir}" done } trap cleanup EXIT # This automatically triggers a call to cleanup. trap "exit 1" HUP INT TERM TSTP while [ $# -gt 0 ]; do case "$1" in "--skip-generation") SKIP_GENERATION=1 ;; "--download-kernel") KERNEL_DOWNLOAD=1 ;; "--use-kernel-dir") if [[ $# -lt 2 ]]; then echo "--use-kernel-dir requires an argument." exit 1 fi shift KERNEL_DIR="$1" KERNEL_DOWNLOAD=0 ;; "--verify-modified-headers-only") if [[ $# -lt 2 ]]; then echo "--verify-modified-headers-only requires an argument." exit 1 fi shift KERNEL_DIR="$1" KERNEL_DOWNLOAD=0 VERIFY_HEADERS_ONLY=1 ;; "-h" | "--help") usage exit 1 ;; "-"*) echo "Error: Unrecognized option $1" usage exit 1 ;; *) echo "Error: Extra arguments on the command-line." usage exit 1 ;; esac shift done ANDROID_KERNEL_DIR="${ANDROID_BUILD_TOP}/${ANDROID_KERNEL_DIR}" if [[ "${ANDROID_BUILD_TOP}" == "" ]]; then echo "ANDROID_BUILD_TOP is not set, did you run lunch?" exit 1 elif [[ ! -d "${ANDROID_KERNEL_DIR}" ]]; then echo "${ANDROID_BUILD_TOP} doesn't appear to be the root of an android tree." echo " ${ANDROID_KERNEL_DIR} is not a directory." exit 1 fi if [[ ${KERNEL_DOWNLOAD} -eq 1 ]]; then TMPDIR=$(mktemp -d /tmp/android_kernelXXXXXXXX) cd "${TMPDIR}" echo "Fetching android linux kernel source..." git clone ${ANDROID_KERNEL_REPO} -b ${ANDROID_KERNEL_BRANCH} --depth=1 cd common KERNEL_DIR="${TMPDIR}/common" elif [[ "${KERNEL_DIR}" == "" ]]; then echo "Must specify one of --use-kernel-dir or --download-kernel." exit 1 elif [[ ! -d "${KERNEL_DIR}" ]] || [[ ! -d "${KERNEL_DIR}/kernel" ]]; then echo "The kernel directory $KERNEL_DIR or $KERNEL_DIR/kernel does not exist." exit 1 else cd "${KERNEL_DIR}" fi if [[ ${VERIFY_HEADERS_ONLY} -eq 1 ]]; then # Verify if modified headers have changed. verify_modified_hdrs "${KERNEL_DIR}/include/scsi" \ "${ANDROID_KERNEL_DIR}/scsi" \ "${KERNEL_DIR}" exit 0 fi if [[ ${SKIP_GENERATION} -eq 0 ]]; then # Build all of the generated headers. for arch in "${ARCH_LIST[@]}"; do echo "Generating headers for arch ${arch}" # Clean up any leftover headers. make ARCH=${arch} distclean make ARCH=${arch} headers_install done fi # Completely delete the old original headers so that any deleted/moved # headers are also removed. rm -rf "${ANDROID_KERNEL_DIR}/uapi" mkdir -p "${ANDROID_KERNEL_DIR}/uapi" cd ${ANDROID_BUILD_TOP} # Copy all of the include/uapi files to the kernel headers uapi directory. copy_hdrs "${KERNEL_DIR}/include/uapi" "${ANDROID_KERNEL_DIR}/uapi" # Copy the staging files to uapi/linux. copy_hdrs "${KERNEL_DIR}/drivers/staging/android/uapi" \ "${ANDROID_KERNEL_DIR}/uapi/linux" "no-copy-dirs" # Remove ion.h, it's not fully supported by the upstream kernel (see b/77976082). rm -f "${ANDROID_KERNEL_DIR}/uapi/linux/ion.h" # Copy the generated headers. copy_hdrs "${KERNEL_DIR}/include/generated/uapi" \ "${ANDROID_KERNEL_DIR}/uapi" for arch in "${ARCH_LIST[@]}"; do # Copy arch headers. copy_hdrs "${KERNEL_DIR}/arch/${arch}/include/uapi" \ "${ANDROID_KERNEL_DIR}/uapi/asm-${arch}" # Copy the generated arch headers. copy_hdrs "${KERNEL_DIR}/arch/${arch}/include/generated/uapi" \ "${ANDROID_KERNEL_DIR}/uapi/asm-${arch}" # Special copy of generated header files from arch//generated/asm that # also exist in uapi/asm-generic. copy_if_exists "${KERNEL_DIR}/include/uapi/asm-generic" \ "${KERNEL_DIR}/arch/${arch}/include/generated/asm" \ "${ANDROID_KERNEL_DIR}/uapi/asm-${arch}/asm" done # Verify if modified headers have changed. verify_modified_hdrs "${KERNEL_DIR}/include/scsi" \ "${ANDROID_KERNEL_DIR}/scsi" \ "${KERNEL_DIR}" echo "Headers updated." if [[ ${SKIP_GENERATION} -eq 0 ]]; then cd "${KERNEL_DIR}" # Clean all of the generated headers. for arch in "${ARCH_LIST[@]}"; do echo "Cleaning kernel files for arch ${arch}" make ARCH=${arch} distclean done fi