summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2019-06-08 23:04:06 +1000
committerChris Johns <chrisj@rtems.org>2019-06-08 23:04:06 +1000
commit99e03687b935fca64a743692ce71f78f4fd237fc (patch)
tree37bd1cdf6ab7162c2914a1974c389b63519d069f
parent2fe9313b447965bc38efaefcc8fdea90a273d5d8 (diff)
misc/boot-image: add uenv templates and uenv.txt support.
-rw-r--r--misc/tools/boot.py222
-rw-r--r--misc/tools/rtems-boot.ini50
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;