yocto machine class解析之flashlayout-stm32mp
上一篇文章中我们详细介绍了st-partitions-image class。里面根据配置生成了许多的分区镜像以及分区镜像的一些参数设置。本章节介绍的flashlayout class就会根据上面生成的这些参数来生成特定的.tsv刷机文件供ST的刷机工具使用。
flashlayout介绍
本小节先介绍一些flashlayout tsv文件的格式和说明,方便后续分析具体的实现过程,下面是
build-openstlinuxeglfs-fsmp1a/tmp-glibc/deploy/images/fsmp1a/flashlayout_fs-mp1a-qt/trusted/目录下的
FlashLayout_sdcard_stm32mp157a-fsmp1a-trusted.tsv文件:
- Opt: 选项字段可以设置为"-“()、“P”(烧写)、“D”(删除)或"E”(不更新) “PE”(不更新)“PD”(删除并更新)
- Id: 会根据这个 id 来决定烧写分区
- Name: 分区名字
- Type: 指定烧写的类型,仅 uboot 使用。
- IP:指定烧写的设备类型与编号,比如 emmc0、 emmc1、 nand0 等, 如果 opt 为‘-’ ,那么此字段就为 none
- Offset:分区的起始位置,表示需要偏移的字节数。
- Binary: 要烧录的文件
flashlayout-stm32mp class分析
下面我们来详细分析flashlayout-stm32mp class的具体实现,flashlayout-stm32mp文件非常长,一点点过把。
介绍
flashlayout的刷机文件可以通过静态设置也可以通过动态生成,使用ENABLE_FLASHLAYOUT_DEFAULT变量来控制。
-
如果设置为静态设置的话需要自己先改好一个falshlayout tsv文件,然后设置这个文件的路径到变量FLASHLAYOUT_DEFAULT_SRC,然后一起打包到deploy的生成镜像里面。
-
动态生成的话需要配置一系列变量,其中tsv文件命名格式所需变量如下:
<FLASHLAYOUT_BASENAME>[<FLASHLAYOUT_CONFIG_LABEL>][<FLASHLAYOUT_TYPE_LABEL>-FLASHLAYOUT_BOOTSCHEME_LABEL].<FLASHLAYOUT_SUFFIX>
其中FLASHLAYOUT_BASENAME 默认是 ‘FlashLayout’,FLASHLAYOUT_SUFFIX默认是’tsv’,改写下上面的格式:
FlashLayout[<FLASHLAYOUT_CONFIG_LABEL>][<FLASHLAYOUT_TYPE_LABEL>-FLASHLAYOUT_BOOTSCHEME_LABEL].tsv
如上面展示的FlashLayout_sdcard_stm32mp157a-fsmp1a-trusted.tsv可以看到:
FLASHLAYOUT_CONFIG_LABEL:sdcard
FLASHLAYOUT_TYPE_LABEL:stm32mp157a
FLASHLAYOUT_BOOTSCHEME_LABEL:trusted -
tsv文件所需格式变量:
<FLASHLAYOUT_PARTITION_ENABLE>(Opt)
<FLASHLAYOUT_PARTITION_ID>(Id)
<FLASHLAYOUT_PARTITION_LABEL>(Name)
<FLASHLAYOUT_PARTITION_TYPE>(Type)
<FLASHLAYOUT_PARTITION_DEVICE>(IP)
<FLASHLAYOUT_PARTITION_OFFSET>(Offset)
<FLASHLAYOUT_PARTITION_BIN2LOAD>(Binary)
<FLASHLAYOUT_PARTITION_SIZE>: 上面FLASHLAYOUT_PARTITION_OFFSET本来应该手动指定,但是如果配置了FLASHLAYOUT_PARTITION_SIZE这个变量则可以根据分区镜像的大小结合DEVICE_ALIGNMENT_SIZE_指定特定的对齐大小来自动计算下一个分区的OFFSET( 就是本分区的FLASHLAYOUT_PARTITION_DEVICE)
#
# --------------------
# Static configuration
# --------------------
# Set ENABLE_FLASHLAYOUT_DEFAULT to '1'.
# Configure FLASHLAYOUT_DEFAULT_SRC with the static flashlayout file locations.
#
# Configuration example (machine file or local.conf):
# ENABLE_FLASHLAYOUT_DEFAULT = "1"
# FLASHLAYOUT_DEFAULT_SRC = "files/flashlayouts/FlashLayout_sdcard_stm32mp157c-ev1_sample.tsv"
#
# ---------------------
# Dynamic configuration
# ---------------------
# Set ENABLE_FLASHLAYOUT_DEFAULT to '0'.
# In order to automatically generate flashlayout files as well formated TSV file
# there are some variables to configure.
#
# Naming:
# <FLASHLAYOUT_BASENAME>[_<FLASHLAYOUT_CONFIG_LABEL>][_<FLASHLAYOUT_TYPE_LABEL>-FLASHLAYOUT_BOOTSCHEME_LABEL].<FLASHLAYOUT_SUFFIX>
#
# FLASHLAYOUT_BASENAME
# Default to 'FlashLayout'
# FLASHLAYOUT_CONFIG_LABEL
# Set from FLASHLAYOUT_CONFIG_LABELS list (without any '_' in config labels)
# FLASHLAYOUT_TYPE_LABEL
# Set from FLASHLAYOUT_TYPE_LABELS list
# FLASHLAYOUT_BOOTSCHEME_LABEL
# Set from FLASHLAYOUT_BOOTSCHEME_LABELS list (without any '_' in bootscheme labels)
# Note that both are appended only when FLASHLAYOUT_TYPE_LABELS and FLASHLAYOUT_BOOTSCHEME_LABELS contain more than two labels.
# FLASHLAYOUT_SUFFIX
# Default to 'tsv'
#
# File content structure:
# Opt Id Name Type IP Offset Binary
# <FLASHLAYOUT_PARTITION_ENABLE>
# <FLASHLAYOUT_PARTITION_ID>
# <FLASHLAYOUT_PARTITION_LABEL>
# <FLASHLAYOUT_PARTITION_TYPE>
# <FLASHLAYOUT_PARTITION_DEVICE>
# <FLASHLAYOUT_PARTITION_OFFSET>
# <FLASHLAYOUT_PARTITION_BIN2LOAD>
#
# Specific configuration:
# FLASHLAYOUT_PARTITION_SIZE
# If configured, it allows to compute the next offset to apply in
# flashlayout file for the following partition.
# Note that according to the device in use for the partition a specific
# alignment size can be specified through DEVICE_ALIGNMENT_SIZE_<device>
# var where <device> is the current FLASHLAYOUT_PARTITION_DEVICE
#
# Note that override is manage for 'FLASHLAYOUT_PARTITION_LABELS' list with:
# - <bootscheme-label> from FLASHLAYOUT_BOOTSCHEME_LABELS' list
# - <config-label> from 'FLASHLAYOUT_CONFIG_LABELS' list
# Priority assignment is:
# It means the 'FLASHLAYOUT_PARTITION_LABELS' value can be overriden by setting:
# FLASHLAYOUT_PARTITION_LABELS_<bootscheme-label>_<config-label>
# FLASHLAYOUT_PARTITION_LABELS_<bootscheme-label>
# FLASHLAYOUT_PARTITION_LABELS_<config-label>
# FLASHLAYOUT_PARTITION_LABELS
#
# Another override mechanism is also implemented for all other partition variables:
# FLASHLAYOUT_PARTITION_ENABLE
# FLASHLAYOUT_PARTITION_ID
# FLASHLAYOUT_PARTITION_TYPE
# FLASHLAYOUT_PARTITION_DEVICE
# FLASHLAYOUT_PARTITION_OFFSET
# FLASHLAYOUT_PARTITION_BIN2LOAD
# We can override these variable with:
# - <config-label> from 'FLASHLAYOUT_CONFIG_LABELS' list
# - <bootscheme-label> from 'FLASHLAYOUT_BOOTSCHEME_LABELS' list
# - <partition-label> from 'FLASHLAYOUT_PARTITION_LABELS' list
# Priority assignment is:
# FLASHLAYOUT_PARTITION_xxx_<bootscheme-label>_<config-label>_<partition-label>
# FLASHLAYOUT_PARTITION_xxx_<bootscheme-label>_<config-label>
# FLASHLAYOUT_PARTITION_xxx_<bootscheme-label>_<partition-label>
# FLASHLAYOUT_PARTITION_xxx_<bootscheme-label>
# FLASHLAYOUT_PARTITION_xxx_<config-label>_<partition-label>
# FLASHLAYOUT_PARTITION_xxx_<config-label>
# FLASHLAYOUT_PARTITION_xxx_<partition-label>
# FLASHLAYOUT_PARTITION_xxx
# -----------------------------------------------------------------------------
变量定义
上面介绍部分大概对生成flashlayout tsv文件有了一定了解,下面看看相关的变量初始化定义:
# Configure flashlayout file generation
ENABLE_FLASHLAYOUT_CONFIG ??= "1"
# Configure direct use of flashlayout file without automatic file generation
ENABLE_FLASHLAYOUT_DEFAULT ??= "0"
# Configure path for provided flashlayout file
FLASHLAYOUT_DEFAULT_SRC ??= ""
# Configure flashlayout file name default format
FLASHLAYOUT_BASENAME ??= "FlashLayout"
FLASHLAYOUT_SUFFIX ??= "tsv"
# Configure flashlayout file generation for stm32wrapper4dbg
ENABLE_FLASHLAYOUT_CONFIG_WRAPPER4DBG ??= "0"
# Configure folders for flashlayout file generation
FLASHLAYOUT_DEPLOYDIR ?= "${DEPLOY_DIR}/images/${MACHINE}"
FLASHLAYOUT_TOPDIR ?= "${WORKDIR}/flashlayout-destdir/"
FLASHLAYOUT_SUBDIR ?= "flashlayout_${PN}"
FLASHLAYOUT_DESTDIR = "${FLASHLAYOUT_TOPDIR}/${FLASHLAYOUT_SUBDIR}"
# Init bootscheme and config labels
FLASHLAYOUT_BOOTSCHEME_LABELS ??= ""
FLASHLAYOUT_CONFIG_LABELS ??= ""
# Init partition image list (used to configure partitions)
FLASHLAYOUT_PARTITION_IMAGES ??= ""
# Init partition and type labels
# Note: possible override with bootscheme and/or config
FLASHLAYOUT_PARTITION_LABELS ??= ""
FLASHLAYOUT_TYPE_LABELS ??= ""
# Init flashlayout partition vars
# Note: possible override with bootscheme and/or config and/or partition
FLASHLAYOUT_PARTITION_ENABLE ??= ""
FLASHLAYOUT_PARTITION_ID ??= ""
FLASHLAYOUT_PARTITION_TYPE ??= ""
FLASHLAYOUT_PARTITION_DEVICE ??= ""
FLASHLAYOUT_PARTITION_OFFSET ??= ""
FLASHLAYOUT_PARTITION_BIN2LOAD ??= ""
FLASHLAYOUT_PARTITION_SIZE ??= ""
FLASHLAYOUT_PARTITION_REPLACE_PATTERNS ??= ""
可以看到ENABLE_FLASHLAYOUT_DEFAULT ??= “0” 即默认使用动态生成flashlayout文件,同时初始化了一系列介绍部分提及到的变量,还可以看到配置了默认flashlayout 的存储路径是“${DEPLOY_DIR}/images/${MACHINE}”下面
工作路径是“${WORKDIR}/flashlayout-destdir/flashlayout_${PN}”,如下所示:
匿名函数分析
下面开始分析出现的第一个函数。
可以看到这个函数似曾相识,在上一篇分析st-partitions-image class中的匿名函数也长的类似,同样用到了PARTITIONS_CONFIG 变量,这个变量的具体内容参考上一节st-partitions-image直接复制过来:
PARTITIONS_CONFIG=" bootfs vendorfs rootfs userfs"
//PARTITIONS_CONFIG[xxxfs] 字段含义
// “
S
T
M
32
M
P
X
X
F
S
I
M
A
G
E
,
{STM32MP_XXFS_IMAGE},
STM32MPXXFSIMAGE,{STM32MP_XXFS_LABEL},
S
T
M
32
M
P
X
X
F
S
M
O
U
N
T
P
O
I
N
T
,
{STM32MP_XXFS_MOUNTPOINT},
STM32MPXXFSMOUNTPOINT,{XXFS_PARTITION_SIZE},System”
PARTITIONS_CONFIG[bootfs] ?= “st-image-bootfs,boot,/boot,65536,System”
PARTITIONS_CONFIG[vendorfs] ?= “st-image-vendorfs,vendorfs,/vendor,16384,FileSystem”
PARTITIONS_CONFIG[rootfs] ?= “fs-mp1a-qt-openstlinux-eglfs,rootfs,1253376,FileSystem”
PARTITIONS_CONFIG[userfs] ?= “st-image-userfs,userfs,/usr/local,131072,FileSystem”
总结下面函数干的事情就是先找到所有do_image_complete 的task,然后过滤掉initrd ramfs bootfs vendorfs rootfs userfs 这几个,
添加一个do_create_flashlayout_config task,执行时机在 do_build 和 do_image_complete中间,执行do_create_flashlayout_config之前还要先执行flashlayout_partition_image_config函数
do_create_flashlayout_config[prefuncs] = flashlayout_partition_image_config
python __anonymous () {
# -----------------------------------------------------------------------------
# Make sure to add the flashlayout file creation after ROOTFS build
# So we should identify image ROOTFS build and only the ROOTFS (for now)
# As we know that PARTITIONS may be built as part of ROOTFS build, let's
# avoid amending the partition images
# -----------------------------------------------------------------------------
if d.getVar('ENABLE_FLASHLAYOUT_CONFIG') == "1":
# Gather all current tasks
tasks = filter(lambda k: d.getVarFlag(k, "task", True), d.keys())
for task in tasks:
# Check that we are dealing with image recipe
if task == 'do_image_complete':
# Init current image name
current_image_name = d.getVar('PN') or ""
# Init RAMFS image if any
initramfs = d.getVar('INITRAMFS_IMAGE') or ""
# Init INITRD image if any
initrd = d.getVar('INITRD_IMAGE') or ""
# Init partition list from PARTITIONS_CONFIG
image_partitions = []
# Append image_partitions list with all configured partition images:
partitionsconfigflags = d.getVarFlags('PARTITIONS_CONFIG')
# The "doc" varflag is special, we don't want to see it here
partitionsconfigflags.pop('doc', None)
partitionsconfig = (d.getVar('PARTITIONS_CONFIG') or "").split()
if len(partitionsconfig) > 0:
for config in partitionsconfig:
for f, v in partitionsconfigflags.items():
if config == f:
items = v.split(',')
# Make sure about PARTITIONS_CONFIG contents
if items[0] and len(items) > 5:
bb.fatal('[PARTITIONS_CONFIG] Only image,label,mountpoint,size,type can be specified!')
# Make sure that we're dealing with partition image and not rootfs image
if len(items) > 2 and items[2]:
# Mount point is available, so we're dealing with partition image
# Append image to image_partitions list
image_partitions.append(d.expand(items[0]))
break
# We need to clearly identify ROOTFS build, not InitRAMFS/initRD one (if any), not partition one either
if current_image_name not in image_partitions and current_image_name != initramfs and current_image_name != initrd:
# We add the flashlayout file creation task just after the do_image_complete for ROOTFS build
bb.build.addtask('do_create_flashlayout_config', 'do_build', 'do_image_complete', d)
# We add also the function that feeds the FLASHLAYOUT_PARTITION_* vars from PARTITIONS_CONFIG
d.appendVarFlag('do_create_flashlayout_config', 'prefuncs', ' flashlayout_partition_image_config')
}
do_create_flashlayout_config任务
上面知道每个image的bb都添加了一个do_create_flashlayout_config 任务和flashlayout_partition_image_config函数,那么下面的重点自然就是这两部分了。先从flashlayout_partition_image_config开始
flashlayout_partition_image_config
flashlayout_partition_image_config同样用到了PARTITIONS_CONFIG变量
以PARTITIONS_CONFIG[bootfs] ?= “st-image-bootfs,boot,/boot,65536,System” 为例, 实际做事如下:
FLASHLAYOUT_PARTITION_IMAGES +=boot
FLASHLAYOUT_PARTITION_BIN2LOAD_boot = st-image-bootfs + "-${DISTRO}-${MACHINE}.ext4
FLASHLAYOUT_PARTITION_SIZE_boot = 65536
FLASHLAYOUT_PARTITION_TYPE_boot = System
FLASHLAYOUT_PARTITION_ID_boot = $part_id
part_id 区分bin(从4开始)还是其他(从33开始)动态自增
PARTITIONS_CONFIG里面的其他镜像以此类推,那么下面这个图里还没有确定的就是P mmc0 0x00284400这几个部分了,
继续看do_create_flashlayout_config任务
python flashlayout_partition_image_config() {
"""
Set the different flashlayout partition vars for the configure partition
images.
Based on PARTITIONS_CONFIG, feed:
FLASHLAYOUT_PARTITION_IMAGES
FLASHLAYOUT_PARTITION_ID_
FLASHLAYOUT_PARTITION_TYPE_
FLASHLAYOUT_PARTITION_SIZE_
FLASHLAYOUT_PARTITION_BIN2LOAD_
"""
partitionsconfigflags = d.getVarFlags('PARTITIONS_CONFIG')
# The "doc" varflag is special, we don't want to see it here
partitionsconfigflags.pop('doc', None)
partitionsconfig = (d.getVar('PARTITIONS_CONFIG') or "").split()
if len(partitionsconfig) > 0:
# Init default partition id for binary type and other
id_bin = 4
id_oth = 33
for config in partitionsconfig:
for f, v in partitionsconfigflags.items():
if config == f:
items = v.split(',')
# Make sure about PARTITIONS_CONFIG contents
if items[0] and len(items) > 5:
bb.fatal('[PARTITIONS_CONFIG] Only image,label,mountpoint,size,type can be specified!')
if items[1]:
bb.debug(1, "Appending %s to FLASHLAYOUT_PARTITION_IMAGES." % items[1])
d.appendVar('FLASHLAYOUT_PARTITION_IMAGES', ' ' + items[1])
else:
bb.fatal('[PARTITIONS_CONFIG] Missing image label setting')
# Init flashlayout label
fl_label = d.expand(items[1])
if items[2] == '':
# There is no mountpoint specified, so we apply rootfs image format
bb.debug(1, "Set FLASHLAYOUT_PARTITION_BIN2LOAD_%s to %s." % (fl_label, items[0] + "-${MACHINE}.ext4"))
d.setVar('FLASHLAYOUT_PARTITION_BIN2LOAD_%s' % fl_label, items[0] + "-${MACHINE}.ext4")
else:
bb.debug(1, "Set FLASHLAYOUT_PARTITION_BIN2LOAD_%s to %s." % (fl_label, items[0] + "-${DISTRO}-${MACHINE}.ext4"))
d.setVar('FLASHLAYOUT_PARTITION_BIN2LOAD_%s' % fl_label, items[0] + "-${DISTRO}-${MACHINE}.ext4")
if items[3]:
bb.debug(1, "Set FLASHLAYOUT_PARTITION_SIZE_%s to %s." % (fl_label, items[3]))
d.setVar('FLASHLAYOUT_PARTITION_SIZE_%s' % fl_label, items[3])
else:
bb.fatal('[PARTITIONS_CONFIG] Missing PARTITION_SIZE setting for % label' % fl_label)
if items[4]:
bb.debug(1, "Set FLASHLAYOUT_PARTITION_TYPE_%s to %s." % (fl_label, items[4]))
d.setVar('FLASHLAYOUT_PARTITION_TYPE_%s' % fl_label, items[4])
# Compute partition id according to type set
if items[4] == 'Binary':
part_id = '0x{0:0{1}X}'.format(id_bin, 2)
id_bin = id_bin + 1
else:
part_id = '0x{0:0{1}X}'.format(id_oth, 2)
id_oth = id_oth + 1
bb.debug(1, "Set FLASHLAYOUT_PARTITION_ID_%s to %s." % (fl_label, part_id))
d.setVar('FLASHLAYOUT_PARTITION_ID_%s' % fl_label, "%s" % part_id)
else:
bb.fatal('[PARTITIONS_CONFIG] Missing PARTITION_TYPE setting for % label' % fl_label)
break
}
do_create_flashlayout_config
在分析do_create_flashlayout_config task具体任务之前先看一下跟task相关的一些设置:
python do_create_flashlayout_config() {
}
do_create_flashlayout_config[dirs] = "${FLASHLAYOUT_DESTDIR}"
FLASHLAYOUT_DEPEND_TASKS ?= ""
do_create_flashlayout_config[depends] += "${FLASHLAYOUT_DEPEND_TASKS}"
SSTATETASKS += "do_create_flashlayout_config"
do_create_flashlayout_config[cleandirs] = "${FLASHLAYOUT_TOPDIR}"
do_create_flashlayout_config[sstate-inputdirs] = "${FLASHLAYOUT_TOPDIR}"
do_create_flashlayout_config[sstate-outputdirs] = "${FLASHLAYOUT_DEPLOYDIR}/"
FLASHLAYOUT_LABELS_VARS = "CONFIG_LABELS PARTITION_LABELS TYPE_LABELS"
FLASHLAYOUT_LABELS_OVERRIDES = "${@' '.join('%s %s %s_%s' % (b, c, b, c) for b in d.getVar('FLASHLAYOUT_BOOTSCHEME_LABELS').split() for c in d.getVar('FLASHLAYOUT_CONFIG_LABELS').split())}"
do_create_flashlayout_config[vardeps] += "${@' '.join(['FLASHLAYOUT_%s_%s' % (v, o) for v in d.getVar('FLASHLAYOUT_LABELS_VARS').split() for o in d.getVar('FLASHLAYOUT_LABELS_OVERRIDES').split()])}"
FLASHLAYOUT_PARTITION_VARS = "ENABLE ID TYPE DEVICE OFFSET BIN2LOAD SIZE REPLACE_PATTERNS"
FLASHLAYOUT_PARTITION_CONFIGURED = "${@" ".join(map(lambda o: "%s" % d.getVar("FLASHLAYOUT_PARTITION_LABELS_%s" % o), d.getVar('FLASHLAYOUT_LABELS_OVERRIDES').split()))}"
FLASHLAYOUT_PARTITION_OVERRIDES = "${@' '.join('%s %s %s_%s' % (o, p, o, p) for o in d.getVar('FLASHLAYOUT_LABELS_OVERRIDES').split() for p in d.getVar('FLASHLAYOUT_PARTITION_CONFIGURED').split())}"
do_create_flashlayout_config[vardeps] += "${@' '.join(['FLASHLAYOUT_PARTITION_%s_%s' % (v, o) for v in d.getVar('FLASHLAYOUT_PARTITION_VARS').split() for o in d.getVar('FLASHLAYOUT_PARTITION_OVERRIDES').split()])}"
FLASHLAYOUT_DEVICE_VARS = "ALIGNMENT_SIZE BOARD_ENABLE START_OFFSET"
FLASHLAYOUT_PARTITION_DEVICE_CONFIGURED = "${@" ".join(map(lambda p: "%s" % d.getVar("DEVICE_%s" % p), d.getVar('DEVICE_STORAGE_NAMES').split()))}"
do_create_flashlayout_config[vardeps] += "${@' '.join(['DEVICE_%s_%s' % (v, o) for v in d.getVar('FLASHLAYOUT_DEVICE_VARS').split() for o in d.getVar('FLASHLAYOUT_PARTITION_DEVICE_CONFIGURED').split()])}"
指定do_create_flashlayout_config 任务的
- 工作路径为“${WORKDIR}/flashlayout-destdir/flashlayout_${PN}”
- depends依赖(暂时为空)
- SSTATETASKS 添加上do_create_flashlayout_config任务,同时指定共享状态的工作路径。
- 设置do_create_flashlayout_config会用到的环境变量依赖列表
下面分析具体的do_create_flashlayout_config任务主体函数
python do_create_flashlayout_config() {
import re
import shutil
# We check first if it is requested to generate any flashlayout files
if d.getVar("ENABLE_FLASHLAYOUT_CONFIG") != "1":
bb.note('ENABLE_FLASHLAYOUT_CONFIG not enabled')
return
# Create destination folder for flashlayout files
bb.utils.remove(d.getVar('FLASHLAYOUT_DESTDIR'), recurse=True)
bb.utils.mkdirhier(d.getVar('FLASHLAYOUT_DESTDIR'))
# We check if user as define a static flashlayout file to use instead of dynamic generation
if d.getVar("ENABLE_FLASHLAYOUT_DEFAULT") == "1":
bb.note('ENABLE_FLASHLAYOUT_DEFAULT enabled')
flashlayout_src = d.getVar("FLASHLAYOUT_DEFAULT_SRC")
if not flashlayout_src:
bb.fatal("FLASHLAYOUT_DEFAULT_SRC not defined, please set a proper value")
if not flashlayout_src.strip():
bb.fatal("No static flashlayout file configured, nothing to do")
for fl_src in flashlayout_src.split():
found, f = flashlayout_search(d, fl_src)
if found:
flashlayout_staticname=os.path.basename(f)
flashlayout_file = os.path.join(d.getVar('FLASHLAYOUT_DESTDIR'), flashlayout_staticname)
shutil.copy2(f, flashlayout_file)
bb.note('Copy %s to output file %s' % (f, flashlayout_file))
else:
bb.fatal("Configure static file: %s not found" % fl_src)
return
# Set bootschemes for partition var override configuration
bootschemes = d.getVar('FLASHLAYOUT_BOOTSCHEME_LABELS')
if not bootschemes:
bb.fatal("FLASHLAYOUT_BOOTSCHEME_LABELS not defined, nothing to do")
if not bootschemes.strip():
bb.fatal("No bootschemes, nothing to do")
# Make sure there is no '_' in FLASHLAYOUT_BOOTSCHEME_LABELS
for bootscheme in bootschemes.split():
if re.match('.*_.*', bootscheme):
bb.fatal("Please remove all '_' for bootschemes defined in FLASHLAYOUT_BOOTSCHEME_LABELS")
bb.note('FLASHLAYOUT_BOOTSCHEME_LABELS: %s' % bootschemes)
for bootscheme in bootschemes.split():
bb.note('*** Loop for bootscheme label: %s' % bootscheme)
# Get the different flashlayout config label
configs = expand_var('FLASHLAYOUT_CONFIG_LABELS', bootscheme, '', '', d)
# Make sure there is no '_' in FLASHLAYOUT_CONFIG_LABELS
for config in configs.split():
if re.match('.*_.*', config):
bb.fatal("Please remove all '_' for configs defined in FLASHLAYOUT_CONFIG_LABELS")
bb.note('FLASHLAYOUT_CONFIG_LABELS: %s' % configs)
if configs.strip() == 'none':
bb.note("FLASHLAYOUT_CONFIG_LABELS is none, so no flashlayout file to generate.")
continue
# Create bootscheme subfolder for flashlayout files
flashlayout_subfolder_path = os.path.join(d.getVar('FLASHLAYOUT_DESTDIR'), bootscheme)
bb.utils.mkdirhier(flashlayout_subfolder_path)
for config in configs.split():
bb.note('*** Loop for config label: %s' % config)
# Set labeltypes list
labeltypes = expand_var('FLASHLAYOUT_TYPE_LABELS', bootscheme, config, '', d)
bb.note('FLASHLAYOUT_TYPE_LABELS: %s' % labeltypes)
if labeltypes.strip() == 'none':
bb.note("FLASHLAYOUT_TYPE_LABELS is none, so no flashlayout file to generate.")
continue
for labeltype in labeltypes.split():
bb.note('*** Loop for label type: %s' % labeltype)
# Init current label
current_label = labeltype
# Init flashlayout file name
if config == 'none':
config_append = ''
else:
config_append = '_' + config
if len(labeltypes.split()) < 2 and len(bootschemes.split()) < 2:
labeltype_append = ''
else:
labeltype_append = '_' + labeltype + '-' + bootscheme
flashlayout_file = os.path.join(flashlayout_subfolder_path, d.expand("${FLASHLAYOUT_BASENAME}%s%s.${FLASHLAYOUT_SUFFIX}" % (config_append, labeltype_append)))
# Get the partition list to write in flashlayout file
partitions = expand_var('FLASHLAYOUT_PARTITION_LABELS', bootscheme, config, '', d)
bb.note('FLASHLAYOUT_PARTITION_LABELS: %s' % partitions)
if partitions == 'none':
bb.note("FLASHLAYOUT_PARTITION_LABELS is none, so no flashlayout file to generate.")
continue
# Generate flashlayout file for labeltype
try:
with open(flashlayout_file, 'w') as fl_file:
# Write to flashlayout file the first line header
fl_file.write('#Opt\tId\tName\tType\tIP\tOffset\tBinary\n')
# Init partition next offset to 'none'
partition_nextoffset = "none"
# Init partition previous device to 'none'
partition_prevdevice = "none"
for partition in partitions.split():
bb.note('*** Loop for partition: %s' % partition)
# Init partition settings
partition_enable = expand_var('FLASHLAYOUT_PARTITION_ENABLE', bootscheme, config, partition, d)
partition_id = expand_var('FLASHLAYOUT_PARTITION_ID', bootscheme, config, partition, d)
partition_name = partition
partition_type = expand_var('FLASHLAYOUT_PARTITION_TYPE', bootscheme, config, partition, d)
partition_device = get_device(bootscheme, config, partition, d)
# Reset partition_nextoffset to 'none' in case partition device has changed
if partition_device != partition_prevdevice:
partition_nextoffset = "none"
# Save partition current device to previous one for next loop
partition_prevdevice = partition_device
# Get partition offset
partition_offset, partition_nextoffset = get_offset(partition_nextoffset, partition_device, bootscheme, config, partition, d)
# Get binary name
partition_bin2load = get_binaryname(labeltype, bootscheme, config, partition, d)
# Be verbose in log file
bb.note('>>> Layout inputs: %s' % fl_file.name)
bb.note('>>> FLASHLAYOUT_PARTITION_ENABLE: %s' % partition_enable)
bb.note('>>> FLASHLAYOUT_PARTITION_ID: %s' % partition_id)
bb.note('>>> FLASHLAYOUT_PARTITION_LABEL: %s' % partition_name)
bb.note('>>> FLASHLAYOUT_PARTITION_TYPE: %s' % partition_type)
bb.note('>>> FLASHLAYOUT_PARTITION_DEVICE: %s' % partition_device)
bb.note('>>> FLASHLAYOUT_PARTITION_OFFSET: %s' % partition_offset)
bb.note('>>> FLASHLAYOUT_PARTITION_BIN2LOAD: %s' % partition_bin2load)
bb.note('>>> done')
# Get the supported labels for current storage device
partition_device_alias = d.getVar('DEVICE_%s' % partition_device) or ""
partition_type_supported_labels = d.getVar('DEVICE_BOARD_ENABLE_%s' % partition_device_alias) or "none"
# Check if partition type is supported for the current label
if partition_device != 'none' and current_label not in partition_type_supported_labels.split():
bb.note('>>> FLASHLAYOUT_PARTITION_DEVICE (%s, alias %s) is not supported for current label (%s): partition %s not appended in flashlayout file' % (partition_device, partition_device_alias, current_label, partition_name))
bb.note('>>> DEVICE_BOARD_ENABLE_%s: %s' % (partition_device_alias, partition_type_supported_labels))
continue
# Write to flashlayout file the partition configuration
fl_file.write('%s\t%s\t%s\t%s\t%s\t%s\t%s\n' %
(partition_enable, partition_id, partition_name, partition_type, partition_device, partition_offset, partition_bin2load))
except OSError:
bb.fatal('Unable to open %s' % (fl_file))
if d.getVar("ENABLE_FLASHLAYOUT_CONFIG_WRAPPER4DBG") == "1":
bb.note('*** Loop for flashlayout for the wrapper for debug %s' % labeltype)
tmp_flashlayout_file = os.path.join(flashlayout_subfolder_path, "flashlayout.tmp")
debug_flashlayout = False
try:
with open(flashlayout_file, 'r') as fl_file:
try:
with open(tmp_flashlayout_file, 'w') as debug_fl_file:
for line in fl_file:
if re.match('^.*/tf-a.*$', line) :
line_tmp = re.sub(r'(.*)/',r'\1/debug/debug-', line)
filename = re.sub(r'.*[\t ](.*)$',r'\1', line_tmp).strip()
if os.path.isfile(os.path.join(d.getVar('DEPLOY_DIR_IMAGE'), filename)):
line = line_tmp
debug_flashlayout = True
debug_fl_file.write('%s' % (line))
except OSError:
bb.fatal('Unable to open %s' % (debug_fl_file))
except OSError:
bb.fatal('Unable to open %s' % (fl_file))
if debug_flashlayout:
flashlayout_wrapper4dbg_subfolder_path = os.path.join(d.getVar('FLASHLAYOUT_DESTDIR'), bootscheme, "debug")
bb.utils.mkdirhier(flashlayout_wrapper4dbg_subfolder_path)
# Wrapper4dbg output filename
debug_flashlayout_file = os.path.join(flashlayout_wrapper4dbg_subfolder_path,d.expand("debug-${FLASHLAYOUT_BASENAME}%s%s.${FLASHLAYOUT_SUFFIX}" % (config_append, labeltype_append)))
bb.note(">>> Update tf-a in %s" % (debug_flashlayout_file))
os.rename(tmp_flashlayout_file, debug_flashlayout_file)
else:
os.remove(tmp_flashlayout_file)
}
函数非常长,大概有170行,重点总结一下实际做的事:
- 如果使能了静态flashlayout生成则做一些检查,然后将自定义的flashlayout tsv文件拷贝到工作路径下
- 定义了一系列函数初始化变量、获取device的名字、计算offset等函数,然后根据BOOTSCHEME_LABELS 划分子目录,创建文件、写入每一行的具体内容,最终做一些校验。
do_create_flashlayout_config 任务里面非常繁杂,但是大概浏览一遍能差不多明白创建流程,这个class留了几个变量是被inc文件设置的,比如:
FLASHLAYOUT_DEPEND_TASKS
FLASHLAYOUT_BOOTSCHEME_LABELS
FLASHLAYOUT_CONFIG_LABELS
…
这些其实都在 machine/conf/inc st-machine-flashlayout-stm32mp.inc里面做了详细的配置。
总结:通过对st-partitions-image 还有flashlayout-stm32mp两个class的分析,STM32MP1创建分区和刷机文件好像变得越来越清晰,是时候该动起来创建自己的分区了,详见下一篇文章!