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 a U-Boot binary with an embedded microcode pointer 6# 7 8from entry import Entry 9from blob import Entry_blob 10import tools 11 12class Entry_u_boot_ucode(Entry_blob): 13 """U-Boot microcode block 14 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 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 """ 60 def __init__(self, section, etype, node): 61 Entry_blob.__init__(self, section, etype, node) 62 63 def ObtainContents(self): 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( 67 'u-boot-spl-with-ucode-ptr') 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)): 70 self.data = '' 71 return True 72 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. 77 fdt_entry = self.section.FindEntryType('u-boot-dtb-with-ucode') 78 if not fdt_entry: 79 return True 80 if not fdt_entry.ready: 81 return False 82 83 if not fdt_entry.collate: 84 # This binary can be empty 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.ReadBlobContents() 96 97 return True 98