diff options
author | Simon Glass | 2023-08-24 13:55:41 -0600 |
---|---|---|
committer | Tom Rini | 2023-08-25 17:55:19 -0400 |
commit | d08db02d2d3d5ccf365e423b0c3dfb6fe311abd6 (patch) | |
tree | 135fa2ed6ac33274c9b671167bf517fc461298b9 /test/py | |
parent | 2b9adcaca2055d891775c59096147f702f6423bd (diff) |
bootstd: Add a test for bootmeth_cros
The ChromiumOS bootmeth has no tests at present. Before adding more
features. add a basic test.
This creates a disk which can be scanned by the bootmeth, so make sure
things work. It is quite rudimentary, since the kernel is faked, the root
disk is missing and there is no cmdline stored.
Enable the bootmeth for snow so it can build the unit test.
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'test/py')
-rw-r--r-- | test/py/tests/test_ut.py | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 640129018c1..82932a662bf 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +import collections import getpass import gzip import os @@ -282,6 +283,146 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) copy_prepared_image(cons, mmc_dev, fname) +def setup_cros_image(cons): + """Create a 20MB disk image with ChromiumOS partitions""" + Partition = collections.namedtuple('part', 'start,size,name') + parts = {} + disk_data = None + + def pack_kernel(cons, arch, kern, dummy): + """Pack a kernel containing some fake data + + Args: + cons (ConsoleBase): Console to use + arch (str): Architecture to use ('x86' or 'arm') + kern (str): Filename containing kernel + dummy (str): Dummy filename to use for config and bootloader + + Return: + bytes: Packed-kernel data + """ + kern_part = os.path.join(cons.config.result_dir, 'kern-part-{arch}.bin') + u_boot_utils.run_and_log( + cons, + f'futility vbutil_kernel --pack {kern_part} ' + '--keyblock doc/chromium/files/devkeys/kernel.keyblock ' + '--signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk ' + f'--version 1 --config {dummy} --bootloader {dummy} ' + f'--vmlinuz {kern}') + + with open(kern_part, 'rb') as inf: + kern_part_data = inf.read() + return kern_part_data + + def set_part_data(partnum, data): + """Set the contents of a disk partition + + This updates disk_data by putting data in the right place + + Args: + partnum (int): Partition number to set + data (bytes): Data for that partition + """ + nonlocal disk_data + + start = parts[partnum].start * sect_size + disk_data = disk_data[:start] + data + disk_data[start + len(data):] + + mmc_dev = 5 + fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') + u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname) + #mnt = os.path.join(cons.config.persistent_data_dir, 'mnt') + #mkdir_cond(mnt) + u_boot_utils.run_and_log(cons, f'cgpt create {fname}') + + uuid_state = 'ebd0a0a2-b9e5-4433-87c0-68b6b72699c7' + uuid_kern = 'fe3a2a5d-4f32-41a7-b725-accc3285a309' + uuid_root = '3cb8e202-3b7e-47dd-8a3c-7ff2a13cfcec' + uuid_rwfw = 'cab6e88e-abf3-4102-a07a-d4bb9be3c1d3' + uuid_reserved = '2e0a753d-9e48-43b0-8337-b15192cb1b5e' + uuid_efi = 'c12a7328-f81f-11d2-ba4b-00a0c93ec93b' + + ptr = 40 + + # Number of sectors in 1MB + sect_size = 512 + sect_1mb = (1 << 20) // sect_size + + required_parts = [ + {'num': 0xb, 'label':'RWFW', 'type': uuid_rwfw, 'size': '1'}, + {'num': 6, 'label':'KERN_C', 'type': uuid_kern, 'size': '1'}, + {'num': 7, 'label':'ROOT_C', 'type': uuid_root, 'size': '1'}, + {'num': 9, 'label':'reserved', 'type': uuid_reserved, 'size': '1'}, + {'num': 0xa, 'label':'reserved', 'type': uuid_reserved, 'size': '1'}, + + {'num': 2, 'label':'KERN_A', 'type': uuid_kern, 'size': '1M'}, + {'num': 4, 'label':'KERN_B', 'type': uuid_kern, 'size': '1M'}, + + {'num': 8, 'label':'OEM', 'type': uuid_state, 'size': '1M'}, + {'num': 0xc, 'label':'EFI-SYSTEM', 'type': uuid_efi, 'size': '1M'}, + + {'num': 5, 'label':'ROOT_B', 'type': uuid_root, 'size': '1'}, + {'num': 3, 'label':'ROOT_A', 'type': uuid_root, 'size': '1'}, + {'num': 1, 'label':'STATE', 'type': uuid_state, 'size': '1M'}, + ] + + for part in required_parts: + size_str = part['size'] + if 'M' in size_str: + size = int(size_str[:-1]) * sect_1mb + else: + size = int(size_str) + u_boot_utils.run_and_log( + cons, + f"cgpt add -i {part['num']} -b {ptr} -s {size} -t {part['type']} {fname}") + ptr += size + + u_boot_utils.run_and_log(cons, f'cgpt boot -p {fname}') + out = u_boot_utils.run_and_log(cons, f'cgpt show -q {fname}') + '''We expect something like this: + 8239 2048 1 Basic data + 45 2048 2 ChromeOS kernel + 8238 1 3 ChromeOS rootfs + 2093 2048 4 ChromeOS kernel + 8237 1 5 ChromeOS rootfs + 41 1 6 ChromeOS kernel + 42 1 7 ChromeOS rootfs + 4141 2048 8 Basic data + 43 1 9 ChromeOS reserved + 44 1 10 ChromeOS reserved + 40 1 11 ChromeOS firmware + 6189 2048 12 EFI System Partition + ''' + + # Create a dict (indexed by partition number) containing the above info + for line in out.splitlines(): + start, size, num, name = line.split(maxsplit=3) + parts[int(num)] = Partition(int(start), int(size), name) + + dummy = os.path.join(cons.config.result_dir, 'dummy.txt') + with open(dummy, 'wb') as outf: + outf.write(b'dummy\n') + + # For now we just use dummy kernels. This limits testing to just detecting + # a signed kernel. We could add support for the x86 data structures so that + # testing could cover getting the cmdline, setup.bin and other pieces. + kern = os.path.join(cons.config.result_dir, 'kern.bin') + with open(kern, 'wb') as outf: + outf.write(b'kernel\n') + + with open(fname, 'rb') as inf: + disk_data = inf.read() + + # put x86 kernel in partition 2 and arm one in partition 4 + set_part_data(2, pack_kernel(cons, 'x86', kern, dummy)) + set_part_data(4, pack_kernel(cons, 'arm', kern, dummy)) + + with open(fname, 'wb') as outf: + outf.write(disk_data) + + return fname + + def setup_cedit_file(cons): infname = os.path.join(cons.config.source_dir, 'test/boot/files/expo_layout.dts') @@ -329,6 +470,7 @@ def test_ut_dm_init_bootstd(u_boot_console): setup_bootflow_image(u_boot_console) setup_bootmenu_image(u_boot_console) setup_cedit_file(u_boot_console) + setup_cros_image(u_boot_console) # Restart so that the new mmc1.img is picked up u_boot_console.restart_uboot() |