Make use of the mk_fs() function to avoid needing to use sudo to mount the loopback partition. This makes the script a little more friendly for those nervous about sudo in their tools.
Signed-off-by: Simon Glass <s...@chromium.org> --- MAINTAINERS | 1 + scripts/build-efi | 104 +++++----------------------------------- scripts/build_helper.py | 64 +++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 92 deletions(-) create mode 100644 scripts/build_helper.py diff --git a/MAINTAINERS b/MAINTAINERS index 939c46ef23a..aebccd9678f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1127,6 +1127,7 @@ W: https://docs.u-boot.org/en/latest/board/emulation/script.html F: configs/qemu_x86* F: doc/board/emulation/script.rst F: scripts/build-qemu.sh +F: scripts/build_helper.py ENVIRONMENT M: Joe Hershberger <joe.hershber...@ni.com> diff --git a/scripts/build-efi b/scripts/build-efi index e71028baa6d..a2b5540ad29 100755 --- a/scripts/build-efi +++ b/scripts/build-efi @@ -17,21 +17,10 @@ Use ~/.build-efi to configure the various paths used by this script. from argparse import ArgumentParser import configparser -import glob import os -import re import shutil -import sys -import time - - -OUR_PATH = os.path.dirname(os.path.realpath(__file__)) -OUR1_PATH = os.path.dirname(OUR_PATH) - -# Bring in the patman and dtoc libraries (but don't override the first path -# in PYTHONPATH) -sys.path.insert(2, os.path.join(OUR1_PATH, 'tools')) +from build_helper import Helper # pylint: disable=C0413 from u_boot_pylib import command @@ -108,11 +97,10 @@ efi_dir = . class BuildEfi: """Class to collect together the various bits of state while running""" def __init__(self, settings, args): + self.helper = Helper() self.settings = settings self.img = self.get_setting('image_file', 'try.img') self.build_dir = self.get_setting("build_dir", '/tmp') - self.mnt = self.get_setting("mount_point", '/mnt/test-efi') - self.tmp = None self.args = args def get_setting(self, name, fallback=None): @@ -174,83 +162,18 @@ class BuildEfi: cmd += extra command.run(*cmd) - def setup_files(self, build, build_type): + def setup_files(self, build, build_type, dst): """Set up files in the staging area Args: build (str): Name of build being packaged, e.g. 'efi-x86_app32' build_type (str): Build type ('app' or 'payload') + dst (str): Destination directory """ print(f'Packaging {build}') - if not os.path.exists(self.tmp): - os.mkdir(self.tmp) fname = f'u-boot-{build_type}.efi' - tools.write_file(f'{self.tmp}/startup.nsh', f'fs0:{fname}', - binary=False) - shutil.copy(f'{self.build_dir}/{build}/{fname}', self.tmp) - - def copy_files(self): - """Copy files into the filesystem""" - command.run('sudo', 'cp', *glob.glob(f'{self.tmp}/*'), self.mnt) - if self.args.kernel: - bzimage = self.get_setting('bzimage_file', 'bzImage') - command.run('sudo', 'cp', bzimage, f'{self.mnt}/vmlinuz') - - def setup_raw(self): - """Create a filesystem on a raw device and copy in the files""" - command.output('mkfs.vfat', self.img) - command.run('sudo', 'mkdir', '-p', self.mnt) - command.run('sudo', 'mount', '-o', 'loop', self.img, self.mnt) - self.copy_files() - command.run('sudo', 'umount', self.mnt) - - def setup_part(self): - """Set up a partition table - - Create a partition table and put the filesystem in the first partition - then copy in the files - """ - - # Create a gpt partition table with one partition - command.run('parted', self.img, 'mklabel', 'gpt', capture_stderr=True) - - # This doesn't work correctly. It creates: - # Number Start End Size File system Name Flags - # 1 1049kB 24.1MB 23.1MB boot msftdata - # Odd if the same is entered interactively it does set the FS type - command.run('parted', '-s', '-a', 'optimal', '--', - self.img, 'mkpart', 'boot', 'fat32', '1MiB', '23MiB') - - # Map this partition to a loop device. Output is something like: - # add map loop48p1 (252:3): 0 45056 linear 7:48 2048 - out = command.output('sudo', 'kpartx', '-av', self.img) - m = re.search(r'(loop.*p.)', out) - if not m: - raise ValueError(f'Invalid output from kpartx: {out}') - - boot_dev = m.group(1) - dev = f'/dev/mapper/{boot_dev}' - - command.output('mkfs.vfat', dev) - - command.run('sudo', 'mount', '-o', 'loop', dev, self.mnt) - - try: - self.copy_files() - finally: - # Sync here since this makes kpartx more likely to work the first time - command.run('sync') - command.run('sudo', 'umount', self.mnt) - - # For some reason this needs a sleep or it sometimes fails, if it was - # run recently (in the last few seconds) - try: - cmd = 'sudo', 'kpartx', '-d', self.img - command.output(*cmd) - except command.CommandExc: - time.sleep(0.5) - cmd = 'sudo', 'kpartx', '-d', self.img - command.output(*cmd) + tools.write_file(f'{dst}/startup.nsh', f'fs0:{fname}', binary=False) + shutil.copy(f'{self.build_dir}/{build}/{fname}', dst) def do_build(self, build): """Build U-Boot for the selected board""" @@ -267,7 +190,6 @@ class BuildEfi: bitness = 32 if args.word else 64 arch = 'arm' if args.arm else 'x86' build_type = 'payload' if args.payload else 'app' - self.tmp = f'{self.build_dir}/efi{bitness}{build_type}' build = f'efi-{arch}_{build_type}{bitness}' if not args.no_build: @@ -276,14 +198,12 @@ class BuildEfi: if args.old and bitness == 32: build = f'efi-{arch}_{build_type}' - self.setup_files(build, build_type) - - command.output('qemu-img', 'create', self.img, '24M') - - if args.partition: - self.setup_part() - else: - self.setup_raw() + with self.helper.make_disk(self.img, fs_type='vfat', + use_part=args.partition) as dirpath: + self.setup_files(build, build_type, dirpath) + if self.args.kernel: + bzimage = self.helper.get_setting('bzimage_file', 'bzImage') + command.run('cp', bzimage, f'{dirpath}/vmlinuz') if args.run: self.run_qemu(bitness, args.serial) diff --git a/scripts/build_helper.py b/scripts/build_helper.py new file mode 100644 index 00000000000..15177a48e80 --- /dev/null +++ b/scripts/build_helper.py @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +"""Common script for build- scripts + +""" + +import contextlib +import os +import shutil +import subprocess +import sys +import tempfile + +OUR_PATH = os.path.dirname(os.path.realpath(__file__)) +OUR1_PATH = os.path.dirname(OUR_PATH) + +# Bring in the patman and test libraries (but don't override the first path in +# PYTHONPATH) +sys.path.insert(2, os.path.join(OUR1_PATH, 'tools')) +sys.path.insert(2, os.path.join(OUR1_PATH, 'test/py/tests')) + +from u_boot_pylib import command +from u_boot_pylib import tools +import fs_helper + + +class Helper: + def __init__(self): + self.settings = None + + @contextlib.contextmanager + def make_disk(self, fname, size_mb=20, fs_type='ext4', use_part=False): + """Create a raw disk image with files on it + + Args: + fname (str): Filename to write the images to + fs_type (str): Filesystem type to create (ext4 or vfat) + size_mb (int): Size in MiB + use_part (bool): True to create a partition table, False to use a + raw disk image + + Yields: + str: Directory to write the files into + """ + with tempfile.NamedTemporaryFile() as tmp: + with tempfile.TemporaryDirectory(prefix='build_helper.') as dirname: + try: + yield dirname + fs_helper.mk_fs(None, fs_type, size_mb << 20, None, dirname, + fs_img=tmp.name, quiet=True) + finally: + pass + + if use_part: + with open(fname, 'wb') as img: + img.truncate(size_mb << 20) + img.seek(1 << 20, 0) + img.write(tools.read_file(tmp.name)) + subprocess.run( + ['sfdisk', fname], text=True, check=True, + capture_output=True, + input=f'type=c, size={size_mb-1}M, start=1M,bootable') + else: + shutil.copy2(tmp.name, fname) -- 2.43.0