diff options
author | Chris Johns <chrisj@rtems.org> | 2019-05-30 20:37:50 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2019-05-30 20:37:50 +1000 |
commit | e5716fdf3fdf883b918a06fd149015a932411265 (patch) | |
tree | f8e19f9b4c9a32232ad039b2ed60e95592536931 | |
parent | e2be6a99192dcfaa6ebf548c7c78e6071aa53167 (diff) |
misc/boot-image: Add a tool to create boot images.
-rwxr-xr-x | misc/rtems-boot-image | 42 | ||||
-rw-r--r-- | misc/tools/boot.py | 670 | ||||
-rwxr-xr-x | misc/tools/cmd-boot-image.py | 44 |
3 files changed, 756 insertions, 0 deletions
diff --git a/misc/rtems-boot-image b/misc/rtems-boot-image new file mode 100755 index 0000000..aa23b2e --- /dev/null +++ b/misc/rtems-boot-image @@ -0,0 +1,42 @@ +#! /bin/sh +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2019 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +set -e +base=$(dirname $(dirname $0)) +cmd=misc/tools/cmd-boot-image.py +PYTHON_WRAPPER=rtemstoolkit/python-wrapper.sh +if test -f ${base}/${PYTHON_WRAPPER}; then + PYTHON_CMD=${base}/${cmd} + . ${base}/${PYTHON_WRAPPER} +elif test -f ${base}/share/rtems/${PYTHON_WRAPPER}; then + PYTHON_CMD=${base}/share/rtems/${cmd} + . ${base}/share/rtems/${PYTHON_WRAPPER} +fi +echo "error: RTEMS Toolkit python wrapper not found, please report" diff --git a/misc/tools/boot.py b/misc/tools/boot.py new file mode 100644 index 0000000..3fad3c4 --- /dev/null +++ b/misc/tools/boot.py @@ -0,0 +1,670 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2019 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# +# This code builds a bootloader image for an SD card for a range of +# boards on a range of hosts. +# + +from __future__ import print_function + +import argparse +import copy +import datetime +import os +import sys + +from rtemstoolkit import check +from rtemstoolkit import error +from rtemstoolkit import execute +from rtemstoolkit import host +from rtemstoolkit import log +from rtemstoolkit import path +from rtemstoolkit import version + +class settings(object): + def __init__(self, bootloader = 'none', base = None): + 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.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 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 + +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): + pass + +class image(object): + + def __init__(self, settings): + self.settings = settings + self.detach_images = [] + self.unmount_paths = [] + self.remove_paths = [] + + def build(self): + # + # Cleanup if any goes wrong. + # + try: + # + # Ge the absolute paths to fixed locations. + # + output = path.abspath(self.settings.output) + build = path.abspath(self.settings.build) + mountpoint = path.join(build, 'mnt') + + # + # Create any paths we need. They are removed when this object is + # deleted. + # + self.create_path(build) + self.create_path(mountpoint) + + # + # 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)) + + # + # Attach the image so it is a device. + # + log.notice('Attach image to device: %s' % (self.settings.output)) + device = self.image_attach(output) + + # + # Partition the image. + # + log.notice('Partition device: %s as %s' % (device, self.settings.part_type)) + self.partition(device, + self.settings.part_type, + self.settings.fs_format, + self.settings.fs_size, + self.settings.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) + + # + # Mount the file system. + # + log.notice('Mount: %s' % (part)) + self.mount(self.settings.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) + + # + # Install a kernel if present + # + if self.settings.kernel is not None: + self.install(self.settings.kernel, mountpoint) + # + # Install the bootloader configuration. + # + self.settings.install_configuration(self, mountpoint) + + # + # Install any user files if present. + # + for f in self.settings.files: + self.install(f, mountpoint) + + # + # Done. + # + log.notice('Finished') + finally: + self.cleanup() + + def install(self, src, dst): + src_base = path.basename(src) + log.notice('Install: %s' % (src_base)) + asrc = path.abspath(src) + adst = path.join(path.abspath(dst), src_base) + log.output('Copy : %s -> %s' % (asrc, adst)) + path.copy(asrc, adst) + + def image_attach(self, path_): + device = self.host_image_attach(path_) + self.detach_images += [device] + return device + + def image_detach(self, device): + if device in self.detach_images: + self.detach_images.remove(device) + self.host_image_detach(device) + + def partition(self, device, ptype, pformat, psize, palign): + self.host_partition(device, ptype, pformat, psize, palign) + + def format_partition(self, device, pformat): + self.host_format_partition(device, pformat) + + def device_partition(self, device, pindex): + return self.host_device_partition(device, pindex) + + def mount(self, pformat, device, path_): + if path_ not in self.unmount_paths: + self.host_mount(pformat, device, path_) + self.unmount_paths += [path_] + + def unmount(self, path_): + if path_ in self.unmount_paths: + self.host_unmount(path_) + self.unmount_paths.remove(path_) + + def cleanup(self): + log.notice('Cleanup') + 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) + + def get_exes(self): + return ['dd', + 'mkimage'] + + 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('missing commands; please fix.') + + def si_parse_size(self, size): + orig = size + units = 1 + suffix = '' + 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] + size = size[:-1] + if not size.isdecimal(): + raise error.general('invalid size: %s' % (orig)) + size = int(size) + return size, suffix, size * units + + def si_size(self, size): + si_s, si_u, size = self.si_parse_size(size) + return size + + def si_size_units(self, size): + si_s, si_u, size = self.si_parse_size(size) + return si_s, si_u + + def create_path(self, where, recreate = True, cleanup = True): + if path.exists(where): + log.output('remove: %s' % (where)) + path.removeall(where) + try: + log.output('make: %s' % (where)) + path.mkdir(where) + except: + raise error.general('cannot create build path: %s' % (where)) + if not path.isreadable(where): + 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: + 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: + raise error.general('executing failure: (exit:%d) %s' % (exit_code, cmd)) + return output + +class freebsd_image(image): + def __init__(self, settings): + super(freebsd_image, self).__init__(settings) + + def get_exes(self): + exes = super(freebsd_image, self).get_exes() + return exes + ['mdconfig', + 'gpart', + 'newfs_msdos', + 'mount', + 'umount'] + + def host_image_attach(self, path_): + return self.command('sudo mdconfig -f %s' % (path_)) + + def host_image_detach(self, device): + self.command('sudo mdconfig -d -u %s' % (device)) + + def host_partition(self, device, ptype, pformat, psize, palign): + types = { 'MBR': 'MBR' } + formats = { 'fat16': 'fat16', + 'fat32': 'fat32' } + if ptype not in types: + raise error.general('unknown type of partitioning: %s' % (ptype)) + if pformat not in formats: + raise error.general('unknown format: %s' % (pformat)) + self.command('sudo gpart create -s %s %s' % (types[ptype], device)) + self.command('sudo gpart add -s %s -t %s -a %s %s' % (psize, + formats[pformat], + palign, + device)) + self.command('sudo gpart set -a active -i 1 %s' % (device)) + + def host_format_partition(self, device, pformat): + formats = { 'fat16': ('newfs_msdos', '16'), + 'fat32': ('newfs_msdos', '32') } + if pformat not in formats: + raise error.general('unknown format: %s' % (pformat)) + self.command('sudo %s -F %s %s' % (formats[pformat][0], + formats[pformat][1], + device)) + + def host_device_partition(self, device, pindex): + return '/dev/%ss%d' % (device, pindex) + + def host_mount(self, pformat, device, path_): + formats = { 'fat16': 'msdos', + '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_)) + + def host_unmount(self, path_): + self.command('sudo umount %s' % (path_)) + +class linux_image(image): + def __init__(self, settings): + super(linux_image, self).__init__(settings) + + def host_image_attach(self, path_): + pass + + def host_image_detach(self, device): + pass + + def host_partition(self, device, ptype, pformat, psize, palign): + pass + + def host_format_partition(self, device, pformat): + pass + + def host_device_partition(self, device, pindex): + pass + + def host_mount(self, pformat, device, path_): + pass + + def host_unmount(self, path_): + pass + +class darwin_image(image): + def __init__(self, settings): + super(darwin_image, self).__init__(settings) + + def host_image_attach(self, path_): + pass + + def host_image_detach(self, device): + pass + + def host_partition(self, device, ptype, pformat, psize, palign): + pass + + def host_format_partition(self, device, pformat): + pass + + def host_device_partition(self, device, pindex): + pass + + def host_mount(self, pformat, device, path_): + pass + + def host_unmount(self, path_): + pass + +builders = { + 'freebsd': freebsd_image, + 'linux ' : linux_image, + 'darwin' : darwin_image +} + +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')) + +class valid_dir(argparse.Action): + def __call__(self, parser, namespace, values, option_string = None): + if type(values) is not list: + values = [values] + for value in values: + if not path.isdir(value): + raise argparse.ArgumentError(self, + 'is not a valid directory: %s' % (value)) + if not path.isreadable(value): + raise argparse.ArgumentError(self, 'is not readable: %s' % (value)) + if not path.iswritable(value): + raise argparse.ArgumentError(self, 'is not writeable: %s' % (value)) + setattr(namespace, self.dest, value) + +class valid_file(argparse.Action): + def __call__(self, parser, namespace, value, option_string = None): + current = getattr(namespace, self.dest) + if not isinstance(current, list) and current is not None: + raise argparse.ArgumentError(self, + ' already provided: %s, have %s' % (value, + current)) + if not path.isfile(value): + raise argparse.ArgumentError(self, 'is not a valid file: %s' % (value)) + if not path.isreadable(value): + raise argparse.ArgumentError(self, 'is not readable: %s' % (value)) + if current is not None: + value = current + [value] + setattr(namespace, self.dest, value) + +class valid_format(argparse.Action): + def __call__(self, parser, namespace, value, option_string = None): + current = getattr(namespace, self.dest) + if not isinstance(current, list) and current is not None: + raise argparse.ArgumentError(self, + ' already provided: %s, have %s' % (value, + current)) + if value not in ['fat16', 'fat32']: + raise argparse.ArgumentError(self, ' invalid format: %s' % (value)) + setattr(namespace, self.dest, value) + +class valid_si(argparse.Action): + def __call__(self, parser, namespace, value, option_string = None): + current = getattr(namespace, self.dest) + if current is not None: + raise argparse.ArgumentError(self, + ' already provided: %s, have %s' % (value, + current)) + units = len(value) + if value[-1].isalpha(): + if value[-1] not in ['k', 'm', 'g']: + raise argparse.ArgumentError(self, + 'invalid SI (k, m, g): %s' % (value[-1])) + units = -1 + if not value[:units].isdecimal(): + raise argparse.ArgumentError(self, 'invalid SI size: %s' % (value)) + setattr(namespace, self.dest, value) + +class valid_ip(argparse.Action): + def __call__(self, parser, namespace, value, option_string = None): + current = getattr(namespace, self.dest) + if current is not None: + raise argparse.ArgumentError(self, + ' already provided: %s, have %s' % (value, + current)) + setattr(namespace, self.dest, value) + +def run(args = sys.argv, command_path = None): + ec = 0 + notice = None + builder = None + try: + description = 'RTEMS U-Boot Image builder creates a U-Boot image for' + description += 'for booting.' + + argsp = argparse.ArgumentParser(prog = 'rtems-uboot-image', + description = description) + argsp.add_argument('-l', '--log', + help = 'Log file (default: %(default)s.', + type = str, default = log_default()) + argsp.add_argument('-v', '--trace', + help = 'Enable trace logging for debugging.', + action = 'store_true') + argsp.add_argument('-s', '--image-size', + 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).', + type = str, action = valid_format, default = 'fat16') + argsp.add_argument('-S', '--fs-size', + 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 ' + \ + '(default: %(default)s).', + type = str, action = valid_si, default = '63m') + argsp.add_argument('-k', '--kernel', + 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).', + type = str, action = valid_file, default = []) + argsp.add_argument('-N', '--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 ' + \ + '(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).', + type = str, action = valid_ip, default = None) + argsp.add_argument('-U', '--custom-uenv', + 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('-o', '--output', + 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) + + argopts = argsp.parse_args(args[1:]) + + load_log(argopts.log) + log.notice('RTEMS Tools - Boot Image, %s' % (version.string())) + log.output(log.info(args)) + log.tracing = argopts.trace + + host.load() + + log.output('Platform: %s' % (host.name)) + + config = uboot_settings(argopts.uboot) + + 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 + + config.log() + + if host.name not in builders: + raise error.general('no builder; platform not supported: %s' % (host.name)) + + builder = builders[host.name](config) + builder.check_exes() + builder.build() + + except error.general as gerr: + notice = str(gerr) + ec = 1 + except error.internal as ierr: + notice = str(ierr) + ec = 1 + except error.exit as eerr: + pass + except KeyboardInterrupt: + notice = 'abort: user terminated' + ec = 1 + except: + raise + notice = 'abort: unknown error' + ec = 1 + if builder is not None: + del builder + if notice is not None: + log.stderr(notice) + sys.exit(ec) + +if __name__ == "__main__": + run() diff --git a/misc/tools/cmd-boot-image.py b/misc/tools/cmd-boot-image.py new file mode 100755 index 0000000..f17a91e --- /dev/null +++ b/misc/tools/cmd-boot-image.py @@ -0,0 +1,44 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2019 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +from __future__ import print_function + +import sys, os + +base = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))) +rtems = os.path.dirname(base) +sys.path = [rtems] + sys.path + +try: + import boot + boot.run(sys.argv[1:], command_path = base) +except ImportError: + print("Incorrect RTEMS Tools installation", file = sys.stderr) + sys.exit(1) |