summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2019-05-31 12:32:29 +1000
committerChris Johns <chrisj@rtems.org>2019-05-31 12:39:08 +1000
commitac0f986efb78075c314fffd0f6d062ebd1061dd8 (patch)
tree1f48f50794e95c5ea7062426b523f8e618d287f3
parente5716fdf3fdf883b918a06fd149015a932411265 (diff)
misc/boot-image: Add MacOS support.
-rw-r--r--misc/tools/boot.py127
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()