build_kernel_image: Command line for NAND
This patch modifies the build scripts to create a kernel command line
with the appropriate parameters:
- The root device and hash device for dm-verity are /dev/ubi${n}_0,
where n is the index of the kernel partition + 1.
- The root device if dm-verity is off retains its current value, but
is substitutable by a script in the board overlay. This allows
some boards that know they will have new firmware to use %R, which
will switch to rootfs on ubiblock when applicable.
- Each ubi partition is attached and ubiblock is created.
A downside to this patch: ubi and ubiblock are attached whether or
not we have booted from NAND, if they are in the disk-layout.json.
This means that booting from USB gets a bunch of harmness UBI-related
error messages in the console.
TEST=Together with another patch in the Storm NAND overlay,
booted from NAND with rootfs and stateful on NAND.
root@localhost $ cat /proc/cmdline
cros_secure earlyprintk=ttyMSM0,115200n8 console=tty1
console=ttyMSM0,115200n8 loglevel=7 init=/sbin/init cros_secure
oops=panic panic=-1 root=/dev/ubiblock3_0 rootwait ro
dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0
noinitrd vt.global_cursor_default=0
kern_guid=e2ad1269-e247-2f46-97ea-d9f572cf87b1 ubi.mtd=8,0,0,8
ubi.mtd=1,0,0,1 ubi.mtd=5,0,0,5 ubi.block=5,0 ubi.mtd=3,0,0,3
ubi.block=3,0
Also boots successfully from USB.
BRANCH=none
BUG=chromium:442784
Signed-off-by: Dan Ehrenberg <dehrenberg@chromium.org>
Change-Id: Ifdf10943bd57a876d6e1fba5f5b6ff2950259196
Reviewed-on: https://chromium-review.googlesource.com/230811
diff --git a/bin/cros_make_image_bootable b/bin/cros_make_image_bootable
index e670ff9..ac11988 100755
--- a/bin/cros_make_image_bootable
+++ b/bin/cros_make_image_bootable
@@ -233,6 +233,7 @@
--private="${private}" \
--public="${public}" \
--enable_serial="${FLAGS_enable_serial}" \
+ --image_type="${FLAGS_image_type}" \
${vblock} \
${enable_rootfs_verification_flag} \
${enable_bootcache_flag}
diff --git a/build_kernel_image.sh b/build_kernel_image.sh
index 0f517af..9f8a3c0 100755
--- a/build_kernel_image.sh
+++ b/build_kernel_image.sh
@@ -59,6 +59,8 @@
"Enable serial port for printks. Example values: ttyS0"
DEFINE_integer loglevel 7 \
"The loglevel to add to the kernel command line."
+DEFINE_string image_type "base" \
+ "Type of image we're building for (base/factory_install)."
# Parse flags
FLAGS "$@" || exit 1
@@ -70,6 +72,7 @@
# N.B. Ordering matters for some of the libraries below, because
# some of the files contain initialization used by later files.
. "${BUILD_LIBRARY_DIR}/board_options.sh" || exit 1
+. "${BUILD_LIBRARY_DIR}/disk_layout_util.sh" || exit 1
rootdigest() {
local digest=${table#*root_hexdigest=}
@@ -99,8 +102,14 @@
:
}
+get_base_root() {
+ echo 'PARTUUID=%U/PARTNROFF=1'
+}
+
load_board_specific_script "${BOARD}" "build_kernel_image.sh"
+base_root=$(get_base_root)
+
device_mapper_args=
# Even with a rootfs_image, root= is not changed unless specified.
if [[ -n "${FLAGS_rootfs_image}" && -n "${FLAGS_rootfs_hash}" ]]; then
@@ -142,8 +151,6 @@
if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then
if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then
base_root='254:0' # major:minor numbers for /dev/dm-0
- else
- base_root='PARTUUID=%U/PARTNROFF=1' # kern_guid + 1
fi
table=${table//HASH_DEV/${base_root}}
table=${table//ROOT_DEV/${base_root}}
@@ -173,7 +180,7 @@
# production use. If +%d can be added upstream, then we can use:
# root_dev=PARTUID=uuid+1
dev_wait=0
-root_dev="PARTUUID=%U/PARTNROFF=1"
+root_dev=${base_root}
if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then
dev_wait=1
if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then
@@ -261,6 +268,33 @@
error "Unknown arch: ${FLAGS_arch}"
fi
+already_seen_rootfs=0
+for p in $(get_partitions "${FLAGS_image_type}"); do
+ format=$(get_format "${FLAGS_image_type}" "${p}")
+ if [[ "${format}" == "ubi" ]]; then
+ type=$(get_type "${FLAGS_image_type}" "${p}")
+ # cgpt.py ensures that the rootfs partitions are compatible, in that if
+ # one is ubi then both are, and they have the same number of reserved
+ # blocks. We only want to attach one of them in boot to save time, so
+ # attach %P and get the information for whichever rootfs comes first.
+ if [[ "${type}" == "rootfs" ]]; then
+ if [[ "${already_seen_rootfs}" -ne 0 ]]; then
+ continue
+ fi
+ already_seen_rootfs=1
+ partname='%P'
+ else
+ partname="${p}"
+ fi
+ echo "ubi.mtd=${partname},0,0,${partname}" \
+ >> "${FLAGS_working_dir}/config.txt"
+ fs_format=$(get_filesystem_format "${FLAGS_image_type}" "${p}")
+ if [[ "${fs_format}" != "ubifs" ]]; then
+ echo "ubi.block=${partname},0" >> "${FLAGS_working_dir}/config.txt"
+ fi
+ fi
+done
+
config_file="${FLAGS_working_dir}/config.txt"
modify_kernel_command_line "${config_file}"
# Create and sign the kernel blob
diff --git a/build_library/cgpt.py b/build_library/cgpt.py
index 8bf8508..54acb47 100755
--- a/build_library/cgpt.py
+++ b/build_library/cgpt.py
@@ -33,6 +33,12 @@
class ConflictingOptions(Exception):
"""Conflicting Options"""
+class MismatchedRootfsFormat(Exception):
+ """Rootfs partitions in different formats"""
+
+class MismatchedRootfsBlocks(Exception):
+ """Rootfs partitions have different numbers of reserved erase blocks"""
+
COMMON_LAYOUT = 'common'
BASE_LAYOUT = 'base'
# Blocks of the partition entry array.
@@ -821,6 +827,25 @@
return partition.get('fs_format')
+def GetFormat(options, image_type, layout_filename, num):
+ """Returns the format of a given partition for a given layout type.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ num: Number of the partition you want to read from
+
+ Returns:
+ Format of the selected partition's filesystem
+ """
+
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partition = GetPartitionByNumber(partitions, num)
+
+ return partition.get('format')
+
+
def GetFilesystemOptions(options, image_type, layout_filename, num):
"""Returns the filesystem options of a given partition and layout type.
@@ -952,15 +977,45 @@
))
-def DoParseOnly(options, image_type, layout_filename):
- """Parses a layout file only, used before reading sizes to check for errors.
+def CheckRootfsPartitionsMatch(partitions):
+ """Checks that rootfs partitions are substitutable with each other.
+
+ This function asserts that either all rootfs partitions are in the same format
+ or none have a format, and it asserts that have the same number of reserved
+ erase blocks.
+ """
+ partition_format = None
+ reserved_erase_blocks = -1
+ for partition in partitions:
+ if partition.get('type') == 'rootfs':
+ new_format = partition.get('format', '')
+ new_reserved_erase_blocks = partition.get('reserved_erase_blocks', 0)
+
+ if partition_format is None:
+ partition_format = new_format
+ reserved_erase_blocks = new_reserved_erase_blocks
+
+ if new_format != partition_format:
+ raise MismatchedRootfsFormat(
+ 'mismatched rootfs formats: "%s" and "%s"' %
+ (partition_format, new_format))
+
+ if reserved_erase_blocks != new_reserved_erase_blocks:
+ raise MismatchedRootfsBlocks(
+ 'mismatched rootfs reserved erase block counts: %s and %s' %
+ (reserved_erase_blocks, new_reserved_erase_blocks))
+
+
+def Validate(options, image_type, layout_filename):
+ """Validates a layout file, used before reading sizes to check for errors.
Args:
options: Flags passed to the script
image_type: Type of image eg base/test/dev/factory_install
layout_filename: Path to partition configuration file
"""
- GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ CheckRootfsPartitionsMatch(partitions)
def main(argv):
@@ -981,6 +1036,10 @@
'usage': ['<image_type>', '<disk_layout>', '<partition_num>'],
'func': GetPartitionSize,
},
+ 'readformat': {
+ 'usage': ['<image_type>', '<disk_layout>', '<partition_num>'],
+ 'func': GetFormat,
+ },
'readfsformat': {
'usage': ['<image_type>', '<disk_layout>', '<partition_num>'],
'func': GetFilesystemFormat,
@@ -1013,9 +1072,9 @@
'usage': ['<image_type>', '<disk_layout>'],
'func': DoDebugOutput,
},
- 'parseonly': {
+ 'validate': {
'usage': ['<image_type>', '<disk_layout>'],
- 'func': DoParseOnly,
+ 'func': Validate,
},
}
diff --git a/build_library/disk_layout_util.sh b/build_library/disk_layout_util.sh
index d2c5771..6789edd 100644
--- a/build_library/disk_layout_util.sh
+++ b/build_library/disk_layout_util.sh
@@ -93,6 +93,14 @@
cgpt_py readfsformat "${image_type}" "${DISK_LAYOUT_PATH}" ${part_id}
}
+get_format() {
+ local image_type=$1
+ local part_id=$2
+ get_disk_layout_path
+
+ cgpt_py readformat "${image_type}" "${DISK_LAYOUT_PATH}" "${part_id}"
+}
+
get_partitions() {
local image_type=$1
get_disk_layout_path
@@ -136,7 +144,7 @@
local image_type=$1
get_disk_layout_path
- cgpt_py parseonly "${image_type}" "${DISK_LAYOUT_PATH}" > /dev/null
+ cgpt_py validate "${image_type}" "${DISK_LAYOUT_PATH}" > /dev/null
}
get_disk_layout_type() {