diff options
author | Chris Johns <chrisj@rtems.org> | 2019-06-06 20:57:15 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2019-06-06 20:57:15 +1000 |
commit | 2fe9313b447965bc38efaefcc8fdea90a273d5d8 (patch) | |
tree | 3d57408a89748f4c225e1a2e30ce36f3cf168421 | |
parent | 7f0748495ea57fcd80791c45ded1dd9a7b1b941f (diff) |
boot-image: Add support for 1st and 2nd loaders.
-rw-r--r-- | misc/tools/boot.py | 582 | ||||
-rw-r--r-- | misc/tools/rtems-boot.ini | 64 |
2 files changed, 432 insertions, 214 deletions
diff --git a/misc/tools/boot.py b/misc/tools/boot.py index 206dc8d..8cbae4b 100644 --- a/misc/tools/boot.py +++ b/misc/tools/boot.py @@ -32,133 +32,261 @@ import sys import tempfile from rtemstoolkit import check +from rtemstoolkit import configuration from rtemstoolkit import error from rtemstoolkit import execute from rtemstoolkit import host from rtemstoolkit import log +from rtemstoolkit import macros from rtemstoolkit import path from rtemstoolkit import version -class settings(object): - def __init__(self, bootloader = 'none', base = None): +def _check_exes(exes): + ok = True + first = True + for exe in exes: + log.output('check exe: %s' % (exe)) + if not check.check_exe(None, exe): + if first: + log.notice('Host executable(s) not found:') + first = False + log.notice(' %s' % (exe)) + ok = False + return ok + +def _command(cmd, cwd): + e = execute.capture_execution() + cwd = path.abspath(cwd) + log.output('>> cwd: %s' % (cwd)) + log.output('> %s' % (cmd)) + exit_code, proc, output = e.shell(cmd, cwd = path.host(cwd)) + log.output(['> ' + l for l in output.split(os.linesep)]) + log.output('> exit: %d' % (exit_code)) + if exit_code != 0: + err = 'executing failure: (exit:%d) %s' % (exit_code, cmd) + raise error.general(err) + return output + +class config(object): + + mandatory_configs = [ + 'image_size', + 'part_type', + 'part_label', + 'fs_format', + 'fs_size', + 'fs_alignment', + 'tool_prefix', + 'bootloaders' + ] + + def __init__(self, command_path, bootloader): + # + # Check if there is a defaults.mc file under the command path. If so + # this is the tester being run from within the git repo. If not found + # assume the tools have been installed and the defaults is in the + # install prefix. + # + boot_ini = 'tools/rtems-boot.ini' + if path.exists(path.join(command_path, boot_ini)): + rtdir = command_path + else: + rtdir = '%{_prefix}/share/rtems' + boot_ini = '%s/%s' % (rtdir, boot_ini) self.build = 'build' - self.bootloader = bootloader - self.base = base - self.image_size = '64m' - self.part_type = 'MBR' - self.fs_format = 'fat16' - self.fs_size = '63m' - self.fs_alignment = '1m' - self.first_stage = None - self.second_stage = None - self.output = None - self.kernel = None - self.net_server_ip = None - self.net_ip = None - self.files = [] - self.config = None + self.macros = macros.macros(rtdir = rtdir, show_minimal = True) + self.config = configuration.configuration() + self.load_config(bootloader, boot_ini) self.clean = True - def config_find(self, key, raw = False): - if key not in self.config: - raise error.general('config item not found: %s' % (key)) - item = self.config[key] - if not raw: - if item == 'y': - item = True - elif item == 'n': - item = False - elif item[0] == '"' and item[-1] == '"': - item = item[1:-1] - return item - - def bootloader_file(self, name): - return path.join(self.base, name) + def __getitem__(self, key): + if self.macros.has_key(key) and self.macros[key] != 'None': + return self.macros.expand('%%{%s}' % (key)) + return None + + def __setitem__(self, key, value): + if value is None: + value = 'None' + self.macros[key] = value + + def get_mandatory_configs(self): + return self.mandatory_configs + + def check_mandatory_configs(self): + for c in self.get_mandatory_configs(): + if not self.macros.has_key(c): + raise error.general('boot config missing: %s' % (c)) + + def load_config(self, bootloader, config): + self.config.load(config) + # + # Check the config file has the basic data and structure. + # + bootloaders = self.config.comma_list('default', 'bootloaders') + for bl in bootloaders: + if not self.config.has_section(bl): + raise error.general('boot config: missing bootloader section: %s' % (bl)) + for b in self.config.comma_list(bl, 'boards'): + if not self.config.has_section(b): + raise error.general('boot config: missing board section: %s' % (b)) + # + # Is the bootloader valid? + # + if bootloader not in bootloaders: + raise error.general('boot config: unknown bootloader: %s' % (bootloader)) + self.macros['bootloader'] = bootloader + self.macros['version_str'] = version.string() + self.macros['version'] = str(version.version()) + self.macros['revision'] = str(version.revision()) + if version.released(): + self.macros['released'] = '1' + # + # Map the config to macros. The [default] section is global. The + # remaining sections are added as macro maps so the specalised + # bootloaders can enable reading from a macro map to provide specific + # values for a specific config such as a board. + # + for s in self.config.get_sections(): + if s != 'default': + self.macros.set_write_map(s, add = True) + for i in self.config.get_items(s): + self.macros[i[0]] = i[1] + self.macros.unset_write_map() + self.macros.set_read_map('global') + self.macros.set_read_map(bootloader) + + def section_macro_map(self, section, nesting_level = 0): + nesting_level += 1 + if nesting_level >= 100: + err = 'boot config: too many map levels (looping?): %s' % (section) + raise error.general(err) + if section not in self.macros.maps(): + raise error.general('boot config: maps section not found: %s' % (section)) + self.macros.set_read_map(section) + for s in self.config.comma_list(section, 'uses', err = False): + self.section_macro_map(s, nesting_level) + + def boards(self): + return self.config.comma_list(self['bootloader'], 'boards') def log(self): - log.output('Settings') - log.output(' Image: {0}'.format(self.output)) - log.output(' Bootloader: {0}'.format(self.bootloader)) - log.output(' Base: {0}'.format(self.base)) - log.output(' Image Size: {0}'.format(self.image_size)) - log.output(' Part Type: {0}'.format(self.part_type)) - log.output(' FS Format: {0}'.format(self.fs_format)) - log.output(' FS Size: {0}'.format(self.fs_size)) - log.output(' FS Align: {0}'.format(self.fs_alignment)) - log.output(' First stage: {0}'.format(self.first_stage)) - log.output(' Second stage: {0}'.format(self.second_stage)) - log.output(' Kernel: {0}'.format(self.kernel)) - log.output(' Net Server IP: {0}'.format(self.net_server_ip)) - log.output(' Net IP: {0}'.format(self.net_ip)) - log.output(' Files: {0}'.format(len(self.files))) - for f in self.files: - log.output(' : {0}'.format(f)) - if self.config is not None: - log.output(' Config: {0}'.format(len(self.config))) - for c in self.config: - log.output(' : {0} = {1}'.format(c, self.config[c])) - - def install_configuration(self, image, dst): - pass + log.output('Configuration:') + log.output(' Bootloader: {0}'.format(self.macros['bootloader'])) + log.output(' Image: {0}'.format(self.macros['output'])) + log.output(' Image Size: {0}'.format(self.macros['image_size'])) + log.output(' Part Type: {0}'.format(self.macros['part_type'])) + log.output(' FS Format: {0}'.format(self.macros['fs_format'])) + log.output(' FS Size: {0}'.format(self.macros['fs_size'])) + log.output(' FS Align: {0}'.format(self.macros['fs_alignment'])) + log.output(' Kernel: {0}'.format(self.macros['kernel'])) + log.output(' Net Server IP: {0}'.format(self.macros['net_server_ip'])) + log.output(' Net IP: {0}'.format(self.macros['net_ip'])) + log.output(' Files: {0}'.format(len(self.files()))) + log.output('Macros:') + macro_str = str(self.macros).split(os.linesep) + log.output(os.linesep.join([' ' + l for l in macro_str])) + + def get_exes(self): + return [] -class uboot_settings(settings): - - boards = { - 'arm-ti-am335x-am335x_evm' : { - 'SPL' : 'MLO', - 'IMG' : 'u-boot.img', - 'RTEMS-LOADADDR' : '0x82000000' - }, - 'arm-xilinx-zynq-zynq-common' : { - 'SPL' : 'spl/boot.bin', - 'IMG' : 'u-boot.img', - 'RTEMS-LOADADDR' : '0x02000000' - }, - } - - templates = { - 'rtems-kernel': [ - 'loadaddr=@RTEMS-LOADADDR@', - 'bootfile=@KERNE@' - ] - } - - def __init__(self, uboot): - super(uboot_settings, self).__init__('u-boot', uboot) - self._config_load(self.bootloader_file('.config')) - if self.board_name() not in self.boards: - raise error.general('board not found: %s' %(self.board_name())) - log.output('Board: %s' % (self.board_name())) - board = self.boards[self.board_name()] - self.first_stage = self.bootloader_file(board['SPL']) - self.second_stage = self.bootloader_file(board['IMG']) - - def _config_load(self, config): - if not path.exists(config): - raise error.general('could not find u-boot\'s config: %s' %(config)) - with open(config, 'r') as f: - items = f.readlines() - self.config_path = config - items = [l[:l.find('#')] for l in items] - items = [l for l in items if len(l) > 0 or len(l) > 0 and l[0] != os.linesep] - self.config = {} - for c in items: - cs = c.split('=') - self.config[cs[0].strip()] = cs[1].strip() - - def board_name(self): - return '%s-%s-%s-%s' % (self.config_find('CONFIG_SYS_ARCH'), - self.config_find('CONFIG_SYS_VENDOR'), - self.config_find('CONFIG_SYS_BOARD'), - self.config_find('CONFIG_SYS_CONFIG_NAME')) - - def install_configuration(self, image, dst): + def check_exes(self): + return _check_exes(self.get_exes()) + + def files(self): + return [f.strip() for f in self.comma_split(self['files']) if len(f) > 0] + + def install_configuration(self, image, mountpoint): pass + def kernel_convert(self, kernel): + return kernel + + def kernel_image(self): + return self['kernel_image'].replace('@KERNEL@', path.basename(self['kernel'])) + + def filter_text(self, lines): + out = [] + for line in lines: + if '@KERNEL@' in line: + line = line.replace('@KERNEL@', path.basename(self['kernel'])) + if '@KERNEL_IMAGE@' in line: + line = line.replace('@KERNEL_IMAGE@', self.kernel_image()) + out += [line] + return out + + def comma_split(self, value): + return [s.strip() for s in value.split(',')] + +class uboot_config(config): + + def __init__(self, command_path, paths, board): + self.uboot = { 'paths': paths, 'board': board } + super(uboot_config, self).__init__(command_path, 'u-boot') + if self.board() not in self.boards(): + raise error.general('board not found: %s' %(self.board())) + log.output('Board: %s' % (self.board())) + self.section_macro_map(self.board()) + self.macros.set_read_map(self['bootloader'] + '-templates') + self.macros.lock_read_map() + log.output(str(self.macros)) + + def load_config(self, bootloader, config): + super(uboot_config, self).load_config(bootloader, config) + paths_count = len(self.uboot['paths']) + if paths_count == 1: + self.macros['ubootdir'] = path.abspath(self.uboot['paths'][0]) + if not path.exists(self['first_stage']): + err = 'u-boot: first stage loader not found: %s' % (self['first_stage']) + raise error.general(err) + if not path.exists(self['second_stage']): + err = 'u-boot: second stage loader not found: %s' % \ + (self['second_stage']) + raise error.general(err) + elif paths_count == 2: + self.macros['first_stage'] = self.uboot['paths'][0] + self.macros['second_stage'] = self.uboot['paths'][1] + self.macros['mkimage'] = 'mkimage' + else: + raise error.general('u-boot: invalid number of paths') + + def get_mandatory_configs(self): + cfgs = super(uboot_config, self).get_mandatory_configs() + return cfgs + ['objcopy', + 'arch', + 'vendor', + 'board', + 'config_name', + 'first_stage', + 'second_stage', + 'kernel_converter'] + + def board(self): + return self.uboot['board'] + + def get_exes(self): + exes = super(uboot_config, self).get_exes() + if self['executables'] is not None: + exes += self.comma_split(self['executables']) + return exes + + def install_configuration(self, image, mountpoint): + if self.macros.has_key('kernel'): + image.install_text(self.filter_text(self.comma_split(self['exe'])), + path.join(mountpoint, self['boot_config'])) + + def kernel_convert(self, kernel): + cmds = self.comma_split(self['kernel_converter']) + for c in range(0, len(cmds)): + if '@KERNEL@' in cmds[c]: + cmds[c] = cmds[c].replace('@KERNEL@', kernel) + for cmd in cmds: + _command(cmd, self['build']) + return self['kernel_image'].replace('@KERNEL@', kernel) + class image(object): - def __init__(self, settings): - self.settings = settings + def __init__(self, conf): + self.conf = conf self.detach_images = [] self.unmount_paths = [] self.remove_paths = [] @@ -171,8 +299,8 @@ class image(object): # # Ge the absolute paths to fixed locations. # - output = path.abspath(self.settings.output) - build = path.abspath(self.settings.build) + output = path.abspath(self.conf['output']) + build = path.abspath(self.conf['build']) mountpoint = path.join(build, 'mnt') # @@ -186,62 +314,63 @@ 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 size %s' % (self.settings.output, - self.settings.image_size)) - self.image_create(output, self.settings.image_size) + log.notice('Create image: %s size %s' % (self.conf['output'], + self.conf['image_size'])) + self.image_create(output, self.conf['image_size']) # # Attach the image so it is a device. # - log.notice('Attach image to device: %s' % (self.settings.output)) + log.notice('Attach image to device: %s' % (self.conf['output'])) device = self.image_attach(output) # # Partition the image. The device may change. # log.notice('Partition device: %s as %s' % (device, - self.settings.part_type)) + self.conf['part_type'])) device = self.partition(output, device, - self.settings.part_type, - self.settings.fs_format, - self.settings.fs_size, - self.settings.fs_alignment) - + self.conf['part_type'], + self.conf['part_label'], + self.conf['fs_format'], + self.conf['fs_size'], + self.conf['fs_alignment']) part = self.device_partition(device, 1) # # Format the first partition. # - log.notice('Format: %s as %s' % (part, self.settings.fs_format)) - self.format_partition(part, self.settings.fs_format) + log.notice('Format: %s as %s' % (part, self.conf['fs_format'])) + self.format_partition(part, self.conf['fs_format']) # # Mount the file system. # log.notice('Mount: %s' % (part)) - self.mount(self.settings.fs_format, part, mountpoint) + self.mount(self.conf['fs_format'], part, mountpoint) # # Install the first stage and second stage boot loaders. # - self.install(self.settings.first_stage, mountpoint) - self.install(self.settings.second_stage, mountpoint) + self.install(self.conf['first_stage'], mountpoint) + self.install(self.conf['second_stage'], mountpoint) # # Install a kernel if present # - if self.settings.kernel is not None: - self.install(self.settings.kernel, mountpoint) + if self.conf['kernel'] is not None: + kernel_image = self.kernel_image(self.conf['kernel']) + self.install(kernel_image, mountpoint) # # Install the bootloader configuration. # - self.settings.install_configuration(self, mountpoint) + self.conf.install_configuration(self, mountpoint) # # Install any user files if present. # - for f in self.settings.files: + for f in self.conf.files(): self.install(f, mountpoint) # @@ -259,6 +388,15 @@ class image(object): log.output('Copy : %s -> %s' % (asrc, adst)) path.copy(asrc, adst) + def install_text(self, text, dst): + dst_base = path.basename(dst) + log.notice('Install: %s' % (dst_base)) + adst = path.abspath(dst) + log.output('Copy : text[%d] -> %s' % (len(text), adst)) + log.output([' ] ' + l for l in text]) + with open(adst, "w") as o: + o.write(os.linesep.join(text)) + def image_create(self, path_, size): self.host_image_create(path_, size, path.exists(path_)) @@ -272,8 +410,8 @@ class image(object): self.detach_images.remove(device) self.host_image_detach(device) - def partition(self, image_, device, ptype, pformat, psize, palign): - return self.host_partition(image_, device, ptype, pformat, psize, palign) + def partition(self, image_, device, ptype, plabel, pformat, psize, palign): + return self.host_partition(image_, device, ptype, plabel, pformat, psize, palign) def format_partition(self, device, pformat): self.host_format_partition(device, pformat) @@ -292,32 +430,32 @@ class image(object): self.unmount_paths.remove(path_) def cleanup(self): - log.notice('Cleanup') + log.notice('Cleaning up') for m in self.unmount_paths: log.output('unmount: %s' % (m)) self.unmount(m) for i in self.detach_images: log.output('detach: %s' % (i)) self.image_detach(i) - for r in self.remove_paths: - log.output('remove: %s' % (r)) - path.removeall(r) + if self.conf.clean: + for r in self.remove_paths: + log.output('remove: %s' % (r)) + path.removeall(r) + + def kernel_image(self, kernel): + dst = path.join(path.abspath(self.conf['build']), path.basename(kernel)) + log.output('Copy: %s -> %s' % (kernel, dst)) + path.copy(kernel, dst) + return self.conf.kernel_convert(dst) def get_exes(self): return ['dd'] def check_exes(self): - ok = True - for exe in self.get_exes(): - log.output('check exe: %s' % (exe)) - if not check.check_exe(None, exe): - log.notice('host executable not found: %s' % (exe)) - ok = False - if not ok: - raise error.general('command(s) not found; please fix.') + return _check_exes(self.get_exes()) def si_units(self, units): - siunits = {'k': 1024, + siunits = { 'k': 1024, 'm': 1024 * 1024, 'g': 1024 * 1024 * 1024 } if units not in siunits: @@ -333,9 +471,9 @@ class image(object): if suffix not in ['k', 'm', 'g']: 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] + units = { 'k': 1024, + 'm': 1024 * 1024, + 'g': 1024 * 1024 * 1024 }[suffix] size = size[:-1] if not size.isdigit(): raise error.general('invalid size: %s' % (orig)) @@ -363,21 +501,11 @@ class image(object): raise error.general('build path is not readable: %s' % (where)) if not path.iswritable(where): raise error.general('build path is not writeable: %s' % (where)) - if cleanup and self.settings.clean: + if cleanup and self.conf.clean: self.remove_paths += [where] def command(self, cmd): - e = execute.capture_execution() - build = path.abspath(self.settings.build) - log.output('>> cwd: %s' % (build)) - log.output('> %s' % (cmd)) - exit_code, proc, output = e.shell(cmd, cwd = path.host(build)) - log.output(['> ' + l for l in output.split(os.linesep)]) - log.output('> exit: %d' % (exit_code)) - if exit_code != 0: - err = 'executing failure: (exit:%d) %s' % (exit_code, cmd) - raise error.general(err) - return output + return _command(cmd, self.conf['build']) def host_image_create(self, path_, size, exists): img_size, img_units = self.si_size_units(size) @@ -391,7 +519,7 @@ class image(object): def host_image_detach(self, device): raise error.general('no platform support: host_image_detach') - def host_partition(self, image_, device, ptype, pformat, psize, palign): + def host_partition(self, image_, device, ptype, plabel, pformat, psize, palign): raise error.general('no platform support: host_partition') def host_format_partition(self, device, pformat): @@ -407,8 +535,8 @@ class image(object): raise error.general('no platform support: host_unmount') class freebsd_image(image): - def __init__(self, settings): - super(freebsd_image, self).__init__(settings) + def __init__(self, conf): + super(freebsd_image, self).__init__(conf) def get_exes(self): exes = super(freebsd_image, self).get_exes() @@ -424,7 +552,7 @@ class freebsd_image(image): def host_image_detach(self, device): self.command('sudo mdconfig -d -u %s' % (device)) - def host_partition(self, image_, device, ptype, pformat, psize, palign): + def host_partition(self, image_, device, ptype, plabel, pformat, psize, palign): types = { 'MBR': 'MBR' } formats = { 'fat16': 'fat16', 'fat32': 'fat32' } @@ -466,8 +594,8 @@ class freebsd_image(image): self.command('sudo umount %s' % (path_)) class linux_image(image): - def __init__(self, settings): - super(linux_image, self).__init__(settings) + def __init__(self, conf): + super(linux_image, self).__init__(conf) def get_exes(self): exes = super(linux_image, self).get_exes() @@ -552,9 +680,9 @@ class linux_image(image): self.command('sudo umount %s' % (path_)) class darwin_image(image): - def __init__(self, settings): - super(darwin_image, self).__init__(settings) - if not self.settings.output.endswith('.img'): + def __init__(self, conf): + super(darwin_image, self).__init__(conf) + if not self.conf['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`') @@ -574,7 +702,7 @@ class darwin_image(image): def host_image_detach(self, device): self.command('sudo hdiutil detach %s' % (device)) - def host_partition(self, image_, device, ptype, pformat, psize, palign): + def host_partition(self, image_, device, ptype, plabel, pformat, psize, palign): types = { 'MBR': 'MBR' } formats = { 'fat16': 'MS-DOS FAT16', 'fat32': 'MS-DOS FAT32' } @@ -588,7 +716,7 @@ class darwin_image(image): # cmd = "sudo diskutil partitionDisk %s 2 %s " % (device, types[ptype]) cmd += "'Free Space' '%%noformat%%' %s " % (palign) - cmd += "'%s' RTEMS %s" % (formats[pformat], psize) + cmd += "'%s' %s %s" % (formats[pformat], plabel, psize) self.command(cmd) # # MacOS mounts the filesystem once the partitioning has finished, @@ -631,8 +759,7 @@ def load_log(logfile): log.default = log.log(streams = [logfile]) def log_default(): - return 'rtems-log-uboot-image-%s.txt' % \ - (datetime.datetime.now().strftime('%Y%m%d-%H%M%S')) + return 'rtems-log-boot-image.txt' class valid_dir(argparse.Action): def __call__(self, parser, namespace, values, option_string = None): @@ -663,6 +790,24 @@ class valid_file(argparse.Action): value = current + [value] setattr(namespace, self.dest, value) +class valid_paths(argparse.Action): + def __call__(self, parser, namespace, value, option_string = None): + current = getattr(namespace, self.dest) + if current is None: + current = [] + if isinstance(value, list): + values = value + else: + values = [values] + for value in values: + if not path.isfile(value) and not path.isdir(value): + err = 'is not a valid file or directory: %s' % (value) + raise argparse.ArgumentError(self, err) + if not path.isreadable(value): + raise argparse.ArgumentError(self, 'is not readable: %s' % (value)) + current += [value] + setattr(namespace, self.dest, current) + class valid_format(argparse.Action): def __call__(self, parser, namespace, value, option_string = None): current = getattr(namespace, self.dest) @@ -705,62 +850,66 @@ def run(args = sys.argv, command_path = None): notice = None builder = None try: - description = 'RTEMS Boot Image builder creates a boot image for' - description += 'for a range of boards.' + description = 'Provide one path to a u-boot build or provide two ' + description += 'paths to the built the first and second stage loaders, ' + description += 'for example a first stage loader is \'MLO\' and a second ' + description += '\'u-boot.img\'.' argsp = argparse.ArgumentParser(prog = 'rtems-boot-image', description = description) argsp.add_argument('-l', '--log', - help = 'Log file (default: %(default)s.', + help = 'log file (default: %(default)s).', type = str, default = log_default()) argsp.add_argument('-v', '--trace', - help = 'Enable trace logging for debugging.', + help = 'enable trace logging for debugging.', action = 'store_true') argsp.add_argument('-s', '--image-size', - help = 'Image size in mega-bytes (default: %(default)s).', + help = 'image size in mega-bytes (default: %(default)s).', type = str, action = valid_si, default = '64m') argsp.add_argument('-F', '--fs-format', - help = 'Root file system format (default: %(default)s).', + help = 'root file system format (default: %(default)s).', type = str, action = valid_format, default = 'fat16') argsp.add_argument('-S', '--fs-size', - help = 'Root file system size in SI units ' + \ + help = 'root file system size in SI units ' + \ '(default: %(default)s).', type = str, action = valid_si, default = '63m') argsp.add_argument('-A', '--fs-align', - help = 'Root file system alignment in SI units ' + \ + help = 'root file system alignment in SI units ' + \ '(default: %(default)s).', type = str, action = valid_si, default = '63m') argsp.add_argument('-k', '--kernel', - help = 'Install the kernel (default: %(default)r).', + help = 'install the kernel (default: %(default)r).', type = str, action = valid_file, default = None) argsp.add_argument('-f', '--file', - help = 'Install the file (default: None).', + help = 'install the file (default: None).', type = str, action = valid_file, default = []) - argsp.add_argument('-N', '--net-boot', - help = 'Configure a network boot using TFTP ' + \ + argsp.add_argument('--net-boot', + help = 'configure a network boot using TFTP ' + \ '(default: %(default)r).', action = 'store_true') - argsp.add_argument('-B', '--net-boot-server', - help = 'Network boot server IP address ' + \ + argsp.add_argument('--net-boot-server', + help = 'network boot server IP address ' + \ '(default: %(default)r).', type = str, action = valid_ip, default = None) - argsp.add_argument('-I', '--net-boot-ip', - help = 'Network boot IP address (default: %(default)r).', + argsp.add_argument('--net-boot-ip', + help = 'network boot IP address (default: %(default)r).', type = str, action = valid_ip, default = None) argsp.add_argument('-U', '--custom-uenv', - help = 'Install the custom uEnv.txt file ' + \ + help = 'install the custom uEnv.txt file ' + \ '(default: %(default)r).', type = str, action = valid_file, default = None) - argsp.add_argument('-b', '--build', - help = 'Path to a directory to build the image in' + \ - ' (default: %(default)s).', - action = valid_dir, default = 'build') + argsp.add_argument('-b', '--board', + help = 'name of the board (default: %(default)r).', + type = str, required = True) + argsp.add_argument('--no-clean', + help = 'do not clean up when finished (default: %(default)r).', + action = 'store_false', default = False) argsp.add_argument('-o', '--output', - help = 'Image output file name', + help = 'image output file name', type = str, required = True) - argsp.add_argument('uboot', - help = 'The path to a built u-boot.', - nargs = 1, type = str, action = valid_dir) + argsp.add_argument('paths', + help = 'files or paths, the number and type sets the mode.', + nargs = '+', action = valid_paths) argopts = argsp.parse_args(args[1:]) @@ -773,28 +922,33 @@ def run(args = sys.argv, command_path = None): log.output('Platform: %s' % (host.name)) - config = uboot_settings(argopts.uboot) + conf = uboot_config(command_path, argopts.paths, argopts.board) + conf.check_mandatory_configs() - config.output = argopts.output - config.net_server_ip = argopts.net_boot_server - config.net_ip = argopts.net_boot_ip - config.build = argopts.build - config.image_size = argopts.image_size - config.fs_format = argopts.fs_format - config.fs_size = argopts.fs_size - config.fs_align = argopts.fs_align - config.kernel = argopts.kernel - config.files = argopts.file - config.uenv_txt = argopts.custom_uenv + conf.clean = argopts.no_clean + conf['output'] = argopts.output + conf['net_server_ip'] = argopts.net_boot_server + conf['net_ip'] = argopts.net_boot_ip + conf['build'] = 'build' # need an option for this at some point + conf['image_size'] = argopts.image_size + conf['fs_format'] = argopts.fs_format + conf['fs_size'] = argopts.fs_size + conf['fs_align'] = argopts.fs_align + conf['kernel'] = argopts.kernel + conf['files'] = ','.join(argopts.file) + conf['uenv_txt'] = argopts.custom_uenv - config.log() + conf.log() if host.name not in builders: err = 'no builder; platform not supported: %s' % (host.name) raise error.general(err) - builder = builders[host.name](config) - builder.check_exes() + builder = builders[host.name](conf) + + if not conf.check_exes() or not builder.check_exes(): + raise error.general('command(s) not found; please fix.') + builder.build() except error.general as gerr: diff --git a/misc/tools/rtems-boot.ini b/misc/tools/rtems-boot.ini new file mode 100644 index 0000000..631a107 --- /dev/null +++ b/misc/tools/rtems-boot.ini @@ -0,0 +1,64 @@ +; +; Bootloader Parameters +; + +[default] +image_size = 64m +part_type = MBR +part_label = RTEMS +fs_format = fat16 +fs_size = 63m +fs_alignment = 1m +tool_prefix = %{arch}-rtems%{version}- +objcopy = %{tool_prefix}objcopy +bootloaders = u-boot + +[u-boot] +boards = u-boot-beaglebone, + u-boot-zedboard +bootdelay = 5 +mkimage = %{ubootdir}/tools/mkimage +executables = cat, gzip, %{mkimage}, %{objcopy} +boot_config = uEnv.txt + +[u-boot-beaglebone] +uses = u-boot-arm-ti-am335x_evm + +[u-boot-zedboard] +uses = u-boot-arm-xilinx-zynq-common + +[u-boot-arm-ti-am335x_evm] +arch = arm +vendor = ti +board = am335x +config_name = am335x_evm +first_stage = %{ubootdir}/MLO +boot_device = mmc 0 +second_stage = %{ubootdir}/u-boot.img +start_address = 0x80000000 +entry_address = 0x80000000 +kernel_loadaddr = 0x82000000 +kernel_converter = %{objcopy} @KERNEL@ -O binary @KERNEL@.bin, + cat @KERNEL@.bin | gzip -9 > @KERNEL@.gz, + %{mkimage} -A arm -O RTEMS -T kernel -a %{start_address} + -e %{entry_address} -n "RTEMS" -d @KERNEL@.gz @KERNEL@.img +kernel_image = @KERNEL@.img + +[u-boot-arm-xilinx-zynq-common] +arch = arm +vendor = xilinx +board = zynq +config_name = zynq-common +first_stage = %{ubootdior}/spl/boot.bin +second_state = %{ubootdir}/u-boot.img +kernel_loadaddr = 0x02000000 +kernel_converter = %{objcopy} -R -S --strip-debug -O binary @KERNEL@ @KERNEL@.bin, + cat @KERNEL@.bin | gzip -9 @KERNEL@.gz +kernel_image = @KERNEL@.img + +[u-boot-templates] +exe = setenv bootdelay %{bootdelay}, + loadaddr=%{kernel_loadaddr}, + bootfile=@KERNEL_IMAGE@, + uenvcmd=run boot_exe, + boot_exe=load %{boot_device} %{kernel_loadaddr}; bootm %{kernel_loadaddr} |