Yocto:NXP s32g emmc镜像生成过程分析_xiliu542的博客-CSDN博客
一、分区起始地址和大小确定
上一篇通过分析编译Log介绍了emmc镜像的生成过程。但是分区大小和分区的起始地址是如何确定的呢?下面就简单分析一下。
从boot.img分区来入手,从上面log可以看到boot分区是从4096KB地址开始的,结束地址是69632KB.
往上翻可以看到一些信息UBOOT_BOOTSAPCE_OFFSET和BOOT_SPACE_ALIGEND这几个变量。
搜索一下UBOOT_BOOTSAPCE_OFFSET,发现是定义在sources/meta-alb/conf/machine/include/s32-gen1-board.inc中为0,也就是uboot是烧录到emmc的0地址。
在搜索 一下BOOT_SPACE_ALIGEND
其在sources/meta-alb/classes/image_types_fsl_sdcard.bbclass中赋值, 进去看这个文件,其中IMAGE_CMD_sdcard是关键函数,里面计算了boot.img,rootfs分区的起始地址和大小
IMAGE_CMD_sdcard () {
if [ -n "${UBOOT_BOOTSPACE_OFFSET}" ]; then //${UBOOT_BOOTSPACE_OFFSET}变量不为空前面定义了变量值为"0"
UBOOT_BOOTSPACE_OFFSET=$(printf "%d" ${UBOOT_BOOTSPACE_OFFSET}) //UBOOT_BOOTSPACE_OFFSET赋值为整数0
else
UBOOT_BOOTSPACE_OFFSET=$(expr ${UBOOT_BOOTSPACE_SEEK} \* 512)
fi
# Align boot partition and calculate total SD card image size
//BOOT_SPACE应该指的就是存放boot.img分区大小,目前定义的时65536KB, BASE_IMAGE_ROOTFS_ALIGNMENT是4096KB对齐
BOOT_SPACE_ALIGNED=$(expr ${BOOT_SPACE} + ${BASE_IMAGE_ROOTFS_ALIGNMENT} - 1)
BOOT_SPACE_ALIGNED=$(expr ${BOOT_SPACE_ALIGNED} - ${BOOT_SPACE_ALIGNED} % ${BASE_IMAGE_ROOTFS_ALIGNMENT})
//上面计算完后BOOT_SPACE_ALIGED=65536
# If the size has not been preset, we default to flash image
# sizes if available turned into [KiB] or to a hardcoded mini
# default of 4MB.
if [ -z "${IMAGE_ROOTFS_ALIGNMENT}" ]; then
if [ -n "${FLASHIMAGE_SIZE}" ]; then
IMAGE_ROOTFS_ALIGNMENT=$(expr ${FLASHIMAGE_SIZE} \* 1024)
else
IMAGE_ROOTFS_ALIGNMENT=${BASE_IMAGE_ROOTFS_ALIGNMENT}
fi
fi
//这里SDCARD_SIZE=4096+65536=69632
# Compute final size of SDCard image and start offset of each rootfs partition
SDCARD_SIZE=$(expr ${IMAGE_ROOTFS_ALIGNMENT} + ${BOOT_SPACE_ALIGNED})
if [ -n "${SDCARD_ROOTFS_REAL}" ]; then
SDCARD_ROOTFS_REAL_START=${SDCARD_SIZE} //这里计算rootfs实际分区起始地址SDCARD_ROOTFS_REAL_START=69632
//下面重新计算SDCARD_SIZE=69632+524288+4096=598016, 这里有个关键点 ROOTFS_SIZE=524288是哪里来的?
SDCARD_SIZE=$(expr ${SDCARD_SIZE} + ${ROOTFS_SIZE} + ${BASE_IMAGE_ROOTFS_ALIGNMENT})
bbdebug 1 "${ROOTFS_SIZE} ${BASE_IMAGE_ROOTFS_ALIGNMENT} ${SDCARD_ROOTFS_REAL_START}"
else
SDCARD_ROOTFS_REAL_START="0"
fi
if [ -n "${SDCARD_ROOTFS_EXTRA1_FILE}" ]; then
SDCARD_ROOTFS_EXTRA1_START=${SDCARD_SIZE}
SDCARD_SIZE=$(expr ${SDCARD_SIZE} + ${SDCARD_ROOTFS_EXTRA1_SIZE} + ${BASE_IMAGE_ROOTFS_ALIGNMENT})
else
SDCARD_ROOTFS_EXTRA1_START="0"
fi
if [ -n "${SDCARD_ROOTFS_EXTRA2_FILE}" ]; then
SDCARD_ROOTFS_EXTRA2_START=${SDCARD_SIZE}
SDCARD_SIZE=$(expr ${SDCARD_SIZE} + ${SDCARD_ROOTFS_EXTRA2_SIZE} + ${BASE_IMAGE_ROOTFS_ALIGNMENT})
else
SDCARD_ROOTFS_EXTRA2_START="0"
fi
cd ${IMGDEPLOYDIR}
# Initialize a sparse file
dd if=/dev/zero of=${SDCARD} bs=1 count=0 seek=$(expr 1024 \* ${SDCARD_SIZE})
# Additional elements for the raw image, copying the approach of the flashimage class
generate_sdcardimage_entry "${SDCARDIMAGE_EXTRA1_FILE}" "SDCARDIMAGE_EXTRA1_OFFSET" "${SDCARDIMAGE_EXTRA1_OFFSET}" "${SDCARD}"
generate_sdcardimage_entry "${SDCARDIMAGE_EXTRA2_FILE}" "SDCARDIMAGE_EXTRA2_OFFSET" "${SDCARDIMAGE_EXTRA2_OFFSET}" "${SDCARD}"
generate_sdcardimage_entry "${SDCARDIMAGE_EXTRA3_FILE}" "SDCARDIMAGE_EXTRA3_OFFSET" "${SDCARDIMAGE_EXTRA3_OFFSET}" "${SDCARD}"
generate_sdcardimage_entry "${SDCARDIMAGE_EXTRA4_FILE}" "SDCARDIMAGE_EXTRA4_OFFSET" "${SDCARDIMAGE_EXTRA4_OFFSET}" "${SDCARD}"
generate_sdcardimage_entry "${SDCARDIMAGE_EXTRA5_FILE}" "SDCARDIMAGE_EXTRA5_OFFSET" "${SDCARDIMAGE_EXTRA5_OFFSET}" "${SDCARD}"
generate_sdcardimage_entry "${SDCARDIMAGE_EXTRA6_FILE}" "SDCARDIMAGE_EXTRA6_OFFSET" "${SDCARDIMAGE_EXTRA6_OFFSET}" "${SDCARD}"
generate_sdcardimage_entry "${SDCARDIMAGE_EXTRA7_FILE}" "SDCARDIMAGE_EXTRA7_OFFSET" "${SDCARDIMAGE_EXTRA7_OFFSET}" "${SDCARD}"
generate_sdcardimage_entry "${SDCARDIMAGE_EXTRA8_FILE}" "SDCARDIMAGE_EXTRA8_OFFSET" "${SDCARDIMAGE_EXTRA8_OFFSET}" "${SDCARD}"
generate_sdcardimage_entry "${SDCARDIMAGE_EXTRA9_FILE}" "SDCARDIMAGE_EXTRA9_OFFSET" "${SDCARDIMAGE_EXTRA9_OFFSET}" "${SDCARD}"
${SDCARD_GENERATION_COMMAND} ${SDCARD_ROOTFS_REAL_START} ${SDCARD_ROOTFS_EXTRA1_START} ${SDCARD_ROOTFS_EXTRA2_START}
cd -
}
上面的BOOT_SPACE就是boot.img分区的大小,定义在
上面主要做了:1. uboot是从0地址开始,大小是4MB,是没有文件系统的。
2.boot.img分区是从4096KB地址开始,大小是65536KB, 分区格式是fat32
3.rootfs分区是从69632KB地址开始,大小是524288KB, 分区格式是ext4
上面函数里面其实有个问题就是${ROOTFS_SIZE}是哪里赋值定义的?搜索了下ROOTFS_SIZE没有地方直接定义,但是有个地方引起了我的注意,就是image.bbclass 里面的d.setVar('ROOTFS_SIZE', str(rootfs_size))
进去看一下sources/poky/meta/classes/image.bbclass文件
python set_image_size () {
rootfs_size = get_rootfs_size(d)
d.setVar('ROOTFS_SIZE', str(rootfs_size))
d.setVarFlag('ROOTFS_SIZE', 'export', '1')
}
通过get_rootfs_size函数获取到rootfs_size,然后设置ROOTFS_SIZE
那get_rootfs_size是如何计算rootfs的大小的呢?
def get_rootfs_size(d):
import subprocess
rootfs_alignment = int(d.getVar('IMAGE_ROOTFS_ALIGNMENT')) //rootfs_alignement = 4096
overhead_factor = float(d.getVar('IMAGE_OVERHEAD_FACTOR')) //定义在sources/meta-alb/recipes-fsl/images/fsl-image-auto.bb:68:# IMAGE_OVERHEAD_FACTOR = "1.3"
rootfs_req_size = int(d.getVar('IMAGE_ROOTFS_SIZE')) //这里有个默认值9216 sources/poky/meta/recipes-core/images/core-image-minimal.bb:11:IMAGE_ROOTFS_SIZE ?= "9216"
rootfs_extra_space = eval(d.getVar('IMAGE_ROOTFS_EXTRA_SPACE')) //没有定义所以这里为0
rootfs_maxsize = d.getVar('IMAGE_ROOTFS_MAXSIZE') //没有定义所以这里为0
image_fstypes = d.getVar('IMAGE_FSTYPES') or ''
initramfs_fstypes = d.getVar('INITRAMFS_FSTYPES') or ''
initramfs_maxsize = d.getVar('INITRAMFS_MAXSIZE')
//下面${IMAGE_ROOTFS}这个变量指的是build_s32g399ardb3/tmp/work/s32g399ardb3-fsl-linux/fsl-image-auto/1.0-r0/rootfs, 也就是编译出来的根文件目录
//调用系统的du -ks build_s32g399ardb3/tmp/work/s32g399ardb3-fsl-linux/fsl-image-auto/1.0-r0/rootfs 计算大小
output = subprocess.check_output(['du', '-ks',
d.getVar('IMAGE_ROOTFS')])
#bb.debug(1, '%s' % (d.getVar('IMAGE_ROOTFS')))
size_kb = int(output.split()[0]) //获取到rootfs文件夹的大小
base_size = size_kb * overhead_factor //rootfs大小乘以1.3
bb.debug(1, '%f = %d * %f' % (base_size, size_kb, overhead_factor))
base_size2 = max(base_size, rootfs_req_size) + rootfs_extra_space
bb.debug(1, '%f = max(%f, %d)[%f] + %d' % (base_size2, base_size, rootfs_req_size, max(base_size, rootfs_req_size), rootfs_extra_space))
base_size = base_size2
if base_size != int(base_size):
base_size = int(base_size + 1)
else:
base_size = int(base_size)
bb.debug(1, '%f = int(%f)' % (base_size, base_size2))
base_size_saved = base_size
base_size += rootfs_alignment - 1
base_size -= base_size % rootfs_alignment //重新计算base_size以4096对齐
bb.debug(1, '%d = aligned(%d)' % (base_size, base_size_saved))
# Do not check image size of the debugfs image. This is not supposed
# to be deployed, etc. so it doesn't make sense to limit the size
# of the debug.
if (d.getVar('IMAGE_BUILDING_DEBUGFS') or "") == "true":
bb.debug(1, 'returning debugfs size %d' % (base_size))
return base_size
# Check the rootfs size against IMAGE_ROOTFS_MAXSIZE (if set)
if rootfs_maxsize:
rootfs_maxsize_int = int(rootfs_maxsize)
if base_size > rootfs_maxsize_int:
bb.fatal("The rootfs size %d(K) exceeds IMAGE_ROOTFS_MAXSIZE: %d(K)" % \
(base_size, rootfs_maxsize_int))
# Check the initramfs size against INITRAMFS_MAXSIZE (if set)
if image_fstypes == initramfs_fstypes != '' and initramfs_maxsize:
initramfs_maxsize_int = int(initramfs_maxsize)
if base_size > initramfs_maxsize_int:
bb.error("The initramfs size %d(K) exceeds INITRAMFS_MAXSIZE: %d(K)" % \
(base_size, initramfs_maxsize_int))
bb.error("You can set INITRAMFS_MAXSIZE a larger value. Usually, it should")
bb.fatal("be less than 1/2 of ram size, or you may fail to boot it.\n")
bb.debug(1, 'returning %d' % (base_size))
#bb.error('base_size %d' % (base_size))
return base_size
也可以从编译log看到计算rootfs_size的过程
NOTE: recipe fsl-image-auto-1.0-r0: task do_image_sdcard: Started
DEBUG: fsl-image-auto-1.0-r0 do_image_sdcard: Executing python function set_image_size
DEBUG: fsl-image-auto-1.0-r0 do_image_sdcard: 520598.000000 = 400460 * 1.300000
DEBUG: fsl-image-auto-1.0-r0 do_image_sdcard: 520598.000000 = max(520598.000000, 9216)[520598.000000] + 0
DEBUG: fsl-image-auto-1.0-r0 do_image_sdcard: 520598.000000 = int(520598.000000)
DEBUG: fsl-image-auto-1.0-r0 do_image_sdcard: 524288 = aligned(520598)
DEBUG: fsl-image-auto-1.0-r0 do_image_sdcard: returning 524288
DEBUG: fsl-image-auto-1.0-r0 do_image_sdcard: Python function set_image_size finished
DEBUG: fsl-image-auto-1.0-r0 do_image_sdcard: Executing shell function do_image_sdcard
所以rootfs分区的大小目前不是固定大小,而是根据编译出来的rootfs大小来去确定的。
二、分区大小修改
1.如果想修改存放boot.img分区大小只需修改sources/meta-alb/conf/machine/include/s32-base.inc中的BOOT_SPACE ?= "65536", 注意单位是KB
2.修改rootfs分区大小,可以修改IMAGE_OVERHEAD_FACTOR。那么将rootfs分区改成固定大小可以通过修改IMAGE_ROOTFS_SIZE。这两个变量都可以通过在sources/meta-alb/recipes-fsl/images/fsl-image-auto.bb定义如下:
三、增加自定义分区和大小
这个我的想法就是修改generate_nxp_sdcard函数,增加自己定义的分区,具体没有做。
generate_nxp_sdcard () {
# Get partitions' start offsets passed as parameters
SDCARD_ROOTFS_REAL_START="$1"
SDCARD_ROOTFS_EXTRA1_START="$2"
SDCARD_ROOTFS_EXTRA2_START="$3"
# Create partition table
parted -s ${SDCARD} mklabel msdos
parted -s ${SDCARD} unit KiB mkpart primary fat32 ${IMAGE_ROOTFS_ALIGNMENT} $(expr ${IMAGE_ROOTFS_ALIGNMENT} \+ ${BOOT_SPACE_ALIGNED})
create_rootfs_partition ${SDCARD_ROOTFS_REAL_START} ${ROOTFS_SIZE} ${SDCARD_ROOTFS_REAL}
create_rootfs_partition ${SDCARD_ROOTFS_EXTRA1_START} ${SDCARD_ROOTFS_EXTRA1_SIZE} ${SDCARD_ROOTFS_EXTRA1_FILE}
create_rootfs_partition ${SDCARD_ROOTFS_EXTRA2_START} ${SDCARD_ROOTFS_EXTRA2_SIZE} ${SDCARD_ROOTFS_EXTRA2_FILE}
parted ${SDCARD} print
# Fill optional Layerscape RCW into the boot block
if [ -n "${SDCARD_RCW_NAME}" ]; then
dd if=${DEPLOY_DIR_IMAGE}/${SDCARD_RCW_NAME} of=${SDCARD} conv=notrunc seek=8 bs=512
fi
_burn_bootloader
_generate_boot_image 1
# Burn Partitions
dd if=${WORKDIR}/boot.img of=${SDCARD} conv=notrunc,fsync seek=1 bs=$(expr ${IMAGE_ROOTFS_ALIGNMENT} \* 1024)
write_rootfs_partition ${SDCARD_ROOTFS_REAL_START} ${ROOTFS_SIZE} ${SDCARD_ROOTFS_REAL}
write_rootfs_partition ${SDCARD_ROOTFS_EXTRA1_START} ${SDCARD_ROOTFS_EXTRA1_SIZE} ${SDCARD_ROOTFS_EXTRA1_FILE}
write_rootfs_partition ${SDCARD_ROOTFS_EXTRA2_START} ${SDCARD_ROOTFS_EXTRA2_SIZE} ${SDCARD_ROOTFS_EXTRA2_FILE}
}