1# Copyright (c) 2016 Google, Inc 2# Written by Simon Glass <sjg@chromium.org> 3# 4# SPDX-License-Identifier: GPL-2.0+ 5# 6# Entry-type module for a U-Boot binary with an embedded microcode pointer 7# 8 9import struct 10 11import command 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 See Entry_u_boot_ucode for full details of the 3 entries involved in this 21 process. 22 """ 23 def __init__(self, image, etype, node): 24 Entry_blob.__init__(self, image, etype, node) 25 self.elf_fname = 'u-boot' 26 self.target_pos = None 27 28 def GetDefaultFilename(self): 29 return 'u-boot-nodtb.bin' 30 31 def ObtainContents(self): 32 # Figure out where to put the microcode pointer 33 fname = tools.GetInputFilename(self.elf_fname) 34 args = [['nm', fname], ['grep', '-w', '_dt_ucode_base_size']] 35 out = (command.RunPipe(args, capture=True, raise_on_error=False). 36 stdout.splitlines()) 37 if len(out) == 1: 38 self.target_pos = int(out[0].split()[0], 16) 39 elif not fdt_util.GetBool(self._node, 'optional-ucode'): 40 self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot') 41 42 return Entry_blob.ObtainContents(self) 43 44 def ProcessContents(self): 45 # If the image does not need microcode, there is nothing to do 46 if not self.target_pos: 47 return 48 49 # Get the position of the microcode 50 ucode_entry = self.image.FindEntryType('u-boot-ucode') 51 if not ucode_entry: 52 self.Raise('Cannot find microcode region u-boot-ucode') 53 54 # Check the target pos is in the image. If it is not, then U-Boot is 55 # being linked incorrectly, or is being placed at the wrong position 56 # in the image. 57 # 58 # The image must be set up so that U-Boot is placed at the 59 # flash address to which it is linked. For example, if 60 # CONFIG_SYS_TEXT_BASE is 0xfff00000, and the ROM is 8MB, then 61 # the U-Boot region must start at position 7MB in the image. In this 62 # case the ROM starts at 0xff800000, so the position of the first 63 # entry in the image corresponds to that. 64 if (self.target_pos < self.pos or 65 self.target_pos >= self.pos + self.size): 66 self.Raise('Microcode pointer _dt_ucode_base_size at %08x is ' 67 'outside the image ranging from %08x to %08x' % 68 (self.target_pos, self.pos, self.pos + self.size)) 69 70 # Get the microcode, either from u-boot-ucode or u-boot-dtb-with-ucode. 71 # If we have left the microcode in the device tree, then it will be 72 # in the former. If we extracted the microcode from the device tree 73 # and collated it in one place, it will be in the latter. 74 if ucode_entry.size: 75 pos, size = ucode_entry.pos, ucode_entry.size 76 else: 77 dtb_entry = self.image.FindEntryType('u-boot-dtb-with-ucode') 78 if not dtb_entry: 79 self.Raise('Cannot find microcode region u-boot-dtb-with-ucode') 80 pos = dtb_entry.pos + dtb_entry.ucode_offset 81 size = dtb_entry.ucode_size 82 83 # Write the microcode position and size into the entry 84 pos_and_size = struct.pack('<2L', pos, size) 85 self.target_pos -= self.pos 86 self.data = (self.data[:self.target_pos] + pos_and_size + 87 self.data[self.target_pos + 8:]) 88