Prepare v2023.10
[platform/kernel/u-boot.git] / tools / binman / etype / u_boot_dtb_with_ucode.py
1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2016 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
4 #
5 # Entry-type module for U-Boot device tree with the microcode removed
6 #
7
8 from binman.entry import Entry
9 from binman.etype.blob_dtb import Entry_blob_dtb
10 from u_boot_pylib import tools
11
12 # This is imported if needed
13 state = None
14
15 class Entry_u_boot_dtb_with_ucode(Entry_blob_dtb):
16     """A U-Boot device tree file, with the microcode removed
17
18     Properties / Entry arguments:
19         - filename: Filename of u-boot.dtb (default 'u-boot.dtb')
20
21     See Entry_u_boot_ucode for full details of the three entries involved in
22     this process. This entry provides the U-Boot device-tree file, which
23     contains the microcode. If the microcode is not being collated into one
24     place then the offset and size of the microcode is recorded by this entry,
25     for use by u-boot-with-ucode_ptr. If it is being collated, then this
26     entry deletes the microcode from the device tree (to save space) and makes
27     it available to u-boot-ucode.
28     """
29     def __init__(self, section, etype, node):
30         # Put this here to allow entry-docs and help to work without libfdt
31         global state
32         from binman import state
33
34         super().__init__(section, etype, node)
35         self.ucode_data = b''
36         self.collate = False
37         self.ucode_offset = None
38         self.ucode_size = None
39         self.ucode = None
40         self.ready = False
41
42     def GetDefaultFilename(self):
43         return 'u-boot.dtb'
44
45     def GetFdtEtype(self):
46         return 'u-boot-dtb'
47
48     def ProcessFdt(self, fdt):
49         # So the module can be loaded without it
50         from dtoc import fdt
51
52         # If the section does not need microcode, there is nothing to do
53         ucode_dest_entry = self.section.FindEntryType(
54             'u-boot-spl-with-ucode-ptr')
55         if not ucode_dest_entry or not ucode_dest_entry.target_offset:
56             ucode_dest_entry = self.section.FindEntryType(
57                 'u-boot-tpl-with-ucode-ptr')
58         if not ucode_dest_entry or not ucode_dest_entry.target_offset:
59             ucode_dest_entry = self.section.FindEntryType(
60                 'u-boot-with-ucode-ptr')
61         if not ucode_dest_entry or not ucode_dest_entry.target_offset:
62             return True
63
64         # Remove the microcode
65         etype = self.GetFdtEtype()
66         fdt = state.GetFdtForEtype(etype)
67         self.ucode = fdt.GetNode('/microcode')
68         if not self.ucode:
69             raise self.Raise("No /microcode node found in '%s'" % etype)
70
71         # There's no need to collate it (move all microcode into one place)
72         # if we only have one chunk of microcode.
73         self.collate = len(self.ucode.subnodes) > 1
74         for node in self.ucode.subnodes:
75             data_prop = node.props.get('data')
76             if data_prop:
77                 self.ucode_data += data_prop.bytes
78                 if self.collate:
79                     node.DeleteProp('data')
80         return True
81
82     def ObtainContents(self):
83         # Call the base class just in case it does something important.
84         super().ObtainContents()
85         if self.ucode and not self.collate:
86             for node in self.ucode.subnodes:
87                 data_prop = node.props.get('data')
88                 if data_prop:
89                     # Find the offset in the device tree of the ucode data
90                     self.ucode_offset = data_prop.GetOffset() + 12
91                     self.ucode_size = len(data_prop.bytes)
92                     self.ready = True
93         else:
94             self.ready = True
95         return self.ready