diff options
author | Chris Johns <chrisj@rtems.org> | 2019-05-31 12:32:29 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2019-05-31 12:39:08 +1000 |
commit | ac0f986efb78075c314fffd0f6d062ebd1061dd8 (patch) | |
tree | 1f48f50794e95c5ea7062426b523f8e618d287f3 | |
parent | e5716fdf3fdf883b918a06fd149015a932411265 (diff) |
misc/boot-image: Add MacOS support.
-rw-r--r-- | misc/tools/boot.py | 127 |
1 files changed, 101 insertions, 26 deletions
diff --git a/misc/tools/boot.py b/misc/tools/boot.py index 3fad3c4..876113c 100644 --- a/misc/tools/boot.py +++ b/misc/tools/boot.py @@ -29,6 +29,7 @@ import copy import datetime import os import sys +import tempfile from rtemstoolkit import check from rtemstoolkit import error @@ -185,11 +186,9 @@ class image(object): # Create the blank image file. This is attached as a device, # partitioned, formatted and the files written to it. # - log.notice('Create image: %s' % (self.settings.output)) - img_size, img_units = self.si_size_units(self.settings.image_size) - self.command('dd if=/dev/zero of=%s bs=1%s count=%d' % (output, - img_units, - img_size)) + log.notice('Create image: %s size %s' % (self.settings.output, + self.settings.image_size)) + self.image_create(output, self.settings.image_size) # # Attach the image so it is a device. @@ -200,7 +199,8 @@ class image(object): # # Partition the image. # - log.notice('Partition device: %s as %s' % (device, self.settings.part_type)) + log.notice('Partition device: %s as %s' % (device, + self.settings.part_type)) self.partition(device, self.settings.part_type, self.settings.fs_format, @@ -258,6 +258,9 @@ class image(object): log.output('Copy : %s -> %s' % (asrc, adst)) path.copy(asrc, adst) + def image_create(self, path_, size): + self.host_image_create(path_, size, path.exists(path_)) + def image_attach(self, path_): device = self.host_image_attach(path_) self.detach_images += [device] @@ -300,8 +303,7 @@ class image(object): path.removeall(r) def get_exes(self): - return ['dd', - 'mkimage'] + return ['dd'] def check_exes(self): ok = True @@ -320,11 +322,13 @@ class image(object): if size[-1].isalpha(): suffix = size[-1] if suffix not in ['k', 'm', 'g']: - raise error.general('invalid SI units (k, m, g): %s: %s' % (suffix, - size)) - units = {'k': 1024, 'm': 1024 * 1024, 'g': 1024 * 1024 * 1024 }[suffix] + err = 'invalid SI unit (k, m, g): %s: %s' % (suffix, size) + raise error.general(err) + units = {'k': 1024, + 'm': 1024 * 1024, + 'g': 1024 * 1024 * 1024 }[suffix] size = size[:-1] - if not size.isdecimal(): + if not size.isdigit(): raise error.general('invalid size: %s' % (orig)) size = int(size) return size, suffix, size * units @@ -362,9 +366,37 @@ class image(object): log.output(['> ' + l for l in output.split(os.linesep)]) log.output('> exit: %d' % (exit_code)) if exit_code != 0: - raise error.general('executing failure: (exit:%d) %s' % (exit_code, cmd)) + err = 'executing failure: (exit:%d) %s' % (exit_code, cmd) + raise error.general(err) return output + def host_image_create(self, path_, size, exists): + img_size, img_units = self.si_size_units(size) + self.command('dd if=/dev/zero of=%s bs=1%s count=%d' % (path_, + img_units, + img_size)) + + def host_image_attach(self, path_): + raise error.general('no platform support: host_image_attach') + + def host_image_detach(self, device): + raise error.general('no platform support: host_image_detach') + + def host_partition(self, device, ptype, pformat, psize, palign): + raise error.general('no platform support: host_partition') + + def host_format_partition(self, device, pformat): + raise error.general('no platform support: host_format_partition') + + def host_device_partition(self, device, pindex): + raise error.general('no platform support: host_device_partition') + + def host_mount(self, pformat, device, path_): + raise error.general('no platform support: host_mount') + + def host_unmount(self, path_): + raise error.general('no platform support: host_unmount') + class freebsd_image(image): def __init__(self, settings): super(freebsd_image, self).__init__(settings) @@ -388,7 +420,8 @@ class freebsd_image(image): formats = { 'fat16': 'fat16', 'fat32': 'fat32' } if ptype not in types: - raise error.general('unknown type of partitioning: %s' % (ptype)) + err = 'unknown type of partitioning: %s' % (ptype) + raise error.general(err) if pformat not in formats: raise error.general('unknown format: %s' % (pformat)) self.command('sudo gpart create -s %s %s' % (types[ptype], device)) @@ -415,7 +448,9 @@ class freebsd_image(image): 'fat32': 'msdos' } if pformat not in formats: raise error.general('unknown format: %s' % (pformat)) - self.command('sudo mount -t %s %s %s' % (formats[pformat], device, path_)) + self.command('sudo mount -t %s %s %s' % (formats[pformat], + device, + path_)) def host_unmount(self, path_): self.command('sudo umount %s' % (path_)) @@ -448,27 +483,66 @@ class linux_image(image): class darwin_image(image): def __init__(self, settings): super(darwin_image, self).__init__(settings) + if not self.settings.output.endswith('.img'): + log.notice('Output file does not end with `.img`. ' + \ + 'Needed on MacOS due to a bug (Id: 51283993)') + raise error.general('output file does not end with `.img`') + + def get_exes(self): + exes = super(darwin_image, self).get_exes() + return exes + ['hdiutil', + 'diskutil', + 'fdisk'] def host_image_attach(self, path_): - pass + output = self.command('sudo hdiutil attach %s -nomount -nobrowse' % (path_)) + if len(output.split(os.linesep)) != 1 or not output.startswith('/dev/'): + raise error.general('invalid hdiutil attach outputl; see log') + return output.strip() def host_image_detach(self, device): - pass + self.command('sudo hdiutil detach %s' % (device)) def host_partition(self, device, ptype, pformat, psize, palign): - pass + types = { 'MBR': 'MBR' } + formats = { 'fat16': 'MS-DOS FAT16', + 'fat32': 'MS-DOS FAT32' } + if ptype not in types: + err = 'unknown type of partitioning: %s' % (ptype) + raise error.general(err) + if pformat not in formats: + raise error.general('unknown format: %s' % (pformat)) + # + # Align the parition by adding free space before. Sign. + # + cmd = "sudo diskutil partitionDisk %s 2 %s " % (device, types[ptype]) + cmd += "'Free Space' '%%noformat%%' %s " % (palign) + cmd += "'%s' RTEMS %s" % (formats[pformat], psize) + self.command(cmd) + # + # MacOS mounts the filesystem once the partitioning has finished, + # unmount it as we have no control over the mountpoint. + # + self.command('sudo diskutil unmountDisk %s' % (device)) + # + # This awkward exchange is needed to set the active bit. + # + with tempfile.NamedTemporaryFile() as tmp: + tmp.write(os.linesep.join(['f 1', 'w', 'p', 'q', ''])) + tmp.seek(0) + self.command('cat %s | sudo fdisk -y -e %s' % (tmp.name, device)) def host_format_partition(self, device, pformat): - pass + log.output(' * No format stage; done when partitioning') def host_device_partition(self, device, pindex): - pass + return '%ss%d' % (device, pindex) def host_mount(self, pformat, device, path_): - pass + self.command('sudo diskutil mount -mountPoint %s %s' % (path_, device)) def host_unmount(self, path_): - pass + self.command('sudo diskutil unmount %s' % (path_)) builders = { 'freebsd': freebsd_image, @@ -554,10 +628,10 @@ def run(args = sys.argv, command_path = None): notice = None builder = None try: - description = 'RTEMS U-Boot Image builder creates a U-Boot image for' - description += 'for booting.' + description = 'RTEMS Boot Image builder creates a boot image for' + description += 'for a range of boards.' - argsp = argparse.ArgumentParser(prog = 'rtems-uboot-image', + argsp = argparse.ArgumentParser(prog = 'rtems-boot-image', description = description) argsp.add_argument('-l', '--log', help = 'Log file (default: %(default)s.', @@ -639,7 +713,8 @@ def run(args = sys.argv, command_path = None): config.log() if host.name not in builders: - raise error.general('no builder; platform not supported: %s' % (host.name)) + err = 'no builder; platform not supported: %s' % (host.name) + raise error.general(err) builder = builders[host.name](config) builder.check_exes() |