]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | # SPDX-License-Identifier: GPL-2.0+ |
e0ff8551 SG |
2 | # Copyright (c) 2016 Google, Inc |
3 | # Written by Simon Glass <sjg@chromium.org> | |
4 | # | |
e0ff8551 SG |
5 | # Entry-type module for a U-Boot binary with an embedded microcode pointer |
6 | # | |
7 | ||
8 | from entry import Entry | |
9 | from blob import Entry_blob | |
10 | import tools | |
11 | ||
12 | class Entry_u_boot_ucode(Entry_blob): | |
13 | """U-Boot microcode block | |
14 | ||
3fb397bb SG |
15 | Properties / Entry arguments: |
16 | None | |
17 | ||
18 | The contents of this entry are filled in automatically by other entries | |
19 | which must also be in the image. | |
20 | ||
e0ff8551 SG |
21 | U-Boot on x86 needs a single block of microcode. This is collected from |
22 | the various microcode update nodes in the device tree. It is also unable | |
23 | to read the microcode from the device tree on platforms that use FSP | |
24 | (Firmware Support Package) binaries, because the API requires that the | |
25 | microcode is supplied before there is any SRAM available to use (i.e. | |
26 | the FSP sets up the SRAM / cache-as-RAM but does so in the call that | |
27 | requires the microcode!). To keep things simple, all x86 platforms handle | |
28 | microcode the same way in U-Boot (even non-FSP platforms). This is that | |
29 | a table is placed at _dt_ucode_base_size containing the base address and | |
30 | size of the microcode. This is either passed to the FSP (for FSP | |
31 | platforms), or used to set up the microcode (for non-FSP platforms). | |
32 | This all happens in the build system since it is the only way to get | |
33 | the microcode into a single blob and accessible without SRAM. | |
34 | ||
35 | There are two cases to handle. If there is only one microcode blob in | |
36 | the device tree, then the ucode pointer it set to point to that. This | |
37 | entry (u-boot-ucode) is empty. If there is more than one update, then | |
38 | this entry holds the concatenation of all updates, and the device tree | |
39 | entry (u-boot-dtb-with-ucode) is updated to remove the microcode. This | |
40 | last step ensures that that the microcode appears in one contiguous | |
41 | block in the image and is not unnecessarily duplicated in the device | |
42 | tree. It is referred to as 'collation' here. | |
43 | ||
44 | Entry types that have a part to play in handling microcode: | |
45 | ||
46 | Entry_u_boot_with_ucode_ptr: | |
47 | Contains u-boot-nodtb.bin (i.e. U-Boot without the device tree). | |
48 | It updates it with the address and size of the microcode so that | |
49 | U-Boot can find it early on start-up. | |
50 | Entry_u_boot_dtb_with_ucode: | |
51 | Contains u-boot.dtb. It stores the microcode in a | |
52 | 'self.ucode_data' property, which is then read by this class to | |
53 | obtain the microcode if needed. If collation is performed, it | |
54 | removes the microcode from the device tree. | |
55 | Entry_u_boot_ucode: | |
56 | This class. If collation is enabled it reads the microcode from | |
57 | the Entry_u_boot_dtb_with_ucode entry, and uses it as the | |
58 | contents of this entry. | |
59 | """ | |
25ac0e61 SG |
60 | def __init__(self, section, etype, node): |
61 | Entry_blob.__init__(self, section, etype, node) | |
e0ff8551 SG |
62 | |
63 | def ObtainContents(self): | |
25ac0e61 SG |
64 | # If the section does not need microcode, there is nothing to do |
65 | ucode_dest_entry = self.section.FindEntryType('u-boot-with-ucode-ptr') | |
66 | ucode_dest_entry_spl = self.section.FindEntryType( | |
a9871c6e | 67 | 'u-boot-spl-with-ucode-ptr') |
3ab9598d SG |
68 | if ((not ucode_dest_entry or not ucode_dest_entry.target_offset) and |
69 | (not ucode_dest_entry_spl or not ucode_dest_entry_spl.target_offset)): | |
9d1adf04 BM |
70 | self.data = '' |
71 | return True | |
72 | ||
736bb0ae SG |
73 | # Get the microcode from the device tree entry. If it is not available |
74 | # yet, return False so we will be called later. If the section simply | |
75 | # doesn't exist, then we may as well return True, since we are going to | |
76 | # get an error anyway. | |
25ac0e61 | 77 | fdt_entry = self.section.FindEntryType('u-boot-dtb-with-ucode') |
736bb0ae SG |
78 | if not fdt_entry: |
79 | return True | |
ecab8973 | 80 | if not fdt_entry.ready: |
e0ff8551 SG |
81 | return False |
82 | ||
83 | if not fdt_entry.collate: | |
25ac0e61 | 84 | # This binary can be empty |
e0ff8551 SG |
85 | self.data = '' |
86 | return True | |
87 | ||
88 | # Write it out to a file | |
89 | dtb_name = 'u-boot-ucode.bin' | |
90 | fname = tools.GetOutputFilename(dtb_name) | |
91 | with open(fname, 'wb') as fd: | |
92 | fd.write(fdt_entry.ucode_data) | |
93 | ||
94 | self._pathname = fname | |
95 | self.ReadContents() | |
96 | ||
97 | return True |