Merge branch 'makea' into 'master'

test: Move towards using a fixture for test images

See merge request u-boot/u-boot!152
This commit is contained in:
Simon Glass
2025-08-17 12:49:58 +00:00
9 changed files with 268 additions and 180 deletions

View File

@@ -115,6 +115,7 @@ static int check_abrec_norun(struct unit_test_state *uts, bool use_oem,
root = oftree_root(tree);
ut_asserteq_str("snow", ofnode_read_string(root, "compatible"));
bootflow_free(&bflow);
return 0;
}

View File

@@ -35,7 +35,7 @@ class ConsoleSandbox(ConsoleBase):
Returns:
A spawn.Spawn object that is attached to U-Boot.
"""
super().get_spawn()
self.prepare_for_spawn()
bcfg = self.config.buildconfig
config_spl = bcfg.get('config_spl', 'n') == 'y'
config_vpl = bcfg.get('config_vpl', 'n') == 'y'

View File

@@ -7,20 +7,18 @@
import gzip
import os
import shutil
import tempfile
import utils
from fs_helper import DiskHelper, FsHelper
from dtoc import fdt_util
from u_boot_pylib import tools
def dtb_for_compatible(ubman, kernpath, version, model):
def dtb_for_compatible(log, kernpath, version, model):
"""Create a fake devicetree binary for a given model name
Args:
ubman (ConsoleBase): U-Boot fixture
log (multiplexed_log.Logfile): Log to write to
kernpath (str): Path to place the created DTB
version (str): Version string to use with the dtb
model (str): Model name
@@ -30,15 +28,17 @@ def dtb_for_compatible(ubman, kernpath, version, model):
"""
dtb_file = os.path.join(kernpath, f'dtb-{version}-{model}')
data = f'/dts-v1/; / {{ compatible = "{model}"; version = "{version}"; }};'
utils.run_and_log(ubman, f'dtc -o {dtb_file}', stdin=data.encode('utf-8'))
utils.run_and_log_no_ubman(log, f'dtc -o {dtb_file}',
stdin=data.encode('utf-8'))
return dtb_file
def create_extlinux(ubman, kernpath, dirpath, slot, version, has_oem):
def create_extlinux(config, log, kernpath, dirpath, slot, version, has_oem):
"""Create a fake extlinux image
Args:
ubman (ConsoleBase): U-Boot fixture
config (ArbitraryAttributeContainer): Configuration
log (multiplexed_log.Logfile): Log to write to
kernpath (str): Directory path for the kernel
dirpath (str): Directory path to write to (created by this function)
slot (str): Slot name (A, B or recovery)
@@ -80,33 +80,38 @@ label l0
with tempfile.TemporaryDirectory(suffix='vbe') as tmp:
kern = os.path.join(tmp, 'kern')
tools.write_file(kern, gzip.compress(f'vmlinux-{slot}'.encode('utf-8')))
mkimage = ubman.config.build_dir + '/tools/mkimage'
mkimage = config.build_dir + '/tools/mkimage'
initrd = os.path.join(tmp, f'initrd.img-{version}')
tools.write_file(initrd, f'initrd {version}', binary=False)
snow = dtb_for_compatible(ubman, tmp, version, 'snow')
kevin = dtb_for_compatible(ubman, tmp, version, 'kevin')
snow = dtb_for_compatible(log, tmp, version, 'snow')
kevin = dtb_for_compatible(log, tmp, version, 'kevin')
fit = os.path.join(kernpath, f'ubuntu-{version}.fit')
cmd = f'{mkimage} -f auto -T kernel -A sandbox -O linux '
dts = f'-b {snow} -b {kevin}' if add_dts else ''
utils.run_and_log(ubman, cmd + f'-d {kern} -i {initrd} {dts} {fit}')
utils.run_and_log_no_ubman(log,
cmd + f'-d {kern} -i {initrd} {dts} {fit}')
# Create a FIT containing OEM devicetrees
if has_oem:
oem_snow = dtb_for_compatible(ubman, tmp, 'oem', 'snow')
oem_kevin = dtb_for_compatible(ubman, tmp, 'oem', 'kevin')
oem_snow = dtb_for_compatible(log, tmp, 'oem', 'snow')
oem_kevin = dtb_for_compatible(log, tmp, 'oem', 'kevin')
fit = os.path.join(dirpath, 'oem.fit')
utils.run_and_log(
ubman,
utils.run_and_log_no_ubman(
log,
f'{mkimage} -f auto -A sandbox -O linux -T flat_dt --load-only'
f' -b {oem_snow} -b {oem_kevin} {fit}')
def setup_vbe_image(ubman):
def setup_vbe_image(config, log):
"""Create three partitions (fat, boot and root) for a VBE boot flow
Args:
config (ArbitraryAttributeContainer): Configuration
log (multiplexed_log.Logfile): Log to write to
The intent is to load either one or two FITs.
Two separate images are created:
@@ -115,10 +120,10 @@ def setup_vbe_image(ubman):
- vbe1 has an OEM FIT containing the devicetrees; OS FIT does not
"""
for seq in range(2):
with (DiskHelper(ubman.config, seq, 'vbe') as img,
FsHelper(ubman.config, 'fat', 1, 'efi') as vfat,
FsHelper(ubman.config, 'ext4', 1, f'boot{seq}') as boot,
FsHelper(ubman.config, 'ext4', 17, 'root') as root):
with (DiskHelper(config, seq, 'vbe') as img,
FsHelper(config, 'fat', 1, 'efi') as vfat,
FsHelper(config, 'ext4', 1, f'boot{seq}') as boot,
FsHelper(config, 'ext4', 17, 'root') as root):
with open(os.path.join(vfat.srcdir, 'u-boot.efi'), 'wb') as outf:
outf.write(b'fake binary\n')
vfat.mk_fs()
@@ -128,14 +133,14 @@ def setup_vbe_image(ubman):
dir_a = os.path.join(boot.srcdir, 'a')
vera = '6.14.0-24-generic'
create_extlinux(ubman, boot.srcdir, dir_a, 'A', vera, has_oem)
create_extlinux(config, log, boot.srcdir, dir_a, 'A', vera, has_oem)
dir_b = os.path.join(boot.srcdir, 'b')
verb = '6.8.0-1028-intel'
create_extlinux(ubman, boot.srcdir, dir_b, 'B', verb, has_oem)
create_extlinux(config, log, boot.srcdir, dir_b, 'B', verb, has_oem)
boot_slot = 'b' if seq else 'a'
fname = os.path.join(ubman.config.result_dir, 'vbe-state.dts')
fname = os.path.join(config.result_dir, 'vbe-state.dts')
tools.write_file(fname, b'''// VBE state file
/dts-v1/;
@@ -153,9 +158,9 @@ def setup_vbe_image(ubman):
};
'''.replace(b'boot_slot', boot_slot.encode('utf-8')))
dtb = fdt_util.EnsureCompiled(fname, ubman.config.result_dir)
print('dtb', dtb)
shutil.copy(dtb, f'{boot.srcdir}/vbe-state')
utils.run_and_log_no_ubman(
log, ['dtc', fname, '-O', 'dtb', '-o',
f'{boot.srcdir}/vbe-state'])
boot.mk_fs()
img.add_fs(boot, DiskHelper.EXT4)

View File

@@ -102,43 +102,43 @@ dtb1_addr = loadaddr + dtb1_offset
# DTB #2 start address in RAM
dtb2_addr = vloadaddr + dtb2_offset
class AbootimgTestDiskImage(object):
class AbootimgTestDiskImage():
"""Disk image used by abootimg tests."""
def __init__(self, ubman, image_name, hex_img):
def __init__(self, config, log, image_name, hex_img):
"""Initialize a new AbootimgDiskImage object.
Args:
ubman: A U-Boot console.
config (ArbitraryAttributeContainer): Configuration
Returns:
Nothing.
"""
gz_hex = ubman.config.persistent_data_dir + '/' + image_name + '.gz.hex'
gz = ubman.config.persistent_data_dir + '/' + image_name + '.gz'
gz_hex = config.persistent_data_dir + '/' + image_name + '.gz.hex'
gz = config.persistent_data_dir + '/' + image_name + '.gz'
filename = image_name
persistent = ubman.config.persistent_data_dir + '/' + filename
self.path = ubman.config.result_dir + '/' + filename
ubman.log.action('persistent is ' + persistent)
with utils.persistent_file_helper(ubman.log, persistent):
persistent = config.persistent_data_dir + '/' + filename
self.path = config.result_dir + '/' + filename
log.action('persistent is ' + persistent)
with utils.persistent_file_helper(log, persistent):
if os.path.exists(persistent):
ubman.log.action('Disk image file ' + persistent +
log.action('Disk image file ' + persistent +
' already exists')
else:
ubman.log.action('Generating ' + persistent)
log.action('Generating ' + persistent)
f = open(gz_hex, "w")
f.write(hex_img)
f.close()
cmd = ('xxd', '-r', '-p', gz_hex, gz)
utils.run_and_log(ubman, cmd)
utils.run_and_log_no_ubman(log, cmd)
cmd = ('gunzip', '-9', gz)
utils.run_and_log(ubman, cmd)
utils.run_and_log_no_ubman(log, cmd)
cmd = ('cp', persistent, self.path)
utils.run_and_log(ubman, cmd)
utils.run_and_log_no_ubman(log, cmd)
gtdi1 = None
@pytest.fixture(scope='function')
@@ -150,7 +150,8 @@ def abootimg_disk_image(ubman):
global gtdi1
if not gtdi1:
gtdi1 = AbootimgTestDiskImage(ubman, 'boot.img', img_hex)
gtdi1 = AbootimgTestDiskImage(ubman.config, ubman.log, 'boot.img',
img_hex)
return gtdi1
gtdi2 = None
@@ -163,7 +164,8 @@ def abootimgv4_disk_image_vboot(ubman):
global gtdi2
if not gtdi2:
gtdi2 = AbootimgTestDiskImage(ubman, 'vendor_boot.img', vboot_img_hex)
gtdi2 = AbootimgTestDiskImage(ubman.config, ubman.log,
'vendor_boot.img', vboot_img_hex)
return gtdi2
gtdi3 = None
@@ -176,7 +178,8 @@ def abootimgv4_disk_image_boot(ubman):
global gtdi3
if not gtdi3:
gtdi3 = AbootimgTestDiskImage(ubman, 'bootv4.img', boot_img_hex)
gtdi3 = AbootimgTestDiskImage(ubman.config, ubman.log, 'bootv4.img',
boot_img_hex)
return gtdi3
@pytest.mark.boardspec('sandbox')

View File

@@ -19,6 +19,7 @@ env__sleep_margin = 0.25
"""
@pytest.mark.slow
def test_sleep(ubman):
"""Test the sleep command, and validate that it sleeps for approximately
the correct amount of time."""
@@ -43,6 +44,7 @@ def test_sleep(ubman):
assert elapsed < (sleep_time + sleep_margin)
@pytest.mark.buildconfigspec("cmd_time")
@pytest.mark.slow
def test_time(ubman):
"""Test the time command, and validate that it gives approximately the
correct amount of command execution time."""

View File

@@ -39,10 +39,14 @@ def copy_partition(ubman, fsfile, outname):
utils.run_and_log(ubman,
f'dd if={fsfile} of={outname} bs=1M seek=1 conv=notrunc')
def setup_bootmenu_image(ubman):
def setup_bootmenu_image(config, log):
"""Create a 20MB disk image with a single ext4 partition
This is modelled on Armbian 22.08 Jammy
Args:
config (ArbitraryAttributeContainer): Configuration
log (multiplexed_log.Logfile): Log to write to
"""
mmc_dev = 4
@@ -120,7 +124,7 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}
# Recompile with:
# mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr
'''
fsh = FsHelper(ubman.config, 'ext4', 18, 'mmc')
fsh = FsHelper(config, 'ext4', 18, 'mmc')
fsh.setup()
bootdir = os.path.join(fsh.srcdir, 'boot')
mkdir_cond(bootdir)
@@ -129,16 +133,16 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}
with open(cmd_fname, 'w', encoding='ascii') as outf:
print(script, file=outf)
infname = os.path.join(ubman.config.source_dir,
infname = os.path.join(config.source_dir,
'test/py/tests/bootstd/armbian.bmp.xz')
bmp_file = os.path.join(bootdir, 'boot.bmp')
utils.run_and_log(
ubman,
utils.run_and_log_no_ubman(
log,
['sh', '-c', f'xz -dc {infname} >{bmp_file}'])
mkimage = ubman.config.build_dir + '/tools/mkimage'
utils.run_and_log(
ubman, f'{mkimage} -C none -A arm -T script -d {cmd_fname} {scr_fname}')
mkimage = config.build_dir + '/tools/mkimage'
utils.run_and_log_no_ubman(
log, f'{mkimage} -C none -A arm -T script -d {cmd_fname} {scr_fname}')
kernel = 'vmlinuz-5.15.63-rockchip64'
target = os.path.join(bootdir, kernel)
@@ -148,22 +152,22 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}
symlink = os.path.join(bootdir, 'Image')
if os.path.exists(symlink):
os.remove(symlink)
utils.run_and_log(
ubman, f'echo here {kernel} {symlink}')
utils.run_and_log_no_ubman(log, f'echo here {kernel} {symlink}')
os.symlink(kernel, symlink)
fsh.mk_fs()
img = DiskHelper(ubman.config, mmc_dev, 'mmc', True)
img = DiskHelper(config, mmc_dev, 'mmc', True)
img.add_fs(fsh, DiskHelper.EXT4)
img.create()
fsh.cleanup()
def setup_extlinux_image(ubman, devnum, basename, vmlinux, initrd, dtbdir,
def setup_extlinux_image(config, log, devnum, basename, vmlinux, initrd, dtbdir,
script):
"""Create a 20MB disk image with a single FAT partition
Args:
ubman (ConsoleBase): Console to use
config (ArbitraryAttributeContainer): Configuration
log (multiplexed_log.Logfile): Log to write to
devnum (int): Device number to use, e.g. 1
basename (str): Base name to use in the filename, e.g. 'mmc'
vmlinux (str): Kernel filename
@@ -171,7 +175,7 @@ def setup_extlinux_image(ubman, devnum, basename, vmlinux, initrd, dtbdir,
dtbdir (str or None): Devicetree filename
script (str): Script to place in the extlinux.conf file
"""
fsh = FsHelper(ubman.config, 'vfat', 18, prefix=basename)
fsh = FsHelper(config, 'vfat', 18, prefix=basename)
fsh.setup()
ext = os.path.join(fsh.srcdir, 'extlinux')
@@ -181,12 +185,12 @@ def setup_extlinux_image(ubman, devnum, basename, vmlinux, initrd, dtbdir,
with open(conf, 'w', encoding='ascii') as fd:
print(script, file=fd)
inf = os.path.join(ubman.config.persistent_data_dir, 'inf')
inf = os.path.join(config.persistent_data_dir, 'inf')
with open(inf, 'wb') as fd:
fd.write(gzip.compress(b'vmlinux'))
mkimage = ubman.config.build_dir + '/tools/mkimage'
utils.run_and_log(
ubman, f'{mkimage} -f auto -d {inf} {os.path.join(fsh.srcdir, vmlinux)}')
mkimage = config.build_dir + '/tools/mkimage'
utils.run_and_log_no_ubman(
log, f'{mkimage} -f auto -d {inf} {os.path.join(fsh.srcdir, vmlinux)}')
with open(os.path.join(fsh.srcdir, initrd), 'w', encoding='ascii') as fd:
print('initrd', file=fd)
@@ -195,15 +199,15 @@ def setup_extlinux_image(ubman, devnum, basename, vmlinux, initrd, dtbdir,
mkdir_cond(os.path.join(fsh.srcdir, dtbdir))
dtb_file = os.path.join(fsh.srcdir, f'{dtbdir}/sandbox.dtb')
utils.run_and_log(
ubman, f'dtc -o {dtb_file}', stdin=b'/dts-v1/; / {};')
utils.run_and_log_no_ubman(
log, f'dtc -o {dtb_file}', stdin=b'/dts-v1/; / {};')
fsh.mk_fs()
img = DiskHelper(ubman.config, devnum, basename, True)
img = DiskHelper(config, devnum, basename, True)
img.add_fs(fsh, DiskHelper.VFAT, bootable=True)
ext4 = FsHelper(ubman.config, 'ext4', 1, prefix=basename)
ext4 = FsHelper(config, 'ext4', 1, prefix=basename)
ext4.setup()
ext4.mk_fs()
@@ -211,11 +215,12 @@ def setup_extlinux_image(ubman, devnum, basename, vmlinux, initrd, dtbdir,
img.create()
fsh.cleanup()
def setup_fedora_image(ubman, devnum, basename):
def setup_fedora_image(config, log, devnum, basename):
"""Create a 20MB Fedora disk image with a single FAT partition
Args:
ubman (ConsoleBase): Console to use
config (ArbitraryAttributeContainer): Configuration
log (multiplexed_log.Logfile): Log to write to
devnum (int): Device number to use, e.g. 1
basename (str): Base name to use in the filename, e.g. 'mmc'
"""
@@ -235,14 +240,15 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB
fdtdir /%s/
initrd /%s''' % (vmlinux, dtbdir, initrd)
setup_extlinux_image(ubman, devnum, basename, vmlinux, initrd, dtbdir,
script)
setup_extlinux_image(config, log, devnum, basename, vmlinux,
initrd, dtbdir, script)
def setup_ubuntu_image(ubman, devnum, basename):
def setup_ubuntu_image(config, log, devnum, basename):
"""Create a 20MB Ubuntu disk image with a single FAT partition
Args:
ubman (ConsoleBase): Console to use
config (ArbitraryAttributeContainer): Configuration
log (multiplexed_log.Logfile): Log to write to
devnum (int): Device number to use, e.g. 1
basename (str): Base name to use in the filename, e.g. 'mmc'
"""
@@ -274,20 +280,26 @@ label l0r
linux /boot/%s
initrd /boot/%s
''' % (vmlinux, initrd, vmlinux, initrd)
setup_extlinux_image(ubman, devnum, basename, vmlinux, initrd, dtbdir,
setup_extlinux_image(config, log, devnum, basename, vmlinux, initrd, dtbdir,
script)
def setup_cros_image(ubman):
"""Create a 20MB disk image with ChromiumOS partitions"""
def setup_cros_image(config, log):
"""Create a 20MB disk image with ChromiumOS partitions
Args:
config (ArbitraryAttributeContainer): Configuration
log (multiplexed_log.Logfile): Log to write to
"""
Partition = collections.namedtuple('part', 'start,size,name')
parts = {}
disk_data = None
def pack_kernel(ubman, arch, kern, dummy):
def pack_kernel(config, log, arch, kern, dummy):
"""Pack a kernel containing some fake data
Args:
ubman (ConsoleBase): Console to use
config (ArbitraryAttributeContainer): Configuration
log (multiplexed_log.Logfile): Log to write to
arch (str): Architecture to use ('x86' or 'arm')
kern (str): Filename containing kernel
dummy (str): Dummy filename to use for config and bootloader
@@ -295,10 +307,9 @@ def setup_cros_image(ubman):
Return:
bytes: Packed-kernel data
"""
kern_part = os.path.join(ubman.config.result_dir,
f'kern-part-{arch}.bin')
utils.run_and_log(
ubman,
kern_part = os.path.join(config.result_dir, f'kern-part-{arch}.bin')
utils.run_and_log_no_ubman(
log,
f'futility vbutil_kernel --pack {kern_part} '
'--keyblock doc/chromium/files/devkeys/kernel.keyblock '
'--signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk '
@@ -324,9 +335,9 @@ def setup_cros_image(ubman):
disk_data = disk_data[:start] + data + disk_data[start + len(data):]
mmc_dev = 5
fname = os.path.join(ubman.config.source_dir, f'mmc{mmc_dev}.img')
utils.run_and_log(ubman, f'qemu-img create {fname} 20M')
utils.run_and_log(ubman, f'cgpt create {fname}')
fname = os.path.join(config.source_dir, f'mmc{mmc_dev}.img')
utils.run_and_log_no_ubman(log, f'qemu-img create {fname} 20M')
utils.run_and_log_no_ubman(log, f'cgpt create {fname}')
uuid_state = 'ebd0a0a2-b9e5-4433-87c0-68b6b72699c7'
uuid_kern = 'fe3a2a5d-4f32-41a7-b725-accc3285a309'
@@ -365,13 +376,13 @@ def setup_cros_image(ubman):
size = int(size_str[:-1]) * sect_1mb
else:
size = int(size_str)
utils.run_and_log(
ubman,
utils.run_and_log_no_ubman(
log,
f"cgpt add -i {part['num']} -b {ptr} -s {size} -t {part['type']} {fname}")
ptr += size
utils.run_and_log(ubman, f'cgpt boot -p {fname}')
out = utils.run_and_log(ubman, f'cgpt show -q {fname}')
utils.run_and_log_no_ubman(log, f'cgpt boot -p {fname}')
out = utils.run_and_log_no_ubman(log, f'cgpt show -q {fname}')
# We expect something like this:
# 8239 2048 1 Basic data
@@ -393,14 +404,14 @@ def setup_cros_image(ubman):
parts[int(num)] = Partition(int(start), int(size), name)
# Set up the kernel command-line
dummy = os.path.join(ubman.config.result_dir, 'dummy.txt')
dummy = os.path.join(config.result_dir, 'dummy.txt')
with open(dummy, 'wb') as outf:
outf.write(b'BOOT_IMAGE=/vmlinuz-5.15.0-121-generic root=/dev/nvme0n1p1 ro quiet splash vt.handoff=7')
# 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(ubman.config.result_dir, 'kern.bin')
kern = os.path.join(config.result_dir, 'kern.bin')
with open(kern, 'wb') as outf:
outf.write(b'kernel\n')
@@ -408,16 +419,21 @@ def setup_cros_image(ubman):
disk_data = inf.read()
# put x86 kernel in partition 2 and arm one in partition 4
set_part_data(2, pack_kernel(ubman, 'x86', kern, dummy))
set_part_data(4, pack_kernel(ubman, 'arm', kern, dummy))
set_part_data(2, pack_kernel(config, log, 'x86', kern, dummy))
set_part_data(4, pack_kernel(config, log, 'arm', kern, dummy))
with open(fname, 'wb') as outf:
outf.write(disk_data)
return fname
def setup_android_image(ubman):
"""Create a 20MB disk image with Android partitions"""
def setup_android_image(config, log):
"""Create a 20MB disk image with Android partitions
Args:
config (ArbitraryAttributeContainer): Configuration
log (multiplexed_log.Logfile): Log to write to
"""
Partition = collections.namedtuple('part', 'start,size,name')
parts = {}
disk_data = None
@@ -437,9 +453,9 @@ def setup_android_image(ubman):
disk_data = disk_data[:start] + data + disk_data[start + len(data):]
mmc_dev = 7
fname = os.path.join(ubman.config.source_dir, f'mmc{mmc_dev}.img')
utils.run_and_log(ubman, f'qemu-img create {fname} 20M')
utils.run_and_log(ubman, f'cgpt create {fname}')
fname = os.path.join(config.source_dir, f'mmc{mmc_dev}.img')
utils.run_and_log_no_ubman(log, f'qemu-img create {fname} 20M')
utils.run_and_log_no_ubman(log, f'cgpt create {fname}')
ptr = 40
@@ -461,13 +477,13 @@ def setup_android_image(ubman):
size = int(size_str[:-1]) * sect_1mb
else:
size = int(size_str)
utils.run_and_log(
ubman,
utils.run_and_log_no_ubman(
log,
f"cgpt add -i {part['num']} -b {ptr} -s {size} -l {part['label']} -t basicdata {fname}")
ptr += size
utils.run_and_log(ubman, f'cgpt boot -p {fname}')
out = utils.run_and_log(ubman, f'cgpt show -q {fname}')
utils.run_and_log_no_ubman(log, f'cgpt boot -p {fname}')
out = utils.run_and_log_no_ubman(log, f'cgpt show -q {fname}')
# Create a dict (indexed by partition number) containing the above info
for line in out.splitlines():
@@ -477,13 +493,15 @@ def setup_android_image(ubman):
with open(fname, 'rb') as inf:
disk_data = inf.read()
test_abootimg.AbootimgTestDiskImage(ubman, 'bootv4.img', test_abootimg.boot_img_hex)
boot_img = os.path.join(ubman.config.result_dir, 'bootv4.img')
test_abootimg.AbootimgTestDiskImage(config, log, 'bootv4.img',
test_abootimg.boot_img_hex)
boot_img = os.path.join(config.result_dir, 'bootv4.img')
with open(boot_img, 'rb') as inf:
set_part_data(2, inf.read())
test_abootimg.AbootimgTestDiskImage(ubman, 'vendor_boot.img', test_abootimg.vboot_img_hex)
vendor_boot_img = os.path.join(ubman.config.result_dir, 'vendor_boot.img')
test_abootimg.AbootimgTestDiskImage(config, log, 'vendor_boot.img',
test_abootimg.vboot_img_hex)
vendor_boot_img = os.path.join(config.result_dir, 'vendor_boot.img')
with open(vendor_boot_img, 'rb') as inf:
set_part_data(4, inf.read())
@@ -493,9 +511,9 @@ def setup_android_image(ubman):
print(f'wrote to {fname}')
mmc_dev = 8
fname = os.path.join(ubman.config.source_dir, f'mmc{mmc_dev}.img')
utils.run_and_log(ubman, f'qemu-img create {fname} 20M')
utils.run_and_log(ubman, f'cgpt create {fname}')
fname = os.path.join(config.source_dir, f'mmc{mmc_dev}.img')
utils.run_and_log_no_ubman(log, f'qemu-img create {fname} 20M')
utils.run_and_log_no_ubman(log, f'cgpt create {fname}')
ptr = 40
@@ -515,13 +533,13 @@ def setup_android_image(ubman):
size = int(size_str[:-1]) * sect_1mb
else:
size = int(size_str)
utils.run_and_log(
ubman,
utils.run_and_log_no_ubman(
log,
f"cgpt add -i {part['num']} -b {ptr} -s {size} -l {part['label']} -t basicdata {fname}")
ptr += size
utils.run_and_log(ubman, f'cgpt boot -p {fname}')
out = utils.run_and_log(ubman, f'cgpt show -q {fname}')
utils.run_and_log_no_ubman(log, f'cgpt boot -p {fname}')
out = utils.run_and_log_no_ubman(log, f'cgpt show -q {fname}')
# Create a dict (indexed by partition number) containing the above info
for line in out.splitlines():
@@ -531,8 +549,9 @@ def setup_android_image(ubman):
with open(fname, 'rb') as inf:
disk_data = inf.read()
test_abootimg.AbootimgTestDiskImage(ubman, 'boot.img', test_abootimg.img_hex)
boot_img = os.path.join(ubman.config.result_dir, 'boot.img')
test_abootimg.AbootimgTestDiskImage(config, log, 'boot.img',
test_abootimg.img_hex)
boot_img = os.path.join(config.result_dir, 'boot.img')
with open(boot_img, 'rb') as inf:
set_part_data(2, inf.read())
@@ -543,16 +562,21 @@ def setup_android_image(ubman):
return fname
def setup_cedit_file(ubman):
"""Set up a .dtb file for use with testing expo and configuration editor"""
infname = os.path.join(ubman.config.source_dir,
def setup_cedit_file(config, log):
"""Set up a .dtb file for use with testing expo and configuration editor
Args:
config (ArbitraryAttributeContainer): Configuration
log (multiplexed_log.Logfile): Log to write to
"""
infname = os.path.join(config.source_dir,
'test/boot/files/expo_layout.dts')
inhname = os.path.join(ubman.config.source_dir,
inhname = os.path.join(config.source_dir,
'test/boot/files/expo_ids.h')
expo_tool = os.path.join(ubman.config.source_dir, 'tools/expo.py')
expo_tool = os.path.join(config.source_dir, 'tools/expo.py')
outfname = 'cedit.dtb'
utils.run_and_log(
ubman, f'{expo_tool} -e {inhname} -l {infname} -o {outfname}')
utils.run_and_log_no_ubman(
log, f'{expo_tool} -e {inhname} -l {infname} -o {outfname}')
@pytest.mark.buildconfigspec('ut_dm')
def test_ut_dm_init(ubman):
@@ -590,16 +614,20 @@ def test_ut_dm_init(ubman):
fh.write(data)
def setup_efi_image(ubman):
"""Create a 20MB disk image with an EFI app on it"""
def setup_efi_image(config):
"""Create a 20MB disk image with an EFI app on it
Args:
config (ArbitraryAttributeContainer): Configuration
"""
devnum = 1
fsh = FsHelper(ubman.config, 'vfat', 18, 'flash')
fsh = FsHelper(config, 'vfat', 18, 'flash')
fsh.setup()
efi_dir = os.path.join(fsh.srcdir, 'EFI')
mkdir_cond(efi_dir)
bootdir = os.path.join(efi_dir, 'BOOT')
mkdir_cond(bootdir)
efi_src = os.path.join(ubman.config.build_dir,
efi_src = os.path.join(config.build_dir,
'lib/efi_loader/testapp.efi')
efi_dst = os.path.join(bootdir, 'BOOTSBOX.EFI')
with open(efi_src, 'rb') as inf:
@@ -608,14 +636,19 @@ def setup_efi_image(ubman):
fsh.mk_fs()
img = DiskHelper(ubman.config, devnum, 'flash', True)
img = DiskHelper(config, devnum, 'flash', True)
img.add_fs(fsh, DiskHelper.VFAT)
img.create()
fsh.cleanup()
def setup_localboot_image(cons):
"""Create a 20MB disk image with a single FAT partition"""
def setup_localboot_image(config, log):
"""Create a 20MB disk image with a single FAT partition
Args:
config (ArbitraryAttributeContainer): Configuration
log (multiplexed_log.Logfile): Log to write to
"""
mmc_dev = 9
script = '''DEFAULT local
@@ -626,27 +659,28 @@ LABEL local
'''
vmlinux = 'vmlinuz'
initrd = 'initrd.img'
setup_extlinux_image(cons, mmc_dev, 'mmc', vmlinux, initrd, None, script)
setup_extlinux_image(config, log, mmc_dev, 'mmc', vmlinux, initrd, None,
script)
@pytest.mark.buildconfigspec('cmd_bootflow')
@pytest.mark.buildconfigspec('sandbox')
def test_ut_dm_init_bootstd(ubman):
"""Initialise data for bootflow tests"""
setup_fedora_image(ubman, 1, 'mmc')
setup_bootmenu_image(ubman)
setup_cedit_file(ubman)
setup_cros_image(ubman)
setup_android_image(ubman)
setup_efi_image(ubman)
setup_ubuntu_image(ubman, 3, 'flash')
setup_localboot_image(ubman)
setup_vbe_image(ubman)
# Restart so that the new mmc1.img is picked up
ubman.restart_uboot()
def test_ut_dm_init_bootstd(u_boot_config, u_boot_log):
"""Initialise data for bootflow tests
Args:
u_boot_config (ArbitraryAttributeContainer): Configuration
u_boot_log (multiplexed_log.Logfile): Log to write to
"""
setup_fedora_image(u_boot_config, u_boot_log, 1, 'mmc')
setup_bootmenu_image(u_boot_config, u_boot_log)
setup_cedit_file(u_boot_config, u_boot_log)
setup_cros_image(u_boot_config, u_boot_log)
setup_android_image(u_boot_config, u_boot_log)
setup_efi_image(u_boot_config)
setup_ubuntu_image(u_boot_config, u_boot_log, 3, 'flash')
setup_localboot_image(u_boot_config, u_boot_log)
setup_vbe_image(u_boot_config, u_boot_log)
def test_ut(ubman, ut_subtest):
"""Execute a "ut" subtest.

View File

@@ -65,6 +65,36 @@ def dtc(dts, ubman, dtc_args, datadir, tmpdir, dtb):
utils.run_and_log(ubman, 'dtc %s %s%s -O dtb '
'-o %s%s' % (dtc_args, datadir, dts, tmpdir, dtb))
def create_rsa_pair(ubman, name, sha_algo, tmpdir):
"""Generate a new RSA key paid and certificate
Args:
ubman (ConsoleBase): U-Boot console
name (str): Name of the key (e.g. 'dev')
sha_algo (str): SHA algorithm to use, e.g. 'sha256'
tmpdir (str): Temporary directory to use for openssl
"""
public_exponent = 65537
if sha_algo == 'sha384':
rsa_keygen_bits = 3072
else:
rsa_keygen_bits = 2048
utils.run_and_log(
ubman,
f'openssl genpkey -algorithm RSA -out {tmpdir}{name}.key '
f'-pkeyopt rsa_keygen_bits:{rsa_keygen_bits} '
f'-pkeyopt rsa_keygen_pubexp:{public_exponent}')
# Create a certificate containing the public key
utils.run_and_log(
ubman,
f'openssl req -batch -new -x509 -key {tmpdir}{name}.key '
f'-out {tmpdir}{name}.crt')
def make_fit(its, ubman, mkimage, dtc_args, datadir, fit):
"""Make a new FIT from the .its source file.
@@ -265,28 +295,6 @@ def test_vboot_base(ubman, name, sha_algo, padding, sign_options, required,
handle.seek(offset)
handle.write(struct.pack(">I", value))
def create_rsa_pair(name):
"""Generate a new RSA key paid and certificate
Args:
name: Name of of the key (e.g. 'dev')
"""
public_exponent = 65537
if sha_algo == "sha384":
rsa_keygen_bits = 3072
else:
rsa_keygen_bits = 2048
utils.run_and_log(ubman, 'openssl genpkey -algorithm RSA -out %s%s.key '
'-pkeyopt rsa_keygen_bits:%d '
'-pkeyopt rsa_keygen_pubexp:%d' %
(tmpdir, name, rsa_keygen_bits, public_exponent))
# Create a certificate containing the public key
utils.run_and_log(ubman, 'openssl req -batch -new -x509 -key %s%s.key '
'-out %s%s.crt' % (tmpdir, name, tmpdir, name))
def test_with_algo(sha_algo, padding, sign_options):
"""Test verified boot with the given hash algorithm.
@@ -520,8 +528,8 @@ def test_vboot_base(ubman, name, sha_algo, padding, sign_options, required,
dtb = '%ssandbox-u-boot.dtb' % tmpdir
sig_node = '/configurations/conf-1/signature'
create_rsa_pair('dev')
create_rsa_pair('prod')
create_rsa_pair(ubman, 'dev', sha_algo, tmpdir)
create_rsa_pair(ubman, 'prod', sha_algo, tmpdir)
# Create a number kernel image with zeroes
with open('%stest-kernel.bin' % tmpdir, 'wb') as fd:
@@ -632,12 +640,22 @@ def test_fdt_add_pubkey(ubman, name, sha_algo, padding, sign_options, algo_arg):
datadir = ubman.config.source_dir + '/test/py/tests/vboot/'
fit = '%stest.fit' % tmpdir
mkimage = ubman.config.build_dir + '/tools/mkimage'
binman = ubman.config.source_dir + '/tools/binman/binman'
fit_check_sign = ubman.config.build_dir + '/tools/fit_check_sign'
fdt_add_pubkey = ubman.config.build_dir + '/tools/fdt_add_pubkey'
dtc_args = '-I dts -O dtb -i %s' % tmpdir
dtb = '%ssandbox-u-boot.dtb' % tmpdir
# keys created in test_vboot test
create_rsa_pair(ubman, 'dev', sha_algo, tmpdir)
create_rsa_pair(ubman, 'prod', sha_algo, tmpdir)
# Create a number kernel image with zeroes
with open(f'{tmpdir}test-kernel.bin', 'wb') as fd:
fd.write(500 * b'\0')
# Compile our device tree files for kernel and U-Boot. These are
# regenerated here since mkimage will modify them (by adding a
# public key) below.
dtc('sandbox-kernel.dts', ubman, dtc_args, datadir, tmpdir, dtb)
dtc('sandbox-u-boot.dts', ubman, dtc_args, datadir, tmpdir, dtb)
test_add_pubkey(sha_algo, padding, sign_options)

View File

@@ -157,31 +157,53 @@ def wait_until_file_open_fails(fn, ignore_errors):
return
raise Exception('File can still be opened')
def run_and_log(ubman, cmd, ignore_errors=False, stdin=None, env=None):
def run_and_log_no_ubman(log, cmd, ignore_errors=False, stdin=None, env=None):
"""Run a command and log its output.
This is useful when you don't want to use a ubman fixture
Args:
ubman: A console connection to U-Boot.
cmd: The command to run, as an array of argv[], or a string.
log (multiplexed_log.Logfile): log fixture
cmd (list of str or str): Command to run, as an array of argv[] or str.
If a string, note that it is split up so that quoted spaces
will not be preserved. E.g. "fred and" becomes ['"fred', 'and"']
ignore_errors: Indicate whether to ignore errors. If True, the function
will simply return if the command cannot be executed or exits with
an error code, otherwise an exception will be raised if such
problems occur.
stdin: Input string to pass to the command as stdin (or None)
env: Environment to use, or None to use the current one
ignore_errors (bool): Indicate whether to ignore errors. If True, the
function will simply return if the command cannot be executed or
exits with an error code, otherwise an exception will be raised if
such problems occur.
stdin (str): Input string to pass to the command as stdin (or None)
env (dict): Environment to use, or None to use the current one
Returns:
The output as a string.
"""
if isinstance(cmd, str):
cmd = cmd.split()
runner = ubman.log.get_runner(cmd[0], sys.stdout)
runner = log.get_runner(cmd[0], sys.stdout)
output = runner.run(cmd, ignore_errors=ignore_errors, stdin=stdin, env=env)
runner.close()
return output
def run_and_log(ubman, cmd, ignore_errors=False, stdin=None, env=None):
"""Run a command and log its output.
Args:
ubman (ConsoleBase): A console connection to U-Boot.
cmd (list of str or str): Command to run, as an array of argv[] or str.
If a string, note that it is split up so that quoted spaces
will not be preserved. E.g. "fred and" becomes ['"fred', 'and"']
ignore_errors (bool): Indicate whether to ignore errors. If True, the
function will simply return if the command cannot be executed or
exits with an error code, otherwise an exception will be raised if
such problems occur.
stdin (str): Input string to pass to the command as stdin (or None)
env (dict): Environment to use, or None to use the current one
Returns:
The output as a string.
"""
return run_and_log_no_ubman(ubman.log, cmd, ignore_errors, stdin, env)
def run_and_log_expect_exception(ubman, cmd, retcode, msg):
"""Run a command that is expected to fail.

View File

@@ -42,6 +42,9 @@ fi
failures=0
# Disable LTO as it messed up event_dump.py (fails to get some line numbers)
export NO_LTO=1
if [ -z "$tools_only" ]; then
# Run all tests that the standard sandbox build can support
echo "${prompt}"