8.1. 微服务器定制化软件包

8.1.1. 第一步:在微服务器[SE5/SE7]上执行系统打包脚本

  1. 下载打包需要使用的脚本: socBak.sh,脚本内容如下所示。

#!/bin/bash

# These parameters are used to exclude irrelevant files
# and directories in the context of repackaging mode.
# Users can add custom irrelevant files and directories
# in the format of ROOTFS_EXCLUDE_FLAGS_INT to the
# ROOTFS_EXCLUDE_FLAGS_USER parameter.
ROOTFS_EXCLUDE_FLAGS_INT='--exclude=./var/log/* --exclude=./boot/* --exclude=./recovery/* --exclude=./data/* --exclude=./media/* --exclude=./sys/* --exclude=./proc/* --exclude=./dev/* --exclude=./factory --exclude=./run/udev/* --exclude=./run/user/* --exclude=./socrepack'
ROOTFS_EXCLUDE_FLAGS_USER=''
ROOTFS_EXCLUDE_FLAGS_OPT="${ROOTFS_EXCLUDE_FLAGS_INT} ${ROOTFS_EXCLUDE_FLAGS_USER} --exclude=./opt/*"
ROOTFS_EXCLUDE_FLAGS_SYSTEM="${ROOTFS_EXCLUDE_FLAGS_INT} ${ROOTFS_EXCLUDE_FLAGS_USER} --exclude=./system/*"
ROOTFS_EXCLUDE_FLAGS=''
ROOTFS_INCLUDE_PATHS='./var/log/nginx ./var/log/redis ./var/log/mosquitto'

# These parameters define several generated files and
# their default sizes for repackaging. Users can modify
# them according to their device specifications.
TGZ_FILES=(boot data opt system recovery rootfs)
# Here are the default sizes for each partition
declare -A TGZ_FILES_SIZE
TGZ_FILES_SIZE=(["boot"]=131072 ["recovery"]=3145728 ["rootfs"]=2621440 ["opt"]=2097152 ["system"]=2097152 ["data"]=4194304)
# The increased size of each partition compared to the original partition table
TGZ_ALL_SIZE=$((100*1024))
EMMC_ALL_SIZE=20971520
EMMC_MAX_SIZE=30000000
ROOTFS_RW_SIZE=$((6144*1024))
TAR_SIZE=0
TGZ_FILES_PATH=$(pwd)
PARTITION_FILE=partition32G.xml
SOC_VERSION=0
NEED_BAK_FLASH=1
SOC_NAME=""
PWD="$(dirname "$(readlink -f "\$0")")"

socbak_cleanup() {
    echo -e "\nReceived a kill signal. Cleaning up..."
    systemctl disable resize-helper.service
    exit 0
}
trap socbak_cleanup SIGTERM SIGINT

SOCBAK_GET_TAR_SIZE_KB=0
socbak_get_tar_size() {
    echo "INFO: get tar $1 files size..."
    pushd ${PWD}
    SOCBAK_GET_TAR_SIZE_KB=$(tar tzvf $1 --totals 2>&1 | tail -n 1 | awk '{printf "%.0f\n", $4/1024}')
    echo "INFO: $1 files size is ${SOCBAK_GET_TAR_SIZE_KB}"
    popd
}

if [ $PWD != "/socrepack" ]; then
    echo "ERROR: The current path is not \"/socrepack\", please check it"
    exit 1
fi
echo "INFO: The current path is \"/socrepack\""

have_system_of_mmc0=$(lsblk | grep mmcblk0p | grep system | wc -l)
if [[ "$have_system_of_mmc0" == "1" ]]; then
    SOC_VERSION=0
    TGZ_FILES=( ${TGZ_FILES[@]/opt} )
    unset TGZ_FILES_SIZE[opt]
    echo "INFO: find /system dir, the version is 3.0.0 or lower, cannot suppot bakpack spi_flash"
    ROOTFS_EXCLUDE_FLAGS="${ROOTFS_EXCLUDE_FLAGS_SYSTEM}"
    NEED_BAK_FLASH=0
elif [ -d "/opt" ]; then
    SOC_VERSION=1
    TGZ_FILES=( ${TGZ_FILES[@]/system} )
    unset TGZ_FILES_SIZE[system]
    echo "INFO: find /opt dir, the version is V22.09.02 or higher"
    ROOTFS_EXCLUDE_FLAGS="${ROOTFS_EXCLUDE_FLAGS_OPT}"
else
    echo "ERROR: cannot find /opt or /system, Please check the operating environment"
    exit 1
fi

if [ "$NEED_BAK_FLASH" -eq 1 ]; then
    echo "INFO: bakpack spi_flash start"
    cp /boot/spi_flash.bin spi_flash.bin
    rm -rf fip.bin
    SOC_NAME=""
    FLASH_OFFSET=0
    chip_reg_flag=$(busybox devmem 0x50010000)
    if [[ "$chip_reg_flag" == "0x16860000" ]]; then
        echo "INFO: soc is bm1684x"
        SOC_NAME="bm1684x"
        FLASH_OFFSET=0
        flash_update -d fip.bin -b 0x6000000 -o 0x30000 -l 0x170000
    elif [[ "$chip_reg_flag" == "0x16840000" ]]; then
        echo "INFO: soc is bm1684"
        SOC_NAME="bm1684"
        FLASH_OFFSET=1
        flash_update -d fip.bin -b 0x6000000 -o 0x40000 -l 0x160000
    else
        echo "ERROR: cannot support reg 0x50010000: ${chip_reg_flag}"
        exit 1
    fi
    rm -rf spi_flash_$SOC_NAME.bin
    flash_update -d spi_flash_$SOC_NAME.bin -b 0x6000000 -o 0 -l 0x200000
    dd if=spi_flash_$SOC_NAME.bin of=spi_flash.bin seek=$FLASH_OFFSET bs=4194304 conv=notrunc
    cp spi_flash.bin /boot/spi_flash.bin.socBakNew
    echo "INFO: bakpack spi_flash end"
fi

for TGZ_FILE in "${TGZ_FILES[@]}"
do
    case $TGZ_FILE in
        "rootfs")
            pushd /
            echo "INFO: tar $TGZ_FILE flags : $ROOTFS_EXCLUDE_FLAGS ..."
            systemctl enable resize-helper.service
            rm -rf $TGZ_FILES_PATH/$TGZ_FILE.tar
            tar --checkpoint=500 --checkpoint-action=ttyout='[%d sec]: C%u, %T%*\r' -caSf $TGZ_FILES_PATH/$TGZ_FILE.tar --checkpoint=100 --checkpoint-action=ttyout='[%d sec]: C%u, %T%*\r'$ROOTFS_EXCLUDE_FLAGS ./*
            tar --checkpoint=500 --checkpoint-action=ttyout='[%d sec]: C%u, %T%*\r' --ignore-failed-read -raSf $TGZ_FILES_PATH/$TGZ_FILE.tar $ROOTFS_INCLUDE_PATHS
            echo "INFO: gzip tar file..."
            gzip -c $TGZ_FILES_PATH/$TGZ_FILE.tar > | dd of=$TGZ_FILES_PATH/$TGZ_FILE.tgz bs=4M status=progress
            rm -rf $TGZ_FILES_PATH/$TGZ_FILE.tar
            systemctl disable resize-helper.service
            TAR_SIZE=$((512*1024))
            popd
            ;;
        *)
            pushd /$TGZ_FILE
            echo "INFO: tar $TGZ_FILE ..."
            tar --checkpoint=500 --checkpoint-action=ttyout='[%d sec]: C%u, %T%*\r' -caSf $TGZ_FILES_PATH/$TGZ_FILE.tgz ./*
            if [ $TGZ_FILE == "data" ]; then
                TAR_SIZE=$((512*1024))
            else
                TAR_SIZE=$((100*1024))
            fi
            popd
            ;;
    esac
    socbak_get_tar_size ${TGZ_FILE}.tgz
    TAR_SIZE=$((${SOCBAK_GET_TAR_SIZE_KB}+${TAR_SIZE}))
    echo "INFO: $TGZ_FILE : $TAR_SIZE KB"
    if [ $TAR_SIZE -gt ${TGZ_FILES_SIZE["$TGZ_FILE"]} ];
    then
        echo "INFO: need to expand $TGZ_FILE from ${TGZ_FILES_SIZE[$TGZ_FILE]} KB to $TAR_SIZE KB"
        TGZ_FILES_SIZE[$TGZ_FILE]=$TAR_SIZE
    fi
done

TGZ_ALL_SIZE=$(($TGZ_ALL_SIZE+${ROOTFS_RW_SIZE}))
for TGZ_FILE in "${TGZ_FILES[@]}"
do
    TGZ_ALL_SIZE=$(($TGZ_ALL_SIZE+${TGZ_FILES_SIZE["$TGZ_FILE"]}))
done
echo partition table size : $TGZ_ALL_SIZE KB

if [ $TGZ_ALL_SIZE -gt $EMMC_ALL_SIZE ];
    then
        echo "INFO: need to expand default partition table size from $EMMC_ALL_SIZE KB to $TGZ_ALL_SIZE KB"
        EMMC_ALL_SIZE=$TGZ_ALL_SIZE
fi

# if [ $TGZ_ALL_SIZE -gt $EMMC_MAX_SIZE ];
#    then
#            echo The total size is too large.
#            exit 1
# fi

echo "INFO: The generated file partition32G.xml can replace file bootloader-arm64/scripts/partition32G.xml in VXX"
echo "INFO: or replace some information for 3.0.0"
echo "<physical_partition size_in_kb=\"$EMMC_ALL_SIZE\">" > $TGZ_FILES_PATH/$PARTITION_FILE
echo "      <partition label=\"BOOT\"       size_in_kb=\"${TGZ_FILES_SIZE[boot]}\"  readonly=\"false\"  format=\"1\" />" >> $TGZ_FILES_PATH/$PARTITION_FILE
echo "      <partition label=\"RECOVERY\"   size_in_kb=\"${TGZ_FILES_SIZE[recovery]}\"  readonly=\"false\" format=\"2\" />" >> $TGZ_FILES_PATH/$PARTITION_FILE
echo "      <partition label=\"MISC\"       size_in_kb=\"10240\"  readonly=\"false\"   format=\"0\" />" >> $TGZ_FILES_PATH/$PARTITION_FILE
echo "      <partition label=\"ROOTFS\"     size_in_kb=\"${TGZ_FILES_SIZE[rootfs]}\" readonly=\"true\"   format=\"2\" />" >> $TGZ_FILES_PATH/$PARTITION_FILE
echo "      <partition label=\"ROOTFS_RW\"  size_in_kb=\"${ROOTFS_RW_SIZE}\" readonly=\"false\"  format=\"2\" />" >> $TGZ_FILES_PATH/$PARTITION_FILE
if [ "$SOC_VERSION" == "1" ]; then
    echo "  <partition label=\"OPT\"        size_in_kb=\"${TGZ_FILES_SIZE[opt]}\" readonly=\"false\"  format=\"2\" />" >> $TGZ_FILES_PATH/$PARTITION_FILE
else
    echo "  <partition label=\"SYSTEM\"     size_in_kb=\"${TGZ_FILES_SIZE[system]}\" readonly=\"false\"  format=\"2\" />" >> $TGZ_FILES_PATH/$PARTITION_FILE
fi
echo "      <partition label=\"DATA\"       size_in_kb=\"${TGZ_FILES_SIZE[data]}\" readonly=\"false\"  format=\"2\" />" >> $TGZ_FILES_PATH/$PARTITION_FILE
echo "</physical_partition>" >> $TGZ_FILES_PATH/$PARTITION_FILE
cat $TGZ_FILES_PATH/$PARTITION_FILE
sync
  1. 准备一个外部存储设备(SD卡,TF卡或U盘等),将打包工具 socBak.sh 拷入该设备下, 将设备插到微服务上, 切换到root账户。

sudo su
  1. 登录到微服务器上,使用 fdisk -l 指令查看刚才接入的外部存储的设备文件名,外部存储设备接入盒子后,系统会自动分配一个设备文件名。

fdisk -l

注解

测试使用的设备在微服务上显示的是 /dev/sda4, 后面操作是在此基础上进行的,不同的设备显示可能不同。

  1. 在根目录下创建 socrepack 目录,将外部存储挂载到该目录下。

cd /
mkdir socrepack
cd socrepack/
mount /dev/sda4 /socrepack/
  1. 给脚本添加执行权限, 然后执行打包脚本。

chmod +x socBak.sh
bash socBak.sh

执行成功后主要生成以下几个文件

└── socrepack
    ├── boot.tgz
    ├── data.tgz
    ├── fip.bin
    ├── opt.tgz
    ├── partition32G.xml
    ├── recovery.tgz
    ├── spi_flash.bin
    ├── spi_flash_bm1684(x).bin
    └── rootfs.tgz

8.1.2. 第二步:在X86机器上制作定制的系统包

注解

X86机器推荐使用Ubuntu18.04系统。

  1. 下载重打包所需文件:

  1. 在bootloader-arm64同级目录下创建install目录, 并在install目录下创建soc_bm1684目录;将sdcard.tgz移动到install/soc_bm1684路径下。

注解

最终的目录结构如下:

├── bootloader-arm64
├── install
│   └── soc_bm1684
│       └── sdcard.tgz
  1. 安装依赖项。

sudo apt install bison flex bc rsync kmod byobu language-pack-en gcc util-linux exfat-utils dosfstools
sudo apt install cpio uuid-dev cmake libssl-dev fakeroot dpkg-dev uuid libxml2
sudo apt install device-tree-compiler u-boot-tools libxml2-dev debootstrap qemu-user-static kpartx
  1. 设置环境变量。

source bootloader-arm64/scripts/envsetup.sh
  1. 使用revert_package命令进行拆包。

revert_package
  1. 拆包结果会在install/soc_bm1684路径,软件包和文件夹的具体描述请参考《 官方BSP文档 》。

注解

其目录结构如下:

└── soc_bm1684
    ├── boot.tgz
    ├── package_update
    ├── rootfs.tgz
    ├── sdcard.tgz
    ├── spi_flash_bm1684.bin
    ├── data.tgz
    ├── opt.tgz
    ├── recovery.tgz
    ├── rootfs_rw.tgz
    ├── spi_flash.bin
    └── spi_flash_bm1684x.bin
  1. 将微服务器上生成的文件替换到install/soc_bm1684目录下。

  2. 将微服务器上生成的partition32G.xml替换到bootloader-arm64/scripts/目录下。

  3. 使用build_update sdcard指令更新刷机包,得到的定制刷机包位于install/soc_bm1684/sdcard目录下。