RK3588 分区

发布于 14 小时前  6 次阅读


一、分区设置

原始配置:

FIRMWARE_VER: 1.0
MACHINE_MODEL: RK3588
MACHINE_ID: 007
MANUFACTURER: RK3588
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 0xffffffff
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
GROW_ALIGN: 0
CMDLINE: mtdparts=:0x00002000@0x00004000(uboot),0x00002000@0x00006000(misc),0x00020000@0x00008000(boot),0x00080000@0x00028000(recovery),0x00010000@0x00108000(backup),-@0x00118000(rootfs:grow)
uuid:rootfs=614e0000-0000-4b53-8000-1d28000054a9
uuid:boot=7A3F0000-0000-446A-8000-702F00006273

新配置:

FIRMWARE_VER: 1.0
MACHINE_MODEL: RK3588
MACHINE_ID: 007
MANUFACTURER: RK3588
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 0xffffffff
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
GROW_ALIGN: 0
CMDLINE: mtdparts=:0x00002000@0x00004000(uboot),0x00002000@0x00006000(misc),0x00020000@0x00008000(boot),0x00080000@0x00028000(recovery),0x00010000@0x00108000(backup),0x00400000@0x00118000(rootfs),0x00040000@0x00518000(app),0x00040000@0x00558000(oemven),-@0x00598000(userdata:grow)
uuid:rootfs=614e0000-0000-4b53-8000-1d28000054a9
uuid:boot=7A3F0000-0000-446A-8000-702F00006273

修改项为:

  1. 限制rootfs分区大小;
  2. 新增app和oemven分区;
  3. 修改userdata分区配置。

二、镜像打包

  镜像打包可以调用mk-image.sh来实现,其调用方式为:

Usage: $0 <src_dir> <target_image> <fs_type> <size(M|K)|auto(0)> [label]

完整的mk-image.sh如下:

#!/bin/bash

# Prefer using buildroot host tools for compatible.
if [ -n "$RK_BUILDROOT_CFG" ]; then
    HOST_DIR="$SDK_DIR/buildroot/output/$RK_BUILDROOT_CFG/host"
    export PATH=$HOST_DIR/usr/sbin:$HOST_DIR/usr/bin:$HOST_DIR/sbin:$HOST_DIR/bin:$PATH
    echo "Using host tools in $HOST_DIR"
else
    "$(dirname "$(realpath "$0")")/check-mkimage.sh"
fi

fatal()
{
    echo -e "FATAL: " $@
    exit 1
}

usage()
{
    echo $@
    fatal "Usage: $0 <src_dir> <target_image> <fs_type> <size(M|K)|auto(0)> [label]"
}

[ ! $# -lt 4 ] || usage "Not enough args${@+: $0 $@}"

export SRC_DIR=$1
export TARGET=$2
FS_TYPE=$3
SIZE=$4
LABEL=$5

case $SIZE in
    auto)
        SIZE_KB=0
        ;;
    *K)
        SIZE_KB=$(( ${SIZE%K} ))
        ;;
    *)
        SIZE_KB=$(( ${SIZE%M} * 1024 )) # default is MB
        ;;
esac

echo $SIZE_KB | grep -vq [^0-9] || usage "Invalid size: $SIZE_KB"

TEMP=$(mktemp -u)

[ -d "$SRC_DIR" ] || usage "No such src dir: $SRC_DIR"

copy_to_ntfs()
{
    DEPTH=1
    while true;do
        find $SRC_DIR -maxdepth $DEPTH -mindepth $DEPTH -type d|grep -q "" \
            || break
        find $SRC_DIR -maxdepth $DEPTH -mindepth $DEPTH -type d \
            -exec sh -c 'ntfscp $TARGET "$1" "${1#$SRC_DIR}"' sh {} \; || \
        fatal "Detected non-buildroot ntfscp(doesn't support dir copy)"
        DEPTH=$(($DEPTH + 1))
    done

    find $SRC_DIR -type f \
        -exec sh -c 'ntfscp $TARGET "$1" "${1#$SRC_DIR}"' sh {} \; || \
            fatal "Failed to do ntfscp!"
}

copy_to_image()
{
    ls $SRC_DIR/* &>/dev/null || return 0

    echo "Copying $SRC_DIR into $TARGET (root permission required)"
    mkdir -p $TEMP || return 1
    sudo mount $TARGET $TEMP || return 1

    cp -rp $SRC_DIR/* $TEMP
    RET=$?

    sudo umount $TEMP
    rm -rf $TEMP

    return $RET
}

check_host_tool()
{
    which $1|grep -wq buildroot
}

mkimage()
{
    echo "Making $TARGET from $SRC_DIR with size(${SIZE_KB}KB)"
    rm -rf $TARGET
    dd of=$TARGET bs=1K seek=$SIZE_KB count=0 &>/dev/null || \
        fatal "Failed to dd image!"
    case $FS_TYPE in
        ext[234])
            if mke2fs -h 2>&1 | grep -wq "\-d"; then
                mke2fs -t $FS_TYPE $TARGET -d $SRC_DIR \
                    || return 1
            else
                echo "Detected old mke2fs(doesn't support '-d' option)!"
                mke2fs -t $FS_TYPE $TARGET || return 1
                copy_to_image || return 1
            fi
            # Set max-mount-counts to 0, and disable the time-dependent checking.
            tune2fs -c 0 -i 0 $TARGET ${LABEL:+-L $LABEL}
            ;;
        msdos|fat|vfat)
            # Use fat32 by default
            mkfs.vfat -F 32 $TARGET ${LABEL:+-n $LABEL} && \
                MTOOLS_SKIP_CHECK=1 \
                mcopy -bspmn -D s -i $TARGET $SRC_DIR/* ::/
            ;;
        ntfs)
            # Enable compression
            mkntfs -FCQ $TARGET ${LABEL:+-L $LABEL}
            if check_host_tool ntfscp; then
                copy_to_ntfs
            else
                copy_to_image
            fi
            ;;
        ubi|ubifs)
            mk_ubi_image
            ;;
    esac
}

mkimage_auto_sized()
{
    tar cf $TEMP $SRC_DIR &>/dev/null
    SIZE_KB=$(du -k $TEMP|grep -o "^[0-9]*")
    rm -rf $TEMP
    echo "Making $TARGET from $SRC_DIR (auto sized)"

    MAX_RETRY=10
    RETRY=0

    while true;do
        EXTRA_SIZE=$(($SIZE_KB / 50))
        SIZE_KB=$(($SIZE_KB + ($EXTRA_SIZE > 4096 ? $EXTRA_SIZE : 4096)))
        mkimage && break

        RETRY=$[RETRY+1]
        [ $RETRY -gt $MAX_RETRY ] && fatal "Failed to make image!"
        echo "Retring with increased size....($RETRY/$MAX_RETRY)"
    done
}

mk_ubi_image()
{
    TARGET_DIR="${RK_OUTDIR:-$(dirname "$TARGET")}"
    UBI_VOL_NAME=${LABEL:-ubi}

    # default page size 2KB
    UBI_PAGE_SIZE=${RK_UBI_PAGE_SIZE:-2048}
    # default block size 128KB
    UBI_BLOCK_SIZE=${RK_UBI_BLOCK_SIZE:-0x20000}

    UBIFS_LEBSIZE=$(( $UBI_BLOCK_SIZE - 2 * $UBI_PAGE_SIZE ))
    UBIFS_MINIOSIZE=$UBI_PAGE_SIZE

    UBIFS_IMAGE="$TARGET_DIR/$UBI_VOL_NAME.ubifs"
    UBINIZE_CFG="$TARGET_DIR/${UBI_VOL_NAME}-ubinize.cfg"

    UBIFS_MAXLEBCNT=$(( $SIZE_KB * 1024 / $UBIFS_LEBSIZE ))

    mkfs.ubifs -x lzo -e $UBIFS_LEBSIZE -m $UBIFS_MINIOSIZE \
        -c $UBIFS_MAXLEBCNT -d $SRC_DIR -F -v -o $UBIFS_IMAGE || return 1

    echo "[ubifs]" > $UBINIZE_CFG
    echo "mode=ubi" >> $UBINIZE_CFG
    echo "vol_id=0" >> $UBINIZE_CFG
    echo "vol_type=dynamic" >> $UBINIZE_CFG
    echo "vol_name=$UBI_VOL_NAME" >> $UBINIZE_CFG
    echo "vol_size=${SIZE_KB}KiB" >> $UBINIZE_CFG
    echo "vol_alignment=1" >> $UBINIZE_CFG
    echo "vol_flags=autoresize" >> $UBINIZE_CFG
    echo "image=$UBIFS_IMAGE" >> $UBINIZE_CFG
    ubinize -o $TARGET -m $UBIFS_MINIOSIZE -p $UBI_BLOCK_SIZE \
        -v $UBINIZE_CFG
}

rm -rf $TARGET
case $FS_TYPE in
    ext[234]|msdos|fat|vfat|ntfs|ubi|ubifs)
        if [ $SIZE_KB -eq 0 ]; then
            mkimage_auto_sized
        else
            mkimage && echo "Generated $TARGET"
        fi
        ;;
    squashfs)
        [ $SIZE_KB -eq 0 ] || fatal "$FS_TYPE: fixed size not supported."
        mksquashfs $SRC_DIR $TARGET -noappend -comp lz4
        ;;
    jffs2)
        [ $SIZE_KB -eq 0 ] || fatal "$FS_TYPE: fixed size not supported."
        mkfs.jffs2 -r $SRC_DIR -o $TARGET 0x10000 --pad=0x400000 -s 0x1000 -n
        ;;
    *)
        usage "File system: $FS_TYPE not supported."
        ;;
esac

  进一步地,我现在有如下的一个目录:

.
├── app
│   ├── ai
│   ├── cl
│   ├── pre
│   ├── pseudo
│   └── ui
├── app.img
├── mk-image.sh
├── oemven
│   └── bootanimation
├── oemven.img
├── package.sh
├── userdata
└── userdata.img

我有三个文件夹:appoemvenuserdata,我使用了如下的package.sh来进行打包

#!/bin/bash

# 检查参数
if [ $# -ne 1 ]; then
    echo "Usage: $0 <partition_name>"
    echo "Supported partitions: app, oemven, userdata"
    exit 1
fi

# 获取脚本所在目录的绝对路径
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# 分区名称
PARTITION=$1

# 定义固定大小分区的大小
FIXED_SIZE="128M"

# 检查分区名是否有效并设置大小
case $PARTITION in
    "app"|"oemven")
        # 使用固定大小
        PARTITION_SIZE=$FIXED_SIZE
        ;;
    "userdata")
        # 使用自动大小
        PARTITION_SIZE="auto"
        ;;
    *)
        echo "Error: Invalid partition name"
        echo "Supported partitions: app, oemven, userdata"
        exit 1
        ;;
esac

# 设置参数
SOURCE_DIR="${SCRIPT_DIR}/${PARTITION}"
IMAGE_NAME="${PARTITION}.img"
FS_TYPE="ext4"

# 检查源目录是否存在
if [ ! -d "$SOURCE_DIR" ]; then
    echo "Error: Source directory '$SOURCE_DIR' not found"
    exit 1
fi

# 检查mk-image.sh是否存在
if [ ! -f "${SCRIPT_DIR}/mk-image.sh" ]; then
    echo "Error: mk-image.sh not found in $SCRIPT_DIR"
    exit 1
fi

# 执行打包命令
echo "Creating image for $PARTITION..."
echo "Source: $SOURCE_DIR"
echo "Target: $IMAGE_NAME"
echo "Filesystem: $FS_TYPE"
echo "Size: $PARTITION_SIZE"

"${SCRIPT_DIR}/mk-image.sh" "$SOURCE_DIR" "$IMAGE_NAME" "$FS_TYPE" "$PARTITION_SIZE" "$PARTITION"

# 检查执行结果
if [ $? -eq 0 ]; then
    echo "Successfully created $IMAGE_NAME"
else
    echo "Error: Failed to create $IMAGE_NAME"
    exit 1
fi

三、镜像挂载

  我们可以通过cat /sys/class/block/mmcblk0p7/uevent来查看mmcblk0p7对应的信息:

root@HGD:/# cat /sys/class/block/mmcblk0p7/uevent 
MAJOR=179
MINOR=7
DEVNAME=mmcblk0p7
DEVTYPE=partition
PARTN=7
PARTNAME=app

可以看到,该分区对应app

  我们通过mount来挂载分区:

mkdir -p /app
mount -t ext4 /dev/mmcblk0p7 /app

  我们通过umount来取消挂载,使用dd来写入分区:

umount /oemven
# backup
dd if=/dev/mmcblk0p8 of=oemven.img.bak bs=4M
# write new
dd if=oemven.img of=/dev/mmcblk0p8 bs=4M conv=fsync status=progress
sync
mount /dev/mmcblk0p8 /oemven

  下面是一个开机自启的挂载脚本:

#!/bin/sh -e
# Auto mount partitions

# 定义挂载信息
MOUNT_POINTS="/app /oemven /userdata"
DEVICES="/dev/mmcblk0p7 /dev/mmcblk0p8 /dev/mmcblk0p9"

# 创建目录并挂载
mount_partitions() {
    echo -n "Mounting partitions... "

    # 创建挂载点(如果不存在)
    for mount_point in $MOUNT_POINTS; do
        if [ ! -d "$mount_point" ]; then
            mkdir -p "$mount_point"
            if [ $? -ne 0 ]; then
                echo "Failed to create directory: $mount_point"
                return 1
            fi
        fi
    done

    # 挂载分区
    mount -t ext4 /dev/mmcblk0p7 /app
    mount -t ext4 /dev/mmcblk0p8 /oemven
    mount -t ext4 /dev/mmcblk0p9 /userdata

    echo "done."
    return 0
}

# 卸载分区
umount_partitions() {
    echo -n "Unmounting partitions... "

    # 逆序卸载分区
    for device in $DEVICES; do
        if mount | grep -q "$device"; then
            umount "$device"
            if [ $? -ne 0 ]; then
                echo "Failed to unmount: $device"
                return 1
            fi
        fi
    done

    echo "done."
    return 0
}

# 检查挂载状态
check_mounts() {
    echo "Checking mount status:"
    df -h | grep "mmcblk0p[789]"
}

case "$1" in
    start)
        echo "Starting auto mount..."
        mount_partitions
        check_mounts
        ;;
    stop)
        echo "Stopping auto mount..."
        umount_partitions
        ;;
    restart|reload)
        echo "Restarting auto mount..."
        umount_partitions
        mount_partitions
        check_mounts
        ;;
    status)
        check_mounts
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
esac

exit 0

除了使用脚本,还可以通过修改fstab来挂载分区。