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