diff options
author | Chris Johns <chrisj@rtems.org> | 2019-06-08 23:04:06 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2019-06-08 23:04:06 +1000 |
commit | 99e03687b935fca64a743692ce71f78f4fd237fc (patch) | |
tree | 37bd1cdf6ab7162c2914a1974c389b63519d069f | |
parent | 2fe9313b447965bc38efaefcc8fdea90a273d5d8 (diff) |
misc/boot-image: add uenv templates and uenv.txt support.
-rw-r--r-- | misc/tools/boot.py | 222 | ||||
-rw-r--r-- | misc/tools/rtems-boot.ini | 50 |
2 files changed, 191 insertions, 81 deletions
diff --git a/misc/tools/boot.py b/misc/tools/boot.py index 8cbae4b..7130612 100644 --- a/misc/tools/boot.py +++ b/misc/tools/boot.py @@ -67,6 +67,40 @@ def _command(cmd, cwd): raise error.general(err) return output + def si_units(self, units): + siunits = { 'k': 1024, + 'm': 1024 * 1024, + 'g': 1024 * 1024 * 1024 } + if units not in siunits: + raise error.general('invalid SI unit: %s' % (units)) + return siunits[units] + +def _si_parse_size(size): + orig = size + units = 1 + suffix = '' + if size[-1].isalpha(): + suffix = size[-1] + 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] + size = size[:-1] + if not size.isdigit(): + raise error.general('invalid size: %s' % (orig)) + size = int(size) + return size, suffix, size * units + +def _si_size(size): + si_s, si_u, size = _si_parse_size(size) + return size + +def _si_size_units(size): + si_s, si_u, size = _si_parse_size(size) + return si_s, si_u + class config(object): mandatory_configs = [ @@ -195,15 +229,18 @@ class config(object): def files(self): return [f.strip() for f in self.comma_split(self['files']) if len(f) > 0] - def install_configuration(self, image, mountpoint): + def install_files(self, image, mountpoint): pass - def kernel_convert(self, kernel): - return kernel + def install_configuration(self, image, mountpoint): + pass def kernel_image(self): return self['kernel_image'].replace('@KERNEL@', path.basename(self['kernel'])) + def fdt_image(self): + return self['fdt_image'].replace('@FDT@', path.basename(self['fdt'])) + def filter_text(self, lines): out = [] for line in lines: @@ -211,11 +248,23 @@ class config(object): line = line.replace('@KERNEL@', path.basename(self['kernel'])) if '@KERNEL_IMAGE@' in line: line = line.replace('@KERNEL_IMAGE@', self.kernel_image()) + if '@FDT@' in line: + line = line.replace('@FDT@', path.basename(self['fdt'])) + if '@FDT_IMAGE@' in line: + line = line.replace('@FDT_IMAGE@', self.fdt_image()) + if '@NET_SERVER_IP@' in line: + line = line.replace('@NET_SERVER_IP@', self['net_server_ip']) + if '@NET_IP@' in line: + line = line.replace('@NET_IP@', self['net_ip']) + if '@NET_BOOTFILE@' in line: + line = line.replace('@NET_BOOTFILE@', self['net_bootfile']) out += [line] return out def comma_split(self, value): - return [s.strip() for s in value.split(',')] + if value is not None: + return [s.strip() for s in value.split(',')] + return [] class uboot_config(config): @@ -269,19 +318,63 @@ class uboot_config(config): exes += self.comma_split(self['executables']) return exes + def install_files(self, image, mountpoint): + if self['kernel'] is not None: + kernel_image = self.kernel_convert(image, self['kernel']) + image.install(kernel_image, mountpoint) + if self['fdt'] is not None: + fdt_image = self.fdt_convert(image, self['fdt']) + image.install(fdt_image, mountpoint) + 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) + uenv_txt = self['uenv_txt'] + if uenv_txt is not None: + log.output('Uenv txt: %s' % (uenv_txt)) + image.install(path.abspath(uenv_txt), mountpoint) + else: + template = None + if self['net_server_ip'] is not None or \ + self['net_ip'] is not None or \ + self['net_bootfile'] is not None: + if self['net_boot_ip'] is not None: + template = 'uenv_net_static' + else: + template = 'uenv_net_dhcp' + else: + if self['fdt'] is not None: + if self['kernel'] is not None: + template = 'uenv_exe_fdt' + else: + template = 'uenv_load_fdt' + elif self['kernel'] is not None: + template = 'uenv_exe' + if template is not None: + log.output('Uenv template: %s' % (template)) + uenv_start = self.comma_split(self['uenv_start']) + uenv_body = self.comma_split(self[template]) + uenv_end = self.comma_split(self['uenv_end']) + uenv = uenv_start + uenv_body + uenv_end + image.install_text(self.filter_text(uenv), + path.join(mountpoint, self['boot_config'])) + + def kernel_convert(self, image, kernel): + dst = path.join(path.abspath(self['build']), path.basename(kernel)) + self['kernel_build'] = dst + log.output('Copy (into build): %s -> %s' % (kernel, dst)) + image.clean_path(dst) + path.copy(kernel, dst) + cmds = self.filter_text(self.comma_split(self['kernel_converter'])) for cmd in cmds: _command(cmd, self['build']) - return self['kernel_image'].replace('@KERNEL@', kernel) + return self['kernel_image'].replace('@KERNEL@', dst) + + def fdt_convert(self, image, fdt): + dst = path.join(path.abspath(self['build']), path.basename(fdt)) + self['fdt_build'] = dst + log.output('Copy (into build): %s -> %s' % (fdt, dst)) + image.clean_path(dst) + path.copy(fdt, dst) + return self['fdt_image'].replace('@FDT@', dst) class image(object): @@ -357,11 +450,10 @@ class image(object): self.install(self.conf['second_stage'], mountpoint) # - # Install a kernel if present + # Install the bootload files. # - if self.conf['kernel'] is not None: - kernel_image = self.kernel_image(self.conf['kernel']) - self.install(kernel_image, mountpoint) + self.conf.install_files(self, mountpoint) + # # Install the bootloader configuration. # @@ -385,14 +477,14 @@ class image(object): 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)) + 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('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)) @@ -442,51 +534,14 @@ class image(object): 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): return _check_exes(self.get_exes()) - def si_units(self, units): - siunits = { 'k': 1024, - 'm': 1024 * 1024, - 'g': 1024 * 1024 * 1024 } - if units not in siunits: - raise error.general('invalid SI unit: %s' % (units)) - return siunits[units] - - 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']: - 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.isdigit(): - 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 clean_path(self, name): + self.remove_paths += [name] def create_path(self, where, recreate = True, cleanup = True): if path.exists(where): @@ -501,14 +556,14 @@ 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.conf.clean: + if cleanup: self.remove_paths += [where] def command(self, cmd): return _command(cmd, self.conf['build']) def host_image_create(self, path_, size, exists): - img_size, img_units = self.si_size_units(size) + img_size, img_units = _si_size_units(size) self.command('dd if=/dev/zero of=%s bs=1%s count=%d' % (path_, img_units, img_size)) @@ -606,9 +661,9 @@ class linux_image(image): 'umount'] def host_image_create(self, path_, size, exists): - img_size, img_units = self.si_size_units(size) + img_size, img_units = _si_size_units(size) self.command('dd if=/dev/zero of=%s bs=%s count=%d' % (path_, - self.si_units(img_units), + _si_units(img_units), img_size)) def host_image_attach(self, path_): return self.command('sudo losetup --partscan --find --show %s' % (path_)) @@ -638,8 +693,8 @@ class linux_image(image): 'n', # add a new partition 'p', # primary '1', # partition 1 - '%d' % (self.si_size(palign) / 512), - '%d' % (self.si_size(psize) / 512), + '%d' % (_si_size(palign) / 512), + '%d' % (_si_size(psize) / 512), 't', # change a partition type '%s' % (formats[pformat]), # hex code 'a', # toggle a bootable flag @@ -822,17 +877,13 @@ class valid_format(argparse.Action): 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(): + if not value[:units].isdigit(): raise argparse.ArgumentError(self, 'invalid SI size: %s' % (value)) setattr(namespace, self.dest, value) @@ -872,14 +923,17 @@ def run(args = sys.argv, command_path = None): argsp.add_argument('-S', '--fs-size', help = 'root file system size in SI units ' + \ '(default: %(default)s).', - type = str, action = valid_si, default = '63m') + type = str, action = valid_si, default = 'auto') argsp.add_argument('-A', '--fs-align', help = 'root file system alignment in SI units ' + \ '(default: %(default)s).', - type = str, action = valid_si, default = '63m') + type = str, action = valid_si, default = '1m') argsp.add_argument('-k', '--kernel', help = 'install the kernel (default: %(default)r).', type = str, action = valid_file, default = None) + argsp.add_argument('-d', '--fdt', + help = 'Flat device tree source/blob (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 = []) @@ -894,6 +948,9 @@ def run(args = sys.argv, command_path = None): argsp.add_argument('--net-boot-ip', help = 'network boot IP address (default: %(default)r).', type = str, action = valid_ip, default = None) + argsp.add_argument('--net-boot-file', + help = 'network boot file (default: %(default)r).', + type = str, default = 'rtems.img') argsp.add_argument('-U', '--custom-uenv', help = 'install the custom uEnv.txt file ' + \ '(default: %(default)r).', @@ -902,8 +959,8 @@ def run(args = sys.argv, command_path = None): 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) + help = 'do not clean when finished (default: %(default)r).', + action = 'store_false', default = True) argsp.add_argument('-o', '--output', help = 'image output file name', type = str, required = True) @@ -918,28 +975,45 @@ def run(args = sys.argv, command_path = None): log.output(log.info(args)) log.tracing = argopts.trace + if argopts.net_boot_server is not None or \ + argopts.net_boot_ip is not None or \ + argopts.net_boot_file is not None: + if argopts.custom_uenv is not None: + raise error.general('cannot set custom uenv and net boot options.') + host.load() log.output('Platform: %s' % (host.name)) conf = uboot_config(command_path, argopts.paths, argopts.board) + conf.check_mandatory_configs() conf.clean = argopts.no_clean + conf['board'] = argopts.board conf['output'] = argopts.output conf['net_server_ip'] = argopts.net_boot_server conf['net_ip'] = argopts.net_boot_ip + conf['net_bootfile'] = argopts.net_boot_file 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['fdt'] = argopts.fdt conf['files'] = ','.join(argopts.file) conf['uenv_txt'] = argopts.custom_uenv conf.log() + if conf['fs_size'] == 'auto': + conf['fs_size'] = \ + str(_si_size(conf['image_size']) - _si_size(conf['fs_align'])) + elif _si_size(conf['image_size']) > \ + _si_size(conf['fs_align']) + _si_size(conf['fs_size']): + raise error.general('filesystem partition size larger than image size.') + if host.name not in builders: err = 'no builder; platform not supported: %s' % (host.name) raise error.general(err) diff --git a/misc/tools/rtems-boot.ini b/misc/tools/rtems-boot.ini index 631a107..2792fe1 100644 --- a/misc/tools/rtems-boot.ini +++ b/misc/tools/rtems-boot.ini @@ -19,6 +19,7 @@ boards = u-boot-beaglebone, bootdelay = 5 mkimage = %{ubootdir}/tools/mkimage executables = cat, gzip, %{mkimage}, %{objcopy} +fdt_compiler = ftc boot_config = uEnv.txt [u-boot-beaglebone] @@ -38,11 +39,13 @@ second_stage = %{ubootdir}/u-boot.img start_address = 0x80000000 entry_address = 0x80000000 kernel_loadaddr = 0x82000000 +fdt_loadaddr = 0x88000000 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 + %{mkimage} -A arm -O RTEMS -T kernel -a %{start_address} + -e %{entry_address} -n "RTEMS" -d @KERNEL@.gz @KERNEL@.img kernel_image = @KERNEL@.img +fdt_image = @FDT@ [u-boot-arm-xilinx-zynq-common] arch = arm @@ -52,13 +55,46 @@ config_name = zynq-common first_stage = %{ubootdior}/spl/boot.bin second_state = %{ubootdir}/u-boot.img kernel_loadaddr = 0x02000000 +fdt_loadaddr = 0x08000000 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} +uenv_start = setenv bootdelay %{bootdelay}, + uenvcmd=run boot_rtems; + reset, + rtems_banner=echo ""; + echo "RTEMS %{board} (%{arch}-%{vendor}-%{config_name})"; + echo " rtems-boot-image v%{version_str}"; + echo ""; +uenv_exe = boot_rtems=run rtems_banner; + echo "Loading @KERNEL_IMAGE@"; + load %{boot_device} %{kernel_loadaddr} @KERNEL_IMAGE@; + bootm %{kernel_loadaddr}; +uenv_exe_fdt = boot_rtems=run rtems_banner; + echo "Loading @KERNEL_IMAGE@"; + load %{boot_device} %{kernel_loadaddr} @KERNEL_IMAGE@; + echo "Loading @FDT_IMAGE@"; + load %{boot_device} %{fdt_loadaddr} @FDT_IMAGE@; + bootm %{kernel_loadaddr} - %{fdt_loadaddr}; +uenv_load_fdt = boot_rtems=run rtems_banner; + echo "Loading @FDT_IMAGE@"; + load %{boot_device} %{fdt_loadaddr} @FDT_IMAGE@; +uenv_net_dhcp = boot_rtems=run rtems_banner; + echo "Netboot: DHCP"; + echo " Server: @NET_SERVER_IP@"; + set autoload no; + dhcp; + set serverip @NET_SERVER_IP@; + tftpboot @NET_BOOTFILE@; + bootm; +uenv_net_static = boot_rtems=run rtems_banner; + echo "Netboot: STATIC"; + echo " Server: @NET_SERVER_IP@"; + echo " IP: @NET_IP@"; + set autoload no; + dhcp; + set serverip @NET_SERVER_IP@; + tftpboot @NET_BOOTFILE@; + bootm; |