fit,data
Generates a `data = <...>` property with the contents of the segment
+ fit,firmware
+ Generates a `firmware = <...>` property. Provides a list of possible
+ nodes to be used as the `firmware` property value. The first valid
+ node is picked as the firmware. Any remaining valid nodes is
+ prepended to the `loadable` property generated by `fit,loadables`
+
fit,loadables
Generates a `loadable = <...>` property with a list of the generated
nodes (including all nodes if this operation is used multiple times)
@config-SEQ {
description = "conf-NAME.dtb";
fdt = "fdt-SEQ";
- firmware = "u-boot";
+ fit,firmware = "atf-1", "u-boot";
fit,loadables;
};
};
configurations {
default = "config-1";
config-1 {
- loadables = "atf-1", "atf-2", "atf-3", "tee-1", "tee-2";
+ loadables = "u-boot", "atf-2", "atf-3", "tee-1", "tee-2";
description = "rk3399-firefly.dtb";
fdt = "fdt-1";
- firmware = "u-boot";
+ firmware = "atf-1";
};
};
-U-Boot SPL can then load the firmware (U-Boot proper) and all the loadables
-(ATF and TEE), then proceed with the boot.
+U-Boot SPL can then load the firmware (ATF) and all the loadables (U-Boot
+proper, ATF and TEE), then proceed with the boot.
fit,data
Generates a `data = <...>` property with the contents of the segment
+ fit,firmware
+ Generates a `firmware = <...>` property. Provides a list of possible
+ nodes to be used as the `firmware` property value. The first valid
+ node is picked as the firmware. Any remaining valid nodes is
+ prepended to the `loadable` property generated by `fit,loadables`
+
fit,loadables
Generates a `loadable = <...>` property with a list of the generated
nodes (including all nodes if this operation is used multiple times)
@config-SEQ {
description = "conf-NAME.dtb";
fdt = "fdt-SEQ";
- firmware = "u-boot";
+ fit,firmware = "atf-1", "u-boot";
fit,loadables;
};
};
configurations {
default = "config-1";
config-1 {
- loadables = "atf-1", "atf-2", "atf-3", "tee-1", "tee-2";
+ loadables = "u-boot", "atf-2", "atf-3", "tee-1", "tee-2";
description = "rk3399-firefly.dtb";
fdt = "fdt-1";
- firmware = "u-boot";
+ firmware = "atf-1";
};
};
- U-Boot SPL can then load the firmware (U-Boot proper) and all the loadables
- (ATF and TEE), then proceed with the boot.
+ U-Boot SPL can then load the firmware (ATF) and all the loadables (U-Boot
+ proper, ATF and TEE), then proceed with the boot.
"""
def __init__(self, section, etype, node):
"""
return
fsw.property(pname, prop.bytes)
+ def _process_firmware_prop(node):
+ """Process optional fit,firmware property
+
+ Picks the first valid entry for use as the firmware, remaining valid
+ entries is prepended to loadables
+
+ Args:
+ node (Node): Generator node to process
+
+ Returns:
+ firmware (str): Firmware or None
+ result (list): List of remaining loadables
+ """
+ val = fdt_util.GetStringList(node, 'fit,firmware')
+ if val is None:
+ return None, self._loadables
+ valid_entries = list(self._loadables)
+ for name, entry in self.GetEntries().items():
+ missing = []
+ entry.CheckMissing(missing)
+ entry.CheckOptional(missing)
+ if not missing:
+ valid_entries.append(name)
+ firmware = None
+ result = []
+ for name in val:
+ if name in valid_entries:
+ if not firmware:
+ firmware = name
+ elif name not in result:
+ result.append(name)
+ for name in self._loadables:
+ if name != firmware and name not in result:
+ result.append(name)
+ return firmware, result
+
def _gen_fdt_nodes(base_node, node, depth, in_images):
"""Generate FDT nodes
first.
Args:
- node (None): Generator node to process
+ node (Node): Generator node to process
depth: Current node depth (0 is the base 'fit' node)
in_images: True if this is inside the 'images' node, so that
'data' properties should be generated
"""
if self._fdts:
+ firmware, fit_loadables = _process_firmware_prop(node)
# Generate nodes for each FDT
for seq, fdt_fname in enumerate(self._fdts):
node_name = node.name[1:].replace('SEQ', str(seq + 1))
fname = tools.get_input_filename(fdt_fname + '.dtb')
with fsw.add_node(node_name):
for pname, prop in node.props.items():
- if pname == 'fit,loadables':
- val = '\0'.join(self._loadables) + '\0'
+ if pname == 'fit,firmware':
+ if firmware:
+ fsw.property_string('firmware', firmware)
+ elif pname == 'fit,loadables':
+ val = '\0'.join(fit_loadables) + '\0'
fsw.property('loadables', val.encode('utf-8'))
elif pname == 'fit,operation':
pass
}
self.assertEqual(expected, props)
+ def testFitFirmwareLoadables(self):
+ """Test an image with an FIT that use fit,firmware"""
+ if not elf.ELF_TOOLS:
+ self.skipTest('Python elftools not available')
+ entry_args = {
+ 'of-list': 'test-fdt1',
+ 'default-dt': 'test-fdt1',
+ 'atf-bl31-path': 'bl31.elf',
+ 'tee-os-path': 'missing.bin',
+ }
+ test_subdir = os.path.join(self._indir, TEST_FDT_SUBDIR)
+ data = self._DoReadFileDtb(
+ '276_fit_firmware_loadables.dts',
+ entry_args=entry_args,
+ extra_indirs=[test_subdir])[0]
+
+ dtb = fdt.Fdt.FromData(data)
+ dtb.Scan()
+
+ node = dtb.GetNode('/configurations/conf-uboot-1')
+ self.assertEqual('u-boot', node.props['firmware'].value)
+ self.assertEqual(['atf-1', 'atf-2'],
+ fdt_util.GetStringList(node, 'loadables'))
+
+ node = dtb.GetNode('/configurations/conf-atf-1')
+ self.assertEqual('atf-1', node.props['firmware'].value)
+ self.assertEqual(['u-boot', 'atf-2'],
+ fdt_util.GetStringList(node, 'loadables'))
+
+ node = dtb.GetNode('/configurations/conf-missing-uboot-1')
+ self.assertEqual('u-boot', node.props['firmware'].value)
+ self.assertEqual(['atf-1', 'atf-2'],
+ fdt_util.GetStringList(node, 'loadables'))
+
+ node = dtb.GetNode('/configurations/conf-missing-atf-1')
+ self.assertEqual('atf-1', node.props['firmware'].value)
+ self.assertEqual(['u-boot', 'atf-2'],
+ fdt_util.GetStringList(node, 'loadables'))
+
+ node = dtb.GetNode('/configurations/conf-missing-tee-1')
+ self.assertEqual('atf-1', node.props['firmware'].value)
+ self.assertEqual(['u-boot', 'atf-2'],
+ fdt_util.GetStringList(node, 'loadables'))
+
if __name__ == "__main__":
unittest.main()
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ fit {
+ description = "test desc";
+ #address-cells = <1>;
+ fit,fdt-list = "of-list";
+
+ images {
+ u-boot {
+ description = "test u-boot";
+ type = "standalone";
+ arch = "arm64";
+ os = "u-boot";
+ compression = "none";
+ load = <0x00000000>;
+ entry = <0x00000000>;
+
+ u-boot-nodtb {
+ };
+ };
+ tee {
+ description = "test tee";
+ type = "tee";
+ arch = "arm64";
+ os = "tee";
+ compression = "none";
+ load = <0x00200000>;
+
+ tee-os {
+ optional;
+ };
+ };
+ @atf-SEQ {
+ fit,operation = "split-elf";
+ description = "test tf-a";
+ type = "firmware";
+ arch = "arm64";
+ os = "arm-trusted-firmware";
+ compression = "none";
+ fit,load;
+ fit,entry;
+ fit,data;
+
+ atf-bl31 {
+ };
+ };
+ @fdt-SEQ {
+ description = "test fdt";
+ type = "flat_dt";
+ compression = "none";
+ };
+ };
+
+ configurations {
+ default = "@conf-uboot-DEFAULT-SEQ";
+ @conf-uboot-SEQ {
+ description = "uboot config";
+ fdt = "fdt-SEQ";
+ fit,firmware = "u-boot";
+ fit,loadables;
+ };
+ @conf-atf-SEQ {
+ description = "atf config";
+ fdt = "fdt-SEQ";
+ fit,firmware = "atf-1", "u-boot";
+ fit,loadables;
+ };
+ @conf-missing-uboot-SEQ {
+ description = "missing uboot config";
+ fdt = "fdt-SEQ";
+ fit,firmware = "missing-1", "u-boot";
+ fit,loadables;
+ };
+ @conf-missing-atf-SEQ {
+ description = "missing atf config";
+ fdt = "fdt-SEQ";
+ fit,firmware = "missing-1", "atf-1", "u-boot";
+ fit,loadables;
+ };
+ @conf-missing-tee-SEQ {
+ description = "missing tee config";
+ fdt = "fdt-SEQ";
+ fit,firmware = "atf-1", "u-boot", "tee";
+ fit,loadables;
+ };
+ };
+ };
+ };
+};