Android Factory分区介绍


1. 背景

Factory分区的创建用于存放一些设备出厂设定的信息例如:SN号、IMEI号等。该分区可能会先被烧录一个具有初始设定的镜像,随后在工厂模式下会继续往分区添加信息。在进入Android系统时,该分区可能被挂载成只读且通过SeLinux限制进程访问。以上介绍的Factory分区的常见使用场景。本文主要介绍Factory分区的编译配置以及挂载配置。

2. 编译配置

编译factory.img的Makefile位于:

device/sigmastar/common/build/factory_image.mk

如果某个product需要编译factory.img,则需要在AndroidBoard.mk中导入该Makefile,以pioneer5下的product为例:

yi.huang@xml3bc12801:~/workspace/AOSP/device/sigmastar/pioneer5$ grep -rnw factory_image.mk
pioneer5_sdp_lr/AndroidBoard.mk:19:include device/sigmastar/common/build/factory_image.mk
pioneer5_sdp/AndroidBoard.mk:19:include device/sigmastar/common/build/factory_image.mk
pioneer5_fpga/AndroidBoard.mk:19:include device/sigmastar/common/build/factory_image.mk
pioneer5_ad/AndroidBoard.mk:19:include device/sigmastar/common/build/factory_image.mk
pioneer5_voip/AndroidBoard.mk:19:include device/sigmastar/common/build/factory_image.mk

factory_image.mk内容大致如下:

  1 #
  2 # Copyright (c) [2019~2020] SigmaStar Technology.
  3 +--- 12 lines: --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 15 ifdef BOARD_FACTORY_PARTITION_SIZE
 16 ifdef BOARD_SSTAR_FACTORYIMAGE_DIR
 17
 18 SSTAR_INSTALLED_FACTORYIMAGE_TARGET := $(PRODUCT_OUT)/factory.img
 19
 20 $(SSTAR_INSTALLED_FACTORYIMAGE_TARGET): $(HOST_OUT_EXECUTABLES)/img2simg$(HOST_EXECUTABLE_SUFFIX)
 21 $(SSTAR_INSTALLED_FACTORYIMAGE_TARGET): $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX)
 22 $(SSTAR_INSTALLED_FACTORYIMAGE_TARGET): $(shell find $(BOARD_SSTAR_FACTORYIMAGE_DIR))
 23     echo "Install factoryimage: $@"
 24     $(hide) rm -f $@
 25     $(hide) $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX) \
 26         -d $(BOARD_SSTAR_FACTORYIMAGE_DIR) -t ext4 \
 27         -O ^metadata_csum,^64bit $@.ext4 \
 28         $(shell echo "($(BOARD_FACTORY_PARTITION_SIZE)+1023)/1024"|bc) || exit;
 29     $(hide) $(HOST_OUT_EXECUTABLES)/img2simg$(HOST_EXECUTABLE_SUFFIX) \
 30         $@.ext4 $@ || exit;
 31     $(hide) rm -f $@.ext4;
 32
 33 factoryimage: $(SSTAR_INSTALLED_FACTORYIMAGE_TARGET)
 34
 35 .PHONY: factoryimage
 36
 37 droidcore-unbundled: $(SSTAR_INSTALLED_FACTORYIMAGE_TARGET)
 38 endif
 39 endif

整体逻辑并不复杂,主要的过程:

25-28行:调用mke2fs生成一个factory.img.ext4的ext4文件系统镜像

29-30行:调用img2simg将factory.img.ext4转换成稀疏格式镜像

关于factory镜像,主要需要配置两个BoardConfig:

  • BOARD_FACTORY_PARTITION_SIZE 设定了factory分区的大小,这决定了生成的factory.img.ext4的大小,可以看到28行将BOARD_FACTORY_PARTITION_SIZE对1K做了向上除法取整传递给了mke2fs。关于mke2fs的参数设定请参考其帮助文档。关于BOARD_FACTORY_PARTITION_SIZE在哪里设定请参考《Android分区说明》。

  • BOARD_SSTAR_FACTORYIMAGE_DIR 设定了factory的资源目录,即factory.img.ext4的根目录位置,以pioneer5为例,目前是device公共的,位于:

    # device/sigmastar/pioneer5/BoardConfig-common.mk
    BOARD_SSTAR_FACTORYIMAGE_DIR := device/sigmastar/pioneer5/factory
    

3. 分区相关配置

请先参考《Android分区说明》,以non-dynamic和disable AVB的配置为例,选中如下配置文件:

device/sigmastar/common/partition/partition-table-8GB-nondynamic.mk
device/sigmastar/common/partition/partition-table-8GB-nondynamic-noavb.json

以上两个文件作用不再赘述,可以看到当前:

# partition-table-8GB-nondynamic.mk
# factory.img(4MB)
BOARD_FACTORY_PARTITION_SIZE := 4194304
{
    "settings": {
        "disk_alignment": 512,
        "disk_size": "7 GB"
    },
    "partitions": [
        {
            "label": "factory",
            "size": 4194304,
            "guid": "auto",
            "type_guid": "brillo_misc",
            "hw_part_name": "UDA",
            "image_name": "factory.img",
            "is_download": false
        },
    ]
}

4. 挂载相关配置

请先参考《Android Fstab配置说明》,以non-dynamic和disable AVB的配置为例,选中如下配置文件:

device/sigmastar/pioneer5/fstab.sstar.nondynamic.nonavb

其中:

# Android fstab file.
#<dev>                                                 <mnt_point>  <type>  <mnt_flags options>                                              <fs_mgr_flags>
/dev/block/platform/soc/soc:emmc/by-name/factory       /mnt/factory ext4    nosuid,nodev,nodiratime,noatime,errors=panic                     latemount,wait

该fstab的设定将factory分区挂载到了/mnt/factory目录。在开发板中也可以看到:

console:/ # df -h
Filesystem            Size Used Avail Use% Mounted on
/dev/block/mmcblk0p11 1.2G 826M  433M  66% /
/dev/block/mmcblk0p13 240M 190M   50M  80% /vendor
/dev/block/mmcblk0p15 7.4M 604K  6.8M   8% /odm
/dev/block/mmcblk0p1  2.8M  21K  2.8M   1% /mnt/factory
/dev/block/mmcblk0p18 3.2G  35M  3.1G   2% /data
/dev/block/mmcblk0p17 3.7M  20K  3.7M   1% /cache
console:/ # ls -la /dev/block/by-name/factory
lrwxrwxrwx 1 root root 20 1970-01-01 00:00 /dev/block/by-name/factory -> /dev/block/mmcblk0p1

5. 读写factory分区

5.1. Kernel下读写

Kernel space下请通过vfs接口读写,和其他分区的文件一样。

User space下可以直接读写其所在挂载点下的文件,和其他分区的文件一样。

5.2. U-boot下读写

U-boot有如下Kconfig与ext4文件系统有关:

# fs/ext4/Kconfig
config FS_EXT4
    bool "Enable ext4 filesystem support"
    help
      This provides support for reading images from the ext4 filesystem.
      ext4 is a widely used general-purpose filesystem for Linux.
      You can also enable CMD_EXT4 to get access to ext4 commands.

config EXT4_WRITE
    bool "Enable ext4 filesystem write support"
    depends on FS_EXT4
    help
      This provides support for creating and writing new files to an
      existing ext4 filesystem partition.

# cmd/Kconfig
config CMD_EXT4
    bool "ext4 command support"
    select FS_EXT4
    help
      Enables EXT4 FS command

config CMD_EXT4_WRITE
    depends on CMD_EXT4
    bool "ext4 write command support"
    select EXT4_WRITE
    help
      Enables EXT4 FS write command

所有配置均打开的情况下,U-boot会有以下命令:

  • ext4load:将文件系统中的文件load到内存指定位置

  • ext4ls:获取文件系统指定目录的内容

  • ext4size:获取文件系统指定文件的大小

  • ext4write:将内存指定位置的内容写到文件系统指定文件

在代码中可以使用fs/fs.c提供的通用文件系统操作接口进行操作。