调整 Linux 布局

备注

本章的内容适用于 NAND flash。

如何缩减固件的大小

在某些情况下,用户可能需要减小固件大小。以下是关于如何缩小固件大小的说明。

如何缩减 ROOTFS 固件的大小

可以删除这些目录中不需要的插件。

<sdk>/sources/yocto/meta-realtek/meta-sdk/recipes-core/images/ameba-image-core.bb
<sdk>/sources/yocto/meta-realtek/meta-realtek-bsp/recipes-core/packagegroups/packagegroup-rtk-commands.bb
<sdk>/sources/yocto/meta-realtek/meta-realtek-bsp/recipes-core/packagegroups/packagegroup-rtk-network.bb

再次编译,生成一个新的 rootfs.img,你会发现它的大小比之前更小。

如何缩减 KERNEL 固件的大小

制定新的布局

在章节 如何缩减 ROOTFS 固件的大小如何缩减 KERNEL 固件的大小 的步骤之后,分区大小的示例如下。其中,遵循的 OEM 是预期的一个额外分区(下同)。

../../_images/formulate_new_layout.png

备注

  • 恢复内核是 initramfs,具有固定大小,固件大小为 4.484M,因此内核分区至少为 5M。

  • NAND 闪存分区的基本单位是块(其大小为 128KB),因此布局的划分应为块的整数倍。

  • 不建议减少 km4_boot_all.bin、km0_km4_app.bin、boot.img 和 vbmeta.img 的大小,因为它们本身就较小,只占用很少的块,减少它们的成本相对较高。

  • vbmeta.img 和 dtb.img 的总大小小于一个块。然而,如果只为它们分配一个块,由于 NAND 中可能存在坏块,如果为它们分配的块是坏的,那这些固件就无法再被写入。因此,为了系统的鲁棒性,建议为它们至少分配两个块。

DTS 中每个布局的偏移量和大小

例如,对于 generic 128M 机器,DTS 中每个布局的偏移量和大小如下所示。

../../_images/offset_size_layout_in_dts.png

其中,A 表示 dtb 和内核的 A 部分,B 表示 dtb 和内核的 B 部分。十六进制值是基于 FLASH 基地址的偏移量。

ImageTool 中每个布局的偏移量和大小

例如,对于 generic 128M 机器,ImageTool 中每个布局的偏移量和大小如下所示。其中所有十六进制值均通过 DTS 中每个布局的偏移量和大小 章节中的偏移量计算得出。

../../_images/offset_size_layout_imagetool.png

备注

必须确保最后的结束地址等于 0x10000000。

如何调整 DTS 中布局的大小

对于内核 5.4.x,DTS 文件的目录是 <sdk>/sources/kernel/linux-5.4/arch/arm/boot/dts ,对于内核 6.6.x,目录是 <sdk>/kernel/linux-6.6/arch/arm/boot/dts/realtek/ameba

用户可以根据 DTS 中每个布局的偏移量和大小 章节中的偏移量和大小,配置分区 reg 的值。

下图显示了调整 DTS 中布局前后的对比示例。

../../_images/before_adjust_layout_dts.png
../../_images/after_adjust_layout_dts.png

如何调整 Uboot defconfig

defconfig 文件的路径是:

<sdk>/sources/boot/uboot/configs

CONFIG_MTDPARTS_DEFAULT

修改前

CONFIG_MTDPARTS_DEFAULT="mtdparts=spi-nand0:0x20000@0x20000(cert-bin),0x40000@0x620000(misc),0x40000@0x6A0000(vbmeta),0x40000@0x6E0000(r-vbmeta),0x60000@0x780000(r-dtb),0xA00000@0x11E0000(r-uImage),0x60000@0x720000(dtb),0xA00000@0x7E0000(uImage)"

修改后

根据 DTS 中每个布局的偏移量和大小 章节中的偏移量和大小, CONFIG_MTDPARTS_DEFAULT 应该为:

CONFIG_MTDPARTS_DEFAULT="mtdparts=spi-nand0:0x20000@0x20000(cert-bin),0x40000@0x620000(misc),0x40000@0x6A0000(vbmeta),0x40000@0x6E0000(r-vbmeta),0x40000@0x760000(r-dtb),0x500000@0XCA0000(r-uImage),0x40000@0x720000(dtb),0x500000@0x7A0000(uImage)"

IMAGE 加载到 DDR 配置

NAND 允许有 2% 的坏块,因此此处加载固件的大小应略小于 DTS 中每个布局的偏移量和大小 章节中计算的大小。

IMG_FLASH_SIZE:

从闪存传输到 DDR 的内核固件的大小。

FDT_FLASH_SIZE:

从闪存传输到 DDR 的 dtb 固件的大小。分配给 dtb 固件的空间已经是最大值(64KB),因此 FDT_FLASH_SIZE 将不再调整。

RECOVERY_IMG_FLASH_SIZE:

从闪存传输到 DDR 的恢复内核固件的大小。

RECOVERY_FDT_FLASH_SIZE:

从闪存传输到 DDR 的恢复 dtb 固件的大小。

SYS_TEXT_BASE:

固件从闪存传输到 DDR 后的 DDR 起始地址(不调整)。

KERNEL_ADDR:

传输到 DDR 的内核固件的起始地址(不调整)。

FDT_ADDR:

传输到 DDR 的 dtb 固件的起始地址。分配给 dtb 固件的空间已经是最大值(64KB),因此 FDT_ADDR 将不再调整。

修改前后的对比如下所示。

../../_images/before_modification.png
../../_images/after_modification.png

内核和 dtb 在 DDR 中的位置本来就很小,因此不需要额外修改。恢复 initramfs 的大小需要为 0x500000 保留一个坏块,因此调整为 0x4E0000。

编译时如何调整 UBI 的大小

userdata ubi -c

其位于 <sdk>/source/yocto/meta-sdk/recipes-core/images/ameba-image-userdata.bb

在修改前,内容如下:

MKUBIFS_ARGS = "-m 2048 -e 126976 -c 297 --jrn-size=380928"

然后你将其大小调整为 56.75M,首先向下取整为 56M,然后按照以下公式计算:

\[56 * 8 – 44 = 404\]
MKUBIFS_ARGS = "-m 2048 -e 126976 -c 404 --jrn-size=380928"

rootfs ubi -c

其位于 <sdk>/source/yocto/meta-realtek-bsp/conf/machine/rtl8730elh-va7.conf

在修改前,内容如下:

MKUBIFS_ARGS = "-F -m 2048 -e 126976 -c 436 -j 380928"

然后你将其大小调整为 20.19M,首先向下取整为 20M,然后按照以下公式计算:

\[20 * 8 - 44 = 116\]
MKUBIFS_ARGS = "-F -m 2048 -e 126976 -c 116 -j 380928"

如何调整 ImageTool 的布局

修改之前,默认的起始地址和结束地址在 ImageTool 中显示如下。

../../_images/address_before_modification.png

你可以根据 ImageTool 中每个布局的偏移量和大小 章节调整起始地址或结束地址。

修改后,新的起始地址与结束地址可能如下所示。

../../_images/address_after_modification.png

添加 OEM 分区

新文件 ameba-image-oem.bb

用户可以在路径 <sdk>/sources/yocto/meta-realtek/meta-sdk/recipes-core/images 中添加新文件 ameba-image-oem.bb,其内容如下:

# Copyright 2023 Realtek.
# Released under the MIT license (see COPYING.MIT for the terms)
SUMMARY = "This is the oem image."
IMAGE_FSTYPES = "ubi"
MKUBIFS_ARGS = "-m 2048 -e 126976 -c 260 --jrn-size=380928"
UBINIZE_ARGS = "-m 2048 -p 131072"
UBI_IMGTYPE = "ubifs"
IMAGE_NAME_SUFFIX = ".oem"
IMAGE_INSTALL = ""
IMAGE_LINGUAS = ""
PACKAGE_INSTALL = ""
inherit image

这里的 260 是按照如下公式所计算得到:

\[38 * 8 - 44\]

用户可以使用 bitbake 命令来编译这个 ameba-image-oem。

在 DTS 中挂载 MTD 块

对于 generic 128M 机器,用户可以修改文件 rtl8730e-spi-nand-128m.dtsi 以挂载特定的 MTD 块。

这里,我们在 dts 文件中添加一个 MTD block 10。

// Add ubi.mtd=10 at end of this line.
bootargs = "console=ttyS0,1500000 earlycon psci=enable ubi.mtd=8 ubi.block=0,0 root=/dev/ubiblock0_0 rootfstype=squashfs,ubifs ubi.mtd=9 ubifs ubi.mtd=10";

自动加载 OEM 分区

用户可以在脚本文件 <sdk>/sources/yocto/meta-realtek/meta-realtek-bsp/recipes-core/initscripts/initscripts-1.0/overlay.sh 中添加步骤,使 OEM 分区自动挂载。

pivot_root /mnt/merged /mnt/merged/rom
#Add the procedure here.
mkdir -p /oem
mount -t ubifs /dev/ubi2_0 /oem
if [ ! -e /run/udev ] ; then
mkdir -p /run/udev
fi

另一种方法是,用户可以通过修改 rcS 文件来实现自动挂载: <sdk>/sources/yocto/meta-realtek/meta-sdk/recipes-rtk/rtk-rc-local/rtk-rc-local/rcS 。用户可以选择其中任意一种方式。

cat /etc/motd
#Add the procedure here.
mkdir -p /oem
mount -t ubifs /dev/ubi2_0 /oem
# Set country to Worldwide
#iw reg set 00

单独编译 OEM。

bitbake ameba-image-oem

编译

在编译新的固件之前,用户需执行 mclean 来清理旧的固件。

mclean

执行 m 或者 bitbake 来最后编译新的固件。

调试

在 Uboot 阶段无法加载内核

在 uboot 加载内核时可能会出现问题,如下图所示。用户可以执行 env print 或者 printenv ,然后可以看到环境变量与预期不同。

../../_images/load_kernel_at_uboot.png

对于此问题,建议用户检查以下信息:

  1. 参考 如何调整 Uboot defconfig 章节,确保被修改的内容符合预期。

  2. 首先清理之前旧的固件。

    bitbake atf-ameba -c cleanall
    bitbake u-boot-ameba -c cleanall
    
  3. 重新编译,确保修改的内容在新的固件里。

找不到 OEM 固件

在编译其,用户可以先手动编译 OEM 固件。

bitbake ameba-image-oem

下面的步骤描述了如何把它添加到命令 m 中。

  1. 编辑脚本文件 <sdk>/sources/yocto/meta-realtek/tools/envsetup.sh 。把 oem 的部分添加到这个文件中,如下所示。

    ../../_images/add_part_oem.png
  2. 执行这条命令把脚本文件复制到根目录。

    cd <sdk>
    cp sources/yocto/meta-realtek/tools/envsetup.sh.
    
  3. 执行命令 m 来编译。你会发现 oem.img 这个固件生成成功。

    ../../_images/build_with_command_m.png

下载固件

用户可以按照下面所示手动修改布局:

../../_images/download_images1.png
../../_images/download_images2.png

或者,用户可以给 Image-Tool 载入 AmebaSmart_Linux_NAND_128MB_Anker.rdev

如果 OEM 是手动独自编译的,用户可以改为下载 meba-image-oem-rtl8730elh-va7-20240906032841.oem.ubi 。如果用户已经如 envsetup.sh (找不到 OEM 固件)所述将这个文件重命名为 oem.img,请下载这个 oem.img。

功能验证

启动正常

在启动过程中,用户可以看到如下所示的信息:

../../_images/booting_information.png

用户可以看到这些信息与期望的布局是一样的。

并且,如果 OEM 固件被加载,用户可以看到如下所示的更多信息:

../../_images/information_after_loaded_oem_image1.png
../../_images/information_after_loaded_oem_image2.png
../../_images/information_after_loaded_oem_image3.png
../../_images/information_after_loaded_oem_image4.png

恢复系统

recovery 的 dts 文件如下所示:

../../_images/dts_file_for_recovery.png

如果您需要修改这个 dts 文件,可以按照以下方式调整 reg 值:

../../_images/adjust_reg_values.png

如果用户使用 USB 进行恢复,应该将 udev-extraconf 添加到 ameba-image-core.bb 中以支持 USB。

../../_images/deals_with_recovery_usb.png