4.4.2. Integrating User Software into System Image

During development, it is often necessary to directly include certain configuration files or completed programs into the system image, so that these files or programs can be used directly on the target device when it runs. This chapter details two commonly used methods for integrating user software and files into the system image:

  1. Adding files to the system partition of the root file system

    This method is suitable for files that need to be deployed alongside system files, such as system libraries or system configuration files. By placing files in the system partition, they can be loaded and used immediately upon device boot.

  2. Creating a new dedicated partition to store custom files

    By creating a new partition and storing custom files or programs within it, greater flexibility and modularity can be achieved. The new partition generates an independent image file, making management and updates easier, while also avoiding any impact on the root file system.

Each method has its own characteristics, and the appropriate integration approach can be selected based on requirements to optimize development and deployment workflows. The following sections describe both methods in detail.

4.4.2.1. Adding Files to the system Partition of the Root File System

Integrating user-defined files into the root file system is very simple. Just copy the prepared files into the directory system/buildroot/prebuilt/boot-utils-runtime. During compilation of the system image, all contents in this directory will be automatically packaged into the system partition without requiring additional steps. The build script responsible for merging these files is located in the BSP source code at build/mk_system.sh, with the implementation shown below:

function build_unpack()
{
        ... (omitted) ...

        # Merge auto-start configuration items
        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
}

Notes:

  • The actual size of the system partition may vary depending on the software version. If the added files cause the total size of the partition to exceed its predefined capacity, image generation will fail. To avoid this issue, the size of the system partition can be adjusted by modifying the partition table. For detailed instructions, refer to Partition Configuration.

Before proceeding, confirm the capacity limit of the system partition and ensure that the added files do not exceed available space.

4.4.2.2. Creating a Dedicated Partition for Custom Files

To manage programs or configuration files more flexibly, a new dedicated partition can be created specifically for storing such content. This approach is particularly suitable for scenarios where programs need to be independently compiled, managed, and upgraded. This section uses the configuration of an app partition as an example to illustrate the procedure (the app partition is supported by default).

Notes

  1. Regarding the Last Partition in the Partition Table

    If the newly added partition is placed after the last partition in the partition table (e.g., after the userdata partition), note the following behaviors:

    • During system startup, the U-Boot stage automatically extends the last partition to the end of the physical storage device (e.g., eMMC or NAND Flash) to maximize storage utilization.

    • On first boot, if the kernel detects that the last partition is unformatted or lacks a valid file system, it will automatically perform formatting.

  2. Default Settings for the userdata Partition

    • During system image generation, the userdata partition is typically the last partition, contains no data, and is set to a small size (default 50MB) to reduce image size.

    • After booting, U-Boot automatically expands the userdata partition to occupy the remaining storage space, and the system formats this partition upon first entry.

    • If adding a new partition after userdata, adjust the size of userdata accordingly to meet actual requirements.

  3. About Empty Partitions

    • If the new partition is empty (no valid data, such as userdata or private) during image creation, it must be formatted during the first system boot.

    • The formatting logic can be referenced from the /etc/init.d/S65mountall script. Add the new partition name to the force_format_part_list variable, for example:

      force_format_part_list="app userdata log private"
      

Implementation Steps

1. Modify the Partition Table

Define the new partition in the partition table. For example, in device/horizon/x5/board_cfg/soc/x5-soc-debug-gpt.json, add the following configuration:

"app": {
    "fs_type": "ext4",
    "part_type": "GOLDEN",
    "size": "700m"
},
  • fs_type: File system type of the partition, set to ext4.

  • size: Size of the partition, in MB (example: 700m).

For more information about partition table configuration, please refer to Partition Configuration.

2. Prepare Partition Content

Create a directory (e.g., app) to store the partition’s files and add required files. For example, add a startup script named startup.sh:

# Execute the following commands under the BSP source root directory
mkdir app
cd app
echo "#!/bin/sh" > startup.sh
echo 'echo "This is the test code"' >> startup.sh
chmod 777 startup.sh

This step can be skipped if the new partition is intended to be empty. In the current system, the startup.sh scripts under /app and /userdata are invoked during system startup by the /etc/init.d/S99auto_startup service.

3. Verify and Generate Partition Image

Refer to the following build command to generate the image based on the partition directory content, for example:

./build/mk_app.sh

The generated image file will be located at out/product/app.img. This step can be skipped if the new partition is empty.

4. Integrate Build Script

Add partition build logic into xbuild.sh:

  • Add the partition option in avail_func:

    avail_func=("all" "lunch" "miniboot" "uboot" "factory" "boot" "hbre" "system" "app" "pack" "otapackage")
    
  • Define the build_app function:

    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" "$@"
    }
    
  • Include the app partition in the overall build logic:

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

After adding the above code, you can compile and generate app.img using ./bd.sh app or ./mk_app.sh.

5. Automatically Mount the New Partition

After adding a new partition to the system, to ensure it is automatically mounted at boot time, add the corresponding mount configuration in the file system/buildroot/prebuilt/boot-utils-runtime/etc/hb-fstab. For example, the mount configuration for the new app partition is as follows:

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

Below is the meaning of each field and related notes:

  • Device Path (/dev/block/platform/by-name/app)

    • Specifies the path to the partition device.

    • This path may vary depending on the hardware and partition configuration; ensure it matches the actual device path.

  • Mount Point (/app)

    • Specifies the target directory where the partition will be mounted.

    • At system startup, the partition contents will be mounted under this directory.

    • Ensure this directory is created during image generation; otherwise, the system may fail to mount the partition, potentially causing boot failure. For example, add directory creation logic in the build_unpack function of mk_system.sh:

      mkdir -p ${SYSTEM_BUILD_DIR}/{app,log,userdata,usr/hobot,data,private}
      
  • File System Type (ext4)

    • Specifies the file system type of the partition.

    • Choose the appropriate value according to the actual file system format (e.g., ext4, vfat, etc.).

    • This must match the fs_type configured in the partition table.

  • Mount Options (defaults)

    • Uses default mount options. defaults is a predefined set of options that includes:

      • rw (read-write mode): Allows read and write operations on the partition.

      • suid (allow set-user-ID): Allows execution of files with SUID (Set User ID) and SGID (Set Group ID) permissions, enabling certain programs to run with the file owner’s privileges.

      • dev (allow device files): Allows device files (e.g., those in /dev) to exist within the partition.

      • exec (allow execution of files): Allows execution of binaries and scripts within the partition.

      • auto (automatic mounting): Enables automatic mounting of the partition at system startup.

      • nouser (disallow mounting by regular users): Only root or users with specific privileges can mount the partition.

      • async (asynchronous I/O): Enables asynchronous I/O operations, improving performance.

    • In the app partition’s mount configuration, the defaults option means:

      • The device /dev/block/platform/by-name/app will be mounted read-write to /app.

      • Files in the partition can have SUID/SGID bits set to support specific program privilege requirements.

      • Executables in the partition can be run, ensuring application functionality.

      • The partition will be automatically mounted at boot without manual intervention.

      • Only root or privileged users can mount the partition, enhancing system security.

      • I/O operations will be performed asynchronously, improving performance.

    • The defaults option ensures the partition has basic read, write, and execute permissions upon mount.

    • If custom mount parameters are needed, replace defaults with specific options. For example:

      • ro: Mount read-only.

      • rw: Mount read-write (default).

      • noexec: Prohibit execution of binaries in the partition.

      • nosuid: Disallow SUID and SGID flags.

  • Dump Backup Flag (0)

    • Indicates whether the partition should be backed up by the dump utility.

    • Set to 0 means no backup, which is the usual setting.

  • File System Check Order (1)

    • Specifies the order in which the file system is checked at boot time.

    • 0 means no check.

    • Non-zero values indicate check priority, with smaller numbers having higher priority.

6. Package the Partition into the System Image

After completing all configurations, use the build script to generate the partition image and pack the new partition image into the system image.

Run the full build and packaging process using the following command:

./bd.sh

If the new partition is empty (i.e., contains no actual data during image generation, like the userdata partition), you may choose to skip packing its image. In the truncate_fill_image function of the xbuild.sh script, adjust the logic as follows:

# FIXME: If there is actual data in the partition behind the mirror, pack will be skipped.
# Currently skipping log and userdata partitions; should be optimized to identify the last partition with data based on configuration
case "${part_name}" in
    log*|userdata*|app*)
        rm -f "${HR_TARGET_PRODUCT_DIR}/${part_name}".img
        ;;
esac

After completing the above steps, the new partition (e.g., app) will be compiled and integrated into the system image.
To verify, check whether the image file out/product/app.img exists, and validate the functionality of the new partition by flashing or booting the system.

Verification

After flashing:

  • If the user connects to the device via serial console during system startup, the log output This is the test code should appear in the serial logs, indicating that /app/startup.sh has executed.

  • Use fdisk -l to view the partition table and confirm the existence of the app partition with a size of 700MB (the size must match the actual partition table configuration).

  • Use mount to confirm the partition is mounted at /app.

  • Use ls /app to check the partition contents and confirm that startup.sh exists and is executable.

    Example output:

    # ls /app/
    startup.sh  lost+found