u_boot_with_ucode_ptr.py 4.1 KB

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