| #!/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 [<options>] | 
 | ### | 
 | ###  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 <DIR> | 
 | ###     Do not check out the kernel source, use the kernel directory | 
 | ###     pointed to by <DIR>. | 
 | ###   --verify-modified-headers-only <DIR> | 
 | ###     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" "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/<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 |