1# SPDX-License-Identifier: GPL-2.0+
2# Copyright 2023-2024 Marek Vasut <marex@denx.de>
3# Written with much help from Simon Glass <sjg@chromium.org>
4#
5# Entry-type module for generating the i.MX8M mkimage -T imx8mimage
6# configuration file and invocation of mkimage -T imx8mimage on the
7# configuration file and input data.
8#
9
10from collections import OrderedDict
11
12from binman.entry import Entry
13from binman.etype.mkimage import Entry_mkimage
14from binman.etype.section import Entry_section
15from binman import elf
16from dtoc import fdt_util
17from u_boot_pylib import tools
18
19class Entry_nxp_imx8mimage(Entry_mkimage):
20    """NXP i.MX8M imx8mimage .cfg file generator and mkimage invoker
21
22    Properties / Entry arguments:
23        - nxp,boot-from - device to boot from (e.g. 'sd')
24        - nxp,loader-address - loader address (SPL text base)
25        - nxp,rom-version - BootROM version ('2' for i.MX8M Nano and Plus)
26    """
27
28    def __init__(self, section, etype, node):
29        super().__init__(section, etype, node)
30        self.required_props = ['nxp,boot-from', 'nxp,rom-version',
31                               'nxp,loader-address']
32
33    def ReadNode(self):
34        super().ReadNode()
35        self.boot_from = fdt_util.GetString(self._node, 'nxp,boot-from')
36        self.loader_address = fdt_util.GetInt(self._node, 'nxp,loader-address')
37        self.rom_version = fdt_util.GetInt(self._node, 'nxp,rom-version')
38        self.ReadEntries()
39
40    def BuildSectionData(self, required):
41        data, input_fname, uniq = self.collect_contents_to_file(
42            self._entries.values(), 'input')
43        # Generate mkimage configuration file similar to imx8mimage.cfg
44        # and pass it to mkimage to generate SPL image for us here.
45        cfg_fname = tools.get_output_filename('nxp.imx8mimage.cfg.%s' % uniq)
46        with open(cfg_fname, 'w') as outf:
47            print('ROM_VERSION v%d' % self.rom_version, file=outf)
48            print('BOOT_FROM %s' % self.boot_from, file=outf)
49            print('LOADER %s %#x' % (input_fname, self.loader_address), file=outf)
50
51        output_fname = tools.get_output_filename(f'cfg-out.{uniq}')
52        args = ['-d', input_fname, '-n', cfg_fname, '-T', 'imx8mimage',
53                output_fname]
54        if self.mkimage.run_cmd(*args) is not None:
55            return tools.read_file(output_fname)
56        else:
57            # Bintool is missing; just use the input data as the output
58            self.record_missing_bintool(self.mkimage)
59            return data
60
61    def SetImagePos(self, image_pos):
62        # Customized SoC specific SetImagePos which skips the mkimage etype
63        # implementation and removes the 0x48 offset introduced there. That
64        # offset is only used for uImage/fitImage, which is not the case in
65        # here.
66        upto = 0x00
67        for entry in super().GetEntries().values():
68            entry.SetOffsetSize(upto, None)
69
70            # Give up if any entries lack a size
71            if entry.size is None:
72                return
73            upto += entry.size
74
75        Entry_section.SetImagePos(self, image_pos)
76