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 8import struct 9 10import command 11import elf 12from entry import Entry 13from blob import Entry_blob 14import fdt_util 15import tools 16 17class Entry_u_boot_with_ucode_ptr(Entry_blob): 18 """U-Boot with embedded microcode pointer 19 20 Properties / Entry arguments: 21 - filename: Filename of u-boot-nodtb.dtb (default 'u-boot-nodtb.dtb') 22 - optional-ucode: boolean property to make microcode optional. If the 23 u-boot.bin image does not include microcode, no error will 24 be generated. 25 26 See Entry_u_boot_ucode for full details of the three entries involved in 27 this process. This entry updates U-Boot with the offset and size of the 28 microcode, to allow early x86 boot code to find it without doing anything 29 complicated. Otherwise it is the same as the u_boot entry. 30 """ 31 def __init__(self, section, etype, node): 32 Entry_blob.__init__(self, section, etype, node) 33 self.elf_fname = 'u-boot' 34 self.target_offset = None 35 36 def GetDefaultFilename(self): 37 return 'u-boot-nodtb.bin' 38 39 def ProcessFdt(self, fdt): 40 # Figure out where to put the microcode pointer 41 fname = tools.GetInputFilename(self.elf_fname) 42 sym = elf.GetSymbolAddress(fname, '_dt_ucode_base_size') 43 if sym: 44 self.target_offset = sym 45 elif not fdt_util.GetBool(self._node, 'optional-ucode'): 46 self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot') 47 return True 48 49 def ProcessContents(self): 50 # If the image does not need microcode, there is nothing to do 51 if not self.target_offset: 52 return 53 54 # Get the offset of the microcode 55 ucode_entry = self.section.FindEntryType('u-boot-ucode') 56 if not ucode_entry: 57 self.Raise('Cannot find microcode region u-boot-ucode') 58 59 # Check the target pos is in the section. If it is not, then U-Boot is 60 # being linked incorrectly, or is being placed at the wrong offset 61 # in the section. 62 # 63 # The section must be set up so that U-Boot is placed at the 64 # flash address to which it is linked. For example, if 65 # CONFIG_SYS_TEXT_BASE is 0xfff00000, and the ROM is 8MB, then 66 # the U-Boot region must start at offset 7MB in the section. In this 67 # case the ROM starts at 0xff800000, so the offset of the first 68 # entry in the section corresponds to that. 69 if (self.target_offset < self.offset or 70 self.target_offset >= self.offset + self.size): 71 self.Raise('Microcode pointer _dt_ucode_base_size at %08x is ' 72 'outside the section ranging from %08x to %08x' % 73 (self.target_offset, self.offset, self.offset + self.size)) 74 75 # Get the microcode, either from u-boot-ucode or u-boot-dtb-with-ucode. 76 # If we have left the microcode in the device tree, then it will be 77 # in the latter. If we extracted the microcode from the device tree 78 # and collated it in one place, it will be in the former. 79 if ucode_entry.size: 80 offset, size = ucode_entry.offset, ucode_entry.size 81 else: 82 dtb_entry = self.section.FindEntryType('u-boot-dtb-with-ucode') 83 if not dtb_entry: 84 dtb_entry = self.section.FindEntryType( 85 'u-boot-tpl-dtb-with-ucode') 86 if not dtb_entry: 87 self.Raise('Cannot find microcode region u-boot-dtb-with-ucode') 88 offset = dtb_entry.offset + dtb_entry.ucode_offset 89 size = dtb_entry.ucode_size 90 91 # Write the microcode offset and size into the entry 92 offset_and_size = struct.pack('<2L', offset, size) 93 self.target_offset -= self.offset 94 self.ProcessContentsUpdate(self.data[:self.target_offset] + 95 offset_and_size + 96 self.data[self.target_offset + 8:]) 97