[util, rom_ext] Add rust "header" generation
This change allows to generate the set of ROM_EXT manifest offset and
size values required by the ROM_EXT image signer tool.
This feature is intended to be used by the future ROM_EXT image signer
tool.
Signed-off-by: Silvestrs Timofejevs <silvestrst@lowrisc.org>
diff --git a/sw/device/rom_exts/manifest.rs.tpl b/sw/device/rom_exts/manifest.rs.tpl
new file mode 100644
index 0000000..fcdcd00
--- /dev/null
+++ b/sw/device/rom_exts/manifest.rs.tpl
@@ -0,0 +1,21 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+% for name, region in regions:
+/// Manifest field ${name} offset from the base.
+pub const ${region.offset_name().as_c_define()}:u32 = ${region.base_addr};
+
+/// Manifest field ${name} size in bytes.
+pub const ${region.size_bytes_name().as_c_define()}:u32 = ${region.size_bytes};
+
+/// Manifest field ${name} size in words.
+pub const ${region.size_words_name().as_c_define()}:u32 = ${region.size_words};
+
+% endfor
+
+% for name, offset in offsets:
+/// Manifest offset ${name} from the base.
+pub const ${offset.offset_name().as_c_define()}:u32 = ${offset.offset};
+
+%endfor
diff --git a/sw/device/rom_exts/meson.build b/sw/device/rom_exts/meson.build
index 8bd4d6b..bcdb805 100644
--- a/sw/device/rom_exts/meson.build
+++ b/sw/device/rom_exts/meson.build
@@ -53,6 +53,7 @@
meson.source_root() / 'util/rom-ext-manifest-generator.py',
'--input-dir', meson.current_source_dir(),
'--output-dir', meson.current_build_dir(),
+ '--output-headers', 'c',
],
)
diff --git a/util/rom-ext-manifest-generator.py b/util/rom-ext-manifest-generator.py
index 654c5dd..8d1b36d 100755
--- a/util/rom-ext-manifest-generator.py
+++ b/util/rom-ext-manifest-generator.py
@@ -51,8 +51,16 @@
rom-ext-manifest-generator --output-dir:
Directory where manifest.h will be created.
+
+ rom-ext-manifest-generator --output-headers=[all | c | rust]:
+ Type of headers to be generated:
+
+ all - All header files
+ c - C header file
+ rust - Rust "header" file
"""
+
class MemoryOffset(object):
def __init__(self, name, offset):
self.name = name
@@ -62,17 +70,14 @@
return self.name + Name(["offset"])
-def generate_cheader(fields, input_dir, output_dir):
- """ Generates C header file from the `template_file`.
+def generate_defines(fields):
+ """ Generates manifest defines.
- It produces a list of tuples with a field name and the `MemoryRegion`
- object, which is used in the `template_path`. The resulting header file is
- placed into `output_path`.
+ It produces two list of tuples. One with a field name and the `MemoryRegion`
+ object, and one with `MemoryOffset` object. Please see the description at
+ the top for more information on the differences between these objects.
"""
- template_path = input_dir / 'manifest.h.tpl'
- output_path = output_dir / 'manifest.h'
-
base_name = Name.from_snake_case("ROM_EXT")
regions = []
@@ -87,7 +92,7 @@
# This ends up aligning `current_offset_bytes` to `required_alignment_bytes`
# that is greater than or equal to `current_offset_bytes`.
current_offset_bytes = (current_offset_bytes + required_alignment_bytes - 1) \
- & ~(required_alignment_bytes - 1)
+ & ~(required_alignment_bytes - 1)
if field['type'] == "offset":
offset_name = base_name + Name.from_snake_case(field['name'])
@@ -103,6 +108,46 @@
regions.append((field['name'], region))
current_offset_bytes += size_bytes
+ return [regions, offsets]
+
+
+def generate_cheader(fields, input_dir, output_dir):
+ """ Generates C header file from the template file.
+
+ It produces a list of `MemoryRegion` and `MemoryOffset` objects, which are
+ used by the template file to generate C header file, which is placed into
+ the `output_path`.
+ """
+
+ template_path = input_dir / 'manifest.h.tpl'
+ output_path = output_dir / 'manifest.h'
+
+ regions, offsets = generate_defines(fields)
+
+ with template_path.open('r') as f:
+ template = Template(f.read())
+
+ header = template.render(regions=regions, offsets=offsets)
+
+ with output_path.open('w') as f:
+ f.write(header)
+
+ print('Template sucessfuly written to {}.'.format(output_path))
+
+
+def generate_rust_header(fields, input_dir, output_dir):
+ """ Generates Rust "header" from the template file.
+
+ It produces a list of `MemoryRegion` and `MemoryOffset` objects, which are
+ used by the template file to generate Rust "header", which is placed into
+ the `output_path`.
+ """
+
+ template_path = input_dir / 'manifest.rs.tpl'
+ output_path = output_dir / 'manifest.rs'
+
+ regions, offsets = generate_defines(fields)
+
with template_path.open('r') as f:
template = Template(f.read())
@@ -115,6 +160,8 @@
def main():
+ ALL_PARTS = ["c", "rust"]
+
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
usage=USAGE,
@@ -130,6 +177,12 @@
type=Path,
help='Manifest header output directory.')
+ parser.add_argument('--output-headers',
+ choices=['all'] + ALL_PARTS,
+ default=[],
+ action='append',
+ help='The type of headers to be produced.')
+
args = parser.parse_args()
manifest_hjson_file = args.input_dir / 'manifest.hjson'
@@ -137,7 +190,16 @@
with manifest_hjson_file.open('r') as hjson_file:
obj = hjson.loads(hjson_file.read())
- generate_cheader(obj['fields'], args.input_dir, args.output_dir)
+ if len(args.output_headers) == 0:
+ args.output_headers += ['all']
+ if 'all' in args.output_headers:
+ args.output_headers += ALL_PARTS
+
+ if "c" in args.output_headers:
+ generate_cheader(obj['fields'], args.input_dir, args.output_dir)
+
+ if "rust" in args.output_headers:
+ generate_rust_header(obj['fields'], args.input_dir, args.output_dir)
if __name__ == '__main__':