LXR | KVM | PM | Time | Interrupt | Systems Performance | Bootup Optimization

OpenWRT(10):OpenWRT下rootfs的cpio/squashfs/ubifs/ext4生成流程

在include/image.mk中定义了initramfs、ubifs、squashfs、ext4等镜像的生成。

OpenWRT提供配置选项入口,借助mkfs.ubifs、mksquashfs4、make_ext4fs创建镜像。

1 ubifs

下面是include/image.mk中生成ubifs镜像的Makefile函数:

define Image/mkfs/ubifs
    $(STAGING_DIR_HOST)/bin/mkfs.ubifs \
        $(UBIFS_OPTS) $(call param_unmangle,$(call param_get,fs,$(1))) \
        $(if $(CONFIG_TARGET_UBIFS_FREE_SPACE_FIXUP),--space-fixup) \
        $(if $(CONFIG_TARGET_UBIFS_COMPRESSION_NONE),--compr=none) \
        $(if $(CONFIG_TARGET_UBIFS_COMPRESSION_LZO),--compr=lzo) \
        $(if $(CONFIG_TARGET_UBIFS_COMPRESSION_ZLIB),--compr=zlib) \
        $(if $(shell echo $(CONFIG_TARGET_UBIFS_JOURNAL_SIZE)),--jrn-size=$(CONFIG_TARGET_UBIFS_JOURNAL_SIZE)) \
        --squash-uids \
        -o $@ -d $(call mkfs_target_dir,$(1))
endef

这段脚本定义一个名为`Image/mkfs/ubifs`的函数,它用于创建Ubifs文件系统镜像。Ubifs(Unsorted Block Image File System)是一种针对闪存存储设备优化的文件系统。下面是对脚本中各部分的详细解释:

  • define Image/mkfs/ubifs:开始定义一个名为Image/mkfs/ubifs的Makefile函数。
  • $(STAGING_DIR_HOST)/bin/mkfs.ubifs:调用mkfs.ubifs工具,这是一个用于创建Ubifs文件系统的命令行工具。
  • $(UBIFS_OPTS):包含Ubifs文件系统的通用选项,这些选项可能包括文件系统的大小、块大小等。
  • $(call param_unmangle,$(call param_get,fs,$(1))):这部分代码调用了两个函数来处理Ubifs文件系统的参数。`param_get`函数用于获取传递给函数的第一个参数(`$(1)`)的值,`param_unmangle`函数用于处理这个值,可能用于转换或修正参数。
  • --space-fixup:如果定义了CONFIG_TARGET_UBIFS_FREE_SPACE_FIXUP,将添加此选项到`mkfs.ubifs`命令中,用于修复Ubifs文件系统中的空闲空间问题。这个选项对于某些NAND闪存设备是必要的,因为它们不能处理文件系统中的“洞”。
  • --compr=none,--compr=lzo,--compr=zlib:根据配置选项,选择Ubifs文件系统的压缩算法。如果没有定义压缩算法,使用none;如果定义了CONFIG_TARGET_UBIFS_COMPRESSION_LZO,则使用LZO压缩;如果定义了CONFIG_TARGET_UBIFS_COMPRESSION_ZLIB,则使用ZLIB压缩。
  • --jrn-size=$(CONFIG_TARGET_UBIFS_JOURNAL_SIZE):如果定义了CONFIG_TARGET_UBIFS_JOURNAL_SIZE,将设置Ubifs文件系统的日志大小,单位通常是块。
  • --squash-uids:此选项用于在创建文件系统时忽略用户ID和组ID,所有文件将使用相同的用户和组权限。
  • -o $@:指定输出文件,$@是Makefile中的自动变量,代表当前的规则目标。
  • -d $(call mkfs_target_dir,$(1)):指定要包含在Ubifs文件系统中的目录,`$(call mkfs_target_dir,$(1))`调用一个函数来获取目录路径。

mkfs.ubifs其他选项可以通过UBIFS_OPTS传入,还包括:

  • -m, --min-io-size:用于设置Ubifs文件系统中的最小I/O单元大小。SIZE参数指定了Ubifs操作的最小数据单元,通常应与底层存储设备的页大小相匹配。
  • -e, --leb-size:设置Ubifs文件系统中逻辑擦除块(LEB)的大小。SIZE参数定义了每个LEB的大小,单位是字节。
  • -c, --max-leb-cnt:设置Ubifs文件系统中逻辑擦除块(LEB)的最大数量。COUNT参数定义了文件系统中可以拥有的最大LEB数量。

比如:

UBIFS_OPTS = -m 2048 -e 124KiB -c 4096

1.1 ubi镜像

include/image-commands.mk中定义名为Build/append-ubi的 Makefile 函数,用于将文件系统和可选的内核以及环境变量打包成一个 UBI 镜像:

define Build/append-ubi
    sh $(TOPDIR)/scripts/ubinize-image.sh \
        $(if $(UBOOTENV_IN_UBI),--uboot-env) \
        $(if $(KERNEL_IN_UBI),--kernel $(IMAGE_KERNEL)) \
        $(foreach part,$(UBINIZE_PARTS),--part $(part)) \
        --rootfs $(IMAGE_ROOTFS) \
        $@.tmp \
        -p $(BLOCKSIZE:%k=%KiB) -m $(PAGESIZE) \
        $(if $(SUBPAGESIZE),-s $(SUBPAGESIZE)) \
        $(if $(VID_HDR_OFFSET),-O $(VID_HDR_OFFSET)) \
        $(UBINIZE_OPTS)
    cat $@.tmp >> $@
    rm $@.tmp
endef
  • sh $(TOPDIR)/scripts/ubinize-image.sh:调用ubinize-image.sh脚本来执行 UBI 镜像的创建。
  • $(if $(UBOOTENV_IN_UBI),--uboot-env):如果定义了UBOOTENV_IN_UBI变量,那么添加--uboot-env参数到ubinize-image.sh脚本中,表示将 U-Boot 环境变量包含在 UBI 镜像中。
  • $(if $(KERNEL_IN_UBI),--kernel $(IMAGE_KERNEL)):如果定义了KERNEL_IN_UBI变量,那么添加--kernel参数和内核镜像的路径到ubinize-image.sh脚本中,表示将内核包含在 UBI 镜像中。
  • $(foreach part,$(UBINIZE_PARTS),--part $(part)):对于UBINIZE_PARTS列表中的每个分区,添加--part参数和分区名称到ubinize-image.sh脚本中。
  • --rootfs $(IMAGE_ROOTFS):指定要包含在 UBI 镜像中的根文件系统。
  • $@.tmp:指定输出文件的临时名称,$@表示目标文件名。
  • -p $(BLOCKSIZE:%k=%KiB):指定 UBI 镜像的块大小,$(BLOCKSIZE) 通常以千字节为单位定义,这里将其转换为 KiB。
  • -m $(PAGESIZE):指定 NAND 页大小。
  • $(if $(SUBPAGESIZE),-s $(SUBPAGESIZE)):如果定义了SUBPAGESIZE变量,那么添加-s参数和子页大小到ubinize-image.sh脚本中。
  • $(if $(VID_HDR_OFFSET),-O $(VID_HDR_OFFSET))`:如果定义了VID_HDR_OFFSET变量,那么添加-O参数和 VID 头偏移量到 ubinize-image.sh脚本中。
  • $(UBINIZE_OPTS):添加任何额外的ubinize-image.sh脚本选项。

scripts/ubinize-image.sh根据输入的参数生成ubi镜像:

  • ubivol函数:创建一个 UBI 卷的配置块。参数包括卷 ID、名称、镜像路径、自动调整大小标志和大小。
  • ubilayout函数:根据提供的参数生成 UBI 布局配置。处理 U-Boot 环境变量、分区、内核和根文件系统的配置。
  • [ "$rootfs_type" = "ubifs" ] || ubivol $vol_id rootfs_data "" 1:如果 $rootfs_type 等于 ubifs,则条件为真,不执行任何操作。如果条件为假(即squashfs类型rootfs),则调用 ubivol 函数来创建一个名为rootfs_data 的 UBI 卷,卷 ID 为 $vol_id,没有指定图像,自动调整大小标志为空,大小为1MiB。
  • --uboot-env、--kernel--rootfs、--part、--rootfs:为这些参数创建Volume。

2 squashfs

下面是include/image.mk中生成squashfs镜像的Makefile函数:

define Image/mkfs/squashfs
    $(call Image/mkfs/squashfs-common,$(1))
endef

define Image/mkfs/squashfs-common
    $(STAGING_DIR_HOST)/bin/mksquashfs4 $(call mkfs_target_dir,$(1)) $@ \
        -nopad -noappend -root-owned \
        -comp $(SQUASHFSCOMP) $(SQUASHFSOPT)
endef

在include/image.mk中SQUASHFSOPT默认配置如下:

SQUASHFSOPT := -b $(SQUASHFS_BLOCKSIZE)
SQUASHFSOPT += -p '/dev d 755 0 0' -p '/dev/console c 600 0 0 5 1'
SQUASHFSOPT += $(if $(CONFIG_SELINUX),-xattrs,-no-xattrs)
SQUASHFSCOMP := gzip

这段代码是Makefile的一部分,定义了两个函数:`Image/mkfs/squashfs`和`Image/mkfs/squashfs-common`。下面是对函数的详细分析:

  • define Image/mkfs/squashfs-common:定义了一个名为Image/mkfs/squashfs-common的Makefile函数,这个函数是实际执行创建squashfs文件系统操作的函数。

  • mksquashfs4:调用mksquashfs4工具,这是一个用于创建squashfs文件系统的命令行工具。$(STAGING_DIR_HOST)是一个Makefile变量,通常指向存放编译过程中生成的中间文件的目录。

  • $(call mkfs_target_dir,$(1)):调用`mkfs_target_dir`函数,并将第一个参数`$(1)`传递给它。这个函数用于获取需要被打包进squashfs文件系统的源目录路径。

  • $@:表示当前Makefile规则的目标。在这个上下文中,它指向squashfs文件系统的输出文件。

  • -nopad:mksquashfs的一个选项,用于禁止对文件系统进行填充操作。

  • -noappend:另一个`mksquashfs`的选项,用于禁止创建可追加的squashfs镜像。

  • -root-owned:指定所有文件在squashfs文件系统中都归root用户所有。

  • -comp $(SQUASHFSCOMP):指定squashfs文件系统的压缩算法。$(SQUASHFSCOMP)是一个Makefile变量,包含了压缩算法的名称。

  • $(SQUASHFSOPT):包含squashfs文件系统创建过程中的其他选项,这些选项可能包括压缩级别、文件系统版本等。

这段代码定义了两个Makefile函数,用于创建squashfs文件系统。`Image/mkfs/squashfs`函数是一个简单的包装器,它调用实际执行创建操作的`Image/mkfs/squashfs-common`函数。`Image/mkfs/squashfs-common`函数则包含了创建squashfs文件系统所需的所有命令和选项。通过这种方式,Makefile可以重用创建squashfs文件系统的代码,同时保持代码的清晰和组织性。

/home/al/data/openwrt/openwrt22.03-a53/staging_dir/host/bin/mksquashfs4 \
/home/al/data/openwrt/openwrt22.03-a53/build_dir/target-aarch64_cortex-a53_musl/root-armvirt \
/home/al/data/openwrt/openwrt22.03-a53/build_dir/target-aarch64_cortex-a53_musl/linux-armvirt_64/root.squashfs \
-nopad -noappend -root-owned -comp xz -Xpreset 9 -Xe -Xlc 0 -Xlp 2 -Xpb 2 -b 256k \
-p '/dev d 755 0 0' -p '/dev/console c 600 0 0 5 1' -no-xattrs

3 ext4

下面是include/image.mk中生成ext4镜像的Makefile函数:

define Image/mkfs/ext4
    $(STAGING_DIR_HOST)/bin/make_ext4fs -L rootfs \
        -l $(ROOTFS_PARTSIZE) -b $(CONFIG_TARGET_EXT4_BLOCKSIZE) \
        $(if $(CONFIG_TARGET_EXT4_RESERVED_PCT),-m $(CONFIG_TARGET_EXT4_RESERVED_PCT)) \
        $(if $(CONFIG_TARGET_EXT4_JOURNAL),,-J) \
        $(if $(SOURCE_DATE_EPOCH),-T $(SOURCE_DATE_EPOCH)) \
        $@ $(call mkfs_target_dir,$(1))/
endef

这段代码是Makefile的一部分,定义了一个名为`Image/mkfs/ext4`的函数,用于创建一个ext4文件系统的镜像。下面是对这段代码的解释:

  • define Image/mkfs/ext4:开始定义一个Makefile函数,名为`Image/mkfs/ext4`。
  • make_ext4fs:调用`make_ext4fs`工具,这是一个用于创建ext4文件系统的命令行工具。`$(STAGING_DIR_HOST)`是一个Makefile变量,指向存放编译过程中生成的中间文件的目录。
  • -L rootfs:指定文件系统的标签为`rootfs`。
  • -l $(ROOTFS_PARTSIZE):指定文件系统的大小,$(ROOTFS_PARTSIZE)是一个Makefile变量,代表文件系统的分区大小。可以是块的数量或者文件的大小(如果以b、k、m或g结尾)。
  • -b $(CONFIG_TARGET_EXT4_BLOCKSIZE):指定文件系统的块大小,$(CONFIG_TARGET_EXT4_BLOCKSIZE)是一个Makefile变量,代表块大小。
  • $(if $(CONFIG_TARGET_EXT4_RESERVED_PCT),-m $(CONFIG_TARGET_EXT4_RESERVED_PCT)):如果定义了`CONFIG_TARGET_EXT4_RESERVED_PCT`,则添加`-m`选项,并使用该变量的值作为保留空间的百分比。
  • $(if $(CONFIG_TARGET_EXT4_JOURNAL),,-J):如果定义了`CONFIG_TARGET_EXT4_JOURNAL`,则不添加任何选项(因为逗号前的空格表示如果条件为真,则什么也不做)。如果没有定义,则添加`-J`选项,这通常用于禁用日志功能。
  • $(if $(SOURCE_DATE_EPOCH),-T $(SOURCE_DATE_EPOCH)):如果定义了`SOURCE_DATE_EPOCH`,则添加`-T`选项,并使用该变量的值作为文件系统的创建时间。
  • $@:表示当前Makefile规则的目标。在这个上下文中,它指向创建的ext4文件系统镜像的输出文件。
  • $(call mkfs_target_dir,$(1))/:调用`mkfs_target_dir`函数,并将第一个参数`$(1)`传递给它。这个函数用于获取需要被打包进ext4文件系统的源目录路径,并在路径后添加一个斜杠以表示目录。

这段代码定义了一个函数,用于根据一系列的配置选项和参数,创建一个ext4文件系统镜像。这个函数可以被Makefile的其他部分调用,以生成所需的文件系统镜像。通过使用条件语句,它允许用户根据配置选择是否保留空间、是否使用日志以及设置文件系统的创建时间。

/home/al/data/openwrt/openwrt22.03-a53/staging_dir/host/bin/make_ext4fs \
-L rootfs -l 109051904 -b 4096 -m 0 -J -T 1721689001 \
/home/al/data/openwrt/openwrt22.03-a53/build_dir/target-aarch64_cortex-a53_musl/linux-armvirt_64/root.ext4 \
/home/al/data/openwrt/openwrt22.03-a53/build_dir/target-aarch64_cortex-a53_musl/root-armvirt/

posted on 2024-08-23 23:59  ArnoldLu  阅读(335)  评论(0编辑  收藏  举报

导航