4.4.2. 集成用户软件系统镜像

开发过程中,常常需要一些配置文件开发完成程序直接包含系统镜像中,以便设备运行能够板端直接使用这些文件程序。本章详细介绍两种常用方法,将用户软件文件集成系统镜像中:

  1. 文件添加文件系统system 分区

    这种方式适用需要直接系统文件一同部署文件,例如系统库、系统配置文件等。通过文件放入 system 分区,可以确保它们设备启动即可加载使用。

  2. 新增一个独立分区存放自定义文件

    通过创建分区自定义文件、程序存放其中,可以实现灵活性模块化。新分区生成独立镜像文件,方便管理更新,同时避免对根文件系统影响。

两种方法各有特点,可根据需求选择合适集成方式优化开发部署流程。以下分别介绍两种方法使用。

4.4.2.1. 文件添加文件系统system 分区

用户自定义文件集成文件系统非常简单。只准备文件复制到路径 system/buildroot/prebuilt/boot-utils-runtime 下。在编译 system 镜像时,这个目录所有内容自动打包system 分区中,无需额外操作。合并这部分文件编译代码在 BSP 源码build/mk_system.sh 脚本中,实现代码如下:

function build_unpack()
{
        ... ( 省略 ) ...

        # 合并自动启动配置项
        if [ -d "${SYSTEM_ORIG_DIR}/boot-utils-runtime" ]; then
                rm -rf "${SYSTEM_BUILD_DIR}"/etc/dropbear
                cp -arf --remove-destination ${SYSTEM_ORIG_DIR}/boot-utils-runtime/* "${SYSTEM_BUILD_DIR}"
        fi
}

注意事项:

  • system 分区容量具体大小可能软件版本有所不同。如果添加文件导致分区大小超过预设容量,镜像生成失败。为避免问题,可以通过修改分区表调整 system 分区大小。详细方法参考分区配置

操作前,请确认 system 分区容量限制,并确保添加文件不会超出可用空间。

4.4.2.2. 新增独立分区存放自定义文件

灵活管理程序配置文件,可以通过新增一个独立分区专门存放这些内容。这种方式特别适合需要程序进行独立编译、管理升级场景。本配置 app 分区为例,详细说明操作步骤(app 分区默认支持)。

注意事项

  1. 关于分区表最后一个分区

    如果新增分区位于分区表最后一个分区之后(例如userdata 分区之后),需要注意以下行为:

    • 系统启动时,U-Boot 阶段根据硬件存储设备(如 eMMC 或 NAND Flash)的实际容量,自动最后一个分区扩展存储设备末尾,以最大化利用存储空间。

    • 首次启动时,Kernel 检测最后一个分区格式化没有有效文件系统时,会自动执行格式化操作。

  2. userdata 分区默认设置

    • 系统镜像制作时,userdata 分区通常最后一个分区,不包含数据,且分区大小设置小(默认 50MB),以减小镜像体积。

    • 启动后,U-Boot自动扩展 userdata 分区剩余存储空间,首次进入系统时会格式化分区。

    • 如果userdata 之后新增分区,请调整 userdata大小满足实际需求。

  3. 关于分区

    • 如果新增分区镜像制作时为空(无有效数据,如 userdataprivate),需要系统首次启动进行格式化。

    • 格式化逻辑可以参考 /etc/init.d/S65mountall 脚本,将分区添加force_format_part_list 变量中,例如:

      force_format_part_list="app userdata log private"
      

实现步骤

1. 修改分区表

分区表定义新分区。以 device/horizon/x5/board_cfg/soc/x5-soc-debug-gpt.json 为例,添加如下配置:

"app": {
    "fs_type": "ext4",
    "part_type": "GOLDEN",
    "size": "700m"
},
  • fs_type:分区文件系统类型,设置ext4

  • size:分区大小,单位为 MB(示例700m)。

有关分区表配置信息,请参考分区配置

2. 准备分区内容

创建一个用于存放分区文件目录(如 app),并其中添加需要文件。例如,添加一个名为 startup.sh启动脚本:

# 在 BSP 源码根目录下执行以下命令
mkdir app
cd app
echo "#!/bin/sh" > startup.sh
echo 'echo "This is the test code"' >> startup.sh
chmod 777 startup.sh

新增分区为空,此步骤过。当前系统/app 和 /userdata  目录startup.sh 程序/etc/init.d/S99auto_startup 服务系统启动调用执行。

3. 验证生成分区镜像

参考以下编译程序,根据分区目录内容生成镜像,例如:

./build/mk_app.sh

生成镜像文件位于 out/product/app.img。若新增分区为空,可步骤。

4. 集成编译脚本

xbuild.sh添加分区编译逻辑:

  • avail_func添加分区选项:

    avail_func=("all" "lunch" "miniboot" "uboot" "factory" "boot" "hbre" "system" "app" "pack" "otapackage")
    
  • 定义 build_app 函数:

    function build_app {
        is_exist=$(get_part_exist app)
        if [ "$is_exist" = "0" ]; then
            return
        fi
        build_component "app" "${HR_LOCAL_DIR}/mk_app.sh" "$@"
    }
    
  • 整体编译逻辑加入 app 分区:

    if [ -d "${HR_TOP_DIR}/app" ]; then
        build_app "$opt"
    fi
    

以上代码添加完成后,可通过 ./bd.sh app./mk_app.sh 编译生成 app.img

5. 自动挂载分区

系统添加分区后,为确保分区启动自动挂载,需要system/buildroot/prebuilt/boot-utils-runtime/etc/hb-fstab 文件添加对应挂载配置。例如,新增 app 分区挂载配置如下:

/dev/block/platform/by-name/app  /app  ext4  defaults  0  1

以下各字含义相关注意事项:

  • 设备路径 (/dev/block/platform/by-name/app)

    • 指定分区设备路径。

    • 根据设备分区配置,此路径可能有所不同,请确保实际设备路径一致。

  • 挂载 (/app)

    • 指定分区挂载目标目录。

    • 系统启动时,分区内容挂载目录下。

    • 需要确保目录镜像制作过程创建,否则系统无法挂载分区,可能导致启动失败。例如mk_system.shbuild_unpack 函数添加目录创建逻辑:

      mkdir -p ${SYSTEM_BUILD_DIR}/{app,log,userdata,usr/hobot,data,private}
      
  • 文件系统类型 (ext4)

    • 指定分区文件系统类型。

    • 根据分区实际文件系统格式选择合适值(如 ext4vfat 等)。

    • 此处必须分区表配置fs_type 一致。

  • 挂载选项 (defaults)

    • 使用默认挂载选项。defaults一个预定选项集合,它包括以下特性:

      • rw(读写模式):允许分区进行读写操作。

      • suid(允许设置用户 ID):允许执行文件的 SUID(Set User ID)和 SGID(Set Group ID)权限。这允许某些程序执行时以文件所有者权限运行。

      • dev(允许设备文件):允许分区存在设备文件(如/dev目录文件)。

      • exec(允许执行文件):允许分区执行文件。

      • auto(自动挂载):允许分区系统启动自动挂载。

      • nouser(不允许普通用户挂载):只有 root 用户具有特定权限用户才能挂载分区。

      • async(异步 I/O):允许异步 I/O 操作,提高性能。

    • app分区挂载配置中,defaults选项具体含义如下:

      • 分区设备/dev/block/platform/by-name/app读写模式挂载挂载/app

      • 分区文件可以设置 SUID/SGID 权限,以支持特定程序权限需求。

      • 分区文件可以系统执行,确保应用程序正常运行。

      • 分区系统启动自动挂载,无需手动干预。

      • 只有 root 用户具有特定权限用户可以挂载分区,以增强系统安全性。

      • I/O 操作异步方式执行,从而提高分区性能表现。

    • defaults 选项可以确保分区挂载具备基本读写执行权限。

    • 如果需要自定义挂载参数,可根据需求替换实际参数。例如:

      • ro:只读挂载。

      • rw:读写挂载(默认)。

      • noexec:禁止执行分区二进制文件。

      • nosuid:禁止设置 SUID 和 SGID 标志位。

  • 备份标志 (0)

    • 指定分区是否需要 dump 备份。

    • 设置0 表示备份,是通常设置0

  • 文件系统检查顺序 (1)

    • 指定系统启动检查文件系统顺序。

    • 0 表示检查分区。

    • 非零值表示检查顺序,数字越小,优先级越高。

6. 打包分区系统镜像

完成所有配置后,可以通过编译脚本生成分区镜像,并新增分区镜像 pack 到系统镜像中。

使用以下命令执行完整编译打包流程:

./bd.sh

如果新增分区分区(即镜像生成时未包含实际数据,如 userdata 分区),可以选择跳过分区镜像打包操作。在 xbuild.sh 脚本truncate_fill_image 函数中,可以如下方式调整逻辑:

# FIXME: If there is actual data in the partition behind the mirror, pack will be skipped.
# 先固定跳过 log 和 userdata 分区,要优化成根据配置来找到最后一个有数据的分区
case "${part_name}" in
    log*|userdata*|app*)
        rm -f "${HR_TARGET_PRODUCT_DIR}/${part_name}".img
        ;;
esac

完成以上步骤后,新增分区(如 app 分区)将编译合并系统镜像中。 如需验证,可以检查镜像文件 out/product/app.img 是否存在,并通过刷机启动系统验证新增分区功能是否正常。

验证

完成机后:

  • 系统启动如果用户通过串口连接设备,那么可以串口打印日志看到 This is the test code日志输出,说明 /app/startup.sh 已经运行。

  • 使用 fdisk -l 查看分区表,确认 app 分区存在,大小700MB(分区大小需要实际分区表配置对齐)。

  • 使用 mount 确认分区挂载/app

  • 使用 ls /app 查看分区内容,确认 startup.sh 存在执行。

    示例输出:

    # ls /app/
    startup.sh  lost+found