# Copyright (c) 2016 Google, Inc
|
# Written by Simon Glass <sjg@chromium.org>
|
#
|
# SPDX-License-Identifier: GPL-2.0+
|
#
|
# Entry-type module for a U-Boot binary with an embedded microcode pointer
|
#
|
|
from entry import Entry
|
from blob import Entry_blob
|
import tools
|
|
class Entry_u_boot_ucode(Entry_blob):
|
"""U-Boot microcode block
|
|
U-Boot on x86 needs a single block of microcode. This is collected from
|
the various microcode update nodes in the device tree. It is also unable
|
to read the microcode from the device tree on platforms that use FSP
|
(Firmware Support Package) binaries, because the API requires that the
|
microcode is supplied before there is any SRAM available to use (i.e.
|
the FSP sets up the SRAM / cache-as-RAM but does so in the call that
|
requires the microcode!). To keep things simple, all x86 platforms handle
|
microcode the same way in U-Boot (even non-FSP platforms). This is that
|
a table is placed at _dt_ucode_base_size containing the base address and
|
size of the microcode. This is either passed to the FSP (for FSP
|
platforms), or used to set up the microcode (for non-FSP platforms).
|
This all happens in the build system since it is the only way to get
|
the microcode into a single blob and accessible without SRAM.
|
|
There are two cases to handle. If there is only one microcode blob in
|
the device tree, then the ucode pointer it set to point to that. This
|
entry (u-boot-ucode) is empty. If there is more than one update, then
|
this entry holds the concatenation of all updates, and the device tree
|
entry (u-boot-dtb-with-ucode) is updated to remove the microcode. This
|
last step ensures that that the microcode appears in one contiguous
|
block in the image and is not unnecessarily duplicated in the device
|
tree. It is referred to as 'collation' here.
|
|
Entry types that have a part to play in handling microcode:
|
|
Entry_u_boot_with_ucode_ptr:
|
Contains u-boot-nodtb.bin (i.e. U-Boot without the device tree).
|
It updates it with the address and size of the microcode so that
|
U-Boot can find it early on start-up.
|
Entry_u_boot_dtb_with_ucode:
|
Contains u-boot.dtb. It stores the microcode in a
|
'self.ucode_data' property, which is then read by this class to
|
obtain the microcode if needed. If collation is performed, it
|
removes the microcode from the device tree.
|
Entry_u_boot_ucode:
|
This class. If collation is enabled it reads the microcode from
|
the Entry_u_boot_dtb_with_ucode entry, and uses it as the
|
contents of this entry.
|
"""
|
def __init__(self, image, etype, node):
|
Entry_blob.__init__(self, image, etype, node)
|
|
def ObtainContents(self):
|
# If the image does not need microcode, there is nothing to do
|
ucode_dest_entry = self.image.FindEntryType('u-boot-with-ucode-ptr')
|
if ucode_dest_entry and not ucode_dest_entry.target_pos:
|
self.data = ''
|
return True
|
|
# Handle microcode in SPL image as well
|
ucode_dest_entry = self.image.FindEntryType('u-boot-spl-with-ucode-ptr')
|
if ucode_dest_entry and not ucode_dest_entry.target_pos:
|
self.data = ''
|
return True
|
|
# Get the microcode from the device tree entry
|
fdt_entry = self.image.FindEntryType('u-boot-dtb-with-ucode')
|
if not fdt_entry or not fdt_entry.ucode_data:
|
return False
|
|
if not fdt_entry.collate:
|
# This section can be empty
|
self.data = ''
|
return True
|
|
# Write it out to a file
|
dtb_name = 'u-boot-ucode.bin'
|
fname = tools.GetOutputFilename(dtb_name)
|
with open(fname, 'wb') as fd:
|
fd.write(fdt_entry.ucode_data)
|
|
self._pathname = fname
|
self.ReadContents()
|
|
return True
|