diff --git a/deploy_scripts/Dockerfiles/Dockerfile_amd b/deploy_scripts/Dockerfiles/Dockerfile_amd new file mode 100644 index 0000000000000000000000000000000000000000..039fd2d2a29eeb5f9ee44ed49404e2c68aaac74c --- /dev/null +++ b/deploy_scripts/Dockerfiles/Dockerfile_amd @@ -0,0 +1,21 @@ +# 本文件将基于kbox基础云手机镜像和kbox二进制制作适用于amd gpu 云手机镜像 +# 本文件前提是保证已有kbox基础云手机镜像(如kbox:latest) +# 在kbox基础云手机镜像的基础上将kbox二进制放入kbox基础云手机镜像中 +# 使用docker命令制作kbox云手机镜像,方便用户使用 + +# ARG是定义参数名称 +# FROM是指定kbox基础云手机镜像 +# MAINTAINER是作者名 +ARG KBOX_IMAGE +FROM ${KBOX_IMAGE} +MAINTAINER root + +COPY ./imageFile/system /imageFile/system + +# 注意: +# 因为每运行RUN一次就会创建一层镜像,容易产生非常臃肿、非常多层的镜像 +# 所以将视频流云手机相关的所有二进制整合在一起,保证只运行一次RUN +RUN chmod -R 755 imageFile \ + && chown -R root:root imageFile \ + && cp -pR imageFile/system/* /system/ \ + && rm -rf imageFile diff --git a/deploy_scripts/Dockerfiles/Dockerfile_awm b/deploy_scripts/Dockerfiles/Dockerfile_awm new file mode 100644 index 0000000000000000000000000000000000000000..ec8a925b5b7fef1c6fbedac87f6f5f7e4724be3d --- /dev/null +++ b/deploy_scripts/Dockerfiles/Dockerfile_awm @@ -0,0 +1,36 @@ +# 本文件将基于kbox基础云手机镜像和awmgpu相关的二进制制作awmgpu云手机镜像 +# 本文件前提是保证已有kbox基础云手机镜像(如kbox:latest) +# 在kbox基础云手机镜像的基础上将awmgpu相关的二进制放入kbox基础云手机镜像中 +# 使用docker命令制作视频流云手机镜像(如kbox:latest_awm),方便用户使用 + +# ARG是定义参数名称 +# FROM是指定kbox基础云手机镜像 +# MAINTAINER是作者名 +ARG KBOX_IMAGE +FROM ${KBOX_IMAGE} +MAINTAINER root + +COPY ./imageFile/system /imageFile/system + +# 注意: +# 因为每运行RUN一次就会创建一层镜像,容易产生非常臃肿、非常多层的镜像 +# 所以将视频流云手机相关的所有二进制整合在一起,保证只运行一次RUN +RUN chmod -R 755 imageFile \ + && chown -R root:root imageFile \ + && cp -pR imageFile/system/* /system/ \ + && rm -rf imageFile \ + && sed -i 's/^ro.hardware.gralloc=.*/ro.hardware.gralloc=awmgpu/g' /system/build.prop \ + && sed -i 's/^ro.hardware.hwcomposer=.*/ro.hardware.hwcomposer=awmgpu/g' /system/build.prop \ + && sed -i 's/^ro.hardware.egl=.*/ro.hardware.egl=powervr/g' /system/build.prop \ + && sed -i 's/^ro.hardware.vulkan=.*/ro.hardware.vulkan=powervr/g' /system/build.prop \ + && sed -i 's/^ro.product.platform=.*/ro.product.platform=powervr/g' /system/build.prop \ + && sed -i 's/^ro.vmi.hardware.gpu=.*/ro.vmi.hardware.gpu=2/g' /system/build.prop \ + && sed -i 's/^ro.vmi.hardware.vpu=.*/ro.vmi.hardware.vpu=0/g' /system/build.prop \ + && sed -i 's/^ro.hardware.gralloc=.*/ro.hardware.gralloc=awmgpu/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.hwcomposer=.*/ro.hardware.hwcomposer=awmgpu/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.egl=.*/ro.hardware.egl=powervr/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.vulkan=.*/ro.hardware.vulkan=powervr/g' /system/vendor/build.prop \ + && sed -i 's/^ro.product.platform=.*/ro.product.platform=powervr/g' /system/vendor/build.prop \ + && sed -i 's/^ro.vmi.hardware.gpu=.*/ro.vmi.hardware.gpu=2/g' /system/vendor/build.prop \ + && sed -i 's/^ro.vmi.hardware.vpu=.*/ro.vmi.hardware.vpu=0/g' /system/vendor/build.prop + diff --git a/deploy_scripts/Dockerfiles/Dockerfile_va b/deploy_scripts/Dockerfiles/Dockerfile_va new file mode 100644 index 0000000000000000000000000000000000000000..3792388a56c2a97802043cfd0dad3d59d3b00389 --- /dev/null +++ b/deploy_scripts/Dockerfiles/Dockerfile_va @@ -0,0 +1,45 @@ +# 本文件将基于kbox基础云手机镜像和va gpu相关的二进制制作va gpu云手机镜像 +# 本文件前提是保证已有kbox基础云手机镜像(如kbox:latest) +# 在kbox基础云手机镜像的基础上将va gpu相关的二进制放入kbox基础云手机镜像中 +# 使用docker命令制作kbox云手机镜像(如kbox:latest_va),方便用户使用 + +# ARG是定义参数名称 +# FROM是指定kbox基础云手机镜像 +# MAINTAINER是作者名 +ARG KBOX_IMAGE +FROM ${KBOX_IMAGE} +MAINTAINER root + +COPY ./imageFile/system /imageFile/system + +# 注意: +# 因为每运行RUN一次就会创建一层镜像,容易产生非常臃肿、非常多层的镜像 +# 所以将视频流云手机相关的所有二进制整合在一起,保证只运行一次RUN +RUN chmod -R 755 imageFile \ + && chown -R root:root imageFile \ + && cp -pR imageFile/system/* /system/ \ + && rm -rf imageFile \ + && sed -i 's/^ro.hardware.gralloc=.*/ro.hardware.gralloc=sgpu100/g' /system/build.prop \ + && sed -i 's/^ro.hardware.hwcomposer=.*/ro.hardware.hwcomposer=sgpu100/g' /system/build.prop \ + && sed -i 's/^ro.hardware.egl=.*/ro.hardware.egl=va/g' /system/build.prop \ + && sed -i 's/^ro.hardware.vulkan=.*/ro.hardware.vulkan=va/g' /system/build.prop \ + && sed -i 's/^ro.product.platform=.*/ro.product.platform=va/g' /system/build.prop \ + && sed -i 's/^ro.vmi.hardware.gpu=.*/ro.vmi.hardware.gpu=257/g' /system/build.prop \ + && sed -i 's/^ro.vmi.hardware.vpu=.*/ro.vmi.hardware.vpu=0/g' /system/build.prop \ + && sed -i 's/^ro.hardware.gralloc=.*/ro.hardware.gralloc=sgpu100/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.hwcomposer=.*/ro.hardware.hwcomposer=sgpu100/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.egl=.*/ro.hardware.egl=va/g' /system/vendor/build.prop \ + && sed -i 's/^ro.hardware.vulkan=.*/ro.hardware.vulkan=va/g' /system/vendor/build.prop \ + && sed -i 's/^ro.product.platform=.*/ro.product.platform=va/g' /system/vendor/build.prop \ + && sed -i 's/^ro.vmi.hardware.gpu=.*/ro.vmi.hardware.gpu=257/g' /system/vendor/build.prop \ + && sed -i 's/^ro.vmi.hardware.vpu=.*/ro.vmi.hardware.vpu=0/g' /system/vendor/build.prop \ + && sed -i '$aro.va.gpu.init=1' /system/vendor/build.prop \ + && sed -i '$adisplayServer.maxInterval=-1' /system/vendor/build.prop \ + && sed -i '/on init/a \ export VASTSTREAM_PIPELINE true' init.kbox.rc \ + && sed -i '/on init/a \ export VASTSTREAM_HOME \/vendor\/lib64\/vame\/' init.kbox.rc \ + && sed -i '/on init/a \ export VACM_LOG_CFG \/vendor\/etc\/' init.kbox.rc \ + && sed -i '/on init/a \ export LIBVASTVA_DRIVERS_PATH \/vendor\/lib64\/' init.kbox.rc \ + && sed -i '/on init/a \ export LIBVASTVA_DRIVER_NAME va' init.kbox.rc \ + && sed -i '/on init/a \ export VACC_RT_DDR_SHARE_MIN_SIZE 4' init.kbox.rc \ + && sed -i '/on init/a \ export VACC_RT_DDR_SHARE_POOL_MAX 0' init.kbox.rc \ + && sed -i '/mount debugfs/a \ exec - root -- /system/vendor/bin/gpu_config.sh' init.kbox.rc diff --git a/deploy_scripts/Dockerfiles/Dockerfile_va_aosp15 b/deploy_scripts/Dockerfiles/Dockerfile_va_aosp15 new file mode 100644 index 0000000000000000000000000000000000000000..f9fc664d2bf919d2b6f9aaa5cc7534838c0216e7 --- /dev/null +++ b/deploy_scripts/Dockerfiles/Dockerfile_va_aosp15 @@ -0,0 +1,51 @@ +# 本文件将基于kbox基础云手机镜像和va gpu相关的二进制制作va gpu云手机镜像 +# 本文件前提是保证已有kbox基础云手机镜像(如kbox:latest) +# 在kbox基础云手机镜像的基础上将va gpu相关的二进制放入kbox基础云手机镜像中 +# 使用docker命令制作kbox云手机镜像(如kbox:latest_va),方便用户使用 + +# ARG是定义参数名称 +# FROM是指定kbox基础云手机镜像 +# MAINTAINER是作者名 +ARG KBOX_IMAGE +FROM ${KBOX_IMAGE} +MAINTAINER root + +COPY ./imageFile/system /imageFile/system + +# 注意: +# 因为每运行RUN一次就会创建一层镜像,容易产生非常臃肿、非常多层的镜像 +# 所以将视频流云手机相关的所有二进制整合在一起,保证只运行一次RUN +RUN cp /system/lib64/liblzma.so /system/vendor/lib64/ \ + && cp /system/lib64/libutilscallstack.so /system/vendor/lib64/ \ + && cp /system/lib64/libunwindstack.so /system/vendor/lib64/ \ + && cp /system/lib/liblzma.so /system/vendor/lib/ \ + && cp /system/lib/libutilscallstack.so /system/vendor/lib/ \ + && cp /system/lib/libunwindstack.so /system/vendor/lib/ \ + && chmod -R 755 imageFile \ + && chown -R root:root imageFile \ + && cp -pR imageFile/system/* /system/ \ + && rm -rf imageFile \ + && sed -i '$aro.hardware.gralloc=sgpu100' /system/build.prop \ + && sed -i '$aro.hardware.hwcomposer=sgpu100' /system/build.prop \ + && sed -i '$aro.hardware.egl=va' /system/build.prop \ + && sed -i '$aro.hardware.vulkan=va' /system/build.prop \ + && sed -i '$aro.product.platform=va' /system/build.prop \ + && sed -i '$aro.vmi.hardware.gpu=257' /system/build.prop \ + && sed -i '$aro.vmi.hardware.vpu=0' /system/build.prop \ + && sed -i '$aro.hardware.gralloc=sgpu100' /system/vendor/build.prop \ + && sed -i '$aro.hardware.hwcomposer=sgpu100' /system/vendor/build.prop \ + && sed -i '$aro.hardware.egl=va' /system/vendor/build.prop \ + && sed -i '$aro.hardware.vulkan=va' /system/vendor/build.prop \ + && sed -i '$aro.product.platform=va' /system/vendor/build.prop \ + && sed -i '$aro.vmi.hardware.gpu=257' /system/vendor/build.prop \ + && sed -i '$aro.vmi.hardware.vpu=0' /system/vendor/build.prop \ + && sed -i '$aro.va.gpu.init=1' /system/vendor/build.prop \ + && sed -i '$adisplayServer.maxInterval=-1' /system/vendor/build.prop \ + && sed -i '/on init/a \ export VASTSTREAM_PIPELINE true' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export VASTSTREAM_HOME \/vendor\/lib64\/vame\/' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export VACM_LOG_CFG \/vendor\/etc\/' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export LIBVASTVA_DRIVERS_PATH \/vendor\/lib64\/' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export LIBVASTVA_DRIVER_NAME va' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export VACC_RT_DDR_SHARE_MIN_SIZE 4' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/on init/a \ export VACC_RT_DDR_SHARE_POOL_MAX 0' /system/vendor/etc/init/init.kbox.rc \ + && sed -i '/mount debugfs/a \ exec - root -- /system/vendor/bin/gpu_config.sh' /system/vendor/etc/init/init.kbox.rc diff --git a/deploy_scripts/android_kbox.sh b/deploy_scripts/android_kbox.sh new file mode 100644 index 0000000000000000000000000000000000000000..82bd8361c113b298e31ab0c0d7aecfd313ee0698 --- /dev/null +++ b/deploy_scripts/android_kbox.sh @@ -0,0 +1,547 @@ +#!/bin/bash +# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +#=============================================================================== +# Global Variable +#=============================================================================== +XD_GPU_ID="1fe0:1010" +VA_SGPU100_ID=":0200" + +#=============================================================================== +# Functions +#=============================================================================== +function check_environment() { + # root权限执行此脚本 + if [ "${UID}" -ne 0 ]; then + echo "请使用root权限执行" + exit 1 + fi + + # 支持非当前目录执行 + CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + echo "Current Path:$CURRENT_DIR" + cd ${CURRENT_DIR} + + # 检查是否存在配置文件,不存在配置文件,直接退出 + local KBOX_CFG=$CURRENT_DIR/kbox_config.cfg + if [ -f $KBOX_CFG ] + then + source $KBOX_CFG + echo "kbox_config.cfg exists, loaded" + else + echo "kbox_config.cfg not found" + exit 1 + fi + + check_devices +} + +function check_devices() { + # 确定kernel版本 + local KERNEL_VERSION=$(uname -r) + + # 检查ashmem device + if [ -z $(ls /dev | grep "ashmem") ]; then + echo "can not find ashmem device" + exit 1 + fi + + chmod 600 /dev/ashmem + chmod 600 /dev/dri/* + chmod 600 /dev/input + + if [ -n "$(lspci -n | grep ${XD_GPU_ID})" ]; then + chmod 666 /dev/ion* + chmod 666 /dev/pvr_sync + fi +} + +function check_paras() { + set +e + + if [ $# -eq 0 ]; then + echo "command must be \"start\", \"delete\" or \"restart\" " + exit 1 + fi + + if [ $1 == "start" ]; then + if [ $# -gt 4 ]; then + echo "the number of parameters exceeds 4!" + echo "Usage: " + echo "./android_kbox.sh start " + echo "./android_kbox.sh start " + exit 1; + fi + + local IMAGE_ID=$2 + if [[ "${IMAGE_ID}" =~ ":" ]]; then + local IMAGE_RE=$(echo ${IMAGE_ID} | cut -d ':' -f1) + tag=$(echo ${IMAGE_ID} | cut -d ':' -f2) + docker images | awk '{print $1" "$2}' | grep -w "${IMAGE_RE}" | grep -w "${tag}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "no image ${IMAGE_ID}" + exit 1 + fi + else + docker images | awk '{print $3}' | grep -w "${IMAGE_ID}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "no image ${IMAGE_ID}" + exit 1 + fi + fi + + if [ -n "`echo "$3$4" | sed 's/[0-9]//g'`" ]; then + echo "The third and fourth parameters must be numbers." + exit 1 + fi + + local MIN=$3 MAX=$4 + if [ -z "$4" ]; then + MAX=$3 + fi + + if [ $MIN -gt $MAX ]; then + echo "start_num must be less than or equal to end_num" + exit 1 + fi + elif [ $1 == "delete" ]; then + if [ $# -gt 3 ]; then + echo "the number of parameters exceeds 3!" + echo "Usage: " + echo "./android_kbox.sh delete " + echo "./android_kbox.sh delete " + exit 1 + fi + + if [ -n "`echo "$2$3" | sed 's/[0-9]//g'`" ]; then + echo "The second and third parameters must be numbers." + exit 1 + fi + + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + + if [ $MIN -gt $MAX ]; then + echo "start_num must be less than or equal to end_num" + exit 1 + fi + elif [ $1 == "restart" ]; then + if [ $# -gt 3 ]; then + echo "the number of parameters exceeds 3!" + echo "Usage: " + echo "./android_kbox.sh restart " + echo "./android_kbox.sh restart " + exit 1 + fi + + if [ -n "`echo "$2$3" | sed 's/[0-9]//g'`" ]; then + echo "The second and third paramelters must be numbers." + exit 1 + fi + + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + + if [ $MIN -gt $MAX ]; then + echo "start_num must be less than or equal to end_num" + exit 1 + fi + else + echo "command must be \"start\", \"delete\" or \"restart\" " + fi +} + +function get_closest_numas() { + local NUM_OF_NUMA=$(lscpu | grep "NUMA node(s)" | awk '{print $3}') + + local CPU_LIST_ARRAY= + for ((NUMA=0; NUMA<${NUM_OF_NUMA}; NUMA++)) + do + CPU_LIST_ARRAY[$NUMA]=$(cat /sys/devices/system/node/node${NUMA}/cpulist |sed "s/-/ /") + done + + local CPU_LIST= + for CPU in $@ + do + for ((NUMA=0; NUMA<${NUM_OF_NUMA}; NUMA++)) + do + # 将带空格的文本转换成array,其中第一个元素是最小值,第二个元素是最大值 + CPU_LIST=(${CPU_LIST_ARRAY[$NUMA]}) + if (( ${CPU} >= ${CPU_LIST[0]} )) && (( ${CPU} <= ${CPU_LIST[1]} )) + then + echo $NUMA + fi + done + done +} + +function wait_container_ready() { + local KBOX_NAME=$1 + docker exec -itd ${KBOX_NAME} /kbox-init.sh + local starttime=$(date +'%Y-%m-%d %H:%M:%S') + local start_seconds=$(date --date="${starttime}" +%s) + local res=0 + local has_restart=0 + if [ $? -eq 0 ]; then + count_time=0 + set +e + while true; do + local cmd="docker exec -i $1 getprop sys.boot_completed | grep 1 &" + local result=$(bash $CURRENT_DIR/base_box.sh wait_async_cmd "${cmd}") + if [ "${result}" == "1" ]; then + bash $CURRENT_DIR/base_box.sh chk_key_process ${CONTAINER_NAME} + [ ${?} -ne 0 ] && has_restart=1 && bash $CURRENT_DIR/base_box.sh restart "${CONTAINER_NAME}" "$MOUNT_DIR" 2 + [ ${?} -eq 1 ] && [ $has_restart -eq 1 ] && echo "${KBOX_NAME} started failed at $(date +'%Y-%m-%d %H:%M:%S')!" && res=1 && break + + echo "${KBOX_NAME} started successfully at $(date +'%Y-%m-%d %H:%M:%S')!" + break + elif [ "${result}" == "-1" ]; then + echo "${KBOX_NAME} wait_async_cmd timeout, exit and continue!" + fi + # 200秒未成功启动超时跳过 + if [ ${count_time} -gt 200 ]; then + echo -e "\033[1;31mStart check timed out,${KBOX_NAME} unable to start\033[0m" + echo -e "\033[1;31m${KBOX_NAME} started failed\033[0m" + break + fi + sleep 1 + count_time=$((count_time + 1)) + done + else + echo "${KBOX_NAME} started failed" + fi + local endtime=$(date +'%Y-%m-%d %H:%M:%S') + local end_seconds=$(date --date="${endtime}" +%s) + echo "time: "$((end_seconds - start_seconds))"s" + return $res +} + +function disable_ipv6_icmp() { + # 更改容器内部accept_redirects参数配置,禁止ipv6的icmp重定向功能 + KBOX_NAME=$1 + temp=$(mktemp) + echo 0 > $temp + pid=$(docker inspect ${KBOX_NAME} | grep Pid | awk -F, '{print $1}' | sed -n '1p' | awk '{print $2}') + nsenter -n -t ${pid} cp $temp /proc/sys/net/ipv6/conf/all/accept_redirects + rm $temp +} + +function check_encode_card() +{ + # 检查nvme指令 + cmd="nvme --help" + $cmd >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "nvme command unavailable, cannot auto detect vpu" + return 0 + fi + + cmd="nvme list" + output=$($cmd) + if echo "$output" | grep -q "QuadraT2A"; then + echo "set encode card to QuadraT2A" + HARD_DECODE_TYPE=1 + elif echo "$output" | grep -q "T432"; then + echo "set encode card to T432" + HARD_DECODE_TYPE=0 + else + echo "encode card unchange" + fi +} + +function enable_hard_decoder() { + local TAG_NUMBER=$1 + local container_name=kbox_$TAG_NUMBER + # Exited转态时需先重启容器才能拷贝文件 + local MOUNT_DIR=${KBOX_MOUNT_MAP[$TAG_NUMBER - 1]} + local status=$(docker ps -a| grep -w $container_name) + if [[ "$status" =~ "Exited" ]]; then + echo "kbox_$TAG_NUMBER is exited!" + if [ -z ${MOUNT_DIR} ]; then + MOUNT_DIR="/root/mount" + fi + mount ${MOUNT_DIR}/img/${container_name}.img ${MOUNT_DIR}/data/${container_name} >/dev/null + docker start ${container_name} + sleep 2 + fi + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + # VA GPU 硬解逻辑到base_box中处理,兼容视频流 + return; + fi + # 从硬解使能软解 + if [ $ENABLE_HARD_DECODE -ne 1 ];then + docker cp ${container_name}:/system/vendor/etc/media_codecs.xml . + sed -i 's/media_codecs_kbox_video.xml/media_codecs_google_video.xml/g' media_codecs.xml + docker cp ./media_codecs.xml ${container_name}:/system/vendor/etc/ + docker exec -itd ${container_name} chmod 644 /system/vendor/etc/media_codecs.xml + return + fi + # 使能硬解 + docker cp ${container_name}:/system/vendor/etc/media_codecs.xml . + sed -i 's/media_codecs_google_video.xml/media_codecs_kbox_video.xml/g' media_codecs.xml + docker cp ./media_codecs.xml ${container_name}:/system/vendor/etc/ + docker exec -itd ${container_name} chmod 644 /system/vendor/etc/media_codecs.xml + echo "enable hard decoder done" +} + +function enable_netint() { + # 不需要使能硬解设备 + if [ $ENABLE_HARD_DECODE -ne 1 ];then + return + fi + + # VA GPU 无此步骤,直接退出 + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + return; + fi + + container_name=$1 + check_encode_card + # T432初始化执行方式不变;Quadra采用ni_rsrc_mon自启动,生命周期由编码卡厂家管理,此处仅打印返回值 + if [ $HARD_DECODE_TYPE -eq 0 ];then + docker exec -itd ${container_name} /system/bin/ni_rsrc_mon_logan + sleep 3 + docker exec -itd ${container_name} chmod 666 /dev/nvm*n* + docker exec -itd ${container_name} chmod 777 -R /dev/shm_netint + [ ${?} != 0 ] && echo "Failed to enable netint device" && return + echo "enable netint device success" + elif [ $HARD_DECODE_TYPE -eq 1 ];then + local container_name=$1 + local ni_init_success=$(docker exec -itd ${container_name} getprop ni_rsrc_init_completed) + if [ "${ni_init_success}" == "yes" ]; then + echo "Failed to enable netint device" + else + echo "enable netint device success" + fi + else + return; + fi +} + +function netint_run_option() { + container_id=$1 + local opt="" + local encs_string=${KBOX_DEC_MAP[$container_id - 1]} + local encs="" + local encs_dev=() + IFS=',' read -r -a encs_dev <<< $encs_string + for i in ${encs_dev[*]}; do + encs+=" --device=${i}:${i}:rwm" + done + opt+=$encs + + echo "$opt" +} + +function start_box_by_id() { + + # 镜像名 + local IMAGE_NAME=$2 + + # 容器编号 + local TAG_NUMBER=$3 + + # 没有GPU不启动容器 + local GPUS_INFO=($(lspci -D | grep "VGA compatible controller: Advanced Micro Devices" | awk '{print $1}')) + # 芯动/VA GPU卡无法通过以上方式识别 + GPUS_INFO+=$(lspci -n | grep ${XD_GPU_ID} | awk '{print $3}') + GPUS_INFO+=$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}') + if [ ${#GPUS_INFO[@]} -eq 0 ]; then + echo "No GPU exists on the host" + exit 1 + fi + + # 容器名 + local CONTAINER_NAME="kbox_$TAG_NUMBER" + + # 存储大小 + local STORAGE_SIZE_GB=16 + + # 运行内存 + local RAM_SIZE_MB + if [ -n "$(lspci -D | grep "VGA compatible controller: Advanced Micro Devices" | grep "73a3")" ] || \ + [ -n "$(lspci -D | grep "VGA compatible controller: Advanced Micro Devices" | grep "Radeon PRO W6800")" ] || \ + [ -n "$(lspci -n | grep ${XD_GPU_ID})" ] || \ + [ -n "$(lspci -n | grep ${VA_SGPU100_ID})" ]; then + RAM_SIZE_MB=6144 + else + RAM_SIZE_MB=4096 + fi + + # CPUS + local CPUS + local CPUS_STRING=${KBOX_CPUSET_MAP[TAG_NUMBER - 1]} + IFS=' ' read -r -a CPUS <<< $CPUS_STRING + + # GPU + local GPUS_RENDER + if [ -n "$(lspci -n | grep ${XD_GPU_ID})" ]; then + # GPU, XD一个GPU对应四个render + local xd_gpus=($(lspci -D | grep "3D controller" | awk '{print $1}')) + if [ ${#xd_gpus[@]} -eq 2 ]; then + GPUS_RENDER=${KBOX_XD_GPU_MAP_8RENDERS[TAG_NUMBER - 1]} + elif [ ${#xd_gpus[@]} -eq 4 ]; then + GPUS_RENDER=${KBOX_XD_GPU_MAP_16RENDERS[TAG_NUMBER - 1]} + elif [ ${#xd_gpus[@]} -eq 6 ]; then + GPUS_RENDER=${KBOX_XD_GPU_MAP_24RENDERS[TAG_NUMBER - 1]} + else + GPUS_RENDER=${KBOX_XD_GPU_MAP_4RENDERS[TAG_NUMBER - 1]} + fi + elif [ -n "$(lspci -n | grep ${VA_SGPU100_ID})" ]; then + GPUS_RENDER=${KBOX_VA_GPU_MAP[TAG_NUMBER - 1]} + else + GPUS_RENDER=${KBOX_GPU_MAP[TAG_NUMBER - 1]} + fi + + # Data mount dir + local MOUNT_DIR=${KBOX_MOUNT_MAP[TAG_NUMBER - 1]} + + # NUMA + local NUMAS=($(echo $(get_closest_numas ${CPUS[@]}) | tr ' ' '\n' | sort -u | tr '\n' ' ')) + + # 调试端口 + local PORTS=("$((8500+$TAG_NUMBER)):5555") + + # docker额外启动参数 + local EXTRA_RUN_OPTION="" + # 使能硬解设备,若获取到的值为空,则不使能 + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + EXTRA_RUN_OPTION=" ENABLE_HARD_DECODE=${ENABLE_HARD_DECODE}" + elif [ -n "$(lspci -n | grep ${XD_GPU_ID})" ]; then + local idx=$((`echo ${GPUS_RENDER:16}` - 128)) + # docker额外启动参数 + EXTRA_RUN_OPTION+=" --device=/dev/pvr_sync:/dev/pvr_sync:rwm " + EXTRA_RUN_OPTION+=" --device=/dev/ion-$idx:/dev/ion:rwm " + EXTRA_RUN_OPTION+=" --device=${GPUS_RENDER}:/dev/renderD190:rwm" + else + # amdgpu 搭配编码卡使用 + EXTRA_RUN_OPTION=$(netint_run_option $TAG_NUMBER) + fi + + bash $CURRENT_DIR/base_box.sh start \ + --name "$CONTAINER_NAME" \ + --cpus "${CPUS[*]}" \ + --numas "${NUMAS[*]}" \ + --gpus "${GPUS_RENDER[*]}" \ + --storage_size_gb "$STORAGE_SIZE_GB" \ + --ram_size_mb "$RAM_SIZE_MB" \ + --ports "${PORTS[*]}" \ + --extra_run_option "$EXTRA_RUN_OPTION" \ + --image "$IMAGE_NAME" \ + --user_data_path "$MOUNT_DIR" \ + --container_data_path "/var/lib/docker" \ + --enable_render_layer "$ENABLE_RENDER_LAYER" + + enable_hard_decoder $TAG_NUMBER + + # 调整vinput设备权限 + cid=$(docker ps | grep -w ${CONTAINER_NAME} | awk '{print $1}') + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + + if [ -n "$(docker ps -a --format {{.Names}} | grep "$CONTAINER_NAME$")" ]; then + # 等待容器启动 + wait_container_ready ${CONTAINER_NAME} + [ ${?} -eq 1 ] && return + + set -e + enable_netint ${CONTAINER_NAME} + + # 更改容器内部accept_redirects参数配置,禁止ipv6的icmp重定向功能 + disable_ipv6_icmp ${CONTAINER_NAME} + echo -e "---------------------- done ----------------------\n" + fi + if [[ $ENABLE_RENDER_LAYER == "1" ]]; then + # 渲染中间层 + local isEnabled=0; + docker exec -it ${CONTAINER_NAME} sh -c "chmod 777 -R /vendor/shader_cache/" + docker exec -it ${CONTAINER_NAME} sh -c "mkdir -p /data/local/debug/gles" + docker exec -it ${CONTAINER_NAME} sh -c "chmod 755 -R /data/local/debug/" + docker exec -it ${CONTAINER_NAME} sh -c "cp /system/vendor/etc/kbox_render_accelerating_configuration.xml /data/local/tmp" > /dev/null 2>&1 || isEnabled=1 + docker exec -it ${CONTAINER_NAME} sh -c "cp /system/vendor/lib64/hw/RenderAccLayer.kbox.so /data/local/debug/gles" > /dev/null 2>&1 + if [ $? -eq 0 ]; then + docker exec -it ${CONTAINER_NAME} sh -c "setprop debug.gles.layers RenderAccLayer.kbox.so" + else + isEnabled=1 + fi + if [ $isEnabled -eq 1 ]; then + echo -e "\033[31mFailed to enabled render layer! kbox_render_accelerating_configuration.xml or RenderAccLayer.kbox.so may not exist\033[0m" + fi + fi +} + +function main() { + if [ ! -e "$CURRENT_DIR/base_box.sh" ]; then + echo "Can not find file base_box.sh" + exit 1 + fi + + if [ $1 = "start" ];then + local MIN=$3 MAX=$4 + if [ -z $4 ]; then + MAX=$3 + fi + + local TAG_NUMBER + for TAG_NUMBER in $(seq $MIN $MAX); do + if [ -n "$(docker ps -a --format {{.Names}} | grep "kbox_$TAG_NUMBER$")" ]; then + echo "kbox_$TAG_NUMBER exist!" + else + start_box_by_id $1 $2 $TAG_NUMBER + fi + done + elif [ $1 = "delete" ]; then + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + + local TAG_NUMBER + for TAG_NUMBER in $(seq $MIN $MAX);do + if [ -z "$(docker ps -a --format {{.Names}} | grep "kbox_$TAG_NUMBER$")" ]; then + echo "no container kbox_$TAG_NUMBER!" + else + local MOUNT_DIR=${KBOX_MOUNT_MAP[TAG_NUMBER - 1]} + bash $CURRENT_DIR/base_box.sh delete "kbox_$TAG_NUMBER" "$MOUNT_DIR" + fi + done + elif [ $1 = "restart" ]; then + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + local TAG_NUMBER + for TAG_NUMBER in $(seq $MIN $MAX);do + if [ -z "$(docker ps -a --format {{.Names}} | grep "kbox_$TAG_NUMBER$")" ]; then + echo "no container kbox_$TAG_NUMBER!" + else + set +e + enable_hard_decoder $TAG_NUMBER + local MOUNT_DIR=${KBOX_MOUNT_MAP[TAG_NUMBER - 1]} + bash $CURRENT_DIR/base_box.sh restart "kbox_$TAG_NUMBER" "$MOUNT_DIR" 3 ${ENABLE_HARD_DECODE} + [ ${?} -eq 1 ] && continue + + enable_netint "kbox_$TAG_NUMBER" + # 调整vinput设备权限 + cid=$(docker ps | grep -w "kbox_$TAG_NUMBER" | awk '{print $1}') + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + if [[ $ENABLE_RENDER_LAYER == "1" ]]; then + docker exec -it "kbox_$TAG_NUMBER" sh -c "cp /system/vendor/lib64/hw/RenderAccLayer.kbox.so /data/local/debug/gles" > /dev/null 2>&1 + if [ $? -eq 0 ]; then + docker exec -it "kbox_$TAG_NUMBER" sh -c "setprop debug.gles.layers RenderAccLayer.kbox.so" + else + echo -e "\033[31mFailed to enabled render layer! RenderAccLayer.kbox.so may not exist\033[0m" + fi + fi + set -e + fi + done + fi +} + +check_environment +check_paras $@ +main "$@" diff --git a/deploy_scripts/android_kbox_aosp15.sh b/deploy_scripts/android_kbox_aosp15.sh new file mode 100644 index 0000000000000000000000000000000000000000..19e3a149fd89037db72850ff20a489c1f1c95602 --- /dev/null +++ b/deploy_scripts/android_kbox_aosp15.sh @@ -0,0 +1,546 @@ +#!/bin/bash +# Copyright Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. + +#=============================================================================== +# Global Variable +#=============================================================================== +XD_GPU_ID="1fe0:1010" +VA_SGPU100_ID=":0200" + +#=============================================================================== +# Functions +#=============================================================================== +function check_environment() { + # root权限执行此脚本 + if [ "${UID}" -ne 0 ]; then + echo "请使用root权限执行" + exit 1 + fi + + # 支持非当前目录执行 + CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + echo "Current Path:$CURRENT_DIR" + cd ${CURRENT_DIR} + + # 检查是否存在配置文件,不存在配置文件,直接退出 + local KBOX_CFG=$CURRENT_DIR/kbox_config.cfg + if [ -f $KBOX_CFG ] + then + source $KBOX_CFG + echo "kbox_config.cfg exists, loaded" + else + echo "kbox_config.cfg not found" + exit 1 + fi + + check_devices +} + +function check_devices() { + # 确定kernel版本 + local KERNEL_VERSION=$(uname -r) + + # 检查ashmem device + if [ -z $(ls /dev | grep "ashmem") ]; then + echo "can not find ashmem device" + exit 1 + fi + + chmod 600 /dev/ashmem + chmod 600 /dev/dri/* + chmod 600 /dev/input + + if [ -n "$(lspci -n | grep ${XD_GPU_ID})" ]; then + chmod 666 /dev/ion* + chmod 666 /dev/pvr_sync + fi +} + +function check_paras() { + set +e + + if [ $# -eq 0 ]; then + echo "command must be \"start\", \"delete\" or \"restart\" " + exit 1 + fi + + if [ $1 == "start" ]; then + if [ $# -gt 4 ]; then + echo "the number of parameters exceeds 4!" + echo "Usage: " + echo "./android_kbox.sh start " + echo "./android_kbox.sh start " + exit 1; + fi + + local IMAGE_ID=$2 + if [[ "${IMAGE_ID}" =~ ":" ]]; then + local IMAGE_RE=$(echo ${IMAGE_ID} | cut -d ':' -f1) + tag=$(echo ${IMAGE_ID} | cut -d ':' -f2) + docker images | awk '{print $1" "$2}' | grep -w "${IMAGE_RE}" | grep -w "${tag}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "no image ${IMAGE_ID}" + exit 1 + fi + else + docker images | awk '{print $3}' | grep -w "${IMAGE_ID}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "no image ${IMAGE_ID}" + exit 1 + fi + fi + + if [ -n "`echo "$3$4" | sed 's/[0-9]//g'`" ]; then + echo "The third and fourth parameters must be numbers." + exit 1 + fi + + local MIN=$3 MAX=$4 + if [ -z "$4" ]; then + MAX=$3 + fi + + if [ $MIN -gt $MAX ]; then + echo "start_num must be less than or equal to end_num" + exit 1 + fi + elif [ $1 == "delete" ]; then + if [ $# -gt 3 ]; then + echo "the number of parameters exceeds 3!" + echo "Usage: " + echo "./android_kbox.sh delete " + echo "./android_kbox.sh delete " + exit 1 + fi + + if [ -n "`echo "$2$3" | sed 's/[0-9]//g'`" ]; then + echo "The second and third parameters must be numbers." + exit 1 + fi + + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + + if [ $MIN -gt $MAX ]; then + echo "start_num must be less than or equal to end_num" + exit 1 + fi + elif [ $1 == "restart" ]; then + if [ $# -gt 3 ]; then + echo "the number of parameters exceeds 3!" + echo "Usage: " + echo "./android_kbox.sh restart " + echo "./android_kbox.sh restart " + exit 1 + fi + + if [ -n "`echo "$2$3" | sed 's/[0-9]//g'`" ]; then + echo "The second and third paramelters must be numbers." + exit 1 + fi + + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + + if [ $MIN -gt $MAX ]; then + echo "start_num must be less than or equal to end_num" + exit 1 + fi + else + echo "command must be \"start\", \"delete\" or \"restart\" " + fi +} + +function get_closest_numas() { + local NUM_OF_NUMA=$(lscpu | grep "NUMA node(s)" | awk '{print $3}') + + local CPU_LIST_ARRAY= + for ((NUMA=0; NUMA<${NUM_OF_NUMA}; NUMA++)) + do + CPU_LIST_ARRAY[$NUMA]=$(cat /sys/devices/system/node/node${NUMA}/cpulist |sed "s/-/ /") + done + + local CPU_LIST= + for CPU in $@ + do + for ((NUMA=0; NUMA<${NUM_OF_NUMA}; NUMA++)) + do + # 将带空格的文本转换成array,其中第一个元素是最小值,第二个元素是最大值 + CPU_LIST=(${CPU_LIST_ARRAY[$NUMA]}) + if (( ${CPU} >= ${CPU_LIST[0]} )) && (( ${CPU} <= ${CPU_LIST[1]} )) + then + echo $NUMA + fi + done + done +} + +function wait_container_ready() { + local KBOX_NAME=$1 + local starttime=$(date +'%Y-%m-%d %H:%M:%S') + local start_seconds=$(date --date="${starttime}" +%s) + local res=0 + local has_restart=0 + if [ $? -eq 0 ]; then + count_time=0 + set +e + while true; do + local cmd="docker exec -i $1 getprop sys.boot_completed | grep 1 &" + local result=$(bash $CURRENT_DIR/base_box_aosp15.sh wait_async_cmd "${cmd}" 2> /dev/null) + if [ "${result}" == "1" ]; then + bash $CURRENT_DIR/base_box_aosp15.sh chk_key_process ${CONTAINER_NAME} + [ ${?} -ne 0 ] && has_restart=1 && bash $CURRENT_DIR/base_box_aosp15.sh restart "${CONTAINER_NAME}" "$MOUNT_DIR" 2 + [ ${?} -eq 1 ] && [ $has_restart -eq 1 ] && echo "${KBOX_NAME} started failed at $(date +'%Y-%m-%d %H:%M:%S')!" && res=1 && break + + echo "${KBOX_NAME} started successfully at $(date +'%Y-%m-%d %H:%M:%S')!" + break + elif [ "${result}" == "-1" ]; then + echo "${KBOX_NAME} wait_async_cmd timeout, exit and continue!" + fi + # 200秒未成功启动超时跳过 + if [ ${count_time} -gt 200 ]; then + echo -e "\033[1;31mStart check timed out,${KBOX_NAME} unable to start\033[0m" + echo -e "\033[1;31m${KBOX_NAME} started failed\033[0m" + break + fi + sleep 1 + count_time=$((count_time + 1)) + done + else + echo "${KBOX_NAME} started failed" + fi + local endtime=$(date +'%Y-%m-%d %H:%M:%S') + local end_seconds=$(date --date="${endtime}" +%s) + echo "time: "$((end_seconds - start_seconds))"s" + return $res +} + +function disable_ipv6_icmp() { + # 更改容器内部accept_redirects参数配置,禁止ipv6的icmp重定向功能 + KBOX_NAME=$1 + temp=$(mktemp) + echo 0 > $temp + pid=$(docker inspect ${KBOX_NAME} | grep Pid | awk -F, '{print $1}' | sed -n '1p' | awk '{print $2}') + nsenter -n -t ${pid} cp $temp /proc/sys/net/ipv6/conf/all/accept_redirects + rm $temp +} + +function check_encode_card() +{ + # 检查nvme指令 + cmd="nvme --help" + $cmd >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "nvme command unavailable, cannot auto detect vpu" + return 0 + fi + + cmd="nvme list" + output=$($cmd) + if echo "$output" | grep -q "QuadraT2A"; then + echo "set encode card to QuadraT2A" + HARD_DECODE_TYPE=1 + elif echo "$output" | grep -q "T432"; then + echo "set encode card to T432" + HARD_DECODE_TYPE=0 + else + echo "encode card unchange" + fi +} + +function enable_hard_decoder() { + local TAG_NUMBER=$1 + local container_name=kbox_$TAG_NUMBER + # Exited转态时需先重启容器才能拷贝文件 + local MOUNT_DIR=${KBOX_MOUNT_MAP[$TAG_NUMBER - 1]} + local status=$(docker ps -a| grep -w $container_name) + if [[ "$status" =~ "Exited" ]]; then + echo "kbox_$TAG_NUMBER is exited!" + if [ -z ${MOUNT_DIR} ]; then + MOUNT_DIR="/root/mount" + fi + mount ${MOUNT_DIR}/img/${container_name}.img ${MOUNT_DIR}/data/${container_name} >/dev/null + docker start ${container_name} + sleep 2 + fi + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + # VA GPU 硬解逻辑到base_box中处理,兼容视频流 + return; + fi + # 从硬解使能软解 + if [ $ENABLE_HARD_DECODE -ne 1 ];then + docker cp ${container_name}:/system/vendor/etc/media_codecs.xml . + sed -i 's/media_codecs_kbox_video.xml/media_codecs_google_video.xml/g' media_codecs.xml + docker cp ./media_codecs.xml ${container_name}:/system/vendor/etc/ + docker exec -itd ${container_name} chmod 644 /system/vendor/etc/media_codecs.xml + return + fi + # 使能硬解 + docker cp ${container_name}:/system/vendor/etc/media_codecs.xml . + sed -i 's/media_codecs_google_video.xml/media_codecs_kbox_video.xml/g' media_codecs.xml + docker cp ./media_codecs.xml ${container_name}:/system/vendor/etc/ + docker exec -itd ${container_name} chmod 644 /system/vendor/etc/media_codecs.xml + echo "enable hard decoder done" +} + +function enable_netint() { + # 不需要使能硬解设备 + if [ $ENABLE_HARD_DECODE -ne 1 ];then + return + fi + + # VA GPU 无此步骤,直接退出 + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + return; + fi + + container_name=$1 + check_encode_card + # T432初始化执行方式不变;Quadra采用ni_rsrc_mon自启动,生命周期由编码卡厂家管理,此处仅打印返回值 + if [ $HARD_DECODE_TYPE -eq 0 ];then + docker exec -itd ${container_name} /system/bin/ni_rsrc_mon_logan + sleep 3 + docker exec -itd ${container_name} chmod 666 /dev/nvm*n* + docker exec -itd ${container_name} chmod 777 -R /dev/shm_netint + [ ${?} != 0 ] && echo "Failed to enable netint device" && return + echo "enable netint device success" + elif [ $HARD_DECODE_TYPE -eq 1 ];then + local container_name=$1 + local ni_init_success=$(docker exec -itd ${container_name} getprop ni_rsrc_init_completed) + if [ "${ni_init_success}" == "yes" ]; then + echo "Failed to enable netint device" + else + echo "enable netint device success" + fi + else + return; + fi +} + +function netint_run_option() { + container_id=$1 + local opt="" + local encs_string=${KBOX_DEC_MAP[$container_id - 1]} + local encs="" + local encs_dev=() + IFS=',' read -r -a encs_dev <<< $encs_string + for i in ${encs_dev[*]}; do + encs+=" --device=${i}:${i}:rwm" + done + opt+=$encs + + echo "$opt" +} + +function start_box_by_id() { + + # 镜像名 + local IMAGE_NAME=$2 + + # 容器编号 + local TAG_NUMBER=$3 + + # 没有GPU不启动容器 + local GPUS_INFO=($(lspci -D | grep "VGA compatible controller: Advanced Micro Devices" | awk '{print $1}')) + # 芯动/VA GPU卡无法通过以上方式识别 + GPUS_INFO+=$(lspci -n | grep ${XD_GPU_ID} | awk '{print $3}') + GPUS_INFO+=$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}') + if [ ${#GPUS_INFO[@]} -eq 0 ]; then + echo "No GPU exists on the host" + exit 1 + fi + + # 容器名 + local CONTAINER_NAME="kbox_$TAG_NUMBER" + + # 存储大小 + local STORAGE_SIZE_GB=16 + + # 运行内存 + local RAM_SIZE_MB + if [ -n "$(lspci -D | grep "VGA compatible controller: Advanced Micro Devices" | grep "73a3")" ] || \ + [ -n "$(lspci -D | grep "VGA compatible controller: Advanced Micro Devices" | grep "Radeon PRO W6800")" ] || \ + [ -n "$(lspci -n | grep ${XD_GPU_ID})" ] || \ + [ -n "$(lspci -n | grep ${VA_SGPU100_ID})" ]; then + RAM_SIZE_MB=6144 + else + RAM_SIZE_MB=4096 + fi + + # CPUS + local CPUS + local CPUS_STRING=${KBOX_CPUSET_MAP[TAG_NUMBER - 1]} + IFS=' ' read -r -a CPUS <<< $CPUS_STRING + + # GPU + local GPUS_RENDER + if [ -n "$(lspci -n | grep ${XD_GPU_ID})" ]; then + # GPU, XD一个GPU对应四个render + local xd_gpus=($(lspci -D | grep "3D controller" | awk '{print $1}')) + if [ ${#xd_gpus[@]} -eq 2 ]; then + GPUS_RENDER=${KBOX_XD_GPU_MAP_8RENDERS[TAG_NUMBER - 1]} + elif [ ${#xd_gpus[@]} -eq 4 ]; then + GPUS_RENDER=${KBOX_XD_GPU_MAP_16RENDERS[TAG_NUMBER - 1]} + elif [ ${#xd_gpus[@]} -eq 6 ]; then + GPUS_RENDER=${KBOX_XD_GPU_MAP_24RENDERS[TAG_NUMBER - 1]} + else + GPUS_RENDER=${KBOX_XD_GPU_MAP_4RENDERS[TAG_NUMBER - 1]} + fi + elif [ -n "$(lspci -n | grep ${VA_SGPU100_ID})" ]; then + GPUS_RENDER=${KBOX_VA_GPU_MAP[TAG_NUMBER - 1]} + else + GPUS_RENDER=${KBOX_GPU_MAP[TAG_NUMBER - 1]} + fi + + # Data mount dir + local MOUNT_DIR=${KBOX_MOUNT_MAP[TAG_NUMBER - 1]} + + # NUMA + local NUMAS=($(echo $(get_closest_numas ${CPUS[@]}) | tr ' ' '\n' | sort -u | tr '\n' ' ')) + + # 调试端口 + local PORTS=("$((8500+$TAG_NUMBER)):5555") + + # docker额外启动参数 + local EXTRA_RUN_OPTION="" + # 使能硬解设备,若获取到的值为空,则不使能 + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + EXTRA_RUN_OPTION=" ENABLE_HARD_DECODE=${ENABLE_HARD_DECODE}" + elif [ -n "$(lspci -n | grep ${XD_GPU_ID})" ]; then + local idx=$((`echo ${GPUS_RENDER:16}` - 128)) + # docker额外启动参数 + EXTRA_RUN_OPTION+=" --device=/dev/pvr_sync:/dev/pvr_sync:rwm " + EXTRA_RUN_OPTION+=" --device=/dev/ion-$idx:/dev/ion:rwm " + EXTRA_RUN_OPTION+=" --device=${GPUS_RENDER}:/dev/renderD190:rwm" + else + # amdgpu 搭配编码卡使用 + EXTRA_RUN_OPTION=$(netint_run_option $TAG_NUMBER) + fi + + bash $CURRENT_DIR/base_box_aosp15.sh start \ + --name "$CONTAINER_NAME" \ + --cpus "${CPUS[*]}" \ + --numas "${NUMAS[*]}" \ + --gpus "${GPUS_RENDER[*]}" \ + --storage_size_gb "$STORAGE_SIZE_GB" \ + --ram_size_mb "$RAM_SIZE_MB" \ + --ports "${PORTS[*]}" \ + --extra_run_option "$EXTRA_RUN_OPTION" \ + --image "$IMAGE_NAME" \ + --user_data_path "$MOUNT_DIR" \ + --container_data_path "/var/lib/docker" \ + --enable_render_layer "$ENABLE_RENDER_LAYER" + + #enable_hard_decoder $TAG_NUMBER + + # 调整vinput设备权限 + cid=$(docker ps | grep -w ${CONTAINER_NAME} | awk '{print $1}') + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + + if [ -n "$(docker ps -a --format {{.Names}} | grep "$CONTAINER_NAME$")" ]; then + # 等待容器启动 + wait_container_ready ${CONTAINER_NAME} + [ ${?} -eq 1 ] && return + + set -e + enable_netint ${CONTAINER_NAME} + + # 更改容器内部accept_redirects参数配置,禁止ipv6的icmp重定向功能 + disable_ipv6_icmp ${CONTAINER_NAME} + echo -e "---------------------- done ----------------------\n" + fi + if [[ $ENABLE_RENDER_LAYER == "1" ]]; then + # 渲染中间层 + local isEnabled=0; + docker exec -it ${CONTAINER_NAME} sh -c "chmod 777 -R /vendor/shader_cache/" + docker exec -it ${CONTAINER_NAME} sh -c "mkdir -p /data/local/debug/gles" + docker exec -it ${CONTAINER_NAME} sh -c "chmod 755 -R /data/local/debug/" + docker exec -it ${CONTAINER_NAME} sh -c "cp /system/vendor/etc/kbox_render_accelerating_configuration.xml /data/local/tmp" > /dev/null 2>&1 || isEnabled=1 + docker exec -it ${CONTAINER_NAME} sh -c "cp /system/vendor/lib64/hw/RenderAccLayer.kbox.so /data/local/debug/gles" > /dev/null 2>&1 + if [ $? -eq 0 ]; then + docker exec -it ${CONTAINER_NAME} sh -c "setprop debug.gles.layers RenderAccLayer.kbox.so" + else + isEnabled=1 + fi + if [ $isEnabled -eq 1 ]; then + echo -e "\033[31mFailed to enabled render layer! kbox_render_accelerating_configuration.xml or RenderAccLayer.kbox.so may not exist\033[0m" + fi + fi +} + +function main() { + if [ ! -e "$CURRENT_DIR/base_box_aosp15.sh" ]; then + echo "Can not find file base_box_aosp15.sh" + exit 1 + fi + + if [ $1 = "start" ];then + local MIN=$3 MAX=$4 + if [ -z $4 ]; then + MAX=$3 + fi + + local TAG_NUMBER + for TAG_NUMBER in $(seq $MIN $MAX); do + if [ -n "$(docker ps -a --format {{.Names}} | grep "kbox_$TAG_NUMBER$")" ]; then + echo "kbox_$TAG_NUMBER exist!" + else + start_box_by_id $1 $2 $TAG_NUMBER + fi + done + elif [ $1 = "delete" ]; then + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + + local TAG_NUMBER + for TAG_NUMBER in $(seq $MIN $MAX);do + if [ -z "$(docker ps -a --format {{.Names}} | grep "kbox_$TAG_NUMBER$")" ]; then + echo "no container kbox_$TAG_NUMBER!" + else + local MOUNT_DIR=${KBOX_MOUNT_MAP[TAG_NUMBER - 1]} + bash $CURRENT_DIR/base_box_aosp15.sh delete "kbox_$TAG_NUMBER" "$MOUNT_DIR" + fi + done + elif [ $1 = "restart" ]; then + local MIN=$2 MAX=$3 + if [ -z $3 ]; then + MAX=$2 + fi + local TAG_NUMBER + for TAG_NUMBER in $(seq $MIN $MAX);do + if [ -z "$(docker ps -a --format {{.Names}} | grep "kbox_$TAG_NUMBER$")" ]; then + echo "no container kbox_$TAG_NUMBER!" + else + set +e + enable_hard_decoder $TAG_NUMBER + local MOUNT_DIR=${KBOX_MOUNT_MAP[TAG_NUMBER - 1]} + bash $CURRENT_DIR/base_box_aosp15.sh restart "kbox_$TAG_NUMBER" "$MOUNT_DIR" 3 ${ENABLE_HARD_DECODE} + [ ${?} -eq 1 ] && continue + + enable_netint "kbox_$TAG_NUMBER" + # 调整vinput设备权限 + cid=$(docker ps | grep -w "kbox_$TAG_NUMBER" | awk '{print $1}') + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + if [[ $ENABLE_RENDER_LAYER == "1" ]]; then + docker exec -it "kbox_$TAG_NUMBER" sh -c "cp /system/vendor/lib64/hw/RenderAccLayer.kbox.so /data/local/debug/gles" > /dev/null 2>&1 + if [ $? -eq 0 ]; then + docker exec -it "kbox_$TAG_NUMBER" sh -c "setprop debug.gles.layers RenderAccLayer.kbox.so" + else + echo -e "\033[31mFailed to enabled render layer! RenderAccLayer.kbox.so may not exist\033[0m" + fi + fi + set -e + fi + done + fi +} + +check_environment +check_paras $@ +main "$@" diff --git a/deploy_scripts/base_box.sh b/deploy_scripts/base_box.sh new file mode 100644 index 0000000000000000000000000000000000000000..5c3f8a3f7b7adfc128fe3f4855318dfdce1ac4b5 --- /dev/null +++ b/deploy_scripts/base_box.sh @@ -0,0 +1,896 @@ +#!/bin/bash +# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +THISDIR=$(readlink -ef $(dirname $0)) +CONTAINERD_CONFIG=$THISDIR/containerd_config +if [ -f "$CONTAINERD_CONFIG" ]; then + DEFAULT_RUNTIME=containerd + RUNTIME_CMD=nerdctl +else + DEFAULT_RUNTIME=docker + RUNTIME_CMD=docker +fi +#=============================================================================== +# Functions +#=============================================================================== +function check_environment() { + # root权限执行此脚本 + if [ "${UID}" -ne 0 ]; then + echo "请使用root权限执行" + exit 1 + fi + + # 支持非当前目录执行 + CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + cd ${CURRENT_DIR} + + # 如果是需要转码的机型,在使用脚本过程中检查转码 + local VENDOR_ID=$(lscpu | grep "Vendor ID:" | grep -v "BIOS" | awk '{print $3}') + if [ x"$VENDOR_ID" == x"0x48" ] || [ x"$VENDOR_ID" == x"HiSilicon" ]; then + check_exagear + fi +} + +function check_exagear() { + # 未注册 + if [ ! -e "/proc/sys/fs/binfmt_misc/ubt_a32a64" ]; then + if [ ! -d "/proc/sys/fs/binfmt_misc/" ]; then + mount -t binfmt_misc none /proc/sys/fs/binfmt_misc + fi + + # 在归档路径下模糊查找 + local UBT_PATHS=($(ls /root/dependency/*/ubt_a32a64)) + if [ ${#UBT_PATHS[@]} -lt 1 ]; then + echo "No ubt_a32a64 file!" + exit 1 + elif [ ${#UBT_PATHS[@]} -gt 1 ]; then + echo "Many ubt_a32a64 files exist! Please check:" + for PA in ${UBT_PATHS[@]}; do + echo "${PA}" + done + exit 1 + fi + + # 恢复exgear文件 + mkdir -p /opt/exagear + chmod -R 700 /opt/exagear + cp -rf ${UBT_PATHS[0]} /opt/exagear/ + cd /opt/exagear + chmod +x ubt_a32a64 + + # 注册转码 续行符后字符串顶格 + echo ":ubt_a32a64:M::\x7fELF\x01\x01\x01\x00\x00\x00\x0"\ +"0\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xf"\ +"f\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00"\ +"\x00\xfe\xff\xff\xff:/opt/exagear/ubt_a32a64:POCF" > /proc/sys/fs/binfmt_misc/register + fi + + # 检查ubt_a32a64版本 + local UBT_VER=($(/opt/exagear/ubt_a32a64 -V |grep -w binary | sed 's/^ExaGear binary translator version: \([^\s]*\)/\1/g' | sed 's/^v//g')) + if [ $UBT_VER \> "2.4.1" ]; then + if [ ! -e "/dev/tango32" ]; then + echo "No tango32!" + exit 1 + fi + fi +} + +function get_lxcfs_path() { + local value + if [ -d "/var/lib/lxc/lxcfs" ]; then + value="/var/lib/lxc/lxcfs" + elif [ -d "/var/lib/lxcfs" ]; then + value="/var/lib/lxcfs" + else + echo "error, fail to get lxcfs path" + exit 1 + fi + + echo ${value} +} + +#CPU文件模拟 +function mock_cpu() { + local CPU_PATH="/var/lib/kbox/cpus/${BOX_NAME}/cpu" + local CPU_NUM=8 + if [ -d "${CPU_PATH}" ];then + umount /var/lib/kbox/cpus/$BOX_NAME/cpu/cpu*/* > /dev/null 2>&1 + rm -rf /var/lib/kbox/cpus/$BOX_NAME + [ $? -ne 0 ] && echo "fail to remove data files /var/lib/kbox/cpus/$BOX_NAME !" && RET="fail" + fi + + mkdir -p ${CPU_PATH} + chmod 755 ${CPU_PATH} + + echo "7" >${CPU_PATH}"/kernel_max" + echo "0-7" >${CPU_PATH}"/possible" + echo "0-7" >${CPU_PATH}"/present" + echo "0-7" >${CPU_PATH}"/online" + + chmod 444 ${CPU_PATH}/kernel_max ${CPU_PATH}/possible ${CPU_PATH}/present ${CPU_PATH}/online + + # mock_cpufreq + mkdir -p ${CPU_PATH}/cpufreq/policy0 ${CPU_PATH}/cpufreq/cpuidle + chmod 755 ${CPU_PATH}/cpufreq ${CPU_PATH}/cpufreq/policy0 ${CPU_PATH}/cpufreq/cpuidle + + echo "$(seq 0 $(($CPU_NUM - 1))|tr 'n' ' ')" >${CPU_PATH}"/cpufreq/policy0/affected_cpus" + echo "1954000" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_max_freq" + echo "1954000" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_cur_freq" + echo "554000" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_min_freq" + echo "0" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_transition_latency" + cat ${CPU_PATH}"/cpufreq/policy0/affected_cpus" >${CPU_PATH}"/cpufreq/policy0/related_cpus" + echo "554000 860000 956000 1042000 1128000 1224000 1320000 1397000 1512000 1628000 1748000 1858000 1954000" >${CPU_PATH}"/cpufreq/policy0/scaling_available_frequencies" + echo "interacitve userspace powersave performance schedutil" >${CPU_PATH}"/cpufreq/policy0/scaling_available_governors" + cat ${CPU_PATH}"/cpufreq/policy0/cpuinfo_cur_freq" >${CPU_PATH}"/cpufreq/policy0/scaling_cur_freq" + echo "cpufreq-dt" >${CPU_PATH}"/cpufreq/policy0/scaling_driver" + echo "performance" >${CPU_PATH}"/cpufreq/policy0/scaling_governor" + cat ${CPU_PATH}"/cpufreq/policy0/cpuinfo_max_freq" >${CPU_PATH}"/cpufreq/policy0/scaling_max_freq" + cat ${CPU_PATH}"/cpufreq/policy0/cpuinfo_min_freq" >${CPU_PATH}"/cpufreq/policy0/scaling_min_freq" + echo "" >${CPU_PATH}"/cpufreq/policy0/scaling_setspeed" + + chmod 444 ${CPU_PATH}/cpufreq/policy0/* + chmod 400 ${CPU_PATH}/cpufreq/policy0/cpuinfo_cur_freq + chmod 644 ${CPU_PATH}/cpufreq/policy0/scaling_governor ${CPU_PATH}/cpufreq/policy0/scaling_setspeed + chmod 660 ${CPU_PATH}/cpufreq/policy0/scaling_max_freq ${CPU_PATH}/cpufreq/policy0/scaling_min_freq + + # mock_cpuidle + mkdir -p ${CPU_PATH}/cpufreq/cpuidle/driver ${CPU_PATH}/cpufreq/cpuidle/state0 ${CPU_PATH}/cpufreq/cpuidle/state1 + chmod 755 ${CPU_PATH}/cpufreq/cpuidle/* + + echo "hisi_cluster0_idle_driver" >${CPU_PATH}"/cpufreq/cpuidle/driver/name" + chmod 444 ${CPU_PATH}"/cpufreq/cpuidle/driver/name" + + echo "ARM64 WFI" >${CPU_PATH}"/cpufreq/cpuidle/state0/desc" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state0/disable" + echo "1" >${CPU_PATH}"/cpufreq/cpuidle/state0/latency" + echo "WFI" >${CPU_PATH}"/cpufreq/cpuidle/state0/name" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state0/power" + echo "1" >${CPU_PATH}"/cpufreq/cpuidle/state0/residency" + echo "$((RANDOM*4+11111))" >${CPU_PATH}"/cpufreq/cpuidle/state0/usage" + echo "$(($(cat ${CPU_PATH}/cpufreq/cpuidle/state0/usage)*666))" >${CPU_PATH}"/cpufreq/cpuidle/state0/time" + + chmod 444 ${CPU_PATH}/cpufreq/cpuidle/state0/* + chmod 644 ${CPU_PATH}/cpufreq/cpuidle/state0/disable + + echo "cpu-sleep-0" >${CPU_PATH}"/cpufreq/cpuidle/state1/desc" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state1/disable" + echo "110" >${CPU_PATH}"/cpufreq/cpuidle/state1/latency" + echo "cpu-sleep-0" >${CPU_PATH}"/cpufreq/cpuidle/state1/name" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state1/power" + echo "3000" >${CPU_PATH}"/cpufreq/cpuidle/state1/residency" + echo "$((RANDOM*+11111))" >${CPU_PATH}"/cpufreq/cpuidle/state1/usage" + echo "$(($(cat ${CPU_PATH}/cpufreq/cpuidle/state1/usage)*22222))" >${CPU_PATH}"/cpufreq/cpuidle/state0/time" + + + chmod 444 ${CPU_PATH}/cpufreq/cpuidle/state1/* + chmod 644 ${CPU_PATH}/cpufreq/cpuidle/state1/disable + + # mock_cpu* + for ((i=0; i<8; i++)); + do + mkdir -p ${CPU_PATH}/cpu$i + chmod 755 ${CPU_PATH}/cpu$i + #其他文件的挂载 + mkdir -p ${CPU_PATH}/cpu$i/hotplug ${CPU_PATH}/cpu$i/power ${CPU_PATH}/cpu$i/regs ${CPU_PATH}/cpu$i/topology + cp /sys/devices/system/cpu/cpu$i/cpu_capacity ${CPU_PATH}/cpu$i/cpu_capacity + mount --bind /sys/devices/system/cpu/cpu$i/hotplug ${CPU_PATH}/cpu$i/hotplug + echo "1" >${CPU_PATH}/cpu$i/online + mount --bind /sys/devices/system/cpu/cpu$i/power ${CPU_PATH}/cpu$i/power + mount --bind /sys/devices/system/cpu/cpu$i/regs ${CPU_PATH}/cpu$i/regs + mount --bind /sys/devices/system/cpu/cpu$i/topology ${CPU_PATH}/cpu$i/topology + mkdir -p ${CPU_PATH}/cpu$i/cpufreq ${CPU_PATH}/cpu$i/cpuidle + mount --bind ${CPU_PATH}/cpufreq/policy0 ${CPU_PATH}/cpu$i/cpufreq + mount --bind ${CPU_PATH}/cpufreq/cpuidle ${CPU_PATH}/cpu$i/cpuidle + done + + RUN_OPTION+="--volume=/var/lib/kbox/cpus/${BOX_NAME}/cpu:/sys/devices/system/cpu:ro" +} + +# 供电模拟:USB供电,未充电状态 +function mock_power_supply() { + local POWER_SUPPLY_PATH="/var/lib/kbox/powers/${BOX_NAME}/power_supply" + + mkdir -p $POWER_SUPPLY_PATH"/Battery" + mkdir -p $POWER_SUPPLY_PATH"/Mains" + mkdir -p $POWER_SUPPLY_PATH"/USB" + mkdir -p $POWER_SUPPLY_PATH"/Wireless" + + echo "100" >$POWER_SUPPLY_PATH"/Battery/capacity" + echo "3945000" >$POWER_SUPPLY_PATH"/Battery/charge_counter" + echo "0" >$POWER_SUPPLY_PATH"/Battery/current_now" + + echo "Good" >$POWER_SUPPLY_PATH"/Battery/health" + echo "1" >$POWER_SUPPLY_PATH"/Battery/online" + + echo "1" >$POWER_SUPPLY_PATH"/Battery/present" + echo "Not charging" >$POWER_SUPPLY_PATH"/Battery/status" + echo "Li-poly" >$POWER_SUPPLY_PATH"/Battery/technology" + echo "260" >$POWER_SUPPLY_PATH"/Battery/temp" + echo "Battery" >$POWER_SUPPLY_PATH"/Battery/type" + echo "4400" > $POWER_SUPPLY_PATH"/Battery/voltage_max" + echo "4356000" >$POWER_SUPPLY_PATH"/Battery/voltage_now" + + echo "500000" >$POWER_SUPPLY_PATH"/USB/current_max" + echo "Good" >$POWER_SUPPLY_PATH"/USB/health" + echo "1" >$POWER_SUPPLY_PATH"/USB/online" + echo "USB" >$POWER_SUPPLY_PATH"/USB/type" + echo "4950000" > $POWER_SUPPLY_PATH"/USB/voltage_max" + + echo "Good" >$POWER_SUPPLY_PATH"/Mains/health" + echo "0" >$POWER_SUPPLY_PATH"/Mains/online" + echo "Mains" >$POWER_SUPPLY_PATH"/Mains/type" + + echo "Good" >$POWER_SUPPLY_PATH"/Wireless/health" + echo "0" >$POWER_SUPPLY_PATH"/Wireless/online" + echo "Wireless" >$POWER_SUPPLY_PATH"/Wireless/type" + + RUN_OPTION+=" --volume=$POWER_SUPPLY_PATH:/sys/class/power_supply:rw " +} + +function check_paras() { + echo "------------------ Kbox Startup ------------------" + + local BOX_NAME CPUS NUMAS GPUS_RENDER STORAGE_SIZE_GB RAM_SIZE_MB PORTS + local EXTRA_RUN_OPTION IMAGE_NAME USER_DATA_PATH CONTAINER_DATA_PATH + local ENABLE_RENDER_LAYER + local PARA_ERROR="" + while :; do + case $1 in + start) shift;; + --name) BOX_NAME=$2; echo "--name) BOX_NAME : $2 "; shift;; + --cpus) CPUS=($2); echo "--cpus) CPUS : $2 "; shift;; + --numas) NUMAS=($2); echo "--numas) NUMAS : $2 "; shift;; + --gpus) GPUS_RENDER=($2); echo "--gpus) GPUS_RENDER : $2 "; shift;; + --storage_size_gb) STORAGE_SIZE_GB=$2; echo "--storage_size_gb) STORAGE_SIZE_GB : $2 "; shift;; + --ram_size_mb) RAM_SIZE_MB=$2; echo "--ram_size_mb) RAM_SIZE_MB : $2 "; shift;; + --ports) PORTS=($2); echo "--ports) PORTS : $2 "; shift;; + --extra_run_option) EXTRA_RUN_OPTION=$2; echo "--extra_run_option) EXTRA_RUN_OPTION : $2 "; shift;; + --image) IMAGE_NAME=$2; echo "--image) IMAGE_NAME : $2 "; shift;; + --user_data_path) USER_DATA_PATH=$2; echo "--user_data_path) USER_DATA_PATH : $2 "; shift;; + --container_data_path) CONTAINER_DATA_PATH=$2; echo "--container_data_path) CONTAINER_DATA_PATH : $2 "; shift;; + --enable_render_layer) ENABLE_RENDER_LAYER=$2; echo "--enable_render_layer) ENABLE_RENDER_LAYER : $2 "; shift;; + --) shift; break;; + -?*) printf 'WARN: Unknown option: %s\n' "$1" >&2; exit 1;; + *) break + esac + + shift + done + + if [ -z $BOX_NAME ]; then + echo "\"--name\" option error, fail: need a kbox name!" + PARA_ERROR="true" + fi + + if [ ${#CPUS[@]} -eq 0 ]; then + echo "\"--cpus\" option error, fail: para empty!" + PARA_ERROR="true" + fi + local CPU + for CPU in ${CPUS[@]}; do + if [ -n "`echo "$CPU" | sed 's/[0-9]//g'`" ]; then + echo "\"--cpus\" option error, fail: cpu parameter must be number!" + PARA_ERROR="true" + fi + if [ $CPU -ge $(lscpu | grep -w "CPU(s)" | head -n 1 | awk '{print $2}') ] || \ + [ $CPU -lt 0 ]; then + echo "\"--cpus\" option error, fail: cpu$CPUS not exist!" + fi + done + + if [ ${#NUMAS[@]} -eq 0 ]; then + echo "\"--numas\" option error, fail: para empty!" + PARA_ERROR="true" + fi + local NUMA + for NUMA in ${NUMAS[@]}; do + if [ -n "`echo "$NUMA" | sed 's/[0-9]//g'`" ]; then + echo "\"--numas\" option error, fail: numa parameter must be number!" + PARA_ERROR="true" + fi + + if [ $NUMA -ge $(lscpu | grep "NUMA node(s)" | awk '{print $3}') ] || \ + [ $NUMA -lt 0 ]; then + echo " \"--numas\" fail: numa$NUMA not exist!" + PARA_ERROR="true" + fi + done + + local GPU + for GPU in ${GPUS_RENDER[@]}; do + if [ ! -e $GPU ]; then + echo "\"--gpus\" error, fail: GPU device $GPU not exist!" + PARA_ERROR="true" + fi + done + + if [ -z "`echo "$STORAGE_SIZE_GB" | sed 's/[0-9]//g'`" ]; then + if [ -z $STORAGE_SIZE_GB ]; then + echo "\"--storage_size_gb\" option error, fail: para empty!" + PARA_ERROR="true" + elif [ $STORAGE_SIZE_GB -le 0 ]; then + echo "\"--storage_size_gb\" option error, fail: storage size must greater than 0 GB!" + PARA_ERROR="true" + fi + else + echo "\"--storage_size_gb\" option error, fail: storage size must be number!" + PARA_ERROR="true" + fi + + if [ -z "`echo "$RAM_SIZE_MB" | sed 's/[0-9]//g'`" ]; then + if [ -z $RAM_SIZE_MB ]; then + echo "\"--ram_size_mb\" option error, fail: para empty!" + PARA_ERROR="true" + elif [ $RAM_SIZE_MB -le 0 ];then + echo "\"--ram_size_mb\" option error, fail: ram size must greater than 0 MB!" + PARA_ERROR="true" + fi + else + echo "\"--ram_size_mb\" option error, fail: ram size must be number!" + PARA_ERROR="true" + fi + + if [ ${#PORTS[@]} -eq 0 ]; then + echo "\"--ports\" option error, fail: para empty!" + PARA_ERROR="true" + fi + local PORT + for PORT in ${PORTS[@]}; do + if [[ "${PORT}" =~ ":" ]]; then + local AGENT_PORT=$(echo ${PORT} | cut -d ':' -f1) + local HOST_PORT=$(echo ${PORT} | cut -d ':' -f2) + if [ -n "`echo "$AGENT_PORT" | sed 's/[0-9]//g'`" ]; then + echo "\"--ports\" option error, fail: agent port must be number!" + PARA_ERROR="true" + fi + + if [ -n "`echo "$HOST_PORT" | sed 's/[0-9]//g'`" ]; then + echo "\"--ports\" option error, fail: host port must be number!" + PARA_ERROR="true" + fi + else + echo "\"--ports\" option error, fail: error port format!" + PARA_ERROR="true" + fi + done + + if [[ "${IMAGE_NAME}" =~ ":" ]]; then + local IMAGE_RE=$(echo ${IMAGE_NAME} | cut -d ':' -f1) + tag=$(echo ${IMAGE_NAME} | cut -d ':' -f2) + $RUNTIME_CMD images | awk '{print $1" "$2}' | grep -w "${IMAGE_RE}" | grep -w "${tag}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "\"--image\" option error, no image ${IMAGE_NAME}!" + PARA_ERROR="true" + fi + else + $RUNTIME_CMD images | awk '{print $3}' | grep -w "${IMAGE_NAME}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "\"--image\" option error, fail: no image ${IMAGE_NAME}!" + PARA_ERROR="true" + fi + fi + + echo "---------------------------------------------------" + if [ "$PARA_ERROR" = "true" ]; then + echo "error: Kbox Start Fail!" + exit 1 + fi +} + +function check_key_process() { + # 检查关键进程是否存在 + local process_name=(system_server zygote zygote64 surfaceflinger) + local cmd="$RUNTIME_CMD exec -i $1 ps -A | egrep -w 'system_server|zygote|zygote64|surfaceflinger' &" + local result=$(wait_cmd "${cmd}") + check_wait_cmd_result "${cmd}" "${result}" + local val + for process in ${process_name[@]}; do + val=$(echo $result |grep -w ${process}'\>') + [ ! -n "$val" ] && echo "$process is null" && return 1 + done + + # 检查关键进程是否重启 + local check_list=(sys.surfaceflinger.has_reboot sys.zygote.has_reboot sys.zygote64.has_reboot) + cmd="$RUNTIME_CMD exec -i $1 getprop |grep '.has_reboot' &" + result=$(wait_cmd "${cmd}") + check_wait_cmd_result "${cmd}" "${result}" + for property in ${check_list[@]}; do + val=$(echo $result |grep -w ${property}'\>') + [[ "$val" =~ "[1]" ]] && echo "$property has restarted" && return 1 + done + + # 检查服务列表 + cmd="$RUNTIME_CMD exec -i $1 service list |grep -w SurfaceFlinger &" + result=$(wait_cmd "${cmd}") + check_wait_cmd_result "${cmd}" "${result}" + if [[ "$result" =~ "[android.ui.ISurfaceComposer]" ]]; then + return 0 + else + echo "service SurfaceFlinger is not normal" + return 1 + fi +} + +function start_box() { + ########################## 1. 参数检查 ########################## + check_paras "$@" + ########################## 2. 参数解析 ########################## + while :; do + case $1 in + start) shift;; + --name) local BOX_NAME=$2; shift;; + --cpus) local CPUS=($2); shift;; + --numas) local NUMAS=($2); shift;; + --gpus) local GPUS_RENDER=($2); shift;; + --storage_size_gb) local STORAGE_SIZE_GB=$2; shift;; + --ram_size_mb) local RAM_SIZE_MB=$2; shift;; + --ports) local PORTS=($2); shift;; + --extra_run_option) local EXTRA_RUN_OPTION=$2; shift;; + --image) local IMAGE_NAME=$2; shift;; + --user_data_path) local USER_DATA_PATH=$2; shift;; + --container_data_path) local CONTAINER_DATA_PATH=$2; shift;; + --enable_render_layer) local ENABLE_RENDER_LAYER=$2; shift;; + --) shift; break;; + -?*) printf 'WARN: Unknown option: %s\n' "$1" >&2;; + *) break + esac + shift + done + + ########################## 3.环境初始化 ########################## + if [ $DEFAULT_RUNTIME == "docker" ]; then + CONTAINER_DATA_PATH="/var/lib/docker" + else + CONTAINER_DATA_PATH="/var/lib/containerd" + fi + + # HOOK_PATH + local HOOK_PATH=$CONTAINER_DATA_PATH/hooks + rm -rf ${HOOK_PATH}/${BOX_NAME} + mkdir -p ${HOOK_PATH}/${BOX_NAME} + + # EVENT PATH + local INPUT_EVENT_PATH="/var/run/${BOX_NAME}/input" + mkdir -p $INPUT_EVENT_PATH"/event0" + mkdir -p $INPUT_EVENT_PATH"/event1" + + # 存储隔离 + if [ -z ${USER_DATA_PATH} ]; then + USER_DATA_PATH="/root/mount" + fi + + if [ ! -d "${USER_DATA_PATH}/img" ]; then + mkdir -p ${USER_DATA_PATH}/img + fi + local KBOX_IMG=${USER_DATA_PATH}/img/$BOX_NAME.img + if [ ! -e $KBOX_IMG ]; then + fallocate -l ${STORAGE_SIZE_GB}G $KBOX_IMG + yes | mkfs -t ext4 $KBOX_IMG + fi + KBOX_DATA_PATH="${USER_DATA_PATH}/data/$BOX_NAME" + mkdir -p $KBOX_DATA_PATH + mount $KBOX_IMG $KBOX_DATA_PATH + echo $(($STORAGE_SIZE_GB * 2 * 1024 * 1024)) >$KBOX_DATA_PATH/storage_size + + ########################## 4.容器启动 ########################## + local RUN_OPTION="" + if [ $DEFAULT_RUNTIME == "docker" ]; then + RUN_OPTION+=" -i " + fi + RUN_OPTION+=" -td " + RUN_OPTION+=" --hostname=${BOX_NAME} " + RUN_OPTION+=" --cap-drop=ALL " + RUN_OPTION+=" --cap-add=SETPCAP " + RUN_OPTION+=" --cap-add=AUDIT_WRITE " + RUN_OPTION+=" --cap-add=SYS_CHROOT " + RUN_OPTION+=" --cap-add=CHOWN " + RUN_OPTION+=" --cap-add=DAC_OVERRIDE " + RUN_OPTION+=" --cap-add=FOWNER " + RUN_OPTION+=" --cap-add=SETGID " + RUN_OPTION+=" --cap-add=SETUID " + RUN_OPTION+=" --cap-add=SYSLOG " + RUN_OPTION+=" --cap-add=SYS_ADMIN " + RUN_OPTION+=" --cap-add=WAKE_ALARM " + RUN_OPTION+=" --cap-add=SYS_PTRACE " + RUN_OPTION+=" --cap-add=BLOCK_SUSPEND " + RUN_OPTION+=" --cap-add=MKNOD " + RUN_OPTION+=" --cap-add=KILL " + RUN_OPTION+=" --cap-add=SYS_RESOURCE " + RUN_OPTION+=" --cap-add=NET_RAW " + RUN_OPTION+=" --cap-add=NET_ADMIN " + RUN_OPTION+=" --cap-add=NET_BIND_SERVICE " + RUN_OPTION+=" --cap-add=SYS_NICE " + RUN_OPTION+=" --cap-add=AUDIT_CONTROL " + RUN_OPTION+=" --cap-add=DAC_READ_SEARCH " + RUN_OPTION+=" --cap-add=IPC_LOCK " + RUN_OPTION+=" --cap-add=SYS_MODULE " + RUN_OPTION+=" --security-opt="apparmor=unconfined" " + RUN_OPTION+=" --security-opt="seccomp=unconfined" " + RUN_OPTION+="--name ${BOX_NAME}" + RUN_OPTION+=" -e CONTAINER_NAME=${BOX_NAME} " + RUN_OPTION+=" -e PATH=/system/bin:/system/xbin " + RUN_OPTION+=" --cidfile ${HOOK_PATH}/${BOX_NAME}/container_id.cid " + RUN_OPTION+=" --cpu-shares=$(lscpu | grep -w "CPU(s)" | head -n 1 | awk '{print $2}') " + + local CPU NUMA TEMP + for CPU in ${CPUS[@]}; do + TEMP+=$CPU"," + done + TEMP=${TEMP: 0: $((${#TEMP} - 1))} + RUN_OPTION+=" --cpuset-cpus=$TEMP " + + TEMP="" + for NUMA in ${NUMAS[@]}; do + TEMP+=$NUMA"," + done + TEMP=${TEMP: 0: $((${#TEMP} - 1))} + RUN_OPTION+=" --cpuset-mems=$TEMP" + + # 内存 +1M,规避依赖UE引擎的游戏在内存设置为4的倍数时会崩溃的问题 + RAM_SIZE_MB=$(($RAM_SIZE_MB + 1)) + RUN_OPTION+=" --memory=${RAM_SIZE_MB}M " + if [ $DEFAULT_RUNTIME == "docker" ]; then + RUN_OPTION+=" --device=/dev/net/tun:/dev/tun:rwm " + else + RUN_OPTION+=" --device=/dev/net/tun:/dev/net/tun:rwm " + fi + RUN_OPTION+=" --device=/dev/ashmem:/dev/ashmem:rwm " + RUN_OPTION+=" --device=/dev/fuse:/dev/fuse:rwm " + RUN_OPTION+=" --device=/dev/uinput:/dev/uinput:rwm " + if [ -c "/dev/ion" ]; then + RUN_OPTION+=" --device=/dev/ion:/dev/ion:rwm " + fi + if [ -c "/dev/i2c-1" ]; then + RUN_OPTION+=" --device=/dev/i2c-1:/dev/i2c-1:rwm " + fi + local i + local VA_SGPU100_ID=":0200" + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + RUN_OPTION+=" --device=/dev/vatools:/dev/vatools:rwm " + RUN_OPTION+=" --device=/dev/va_sync:/dev/va_sync:rwm " + local RENDER_IDX + for (( i=0; i<${#GPUS_RENDER[@]};i++ )); do + RUN_OPTION+=" --device=${GPUS_RENDER[$i]}:${GPUS_RENDER[$i]}:rwm " + RENDER_IDX=$(($(echo "${GPUS_RENDER[$i]}" | tr -cd "[0-9]")-128)) + RUN_OPTION+=" --device=/dev/va${RENDER_IDX}_ctl:/dev/va${RENDER_IDX}_ctl:rwm " + RUN_OPTION+=" --device=/dev/va_video${RENDER_IDX}:/dev/va_video${RENDER_IDX}:rwm " + RUN_OPTION+=" --device=/dev/vacc${RENDER_IDX}:/dev/vacc${RENDER_IDX}:rwm " + done + else + for (( i=0; i<${#GPUS_RENDER[@]};i++ )); do + RUN_OPTION+=" --device=${GPUS_RENDER[$i]}:/dev/dri/renderD$((128 + $i)):rwm " + done + fi + if [ -e "/dev/tango32" ]; then + RUN_OPTION+=" --device=/dev/tango32:/dev/tango32:rwm " + fi + RUN_OPTION+=" --volume=$KBOX_DATA_PATH/cache:/cache:rw " + RUN_OPTION+=" --volume=$KBOX_DATA_PATH/data:/data:rw " + RUN_OPTION+=" --volume=$INPUT_EVENT_PATH/event0:/dev/input/event0:rw " + RUN_OPTION+=" --volume=$INPUT_EVENT_PATH/event1:/dev/input/event1:rw " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/diskstats:/proc/diskstats:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/meminfo:/proc/meminfo:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/stat:/proc/stat:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/swaps:/proc/swaps:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/uptime:/proc/uptime:ro " + RUN_OPTION+=" --volume=$KBOX_DATA_PATH/storage_size:/storage_size:rw " + if [[ $ENABLE_RENDER_LAYER == "1" ]]; then + RUN_OPTION+=" --volume=${USER_DATA_PATH}/shader_cache/:/vendor/shader_cache/:rw " + fi + mock_cpu + mock_power_supply + local PORT + for PORT in ${PORTS[@]}; do + RUN_OPTION+=" -p $PORT " + done + RUN_OPTION+=" --sysctl net.ipv6.conf.all.accept_redirects=0" + # 额外的选项 + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + # VA GPU 使用该参数传递是否使能硬解,其余情况下传递硬解设备信息。 + ENABLE_HARD_DECODE=$(echo "${EXTRA_RUN_OPTION}" | grep -oP '(?<=ENABLE_HARD_DECODE=)[01]') + EXTRA_RUN_OPTION=${EXTRA_RUN_OPTION% *} + fi + RUN_OPTION+=" $EXTRA_RUN_OPTION " + $RUNTIME_CMD run $RUN_OPTION $IMAGE_NAME sh + + if [ $DEFAULT_RUNTIME == "containerd" ]; then + $RUNTIME_CMD exec -i ${BOX_NAME} ln -s /dev/net/tun /dev/tun + fi + + # 支持Android系统属性可定制 + # local.prop用于修改定制属性,但该文件不是一定存在,需要用户手动生成。 + if [ -e "$CURRENT_DIR/local.prop" ]; then + $RUNTIME_CMD cp $CURRENT_DIR/local.prop ${BOX_NAME}:/data + $RUNTIME_CMD exec ${BOX_NAME} chmod 400 /data/local.prop + fi + + # VA GPU需要配置相关属性、修改设备的权限, 否则会导致容器无法启动, 当前VA GPU仅支持一张卡,故使用 GPUS_RENDER[0] + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + $RUNTIME_CMD cp ${BOX_NAME}:/system/vendor/build.prop build.prop_${BOX_NAME} + if [ $ENABLE_HARD_DECODE -eq 1 ];then + sed -i "s/ro.hardware.omxsoftdecode=1/ro.hardware.omxsoftdecode=0/g" build.prop_${BOX_NAME} + else + sed -i "s/ro.hardware.omxsoftdecode=0/ro.hardware.omxsoftdecode=1/g" build.prop_${BOX_NAME} + fi + $RUNTIME_CMD cp build.prop_${BOX_NAME} ${BOX_NAME}:/system/vendor/build.prop + rm -rf ./build.prop_${BOX_NAME} + fi + local cid=$($RUNTIME_CMD ps | grep -w " ${BOX_NAME}" | awk '{print $1}') + + local BINDER_MAJOR_ID=$(cat /proc/devices | grep binder | awk '{print $1}') + if [ $DEFAULT_RUNTIME == "docker" ]; then + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/docker/$cid*/cgroup.clone_children + else + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/default/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/default/$cid*/cgroup.clone_children + fi +} + +function delete_box() { + local BOX_NAME=$1 + local USER_DATA_PATH=$2 + local keep_data=0 + if [ $3 ] && [ $3 -eq 1 ]; then + keep_data=1 + fi + local RET="true" + local umount_try=30 + local rm_try=30 + set +e + # 删除容器 + if [ -n "$("$RUNTIME_CMD" ps -a --format {{.Names}} | grep "$BOX_NAME$")" ]; then + while [ $rm_try -gt 1 ] + do + $RUNTIME_CMD kill $BOX_NAME > /dev/null 2>&1 + $RUNTIME_CMD rm $BOX_NAME > /dev/null 2>&1 + if [ $? -ne 0 ]; then + rm_try=$((rm_try - 1)) + RET="fail" + sleep 1 + else + echo "remove container $BOX_NAME OK" + RET="true" + break + fi + done + fi + + # 删除cpu/文件 + umount /var/lib/kbox/cpus/$BOX_NAME/cpu/cpu*/* > /dev/null 2>&1 + rm -rf /var/lib/kbox/cpus/$BOX_NAME + [ $? -ne 0 ] && echo "fail to remove data files /var/lib/kbox/cpus/$BOX_NAME !" && RET="fail" + + # 删除power_supply文件 + rm -rf /var/lib/kbox/powers/${BOX_NAME} + + # 删除数据文件 + if [ -z ${USER_DATA_PATH} ]; then + USER_DATA_PATH="/root/mount" + fi + + if [ -d "$USER_DATA_PATH/data/$BOX_NAME" ]; then + while [ $umount_try -gt 1 ] + do + umount $USER_DATA_PATH/data/$BOX_NAME > /dev/null 2>&1 + [ $? -ne 0 ] && echo "$BOX_NAME is already umounted!" + mount | grep -w "$USER_DATA_PATH/data/$BOX_NAME" + if [ $? -eq 0 ]; then + umount_try=$((umount_try - 1)) + sleep 1 + else + echo "umounted $BOX_NAME OK" + break + fi + done + rm -rf $USER_DATA_PATH/data/$BOX_NAME > /dev/null 2>&1 + [ $? -ne 0 ] && echo "fail to remove data files $USER_DATA_PATH/data/$BOX_NAME !" && RET="fail" + fi + + # 删除数据img文件 + if [ -e "$USER_DATA_PATH/img/$BOX_NAME.img" ] && [ $keep_data -ne 1 ]; then + rm -rf $USER_DATA_PATH/img/$BOX_NAME.img > /dev/null 2>&1 + [ $? -ne 0 ] && echo "fail to remove image file $USER_DATA_PATH/img/$BOX_NAME.img !" && RET="fail" + fi + + # 删除input event path + if [ -d /var/run/$BOX_NAME ]; then + rm -rf /var/run/${BOX_NAME} > /dev/null 2>&1 + [ $? -ne 0 ] && echo "fail to remove event path /var/run/${BOX_NAME} !" && RET="fail" + fi + + if [ $RET == "true" ];then + echo "container ${BOX_NAME} is deleted successfully." + fi +} + +function wait_async_cmd() { + eval $1 + local pid=$(jobs -rp) + local count_time=0 + while true; do + local count=$(jobs -rp | wc -l) + if [ ${count} -eq 0 ]; then + wait ${pid} + # $?表示wait的返回状态,用于获取eval $1执行的命令是否执行成功,执行成功返回0 + if [ $? -ne 0 ]; then + echo -2 # 命令执行失败 + fi + break + fi + + if [ ${count_time} -gt 8 ]; then + kill -9 ${pid} + echo -1 + break + fi + + sleep 0.5 + count_time=$((count_time + 1)) + done +} + +function wait_cmd() { + local count_time=0 + while true; do + local result=$(wait_async_cmd "$1") + if [ "$result" != "-1" ]; then + echo ${result} + break + fi + + if [ ${count_time} -gt 3 ]; then + echo -1 + break + fi + count_time=$((count_time + 1)) + done +} + +check_wait_cmd_result() { + local cmd=$1 + local result=$2 + if [ "$result" == "-1" ]; then + echo "cmd \"${cmd}\" wait_cmd timeout" + fi +} + +function restart_box() { + local BOX_NAME=$1 + local USER_DATA_PATH=$2 + + local restart_times=3 # 默认最大重启次数为三次 + if [ $# -eq 3 ]; then + restart_times=$3 + fi + local ENABLE_HARD_DECODE=0 + if [ $# -eq 4 ]; then + ENABLE_HARD_DECODE=$4 + fi + + set +e + if [ -z ${USER_DATA_PATH} ]; then + USER_DATA_PATH="/root/mount" + fi + + echo "mount ${BOX_NAME}.img" + mount ${USER_DATA_PATH}/img/${BOX_NAME}.img ${USER_DATA_PATH}/data/${BOX_NAME} >/dev/null + + mock_cpu + + $RUNTIME_CMD inspect ${BOX_NAME} >/dev/null + if [ $? -ne 0 ]; then + # 无容器判断 + break + fi + + for i in $(seq 1 $restart_times) + do + local should_restart=0 # 0为不应该再重启,1为需要再次重启 + $RUNTIME_CMD stop -t 0 ${BOX_NAME} + echo "${BOX_NAME} begins restarting the $i times!" + $RUNTIME_CMD start ${BOX_NAME} + + if [ $DEFAULT_RUNTIME == "containerd" ]; then + $RUNTIME_CMD exec -i ${BOX_NAME} ln -s /dev/net/tun /dev/tun + fi + for j in $(seq 1 3) + do { + $RUNTIME_CMD inspect ${BOX_NAME} --format {{.State.Status}} |grep running + if [ $? -eq 0 ]; then + # 等待容器状态为 running + break + fi + sleep 1 + } done + + local execOneTime=true + local VA_SGPU100_ID=":0200" + + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ] && [ execOneTime ]; then + $RUNTIME_CMD cp ${BOX_NAME}:/system/vendor/build.prop build.prop_${BOX_NAME} + if [ $ENABLE_HARD_DECODE -eq 1 ];then + sed -i "s/ro.hardware.omxsoftdecode=1/ro.hardware.omxsoftdecode=0/g" build.prop_${BOX_NAME} + else + sed -i "s/ro.hardware.omxsoftdecode=0/ro.hardware.omxsoftdecode=1/g" build.prop_${BOX_NAME} + fi + $RUNTIME_CMD cp build.prop_${BOX_NAME} ${BOX_NAME}:/system/vendor/build.prop + rm -rf ./build.prop_${BOX_NAME} + execOneTime=false + fi + local cid=$($RUNTIME_CMD ps | grep -w " ${BOX_NAME}" | awk '{print $1}') + local BINDER_MAJOR_ID=$(cat /proc/devices | grep binder | awk '{print $1}') + if [ $DEFAULT_RUNTIME == "docker" ]; then + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/docker/$cid*/cgroup.clone_children + else + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/default/$cid*/devices.allow) + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/default/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/default/$cid*/cgroup.clone_children + fi + + # 支持Android系统属性可定制 + # local.prop用于修改定制属性,但该文件不是一定存在,需要用户手动生成。 + if [ -e "$CURRENT_DIR/local.prop" ]; then + $RUNTIME_CMD cp $CURRENT_DIR/local.prop ${BOX_NAME}:/data + $RUNTIME_CMD exec ${BOX_NAME} chmod 400 /data/local.prop + fi + + if [ $DEFAULT_RUNTIME == "docker" ]; then + $RUNTIME_CMD exec -itd ${BOX_NAME} /kbox-init.sh + else + $RUNTIME_CMD exec -d ${BOX_NAME} /kbox-init.sh 1 + fi + + local count_time=0 + while true; do + local cmd="$RUNTIME_CMD exec -i ${BOX_NAME} getprop sys.boot_completed | grep 1 &" + local result=$(wait_cmd "${cmd}") + check_wait_cmd_result "${cmd}" "${result}" + if [ "${result}" == "1" ]; then + # 等待容器启动完成 + check_key_process ${BOX_NAME} + [ ${?} -ne 0 ] && echo "${BOX_NAME} check key process fail" && should_restart=1 + break + fi + if [ ${count_time} -gt 50 ]; then + echo -e "\033[1;31m reStart check timed out,${BOX_NAME} unable to restart\033[0m" + should_restart=1 + break + fi + sleep 1 + count_time=$((count_time + 1)) + done + + if [ $i -eq $restart_times ] && [ $should_restart -eq 1 ];then + echo "${BOX_NAME} start failed!" + return 1 + fi + local cmd="$RUNTIME_CMD exec -i ${BOX_NAME} logcat -d |grep \"addInterfaceToNetwork() failed\" &" + local result=$(wait_async_cmd "${cmd}") + if [ "${result}" == "-1" ];then + echo "${BOX_NAME} wait_async_cmd logcat timeout" + elif [ "${result}" == "-2" ];then + # 无异常日志, 且检查关键进程均无异常,退出重启流程 + if [ $should_restart -eq 0 ]; then + break + fi + fi + done +} + +check_environment +CMD=$1; shift +case $CMD in + start) start_box "$@";; + delete) delete_box "$@";; + restart) restart_box "$@";; + wait_async_cmd) wait_async_cmd "$@";; + chk_key_process) check_key_process "$@";; + *) echo "command must be \"start\", \"delete\", \"restart\", \"wait_async_cmd\" or \"chk_key_process\"";; +esac diff --git a/deploy_scripts/base_box_aosp15.sh b/deploy_scripts/base_box_aosp15.sh new file mode 100644 index 0000000000000000000000000000000000000000..e873c8d6c2262946d18f7b5484cf264e05ce2608 --- /dev/null +++ b/deploy_scripts/base_box_aosp15.sh @@ -0,0 +1,921 @@ +#!/bin/bash +# Copyright Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. +#set -x + +THISDIR=$(readlink -ef $(dirname $0)) +CONTAINERD_CONFIG=$THISDIR/containerd_config +if [ -f "$CONTAINERD_CONFIG" ]; then + DEFAULT_RUNTIME=containerd + RUNTIME_CMD=nerdctl +else + DEFAULT_RUNTIME=docker + RUNTIME_CMD=docker +fi +#=============================================================================== +# Functions +#=============================================================================== +function check_environment() { + # root权限执行此脚本 + if [ "${UID}" -ne 0 ]; then + echo "请使用root权限执行" + exit 1 + fi + + # 支持非当前目录执行 + CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + cd ${CURRENT_DIR} + + # 如果是需要转码的机型,在使用脚本过程中检查转码 + local VENDOR_ID=$(lscpu | grep "Vendor ID:" | grep -v "BIOS" | awk '{print $3}') + if [ x"$VENDOR_ID" == x"0x48" ] || [ x"$VENDOR_ID" == x"HiSilicon" ]; then + check_exagear + fi +} + +function check_exagear() { + # 未注册 + if [ ! -e "/proc/sys/fs/binfmt_misc/ubt_a32a64" ]; then + if [ ! -d "/proc/sys/fs/binfmt_misc/" ]; then + mount -t binfmt_misc none /proc/sys/fs/binfmt_misc + fi + + # 在归档路径下模糊查找 + local UBT_PATHS=($(ls /root/dependency/*/ubt_a32a64)) + if [ ${#UBT_PATHS[@]} -lt 1 ]; then + echo "No ubt_a32a64 file!" + exit 1 + elif [ ${#UBT_PATHS[@]} -gt 1 ]; then + echo "Many ubt_a32a64 files exist! Please check:" + for PA in ${UBT_PATHS[@]}; do + echo "${PA}" + done + exit 1 + fi + + # 恢复exgear文件 + mkdir -p /opt/exagear + chmod -R 700 /opt/exagear + cp -rf ${UBT_PATHS[0]} /opt/exagear/ + cd /opt/exagear + chmod +x ubt_a32a64 + + # 注册转码 续行符后字符串顶格 + echo ":ubt_a32a64:M::\x7fELF\x01\x01\x01\x00\x00\x00\x0"\ +"0\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xf"\ +"f\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00"\ +"\x00\xfe\xff\xff\xff:/opt/exagear/ubt_a32a64:POCF" > /proc/sys/fs/binfmt_misc/register + fi + + # 检查ubt_a32a64版本 + local UBT_VER=($(/opt/exagear/ubt_a32a64 -V |grep -w binary | sed 's/^ExaGear binary translator version: \([^\s]*\)/\1/g' | sed 's/^v//g')) + if [ $UBT_VER \> "2.4.1" ]; then + if [ ! -e "/dev/tango32" ]; then + echo "No tango32!" + exit 1 + fi + fi +} + +function get_lxcfs_path() { + local value + if [ -d "/var/lib/lxc/lxcfs" ]; then + value="/var/lib/lxc/lxcfs" + elif [ -d "/var/lib/lxcfs" ]; then + value="/var/lib/lxcfs" + else + echo "error, fail to get lxcfs path" + exit 1 + fi + + echo ${value} +} + +#CPU文件模拟 +function mock_cpu() { + local CPU_PATH="/var/lib/kbox/cpus/${BOX_NAME}/cpu" + local CPU_NUM=8 + if [ -d "${CPU_PATH}" ];then + umount /var/lib/kbox/cpus/$BOX_NAME/cpu/cpu*/* > /dev/null 2>&1 + rm -rf /var/lib/kbox/cpus/$BOX_NAME + [ $? -ne 0 ] && echo "fail to remove data files /var/lib/kbox/cpus/$BOX_NAME !" && RET="fail" + fi + + mkdir -p ${CPU_PATH} + chmod 755 ${CPU_PATH} + + echo "7" >${CPU_PATH}"/kernel_max" + echo "0-7" >${CPU_PATH}"/possible" + echo "0-7" >${CPU_PATH}"/present" + echo "0-7" >${CPU_PATH}"/online" + + chmod 444 ${CPU_PATH}/kernel_max ${CPU_PATH}/possible ${CPU_PATH}/present ${CPU_PATH}/online + + # mock_cpufreq + mkdir -p ${CPU_PATH}/cpufreq/policy0 ${CPU_PATH}/cpufreq/cpuidle + chmod 755 ${CPU_PATH}/cpufreq ${CPU_PATH}/cpufreq/policy0 ${CPU_PATH}/cpufreq/cpuidle + + echo "$(seq 0 $(($CPU_NUM - 1))|tr 'n' ' ')" >${CPU_PATH}"/cpufreq/policy0/affected_cpus" + echo "1954000" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_max_freq" + echo "1954000" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_cur_freq" + echo "554000" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_min_freq" + echo "0" >${CPU_PATH}"/cpufreq/policy0/cpuinfo_transition_latency" + cat ${CPU_PATH}"/cpufreq/policy0/affected_cpus" >${CPU_PATH}"/cpufreq/policy0/related_cpus" + echo "554000 860000 956000 1042000 1128000 1224000 1320000 1397000 1512000 1628000 1748000 1858000 1954000" >${CPU_PATH}"/cpufreq/policy0/scaling_available_frequencies" + echo "interacitve userspace powersave performance schedutil" >${CPU_PATH}"/cpufreq/policy0/scaling_available_governors" + cat ${CPU_PATH}"/cpufreq/policy0/cpuinfo_cur_freq" >${CPU_PATH}"/cpufreq/policy0/scaling_cur_freq" + echo "cpufreq-dt" >${CPU_PATH}"/cpufreq/policy0/scaling_driver" + echo "performance" >${CPU_PATH}"/cpufreq/policy0/scaling_governor" + cat ${CPU_PATH}"/cpufreq/policy0/cpuinfo_max_freq" >${CPU_PATH}"/cpufreq/policy0/scaling_max_freq" + cat ${CPU_PATH}"/cpufreq/policy0/cpuinfo_min_freq" >${CPU_PATH}"/cpufreq/policy0/scaling_min_freq" + echo "" >${CPU_PATH}"/cpufreq/policy0/scaling_setspeed" + + chmod 444 ${CPU_PATH}/cpufreq/policy0/* + chmod 400 ${CPU_PATH}/cpufreq/policy0/cpuinfo_cur_freq + chmod 644 ${CPU_PATH}/cpufreq/policy0/scaling_governor ${CPU_PATH}/cpufreq/policy0/scaling_setspeed + chmod 660 ${CPU_PATH}/cpufreq/policy0/scaling_max_freq ${CPU_PATH}/cpufreq/policy0/scaling_min_freq + + # mock_cpuidle + mkdir -p ${CPU_PATH}/cpufreq/cpuidle/driver ${CPU_PATH}/cpufreq/cpuidle/state0 ${CPU_PATH}/cpufreq/cpuidle/state1 + chmod 755 ${CPU_PATH}/cpufreq/cpuidle/* + + echo "hisi_cluster0_idle_driver" >${CPU_PATH}"/cpufreq/cpuidle/driver/name" + chmod 444 ${CPU_PATH}"/cpufreq/cpuidle/driver/name" + + echo "ARM64 WFI" >${CPU_PATH}"/cpufreq/cpuidle/state0/desc" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state0/disable" + echo "1" >${CPU_PATH}"/cpufreq/cpuidle/state0/latency" + echo "WFI" >${CPU_PATH}"/cpufreq/cpuidle/state0/name" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state0/power" + echo "1" >${CPU_PATH}"/cpufreq/cpuidle/state0/residency" + echo "$((RANDOM*4+11111))" >${CPU_PATH}"/cpufreq/cpuidle/state0/usage" + echo "$(($(cat ${CPU_PATH}/cpufreq/cpuidle/state0/usage)*666))" >${CPU_PATH}"/cpufreq/cpuidle/state0/time" + + chmod 444 ${CPU_PATH}/cpufreq/cpuidle/state0/* + chmod 644 ${CPU_PATH}/cpufreq/cpuidle/state0/disable + + echo "cpu-sleep-0" >${CPU_PATH}"/cpufreq/cpuidle/state1/desc" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state1/disable" + echo "110" >${CPU_PATH}"/cpufreq/cpuidle/state1/latency" + echo "cpu-sleep-0" >${CPU_PATH}"/cpufreq/cpuidle/state1/name" + echo "0" >${CPU_PATH}"/cpufreq/cpuidle/state1/power" + echo "3000" >${CPU_PATH}"/cpufreq/cpuidle/state1/residency" + echo "$((RANDOM*+11111))" >${CPU_PATH}"/cpufreq/cpuidle/state1/usage" + echo "$(($(cat ${CPU_PATH}/cpufreq/cpuidle/state1/usage)*22222))" >${CPU_PATH}"/cpufreq/cpuidle/state0/time" + + + chmod 444 ${CPU_PATH}/cpufreq/cpuidle/state1/* + chmod 644 ${CPU_PATH}/cpufreq/cpuidle/state1/disable + + # mock_cpu* + for ((i=0; i<8; i++)); + do + mkdir -p ${CPU_PATH}/cpu$i + chmod 755 ${CPU_PATH}/cpu$i + #其他文件的挂载 + mkdir -p ${CPU_PATH}/cpu$i/hotplug ${CPU_PATH}/cpu$i/power ${CPU_PATH}/cpu$i/regs ${CPU_PATH}/cpu$i/topology + cp /sys/devices/system/cpu/cpu$i/cpu_capacity ${CPU_PATH}/cpu$i/cpu_capacity + mount --bind /sys/devices/system/cpu/cpu$i/hotplug ${CPU_PATH}/cpu$i/hotplug + echo "1" >${CPU_PATH}/cpu$i/online + mount --bind /sys/devices/system/cpu/cpu$i/power ${CPU_PATH}/cpu$i/power + mount --bind /sys/devices/system/cpu/cpu$i/regs ${CPU_PATH}/cpu$i/regs + mount --bind /sys/devices/system/cpu/cpu$i/topology ${CPU_PATH}/cpu$i/topology + mkdir -p ${CPU_PATH}/cpu$i/cpufreq ${CPU_PATH}/cpu$i/cpuidle + mount --bind ${CPU_PATH}/cpufreq/policy0 ${CPU_PATH}/cpu$i/cpufreq + mount --bind ${CPU_PATH}/cpufreq/cpuidle ${CPU_PATH}/cpu$i/cpuidle + done + + RUN_OPTION+="--volume=/var/lib/kbox/cpus/${BOX_NAME}/cpu:/sys/devices/system/cpu:ro" +} + +# 供电模拟:USB供电,未充电状态 +function mock_power_supply() { + local POWER_SUPPLY_PATH="/var/lib/kbox/powers/${BOX_NAME}/power_supply" + + mkdir -p $POWER_SUPPLY_PATH"/Battery" + mkdir -p $POWER_SUPPLY_PATH"/Mains" + mkdir -p $POWER_SUPPLY_PATH"/USB" + mkdir -p $POWER_SUPPLY_PATH"/Wireless" + + echo "100" >$POWER_SUPPLY_PATH"/Battery/capacity" + echo "3945000" >$POWER_SUPPLY_PATH"/Battery/charge_counter" + echo "0" >$POWER_SUPPLY_PATH"/Battery/current_now" + + echo "Good" >$POWER_SUPPLY_PATH"/Battery/health" + echo "1" >$POWER_SUPPLY_PATH"/Battery/online" + + echo "1" >$POWER_SUPPLY_PATH"/Battery/present" + echo "Not charging" >$POWER_SUPPLY_PATH"/Battery/status" + echo "Li-poly" >$POWER_SUPPLY_PATH"/Battery/technology" + echo "260" >$POWER_SUPPLY_PATH"/Battery/temp" + echo "Battery" >$POWER_SUPPLY_PATH"/Battery/type" + echo "4400" > $POWER_SUPPLY_PATH"/Battery/voltage_max" + echo "4356000" >$POWER_SUPPLY_PATH"/Battery/voltage_now" + + echo "500000" >$POWER_SUPPLY_PATH"/USB/current_max" + echo "Good" >$POWER_SUPPLY_PATH"/USB/health" + echo "1" >$POWER_SUPPLY_PATH"/USB/online" + echo "USB" >$POWER_SUPPLY_PATH"/USB/type" + echo "4950000" > $POWER_SUPPLY_PATH"/USB/voltage_max" + + echo "Good" >$POWER_SUPPLY_PATH"/Mains/health" + echo "0" >$POWER_SUPPLY_PATH"/Mains/online" + echo "Mains" >$POWER_SUPPLY_PATH"/Mains/type" + + echo "Good" >$POWER_SUPPLY_PATH"/Wireless/health" + echo "0" >$POWER_SUPPLY_PATH"/Wireless/online" + echo "Wireless" >$POWER_SUPPLY_PATH"/Wireless/type" + + RUN_OPTION+=" --volume=$POWER_SUPPLY_PATH:/sys/class/power_supply:rw " +} + +function check_paras() { + echo "------------------ Kbox Startup ------------------" + + local BOX_NAME CPUS NUMAS GPUS_RENDER STORAGE_SIZE_GB RAM_SIZE_MB PORTS + local EXTRA_RUN_OPTION IMAGE_NAME USER_DATA_PATH CONTAINER_DATA_PATH + local ENABLE_RENDER_LAYER + local PARA_ERROR="" + while :; do + case $1 in + start) shift;; + --name) BOX_NAME=$2; echo "--name) BOX_NAME : $2 "; shift;; + --cpus) CPUS=($2); echo "--cpus) CPUS : $2 "; shift;; + --numas) NUMAS=($2); echo "--numas) NUMAS : $2 "; shift;; + --gpus) GPUS_RENDER=($2); echo "--gpus) GPUS_RENDER : $2 "; shift;; + --storage_size_gb) STORAGE_SIZE_GB=$2; echo "--storage_size_gb) STORAGE_SIZE_GB : $2 "; shift;; + --ram_size_mb) RAM_SIZE_MB=$2; echo "--ram_size_mb) RAM_SIZE_MB : $2 "; shift;; + --ports) PORTS=($2); echo "--ports) PORTS : $2 "; shift;; + --extra_run_option) EXTRA_RUN_OPTION=$2; echo "--extra_run_option) EXTRA_RUN_OPTION : $2 "; shift;; + --image) IMAGE_NAME=$2; echo "--image) IMAGE_NAME : $2 "; shift;; + --user_data_path) USER_DATA_PATH=$2; echo "--user_data_path) USER_DATA_PATH : $2 "; shift;; + --container_data_path) CONTAINER_DATA_PATH=$2; echo "--container_data_path) CONTAINER_DATA_PATH : $2 "; shift;; + --enable_render_layer) ENABLE_RENDER_LAYER=$2; echo "--enable_render_layer) ENABLE_RENDER_LAYER : $2 "; shift;; + --) shift; break;; + -?*) printf 'WARN: Unknown option: %s\n' "$1" >&2; exit 1;; + *) break + esac + + shift + done + + if [ -z $BOX_NAME ]; then + echo "\"--name\" option error, fail: need a kbox name!" + PARA_ERROR="true" + fi + + if [ ${#CPUS[@]} -eq 0 ]; then + echo "\"--cpus\" option error, fail: para empty!" + PARA_ERROR="true" + fi + local CPU + for CPU in ${CPUS[@]}; do + if [ -n "`echo "$CPU" | sed 's/[0-9]//g'`" ]; then + echo "\"--cpus\" option error, fail: cpu parameter must be number!" + PARA_ERROR="true" + fi + if [ $CPU -ge $(lscpu | grep -w "CPU(s)" | head -n 1 | awk '{print $2}') ] || \ + [ $CPU -lt 0 ]; then + echo "\"--cpus\" option error, fail: cpu$CPUS not exist!" + fi + done + + if [ ${#NUMAS[@]} -eq 0 ]; then + echo "\"--numas\" option error, fail: para empty!" + PARA_ERROR="true" + fi + local NUMA + for NUMA in ${NUMAS[@]}; do + if [ -n "`echo "$NUMA" | sed 's/[0-9]//g'`" ]; then + echo "\"--numas\" option error, fail: numa parameter must be number!" + PARA_ERROR="true" + fi + + if [ $NUMA -ge $(lscpu | grep "NUMA node(s)" | awk '{print $3}') ] || \ + [ $NUMA -lt 0 ]; then + echo " \"--numas\" fail: numa$NUMA not exist!" + PARA_ERROR="true" + fi + done + + local GPU + for GPU in ${GPUS_RENDER[@]}; do + if [ ! -e $GPU ]; then + echo "\"--gpus\" error, fail: GPU device $GPU not exist!" + PARA_ERROR="true" + fi + done + + if [ -z "`echo "$STORAGE_SIZE_GB" | sed 's/[0-9]//g'`" ]; then + if [ -z $STORAGE_SIZE_GB ]; then + echo "\"--storage_size_gb\" option error, fail: para empty!" + PARA_ERROR="true" + elif [ $STORAGE_SIZE_GB -le 0 ]; then + echo "\"--storage_size_gb\" option error, fail: storage size must greater than 0 GB!" + PARA_ERROR="true" + fi + else + echo "\"--storage_size_gb\" option error, fail: storage size must be number!" + PARA_ERROR="true" + fi + + if [ -z "`echo "$RAM_SIZE_MB" | sed 's/[0-9]//g'`" ]; then + if [ -z $RAM_SIZE_MB ]; then + echo "\"--ram_size_mb\" option error, fail: para empty!" + PARA_ERROR="true" + elif [ $RAM_SIZE_MB -le 0 ];then + echo "\"--ram_size_mb\" option error, fail: ram size must greater than 0 MB!" + PARA_ERROR="true" + fi + else + echo "\"--ram_size_mb\" option error, fail: ram size must be number!" + PARA_ERROR="true" + fi + + if [ ${#PORTS[@]} -eq 0 ]; then + echo "\"--ports\" option error, fail: para empty!" + PARA_ERROR="true" + fi + local PORT + for PORT in ${PORTS[@]}; do + if [[ "${PORT}" =~ ":" ]]; then + local AGENT_PORT=$(echo ${PORT} | cut -d ':' -f1) + local HOST_PORT=$(echo ${PORT} | cut -d ':' -f2) + if [ -n "`echo "$AGENT_PORT" | sed 's/[0-9]//g'`" ]; then + echo "\"--ports\" option error, fail: agent port must be number!" + PARA_ERROR="true" + fi + + if [ -n "`echo "$HOST_PORT" | sed 's/[0-9]//g'`" ]; then + echo "\"--ports\" option error, fail: host port must be number!" + PARA_ERROR="true" + fi + else + echo "\"--ports\" option error, fail: error port format!" + PARA_ERROR="true" + fi + done + + if [[ "${IMAGE_NAME}" =~ ":" ]]; then + local IMAGE_RE=$(echo ${IMAGE_NAME} | cut -d ':' -f1) + tag=$(echo ${IMAGE_NAME} | cut -d ':' -f2) + $RUNTIME_CMD images | awk '{print $1" "$2}' | grep -w "${IMAGE_RE}" | grep -w "${tag}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "\"--image\" option error, no image ${IMAGE_NAME}!" + PARA_ERROR="true" + fi + else + $RUNTIME_CMD images | awk '{print $3}' | grep -w "${IMAGE_NAME}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "\"--image\" option error, fail: no image ${IMAGE_NAME}!" + PARA_ERROR="true" + fi + fi + + echo "---------------------------------------------------" + if [ "$PARA_ERROR" = "true" ]; then + echo "error: Kbox Start Fail!" + exit 1 + fi +} + +function check_key_process() { + # 检查关键进程是否存在 + local process_name=(system_server zygote zygote64 surfaceflinger) + local cmd="$RUNTIME_CMD exec -i $1 ps -A | egrep -w 'system_server|zygote|zygote64|surfaceflinger' &" + local result=$(wait_cmd "${cmd}") + check_wait_cmd_result "${cmd}" "${result}" + local val + for process in ${process_name[@]}; do + val=$(echo $result |grep -w ${process}'\>') + [ ! -n "$val" ] && echo "$process is null" && return 1 + done + + # 检查关键进程是否重启 + local check_list=(sys.surfaceflinger.has_reboot sys.zygote.has_reboot sys.zygote64.has_reboot) + cmd="$RUNTIME_CMD exec -i $1 getprop |grep '.has_reboot' &" + result=$(wait_cmd "${cmd}" 2>/dev/null ) + check_wait_cmd_result "${cmd}" "${result}" + for property in ${check_list[@]}; do + val=$(echo $result |grep -w ${property}'\>') + [[ "$val" =~ "[1]" ]] && echo "$property has restarted" && return 1 + done + + # 检查服务列表 + cmd="$RUNTIME_CMD exec -i $1 service list |grep -w SurfaceFlinger &" + result=$(wait_cmd "${cmd}") + check_wait_cmd_result "${cmd}" "${result}" + if [[ "$result" =~ "[android.ui.ISurfaceComposer]" ]]; then + return 0 + else + echo "service SurfaceFlinger is not normal" + return 1 + fi +} +# 自动选择回环设备节点 +function chose_loop_device() { + TARGET_LOOPS=40 + MAPPED_LOOPS=0 + CURRENT_LOOP=0 + while [ $MAPPED_LOOPS -lt $TARGET_LOOPS ]; do + # 获取已被占用的loop设备列表(每次循环更新,避免遗漏新占用的设备) + OCCUPIED_LOOPS=$(losetup -a | grep -oP '/dev/loop\K[0-9]+' | sort -n) + # 检查当前loop设备 + # 检查是否已被占用 + if ! echo "$OCCUPIED_LOOPS" | grep -q "^$CURRENT_LOOP$"; then + # 检查设备节点是否存在 + if [ ! -e "/dev/loop$CURRENT_LOOP" ]; then + mknod -m 0660 "/dev/loop$CURRENT_LOOP" b 7 $CURRENT_LOOP + fi + # 添加到映射选项 + RUN_OPTION+=" --device=/dev/loop$CURRENT_LOOP:/dev/loop$CURRENT_LOOP" + MAPPED_LOOPS=$((MAPPED_LOOPS + 1)) + fi + # 移动到下一个loop设备 + CURRENT_LOOP=$((CURRENT_LOOP + 1)) + done +} + + +function start_box() { + ########################## 1. 参数检查 ########################## + check_paras "$@" + ########################## 2. 参数解析 ########################## + while :; do + case $1 in + start) shift;; + --name) local BOX_NAME=$2; shift;; + --cpus) local CPUS=($2); shift;; + --numas) local NUMAS=($2); shift;; + --gpus) local GPUS_RENDER=($2); shift;; + --storage_size_gb) local STORAGE_SIZE_GB=$2; shift;; + --ram_size_mb) local RAM_SIZE_MB=$2; shift;; + --ports) local PORTS=($2); shift;; + --extra_run_option) local EXTRA_RUN_OPTION=$2; shift;; + --image) local IMAGE_NAME=$2; shift;; + --user_data_path) local USER_DATA_PATH=$2; shift;; + --container_data_path) local CONTAINER_DATA_PATH=$2; shift;; + --enable_render_layer) local ENABLE_RENDER_LAYER=$2; shift;; + --) shift; break;; + -?*) printf 'WARN: Unknown option: %s\n' "$1" >&2;; + *) break + esac + shift + done + + ########################## 3.环境初始化 ########################## + if [ $DEFAULT_RUNTIME == "docker" ]; then + CONTAINER_DATA_PATH="/var/lib/docker" + else + CONTAINER_DATA_PATH="/var/lib/containerd" + fi + + # HOOK_PATH + local HOOK_PATH=$CONTAINER_DATA_PATH/hooks + rm -rf ${HOOK_PATH}/${BOX_NAME} + mkdir -p ${HOOK_PATH}/${BOX_NAME} + + # EVENT PATH + local INPUT_EVENT_PATH="/var/run/${BOX_NAME}/input" + mkdir -p $INPUT_EVENT_PATH"/event0" + mkdir -p $INPUT_EVENT_PATH"/event1" + + # 存储隔离 + if [ -z ${USER_DATA_PATH} ]; then + USER_DATA_PATH="/root/mount" + fi + + if [ ! -d "${USER_DATA_PATH}/img" ]; then + mkdir -p ${USER_DATA_PATH}/img + fi + local KBOX_IMG=${USER_DATA_PATH}/img/$BOX_NAME.img + if [ ! -e $KBOX_IMG ]; then + fallocate -l ${STORAGE_SIZE_GB}G $KBOX_IMG + yes | mkfs -t ext4 $KBOX_IMG + fi + KBOX_DATA_PATH="${USER_DATA_PATH}/data/$BOX_NAME" + mkdir -p $KBOX_DATA_PATH + mount $KBOX_IMG $KBOX_DATA_PATH + echo $(($STORAGE_SIZE_GB * 2 * 1024 * 1024)) >$KBOX_DATA_PATH/storage_size + + ########################## 4.容器启动 ########################## + local RUN_OPTION="" + if [ $DEFAULT_RUNTIME == "docker" ]; then + RUN_OPTION+=" -i " + fi + RUN_OPTION+=" -td " + RUN_OPTION+=" --hostname=${BOX_NAME} " + #RUN_OPTION+=" --cap-add=CAP_MKNOD " + RUN_OPTION+=" --cap-add=SETPCAP " + RUN_OPTION+=" --cap-add=AUDIT_WRITE " + RUN_OPTION+=" --cap-add=SYS_CHROOT " + RUN_OPTION+=" --cap-add=CHOWN " + RUN_OPTION+=" --cap-add=DAC_OVERRIDE " + RUN_OPTION+=" --cap-add=FOWNER " + RUN_OPTION+=" --cap-add=SETGID " + RUN_OPTION+=" --cap-add=SETUID " + RUN_OPTION+=" --cap-add=SYSLOG " + RUN_OPTION+=" --cap-add=SYS_ADMIN " + RUN_OPTION+=" --cap-add=WAKE_ALARM " + RUN_OPTION+=" --cap-add=SYS_PTRACE " + RUN_OPTION+=" --cap-add=BLOCK_SUSPEND " + RUN_OPTION+=" --cap-add=MKNOD " + RUN_OPTION+=" --cap-add=KILL " + RUN_OPTION+=" --cap-add=SYS_RESOURCE " + RUN_OPTION+=" --cap-add=NET_RAW " + RUN_OPTION+=" --cap-add=NET_ADMIN " + RUN_OPTION+=" --cap-add=NET_BIND_SERVICE " + RUN_OPTION+=" --cap-add=SYS_NICE " + RUN_OPTION+=" --cap-add=AUDIT_CONTROL " + RUN_OPTION+=" --cap-add=DAC_READ_SEARCH " + RUN_OPTION+=" --cap-add=IPC_LOCK " + RUN_OPTION+=" --cap-add=SYS_MODULE " + RUN_OPTION+=" --security-opt="apparmor:unconfined" " + RUN_OPTION+=" --security-opt="seccomp:unconfined" " + RUN_OPTION+=" --device=/dev/loop-control:/dev/loop-control " + RUN_OPTION+=" --device=/dev/loop0:/dev/loop0 " + RUN_OPTION+=" --name ${BOX_NAME} " + RUN_OPTION+=" -v /sys:/sys " + RUN_OPTION+=" -e CONTAINER_NAME=${BOX_NAME} " + RUN_OPTION+=" -e PATH=/system/bin:/system/xbin " + RUN_OPTION+=" --cidfile ${HOOK_PATH}/${BOX_NAME}/container_id.cid " + RUN_OPTION+=" --cpu-shares=$(lscpu | grep -w "CPU(s)" | head -n 1 | awk '{print $2}') " + + chose_loop_device + + local CPU NUMA TEMP + for CPU in ${CPUS[@]}; do + TEMP+=$CPU"," + done + TEMP=${TEMP: 0: $((${#TEMP} - 1))} + RUN_OPTION+=" --cpuset-cpus=$TEMP " + + TEMP="" + for NUMA in ${NUMAS[@]}; do + TEMP+=$NUMA"," + done + TEMP=${TEMP: 0: $((${#TEMP} - 1))} + RUN_OPTION+=" --cpuset-mems=$TEMP" + + # 内存 +1M,规避依赖UE引擎的游戏在内存设置为4的倍数时会崩溃的问题 + RAM_SIZE_MB=$(($RAM_SIZE_MB + 1)) + RUN_OPTION+=" --memory=${RAM_SIZE_MB}M " + if [ $DEFAULT_RUNTIME == "docker" ]; then + RUN_OPTION+=" --device=/dev/net/tun:/dev/tun:rwm " + else + RUN_OPTION+=" --device=/dev/net/tun:/dev/net/tun:rwm " + fi + RUN_OPTION+=" --device=/dev/ashmem:/dev/ashmem:rwm " + RUN_OPTION+=" --device=/dev/fuse:/dev/fuse:rwm " + RUN_OPTION+=" --device=/dev/uinput:/dev/uinput:rwm " + if [ -c "/dev/ion" ]; then + RUN_OPTION+=" --device=/dev/ion:/dev/ion:rwm " + fi + if [ -c "/dev/i2c-1" ]; then + RUN_OPTION+=" --device=/dev/i2c-1:/dev/i2c-1:rwm " + fi + local i + local VA_SGPU100_ID=":0200" + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + RUN_OPTION+=" --device=/dev/vatools:/dev/vatools:rwm " + RUN_OPTION+=" --device=/dev/va_sync:/dev/va_sync:rwm " + local RENDER_IDX + for (( i=0; i<${#GPUS_RENDER[@]};i++ )); do + RUN_OPTION+=" --device=${GPUS_RENDER[$i]}:${GPUS_RENDER[$i]}:rwm " + RENDER_IDX=$(($(echo "${GPUS_RENDER[$i]}" | tr -cd "[0-9]")-128)) + RUN_OPTION+=" --device=/dev/va${RENDER_IDX}_ctl:/dev/va${RENDER_IDX}_ctl:rwm " + RUN_OPTION+=" --device=/dev/va_video${RENDER_IDX}:/dev/va_video${RENDER_IDX}:rwm " + RUN_OPTION+=" --device=/dev/vacc${RENDER_IDX}:/dev/vacc${RENDER_IDX}:rwm " + done + else + for (( i=0; i<${#GPUS_RENDER[@]};i++ )); do + RUN_OPTION+=" --device=${GPUS_RENDER[$i]}:/dev/dri/renderD$((128 + $i)):rwm " + done + fi + if [ -e "/dev/tango32" ]; then + RUN_OPTION+=" --device=/dev/tango32:/dev/tango32:rwm " + fi + RUN_OPTION+=" --volume=$KBOX_DATA_PATH/cache:/cache:rw " + RUN_OPTION+=" --volume=$KBOX_DATA_PATH/data:/data:rw " + RUN_OPTION+=" --volume=$INPUT_EVENT_PATH/event0:/dev/input/event0:rw " + RUN_OPTION+=" --volume=$INPUT_EVENT_PATH/event1:/dev/input/event1:rw " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/diskstats:/proc/diskstats:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/meminfo:/proc/meminfo:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/stat:/proc/stat:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/swaps:/proc/swaps:ro " + RUN_OPTION+=" --volume=$(get_lxcfs_path)/proc/uptime:/proc/uptime:ro " + RUN_OPTION+=" --volume=$KBOX_DATA_PATH/storage_size:/storage_size:rw " + if [[ $ENABLE_RENDER_LAYER == "1" ]]; then + RUN_OPTION+=" --volume=${USER_DATA_PATH}/shader_cache/:/vendor/shader_cache/:rw " + fi + mock_cpu + mock_power_supply + local PORT + for PORT in ${PORTS[@]}; do + RUN_OPTION+=" -p $PORT " + done + RUN_OPTION+=" --sysctl net.ipv6.conf.all.accept_redirects=0" + # 额外的选项 + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + # VA GPU 使用该参数传递是否使能硬解,其余情况下传递硬解设备信息。 + ENABLE_HARD_DECODE=$(echo "${EXTRA_RUN_OPTION}" | grep -oP '(?<=ENABLE_HARD_DECODE=)[01]') + EXTRA_RUN_OPTION=${EXTRA_RUN_OPTION% *} + fi + RUN_OPTION+=" $EXTRA_RUN_OPTION " + $RUNTIME_CMD run $RUN_OPTION --device-cgroup-rule "c *:* rwm" $IMAGE_NAME /init + + if [ $DEFAULT_RUNTIME == "containerd" ]; then + $RUNTIME_CMD exec -i ${BOX_NAME} ln -s /dev/net/tun /dev/tun + fi + + # 支持Android系统属性可定制 + # local.prop用于修改定制属性,但该文件不是一定存在,需要用户手动生成。 + if [ -e "$CURRENT_DIR/local.prop" ]; then + $RUNTIME_CMD cp $CURRENT_DIR/local.prop ${BOX_NAME}:/data + $RUNTIME_CMD exec ${BOX_NAME} chmod 400 /data/local.prop + fi + + # VA GPU需要配置相关属性、修改设备的权限, 否则会导致容器无法启动, 当前VA GPU仅支持一张卡,故使用 GPUS_RENDER[0] + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ]; then + $RUNTIME_CMD cp ${BOX_NAME}:/system/vendor/build.prop build.prop_${BOX_NAME} + if [ $ENABLE_HARD_DECODE -eq 1 ];then + sed -i "s/ro.hardware.omxsoftdecode=1/ro.hardware.omxsoftdecode=0/g" build.prop_${BOX_NAME} + else + sed -i "s/ro.hardware.omxsoftdecode=0/ro.hardware.omxsoftdecode=1/g" build.prop_${BOX_NAME} + fi + $RUNTIME_CMD cp build.prop_${BOX_NAME} ${BOX_NAME}:/system/vendor/build.prop + rm -rf ./build.prop_${BOX_NAME} + fi + local cid=$($RUNTIME_CMD ps | grep -w " ${BOX_NAME}" | awk '{print $1}') + local BINDER_MAJOR_ID=$(cat /proc/devices | grep binder | awk '{print $1}') + if [ $DEFAULT_RUNTIME == "docker" ]; then + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/docker/$cid*/cgroup.clone_children + else + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/default/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/default/$cid*/cgroup.clone_children + fi +} + +function delete_box() { + local BOX_NAME=$1 + local USER_DATA_PATH=$2 + local keep_data=0 + if [ $3 ] && [ $3 -eq 1 ]; then + keep_data=1 + fi + local RET="true" + local umount_try=30 + local rm_try=30 + set +e + # 删除容器 + if [ -n "$("$RUNTIME_CMD" ps -a --format {{.Names}} | grep "$BOX_NAME$")" ]; then + while [ $rm_try -gt 1 ] + do + $RUNTIME_CMD kill $BOX_NAME > /dev/null 2>&1 + $RUNTIME_CMD rm $BOX_NAME > /dev/null 2>&1 + if [ $? -ne 0 ]; then + rm_try=$((rm_try - 1)) + RET="fail" + sleep 1 + else + echo "remove container $BOX_NAME OK" + RET="true" + break + fi + done + fi + + # 删除cpu/文件 + umount /var/lib/kbox/cpus/$BOX_NAME/cpu/cpu*/* > /dev/null 2>&1 + rm -rf /var/lib/kbox/cpus/$BOX_NAME + [ $? -ne 0 ] && echo "fail to remove data files /var/lib/kbox/cpus/$BOX_NAME !" && RET="fail" + + # 删除power_supply文件 + rm -rf /var/lib/kbox/powers/${BOX_NAME} + + # 删除数据文件 + if [ -z ${USER_DATA_PATH} ]; then + USER_DATA_PATH="/root/mount" + fi + + if [ -d "$USER_DATA_PATH/data/$BOX_NAME" ]; then + while [ $umount_try -gt 1 ] + do + umount $USER_DATA_PATH/data/$BOX_NAME > /dev/null 2>&1 + [ $? -ne 0 ] && echo "$BOX_NAME is already umounted!" + mount | grep -w "$USER_DATA_PATH/data/$BOX_NAME" + if [ $? -eq 0 ]; then + umount_try=$((umount_try - 1)) + sleep 1 + else + echo "umounted $BOX_NAME OK" + break + fi + done + rm -rf $USER_DATA_PATH/data/$BOX_NAME > /dev/null 2>&1 + [ $? -ne 0 ] && echo "fail to remove data files $USER_DATA_PATH/data/$BOX_NAME !" && RET="fail" + fi + + # 删除数据img文件 + if [ -e "$USER_DATA_PATH/img/$BOX_NAME.img" ] && [ $keep_data -ne 1 ]; then + rm -rf $USER_DATA_PATH/img/$BOX_NAME.img > /dev/null 2>&1 + [ $? -ne 0 ] && echo "fail to remove image file $USER_DATA_PATH/img/$BOX_NAME.img !" && RET="fail" + fi + + # 删除input event path + if [ -d /var/run/$BOX_NAME ]; then + rm -rf /var/run/${BOX_NAME} > /dev/null 2>&1 + [ $? -ne 0 ] && echo "fail to remove event path /var/run/${BOX_NAME} !" && RET="fail" + fi + + if [ $RET == "true" ];then + echo "container ${BOX_NAME} is deleted successfully." + fi +} + +function wait_async_cmd() { + eval $1 + local pid=$(jobs -rp) + local count_time=0 + while true; do + local count=$(jobs -rp | wc -l) + if [ ${count} -eq 0 ]; then + wait ${pid} + # $?表示wait的返回状态,用于获取eval $1执行的命令是否执行成功,执行成功返回0 + if [ $? -ne 0 ]; then + echo -2 # 命令执行失败 + fi + break + fi + + if [ ${count_time} -gt 8 ]; then + kill -9 ${pid} + echo -1 + break + fi + + sleep 0.5 + count_time=$((count_time + 1)) + done +} + +function wait_cmd() { + local count_time=0 + while true; do + local result=$(wait_async_cmd "$1") + if [ "$result" != "-1" ]; then + echo ${result} + break + fi + + if [ ${count_time} -gt 3 ]; then + echo -1 + break + fi + count_time=$((count_time + 1)) + done +} + +check_wait_cmd_result() { + local cmd=$1 + local result=$2 + if [ "$result" == "-1" ]; then + echo "cmd \"${cmd}\" wait_cmd timeout" + fi +} + +function restart_box() { + local BOX_NAME=$1 + local USER_DATA_PATH=$2 + + local restart_times=3 # 默认最大重启次数为三次 + if [ $# -eq 3 ]; then + restart_times=$3 + fi + local ENABLE_HARD_DECODE=0 + if [ $# -eq 4 ]; then + ENABLE_HARD_DECODE=$4 + fi + + set +e + if [ -z ${USER_DATA_PATH} ]; then + USER_DATA_PATH="/root/mount" + fi + + echo "mount ${BOX_NAME}.img" + mount ${USER_DATA_PATH}/img/${BOX_NAME}.img ${USER_DATA_PATH}/data/${BOX_NAME} >/dev/null + + mock_cpu + + $RUNTIME_CMD inspect ${BOX_NAME} >/dev/null + if [ $? -ne 0 ]; then + # 无容器判断 + break + fi + + for i in $(seq 1 $restart_times) + do + local should_restart=0 # 0为不应该再重启,1为需要再次重启 + $RUNTIME_CMD stop -t 0 ${BOX_NAME} + echo "${BOX_NAME} begins restarting the $i times!" + RUN_OPTION+="" + chose_loop_device + $RUNTIME_CMD start ${BOX_NAME} + + if [ $DEFAULT_RUNTIME == "containerd" ]; then + $RUNTIME_CMD exec -i ${BOX_NAME} ln -s /dev/net/tun /dev/tun + fi + for j in $(seq 1 3) + do { + $RUNTIME_CMD inspect ${BOX_NAME} --format {{.State.Status}} |grep running + if [ $? -eq 0 ]; then + # 等待容器状态为 running + break + fi + sleep 1 + } done + + local execOneTime=true + local VA_SGPU100_ID=":0200" + + if [ -n "$(lspci -n | grep ${VA_SGPU100_ID} | awk '{print $3}')" ] && [ execOneTime ]; then + $RUNTIME_CMD cp ${BOX_NAME}:/system/vendor/build.prop build.prop_${BOX_NAME} + if [ $ENABLE_HARD_DECODE -eq 1 ];then + sed -i "s/ro.hardware.omxsoftdecode=1/ro.hardware.omxsoftdecode=0/g" build.prop_${BOX_NAME} + else + sed -i "s/ro.hardware.omxsoftdecode=0/ro.hardware.omxsoftdecode=1/g" build.prop_${BOX_NAME} + fi + $RUNTIME_CMD cp build.prop_${BOX_NAME} ${BOX_NAME}:/system/vendor/build.prop + rm -rf ./build.prop_${BOX_NAME} + execOneTime=false + fi + local cid=$($RUNTIME_CMD ps | grep -w " ${BOX_NAME}" | awk '{print $1}') + local BINDER_MAJOR_ID=$(cat /proc/devices | grep binder | awk '{print $1}') + if [ $DEFAULT_RUNTIME == "docker" ]; then + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/docker/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/docker/$cid*/cgroup.clone_children + else + # 赋予容器binder设备节点cgroup devices权限 + echo "c $BINDER_MAJOR_ID:* rwm" >$(ls -d /sys/fs/cgroup/devices/default/$cid*/devices.allow) + echo "c 13:* rwm" >$(ls -d /sys/fs/cgroup/devices/default/$cid*/devices.allow) + echo 1 > /sys/fs/cgroup/cpuset/default/$cid*/cgroup.clone_children + fi + + # 支持Android系统属性可定制 + # local.prop用于修改定制属性,但该文件不是一定存在,需要用户手动生成。 + if [ -e "$CURRENT_DIR/local.prop" ]; then + $RUNTIME_CMD cp $CURRENT_DIR/local.prop ${BOX_NAME}:/data + $RUNTIME_CMD exec ${BOX_NAME} chmod 400 /data/local.prop + fi + + local count_time=0 + while true; do + local cmd="$RUNTIME_CMD exec -i ${BOX_NAME} getprop sys.boot_completed | grep 1 &" + local result=$(wait_cmd "${cmd}" 2>/dev/null) + check_wait_cmd_result "${cmd}" "${result}" + if [ "${result}" == "1" ]; then + # 等待容器启动完成 + check_key_process ${BOX_NAME} + [ ${?} -ne 0 ] && echo "${BOX_NAME} check key process fail" && should_restart=1 + break + fi + if [ ${count_time} -gt 50 ]; then + echo -e "\033[1;31m reStart check timed out,${BOX_NAME} unable to restart\033[0m" + should_restart=1 + break + fi + sleep 1 + count_time=$((count_time + 1)) + done + + if [ $i -eq $restart_times ] && [ $should_restart -eq 1 ];then + echo "${BOX_NAME} start failed!" + return 1 + fi + local cmd="$RUNTIME_CMD exec -i ${BOX_NAME} logcat -d |grep \"addInterfaceToNetwork() failed\" &" + local result=$(wait_async_cmd "${cmd}") + if [ "${result}" == "-1" ];then + echo "${BOX_NAME} wait_async_cmd logcat timeout" + elif [ "${result}" == "-2" ];then + # 无异常日志, 且检查关键进程均无异常,退出重启流程 + if [ $should_restart -eq 0 ]; then + break + fi + fi + done +} + +check_environment +CMD=$1; shift +case $CMD in + start) start_box "$@";; + delete) delete_box "$@";; + restart) restart_box "$@";; + wait_async_cmd) wait_async_cmd "$@";; + chk_key_process) check_key_process "$@";; + *) echo "command must be \"start\", \"delete\", \"restart\", \"wait_async_cmd\" or \"chk_key_process\"";; +esac diff --git a/deploy_scripts/kbox_config.cfg b/deploy_scripts/kbox_config.cfg new file mode 100644 index 0000000000000000000000000000000000000000..47019e0633187d922438aa417acb3c00e2fd5458 --- /dev/null +++ b/deploy_scripts/kbox_config.cfg @@ -0,0 +1,915 @@ +#! /bin/bash +# Copyright Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. +# 启动脚本配置文件,可配置GPU、CPU等 + +#是否使能硬件解码功能, 1表示使能,其他值默认不使能 +ENABLE_HARD_DECODE=0 + +#是否使能渲染中间层,1表示使能,其他值默认不使能 +ENABLE_RENDER_LAYER=0 + +#硬件解码卡类型:0:T432 1:Quadra +HARD_DECODE_TYPE=2 + +# NETINT编解码卡设备节点, 启用硬解或者重启时启用硬解都需在第一次启动时增加设备节点,以下为示意 +# NETINT0="/dev/nvme0,/dev/nvme0n1,/dev/nvme1,/dev/nvme1n1,/dev/nvme2,/dev/nvme2n1,/dev/nvme3,/dev/nvme3n1" +# NETINT1="/dev/nvme4,/dev/nvme4n1,/dev/nvme5,/dev/nvme5n1,/dev/nvme6,/dev/nvme6n1,/dev/nvme7,/dev/nvme7n1" +NETINT0="" +NETINT1="" + +KBOX_DEC_MAP=( + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT0}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" + "${NETINT1}" +) + +KBOX_GPU_MAP=( +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +/dev/dri/renderD129 +) + +KBOX_XD_GPU_MAP_4RENDERS=( +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +) + +KBOX_XD_GPU_MAP_8RENDERS=( +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +) + +KBOX_XD_GPU_MAP_16RENDERS=( +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +) + +KBOX_XD_GPU_MAP_24RENDERS=( +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD144 +/dev/dri/renderD145 +/dev/dri/renderD146 +/dev/dri/renderD147 +/dev/dri/renderD148 +/dev/dri/renderD149 +/dev/dri/renderD150 +/dev/dri/renderD151 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD144 +/dev/dri/renderD145 +/dev/dri/renderD146 +/dev/dri/renderD147 +/dev/dri/renderD148 +/dev/dri/renderD149 +/dev/dri/renderD150 +/dev/dri/renderD151 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD144 +/dev/dri/renderD145 +/dev/dri/renderD146 +/dev/dri/renderD147 +/dev/dri/renderD148 +/dev/dri/renderD149 +/dev/dri/renderD150 +/dev/dri/renderD151 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD144 +/dev/dri/renderD145 +/dev/dri/renderD146 +/dev/dri/renderD147 +/dev/dri/renderD148 +/dev/dri/renderD149 +/dev/dri/renderD150 +/dev/dri/renderD151 +/dev/dri/renderD140 +/dev/dri/renderD141 +) + +KBOX_VA_GPU_MAP=( +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD130 +/dev/dri/renderD131 +/dev/dri/renderD132 +/dev/dri/renderD133 +/dev/dri/renderD134 +/dev/dri/renderD135 +/dev/dri/renderD128 +/dev/dri/renderD129 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +/dev/dri/renderD138 +/dev/dri/renderD139 +/dev/dri/renderD140 +/dev/dri/renderD141 +/dev/dri/renderD142 +/dev/dri/renderD143 +/dev/dri/renderD136 +/dev/dri/renderD137 +) +KBOX_MOUNT_MAP=( +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +/home/mount +) +KBOX_CPUSET_MAP=( +"4 5" +"4 5" +"6 7" +"6 7" +"8 9" +"8 9" +"10 11" +"10 11" +"12 13" +"12 13" +"14 15" +"14 15" +"16 17" +"16 17" +"18 19" +"18 19" +"20 21" +"20 21" +"22 23" +"22 23" +"24 25" +"24 25" +"26 27" +"26 27" +"36 37" +"36 37" +"38 39" +"38 39" +"40 41" +"40 41" +"42 43" +"42 43" +"44 45" +"44 45" +"46 47" +"46 47" +"48 49" +"48 49" +"50 51" +"50 51" +"52 53" +"52 53" +"54 55" +"54 55" +"56 57" +"56 57" +"58 59" +"58 59" +"60 61" +"60 61" +"68 69" +"68 69" +"70 71" +"70 71" +"72 73" +"72 73" +"74 75" +"74 75" +"76 77" +"76 77" +"78 79" +"78 79" +"80 81" +"80 81" +"82 83" +"82 83" +"84 85" +"84 85" +"86 87" +"86 87" +"88 89" +"88 89" +"90 91" +"90 91" +"100 101" +"100 101" +"102 103" +"102 103" +"104 105" +"104 105" +"106 107" +"106 107" +"108 109" +"108 109" +"110 111" +"110 111" +"112 113" +"112 113" +"114 115" +"114 115" +"116 117" +"116 117" +"118 119" +"118 119" +"120 121" +"120 121" +"122 123" +"122 123" +"124 125" +"124 125" +) diff --git a/deploy_scripts/kbox_maintainer.py b/deploy_scripts/kbox_maintainer.py new file mode 100644 index 0000000000000000000000000000000000000000..4c9da1c15c59e84f74b35d148a9a9bbc9ba6ec79 --- /dev/null +++ b/deploy_scripts/kbox_maintainer.py @@ -0,0 +1,84 @@ +import sys +import os +from argparse import ArgumentParser + +try: + sys.path.insert(0, os.getcwd()) + from kbox_maintainer import check + from kbox_maintainer import recover + from kbox_maintainer import log + from kbox_maintainer import resource +except KeyboardInterrupt: + raise SystemExit() + +if __name__ == "__main__": + + parser = ArgumentParser( + description="===Kbox Maintainment tool set usage===", + epilog="Hope this tool is helpful :)", + allow_abbrev=False, + ) + + subparsers = parser.add_subparsers( + title='maintainer options', + description='option is required to run different task', + metavar='option', + dest='option', + help='help details', + required=True + ) + + check_parser = subparsers.add_parser( + 'check', + help='check container(s) status' + ) + + check_parser.add_argument( + "containers", + nargs='*', + metavar="containers", + help='container name or id, check all when no container is specified' + ) + check_parser.set_defaults(func=check) + + recover_parser = subparsers.add_parser( + 'recover', + help='recover container(s)' + ) + + recover_parser.add_argument( + "containers", + nargs='*', + metavar="containers", + help='container name or id, recover all when no container is specified' + ) + recover_parser.set_defaults(func=recover) + + log_parser = subparsers.add_parser( + 'log', + help='log container(s)' + ) + + log_parser.add_argument( + "containers", + nargs='*', + metavar="containers", + help='container name or id, log all when no container is specified' + ) + log_parser.set_defaults(func=log) + + resource_parser = subparsers.add_parser( + 'resource', + help='resource container(s)' + ) + + resource_parser.add_argument( + "containers", + nargs='*', + metavar="containers", + help='container name or id, resource all when none is specified' + ) + resource_parser.set_defaults(func=resource) + + args = parser.parse_args(sys.argv[1:]) + args.func(args.containers) diff --git a/deploy_scripts/kbox_maintainer/__init__.py b/deploy_scripts/kbox_maintainer/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..431958e875b27deeaecdfc0d3f2a176bab01b984 --- /dev/null +++ b/deploy_scripts/kbox_maintainer/__init__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# coding: utf-8 +""" +Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +kbox_maintainer is a tool set aiming at Kbox maintainment. + +""" + +from kbox_maintainer.checker import check +from kbox_maintainer.checker import recover +from kbox_maintainer.logger import log +from kbox_maintainer.logger import resource + +__all__ = ["check", "recover", "log", "resource"] \ No newline at end of file diff --git a/deploy_scripts/kbox_maintainer/checker/__init__.py b/deploy_scripts/kbox_maintainer/checker/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a2c8b7f6f74a0457be2035f96dde9b272376f75c --- /dev/null +++ b/deploy_scripts/kbox_maintainer/checker/__init__.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# coding: utf-8 +""" +Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +Cherker is to check the system and make sure everything is OK. + +check: check system status and container status. + +recover: check and try to recover system status and container status. +""" + +from kbox_maintainer.checker.api import check +from kbox_maintainer.checker.api import recover + +__all__ = ["check", "recover"] diff --git a/deploy_scripts/kbox_maintainer/checker/api.py b/deploy_scripts/kbox_maintainer/checker/api.py new file mode 100644 index 0000000000000000000000000000000000000000..95f29479751a747f32123e91bf1dba1ba0bff9ab --- /dev/null +++ b/deploy_scripts/kbox_maintainer/checker/api.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# -*- encoding:utf-8 -*- +# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +import sys +import logging +from kbox_maintainer.checker.checker import Checker + + +def check(containers): + print(containers) + if not sys.platform.startswith('linux'): + logging.critical("This tool only support linux platform") + exit(0) + + if not Checker.check_exagear(): + logging.error( + "exagear not register, using [kbox_maintainer.py recover]") + return + + checker = Checker() + checker.check_containers(containers) + + +def recover(containers): + print(containers) + if not sys.platform.startswith('linux'): + logging.critical("This tool only support linux platform") + exit(0) + + if not Checker.check_exagear() and not Checker.recover_exagear(): + logging.fatal( + "exagear cannot recover!!!") + return + + checker = Checker() + checker.recover_containers(containers) diff --git a/deploy_scripts/kbox_maintainer/checker/checker.py b/deploy_scripts/kbox_maintainer/checker/checker.py new file mode 100644 index 0000000000000000000000000000000000000000..02a017277e8b59f13527e83cda03947c81b76e97 --- /dev/null +++ b/deploy_scripts/kbox_maintainer/checker/checker.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +# -*- encoding:utf-8 -*- +# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +import logging +import subprocess +import stat +from pathlib import Path +import docker +from os import uname +import re +from cpuinfo import get_cpu_info + +class Checker(object): + + def __init__(self): + self.__client = docker.from_env() + + @staticmethod + def _check_one_container(container): + container.reload() + if container.status != 'running': + print("container[short_id:{}, name:{}] is {}".format( + container.short_id, container.name, container.status)) + return False + + exit_code, output = container.exec_run("getprop sys.boot_completed") + if exit_code != 0: + print("container[name:{}] getprop failed, exit_code={}".format( + container.name, exit_code)) + return False + + if output != b'1\n': + print("container[name:{}] system boot is incomplete!!!".format( + container.name)) + return False + + process_name=["zygote", "zygote64", "surfaceflinger", "system_server"] + exit_code, output = container.exec_run("ps -a") + if exit_code != 0: + print("container[name:{}] get process failed, exit_code={}".format( + container.name, exit_code)) + return False + + for process in process_name: + patt = ' ' + process + '\n' + matchobj = re.search(patt, output.decode()) + if not matchobj: + print("container[name:{}] process[{}] is null!!!".format(container.name, process)) + return False + + check_list=["sys.surfaceflinger.has_reboot", "sys.zygote.has_reboot", "sys.zygote64.has_reboot"] + for proper in check_list: + exit_code, output = container.exec_run("getprop " + proper) + if exit_code != 0: + print("container[name:{}] get sys.prop[{}] failed, exit_code={}".format( + container.name, proper, exit_code)) + return False + if output == b'1\n': + print("container[name:{}] {}!!!".format(container.name, proper)) + return False + + exit_code, output = container.exec_run("service list |grep -w SurfaceFlinger") + if exit_code != 0: + print("container[name:{}] get service SurfaceFlinger failed, exit_code={}".format( + container.name, exit_code)) + return False + if str(output).find("[android.ui.ISurfaceComposer]") == -1: + print("container[name:{}] check service SurfaceFlinger failed!!!".format( + container.name)) + return False + + return True + + def check_containers(self, containers): + if containers: + containers_list = [self.__client.containers.get( + container) for container in containers] + else: + containers_list = self.__client.containers.list(all=True) + + unhealthy_containers = [] + for container in containers_list: + healthy = Checker._check_one_container(container) + if not healthy: + unhealthy_containers.append(container) + + print("===container check report===\n") + print("Total checked containers: {}\n".format(len(containers_list))) + if unhealthy_containers: + print("unhealth containers name:") + print([container.name for container in unhealthy_containers]) + else: + print("All the checked containers are healthy!") + + return unhealthy_containers + + @staticmethod + def _recover_one_container(container): + # exec android_kbox.sh scripts + container_no = container.name.split('_')[1] + cmd = Path.cwd() / "android_kbox.sh" + base_cmd = Path.cwd() / "base_box.sh" + if not cmd.is_file() or not base_cmd.is_file(): + logging.fatal("{} is not found".format(str(cmd))) + return + + cmd.chmod(mode=cmd.stat().st_mode | stat.S_IXUSR) + base_cmd.chmod(mode=base_cmd.stat().st_mode | stat.S_IXUSR) + + subprocess.run([str(cmd), "restart", container_no]) + + def recover_containers(self, containers): + unhealthy_containers = self.check_containers(containers) + if not unhealthy_containers: + return [] + + for container in unhealthy_containers: + Checker._recover_one_container(container) + + unrecover_containers = [] + for container in unhealthy_containers: + if not Checker._check_one_container(container): + unrecover_containers.append(container) + + print("===container recover report===\n") + if unrecover_containers: + print("unrecover containers name:") + print([container.name for container in unrecover_containers]) + else: + print("All the containers are recovered!") + + return unrecover_containers + + @staticmethod + def check_exagear(): + exagear = Path("/proc/sys/fs/binfmt_misc/ubt_a32a64") + return exagear.is_file() and exagear.read_text().startswith("enabled") + + @staticmethod + def recover_exagear(): + # exec android_kbox.sh scripts + cmd = Path.cwd() / "android_kbox.sh" + base_cmd = Path.cwd() / "base_box.sh" + if not cmd.is_file() or not base_cmd.is_file(): + logging.fatal("{} is not found".format(str(cmd))) + return + + cmd.chmod(mode=cmd.stat().st_mode | stat.S_IXUSR) + base_cmd.chmod(mode=base_cmd.stat().st_mode | stat.S_IXUSR) + + subprocess.run([str(cmd), "restart"]) + return Checker.check_exagear() diff --git a/deploy_scripts/kbox_maintainer/logger/__init__.py b/deploy_scripts/kbox_maintainer/logger/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..6f70c000863e8fcd8f2faf1ecc309fec886dc7d6 --- /dev/null +++ b/deploy_scripts/kbox_maintainer/logger/__init__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# coding: utf-8 +""" +Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +logger is to collect the needed log. + +log: run to collect logs (both hostOS and guestOS). + +""" + +from kbox_maintainer.logger.api import log +from kbox_maintainer.logger.api import resource + +__all__ = ["log", "resource"] \ No newline at end of file diff --git a/deploy_scripts/kbox_maintainer/logger/api.py b/deploy_scripts/kbox_maintainer/logger/api.py new file mode 100644 index 0000000000000000000000000000000000000000..819d46b5ed4e6aaf121454d23a5fe785bc3d954b --- /dev/null +++ b/deploy_scripts/kbox_maintainer/logger/api.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# -*- encoding:utf-8 -*- +# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +import sys +import logging +from kbox_maintainer.logger.logger import Logger + + +def log(containers): + print(containers) + if not sys.platform.startswith('linux'): + logging.critical("This tool only support linux platform") + exit(0) + logger = Logger() + logger.log_containers(containers) + +def resource(containers): + print(containers) + if not sys.platform.startswith('linux'): + logging.critical("This tool only support linux platform") + exit(0) + logger = Logger() + logger.resource_containers(containers) \ No newline at end of file diff --git a/deploy_scripts/kbox_maintainer/logger/logger.py b/deploy_scripts/kbox_maintainer/logger/logger.py new file mode 100644 index 0000000000000000000000000000000000000000..52ce45ea5e870ba40c101560395408fbeaefa67a --- /dev/null +++ b/deploy_scripts/kbox_maintainer/logger/logger.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python3 +# -*- encoding:utf-8 -*- +# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +import logging +import subprocess +from pathlib import Path +from shutil import make_archive +from shutil import copy +from shutil import rmtree +from shutil import copytree +from datetime import datetime +from tempfile import mkdtemp +import docker + + +class Logger(object): + def __init__(self): + self.__client = docker.from_env() + self.log_path = Path(mkdtemp(suffix='_log', prefix='kbox_', dir=str(Path.cwd()))) + self.guestos_log_path = self.log_path / "guestos" + self.hostos_log_path = self.log_path / "hostos" + self.guestos_log_path.mkdir(parents=True, exist_ok=True) + self.hostos_log_path.mkdir(parents=True, exist_ok=True) + + def _get_data_mount_path(self, container): + container_binds = self.__client.api.inspect_container(container.name)["HostConfig"]['Binds'] + for bind in container_binds: + if "data:/data:rw" in bind: + return bind.split(':')[0] + + raise ValueError("container {} not find data mount inspect".format(container.name)) + + def _run_cmd(self, container, cmd, to_file=False): + if container.status != 'running': + print("container[short_id:{}, name:{}] is {}".format( + container.short_id, container.name, container.status)) + return False + + if not cmd: + logging.error("invalid cmd") + return False + + exit_code, output = container.exec_run(cmd) + if exit_code != 0: + logging.error("cmd[{}] run failed".format(cmd)) + return False + + if to_file: + log_name = cmd.replace(" ", "_") + ".log" + file_path = self.guestos_log_path / container.name / log_name + file_path.write_text(output.decode()) + return True + + def _log_one_container(self, container): + container.reload() + if container.status != 'running': + print("container[short_id:{}, name:{}] is {}".format( + container.short_id, container.name, container.status)) + return False + + container_log = self.guestos_log_path / container.name + container_log.mkdir(parents=True, exist_ok=True) + docker_inspect_log = container_log / "docker_inspect.log" + with docker_inspect_log.open(mode="w") as f: + docker_inspect_proc = subprocess.run( + ["docker", "inspect", container.name], stdout=f) + if docker_inspect_proc.returncode != 0: + logging.fatal("docker inspect failed") + return False + + log_path = "/data/" + self.log_path.parts[-1] + ret_val = self._run_cmd(container, "mkdir -p " + log_path) \ + and self._run_cmd(container, "logcat -d -f " + log_path + "/logcat.log") \ + and self._run_cmd(container, "cp -r /data/anr " + log_path) \ + and self._run_cmd(container, "getprop", to_file=True) \ + and self._run_cmd(container, "dumpsys activity", to_file=True) \ + and self._run_cmd(container, "dumpsys meminfo", to_file=True) \ + and self._run_cmd(container, "dumpsys input", to_file=True) \ + and self._run_cmd(container, "ps -a", to_file=True) \ + and self._run_cmd(container, "cp -r /proc/cpuinfo " + log_path) \ + and self._run_cmd(container, "dumpsys meminfo", to_file=True) \ + and self._run_cmd(container, "top -n1", to_file=True) \ + and self._run_cmd(container, "df -h", to_file=True) \ + and self._run_cmd(container, "lspci", to_file=True) + + src_path = self._get_data_mount_path(container) + "/" + self.log_path.parts[-1] + dst_path = str(container_log / "data") + copytree(src_path, dst_path) + + return ret_val and self._run_cmd(container, "rm -rf " + log_path) + + def log_containers(self, containers): + var_log = self.hostos_log_path / "var_log" + make_archive(str(var_log), "tar", '/var/log') + + dmesg_log = self.hostos_log_path / "dmesg.log" + with dmesg_log.open(mode="w") as f: + dmesg_proc = subprocess.run(["dmesg", "-T"], stdout=f) + if dmesg_proc.returncode != 0: + logging.fatal("dmesg failed") + return + + docker_stats_log = self.hostos_log_path / "docker_stats.log" + with docker_stats_log.open(mode="w") as f: + docker_stats_proc = subprocess.run( + ["docker", "stats", "--no-stream"], stdout=f) + if docker_stats_proc.returncode != 0: + logging.fatal("docker stats failed") + return + + admgpu_pm_info_pathes = Path( + "/sys/kernel/debug/dri/").glob('*/amdgpu_pm_info') + for src_path in admgpu_pm_info_pathes: + dst_path = self.hostos_log_path / \ + "amdgpu_pm_info_{}".format(src_path.parts[-2]) + copy(str(src_path), str(dst_path)) + + if containers: + containers_list = [self.__client.containers.get( + container) for container in containers] + else: + containers_list = self.__client.containers.list(all=True) + + if not containers_list: + logging.fatal("No container found") + return + + log_failed_containers = [] + for container in containers_list: + log_ok = self._log_one_container(container) + if not log_ok: + log_failed_containers.append(container) + + print("===container log report===\n") + print("Total containers: {}\n".format(len(containers_list))) + if log_failed_containers: + print("log failed containers name:") + print([container.name for container in log_failed_containers]) + + if len(containers_list) > 1: + archive_path = Path.cwd() / \ + "cloudphone_log_{}".format( + datetime.utcnow().strftime("%Y%m%d%H%M%S")) + else: + archive_path = Path.cwd() / \ + "{}_log_{}".format( + containers_list[0].name, + datetime.utcnow().strftime("%Y%m%d%H%M%S")) + + make_archive(str(archive_path), "gztar", str(self.log_path)) + + print("===log finished===") + rmtree(str(self.log_path)) + + def _resource_one_container(self, container): + container.reload() + if container.status != 'running': + print("container[short_id:{}, name:{}] is {}".format( + container.short_id, container.name, container.status)) + return False + + container_res = self.guestos_log_path / container.name + container_res.mkdir(parents=True, exist_ok=True) + + temp_log_path = "/data/" + self.log_path.parts[-1] + ret_val = self._run_cmd(container, "mkdir -p " + temp_log_path) \ + and self._run_cmd(container, "cp -r /proc/cpuinfo " + temp_log_path) \ + and self._run_cmd(container, "dumpsys meminfo", to_file=True) \ + and self._run_cmd(container, "top -n1", to_file=True) \ + and self._run_cmd(container, "df -h", to_file=True) \ + and self._run_cmd(container, "lspci", to_file=True) + + src_path = self._get_data_mount_path(container) + "/" + self.log_path.parts[-1] + dst_path = str(container_res / "data") + copytree(src_path, dst_path) + + return ret_val and self._run_cmd(container, "rm -rf " + temp_log_path) + + def resource_containers(self, containers): + admgpu_pm_info_pathes = Path( + "/sys/kernel/debug/dri/").glob('*/amdgpu_pm_info') + for src_path in admgpu_pm_info_pathes: + dst_path = self.hostos_log_path / \ + "amdgpu_pm_info_{}".format(src_path.parts[-2]) + copy(str(src_path), str(dst_path)) + + if containers: + containers_list = [self.__client.containers.get( + container) for container in containers] + else: + containers_list = self.__client.containers.list(all=True) + + if not containers_list: + logging.fatal("No container found") + return + + res_failed_containers = [] + for container in containers_list: + res_ok = self._resource_one_container(container) + if not res_ok: + res_failed_containers.append(container) + + print("===container resource report===\n") + print("Total containers: {}\n".format(len(containers_list))) + if res_failed_containers: + print("resource failed containers name:") + print([container.name for container in res_failed_containers]) + + if len(containers_list) > 1: + archive_path = Path.cwd() / \ + "cloudphone_res_{}".format( + datetime.utcnow().strftime("%Y%m%d%H%M%S")) + else: + archive_path = Path.cwd() / \ + "{}_res_{}".format( + containers_list[0].name, + datetime.utcnow().strftime("%Y%m%d%H%M%S")) + + make_archive(str(archive_path), "gztar", str(self.log_path)) + + print("===resource stats finished===") + rmtree(str(self.log_path)) \ No newline at end of file diff --git a/deploy_scripts/kbox_maintainer/readme.md b/deploy_scripts/kbox_maintainer/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..e69d5d7234ca20a9188bd2785ebcb26d3e234a10 --- /dev/null +++ b/deploy_scripts/kbox_maintainer/readme.md @@ -0,0 +1,16 @@ +# Kbox_Maintainer: A tool collection for Kbox maintainment + +# Requirements +- This tool must be put in deploy_scripts dir +- run `pip install -r requirements.txt` to install requirements before first run. + + +# Usage +This tool is written in Python3. +```shell +cd ./deploy_scripts +python3 kbox_maintainer.py --help +``` + + + diff --git a/deploy_scripts/kbox_maintainer/requirements.txt b/deploy_scripts/kbox_maintainer/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..b8076545056b8fb4c7b8969eed406e5c2907aefa --- /dev/null +++ b/deploy_scripts/kbox_maintainer/requirements.txt @@ -0,0 +1,4 @@ +docker==5.0.0 +py-cpuinfo==8.0.0 +requests==2.22.0 +six==1.16.0 \ No newline at end of file diff --git a/deploy_scripts/make_image.sh b/deploy_scripts/make_image.sh new file mode 100644 index 0000000000000000000000000000000000000000..553f72d2dd873cd457b87bd2d3848498e55b242c --- /dev/null +++ b/deploy_scripts/make_image.sh @@ -0,0 +1,261 @@ +#!/bin/bash +# 本脚本将基于kbox基础云手机镜像、商用二进制包和目标GPU的二进制驱动合并制作云手机镜像,方便用户使用 +# 操作命令 +# ./make_images.sh [kbox基础云手机镜像名称] [目标GPU Kbox云手机镜像名称] [gpu驱动包名称] +# 脚本至少提供两个参数 +#第一个参数:kbox基础云手机镜像名称:kbox:latest +#第二个参数:目标GPU Kbox云手机镜像名称:kbox:latest_{GPU_NAME} +#第三个参数:[gpu驱动包名称] 为可选参数,无该参数时默认制作基于amd GPU 的kbox镜像。 +# 例: +# ./make_image.sh kbox:latest kbox:latest_ +# ./make_image.sh kbox:latest kbox:latest_ xxxx.tar.gz + +set -e + +CUR_PATH=$(cd $(dirname "${0}");pwd) + +GPUTYPE="" +GPU_DRIVER_PACKAGE= +TMP_PACKAGE_DIR=${CUR_PATH}/imageFile +DOCKER_FILE_DIR=${CUR_PATH}/Dockerfiles +DOCKER_FILE_BAK=${CUR_PATH}/Dockerfile.bak +DOCKER_FILE=${CUR_PATH}/Dockerfile + +function gen_docker_file() +{ + local target_docker_file="${DOCKER_FILE_DIR}/Dockerfile_" + if [ ${GPUTYPE} = "amd" ]; then + target_docker_file="${target_docker_file}amd" + elif [ ${GPUTYPE} = "awm" ]; then + target_docker_file="${target_docker_file}awm" + elif [ ${GPUTYPE} = "va" ]; then + target_docker_file="${target_docker_file}va" + fi + + # 判断Dockerfile是否存在 + if [ ! -f "${target_docker_file}" ]; then + echo -e "\033[1;31m[ERROR] ${target_docker_file} is not exist. \033[0m" && return -1 + fi + + if [ -f "${DOCKER_FILE}" ]; then + mv ${DOCKER_FILE} ${DOCKER_FILE_BAK} + fi + + cp ${target_docker_file} ${DOCKER_FILE} +} + +function gen_vagpu_package() +{ + cp -rp ${TMP_PACKAGE_DIR}/va_driver/system/* ${TMP_PACKAGE_DIR}/system/ + rm -rf ${TMP_PACKAGE_DIR}/system/vendor/bin/displayServer +} + +function gen_awmgpu_package() +{ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/codec_api/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/codec_api/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/codec_api/firmware/release/* ${TMP_PACKAGE_DIR}/system/etc/firmware/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm/libEGL_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm64/libEGL_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm/libIMGegl.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm64/libIMGegl.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm/libpvrANDROID_WSEGL.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm64/libpvrANDROID_WSEGL.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libGLESv1_CM_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libGLESv1_CM_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libGLESv2_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libGLESv2_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libsrv_um.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libsrv_um.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libufwriter.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libufwriter.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libusc.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libusc.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/firmware/* ${TMP_PACKAGE_DIR}/system/etc/firmware/awmgpu/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/gralloc/arm/* ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/gralloc/arm64/* ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/ifbc/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/ifbc/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/isr/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/isr/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/isr/wbc/ ${TMP_PACKAGE_DIR}/system/etc/firmware/awmgpu/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/libva/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/libva/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/va-api/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/va-api/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/openmax/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/openmax/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/vulkan/arm/* ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/vulkan/arm64/* ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/c-utils/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/c-utils/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ +} + +function prepare_gpu_driver() +{ + # 判断Dockerfile是否存在 + if [ ! -d "${DOCKER_FILE_DIR}" ]; then + echo -e "\033[1;31m[ERROR] ${DOCKER_FILE_DIR} is not exist. \033[0m" && return -1 + fi + + if [ ${GPUTYPE} != "amd" ]; then + # 解压GPU驱动包(注意:通过--no-same-owner保证解压后的文件属组为当前操作用户(root)文件属组) + cmd="tar --no-same-owner -zxvf ${GPU_DRIVER_PACKAGE} -C ${TMP_PACKAGE_DIR}" + echo -e "\033[1;36m[INFO] "$cmd" \033[0m" + $cmd > /dev/null + fi + + if [ $GPUTYPE == "awm" ]; then + gen_awmgpu_package + elif [ $GPUTYPE == "va" ]; then + gen_vagpu_package + fi + + gen_docker_file +} + +# 当前目录下有商用二进制压缩包时,使用该压缩包;如不存在该压缩包,跳过该步骤。避免覆盖用户自己编译镜像中的二进制。 +function prepare_kbox_binary() +{ + if [ -z $(ls | grep BoostKit-kbox_*.zip) ];then + echo -e -n "\033[1;31m[INFO] kbox binary package is not exist, " + echo -e "make sure ${DOCKER_IMAGE_IN} contain kbox binary. \033[0m" && return 0 + fi + BoostKit_package=$(ls BoostKit-kbox_*.zip) + unzip -o "${BoostKit_package}" -d ${TMP_PACKAGE_DIR} > /dev/null + binary_packages=$(ls ${TMP_PACKAGE_DIR}/Kbox-*-*-binary.zip) + unzip -o "${binary_packages}" -d ${TMP_PACKAGE_DIR} > /dev/null + BinaryPath=${TMP_PACKAGE_DIR}/product_prebuilt + + cp ${BinaryPath}/audio/lib/hw/audio.primary.kbox.so ${TMP_PACKAGE_DIR}/system/lib/hw/ + cp ${BinaryPath}/audio/lib64/hw/audio.primary.kbox.so ${TMP_PACKAGE_DIR}/system/lib64/hw/ + cp ${BinaryPath}/gbm_gralloc/lib/hw/gralloc.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/gbm_gralloc/lib64/hw/gralloc.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + cp ${BinaryPath}/gps/lib/hw/gps.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/gps/lib64/hw/gps.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + + cp ${BinaryPath}/omx/lib/* ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp ${BinaryPath}/omx/lib64/* ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + + if [ $GPUTYPE = "awm" ]; then + cp ${BinaryPath}/product_hwcomposer/lib/hw/hwcomposer.awmgpu.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/product_hwcomposer/lib64/hw/hwcomposer.awmgpu.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + elif [ $GPUTYPE = "amd" ]; then + cp ${BinaryPath}/product_hwcomposer/lib/hw/hwcomposer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/product_hwcomposer/lib64/hw/hwcomposer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + fi + + cp ${BinaryPath}/sensors/lib/hw/sensors.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/sensors/lib64/hw/sensors.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + cp ${BinaryPath}/vinput/bin/vinput ${TMP_PACKAGE_DIR}/system/vendor/bin/ + cp ${BinaryPath}/vinput/vinput.rc ${TMP_PACKAGE_DIR}/system/vendor/etc/init/vinput.rc + + if [ -d ${BinaryPath}/RenderAccLayer ]; then + cp ${BinaryPath}/RenderAccLayer/lib/hw/RenderAccLayer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/RenderAccLayer/lib64/hw/RenderAccLayer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + cp ${BinaryPath}/RenderAccLayer/kbox_render_accelerating_configuration.xml ${TMP_PACKAGE_DIR}/system/vendor/etc/ + fi +} + +function prepare_file_system() +{ + # 判断目录是否存在,若存在则删除重建 + if [ -d "${TMP_PACKAGE_DIR}" ]; then + rm -rf ${TMP_PACKAGE_DIR} + fi + mkdir -p ${TMP_PACKAGE_DIR}/system/lib/hw + mkdir -p ${TMP_PACKAGE_DIR}/system/lib64/hw + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/bin/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/etc/init/ + if [ $GPUTYPE = "awm" ]; then + mkdir -p ${TMP_PACKAGE_DIR}/system/etc/firmware/awmgpu/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + fi +} + +function detect_gpu_type() +{ + XD_GPU_ID="1fe0:1010" + VA_GPU_ID=":0200" + local xd_gpus=($(lspci -D | grep ${XD_GPU_ID} | awk '{print $1}')) + local va_gpus=($(lspci -D | grep ${VA_GPU_ID} | awk '{print $1}')) + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + + if [ 0 -ne ${#amd_gpus[@]} ]; then + GPUTYPE="amd" + if [ "${GPU_DRIVER_PACKAGE}" != "" ]; then + echo -e "\033[1;31m[INFO] amd gpu doesn't need driver package, ignore: ${GPU_DRIVER_PACKAGE}. \033[0m" + return 0 + fi + elif [ 0 -ne ${#va_gpus[@]} ]; then + GPUTYPE="va" + if [ "${GPU_DRIVER_PACKAGE}" != "va"* ] || [ -z $(ls | grep "${GPU_DRIVER_PACKAGE}") ]; then + echo -e -n "\033[1;31m[ERROR] please check gpu driver package " + echo -e "and make sure it match the gpu type. \033[0m" && exit -1 + fi + elif [ 0 -ne ${#xd_gpus[@]} ]; then + GPUTYPE="awm" + if [ "${GPU_DRIVER_PACKAGE}" != "awmgpu"* ] || [ -z $(ls | grep "${GPU_DRIVER_PACKAGE}") ]; then + echo -e -n "\033[1;31m[ERROR] please check gpu driver package " + echo -e "and make sure it match the gpu type. \033[0m" && exit -1 + fi + else + echo -e "\033[1;31m[ERROR] unsupport gpu type. \033[0m" && exit -1 + fi +} + +# 制作镜像 +function make_image() +{ + cmd="docker build --build-arg KBOX_IMAGE=${DOCKER_IMAGE_IN} -t ${DOCKER_IMAGE_OUT} ." + echo -e "\033[1;36m[INFO] "$cmd" \033[0m" + $cmd + wait +} + +function main() +{ + echo -e "\033[1;36m[INFO] Begin to make image \033[0m" + local start_time=$(date +%s) + local end_time=0 + + if [ $# -ne 2 ] && [ $# -ne 3 ]; then + echo -e "\033[1;31m[ERROR] input args should include base image, image to be made and gpu driver package\033[0m" + exit -1; + fi + + DOCKER_IMAGE_IN="$1" + DOCKER_IMAGE_OUT="$2" + + if [ -n "$3" ]; then + GPU_DRIVER_PACKAGE=$3 + fi + + detect_gpu_type + prepare_file_system + prepare_kbox_binary + prepare_gpu_driver + + make_image + [ ${?} != 0 ] && echo -e "\033[1;31m[ERROR] Failed to make image. \033[0m" && exit -1 + + # 制作镜像时间统计 + end_time=$(date +%s) + time_interval=$((${end_time}-${start_time})) + echo -e "\033[1;36m[INFO] End to make image from ${DOCKER_IMAGE_IN} to ${DOCKER_IMAGE_OUT} \033[0m" + echo -e "\033[1;36m[INFO] Make image takes ${time_interval} seconds. \033[0m" +} + +main "$@" diff --git a/deploy_scripts/make_image_aosp15.sh b/deploy_scripts/make_image_aosp15.sh new file mode 100644 index 0000000000000000000000000000000000000000..598b24a076a920dfb5b7c426609381acc558e3ff --- /dev/null +++ b/deploy_scripts/make_image_aosp15.sh @@ -0,0 +1,261 @@ +#!/bin/bash +# 本脚本将基于kbox基础云手机镜像(AOSP15版本)、商用二进制包和目标GPU的二进制驱动合并制作云手机镜像,方便用户使用 +# 操作命令 +# ./make_image_aosp15.sh [kbox基础云手机镜像名称] [目标GPU Kbox云手机镜像名称] [gpu驱动包名称] +# 脚本至少提供两个参数 +#第一个参数:kbox基础云手机镜像名称:kbox:latest +#第二个参数:目标GPU Kbox云手机镜像名称:kbox:latest_{GPU_NAME} +#第三个参数:[gpu驱动包名称] 为可选参数,无该参数时默认制作基于amd GPU 的kbox镜像。 +# 例: +# ./make_image_aosp15.sh kbox:latest kbox:latest_ +# ./make_image_aosp15.sh kbox:latest kbox:latest_ xxxx.tar.gz + +set -e + +CUR_PATH=$(cd $(dirname "${0}");pwd) + +GPUTYPE="" +GPU_DRIVER_PACKAGE= +TMP_PACKAGE_DIR=${CUR_PATH}/imageFile +DOCKER_FILE_DIR=${CUR_PATH}/Dockerfiles +DOCKER_FILE_BAK=${CUR_PATH}/Dockerfile.bak +DOCKER_FILE=${CUR_PATH}/Dockerfile + +function gen_docker_file() +{ + local target_docker_file="${DOCKER_FILE_DIR}/Dockerfile_" + if [ ${GPUTYPE} = "amd" ]; then + target_docker_file="${target_docker_file}amd" + elif [ ${GPUTYPE} = "awm" ]; then + target_docker_file="${target_docker_file}awm" + elif [ ${GPUTYPE} = "va" ]; then + target_docker_file="${target_docker_file}va_aosp15" + fi + + # 判断Dockerfile是否存在 + if [ ! -f "${target_docker_file}" ]; then + echo -e "\033[1;31m[ERROR] ${target_docker_file} is not exist. \033[0m" && return -1 + fi + + if [ -f "${DOCKER_FILE}" ]; then + mv ${DOCKER_FILE} ${DOCKER_FILE_BAK} + fi + + cp ${target_docker_file} ${DOCKER_FILE} +} + +function gen_vagpu_package() +{ + cp -rp ${TMP_PACKAGE_DIR}/va_driver/system/* ${TMP_PACKAGE_DIR}/system/ + rm -rf ${TMP_PACKAGE_DIR}/system/vendor/bin/displayServer +} + +function gen_awmgpu_package() +{ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/codec_api/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/codec_api/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/codec_api/firmware/release/* ${TMP_PACKAGE_DIR}/system/etc/firmware/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm/libEGL_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm64/libEGL_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm/libIMGegl.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm64/libIMGegl.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm/libpvrANDROID_WSEGL.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/egl/arm64/libpvrANDROID_WSEGL.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libGLESv1_CM_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libGLESv1_CM_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libGLESv2_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libGLESv2_powervr.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libsrv_um.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libsrv_um.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libufwriter.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libufwriter.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm/libusc.so ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/arm64/libusc.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/opengles/firmware/* ${TMP_PACKAGE_DIR}/system/etc/firmware/awmgpu/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/gralloc/arm/* ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/gralloc/arm64/* ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/ifbc/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/ifbc/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/isr/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/isr/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/isr/wbc/ ${TMP_PACKAGE_DIR}/system/etc/firmware/awmgpu/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/libva/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/libva/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/va-api/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/va-api/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/openmax/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/openmax/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/vulkan/arm/* ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/vulkan/arm64/* ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/c-utils/arm/* ${TMP_PACKAGE_DIR}/system/lib/ + cp -pr ${TMP_PACKAGE_DIR}/awmgpu/c-utils/arm64/* ${TMP_PACKAGE_DIR}/system/lib64/ +} + +function prepare_gpu_driver() +{ + # 判断Dockerfile是否存在 + if [ ! -d "${DOCKER_FILE_DIR}" ]; then + echo -e "\033[1;31m[ERROR] ${DOCKER_FILE_DIR} is not exist. \033[0m" && return -1 + fi + + if [ ${GPUTYPE} != "amd" ]; then + # 解压GPU驱动包(注意:通过--no-same-owner保证解压后的文件属组为当前操作用户(root)文件属组) + cmd="tar --no-same-owner -zxvf ${GPU_DRIVER_PACKAGE} -C ${TMP_PACKAGE_DIR}" + echo -e "\033[1;36m[INFO] "$cmd" \033[0m" + $cmd > /dev/null + fi + + if [ $GPUTYPE == "awm" ]; then + gen_awmgpu_package + elif [ $GPUTYPE == "va" ]; then + gen_vagpu_package + fi + + gen_docker_file +} + +# 当前目录下有商用二进制压缩包时,使用该压缩包;如不存在该压缩包,跳过该步骤。避免覆盖用户自己编译镜像中的二进制。 +function prepare_kbox_binary() +{ + if [ -z $(ls | grep BoostKit-kbox_*.zip) ];then + echo -e -n "\033[1;31m[INFO] kbox binary package is not exist, " + echo -e "make sure ${DOCKER_IMAGE_IN} contain kbox binary. \033[0m" && return 0 + fi + BoostKit_package=$(ls BoostKit-kbox_*.zip) + unzip -o "${BoostKit_package}" -d ${TMP_PACKAGE_DIR} > /dev/null + binary_packages=$(ls ${TMP_PACKAGE_DIR}/Kbox-*-*-binary.zip) + unzip -o "${binary_packages}" -d ${TMP_PACKAGE_DIR} > /dev/null + BinaryPath=${TMP_PACKAGE_DIR}/product_prebuilt + + cp ${BinaryPath}/audio/lib/hw/audio.primary.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/audio/lib64/hw/audio.primary.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + cp ${BinaryPath}/gbm_gralloc/lib/hw/gralloc.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/gbm_gralloc/lib64/hw/gralloc.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + cp ${BinaryPath}/gps/lib/hw/gps.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/gps/lib64/hw/gps.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + + cp ${BinaryPath}/omx/lib/* ${TMP_PACKAGE_DIR}/system/vendor/lib/ + cp ${BinaryPath}/omx/lib64/* ${TMP_PACKAGE_DIR}/system/vendor/lib64/ + + if [ $GPUTYPE = "awm" ]; then + cp ${BinaryPath}/product_hwcomposer/lib/hw/hwcomposer.awmgpu.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/product_hwcomposer/lib64/hw/hwcomposer.awmgpu.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + elif [ $GPUTYPE = "amd" ]; then + cp ${BinaryPath}/product_hwcomposer/lib/hw/hwcomposer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/product_hwcomposer/lib64/hw/hwcomposer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + fi + + cp ${BinaryPath}/sensors/lib/hw/sensors.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/sensors/lib64/hw/sensors.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + cp ${BinaryPath}/vinput/bin/vinput ${TMP_PACKAGE_DIR}/system/vendor/bin/ + cp ${BinaryPath}/vinput/vinput.rc ${TMP_PACKAGE_DIR}/system/vendor/etc/init/vinput.rc + + if [ -d ${BinaryPath}/RenderAccLayer ]; then + cp ${BinaryPath}/RenderAccLayer/lib/hw/RenderAccLayer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + cp ${BinaryPath}/RenderAccLayer/lib64/hw/RenderAccLayer.kbox.so ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + cp ${BinaryPath}/RenderAccLayer/kbox_render_accelerating_configuration.xml ${TMP_PACKAGE_DIR}/system/vendor/etc/ + fi +} + +function prepare_file_system() +{ + # 判断目录是否存在,若存在则删除重建 + if [ -d "${TMP_PACKAGE_DIR}" ]; then + rm -rf ${TMP_PACKAGE_DIR} + fi + mkdir -p ${TMP_PACKAGE_DIR}/system/lib/hw + mkdir -p ${TMP_PACKAGE_DIR}/system/lib64/hw + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib/hw/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib64/hw/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/bin/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/etc/init/ + if [ $GPUTYPE = "awm" ]; then + mkdir -p ${TMP_PACKAGE_DIR}/system/etc/firmware/awmgpu/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib/egl/ + mkdir -p ${TMP_PACKAGE_DIR}/system/vendor/lib64/egl/ + fi +} + +function detect_gpu_type() +{ + XD_GPU_ID="1fe0:1010" + VA_GPU_ID=":0200" + local xd_gpus=($(lspci -D | grep ${XD_GPU_ID} | awk '{print $1}')) + local va_gpus=($(lspci -D | grep ${VA_GPU_ID} | awk '{print $1}')) + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + + if [ 0 -ne ${#amd_gpus[@]} ]; then + GPUTYPE="amd" + if [ "${GPU_DRIVER_PACKAGE}" != "" ]; then + echo -e "\033[1;31m[INFO] amd gpu doesn't need driver package, ignore: ${GPU_DRIVER_PACKAGE}. \033[0m" + return 0 + fi + elif [ 0 -ne ${#va_gpus[@]} ]; then + GPUTYPE="va" + if [ "${GPU_DRIVER_PACKAGE}" != "va"* ] || [ -z $(ls | grep "${GPU_DRIVER_PACKAGE}") ]; then + echo -e -n "\033[1;31m[ERROR] please check gpu driver package " + echo -e "and make sure it match the gpu type. \033[0m" && exit -1 + fi + elif [ 0 -ne ${#xd_gpus[@]} ]; then + GPUTYPE="awm" + if [ "${GPU_DRIVER_PACKAGE}" != "awmgpu"* ] || [ -z $(ls | grep "${GPU_DRIVER_PACKAGE}") ]; then + echo -e -n "\033[1;31m[ERROR] please check gpu driver package " + echo -e "and make sure it match the gpu type. \033[0m" && exit -1 + fi + else + echo -e "\033[1;31m[ERROR] unsupport gpu type. \033[0m" && exit -1 + fi +} + +# 制作镜像 +function make_image() +{ + cmd="docker build --build-arg KBOX_IMAGE=${DOCKER_IMAGE_IN} -t ${DOCKER_IMAGE_OUT} ." + echo -e "\033[1;36m[INFO] "$cmd" \033[0m" + $cmd + wait +} + +function main() +{ + echo -e "\033[1;36m[INFO] Begin to make image \033[0m" + local start_time=$(date +%s) + local end_time=0 + + if [ $# -ne 2 ] && [ $# -ne 3 ]; then + echo -e "\033[1;31m[ERROR] input args should include base image, image to be made and gpu driver package\033[0m" + exit -1; + fi + + DOCKER_IMAGE_IN="$1" + DOCKER_IMAGE_OUT="$2" + + if [ -n "$3" ]; then + GPU_DRIVER_PACKAGE=$3 + fi + + detect_gpu_type + prepare_file_system + prepare_kbox_binary + prepare_gpu_driver + + make_image + [ ${?} != 0 ] && echo -e "\033[1;31m[ERROR] Failed to make image. \033[0m" && exit -1 + + # 制作镜像时间统计 + end_time=$(date +%s) + time_interval=$((${end_time}-${start_time})) + echo -e "\033[1;36m[INFO] End to make image from ${DOCKER_IMAGE_IN} to ${DOCKER_IMAGE_OUT} \033[0m" + echo -e "\033[1;36m[INFO] Make image takes ${time_interval} seconds. \033[0m" +} + +main "$@" diff --git a/deploy_scripts/openEuler_deploy/kbox_install_kernel.sh b/deploy_scripts/openEuler_deploy/kbox_install_kernel.sh new file mode 100644 index 0000000000000000000000000000000000000000..555c7a0a8a2ad6e56c5163bcbb68b5b4335556bd --- /dev/null +++ b/deploy_scripts/openEuler_deploy/kbox_install_kernel.sh @@ -0,0 +1,387 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2023-2023. All rights reserved. +# File Name: kbox_install_kernel.sh +# Description: openEuler kbox内核编译安装及环境部署。 +# Usage: +# 1.请确认脚本位于:Kbox-AOSP*/deploy_scripts/openEuler_deploy/ +# 2.需使用root用户或sudo命令执行此脚本 +# 3.脚本运行格式: +# [1] 联网模式:该模式下脚本会联网下载所需源码包 +# ./kbox_install_kernel.sh +# [2] 本地模式:该模式下脚本会会从本地获取源码包,${packages_dir}即本地包所在目录的绝对路径,详见步骤4 +# ./kbox_install_kernel.sh ${packages_dir} +# 示例: ./kbox_install_kernel.sh /home/kbox_packages/ +# 4.若使用"本地模式"运行脚本,需提前上传以下文件到${packages_dir}目录下:("联网模式"无需上传) +# [1] linux-firmware-20210919.tar.gz (仅amdgpu需要) +# [2] kernel-5.10.0-136.12.0.zip 或 kernel-5.10.0-182.0.0.zip 或 kernel-5.10.0-216.0.0.zip +# [3] ExaGear_ARM32-ARM64_V2.5.tar.gz +# ******************************************************************************** # + +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ] +then + bash "$0" "$@" + exit $? +fi + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +# 操作系统版本 +OS_MAJOR_VERSION="openEuler_22.03" +OS_MINOR_VERSION=$(cat /etc/os-release | grep -w VERSION | awk -F '[" ]' '{print $3}' | sed 's/(//g' | sed 's/)//g') +# linux kernel版本 +if [ ${OS_MINOR_VERSION} = "LTS-SP1" ] +then + KERNEL_VERSION="5.10.0-136.12.0" +elif [ ${OS_MINOR_VERSION} = "LTS-SP3" ] +then + KERNEL_VERSION="5.10.0-182.0.0" +else + KERNEL_VERSION="5.10.0-216.0.0" +fi + +exagear_bin_src="https://kunpeng-repo.obs.cn-north-4.myhuaweicloud.com/Exagear ARM32-ARM64/Exagear ARM32-ARM64 202.0.0/ExaGear_ARM32-ARM64_V2.5.tar.gz" +linux_firmware_src="https://mirrors.edge.kernel.org/pub/linux/kernel/firmware/linux-firmware-20210919.tar.gz" +linux_firmware_verify_src="https://mirrors.edge.kernel.org/pub/linux/kernel/firmware/sha256sums.asc" +kernel_src="https://gitee.com/openeuler/kernel.git" + +# 内核源码存放目录 +kernel_dir="/usr/src/kernels/" +# 当前目录 +CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +cd "${CURRENT_DIR}" || exit +# 依赖目录 +mkdir -p /root/dependency/ +work_dir=/root/dependency/ +# Kbox_AOSP根目录 +kbox_dir=$(cd "${CURRENT_DIR}"/../../ && pwd) +# 本地依赖包目录 +packages_dir=$1 + +cpu_num=$(< /proc/cpuinfo grep -c "processor") + +################################################################################ +# Function Name: check_local_package +# Description : 检查本地依赖包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function check_local_package(){ + [ -e "${packages_dir}/${1}" ] || error "指定路径下无法找到${packages_dir}/${1}" +} + +################################################################################ +# Function Name: check_local_packages +# Description : 检查本地依赖包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function check_local_packages(){ + # 仅amdgpu需准备固件包 + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + if [ 0 -ne ${#amd_gpus[@]} ]; then + check_local_package "linux-firmware-20210919.tar.gz" + fi + check_local_package "kernel-${KERNEL_VERSION}.zip" + check_local_package "ExaGear_ARM32-ARM64_V2.5.tar.gz" +} + +################################################################################ +# Function Name: set_run_mode +# Description : 选择源码包获取方式 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function set_run_mode(){ + if [ $# -eq 0 ] + then + run_mode="Download" + elif [ $# -eq 1 ] + then + run_mode="Local" + else + error "The number of input parameters is incorrect." + fi +} + +################################################################################ +# Function Name: modify_config +# Description : config文件修改。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function modify_config(){ + < ${3} grep -v "#"|grep -w "${1}" + if [ $? -eq 0 ] + then + if [ "${2}" = "n" ] + then + sed -i "s|${1}=.*|\# ${1} is not set|g" ${3} + else + sed -i "s|${1}=.*|${1}=${2}|g" ${3} + fi + else + if [ "${2}" != "n" ] + then + echo "${1}=${2}" >> ${3} + fi + fi + echo "${3} >> $(< ${3} grep -w "${1}")" +} + +################################################################################ +# Function Name: install_dependency +# Description : 安装编译构建所需依赖。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_dependency(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 1 安装依赖 ]]]]]]]]]]]]]]]]]]]]" + yum install -y dpkg dpkg-devel openssl openssl-devel ncurses ncurses-devel \ + bison flex bc libdrm build elfutils-libelf-devel docker lxc \ + lxcfs lxcfs-tools git tar patch make gcc + systemctl start lxcfs + systemctl enable lxcfs +} + +################################################################################ +# Function Name: download_copy_packages +# Description : 下载/拷贝源码包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function download_copy_packages(){ + local verify_sha256sums + local file_sha256sums + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + cd "${work_dir}" || exit + if [ ${run_mode} = "Download" ] + then + echo "[[[[[[[[[[[[[[[[[[[[ STEP 2 源码包下载 ]]]]]]]]]]]]]]]]]]]]" + + # 仅amdgpu需下载固件包 + if [ 0 -ne ${#amd_gpus[@]} ]; then + local verify_sha256sums="" + local file_sha256sums="" + [ -e "sha256sums.asc" ] && rm -rf sha256sums.asc + echo "---------校验linux固件---------" + wget -q --show-progress ${linux_firmware_verify_src} --no-check-certificate || error "固件校验文件下载失败" + verify_sha256sums=$(grep linux-firmware-20210919.tar.gz sha256sums.asc) + [ -e "linux-firmware-20210919.tar.gz" ] && file_sha256sums=$(sha256sum linux-firmware-20210919.tar.gz) + if [ "${verify_sha256sums}" != "${file_sha256sums}" ] + then + [ -e "linux-firmware-20210919.tar.gz" ] && rm -rf linux-firmware-20210919.tar.gz + echo "---------下载linux固件---------" + wget -q --show-progress "${linux_firmware_src}" --no-check-certificate || error "固件下载失败" + fi + fi + + echo "---------下载kernel源码---------" + [ -e "${kernel_dir}/kernel-${KERNEL_VERSION}" ] && rm -rf "${kernel_dir}/kernel-${KERNEL_VERSION}" + git config --global http.sslVerify false + git clone -b ${KERNEL_VERSION} --depth 1 ${kernel_src} "${kernel_dir}/kernel-${KERNEL_VERSION}" || error "kernel源码下载失败" + + echo "---------下载Exagear二进制---------" + [ -e "ExaGear_ARM32-ARM64_V2.5.tar.gz" ] && rm -rf ExaGear_ARM32-ARM64_V2.5.tar.gz + wget -q --show-progress "${exagear_bin_src}" --no-check-certificate || error "Exagear二进制下载失败" + else + echo "[[[[[[[[[[[[[[[[[[[[ STEP 2 源码包准备 ]]]]]]]]]]]]]]]]]]]]" + check_local_packages + cp "${packages_dir}/ExaGear_ARM32-ARM64_V2.5.tar.gz" . || exit + + if [ 0 -ne ${#amd_gpus[@]} ]; then + cp "${packages_dir}/linux-firmware-20210919.tar.gz" . || exit + fi + cp "${packages_dir}/kernel-${KERNEL_VERSION}.zip" "${kernel_dir}" || exit + [ -e "${kernel_dir}/kernel-${KERNEL_VERSION}" ] && rm -rf "${kernel_dir}/kernel-${KERNEL_VERSION}" + unzip "${kernel_dir}/kernel-${KERNEL_VERSION}.zip" -d "${kernel_dir}" > /dev/null 2>&1 || error "kernel-${KERNEL_VERSION}.zip解压失败" + fi +} + +################################################################################ +# Function Name: enable_exagear +# Description : 转码使能。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function enable_exagear(){ + cd ${work_dir} || exit + + local UBT_PATHS=($(ls ${work_dir}/*/ubt_a32a64 | sed 's/ubt_a32a64//')) + for PA in ${UBT_PATHS[@]}; do + rm -rf "${PA}" + done + + tar -xzvf ExaGear_ARM32-ARM64_V2.5.tar.gz > /dev/null 2>&1 || error "ExaGear_ARM32-ARM64_V2.5.tar.gz解压失败" + local NEW_UBT_PATHS=$(ls ${work_dir}/*/ubt_a32a64 | sed 's/ubt_a32a64//') + chown -R root:root "${NEW_UBT_PATHS}" + chmod -R 700 "${NEW_UBT_PATHS}" + mkdir -p /opt/exagear + chmod -R 700 /opt/exagear + cp -f ${NEW_UBT_PATHS}/ubt_a32a64 /opt/exagear/ || exit + chmod +x /opt/exagear/ubt_a32a64 +} + +################################################################################ +# Function Name: prepare_environment +# Description : 环境准备。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function prepare_environment(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 3 环境准备 ]]]]]]]]]]]]]]]]]]]]" + echo "---------使能Exagear---------" + enable_exagear + + # 仅amdgpu需更新固件 + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + if [ 0 -ne ${#amd_gpus[@]} ]; then + echo "---------更新gpu固件---------" + cd "${work_dir}" || exit + [ -e "linux-firmware-20210919" ] && rm -rf linux-firmware-20210919 + tar -xvpf linux-firmware-20210919.tar.gz > /dev/null 2>&1 || error "linux-firmware-20210919.tar.gz解压失败" + cp -ar linux-firmware-20210919/*gpu /usr/lib/firmware/ || exit + echo "---------gpu固件更新完毕" + fi + + echo "---------文件配置---------" + modify_config "fs.inotify.max_user_instances" "8192" /etc/sysctl.conf + if [ ! -e "/etc/selinux/config" ] + then + touch /etc/selinux/config + echo "SELINUX=disabled" >> /etc/selinux/config + else + modify_config "SELINUX" "disabled" /etc/selinux/config + fi + echo "---------以上配置在重启后生效---------" +} + +################################################################################ +# Function Name: apply_patch +# Description : 转码及内核补丁合入。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function apply_patch(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 4 合入kernel补丁 ]]]]]]]]]]]]]]]]]]]]" + touch ${kernel_dir}/kernel-${KERNEL_VERSION}/.scmversion + + cd "${kbox_dir}"/patchForExagear/hostOS || exit + cp 0001-exagear-kernel-module.patch "${kernel_dir}"/kernel-"${KERNEL_VERSION}"/ || exit + cd "${kbox_dir}"/patchForKernel/"${OS_MAJOR_VERSION}"/kernel_"${KERNEL_VERSION}"/ || exit + cp *.patch "${kernel_dir}"/kernel-"${KERNEL_VERSION}" || exit + + cd "${kernel_dir}"/kernel-"${KERNEL_VERSION}"/ || exit + exagear_patch_name=$(ls | grep .patch | grep -m 1 module) + echo "-- patching ${exagear_patch_name}" + patch -p1 < ${exagear_patch_name} || exit + patches_list=$(ls | grep -v module | grep .patch) + for patch_name in ${patches_list[@]} + do + echo "-- patching ${patch_name}" + patch -p1 < ${patch_name} || exit + done +} + +################################################################################ +# Function Name: build_install_kernel +# Description : 内核及内核模块编译。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function build_install_kernel(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 5 编译&安装kernel ]]]]]]]]]]]]]]]]]]]]" + echo "---------内核编译---------" + cd "${kernel_dir}"/kernel-"${KERNEL_VERSION}"/ || exit + if [ -e /boot/config-$(uname -r) ]; then + cp /boot/config-$(uname -r) .config || exit + else + cp /boot/$(ls /boot/ | grep -m1 config-) .config || exit + fi + + (echo -e \'\\0x65\'; echo -e \'\\0x79\') | make menuconfig > /dev/null 2>&1 + sleep 1 + + [ ! -e ".config" ] && error "config file not found" + modify_config "CONFIG_KBOX" "y" .config + modify_config "CONFIG_ANDROID_BINDER_DEVICES" "\"binder,hwbinder,vndbinder\"" .config + modify_config "CONFIG_HISI_PMU" "m" .config + modify_config "CONFIG_SYSTEM_TRUSTED_KEYS" "\"\"" .config + modify_config "CONFIG_DEBUG_INFO" "n" .config + modify_config "CONFIG_PID_RESERVE" "n" .config + modify_config "CONFIG_PSI_DEFAULT_DISABLED" "n" .config + modify_config "CONFIG_LOCALVERSION" "\"\"" .config + modify_config "CONFIG_SYSTEM_REVOCATION_KEYS" "\"\"" .config + + (echo -e \'\\0x65\'; echo -e \'\\0x79\') | make menuconfig > /dev/null 2>&1 + sleep 1 + + echo "---------内核编译---------" + make clean && make -j"${cpu_num}" + [ $? -ne 0 ] && error "内核编译失败" + echo "---------安装模块---------" + make modules_install + [ $? -ne 0 ] && error "模块安装失败" + echo "---------安装内核---------" + yum list installed | grep dkms > /dev/null 2>&1 + [ $? -eq 0 ] && yum remove -y dkms > /dev/null 2>&1 # dkms会导致make install报错 + make install + make install # 重复运行一遍,以消除uds、kvdo相关报错 + [ $? -ne 0 ] && error "内核安装失败" + echo "---------更新启动项---------" + local grub_cmdline=$(grep -Po 'GRUB_CMDLINE_LINUX="\K.*(?=")' /etc/default/grub | tr -s ' ') + local check_cmdline=""cgroup_enable=memory" "swapaccount=1"" + if [[ -z "$grub_cmdline" ]]; then + sed -i "s/GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX=\"cgroup_enable=memory swapaccount=1\"/g" /etc/default/grub + else + for p in ${check_cmdline[@]}; do + if [[ ! "$grub_cmdline" =~ "$p" ]]; then + grub_cmdline="$grub_cmdline $p" + fi + done + sed -i "s#^GRUB_CMDLINE_LINUX=.*#GRUB_CMDLINE_LINUX=\"$grub_cmdline\"#g" /etc/default/grub + fi + sed -i "s/GRUB_DEFAULT=.*/GRUB_DEFAULT=saved/g" /etc/default/grub + grub2-mkconfig -o /boot/efi/EFI/openEuler/grub.cfg + grub_default=$(< /boot/efi/EFI/openEuler/grub.cfg grep "menuentry"|grep -v "recovery mode\|old"|grep -w "(5.10.0)"|awk -F \' '{print $2}') + grub2-set-default "${grub_default}" + [ $? -ne 0 ] && error "启动项更新失败" +} + +################################################################################ +# Function Name: system_reboot +# Description : 系统重启。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function system_reboot(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 6 重启系统 ]]]]]]]]]]]]]]]]]]]]" + local reboot_val + read -p "内核安装与参数配置已完成, 是否重启以生效 [Y/y]" reboot_val + + if [ ${reboot_val} = "Y" ] || [ ${reboot_val} = "y" ] + then + echo "---------系统即将重启---------" + reboot + else + echo "---------请稍后手动重启系统---------" + fi +} + +main(){ + set_run_mode $@ + install_dependency + download_copy_packages + prepare_environment + apply_patch + build_install_kernel + system_reboot +} + +main "$@" +exit 0 diff --git a/deploy_scripts/ubuntu_deploy/kbox_install_kernel.sh b/deploy_scripts/ubuntu_deploy/kbox_install_kernel.sh new file mode 100644 index 0000000000000000000000000000000000000000..7bf51094af5577aa5a8ed22d2fe7105f5d55bd53 --- /dev/null +++ b/deploy_scripts/ubuntu_deploy/kbox_install_kernel.sh @@ -0,0 +1,444 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2023-2023. All rights reserved. +# File Name: kbox_install_kernel.sh +# Description: ubuntu kbox内核编译安装及环境部署。 +# Usage: +# 1.请确认脚本位于:Kbox-AOSP*/deploy_scripts/ubuntu_deploy/ +# 2.需使用root用户或sudo命令执行此脚本 +# 3.脚本运行格式: +# [1] 联网模式:该模式下脚本会联网下载所需源码包 +# ./kbox_install_kernel.sh +# [2] 本地模式:该模式下脚本会会从本地获取源码包,${packages_dir}即本地包所在目录的绝对路径,详见步骤4 +# ./kbox_install_kernel.sh ${packages_dir} +# 示例: ./kbox_install_kernel.sh /home/kbox_packages/ +# 4.若使用"本地模式"运行脚本,需提前上传以下文件到${packages_dir}目录下:("联网模式"无需上传) +# [1] linux-firmware-20210919.tar.gz (仅amdgpu需要) +# [2] linux-5.15.98.tar.gz +# [3] docker-19.03.15.tgz +# [4] ExaGear_ARM32-ARM64_V2.5.tar.gz +# ******************************************************************************** # + +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ] +then + bash "$0" "$@" + exit $? +fi + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +# 操作系统版本 +OS_VERSION="ubuntu_20.04" +# linux kernel版本 +KERNEL_VERSION="5.15.98" + +docker_src="https://download.docker.com/linux/static/stable/aarch64/docker-19.03.15.tgz" +exagear_bin_src="https://kunpeng-repo.obs.cn-north-4.myhuaweicloud.com/Exagear ARM32-ARM64/Exagear ARM32-ARM64 202.0.0/ExaGear_ARM32-ARM64_V2.5.tar.gz" +linux_firmware_src="https://mirrors.edge.kernel.org/pub/linux/kernel/firmware/linux-firmware-20210919.tar.gz" +linux_firmware_verify_src="https://mirrors.edge.kernel.org/pub/linux/kernel/firmware/sha256sums.asc" +kernel_src="https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-${KERNEL_VERSION}.tar.gz" +kernel_verify_src="https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/sha256sums.asc" + +# 内核源码存放目录 +kernel_dir="/usr/src/" +# 当前目录 +CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +cd "${CURRENT_DIR}" || exit +# 依赖目录 +mkdir -p /root/dependency/ +work_dir=/root/dependency/ +# Kbox_AOSP根目录 +kbox_dir=$(cd "${CURRENT_DIR}"/../../ && pwd) +# 本地依赖包目录 +packages_dir=$1 + +cpu_num=$(< /proc/cpuinfo grep -c "processor") + +################################################################################ +# Function Name: check_local_package +# Description : 检查本地依赖包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function check_local_package(){ + [ -e "${packages_dir}/${1}" ] || error "指定路径下无法找到${packages_dir}/${1}" +} + +################################################################################ +# Function Name: check_local_packages +# Description : 检查本地依赖包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function check_local_packages(){ + # 仅amdgpu需准备固件包 + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + if [ 0 -ne ${#amd_gpus[@]} ]; then + check_local_package "linux-firmware-20210919.tar.gz" + fi + check_local_package "linux-${KERNEL_VERSION}.tar.gz" + check_local_package "docker-19.03.15.tgz" + check_local_package "ExaGear_ARM32-ARM64_V2.5.tar.gz" +} + +################################################################################ +# Function Name: set_run_mode +# Description : 选择源码包获取方式 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function set_run_mode(){ + if [ $# -eq 0 ] + then + run_mode="Download" + elif [ $# -eq 1 ] + then + run_mode="Local" + else + error "The number of input parameters is incorrect." + fi +} + +################################################################################ +# Function Name: modify_config +# Description : config文件修改。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function modify_config(){ + < ${3} grep -v "#"|grep -w "${1}" + if [ $? -eq 0 ] + then + if [ "${2}" = "n" ] + then + sed -i "s|${1}=.*|\# ${1} is not set|g" ${3} + else + sed -i "s|${1}=.*|${1}=${2}|g" ${3} + fi + else + if [ "${2}" != "n" ] + then + echo "${1}=${2}" >> ${3} + fi + fi + echo "${3} >> $(< ${3} grep -w "${1}")" +} + +################################################################################ +# Function Name: download_copy_packages +# Description : 下载/拷贝源码包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function download_copy_packages(){ + local verify_sha256sums + local file_sha256sums + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + cd "${work_dir}" || exit + if [ ${run_mode} = "Download" ] + then + echo "[[[[[[[[[[[[[[[[[[[[ STEP 1 源码包下载 ]]]]]]]]]]]]]]]]]]]]" + + # 仅amdgpu需下载固件包 + if [ 0 -ne ${#amd_gpus[@]} ]; then + local verify_sha256sums="" + local file_sha256sums="" + [ -e "sha256sums.asc" ] && rm -rf sha256sums.asc + echo "---------校验linux固件---------" + wget -q --show-progress ${linux_firmware_verify_src} --no-check-certificate || error "固件校验文件下载失败" + verify_sha256sums=$(grep linux-firmware-20210919.tar.gz sha256sums.asc) + [ -e "linux-firmware-20210919.tar.gz" ] && file_sha256sums=$(sha256sum linux-firmware-20210919.tar.gz) + if [ "${verify_sha256sums}" != "${file_sha256sums}" ] + then + [ -e "linux-firmware-20210919.tar.gz" ] && rm -rf linux-firmware-20210919.tar.gz + echo "---------下载linux固件---------" + wget -q --show-progress "${linux_firmware_src}" --no-check-certificate || error "固件下载失败" + fi + fi + + verify_sha256sums="" + file_sha256sums="" + [ -e "sha256sums.asc" ] && rm -rf sha256sums.asc + echo "---------校验kernel源码---------" + wget -q --show-progress ${kernel_verify_src} --no-check-certificate || error "kernel校验文件下载失败" + verify_sha256sums=$(grep linux-${KERNEL_VERSION}.tar.gz sha256sums.asc) + [ -e "linux-${KERNEL_VERSION}.tar.gz" ] && file_sha256sums=$(sha256sum linux-${KERNEL_VERSION}.tar.gz) + if [ "${verify_sha256sums}" != "${file_sha256sums}" ] + then + [ -e "linux-${KERNEL_VERSION}.tar.gz" ] && rm -rf linux-${KERNEL_VERSION}.tar.gz + echo "---------下载kernel源码---------" + wget -q --show-progress "${kernel_src}" --no-check-certificate || error "kernel源码下载失败" + fi + + echo "---------下载docker---------" + [ -e "docker-19.03.15.tgz" ] && rm -rf docker-19.03.15.tgz + wget -q --show-progress "${docker_src}" --no-check-certificate || error "docker下载失败" + + echo "---------下载Exagear二进制---------" + [ -e "ExaGear_ARM32-ARM64_V2.5.tar.gz" ] && rm -rf ExaGear_ARM32-ARM64_V2.5.tar.gz + wget -q --show-progress "${exagear_bin_src}" --no-check-certificate || error "Exagear二进制下载失败" + else + echo "[[[[[[[[[[[[[[[[[[[[ STEP 1 源码包准备 ]]]]]]]]]]]]]]]]]]]]" + check_local_packages + cp "${packages_dir}/docker-19.03.15.tgz" . || exit + cp "${packages_dir}/ExaGear_ARM32-ARM64_V2.5.tar.gz" . || exit + + if [ 0 -ne ${#amd_gpus[@]} ]; then + cp "${packages_dir}/linux-firmware-20210919.tar.gz" . || exit + fi + cp "${packages_dir}/linux-${KERNEL_VERSION}.tar.gz" . || exit + fi +} + +################################################################################ +# Function Name: install_dependency +# Description : 安装编译构建所需依赖。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_dependency(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 2 安装依赖 ]]]]]]]]]]]]]]]]]]]]" + apt update || exit + apt install -y dpkg dpkg-dev libncurses5-dev libssl-dev libpciaccess0 \ + libdrm-amdgpu1 xserver-xorg-video-amdgpu lxc build-essential \ + libncurses5-dev openssl libssl-dev pkg-config bison flex libelf-dev +} + +################################################################################ +# Function Name: install_docker +# Description : 安装预置的docker-*.tgz包。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_docker(){ + local docker_version=$(docker -v | grep "Docker version") + if [[ -n ${docker_version} ]] + then + echo "docker已安装" + return 0 + fi + + cd ${work_dir} || exit + [ -e "docker" ] && rm -rf docker + tar xvpf docker-19.03.15.tgz > /dev/null 2>&1 || error "docker-19.03.15.tgz解压失败" + cp -p docker/* /usr/bin || exit + cat >/usr/lib/systemd/system/docker.service < /dev/null 2>&1 || error "ExaGear_ARM32-ARM64_V2.5.tar.gz解压失败" + local NEW_UBT_PATHS=$(ls ${work_dir}/*/ubt_a32a64 | sed 's/ubt_a32a64//') + chown -R root:root "${NEW_UBT_PATHS}" + chmod -R 700 "${NEW_UBT_PATHS}" + mkdir -p /opt/exagear + chmod -R 700 /opt/exagear + cp -f ${NEW_UBT_PATHS}/ubt_a32a64 /opt/exagear/ || exit + chmod +x /opt/exagear/ubt_a32a64 +} + +################################################################################ +# Function Name: prepare_environment +# Description : 环境准备。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function prepare_environment(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 3 环境准备 ]]]]]]]]]]]]]]]]]]]]" + echo "---------安装docker---------" + install_docker + + echo "---------使能Exagear---------" + enable_exagear + + # 仅amdgpu需更新固件 + local amd_gpus=($(lspci -D | grep "AMD" | grep -E "VGA|73a3|73a1|73e3" | awk '{print $1}')) + if [ 0 -ne ${#amd_gpus[@]} ]; then + echo "---------更新gpu固件---------" + cd "${work_dir}" || exit + [ -e "linux-firmware-20210919" ] && rm -rf linux-firmware-20210919 + tar -xvpf linux-firmware-20210919.tar.gz > /dev/null 2>&1 || error "linux-firmware-20210919.tar.gz解压失败" + cp -ar linux-firmware-20210919/*gpu /usr/lib/firmware/ || exit + echo "---------gpu固件更新完毕" + fi + + echo "---------文件配置---------" + modify_config "fs.inotify.max_user_instances" "8192" /etc/sysctl.conf + if [ ! -e "/etc/selinux/config" ] + then + touch /etc/selinux/config + echo "SELINUX=disabled" >> /etc/selinux/config + else + modify_config "SELINUX" "disabled" /etc/selinux/config + fi + echo "---------以上配置在重启后生效---------" +} + +################################################################################ +# Function Name: apply_patch +# Description : 转码及内核补丁合入。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function apply_patch(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 4 合入kernel补丁 ]]]]]]]]]]]]]]]]]]]]" + + cd "${work_dir}" || exit + [ -e "linux-${KERNEL_VERSION}" ] && rm -rf linux-${KERNEL_VERSION} + [ -e "linux-kernel-${KERNEL_VERSION}" ] && rm -rf linux-kernel-${KERNEL_VERSION} + echo "---------解压kernel源码---------" + tar -zxvf "linux-${KERNEL_VERSION}.tar.gz" > /dev/null 2>&1 || error "linux-${KERNEL_VERSION}.tar.gz解压失败" + mv linux-${KERNEL_VERSION} linux-kernel-${KERNEL_VERSION} + [ -e "${kernel_dir}/linux-kernel-${KERNEL_VERSION}" ] && rm -rf ${kernel_dir}/linux-kernel-${KERNEL_VERSION} + cp -r linux-kernel-${KERNEL_VERSION} ${kernel_dir} || exit + touch ${kernel_dir}/linux-kernel-${KERNEL_VERSION}/.scmversion + + cd "${kbox_dir}"/patchForExagear/hostOS/ || exit + cp 0001-exagear-kernel-module.patch "${kernel_dir}"/linux-kernel-"${KERNEL_VERSION}" || exit + + cd "${kbox_dir}"/patchForKernel/"${OS_VERSION}"/kernel_"${KERNEL_VERSION}"/ || exit + cp *.patch "${kernel_dir}"/linux-kernel-"${KERNEL_VERSION}" || exit + + cd "${kernel_dir}"/linux-kernel-"${KERNEL_VERSION}"/ || exit + exagear_patch_name=$(ls | grep .patch | grep -m 1 module) + echo "-- patching ${exagear_patch_name}" + patch -p1 < ${exagear_patch_name} || exit + patches_list=$(ls | grep -v module | grep .patch) + for patch_name in ${patches_list[@]} + do + echo "-- patching ${patch_name}" + patch -p1 < ${patch_name} || exit + done +} + +################################################################################ +# Function Name: build_install_kernel +# Description : 内核及内核模块编译。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function build_install_kernel(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 5 编译&安装kernel ]]]]]]]]]]]]]]]]]]]]" + echo "---------内核编译---------" + cd "${kernel_dir}"/linux-kernel-"${KERNEL_VERSION}"/ || exit + cp /boot/config-$(uname -r) .config || exit + + (echo -e \'\\0x65\'; echo -e \'\\0x79\') | make menuconfig > /dev/null 2>&1 + sleep 1 + + [ ! -e ".config" ] && error "config file not found" + modify_config "CONFIG_STAGING" "y" .config + modify_config "CONFIG_ANDROID" "y" .config + modify_config "CONFIG_ASHMEM" "y" .config + modify_config "CONFIG_ANDROID_BINDER_IPC" "y" .config + modify_config "CONFIG_ANDROID_BINDERFS" "y" .config + modify_config "CONFIG_ANDROID_ALARM" "y" .config + modify_config "CONFIG_ANON_VMA_NAME" "y" .config + modify_config "CONFIG_TANGO32" "y" .config + modify_config "CONFIG_VFAT_FS" "y" .config + modify_config "CONFIG_INPUT_UINPUT" "y" .config + modify_config "CONFIG_HISI_PMU" "y" .config + modify_config "CONFIG_SYSTEM_TRUSTED_KEYS" "\"\"" .config + modify_config "CONFIG_DEBUG_INFO" "n" .config + modify_config "CONFIG_LOCALVERSION" "\"\"" .config + modify_config "CONFIG_SYSTEM_REVOCATION_KEYS" "\"\"" .config + + (echo -e \'\\0x65\'; echo -e \'\\0x79\') | make menuconfig > /dev/null 2>&1 + sleep 1 + + echo "---------内核编译---------" + make clean && make -j"${cpu_num}" + [ $? -ne 0 ] && error "内核编译失败" + echo "---------安装模块---------" + make modules_install + [ $? -ne 0 ] && error "模块安装失败" + echo "---------安装内核---------" + make install + [ $? -ne 0 ] && error "内核安装失败" + echo "---------更新启动项---------" + grub_default=$(< /boot/grub/grub.cfg grep "Ubuntu, with Linux"|awk -F \' '{print i++ ":"$2}'|grep -v "recovery mode"|grep -w ""${KERNEL_VERSION}"$"|awk -F ':' '{print $1}') + sed -i "s/GRUB_DEFAULT=.*/GRUB_DEFAULT=\"1\> ${grub_default}\"/g" /etc/default/grub + sed -i "s/GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX=\"cgroup_enable=memory swapaccount=1\"/g" /etc/default/grub + update-grub2 + [ $? -ne 0 ] && error "启动项更新失败" +} + +################################################################################ +# Function Name: system_reboot +# Description : 系统重启。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function system_reboot(){ + echo "[[[[[[[[[[[[[[[[[[[[ STEP 6 重启系统 ]]]]]]]]]]]]]]]]]]]]" + local reboot_val + read -p "内核安装与参数配置已完成, 是否重启以生效 [Y/y]" reboot_val + + if [ ${reboot_val} = "Y" ] || [ ${reboot_val} = "y" ] + then + echo "---------系统即将重启---------" + reboot + else + echo "---------请稍后手动重启系统---------" + fi +} + +main(){ + set_run_mode $@ + download_copy_packages + install_dependency + prepare_environment + apply_patch + build_install_kernel + system_reboot +} + +main "$@" +exit 0 diff --git a/deploy_scripts/vm_deploy/auto_deploy_vm/auto_setup_vm.sh b/deploy_scripts/vm_deploy/auto_deploy_vm/auto_setup_vm.sh new file mode 100755 index 0000000000000000000000000000000000000000..2e1e68e5ea7529f548f1705f769c643775325e38 --- /dev/null +++ b/deploy_scripts/vm_deploy/auto_deploy_vm/auto_setup_vm.sh @@ -0,0 +1,23 @@ +mapfile -t cpu_num < <(cat numa_resource_dispatch.json | grep "cpu num" | awk '{print $3}' | sed 's/,$//') +mapfile -t numa_node < <(cat numa_resource_dispatch.json | grep "numa node" | awk '{print $3}'| sed 's/,$//') +mapfile -t vm_name < <(cat numa_resource_dispatch.json | grep "vm name" | awk '{print $3}' | sed 's/,$//' | sed 's/"//g') +mapfile -t vm_xml < <(cat numa_resource_dispatch.json | grep "output file" | awk '{print $3}' | sed 's/,$//' | sed 's/"//g') + + +for i in "${!vm_name[@]}";do + echo "=================${numa_node[$i]}" + echo "=================${cpu_num[$i]}" + echo "virsh define ${vm_xml[i]}" + virsh define ${vm_xml[i]} + sleep 2 + cpu_start=$((${numa_node[$i]} * ${cpu_num[$i]})) + cpu_end=$((${cpu_start} + ${cpu_num[$i]} - 1)) + echo "./setup_vm.sh ${vm_name[$i]} --cputune $cpu_start,$cpu_end" + ./setup_vm.sh ${vm_name[$i]} --cputune $cpu_start,$cpu_end + echo "./setup_vm.sh ${vm_name[$i]} --numatune ${numa_node[$i]}" + ./setup_vm.sh ${vm_name[$i]} --numatune ${numa_node[$i]} + echo "./setup_vm.sh ${vm_name[$i]} --emulatorpin $cpu_start-$cpu_end" + ./setup_vm.sh ${vm_name[$i]} --emulatorpin $cpu_start-$cpu_end + echo "./setup_vm.sh ${vm_name[$i]} --enable_hugepages" + ./setup_vm.sh ${vm_name[$i]} --enable_hugepages +done diff --git a/deploy_scripts/vm_deploy/auto_deploy_vm/collect_data.sh b/deploy_scripts/vm_deploy/auto_deploy_vm/collect_data.sh new file mode 100755 index 0000000000000000000000000000000000000000..72f3dea9d5e2dbd14c540fd6f69c5bcfe3874be1 --- /dev/null +++ b/deploy_scripts/vm_deploy/auto_deploy_vm/collect_data.sh @@ -0,0 +1,16 @@ +qcow2_path=$1 +find $qcow2_path -type f | sort > os_imgs.txt +lspci | grep 0200 | awk '{print $1}' > gpu_pci.txt +lspci -vvv -d 1f4f:0200 | grep NUMA | awk '{print $3}' > gpu_numa.txt +cat /sys/devices/system/node/node*/meminfo | grep HugePages_Total | awk '{print $4}' > numa_Hugepage.txt +find /dev/ | grep nvme | sort | tail -n 4 > disk_partitions.txt +totalcpu=$(lscpu | grep "CPU(s):" | head -n 1 | awk '{print $2}') +numa_cpu=$((totalcpu / 4)) +rm -rf numa_cpu.txt +rm -rf vm_nvram.txt +for i in $(seq 0 3) +do + echo $numa_cpu >> numa_cpu.txt + echo "/var/lib/libvirt/qemu/nvram/vm${i}_VARS.fd" >> vm_nvram.txt +done + diff --git a/deploy_scripts/vm_deploy/auto_deploy_vm/dispatch_vm_resource.py b/deploy_scripts/vm_deploy/auto_deploy_vm/dispatch_vm_resource.py new file mode 100755 index 0000000000000000000000000000000000000000..34e336ad97da82b737a0d5bdbc8352659fb72ecc --- /dev/null +++ b/deploy_scripts/vm_deploy/auto_deploy_vm/dispatch_vm_resource.py @@ -0,0 +1,68 @@ +import numpy as np +import sys +import json +import xml.etree.ElementTree as ET +from collections import defaultdict + +# get gpu pci, vf nic pci, cpu nums, numa hugepage size from txt file +data_txt = np.loadtxt("gpu_numa.txt", dtype=int) +data = data_txt.tolist() + +print(data) + +numa_cpus_txt = np.loadtxt("numa_cpu.txt", dtype=int) +numa_cpus = numa_cpus_txt.tolist() +print("numa cpus:", numa_cpus) + +numa_pages_txt = np.loadtxt("numa_Hugepage.txt", dtype=int) +numa_pages = numa_pages_txt.tolist() +print("numa pages:", numa_pages) + + +with open("vfNic.txt", "r") as file: + vf_nics = [line.strip().replace('"', '') for line in file] +print(vf_nics) + +with open("gpu_pci.txt", "r") as file: + data1 = [line.strip().replace('"', '') for line in file] +print(data1) + +with open("os_imgs.txt", "r") as file: + os_imgs = [line.strip().replace('"', '') for line in file] +print(os_imgs) + +with open("vm_nvram.txt", "r") as file: + vm_nvram = [line.strip().replace('"', '') for line in file] +print(vm_nvram) + +with open("disk_partitions.txt", "r") as file: + disk_partitions = [line.strip().replace('"', '') for line in file] +print(disk_partitions) + +mapping = defaultdict(list) +for i in range(len(data)): + mapping[data[i]].append(data1[i]) + +numa_pci = dict(mapping) +print(numa_pci) + +input_xml = sys.argv[1] +output_xml = ["Numa0.xml", "Numa1.xml", "Numa2.xml", "Numa3.xml"] +dict_key = ["numa0", "numa1", "numa2", "numa3"] +vm_name = ["vm0", "vm1", "vm2", "vm3"] +source_dict = {} + +for index in range(len(vm_name)): + if index > len(vf_nics): + print("vf nic is not enough") + break + arr = [disk_partitions[index]] + numa_dict = {"vm name":vm_name[index], "numa node": index, "cpu num": numa_cpus[index], "memory(huge pages)": numa_pages[index], "os img": os_imgs[index], "vm nvram": vm_nvram[index] , "disk partitions": arr, "gpu pci": numa_pci.get(index, ""), "vf_nic pci": vf_nics[index], "input file": str(input_xml), "output file": output_xml[index]} + source_dict.update({dict_key[index]: numa_dict}) + +OutputPath = './numa_resource_dispatch.json' +f = open(OutputPath, 'w', encoding='utf-8') +a = json.dumps(source_dict, sort_keys=False, indent=4, ensure_ascii=False) +f.write(a) +f.close() + diff --git a/deploy_scripts/vm_deploy/auto_deploy_vm/modify_vm_xml.py b/deploy_scripts/vm_deploy/auto_deploy_vm/modify_vm_xml.py new file mode 100644 index 0000000000000000000000000000000000000000..95cb82b6123f8f5e938ad98b6ad2751cd8f51917 --- /dev/null +++ b/deploy_scripts/vm_deploy/auto_deploy_vm/modify_vm_xml.py @@ -0,0 +1,102 @@ +import numpy as np +import json +import copy +import xml.etree.ElementTree as ET +from collections import defaultdict + +#modify gpu_pci, vf_nic in vm xml +def modify_xml(vm_name, input_xml, output_xml, numa_node, numa_cpu, numa_page, os_img, vm_nvram, disk_partitions, gpu_pci, vf_nic): + print("modify xml", input_xml) + tree = ET.parse(input_xml) + root = tree.getroot() + + vm_id = root.find(".//name") + if vm_id is not None: + vm_id.text = vm_name + + memory_elem = root.find(".//memory") + memValue = str(numa_page * 1024 * 1024) + if memory_elem is not None: + memory_elem.text = memValue + + devices_element = root.find(".//devices") + disk_index = 0; + os_img_used = 0; + for disk in root.findall(".//disk"): + print("len of disk_partition:", len(disk_partitions)) + if disk_index >= len(disk_partitions) and os_img_used == 1: + devices_element.remove(disk) + continue + driver = disk.find("driver") + boot = disk.find("boot") + source = disk.find("source") + if driver is not None and driver.get("type") == "qcow2": + print("config os_img") + source.set("file", os_img) + os_img_used = 1 + if disk.get("type") == "block": + source.set("dev", disk_partitions[disk_index]) + disk_index += 1 + + + numatune = root.find(".//numatune") + if numatune is not None: + memory = numatune.find("memory") + if memory is not None: + memory.set("nodeset", numa_node) + + cur_memory_elem = root.find(".//currentMemory") + if cur_memory_elem is not None: + cur_memory_elem.text = memValue + + vcpu_elem = root.find(".//vcpu") + if vcpu_elem is not None: + vcpu_elem.text = str(numa_cpu) + + nvram = root.find(".//nvram") + if nvram is not None: + nvram.text = vm_nvram + + hostdev_elements = root.findall(".//hostdev") + for i, hostdev in enumerate(hostdev_elements): + source = hostdev.find("source") + if source is not None: + address = source.find("address") + if i < len(gpu_pci): + pci = gpu_pci[i] + elif i == len(gpu_pci): + pci = vf_nic + elif i > len(gpu_pci): + devices_element.remove(hostdev) + continue + parts = pci.replace(".", ":").split(":") + hex_values = [f"0x{part.zfill(2)}" for part in parts] + bus_value = address.get("bus") + print("bus_value is ", address.get("bus"), "; change to ", hex_values[0]) + print("slot_value is ", address.get("slot"), "; change to ", hex_values[1]) + print("function_value is ", address.get("function"), "; change to ", hex_values[2]) + address.set("bus", hex_values[0]) + address.set("slot", hex_values[1]) + address.set("function", hex_values[2]) + + tree.write(output_xml) + + +with open("numa_resource_dispatch.json", "r", encoding="utf-8") as file: + data = json.load(file) + +for key, value in data.items(): + vm_name = value["vm name"] + numa_node = str(value["numa node"]) + cpu_num = value["cpu num"] + huge_pages = value["memory(huge pages)"] + os_img = value["os img"] + vm_nvram = value["vm nvram"] + disk_partitions = value["disk partitions"] + print(disk_partitions) + numa_gpu_pci = value["gpu pci"] + vf_nic_pci = value["vf_nic pci"] + input_file = value["input file"] + output_file = value["output file"] + modify_xml(vm_name, input_file, output_file, numa_node, cpu_num, huge_pages, os_img, vm_nvram, disk_partitions, numa_gpu_pci, vf_nic_pci) + diff --git a/deploy_scripts/vm_deploy/auto_deploy_vm/start_vm.sh b/deploy_scripts/vm_deploy/auto_deploy_vm/start_vm.sh new file mode 100755 index 0000000000000000000000000000000000000000..8479aa4685295bd911cc3ee7a8a3521a7acb98ee --- /dev/null +++ b/deploy_scripts/vm_deploy/auto_deploy_vm/start_vm.sh @@ -0,0 +1,7 @@ +mapfile -t vm_name < <(cat numa_resource_dispatch.json | grep "vm name" | awk '{print $3}' | sed 's/,$//' | sed 's/"//g') + + +for i in "${!vm_name[@]}";do + echo "virsh start ${vm_name[i]}" + virsh start ${vm_name[i]} +done diff --git a/deploy_scripts/vm_deploy/auto_deploy_vm/vfNic_generate.sh b/deploy_scripts/vm_deploy/auto_deploy_vm/vfNic_generate.sh new file mode 100755 index 0000000000000000000000000000000000000000..9b417a73c9b0534ff520bb2706bc7f483d0c3d99 --- /dev/null +++ b/deploy_scripts/vm_deploy/auto_deploy_vm/vfNic_generate.sh @@ -0,0 +1,11 @@ +nic=$(ip a | grep 192 | head -n 1 | awk '{print $NF}') +echo "nic: $nic" +pci=$(lshw -c network -businfo | grep -w ${nic} | awk '{print $1}' | cut -d'@' -f2) +echo "pci: $pci" + +vfs_max=$(cat /sys/bus/pci/devices/${pci}/sriov_totalvfs) +echo "max vfs : $vfs_max" + +echo $vfs_max > /sys/bus/pci/devices/${pci}/sriov_numvfs + +lshw -c network -businfo | grep -w "Virtual Function" | awk '{print $1}' | cut -d':' -f2- > vfNic.txt diff --git a/deploy_scripts/vm_deploy/auto_deploy_vm/vm0.xml b/deploy_scripts/vm_deploy/auto_deploy_vm/vm0.xml new file mode 100644 index 0000000000000000000000000000000000000000..6929e339defa96a4f9ff4cae2d138cc5da7b6a68 --- /dev/null +++ b/deploy_scripts/vm_deploy/auto_deploy_vm/vm0.xml @@ -0,0 +1,296 @@ + + vm0 + 209715200 + 209715200 + + + + 80 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + hvm + /usr/share/edk2/aarch64/QEMU_EFI-pflash.raw + /var/lib/libvirt/qemu/nvram/vm0_VARS.fd + + + + + + + + + + + destroy + restart + destroy + + /usr/libexec/qemu-kvm + + + + +
+ + + + + +
+ + + + + +
+ + +
+ + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + +
+ + + + + + + + + + + +
+ + +
+ + +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + + diff --git a/deploy_scripts/vm_deploy/patchForKernel/general.patch b/deploy_scripts/vm_deploy/patchForKernel/general.patch new file mode 100644 index 0000000000000000000000000000000000000000..fae808e484607d5a2ff3b962d2cf60d067cd39d5 --- /dev/null +++ b/deploy_scripts/vm_deploy/patchForKernel/general.patch @@ -0,0 +1,79 @@ +diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h +index f5dff6d40..3130b77c0 100644 +--- a/arch/arm64/include/asm/kvm_pgtable.h ++++ b/arch/arm64/include/asm/kvm_pgtable.h +@@ -46,6 +46,7 @@ enum kvm_pgtable_prot { + KVM_PGTABLE_PROT_R = BIT(2), + + KVM_PGTABLE_PROT_DEVICE = BIT(3), ++ KVM_PGTABLE_PROT_NORMAL_NC = BIT(4), + + KVM_PGTABLE_PROT_PBHA0 = BIT(59), + KVM_PGTABLE_PROT_PBHA1 = BIT(60), +diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h +index 644cfa328..1923b28c8 100644 +--- a/arch/arm64/include/asm/memory.h ++++ b/arch/arm64/include/asm/memory.h +@@ -143,6 +143,7 @@ + * Memory types for Stage-2 translation + */ + #define MT_S2_NORMAL 0xf ++#define MT_S2_NORMAL_NC 0x5 + #define MT_S2_DEVICE_nGnRE 0x1 + + /* +@@ -150,6 +151,7 @@ + * Stage-2 enforces Normal-WB and Device-nGnRE + */ + #define MT_S2_FWB_NORMAL 6 ++#define MT_S2_FWB_NORMAL_NC 5 + #define MT_S2_FWB_DEVICE_nGnRE 1 + + #ifdef CONFIG_ARM64_4K_PAGES +diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c +index a78928951..b24f643ed 100644 +--- a/arch/arm64/kvm/hyp/pgtable.c ++++ b/arch/arm64/kvm/hyp/pgtable.c +@@ -444,10 +444,18 @@ static int stage2_map_set_prot_attr(enum kvm_pgtable_prot prot, + struct stage2_map_data *data) + { + bool device = prot & KVM_PGTABLE_PROT_DEVICE; +- kvm_pte_t attr = device ? PAGE_S2_MEMATTR(DEVICE_nGnRE) : +- PAGE_S2_MEMATTR(NORMAL); ++ bool normal_nc = prot & KVM_PGTABLE_PROT_NORMAL_NC; ++ kvm_pte_t attr; + u32 sh = KVM_PTE_LEAF_ATTR_LO_S2_SH_IS; + ++ if (device) ++ attr = PAGE_S2_MEMATTR(DEVICE_nGnRE); ++ else if (normal_nc) ++ attr = PAGE_S2_MEMATTR(NORMAL_NC); ++ else ++ attr = PAGE_S2_MEMATTR(NORMAL); ++ ++ + if (!(prot & KVM_PGTABLE_PROT_X)) + attr |= KVM_PTE_LEAF_ATTR_HI_S2_XN; + else if (device) +diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c +index 6fa92a143..94a07ff7e 100644 +--- a/arch/arm64/kvm/mmu.c ++++ b/arch/arm64/kvm/mmu.c +@@ -503,7 +503,7 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, + int ret = 0; + struct kvm_mmu_memory_cache cache = { 0, __GFP_ZERO, NULL, }; + struct kvm_pgtable *pgt = kvm->arch.mmu.pgt; +- enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_DEVICE | ++ enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_NORMAL_NC | + KVM_PGTABLE_PROT_R | + (writable ? KVM_PGTABLE_PROT_W : 0); + +@@ -933,7 +933,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + } + + if (device) +- prot |= KVM_PGTABLE_PROT_DEVICE; ++ prot |= KVM_PGTABLE_PROT_NORMAL_NC; + else if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC)) + prot |= KVM_PGTABLE_PROT_X; + diff --git a/deploy_scripts/vm_deploy/setup_vm.sh b/deploy_scripts/vm_deploy/setup_vm.sh new file mode 100755 index 0000000000000000000000000000000000000000..fe087ef35c8a42cba180b1714e169874d8862179 --- /dev/null +++ b/deploy_scripts/vm_deploy/setup_vm.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +function cputune() +{ + local domain="$1" + local start="$2" + local end="$3" + + local vcpu_idx=0 + for i in $(seq $start $end); do + virsh vcpupin $domain $vcpu_idx $i --config + vcpu_idx=$((vcpu_idx + 1)) + done + + virsh vcpupin $domain +} + +function numatune() +{ + local domain="$1" + local nodeset="$2" + virsh numatune $domain --mode strict --nodeset $nodeset --config + virsh numatune $domain +} + +function emulatorpin() +{ + local domain="$1" + local cpulist="$2" + virsh emulatorpin $domain --cpulist "$cpulist" --config + virsh emulatorpin $domain +} + +function enable_hugepages() +{ + local domain="$1" + virt-xml $1 --edit --memorybacking hugepages=on +} + +function usage() +{ +cat </dev/null 2>&1 + if [ $? -ne 0 ]; then + echo -e "\033[1;31m[ERROR] nvme command unavailable, please install nvme-cli. \033[0m" + exit -1 + fi +} + +function check_vpu() +{ + check_nvme_command + cmd="nvme list" + output=$($cmd) + + if echo "$output" | grep -q "T432"; then + echo -e "\033[1;36m[INFO] make image for T432 \033[0m" + DOCKER_FILE_CANDIDATE=${CUR_PATH}/Dockerfile_T432 + elif echo "$output" | grep -q "QuadraT2A"; then + echo -e "\033[1;36m[INFO] make image for QuadraT2A \033[0m" + DOCKER_FILE_CANDIDATE=${CUR_PATH}/Dockerfile_QuadraT2A + else + echo -e "\033[1;36m[INFO] make image without vpu \033[0m" + fi + + # 判断Dockerfile是否存在 + if [ ! -f "${DOCKER_FILE}" ]; then + echo -e "\033[1;31m[ERROR] ${DOCKER_FILE} is not exist. \033[0m" && return -1 + fi + + cp ${DOCKER_FILE_CANDIDATE} ${DOCKER_FILE} +} +# 前置条件验证 +function check_env() +{ + check_vpu + + # 判断DECODE原型包是否存在 + if [ ! -f "${DEMO_NETINT_PACKAGE}" ]; then + echo -e "\033[1;31m[ERROR] ${DEMO_NETINT_PACKAGE} is not exist. \033[0m" && return -1 + fi + + # 判断DECODE原型包目录是否存在,若存在则删除重建 + if [ -d "${TMP_DEMO_DIR}" ]; then + rm -rf ${TMP_DEMO_DIR} + fi + mkdir -p ${TMP_DEMO_DIR} + + # 解压DECODE原型包(注意:通过--no-same-owner保证解压后的文件属组为当前操作用户(root)文件属组) + cmd="tar --no-same-owner -zxvf ${DEMO_NETINT_PACKAGE} -C ${TMP_DEMO_DIR}" + echo -e "\033[1;36m[INFO] "$cmd" \033[0m" + $cmd > /dev/null +} + +# 制作镜像 +function make_image() +{ + if [ -n "$1" ]; then + DOCKER_IMAGE_KBOX="$1" + fi + if [ -n "$2" ]; then + DOCKER_IMAGE_KBOX_LATEST="$2" + fi + cmd="docker build --build-arg KBOX_IMAGE=${DOCKER_IMAGE_KBOX} -t ${DOCKER_IMAGE_KBOX_LATEST} ." + echo -e "\033[1;36m[INFO] "$cmd" \033[0m" + $cmd + wait +} + +function main() +{ + echo -e "\033[1;36m[INFO] Begin to make image \033[0m" + # 构建镜像 + local start_time=$(date +%s) + local end_time=0 + + check_env + [ ${?} != 0 ] && echo -e "\033[1;31m[ERROR] Failed to check environment. \033[0m" && exit -1 + + make_image "$@" + [ ${?} != 0 ] && echo -e "\033[1;31m[ERROR] Failed to make image. \033[0m" && exit -1 + + # 制作镜像时间统计 + end_time=$(date +%s) + time_interval=$((${end_time}-${start_time})) + echo -e "\033[1;36m[INFO] End to make image from ${DOCKER_IMAGE_KBOX} to ${DOCKER_IMAGE_KBOX_LATEST} \033[0m" + echo -e "\033[1;36m[INFO] Make image takes ${time_interval} seconds. \033[0m" +} + +main "$@" diff --git a/make_img_sample/kbox11_android_build/00_kbox_prepare.sh b/make_img_sample/kbox11_android_build/00_kbox_prepare.sh new file mode 100644 index 0000000000000000000000000000000000000000..79b9a69d3396cf70c029921543e25f9f8e59ccba --- /dev/null +++ b/make_img_sample/kbox11_android_build/00_kbox_prepare.sh @@ -0,0 +1,414 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2020-2020. All rights reserved. +# File Name: 00_kbox_prepare.sh +# Description: 源码相关准备. +# Usage: bash 00_kbox_prepare.sh +# ******************************************************************************** # + +#set -x +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ] +then + bash "$0" "$@" + exit $? +fi + +# 检查参数是否传递正确 +if [ $# -ne 3 ]; then + echo "Usage: $0 " + exit 1 +fi + +# 获取传递给脚本的参数 +CURRENT_DIR=$1 +AOSP_PATH=$2 +PACKAGE_PATH=$3 + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +export GIT_SSL_NO_VERIFY=1 +mkdir -p ~/bin +PATH=~/bin:$PATH +cpu_num=$(< /proc/cpuinfo grep -c "processor") + +# 关闭ubuntu的Daemons using outdated libraries服务重启提示弹窗 +echo "\$nrconf{kernelhints} = 0;" >> /etc/needrestart/needrestart.conf +echo "\$nrconf{restart} = 'l';" >> /etc/needrestart/needrestart.conf + +meson_version="0.63.2" +meson_dir="meson-${meson_version}" +buildtools_path="$CURRENT_DIR/buildtools" + +mesa_version="22.1.7" +llvm_version="13.0.1" +libdrm_version="2.4.111" +libva_version="2.14.0" + +mesa_src="mesa-${mesa_version}.tar.xz" +llvm_src="llvm-${llvm_version}.src.tar.xz" +libdrm_src="drm-libdrm-${libdrm_version}.zip" +libva_src="${libva_version}.tar.gz" +vmi_cloudphone_src="vmi-CloudPhone" + +################################################################################ +# Function Name: clean +# Description : 清理依赖目录 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function clean(){ + echo "----------清理当前目录下的buildtools目录----------" + rm -rf $CURRENT_DIR/buildtools || { error "无法删除buildtools目录"; } + echo "----------清理当前目录下的sourcecode目录----------" + rm -rf $CURRENT_DIR/sourcecode || { error "无法删除sourcecode目录"; } + echo "----------清理成功----------" +} + +################################################################################ +# Function Name: build_dependency +# Description : 安装编译构建所需依赖 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function build_dependency(){ + echo "----------开始安装编译构建所需依赖----------" + apt update || error "apt update 失败" + sudo apt-get -y install libgl1-mesa-dev || error "libgl1-mesa-dev 安装失败" + sudo apt-get -y install g++-multilib || error "g++-multilib 安装失败" + sudo apt-get -y install wget || error "wget 安装失败" + sudo apt-get -y install git || error "git 安装失败" + sudo apt-get -y install flex || error "flex 安装失败" + sudo apt-get -y install bison || error "bison 安装失败" + sudo apt-get -y install gperf || error "gperf 安装失败" + sudo apt-get -y install build-essential || error "build-essential 安装失败" + sudo apt-get -y install tofrodos || error "tofrodos 安装失败" + sudo apt-get -y install python3-markdown || error "python3-markdown 安装失败" + sudo apt-get -y install xsltproc || error "xsltproc 安装失败" + sudo apt-get -y install dpkg-dev || error "dpkg-dev 安装失败" + sudo apt-get -y install libsdl1.2-dev || error "libsdl1.2-dev 安装失败" + sudo apt-get -y install git-core || error "git-core 安装失败" + sudo apt-get -y install gnupg || error "gnupg 安装失败" + sudo apt-get -y install zip || error "zip 安装失败" + sudo apt-get -y install curl || error "curl 安装失败" + sudo apt-get -y install zlib1g-dev || error "zlib1g-dev 安装失败" + sudo apt-get -y install gcc-multilib || error "gcc-multilib 安装失败" + sudo apt-get -y install libc6-dev-i386 || error "libc6-dev-i386 安装失败" + sudo apt-get -y install libx11-dev || error "libx11-dev 安装失败" + sudo apt-get -y install libncurses5-dev || error "libncurses5-dev 安装失败" + sudo apt-get -y install lib32ncurses5-dev || error "lib32ncurses5-dev 安装失败" + sudo apt-get -y install x11proto-core-dev || error "x11proto-core-dev 安装失败" + sudo apt-get -y install libxml2-utils || error "libxml2-utils 安装失败" + sudo apt-get -y install unzip || error "unzip 安装失败" + sudo apt-get -y install m4 || error "m4 安装失败" + sudo apt-get -y install lib32z-dev || error "lib32z-dev 安装失败" + sudo apt-get -y install ccache || error "ccache 安装失败" + sudo apt-get -y install libssl-dev || error "libssl-dev 安装失败" + sudo apt-get -y install gettext || error "gettext 安装失败" + sudo apt-get -y install python3-mako || error "python3-mako 安装失败" + sudo apt-get -y install libncurses5 || error "libncurses5 安装失败" + sudo apt-get -y install python3-chardet || error "python3-chardet 安装失败" + sudo apt-get -y install python3-markupsafe || error "python3-markupsafe 安装失败" + sudo apt-get -y install python3-packaging || error "python3-packaging 安装失败" + sudo apt-get -y install python3-pkg-resources || error "python3-pkg-resources 安装失败" + sudo apt-get -y install python3-pygments || error "python3-pygments 安装失败" + sudo apt-get -y install python3-pyparsing || error "python3-pyparsing 安装失败" + sudo apt-get -y install python3-six || error "python3-six 安装失败" + sudo apt-get -y install python3-yaml || error "python3-yaml 安装失败" + sudo apt-get -y install python2 || error "python2 安装失败" + sudo apt-get -y install python2.7 || error "python2.7 安装失败" + sudo apt-get -y install python3 || error "python3 安装失败" + sudo apt-get -y install python3-apport || error "python3-apport 安装失败" + sudo apt-get -y install python3-apt || error "python3-apt 安装失败" + sudo apt-get -y install python3-attr || error "python3-attr 安装失败" + sudo apt-get -y install python3-automat || error "python3-automat 安装失败" + sudo apt-get -y install python3-blinker || error "python3-blinker 安装失败" + sudo apt-get -y install python3-certifi || error "python3-certifi 安装失败" + sudo apt-get -y install python3-cffi-backend || error "python3-cffi-backend 安装失败" + sudo apt-get -y install python3-click || error "python3-click 安装失败" + sudo apt-get -y install python3-colorama || error "python3-colorama 安装失败" + sudo apt-get -y install python3-commandnotfound || error "python3-commandnotfound 安装失败" + sudo apt-get -y install python3-configobj || error "python3-configobj 安装失败" + sudo apt-get -y install python3-constantly || error "python3-constantly 安装失败" + sudo apt-get -y install python3-cryptography || error "python3-cryptography 安装失败" + sudo apt-get -y install python3-dbus || error "python3-dbus 安装失败" + sudo apt-get -y install python3-debconf || error "python3-debconf 安装失败" + sudo apt-get -y install python3-debian || error "python3-debian 安装失败" + sudo apt-get -y install python3-dev || error "python3-dev 安装失败" + sudo apt-get -y install python3-distro || error "python3-distro 安装失败" + sudo apt-get -y install python3-distro-info || error "python3-distro-info 安装失败" + sudo apt-get -y install python3-distupgrade || error "python3-distupgrade 安装失败" + sudo apt-get -y install python3-distutils || error "python3-distutils 安装失败" + sudo apt-get -y install python3-entrypoints || error "python3-entrypoints 安装失败" + sudo apt-get -y install python3-gdbm || error "python3-gdbm 安装失败" + sudo apt-get -y install python3-gi || error "python3-gi 安装失败" + sudo apt-get -y install python3-hamcrest || error "python3-hamcrest 安装失败" + sudo apt-get -y install python3-httplib2 || error "python3-httplib2 安装失败" + sudo apt-get -y install python3-hyperlink || error "python3-hyperlink 安装失败" + sudo apt-get -y install python3-idna || error "python3-idna 安装失败" + sudo apt-get -y install python3-importlib-metadata || error "python3-importlib-metadata 安装失败" + sudo apt-get -y install python3-incremental || error "python3-incremental 安装失败" + sudo apt-get -y install python3-jinja2 || error "python3-jinja2 安装失败" + sudo apt-get -y install python3-json-pointer || error "python3-json-pointer 安装失败" + sudo apt-get -y install python3-jsonpatch || error "python3-jsonpatch 安装失败" + sudo apt-get -y install python3-jsonschema || error "python3-jsonschema 安装失败" + sudo apt-get -y install python3-jwt || error "python3-jwt 安装失败" + sudo apt-get -y install python3-keyring || error "python3-keyring 安装失败" + sudo apt-get -y install python3-launchpadlib || error "python3-launchpadlib 安装失败" + sudo apt-get -y install python3-lazr.restfulclient || error "python3-lazr.restfulclient 安装失败" + sudo apt-get -y install python3-lazr.uri || error "python3-lazr.uri 安装失败" + sudo apt-get -y install python3-lib2to3 || error "python3-lib2to3 安装失败" + sudo apt-get -y install python3-more-itertools || error "python3-more-itertools 安装失败" + sudo apt-get -y install python3-nacl || error "python3-nacl 安装失败" + sudo apt-get -y install python3-netifaces || error "python3-netifaces 安装失败" + sudo apt-get -y install python3-newt || error "python3-newt 安装失败" + sudo apt-get -y install python3-oauthlib || error "python3-oauthlib 安装失败" + sudo apt-get -y install python3-openssl || error "python3-openssl 安装失败" + sudo apt-get -y install python3-pip || error "python3-pip 安装失败" + sudo apt-get -y install python3-problem-report || error "python3-problem-report 安装失败" + sudo apt-get -y install python3-pyasn1 || error "python3-pyasn1 安装失败" + sudo apt-get -y install python3-pyasn1-modules || error "python3-pyasn1-modules 安装失败" + sudo apt-get -y install python3-pymacaroons || error "python3-pymacaroons 安装失败" + sudo apt-get -y install python3-pyrsistent || error "python3-pyrsistent 安装失败" + sudo apt-get -y install python3-requests || error "python3-requests 安装失败" + sudo apt-get -y install python3-requests-unixsocket || error "python3-requests-unixsocket 安装失败" + sudo apt-get -y install python3-secretstorage || error "python3-secretstorage 安装失败" + sudo apt-get -y install python3-serial || error "python3-serial 安装失败" + sudo apt-get -y install python3-service-identity || error "python3-service-identity 安装失败" + sudo apt-get -y install python3-setuptools || error "python3-setuptools 安装失败" + sudo apt-get -y install python3-simplejson || error "python3-simplejson 安装失败" + sudo apt-get -y install python3-software-properties || error "python3-software-properties 安装失败" + sudo apt-get -y install python3-systemd || error "python3-systemd 安装失败" + sudo apt-get -y install python3-twisted || error "python3-twisted 安装失败" + sudo apt-get -y install python3-update-manager || error "python3-update-manager 安装失败" + sudo apt-get -y install python3-urllib3 || error "python3-urllib3 安装失败" + sudo apt-get -y install python3-wadllib || error "python3-wadllib 安装失败" + sudo apt-get -y install python3-wheel || error "python3-wheel 安装失败" + sudo apt-get -y install python3-zipp || error "python3-zipp 安装失败" + sudo apt-get -y install python3-zope.interface || error "python3-zope.interface 安装失败" + sudo apt-get -y install python-is-python3 || error "python-is-python3 安装失败" + sudo apt-get -y install ninja-build || error "ninja-build 安装失败" + sudo apt-get -y install autoconf || error "autoconf 安装失败" + echo "----------安装编译构建所需依赖成功----------" +} + +################################################################################ +# Function Name: aosp_prepare +# Description : 下载并清理aosp源码 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function aosp_prepare(){ + echo "---------清理并准备aosp源码----------" + cd $AOSP_PATH || { error "无法进入AOSP11目录"; } + # 删除上次编译产生的目录 + rm -rf external/mesa || { error "无法删除external/mesa目录"; } + rm -rf external/libdrm || { error "无法删除external/libdrm目录"; } + rm -rf external/llvm70 || { error "无法删除external/llvm70目录"; } + rm -rf vendor || { error "无法删除vendor目录"; } + # 删除纯净源码中external/mesa3d, external/libdrm, device/generic/arm64三个文件夹 + rm -rf external/mesa3d || { error "无法删除external/mesa3d目录"; } + rm -rf external/libdrm || { error "无法删除external/libdrm目录"; } + rm -rf device/generic/arm64 || { error "无法删除device/generic/arm64目录"; } + echo "---------aosp源码准备完成----------" +} + +################################################################################ +# Function Name: make_buildtools +# Description : 检查buildtools目录是否存在 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function make_buildtools(){ + # 检查buildtools目录是否存在,如果不存在就创建,并为目录拥有者添加读、写和可执行权限 + cd $CURRENT_DIR || error "切换到主目录失败" + if [ ! -d $buildtools_path ]; then + mkdir $buildtools_path || error "创建buildtools目录失败" + chmod -R 700 $buildtools_path || error "修改buildtools目录权限失败" + fi +} + +################################################################################ +# Function Name: package_prepare +# Description : 检查所需依赖包是否齐全 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function package_prepare(){ + echo "---------开始检查所需依赖包是否齐全----------" + cd $PACKAGE_PATH || error "切换到package目录失败" + if [ ! -f "${meson_dir}.tar.gz" ]; then + error "请确保meson已经上传到$PACKAGE_PATH" + fi + cp -r "${meson_dir}.tar.gz" "$buildtools_path" || error "从package目录拷贝meson压缩包到buildtools目录失败" + + if [ ! -f "$mesa_src" ]; then + error "请确保mesa已经上传到$PACKAGE_PATH" + fi + cp -r "$mesa_src" "$buildtools_path" || error "从package目录拷贝mesa压缩包到buildtools目录失败" + + if [ ! -f "$llvm_src" ]; then + error "请确保llvm已经上传到$PACKAGE_PATH" + fi + cp -r "$llvm_src" "$buildtools_path" || error "从package目录拷贝llvm压缩包到buildtools目录失败" + + if [ ! -f "$libdrm_src" ]; then + error "请确保libdrm已经上传到$PACKAGE_PATH" + fi + cp -r "$libdrm_src" "$buildtools_path" || error "从package目录拷贝libdrm压缩包到buildtools目录失败" + + if [ -f "$libva_src" ]; then + cp -r "$libva_src" "$buildtools_path" || error "从package目录拷贝libva压缩包到buildtools目录失败" + elif [ -f "libva-$libva_src" ]; then + cp -r "libva-$libva_src" "$buildtools_path/$libva_src" || error "从package目录拷贝libva压缩包到buildtools目录失败" + else + error "请确保libva已经上传到$PACKAGE_PATH" + fi + + if [ -f "${vmi_cloudphone_src}.zip" ]; then + cp -r "${vmi_cloudphone_src}.zip" "$buildtools_path" || error "从package目录拷贝cloudphone压缩包到buildtools目录失败" + elif [ -f "CloudPhone.zip" ]; then + cp -r "CloudPhone.zip" "$buildtools_path/${vmi_cloudphone_src}.zip" || error "从package目录拷贝cloudphone压缩包到buildtools目录失败" + else + error "请确保cloudphone已经上传到$PACKAGE_PATH" + fi + echo "---------依赖包齐全----------" +} + +################################################################################ +# Function Name: install_meson +# Description : 安装Meson +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_meson(){ + echo "---------开始安装meson----------" + # 检查并解压Meson + cd $buildtools_path || error "切换到buildtools目录失败" + echo "---------解压meson---------" + tar -xvpf "${meson_dir}.tar.gz" || error "Failed to extract meson" + echo "---------解压完成----------" + + # 检查Meson路径是否已经在PATH中 + meson_path="$buildtools_path/$meson_dir" + if [[ ":$PATH:" != *":$meson_path:"* ]]; then + export PATH=$meson_path:$PATH + echo "Added Meson to PATH in current session" + + # 更新~/.bashrc以确保在新的shell会话中生效 + if ! grep -qF "$meson_path" ~/.bashrc; then + echo "export PATH=$meson_path:\$PATH" >> ~/.bashrc + echo "Added Meson to PATH in ~/.bashrc" + else + echo "Meson path already exists in ~/.bashrc" + fi + else + echo "Meson path already exists in PATH" + fi + + echo "---------安装meson完成----------" +} + +################################################################################ +# Function Name: merge_external +# Description : 安装mesa、llvm、libdrm、libva、Media源码, 并替换到aosp源码中 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +# Mesa +function install_mesa() { + echo "---------开始安装mesa----------" + local filename=$mesa_src + local dir_name="mesa-${mesa_version}" + echo "---------解压mesa---------" + extract_file "$filename" "$dir_name" "mesa" + echo "---------解压完成----------" + echo "---------安装mesa完成----------" +} + +# LLVM +function install_llvm() { + echo "---------开始安装llvm----------" + local filename=$llvm_src + local dir_name="llvm-${llvm_version}.src" + echo "---------解压llvm---------" + extract_file "$filename" "$dir_name" "llvm70" + echo "---------解压完成----------" + echo "---------安装llvm完成----------" +} + +# Libdrm +function install_libdrm() { + echo "---------开始安装libdrm----------" + local filename=$libdrm_src + local dir_name="drm-libdrm-${libdrm_version}" + echo "---------解压libdrm---------" + extract_file "$filename" "$dir_name" "libdrm" + echo "---------解压完成----------" + echo "---------安装libdrm完成----------" +} + +# Libva +function install_libva() { + echo "---------开始安装libva----------" + local filename=$libva_src + local dir_name="libva-${libva_version}" + echo "---------解压livba---------" + extract_file "$filename" "$dir_name" "libva" + echo "---------解压完成----------" + echo "---------安装libva完成----------" +} + +function install_cloudphone() { + echo "---------开始安装cloudphone----------" + local filename=$vmi_cloudphone_src + cd $buildtools_path || error "Failed to switch to buildtools_path" + echo "---------解压cloudphone---------" + unzip "${filename}.zip" || error "Failed to extract cloudphone" + echo "---------解压完成----------" + cp -r ./"$filename"/CloudPhoneService/VideoEngine/Media/video_decoder "$AOSP_PATH/external/" || error "复制 video_decoder 到 aosp 目录失败" + cp -r ./"$filename"/CloudPhoneService/VideoEngine/Media/vendor "$AOSP_PATH/external/" || error "复制 vendor 到 aosp 目录失败" + echo "---------安装cloudphone完成----------" +} + +# 解压文件 +function extract_file() { + local filename=$1 + local dir_name=$2 + local out_dir=$3 + + cd $buildtools_path || error "Failed to switch to buildtools_path" + if [[ "$filename" =~ \.tar\.gz$ ]] || [[ "$filename" =~ \.tar\.xz$ ]]; then + tar -xvf "$filename" || error "Failed to extract $dir_name" + elif [[ "$filename" =~ \.zip$ ]]; then + unzip "$filename" || error "Failed to extract $dir_name" + fi + mv "$dir_name" "$out_dir" || error "Failed to rename $dir_name" + cp -r "$out_dir" "$AOSP_PATH/external/" || error "Failed to copy $out_dir to AOSP" +} + +function merge_external(){ + install_mesa + install_llvm + install_libdrm + install_libva + # 解码适配库, 分支: CloudPhone + install_cloudphone +} + +main(){ + clean + build_dependency + aosp_prepare + make_buildtools + package_prepare + install_meson + merge_external + return 0 +} + +main "$@" diff --git a/make_img_sample/kbox11_android_build/01_apply_patch.sh b/make_img_sample/kbox11_android_build/01_apply_patch.sh new file mode 100644 index 0000000000000000000000000000000000000000..cd28b12a610d24e559f3323b614d86beded39f96 --- /dev/null +++ b/make_img_sample/kbox11_android_build/01_apply_patch.sh @@ -0,0 +1,250 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2020-2020. All rights reserved. +# File Name: 01_apply_patch.sh +# Description: 合入相关修改补丁及源码. +# Usage: bash 01_apply_patch.sh +# ******************************************************************************** # + +#set -x +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ] +then + bash "$0" "$@" + exit $? +fi + +# 检查参数是否传递正确 +if [ $# -ne 3 ]; then + echo "Usage: $0 " + exit 1 +fi + +# 获取传递给脚本的参数 +CURRENT_DIR=$1 +AOSP_PATH=$2 +PACKAGE_PATH=$3 + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +################################################################################ +# Function Name: clean +# Description : 清理依赖目录 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function clean(){ + echo "---------清理dependency目录---------" + rm -rf $CURRENT_DIR/dependency + echo "---------清理dependency目录完成---------" +} + +# 检查补丁是否已应用的函数 +function is_patch_applied(){ + local patch_name=$1 + patch -p1 --dry-run < "$patch_name" > /dev/null 2>&1 + if [ $? -eq 0 ]; then + return 1 # 补丁未应用 + else + return 0 # 补丁已应用 + fi +} + +################################################################################ +# Function Name: check_package +# Description : ExaGear转码补丁包、Kbox二进制软件包是否存在 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function check_package(){ + echo "---------检查patchForExagear目录---------" + if [ ! -d "$CURRENT_DIR/../../patchForExagear" ] + then + error "检查patchForExagear失败, 目录不存在" + fi + + echo "---------检查ExaGear转码补丁包---------" + if [ ! -f "$PACKAGE_PATH/ExaGear_ARM32-ARM64_V2.5.tar.gz" ] + then + error "检查ExaGear_ARM32-ARM64_V2.5.tar.gz转码补丁包失败, 文件不存在" + fi + echo "---------检查ExaGear转码补丁包通过---------" + + echo "---------检查Kbox二进制软件包---------" + if ! find "$PACKAGE_PATH" -maxdepth 1 -type f -name "BoostKit-kbox_*.zip" | grep -q . + then + error "检查BoostKit-kbox二进制软件包检查失败, 文件不存在" + fi + echo "---------检查Kbox二进制软件包通过----------" +} + +################################################################################ +# Function Name: apply_exagear +# Description : 合入转码补丁及文件 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function apply_exagear(){ + # 检查~/dependency目录是否存在, 如果目录不存在就创建,并为目录拥有者添加读、写和可执行权限 + cd "$CURRENT_DIR" || error "无法切换到 $CURRENT_DIR 目录" + if [ ! -d "dependency" ]; then + mkdir "$CURRENT_DIR/dependency" || error "无法创建目录 $CURRENT_DIR/dependency" + chmod -R 700 "$CURRENT_DIR/dependency" || error "无法修改目录权限 $CURRENT_DIR/dependency" + fi + cp -r "../../patchForExagear" "$CURRENT_DIR/dependency" || + error "无法复制文件 patchForExagear 到 $CURRENT_DIR/dependency目录" + cd "$CURRENT_DIR/dependency/patchForExagear/guestOS/aosp11" || + error "无法切换到 $CURRENT_DIR/dependency/patchForExagear/guestOS/aosp11 目录" + cp 0001-exagear-adapt-android-11.0.0_r48.patch "$AOSP_PATH" || + error "无法复制文件 0001-exagear-adapt-android-11.0.0_r48.patch 到 $AOSP_PATH" + cd "$AOSP_PATH" || error "无法切换到 $AOSP_PATH 目录" + + # 检查0001-exagear-adapt-android-11.0.0_r48.patch补丁是否已应用 + if is_patch_applied "0001-exagear-adapt-android-11.0.0_r48.patch"; then + echo "0001-exagear-adapt-android-11.0.0_r48.patch 补丁已应用, 跳过" + else + echo "正在合入补丁 0001-exagear-adapt-android-11.0.0_r48.patch ..." + if patch -p1 < "0001-exagear-adapt-android-11.0.0_r48.patch"; then + echo "补丁 0001-exagear-adapt-android-11.0.0_r48.patch 合入成功" + else + error "补丁 0001-exagear-adapt-android-11.0.0_r48.patch 合入失败" + fi + fi + + cp "$PACKAGE_PATH/ExaGear_ARM32-ARM64_V2.5.tar.gz" "$CURRENT_DIR/dependency" || + error "无法复制文件 $PACKAGE_PATH/ExaGear_ARM32-ARM64_V2.5.tar.gz 到 $CURRENT_DIR/dependency" + # 将ExaGear转码包(ExaGear_ARM32-ARM64_V2.5.tar.gz)上传至“~/dependency”目录请对上传文件、目录的权限进行合理配置, 其他用户属组建议不配置写权限 + cd "$CURRENT_DIR/dependency/" || error "无法切换到 $CURRENT_DIR/dependency/ 目录" + sudo tar -xzvf ExaGear_ARM32-ARM64_V2.5.tar.gz || error "无法解压文件 ExaGear_ARM32-ARM64_V2.5.tar.gz" + sudo chown -R root:root ExaGear_ARM32-ARM64 || error "无法修改目录权限 ExaGear_ARM32-ARM64" + sudo chmod -R 700 ExaGear_ARM32-ARM64 || error "无法修改目录权限 ExaGear_ARM32-ARM64" + # 将“~/dependency/ExaGear_ARM32-ARM64”目录下的preubt_a32a64_a64、preubt_a32a64_x64、ubt_a32a64文件 + # 拷贝至“~/dependency/patchForExagear/guestOS/aosp11/vendor/huawei/exagear/prebuilts”目录 + cd "$CURRENT_DIR/dependency/ExaGear_ARM32-ARM64" || error "无法切换到 $CURRENT_DIR/dependency/ExaGear_ARM32-ARM64 目录" + cp * "$CURRENT_DIR/dependency/patchForExagear/guestOS/aosp11/vendor/huawei/exagear/prebuilts" || + error "无法复制文件到$CURRENT_DIR/dependency/patchForExagear/guestOS/aosp11/vendor/huawei/exagear/prebuilts目录" + # 拷贝“vendor”目录至“aosp”目录下 + cd "$CURRENT_DIR/dependency/patchForExagear/guestOS/aosp11" || + error "无法切换到 $CURRENT_DIR/dependency/patchForExagear/guestOS/aosp11 目录" + cp -r ./vendor "$AOSP_PATH/" || error "无法复制目录 vendor 到 $AOSP_PATH 目录" +} + +################################################################################ +# Function Name: apply_patch +# Description : 合入kbox aosp补丁 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ + +PATCH_DIR=$CURRENT_DIR/dependency/patchForAndroid + +# 合入补丁的函数 +function apply_patch(){ + local patch_name=$1 + local patch_path="${patch_name%-*}" # 从补丁名称中解析出路径 + patch_path="${patch_path//-/\/}" # 将路径中的-替换成/ + + # 完整的目标路径 + local full_path="$AOSP_PATH/$patch_path" + + # 检查目标路径是否存在 + if [ ! -d "$full_path" ]; then + error "目标路径 $full_path 不存在, 跳过补丁 $patch_name" + fi + + # 拷贝补丁到目标目录并应用 + cp "$PATCH_DIR/$patch_name" "$full_path" || error "无法复制补丁文件 $PATCH_DIR/$patch_name 到目标目录 $full_path" + cd "$full_path" || error "无法切换到目标目录 $full_path" + if is_patch_applied "$patch_name"; then + echo "补丁 $patch_name 已经应用, 跳过" + else + if patch -p1 -N < "$patch_name"; then + echo "补丁 $patch_name 合入成功" + else + error "补丁 $patch_name 合入失败" + fi + fi + cd - > /dev/null || error "无法返回上级目录" +} + +function apply_patchs(){ + # 从patch_config.sh文件中读取补丁列表 + if [ ! -f "$CURRENT_DIR/patch_config.sh" ]; then + error "patch_config.sh不存在" + fi + source $CURRENT_DIR/patch_config.sh + # 解压Kbox-AOSP11.zip, 将Kbox-AOSP11文件夹中的“patchForAndroid”目录上传至“~/dependency”目录 + # 请对上传文件、目录的权限进行合理配置, 其他用户属组建议不配置写权限 + cd "$CURRENT_DIR" || error "无法切换到 $CURRENT_DIR 目录" + cp -r "../../patchForAndroid" "$CURRENT_DIR/dependency" || + error "无法复制文件 patchForAndroid 到 $CURRENT_DIR/dependency目录" + cd "$CURRENT_DIR/dependency/patchForAndroid" || error "无法切换到 $CURRENT_DIR/dependency/patchForAndroid 目录" + # 遍历补丁列表并应用每一个补丁 + for patch_name in "${android_patch_wl[@]}"; do + echo "正在合入补丁 $patch_name ..." + if ! apply_patch "$patch_name"; then + error "错误:无法合入补丁 $patch_name." + fi + done + + echo "所有补丁尝试合入完成" +} + +################################################################################ +# Function Name: product_prebuilt +# Description : 合入kbox自研二进制相关源码及补丁 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +# 注意:这里必须保证用户把Android Kbox二进制文件包下载到用户目录下, 不然这里会直接退出 +function product_prebuilt(){ + echo "---------合入二进制内容补丁----------" + cd "$PACKAGE_PATH" || error "无法切换到 $PACKAGE_PATH 目录" + + # 查找匹配的ZIP文件并确认其存在 + zip_files=($(ls BoostKit-kbox_*.zip)) + if [ ${#zip_files[@]} -eq 0 ]; then + error "BoostKit-kbox_*.zip不存在" + fi + + # 复制文件到 $CURRENT_DIR/dependency 目录 + cp "${zip_files[0]}" "$CURRENT_DIR/dependency" || + error "无法复制文件 ${zip_files[0]} 到 $CURRENT_DIR/dependency 目录" + + cd "$CURRENT_DIR/dependency" || error "无法切换到 $CURRENT_DIR/dependency 目录" + + # 解压最新下载的zip文件, 并自动覆盖任何现有文件 + unzip -o "${zip_files[0]}" || error "无法解压 ${zip_files[0]}" + + # 继续解压Kbox-BoostKit-kbox_*-binary.zip + binary_packages=$(ls Kbox-BoostKit-kbox_*-binary.zip) + unzip -o "${binary_packages}" || error "无法解压 $binary_packages" + + # 将二进制内容复制到AOSP源码根目录并处理冲突文件 + cp -rf "$CURRENT_DIR/dependency/product_prebuilt" "$AOSP_PATH/" || error "无法复制文件到 $AOSP_PATH" + rm -rf "$AOSP_PATH/device/generic/goldfish-opengl/system/codecs" + sed -i 's/include $(GOLDFISH_OPENGL_PATH)\/system\/codecs\/omx/#include $(GOLDFISH_OPENGL_PATH)\/system\/codecs\/omx/g' \ + "$AOSP_PATH/device/generic/goldfish-opengl/Android.mk" + + # 在AOSP源码目录创建“vendor/kbox”目录, 拷贝“products”目录至该目录 + mkdir -p "$AOSP_PATH/vendor/kbox" || error "无法创建目录 $AOSP_PATH/vendor/kbox" + chmod -R 700 "$AOSP_PATH/vendor/kbox" || error "无法修改权限为 700 $AOSP_PATH/vendor/kbox" + cp -r "$CURRENT_DIR/dependency/products" "$AOSP_PATH/vendor/kbox" || error "无法复制文件到 $AOSP_PATH/vendor/kbox" + + echo "---------Success----------" +} + +main(){ + clean + check_package + apply_exagear + apply_patchs + product_prebuilt + return 0 +} + +main "$@" diff --git a/make_img_sample/kbox11_android_build/02_compile_aosp.sh b/make_img_sample/kbox11_android_build/02_compile_aosp.sh new file mode 100644 index 0000000000000000000000000000000000000000..be46e7ab11dcdcfa77ce4298d38347444737519f --- /dev/null +++ b/make_img_sample/kbox11_android_build/02_compile_aosp.sh @@ -0,0 +1,111 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2020-2020. All rights reserved. +# File Name: 02_compile_aosp.sh +# Description: android镜像编译及打包. +# Usage: bash 02_compile_aosp.sh +# ******************************************************************************** # + +#set -x +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ]; then + bash "$0" "$@" + exit $? +fi + +# 检查参数是否传递正确 +if [ $# -ne 4 ]; then + echo "Usage: $0 " + exit 1 +fi + +# 获取传递给脚本的参数 +CURRENT_DIR=$1 +AOSP_PATH=$2 +PACKAGE_PATH=$3 +DNS=$4 + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +cpu_num=$(< /proc/cpuinfo grep -c "processor") +hostmemory=$(< /proc/meminfo head -n1|awk '{print $2}') +hostmemory=$((hostmemory/1024/1024/4)) +if [ "${cpu_num}" -gt "${hostmemory}" ] +then + cpu_num=${hostmemory} + echo "java limit j${hostmemory}" +fi + +################################################################################ +# Function Name: aosp_compile +# Description : aosp编译 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function aosp_compile(){ + echo "-----------aosp源码编译-----------" + cd $AOSP_PATH || error "无法切换到AOSP目录" + [ -e ~ ] && rm -rf $AOSP_PATH/out + [ -e ~ ] && rm -rf $AOSP_PATH/create-package.sh + # 编译前修改文件系统为读写模式, 否则视频流无法出流 + sed -i 's|mount rootfs rootfs / remount bind ro|mount rootfs rootfs / remount bind rw|' system/core/rootdir/init.rc + # 修改kbox.mk文件中的网络配置 + sed -i "s|net.dns1=.*|net.dns1=${DNS} \\\\|" $AOSP_PATH/vendor/kbox/products/kbox.mk + # 生成release key + rm -rf ./build/target/product/security/release* + chmod +x ./development/tools/make_key || error "无法设置make_key为可执行" + echo -e "\n" | ./development/tools/make_key build/target/product/security/releasekey '/C=CN/O=Huawei/CN=kunpeng' || + true + source build/envsetup.sh || error "无法加载build环境" + lunch kbox_arm64-user || error "lunch命令执行失败" + export LC_ALL=C + echo "2" > /proc/sys/kernel/randomize_va_space #可信需求 + make clean && make -j${cpu_num} + if [ $? -ne 0 ]; then + error "aosp编译失败" + make clean + fi + echo "---------Success----------" +} + +################################################################################ +# Function Name: create_package +# Description : 镜像打tar包 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function create_package(){ + echo "-----------生成Android镜像包-----------" + cp -r "$CURRENT_DIR/create-package.sh" "$AOSP_PATH/" || error "无法复制create-package.sh到AOSP目录" + cd $AOSP_PATH || error "无法切换到AOSP目录" + chmod +x create-package.sh || error "无法设置create-package.sh为可执行" + ./create-package.sh $AOSP_PATH/out/target/product/arm64/system.img + [ $? -ne 0 ] && error "生成Android镜像失败" + echo "---------Success----------" +} + +################################################################################ +# Function Name: end_of_build +# Description : 生成MD5文件及清理 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function end_of_build(){ + cd $AOSP_PATH || error "无法切换到AOSP目录" + md5sum android.tar > android.tar.md5 + echo $AOSP_PATH/android.tar + echo "---------End----------" +} + +main(){ + aosp_compile + create_package + end_of_build + return 0 +} + +main "$@" \ No newline at end of file diff --git a/make_img_sample/kbox11_android_build/create-package.sh b/make_img_sample/kbox11_android_build/create-package.sh new file mode 100644 index 0000000000000000000000000000000000000000..4bb8e9e0ddb621909b4093faa43ee84d3c95a14b --- /dev/null +++ b/make_img_sample/kbox11_android_build/create-package.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2020-2022. All rights reserved. +# File Name: create-package.sh +# Description: android镜像打tar包. +# Usage: create-package.sh +# ******************************************************************************** # + +set -ex + +system=$1 +destdir=$PWD + +if [ -z "$system" ]; then + echo "Usage: $0 " + exit 1 +fi + +workdir=$(mktemp -d) +rootfs=$workdir/rootfs + +mkdir -p "$rootfs" + +mkdir "$workdir"/system +sudo mount -o loop,ro "$system" "$workdir"/system +sudo cp -ar "$workdir"/system/* "$rootfs"/ +sudo umount "$workdir"/system + +sudo cp -ar "$rootfs"/system/apex/com.android.runtime "$rootfs"/apex/ + +# FIXME +sudo chmod +x "$rootfs"/kbox-init.sh + +if [ -e android.tar ]; then + DATE=$(date +%F_%R) + SAVETO=android-old-$DATE.tar + + echo "#########################################################" + echo "# WARNING: Old android.tar still exists. " + echo "# Moving it to $SAVETO. " + echo "#########################################################" + + mv android.tar "$SAVETO" +fi + +#sudo mksquashfs $rootfs $destdir/android.tar -comp xz -no-xattrs +cd "$rootfs" +sudo tar --numeric-owner -cf "$destdir"/android.tar ./ +sudo chown "$USER":"$USER" "$destdir"/android.tar + +cd "$destdir" +sudo rm -rf "$workdir" diff --git a/make_img_sample/kbox11_android_build/kbox11_android_build.sh b/make_img_sample/kbox11_android_build/kbox11_android_build.sh new file mode 100644 index 0000000000000000000000000000000000000000..351479bc07d60f0ad0e559e4c323e090f81e3bfb --- /dev/null +++ b/make_img_sample/kbox11_android_build/kbox11_android_build.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2020-2020. All rights reserved. +# File Name: kbox11_android_build.sh +# Description: android镜像编译总调用脚本. +# Usage: bash kbox11_android_build.sh +# ******************************************************************************** # + +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ]; then + bash "$0" "$@" + exit $? +fi + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +# root权限执行此脚本 +[ "${UID}" -ne 0 ] && error "请使用root权限执行" + +# 默认工作目录 +CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +[ -z "$CURRENT_DIR" ] && error "获取当前脚本路径失败" +echo "当前脚本的全路径为: $CURRENT_DIR" +# aosp目录, 此路径可修改 +AOSP_PATH="/home/auto_compile/aosp" +PACKAGE_PATH="$CURRENT_DIR/package" + +# 网络配置参数 +DNS= + +# 检查网络配置参数是否为空 +if [ -z "${DNS}" ]; then + error "请确保DNS已设置" +fi + +# 切换到当前目录 +cd "${CURRENT_DIR}" || error "切换到当前脚本所在目录失败" + +# 获取当前系统的硬件架构 +arch=$(uname -m) + +# 检查是否为 x86 架构 +if [[ "$arch" != "x86_64" ]] && [[ "$arch" != "i686" ]]; then + error "当前环境不是 x86 架构" +fi + +main(){ + source "${CURRENT_DIR}/00_kbox_prepare.sh" "${CURRENT_DIR}" "${AOSP_PATH}" "${PACKAGE_PATH}" + [ $? -ne 0 ] && error "00_kbox_prepare.sh执行失败" + echo "00_kbox_prepare OK!!!" + source "${CURRENT_DIR}/01_apply_patch.sh" "${CURRENT_DIR}" "${AOSP_PATH}" "${PACKAGE_PATH}" + [ $? -ne 0 ] && error "01_apply_patch.sh执行失败" + echo "01_apply_patch OK!!!" + source "${CURRENT_DIR}/02_compile_aosp.sh" "${CURRENT_DIR}" "${AOSP_PATH}" "${PACKAGE_PATH}" "${DNS}" + [ $? -ne 0 ] && error "02_compile_aosp.sh执行失败" +} + +main "$@"|tee kbox_image_build.txt +exit 0 diff --git a/make_img_sample/kbox11_android_build/patch_config.sh b/make_img_sample/kbox11_android_build/patch_config.sh new file mode 100644 index 0000000000000000000000000000000000000000..aefa02fb4e8fb88ae376a39caa9eaa4369a3c305 --- /dev/null +++ b/make_img_sample/kbox11_android_build/patch_config.sh @@ -0,0 +1,36 @@ +#!/bin/bash +android_patch_wl=( +bionic-0001.patch +build-make-0001.patch +build-soong-0001.patch +device-generic-goldfish-0001.patch +device-google-cuttlefish-0001.patch +external-libdrm-0001.patch +external-libva-0001.patch +external-llvm70-0001.patch +external-mesa-0001.patch +external-minijail-0001.patch +external-selinux-0001.patch +frameworks-av-0001.patch +frameworks-base-0001.patch +frameworks-native-0001.patch +frameworks-opt-net-wifi-0001.patch +hardware-interfaces-0001.patch +hardware-libhardware-0001.patch +libcore-0001.patch +packages-apps-ManagedProvisioning-0001.patch +packages-apps-SecureElement-0001.patch +packages-apps-Settings-0001.patch +packages-apps-Traceur-0001.patch +packages-providers-DownloadProvider-0001.patch +system-bpf-0001.patch +system-bt-0001.patch +system-core-0001.patch +system-hwservicemanager-0001.patch +system-libhwbinder-0001.patch +system-libvintf-0001.patch +system-memory-lmkd-0001.patch +system-netd-0001.patch +system-sepolicy-0001.patch +system-vold-0001.patch +) diff --git a/make_img_sample/kbox11_iso_build/kbox11_iso_build.sh b/make_img_sample/kbox11_iso_build/kbox11_iso_build.sh new file mode 100644 index 0000000000000000000000000000000000000000..307ece2f0d912125eef7ecb11a1f31e4b70bdcbd --- /dev/null +++ b/make_img_sample/kbox11_iso_build/kbox11_iso_build.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2020-2020. All rights reserved. +# File Name: kbox11_iso_build.sh +# Description: ubuntu iso镜像生成总调用脚本. +# Usage: bash kbox11_iso_build.sh +# ******************************************************************************** # + +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ]; then + bash "$0" "$@" + exit $? +fi + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +cd "${CURRENT_DIR}" || exit +package_dir=$(cd "${CURRENT_DIR}"/../../../ && pwd) +iso_file="ubuntu-20.04.1-live-server-arm64.iso" +export iso_file + +main(){ + bash kbox9_kernel.sh + if [ -f "${package_dir}/${iso_file}" ] + then + bash make_iso.sh + fi +} + +main "$@" +exit 0 diff --git a/make_img_sample/kbox11_iso_build/kbox11_kernel.sh b/make_img_sample/kbox11_iso_build/kbox11_kernel.sh new file mode 100644 index 0000000000000000000000000000000000000000..563ec0d2dcac5881526a6084dee681b0f95eee4c --- /dev/null +++ b/make_img_sample/kbox11_iso_build/kbox11_kernel.sh @@ -0,0 +1,190 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2020-2020. All rights reserved. +# File Name: kbox11_kernel.sh +# Description: kbox11内核编译构建. +# Usage: bash kbox11_kernel.sh +# ******************************************************************************** # + +#set -x +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ]; then + bash "$0" "$@" + exit $? +fi + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +cd "${CURRENT_DIR}" || exit +package_dir=$(cd "${CURRENT_DIR}"/../../../ && pwd) +mkdir -p "${CURRENT_DIR}"/../../../kernel/ +kernel_dir=$(cd "${CURRENT_DIR}"/../../../kernel/ && pwd) +chmod 755 "${kernel_dir}" +workdir=$(cd "${CURRENT_DIR}"/../../../compile/ && pwd) +[ ! -e "${workdir}" ] && exit +cpu_num=$(< /proc/cpuinfo grep -c "processor") + + +# 目标OS版本,针对此版本所有的内核补丁和适配的ashmem/binder补丁放在单独的目录下面 +OS_VERSION=ubuntu_20.04 + +################################################################################ +# Function Name: install_dependency +# Description : 安装编译构建所需依赖。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_dependency(){ + apt update || exit + apt install -y dpkg dpkg-dev libncurses5-dev libssl-dev libpciaccess0 + apt install -y libdrm-amdgpu1 xserver-xorg-video-amdgpu + apt install -y build-essential + apt install -y libncurses5-dev openssl libssl-dev + apt install -y pkg-config + apt install -y bison + apt install -y flex + apt install -y libelf-dev +} + +################################################################################ +# Function Name: modify_config +# Description : .config文件修改。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function modify_config(){ + < .config grep -v "#"|grep -w "${1}" + if [ $? -eq 0 ] + then + sed -i "s|${1}=.*|${1}=${2}|g" .config + else + echo "${1}=${2}" >> .config + fi + echo ">> $(< .config grep -v "#"|grep -w "${1}")" +} + +################################################################################ +# Function Name: build_init +# Description : ubuntu内核源码准备。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function build_init(){ + echo "-------------------解压内核--------------------" + cd "${kernel_dir}" || exit + rm -rf linux-5.4.0 + if [ ! -e "linux_5.4.0.orig.tar.gz" ] + then + error "-------------------缺少linux_5.4.0.orig.tar.gz--------------------" + fi + + if [ ! -e "linux_5.4.0-26.30.diff.gz" ] + then + error "-------------------缺少linux_5.4.0-26.30.diff.gz--------------------" + fi + + if [ ! -e "linux_5.4.0-26.30.dsc" ] + then + error "-------------------缺少linux_5.4.0-26.30.dsc--------------------" + fi + + dpkg-source -x linux_5.4.0-26.30.dsc || exit +} + +################################################################################ +# Function Name: apply_patch +# Description : 转码及内核补丁合入。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function apply_patch(){ + echo "------------合入转码补丁及内核补丁------------------" + cp -r "${workdir}"/src/patchForKernel/${OS_VERSION} "${kernel_dir}"/linux-5.4.0/ || exit + cd "${kernel_dir}"/linux-5.4.0/ || exit + echo "*--patching ubuntu-5.4.0-18.22.patch" + patch -p1 < ${OS_VERSION}/kernel/ubuntu-5.4.0-18.22.patch || exit + echo "*--5.4.30_mmap.patch" + patch -p1 < ${OS_VERSION}/kernel/5.4.30_mmap.patch || exit + echo "*--kernel.patch" + patch -p1 < ${OS_VERSION}/kernel/kernel.patch || exit + echo "*--pid_max_limit.patch" + patch -p1 < ${OS_VERSION}/kernel/pid_max_limit.patch || exit +} + +################################################################################ +# Function Name: build_install_kernel +# Description : 内核及内核模块编译。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function build_install_kernel(){ + echo "---------编译及安装kernel---------" + echo "---------内核编译---------" + cd "${kernel_dir}"/linux-5.4.0/ || exit + (echo -e \'\\0x65\'; echo -e \'\\0x79\') | make menuconfig + sleep 1 + [ ! -e ".config" ] && error "config file not found" + modify_config "CONFIG_BINFMT_MISC" "y" + modify_config "CONFIG_EXAGEAR_BT" "y" + modify_config "CONFIG_CHECKPOINT_RESTORE" "y" + modify_config "CONFIG_PROC_CHILDREN" "y" + modify_config "CONFIG_VFAT_FS" "y" + modify_config "CONFIG_INPUT_UINPUT" "y" + modify_config "CONFIG_HISI_PMU" "y" + + echo "---------内核编译---------" + make clean && make -j"${cpu_num}" + [ $? -ne 0 ] && error "内核编译失败" + echo "---------内核模块编译---------" + make modules_install + [ $? -ne 0 ] && error "内核模块编译失败" + mkdir -p "${kernel_dir}"/output/boot + INSTALL_PATH="${kernel_dir}"/output/boot/ make zinstall + INSTALL_MOD_PATH="${kernel_dir}"/output/ make INSTALL_MOD_STRIP=1 modules_install -j8 + cp "${workdir}"/exagear/ExaGear_ARM32-ARM64/ubt_a32a64 "${kernel_dir}"/output/ +} + +################################################################################ +# Function Name: build_ashmem_binder +# Description : ashmem和binder两个内核模块编译。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function build_ashmem_binder(){ + cd "${package_dir}" || exit + [ -e "${kernel_dir}/ashmem" ] && rm -rf "${kernel_dir}"/ashmem + [ -e "${kernel_dir}/binder" ] && rm -rf "${kernel_dir}"/binder + cp -r ashmem "${kernel_dir}"/ + cp -r binder "${kernel_dir}"/ + cd "${kernel_dir}" || exit + patch -p1 < "${workdir}"/src/patchForKernel/"${OS_VERSION}"/ashmem_binder/ashmem.patch || exit + patch -p1 < "${workdir}"/src/patchForKernel/"${OS_VERSION}"/ashmem_binder/binder.patch || exit + echo "--------编译asdmem--------" + cd "${kernel_dir}"/ashmem || exit + make clean + make -C "${kernel_dir}"/linux-5.4.0 V=0 M="${kernel_dir}"/ashmem + [ $? -ne 0 ] && error "asdmem compile failed" + cp ashmem_linux.ko "${kernel_dir}"/output/ + echo "---------编译binder--------" + cd "${kernel_dir}"/binder || exit + make clean + make -C "${kernel_dir}"/linux-5.4.0 V=0 M="${kernel_dir}"/binder + [ $? -ne 0 ] && error "binder compile failed" + cp aosp9_binder_linux.ko "${kernel_dir}"/output/ +} + +main(){ + install_dependency + build_init + apply_patch + build_install_kernel + build_ashmem_binder +} + +main "$@" +exit 0 diff --git a/make_img_sample/kbox11_iso_build/make_iso.sh b/make_img_sample/kbox11_iso_build/make_iso.sh new file mode 100644 index 0000000000000000000000000000000000000000..561499c0932f862e5f853198689ea1a154ffeb8c --- /dev/null +++ b/make_img_sample/kbox11_iso_build/make_iso.sh @@ -0,0 +1,131 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2020-2020. All rights reserved. +# File Name: make_iso.sh +# Description: ubuntu iso镜像制作. +# Usage: bash make_iso.sh +# ******************************************************************************** # + +#set -x +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ] +then + bash "$0" "$@" + exit $? +fi + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +cd "${CURRENT_DIR}" || exit +package_dir=$(cd "${CURRENT_DIR}"/../../../ && pwd) +[ ! -e "${CURRENT_DIR}/../../../kernel/output/" ] && exit +output_dir=$(cd "${CURRENT_DIR}"/../../../kernel/output/ && pwd) +[ ! -e "${CURRENT_DIR}/../../../iso_old/" ] && rm -rf "${CURRENT_DIR}"/../../../iso_old +mkdir -p "${CURRENT_DIR}"/../../../iso_old/ +iso_dir_old=$(cd "${CURRENT_DIR}"/../../../iso_old/ && pwd) +iso_name="${iso_file:-ubuntu-20.04.1-live-server-arm64.iso}" + +################################################################################ +# Function Name: check_mount +# Description : 检查并卸载旧ubuntu镜像的挂载。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function check_mount(){ + mount |grep "${iso_dir_old}" > /dev/null 2>&1 + [ $? -eq 0 ] && umount "${iso_dir_old}" +} + +################################################################################ +# Function Name: install_dependency +# Description : 安装ubuntu iso镜像制作所需依赖。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_dependency(){ + apt update || exit + apt install -y squashfs-tools genisoimage + apt install -y cifs-utils +} + +################################################################################ +# Function Name: prepare +# Description : 将ubuntu iso镜像安装启动后需要用到的文件预置入iso镜像。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function prepare(){ + cd "${package_dir}" || exit + rm -rf ARM64_demo.iso + chmod 755 "${iso_dir_old}" + check_mount + mount -o loop "${iso_name}" "${iso_dir_old}" + rm -rf iso_new + cp -rf "${iso_dir_old}" iso_new + umount "${iso_dir_old}" + rm -rf "${iso_dir_old}" + cd iso_new || exit + unsquashfs ./casper/filesystem.squashfs || exit + mkdir -p squashfs-root/usr/new_file + mkdir -p squashfs-root/usr/new_file/image + cp -rf "${output_dir}"/boot squashfs-root/usr/new_file/ + cp -rf "${output_dir}"/lib squashfs-root/usr/new_file/ + cp -rf "${output_dir}"/ubt_a32a64 squashfs-root/usr/new_file/ + cp -rf "${output_dir}"/ashmem_linux.ko squashfs-root/usr/new_file/ + cp -rf "${output_dir}"/aosp9_binder_linux.ko squashfs-root/usr/new_file/ + cp -rf "${package_dir}"/android.tar squashfs-root/usr/new_file/image/ + cp -rf "${package_dir}"/Kbox-AOSP9/deploy_scripts squashfs-root/usr/new_file/ + cp -rf "${CURRENT_DIR}"/rc-local.service squashfs-root/etc/systemd/system/ + cp -rf "${CURRENT_DIR}"/rc.local squashfs-root/etc/ + chmod 750 squashfs-root/etc/rc.local + chmod 750 squashfs-root/etc/systemd/system/rc-local.service + cp -rf "${CURRENT_DIR}"/start.sh squashfs-root/usr/new_file/ + cp -rf "${package_dir}"/docker_deb squashfs-root/usr/new_file/ + cp -rf "${package_dir}"/lxcfs_deb squashfs-root/usr/new_file/ +} + +################################################################################ +# Function Name: build_ios +# Description : 打包生成ubuntu iso镜像。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function build_ios(){ + cd "${package_dir}"/iso_new || exit + chroot squashfs-root dpkg-query -W --showformat='${Package} ${Version}\n' | sudo tee install/filesystem.manifest + rm casper/filesystem.squashfs + mksquashfs squashfs-root casper/filesystem.squashfs || exit + printf "$(sudo du -sx --block-size=1 squashfs-root | cut -f1)" > install/filesystem.size + sudo find . -type f -print0 | xargs -0 md5sum | grep -v "\./md5sum.txt" > md5sum.txt + genisoimage -r -V "ARM64_demo" -o "${package_dir}"/ARM64_demo.iso -J -joliet-long -cache-inodes -c boot/boot.cat -e boot/grub/efi.img -no-emul-boot . + cd "${package_dir}" || exit + rm -rf iso_new +} + +################################################################################ +# Function Name: end_of_build +# Description : 生成MD5文件及清理。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function end_of_build(){ + cd "${package_dir}" || exit + md5sum ARM64_demo.iso > ARM64_demo.iso.md5 + echo "${package_dir}"/ARM64_demo.iso + echo "---------End----------" +} + +main(){ + install_dependency + prepare + build_ios + end_of_build +} + +main "$@" +exit 0 diff --git a/make_img_sample/kbox11_iso_build/rc-local.service b/make_img_sample/kbox11_iso_build/rc-local.service new file mode 100644 index 0000000000000000000000000000000000000000..33d2fc88ff9dd5953b721601deaf6479d77b600f --- /dev/null +++ b/make_img_sample/kbox11_iso_build/rc-local.service @@ -0,0 +1,29 @@ +#Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# This unit gets pulled automatically into multi-user.target by +# systemd-rc-local-generator if /etc/rc.local is executable. +[Unit] +Description=/etc/rc.local Compatibility +Documentation=man:systemd-rc-local-generator(8) +ConditionFileIsExecutable=/etc/rc.local +After=network.target + +[Service] +Type=forking +ExecStart=/etc/rc.local start +TimeoutSec=0 +RemainAfterExit=yes +GuessMainPID=no + +[Install] +WantedBy=multi-user.target +Alias=rc-local.service diff --git a/make_img_sample/kbox11_iso_build/rc.local b/make_img_sample/kbox11_iso_build/rc.local new file mode 100644 index 0000000000000000000000000000000000000000..76708311987d62d7327a5cc591e3109024e9fd8c --- /dev/null +++ b/make_img_sample/kbox11_iso_build/rc.local @@ -0,0 +1,9 @@ +#!/bin/sh -e +#Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + +echo "log" > /usr/local/log + +cd /usr/new_file/ +chmod 750 start.sh +./start.sh +exit 0 diff --git a/make_img_sample/kbox11_iso_build/start.sh b/make_img_sample/kbox11_iso_build/start.sh new file mode 100644 index 0000000000000000000000000000000000000000..407343fa6056449ccd97d928cd8e35c68b997994 --- /dev/null +++ b/make_img_sample/kbox11_iso_build/start.sh @@ -0,0 +1,394 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2020-2020. All rights reserved. +# File Name: start.sh +# Description: ubuntu iso镜像安装启动后环境部署脚本. +# Usage: bash start.sh +# ******************************************************************************** # + +#set -x +# 脚本解释器 强制设置为 bash +if [ "$BASH" != "/bin/bash" ] && [ "$BASH" != "/usr/bin/bash" ] +then + bash "$0" "$@" + exit $? +fi + +function error(){ + echo -e "\033[1;31m$1\033[0m" + exit 1 +} + +CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +cd "${CURRENT_DIR}" || exit +new_file_dir="/usr/new_file" +lxcfs_path="/var/lib/lxcfs" +kernel_r=$(uname -r) + +################################################################################ +# Function Name: install_docker +# Description : 安装预置的docker-*.tgz包。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_docker(){ + local docker_info_StorageDriver + cd ${new_file_dir}/docker_deb || exit + tar xvpf docker-*.tgz + cp -p docker/* /usr/bin + cat >/usr/lib/systemd/system/docker.service <> /etc/default/docker + systemctl restart docker + fi +} + +################################################################################ +# Function Name: install_kernel +# Description : 新ubuntu内核安装。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_kernel(){ + if [ "${kernel_r}" != "5.4.30" ] + then + install_docker + echo -e "\033[32m内核安装更换,系统将会重启\033[0m" + < /boot/grub/grub.cfg grep "Ubuntu, with Linux"|awk -F \' '{print i++ ":"$2}'|grep -v "recovery mode"|grep -w "5.4.30$" > /dev/null 2>&1 + if [ $? -ne 0 ] + then + cd ${new_file_dir} || exit + cp -r boot/* /boot/ + cp -r lib/* /lib/ + mkinitramfs -o /boot/initrd.img-5.4.30 5.4.30 + fi + cd /boot/grub || exit + grub_default=$(< /boot/grub/grub.cfg grep "Ubuntu, with Linux"|awk -F \' '{print i++ ":"$2}'|grep -v "recovery mode"|grep -w "5.4.30$"|awk -F ':' '{print $1}') + sed -i "s/GRUB_DEFAULT=.*/GRUB_DEFAULT=\"1\> ${grub_default}\"/g" /etc/default/grub + sed -i "s/GRUB_TIMEOUT_STYLE=.*/GRUB_TIMEOUT_STYLE=menu/g" /etc/default/grub + sed -i "s/GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX=\"cgroup_enable=memory swapaccount=1\"/g" /etc/default/grub + sudo update-grub2 + optimize_conf + reboot + fi + systemctl daemon-reload + systemctl restart docker + systemctl enable docker +} + +################################################################################ +# Function Name: set_amdgpu_performance +# Description : 设置AMD显卡性能模式。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function set_amdgpu_performance(){ + local pci_ids + local r_pci_id + local card + echo "------------设置AMD显卡性能模式--------------" + pci_ids=("$(lspci|grep "AMD"|grep "VGA"|awk '{print $1}')") + for pci_id in ${pci_ids[*]} + do + if [ ${#pci_id} -eq 7 ] + then + r_pci_id="0000:${pci_id}" + else + r_pci_id="${pci_id}" + fi + card=$(ls /sys/bus/pci/devices/"${r_pci_id}"/drm/|grep card) + echo high > /sys/class/drm/"${card}"/device/power_dpm_force_performance_level + done +} + +################################################################################ +# Function Name: set_a32a64 +# Description : 转码使能。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function set_a32a64(){ + if [ -e "/proc/sys/fs/binfmt_misc/ubt_a32a64" ] + then + < /proc/sys/fs/binfmt_misc/ubt_a32a64 grep "enabled" > /dev/null 2>&1 + [ $? -eq 0 ] && return 0 + fi + echo "------------配置转码------------" + [ -e "/proc/sys/fs/binfmt_misc/ubt_a32a64" ] && echo -1 > /proc/sys/fs/binfmt_misc/ubt_a32a64 + rm -rf /opt/exagear/ubt_a32a64 + mount |grep "binfmt_misc on" > /dev/null 2>&1 + [ $? -ne 0 ] && mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc + mkdir -p /opt/exagear + cp ${new_file_dir}/ubt_a32a64 /opt/exagear/ + chmod +x /opt/exagear/ubt_a32a64 + echo ":ubt_a32a64:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff:/opt/exagear/ubt_a32a64:POCF" > /proc/sys/fs/binfmt_misc/register + < /proc/sys/fs/binfmt_misc/ubt_a32a64 grep "enabled" + [ $? -ne 0 ] && error "tango规则是否注册失败" +} + +################################################################################ +# Function Name: insmod_ashmem_binder +# Description : 安装ashmem、binder两个内核模块。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function insmod_ashmem_binder(){ + local count_time=0 + local binder_num + echo "-------安装ashmem、binder模块--------" + cd ${new_file_dir} || exit + lsmod |grep -w aosp9_binder_linux + if [ $? -ne 0 ] + then + insmod aosp9_binder_linux.ko num_devices=400 + lsmod |grep -w aosp9_binder_linux + [ $? -ne 0 ] && error "binder安装失败" + fi + cd ${new_file_dir} || exit + lsmod |grep -w ashmem_linux + if [ $? -ne 0 ] + then + insmod ashmem_linux.ko + lsmod |grep -w ashmem_linux + [ $? -ne 0 ] && error "ashmem安装失败" + fi + while true + do + sleep 1 + binder_num=$(ls /dev/|grep -c "^aosp9_binder[0-9]\{1,3\}$") + [ "${binder_num}" -eq 400 ] && break + if [ ${count_time} -gt 15 ] + then + echo -e "\033[1;31m insmod aosp9_binder failed\033[0m" + break + fi + (( count_time++ )) || true + done + echo "--------配置dev可执行权限--------" + chmod 600 /dev/aosp9_binder* + chmod 600 /dev/ashmem + chmod 600 /dev/dri/* + chmod 600 /dev/input +} + +################################################################################ +# Function Name: modify_kv_config +# Description : key=value类型配置文件修改。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function modify_kv_config(){ + local conf_file=$1 + local item=$2 + local value=$3 + local kv_num + local kv_v + local kv_vr + kv=$(< "${conf_file}" grep -v "^#"|grep -E "^${item}[[:space:]]*=") + kv_num=$(< "${conf_file}" grep -v "^#"|grep -cE "^${item}[[:space:]]*=") + if [ "${kv_num}" -gt 1 ] + then + sed -i "/${item}/d" "${conf_file}" + echo "${item}=${value}" >> "${conf_file}" + elif [ "${kv_num}" -le 0 ] + then + echo "${item}=${value}" >> "${conf_file}" + else + kv_v=$(echo "${kv}"|awk -F '=' '{print $2}') + kv_vr=$(eval echo "${kv_v}") + if [ "${kv_vr}" != "${value}" ] + then + sed -i "s|^${item}[[:space:]]*=.*|${item}=${value}|g" "${conf_file}" + fi + fi +} + +################################################################################ +# Function Name: modify_ns_config +# Description : key value类型配置文件修改。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function modify_ns_config(){ + local conf_file=$1 + local item=$2 + local value=$3 + local ns + local ns_num + local ns_v + local ns_vr + ns=$(< "${conf_file}" grep -v "^#"|grep -w "^${item}") + ns_num=$(< "${conf_file}" grep -v "^#"|grep -wc "^${item}") + if [ "${ns_num}" -gt 1 ] + then + sed -i "/${item}/d" "${conf_file}" + echo "${item} ${value}" >> "${conf_file}" + elif [ "${ns_num}" -le 0 ] + then + echo "${item} ${value}" >> "${conf_file}" + else + ns_v=$(echo "${ns}"|awk '{print $NF}') + ns_vr=$(eval echo "${ns_v}") + if [ "${ns_vr}" != "${value}" ] + then + sed -i "s|^${item}.*|${item} ${value}|g" "${conf_file}" + fi + fi +} + +################################################################################ +# Function Name: optimize_conf +# Description : 系统优化配置。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function optimize_conf(){ + #间隔只有一个空格(格式统一) + sed -i 's/^[[:space:]]\+//g' /etc/sysctl.conf + sed -i '/^[^#]/s/[[:space:]]\+/ /g' /etc/sysctl.conf + sed -i 's/^[[:space:]]\+//g' /etc/security/limits.conf + sed -i '/^[^#]/s/[[:space:]]\+/ /g' /etc/security/limits.conf + modify_kv_config /etc/sysctl.conf kernel.pid_max 4119481 + modify_kv_config /etc/sysctl.conf kernel.threads-max 4119481 + modify_kv_config /etc/sysctl.conf fs.inotify.max_user_instances 81920 + modify_kv_config /etc/sysctl.conf net.ipv4.ip_forward 1 + ulimit -u 2059740 + modify_ns_config /etc/security/limits.conf "* soft core" 0 + modify_ns_config /etc/security/limits.conf "* hard core" 0 + modify_ns_config /etc/security/limits.conf "root soft nofile" 165535 + modify_ns_config /etc/security/limits.conf "root hard nofile" 165535 +} + +################################################################################ +# Function Name: set_mapping_node +# Description : 设置映射到容器内的节点,主要解决部分游戏会根据这个节点来开启渲染线程, +# 如不设置,默认根据CPU数量来开启渲染线程,这样的话,渲染线程就会开启的 +# 太多,影响游戏运行。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function set_mapping_node(){ + mkdir -p /root/vpresent + [ -d "/root/vpresent/possible" ] && rm -rf /root/vpresent/possible + [ -d "/root/vpresent/present" ] && rm -rf /root/vpresent/present + touch /root/vpresent/possible + touch /root/vpresent/present + echo 0-1 > /root/vpresent/possible + echo 0-1 > /root/vpresent/present + chmod 600 /root/vpresent/* +} + +################################################################################ +# Function Name: install_lxcfs +# Description : 安装lxcfs服务。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function install_lxcfs(){ + cd ${new_file_dir}/lxcfs_deb || exit + dpkg -i lxcfs_*_arm64.deb + dpkg -i liblxc-common_*_arm64.deb + local lxcfs_status + lxcfs_status=$(systemctl is-active lxcfs.service) + if [ "${lxcfs_status}" = "inactive" ] + then + systemctl restart lxcfs + fi + if [ ! -f "${lxcfs_path}/proc/cpuinfo" ] + then + rm -rf ${lxcfs_path:?}/* + /usr/bin/lxcfs ${lxcfs_path}/ + sleep 2 + systemctl restart lxcfs.service + [ $? -ne 0 ] && error "Failed to restart the lxcfs service. Check the lxcfs service." + fi + echo "lxcfs.service is $(systemctl is-active lxcfs.service)" +} + +################################################################################ +# Function Name: import_android_image +# Description : 导入android镜像到docker。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function import_android_image(){ + cd ${new_file_dir} || exit + docker images|awk '{print $1" "$2}'|grep -w "kbox9_exagear"|grep -w "new" > /dev/null 2>&1 + [ $? -eq 0 ] && return 0 + if [ -f "image/android.tar" ] + then + docker import image/android.tar kbox9_exagear:new || exit + fi +} + +################################################################################ +# Function Name: start_kbox_default +# Description : 尝试启动一个kbox9,判断环境是否已经配置好。 +# Parameter : +# Returns : 0 on success, otherwise on fail +################################################################################ +function start_kbox_default(){ + local kbox_name + local count_time=0 + local boot_state + cd ${new_file_dir}/deploy_scripts || exit + docker ps -a|awk '{print $(NF-1)" "$NF}'|grep -E "8501|kbox_1" > /dev/null 2>&1 + [ $? -eq 0 ] && return 0 + sh aosp9_start_box.sh kbox9_exagear:new 1 1 2 > /dev/null 2>&1 + kbox_name=kbox_1 + docker exec -i ${kbox_name} sh -c "getprop sys.boot_completed"|grep 1 + if [ $? -ne 0 ] + then + echo "${kbox_name} 启动失败,请重新检查环境。" + fi +} + +main(){ + install_kernel + set_amdgpu_performance + set_a32a64 + insmod_ashmem_binder + import_android_image + set_mapping_node + install_lxcfs + start_kbox_default +} + +main "$@" +exit 0 diff --git a/make_img_sample/kbox14_android_build/create-package_aosp14.sh b/make_img_sample/kbox14_android_build/create-package_aosp14.sh new file mode 100644 index 0000000000000000000000000000000000000000..35d9ec7966a21ab778cb05dcfbf6a7e5ef2dd9ab --- /dev/null +++ b/make_img_sample/kbox14_android_build/create-package_aosp14.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2020-2022. All rights reserved. +# File Name: create-package.sh +# Description: android镜像打tar包. +# Usage: create-package_aosp14.sh +# ******************************************************************************** # + +set -ex + +system=$1 +destdir=$PWD + +if [ -z "$system" ]; then + echo "Usage: $0 " + exit 1 +fi + +workdir=$(mktemp -d) +rootfs=$workdir/rootfs + +mkdir -p "$rootfs" + +mkdir "$workdir"/system +sudo mount -o loop,ro "$system" "$workdir"/system +sudo cp -ar "$workdir"/system/* "$rootfs"/ +sudo umount "$workdir"/system + +apexlist=($(ls "$rootfs"/system/apex | grep apex)) +apexworkdir=$(mktemp -d) +for((i=0;i<${#apexlist[@]};i++)) do + mkdir -p "$apexworkdir"/mnt + sudo cp -anr "$rootfs"/system/apex/"${apexlist[$i]}" "$apexworkdir" + basename=$(basename "${apexlist[$i]}" .apex) + sudo unzip "$apexworkdir"/"${apexlist[$i]}" -d "$apexworkdir" + sudo mount -o loop,ro "$apexworkdir"/apex_payload.img "$apexworkdir"/mnt + sudo mkdir -p "$rootfs"/apex/"$basename" + sudo cp -anr "$apexworkdir"/mnt/* "$rootfs"/apex/"$basename" + sudo rm -rf "$rootfs"/apex/"$basename"/'lost+found' + sudo cp -anr "$apexworkdir"/apex_pubkey "$rootfs"/apex/"$basename" + sudo umount "$apexworkdir"/mnt + sudo rm -rf "$apexworkdir"/* +done +sudo rm -rf "$apexworkdir" +sudo mv "$rootfs"/apex/com.android.vndk.current "$rootfs"/apex/com.android.vndk.v34 + +# FIXME +sudo chmod +x "$rootfs"/kbox-init.sh + +if [ -e android.tar ]; then + DATE=$(date +%F_%R) + SAVETO=android-old-$DATE.tar + + echo "#########################################################" + echo "# WARNING: Old android.tar still exists. " + echo "# Moving it to $SAVETO. " + echo "#########################################################" + + mv android.tar "$SAVETO" +fi + +#sudo mksquashfs $rootfs $destdir/android.tar -comp xz -no-xattrs +cd "$rootfs" +sudo tar --numeric-owner -cf "$destdir"/android.tar ./ +sudo chown "$USER":"$USER" "$destdir"/android.tar + +cd "$destdir" +sudo rm -rf "$workdir" diff --git a/make_img_sample/kbox15_android_build/create-package_aosp15.sh b/make_img_sample/kbox15_android_build/create-package_aosp15.sh new file mode 100755 index 0000000000000000000000000000000000000000..c921a542628add2f9acc30e2368d8c21e3f08cc2 --- /dev/null +++ b/make_img_sample/kbox15_android_build/create-package_aosp15.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +# ******************************************************************************** # +# Copyright Kbox Technologies Co., Ltd. 2025-2025. All rights reserved. +# File Name: create-package_aosp15.sh +# Description: android镜像打tar包. +# Usage: create-package_aosp15.sh +# ******************************************************************************** # + +set -ex + +system=$1 +destdir=$PWD +RM_BINARY=$2 + +if [ -z "$system" ]; then + echo "Usage: $0 " + exit 1 +fi + +workdir=$(mktemp -d) +rootfs=$workdir/rootfs + +mkdir -p "$rootfs" + +mkdir "$workdir"/system +sudo mount -o loop,rw "$system" "$workdir"/system +sudo cp -ar "$workdir"/system/* "$rootfs"/ +sudo umount "$workdir"/system + +apexlist=($(ls "$rootfs"/system/apex | grep apex)) +apexworkdir=$(mktemp -d) +for((i=0;i<${#apexlist[@]};i++)) do + mkdir -p "$apexworkdir"/mnt + sudo cp -anr "$rootfs"/system/apex/"${apexlist[$i]}" "$apexworkdir" + basename=$(basename "${apexlist[$i]}" .apex) + sudo unzip "$apexworkdir"/"${apexlist[$i]}" -d "$apexworkdir" + sudo mount -o loop,ro "$apexworkdir"/apex_payload.img "$apexworkdir"/mnt + sudo mkdir -p "$rootfs"/apex/"$basename" + sudo cp -anr "$apexworkdir"/mnt/* "$rootfs"/apex/"$basename" + sudo rm -rf "$rootfs"/apex/"$basename"/'lost+found' + sudo cp -anr "$apexworkdir"/apex_pubkey "$rootfs"/apex/"$basename" + sudo umount "$apexworkdir"/mnt + sudo rm -rf "$apexworkdir"/* +done +sudo rm -rf "$apexworkdir" + +if [ -e android.tar ]; then + DATE=$(date +%F_%R) + SAVETO=android-old-$DATE.tar + + echo "#########################################################" + echo "# WARNING: Old android.tar still exists. " + echo "# Moving it to $SAVETO. " + echo "#########################################################" + + mv android.tar "$SAVETO" +fi + +sudo cp "$destdir"/out/target/product/kbox_arm64/obj/MESON_MESA3D/install/usr/local/lib/dri/radeonsi_drv_video.so $rootfs/system/vendor/lib64/dri/ + +cd "$rootfs" +sudo tar --numeric-owner -cf "$destdir"/android.tar ./ +sudo chown "$USER":"$USER" "$destdir"/android.tar + +cd "$destdir" +sudo rm -rf "$workdir" diff --git a/aosp15r17-patch/device/google/cuttlefish/device-google-cuttlefish-0001.patch b/patchForAndroid/aosp15r17-patch/device/google/cuttlefish/device-google-cuttlefish-0001.patch similarity index 100% rename from aosp15r17-patch/device/google/cuttlefish/device-google-cuttlefish-0001.patch rename to patchForAndroid/aosp15r17-patch/device/google/cuttlefish/device-google-cuttlefish-0001.patch diff --git a/aosp15r17-patch/external/libdrm/external-libdrm-0001.patch b/patchForAndroid/aosp15r17-patch/external/libdrm/external-libdrm-0001.patch similarity index 100% rename from aosp15r17-patch/external/libdrm/external-libdrm-0001.patch rename to patchForAndroid/aosp15r17-patch/external/libdrm/external-libdrm-0001.patch diff --git a/aosp15r17-patch/external/libva/external-libva-0001.patch b/patchForAndroid/aosp15r17-patch/external/libva/external-libva-0001.patch similarity index 100% rename from aosp15r17-patch/external/libva/external-libva-0001.patch rename to patchForAndroid/aosp15r17-patch/external/libva/external-libva-0001.patch diff --git a/aosp15r17-patch/external/mesa3d/external-mesa3d-0001.patch b/patchForAndroid/aosp15r17-patch/external/mesa3d/external-mesa3d-0001.patch similarity index 100% rename from aosp15r17-patch/external/mesa3d/external-mesa3d-0001.patch rename to patchForAndroid/aosp15r17-patch/external/mesa3d/external-mesa3d-0001.patch diff --git a/aosp15r17-patch/external/minigbm/external-minigbm-0001.patch b/patchForAndroid/aosp15r17-patch/external/minigbm/external-minigbm-0001.patch similarity index 100% rename from aosp15r17-patch/external/minigbm/external-minigbm-0001.patch rename to patchForAndroid/aosp15r17-patch/external/minigbm/external-minigbm-0001.patch diff --git a/aosp15r17-patch/external/minijail/external-minijail-0001.patch b/patchForAndroid/aosp15r17-patch/external/minijail/external-minijail-0001.patch similarity index 100% rename from aosp15r17-patch/external/minijail/external-minijail-0001.patch rename to patchForAndroid/aosp15r17-patch/external/minijail/external-minijail-0001.patch diff --git a/aosp15r17-patch/external/selinux/external-selinux-0001.patch b/patchForAndroid/aosp15r17-patch/external/selinux/external-selinux-0001.patch similarity index 100% rename from aosp15r17-patch/external/selinux/external-selinux-0001.patch rename to patchForAndroid/aosp15r17-patch/external/selinux/external-selinux-0001.patch diff --git a/aosp15r17-patch/frameworks/av/frameworks-av-0001.patch b/patchForAndroid/aosp15r17-patch/frameworks/av/frameworks-av-0001.patch similarity index 100% rename from aosp15r17-patch/frameworks/av/frameworks-av-0001.patch rename to patchForAndroid/aosp15r17-patch/frameworks/av/frameworks-av-0001.patch diff --git a/aosp15r17-patch/frameworks/base/frameworks-base-0001.patch b/patchForAndroid/aosp15r17-patch/frameworks/base/frameworks-base-0001.patch similarity index 100% rename from aosp15r17-patch/frameworks/base/frameworks-base-0001.patch rename to patchForAndroid/aosp15r17-patch/frameworks/base/frameworks-base-0001.patch diff --git a/aosp15r17-patch/frameworks/base/frameworks-base-0002.patch b/patchForAndroid/aosp15r17-patch/frameworks/base/frameworks-base-0002.patch similarity index 100% rename from aosp15r17-patch/frameworks/base/frameworks-base-0002.patch rename to patchForAndroid/aosp15r17-patch/frameworks/base/frameworks-base-0002.patch diff --git a/aosp15r17-patch/frameworks/native/frameworks-native-0001.patch b/patchForAndroid/aosp15r17-patch/frameworks/native/frameworks-native-0001.patch similarity index 100% rename from aosp15r17-patch/frameworks/native/frameworks-native-0001.patch rename to patchForAndroid/aosp15r17-patch/frameworks/native/frameworks-native-0001.patch diff --git a/aosp15r17-patch/hardware/libhardware/hardware-libhardware-0001.patch b/patchForAndroid/aosp15r17-patch/hardware/libhardware/hardware-libhardware-0001.patch similarity index 100% rename from aosp15r17-patch/hardware/libhardware/hardware-libhardware-0001.patch rename to patchForAndroid/aosp15r17-patch/hardware/libhardware/hardware-libhardware-0001.patch diff --git a/aosp15r17-patch/packages/modules/Bluetooth/packages-modules-Bluetooth-0001.patch b/patchForAndroid/aosp15r17-patch/packages/modules/Bluetooth/packages-modules-Bluetooth-0001.patch similarity index 100% rename from aosp15r17-patch/packages/modules/Bluetooth/packages-modules-Bluetooth-0001.patch rename to patchForAndroid/aosp15r17-patch/packages/modules/Bluetooth/packages-modules-Bluetooth-0001.patch diff --git a/aosp15r17-patch/packages/modules/Connectivity/packages-modules-Connectivity-0001.patch b/patchForAndroid/aosp15r17-patch/packages/modules/Connectivity/packages-modules-Connectivity-0001.patch similarity index 100% rename from aosp15r17-patch/packages/modules/Connectivity/packages-modules-Connectivity-0001.patch rename to patchForAndroid/aosp15r17-patch/packages/modules/Connectivity/packages-modules-Connectivity-0001.patch diff --git a/aosp15r17-patch/system/bpf/system-bpf-0001.patch b/patchForAndroid/aosp15r17-patch/system/bpf/system-bpf-0001.patch similarity index 100% rename from aosp15r17-patch/system/bpf/system-bpf-0001.patch rename to patchForAndroid/aosp15r17-patch/system/bpf/system-bpf-0001.patch diff --git a/aosp15r17-patch/system/core/system-core-0001.patch b/patchForAndroid/aosp15r17-patch/system/core/system-core-0001.patch similarity index 100% rename from aosp15r17-patch/system/core/system-core-0001.patch rename to patchForAndroid/aosp15r17-patch/system/core/system-core-0001.patch diff --git a/aosp15r17-patch/system/libbase/system-libbase-0001.patch b/patchForAndroid/aosp15r17-patch/system/libbase/system-libbase-0001.patch similarity index 100% rename from aosp15r17-patch/system/libbase/system-libbase-0001.patch rename to patchForAndroid/aosp15r17-patch/system/libbase/system-libbase-0001.patch diff --git a/aosp15r17-patch/system/libhwbinder/system-libhwbinder-0001.patch b/patchForAndroid/aosp15r17-patch/system/libhwbinder/system-libhwbinder-0001.patch similarity index 100% rename from aosp15r17-patch/system/libhwbinder/system-libhwbinder-0001.patch rename to patchForAndroid/aosp15r17-patch/system/libhwbinder/system-libhwbinder-0001.patch diff --git a/aosp15r17-patch/system/libvintf/system-libvintf-0001.patch b/patchForAndroid/aosp15r17-patch/system/libvintf/system-libvintf-0001.patch similarity index 100% rename from aosp15r17-patch/system/libvintf/system-libvintf-0001.patch rename to patchForAndroid/aosp15r17-patch/system/libvintf/system-libvintf-0001.patch diff --git a/aosp15r17-patch/system/netd/system-netd-0001.patch b/patchForAndroid/aosp15r17-patch/system/netd/system-netd-0001.patch similarity index 100% rename from aosp15r17-patch/system/netd/system-netd-0001.patch rename to patchForAndroid/aosp15r17-patch/system/netd/system-netd-0001.patch diff --git a/aosp15r17-patch/system/vold/system-vold-0001.patch b/patchForAndroid/aosp15r17-patch/system/vold/system-vold-0001.patch similarity index 100% rename from aosp15r17-patch/system/vold/system-vold-0001.patch rename to patchForAndroid/aosp15r17-patch/system/vold/system-vold-0001.patch diff --git a/apply-patch.sh b/patchForAndroid/apply-patch.sh similarity index 100% rename from apply-patch.sh rename to patchForAndroid/apply-patch.sh diff --git a/reverse-patch.sh b/patchForAndroid/reverse-patch.sh similarity index 100% rename from reverse-patch.sh rename to patchForAndroid/reverse-patch.sh