binman: Add support for building x86 ROMs

The structure of x86 ROMs is pretty complex. There are various binary blobs
to place in the image. Microcode requires special handling so that it is
available to very early code and can be used without any memory whatsoever.

Add support for the various entry types that are currently needed, along
with some tests.

Signed-off-by: Simon Glass <sjg@chromium.org>
Tested-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
Simon Glass 2016-11-25 20:15:53 -07:00
parent 4f44304b0b
commit e0ff855138
23 changed files with 760 additions and 3 deletions

View File

@ -369,6 +369,17 @@ Examples of the above options can be found in the tests. See the
tools/binman/test directory.
Special properties
------------------
Some entries support special properties, documented here:
u-boot-with-ucode-ptr:
optional-ucode: boolean property to make microcode optional. If the
u-boot.bin image does not include microcode, no error will
be generated.
Order of image creation
-----------------------

View File

@ -0,0 +1,55 @@
# Copyright (c) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
# SPDX-License-Identifier: GPL-2.0+
#
# Entry-type module for 'u-boot'
#
import struct
from entry import Entry
from blob import Entry_blob
FD_SIGNATURE = struct.pack('<L', 0x0ff0a55a)
MAX_REGIONS = 5
(REGION_DESCRIPTOR, REGION_BIOS, REGION_ME, REGION_GBE,
REGION_PDATA) = range(5)
class Region:
def __init__(self, data, frba, region_num):
pos = frba + region_num * 4
val = struct.unpack('<L', data[pos:pos + 4])[0]
self.base = (val & 0xfff) << 12
self.limit = ((val & 0x0fff0000) >> 4) | 0xfff
self.size = self.limit - self.base + 1
class Entry_intel_descriptor(Entry_blob):
"""Intel flash descriptor block (4KB)
This is placed at the start of flash and provides information about
the SPI flash regions. In particular it provides the base address and
size of the ME region, allowing us to place the ME binary in the right
place.
"""
def __init__(self, image, etype, node):
Entry_blob.__init__(self, image, etype, node)
self._regions = []
def GetDefaultFilename(self):
return 'descriptor.bin'
def GetPositions(self):
pos = self.data.find(FD_SIGNATURE)
if pos == -1:
self.Raise('Cannot find FD signature')
flvalsig, flmap0, flmap1, flmap2 = struct.unpack('<LLLL',
self.data[pos:pos + 16])
frba = ((flmap0 >> 16) & 0xff) << 4
for i in range(MAX_REGIONS):
self._regions.append(Region(self.data, frba, i))
# Set the offset for ME only, for now, since the others are not used
return {'intel-me': [self._regions[REGION_ME].base,
self._regions[REGION_ME].size]}

View File

@ -0,0 +1,17 @@
# Copyright (c) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
# SPDX-License-Identifier: GPL-2.0+
#
# Entry-type module for Intel Management Engine binary blob
#
from entry import Entry
from blob import Entry_blob
class Entry_intel_me(Entry_blob):
def __init__(self, image, etype, node):
Entry_blob.__init__(self, image, etype, node)
def GetDefaultFilename(self):
return 'me.bin'

View File

@ -0,0 +1,17 @@
# Copyright (c) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
# SPDX-License-Identifier: GPL-2.0+
#
# Entry-type module for Intel Memory Reference Code binary blob
#
from entry import Entry
from blob import Entry_blob
class Entry_intel_mrc(Entry_blob):
def __init__(self, image, etype, node):
Entry_blob.__init__(self, image, etype, node)
def GetDefaultFilename(self):
return 'mrc.bin'

View File

@ -0,0 +1,17 @@
# Copyright (c) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
# SPDX-License-Identifier: GPL-2.0+
#
# Entry-type module for x86 VGA ROM binary blob
#
from entry import Entry
from blob import Entry_blob
class Entry_intel_vga(Entry_blob):
def __init__(self, image, etype, node):
Entry_blob.__init__(self, image, etype, node)
def GetDefaultFilename(self):
return 'vga.bin'

View File

@ -0,0 +1,76 @@
# Copyright (c) 2016 Google, Inc
## Written by Simon Glass <sjg@chromium.org>
# SPDX-License-Identifier: GPL-2.0+
#
# Entry-type module for U-Boot device tree with the microcode removed
#
import fdt_select
from entry import Entry
from blob import Entry_blob
import tools
class Entry_u_boot_dtb_with_ucode(Entry_blob):
"""A U-Boot device tree file, with the microcode removed
See Entry_u_boot_ucode for full details of the 3 entries involved in this
process.
"""
def __init__(self, image, etype, node):
Entry_blob.__init__(self, image, etype, node)
self.ucode_data = ''
self.collate = False
self.ucode_offset = None
self.ucode_size = None
def GetDefaultFilename(self):
return 'u-boot.dtb'
def ObtainContents(self):
Entry_blob.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 not ucode_dest_entry or not ucode_dest_entry.target_pos:
return True
# Create a new file to hold the copied device tree
dtb_name = 'u-boot-dtb-with-ucode.dtb'
fname = tools.GetOutputFilename(dtb_name)
with open(fname, 'wb') as fd:
fd.write(self.data)
# Remove the microcode
fdt = fdt_select.FdtScan(fname)
fdt.Scan()
ucode = fdt.GetNode('/microcode')
if not ucode:
raise self.Raise("No /microcode node found in '%s'" % fname)
# There's no need to collate it (move all microcode into one place)
# if we only have one chunk of microcode.
self.collate = len(ucode.subnodes) > 1
for node in ucode.subnodes:
data_prop = node.props.get('data')
if data_prop:
self.ucode_data += ''.join(data_prop.bytes)
if not self.collate:
poffset = data_prop.GetOffset()
if poffset is None:
# We cannot obtain a property offset. Collate instead.
self.collate = True
else:
# Find the offset in the device tree of the ucode data
self.ucode_offset = poffset + 12
self.ucode_size = len(data_prop.bytes)
if self.collate:
prop = node.DeleteProp('data')
if self.collate:
fdt.Pack()
fdt.Flush()
# Make this file the contents of this entry
self._pathname = fname
self.ReadContents()
return True

View File

@ -0,0 +1,84 @@
# 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
# 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

View File

@ -0,0 +1,87 @@
# 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
#
import struct
import command
from entry import Entry
from blob import Entry_blob
import fdt_util
import tools
class Entry_u_boot_with_ucode_ptr(Entry_blob):
"""U-Boot with embedded microcode pointer
See Entry_u_boot_ucode for full details of the 3 entries involved in this
process.
"""
def __init__(self, image, etype, node):
Entry_blob.__init__(self, image, etype, node)
self.elf_fname = 'u-boot'
self.target_pos = None
def GetDefaultFilename(self):
return 'u-boot-nodtb.bin'
def ObtainContents(self):
# Figure out where to put the microcode pointer
fname = tools.GetInputFilename(self.elf_fname)
args = [['nm', fname], ['grep', '-w', '_dt_ucode_base_size']]
out = (command.RunPipe(args, capture=True, raise_on_error=False).
stdout.splitlines())
if len(out) == 1:
self.target_pos = int(out[0].split()[0], 16)
elif not fdt_util.GetBool(self._node, 'optional-ucode'):
self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot')
return Entry_blob.ObtainContents(self)
def ProcessContents(self):
# If the image does not need microcode, there is nothing to do
if not self.target_pos:
return
# Get the position of the microcode
ucode_entry = self.image.FindEntryType('u-boot-ucode')
if not ucode_entry:
self.Raise('Cannot find microcode region u-boot-ucode')
# Check the target pos is in the image. If it is not, then U-Boot is
# being linked incorrectly, or is being placed at the wrong position
# in the image.
#
# The image 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 position 7MB in the image. In this
# case the ROM starts at 0xff800000, so the position of the first
# entry in the image corresponds to that.
if (self.target_pos < self.pos or
self.target_pos >= self.pos + self.size):
self.Raise('Microcode pointer _dt_ucode_base_size at %08x is '
'outside the image ranging from %08x to %08x' %
(self.target_pos, self.pos, self.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 former. If we extracted the microcode from the device tree
# and collated it in one place, it will be in the latter.
if ucode_entry.size:
pos, size = ucode_entry.pos, ucode_entry.size
else:
dtb_entry = self.image.FindEntryType('u-boot-dtb-with-ucode')
if not dtb_entry:
self.Raise('Cannot find microcode region u-boot-dtb-with-ucode')
pos = dtb_entry.pos + dtb_entry.ucode_offset
size = dtb_entry.ucode_size
# Write the microcode position and size into the entry
pos_and_size = struct.pack('<2L', pos, size)
self.target_pos -= self.pos
self.data = (self.data[:self.target_pos] + pos_and_size +
self.data[self.target_pos + 8:])

View File

@ -0,0 +1,17 @@
# Copyright (c) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
# SPDX-License-Identifier: GPL-2.0+
#
# Entry-type module for the 16-bit x86 start-up code for U-Boot
#
from entry import Entry
from blob import Entry_blob
class Entry_x86_start16(Entry_blob):
def __init__(self, image, etype, node):
Entry_blob.__init__(self, image, etype, node)
def GetDefaultFilename(self):
return 'u-boot-x86-16bit.bin'

View File

@ -65,10 +65,21 @@ class TestFunctional(unittest.TestCase):
TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
TestFunctional._MakeInputFile('me.bin', ME_DATA)
TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
self._output_setup = False
# ELF file with a '_dt_ucode_base_size' symbol
with open(self.TestFile('u_boot_ucode_ptr')) as fd:
TestFunctional._MakeInputFile('u-boot', fd.read())
# Intel flash descriptor file
with open(self.TestFile('descriptor.bin')) as fd:
TestFunctional._MakeInputFile('descriptor.bin', fd.read())
@classmethod
def tearDownClass(self):
"""Remove the temporary input directory and its contents"""
@ -125,6 +136,18 @@ class TestFunctional(unittest.TestCase):
'-d', self.TestFile(fname))
def _SetupDtb(self, fname, outfile='u-boot.dtb'):
"""Set up a new test device-tree file
The given file is compiled and set up as the device tree to be used
for ths test.
Args:
fname: Filename of .dts file to read
outfile: Output filename for compiled device tree binary
Returns:
Contents of device tree binary
"""
if not self._output_setup:
tools.PrepareOutputDir(self._indir, True)
self._output_setup = True
@ -132,8 +155,9 @@ class TestFunctional(unittest.TestCase):
with open(dtb) as fd:
data = fd.read()
TestFunctional._MakeInputFile(outfile, data)
return data
def _DoReadFile(self, fname, use_real_dtb=False):
def _DoReadFileDtb(self, fname, use_real_dtb=False):
"""Run binman and return the resulting image
This runs binman with a given test file and then reads the resulting
@ -148,10 +172,16 @@ class TestFunctional(unittest.TestCase):
the u-boot-dtb entry. Normally this is not needed and the
test contents (the U_BOOT_DTB_DATA string) can be used.
But in some test we need the real contents.
Returns:
Tuple:
Resulting image contents
Device tree contents
"""
dtb_data = None
# Use the compiled test file as the u-boot-dtb input
if use_real_dtb:
self._SetupDtb(fname)
dtb_data = self._SetupDtb(fname)
try:
retcode = self._DoTestFile(fname)
@ -162,12 +192,16 @@ class TestFunctional(unittest.TestCase):
fname = tools.GetOutputFilename('image.bin')
self.assertTrue(os.path.exists(fname))
with open(fname) as fd:
return fd.read()
return fd.read(), dtb_data
finally:
# Put the test file back
if use_real_dtb:
TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
def _DoReadFile(self, fname, use_real_dtb=False):
"""Helper function which discards the device-tree binary"""
return self._DoReadFileDtb(fname, use_real_dtb)[0]
@classmethod
def _MakeInputFile(self, fname, contents):
"""Create a new test input file, creating directories as needed
@ -213,6 +247,17 @@ class TestFunctional(unittest.TestCase):
self.assertEqual(pos, entry.pos)
pos += entry.size
def GetFdtLen(self, dtb):
"""Get the totalsize field from a device tree binary
Args:
dtb: Device tree binary contents
Returns:
Total size of device tree binary, from the header
"""
return struct.unpack('>L', dtb[4:8])[0]
def testRun(self):
"""Test a basic run with valid args"""
result = self._RunBinman('-h')
@ -540,3 +585,131 @@ class TestFunctional(unittest.TestCase):
"""Test that a device tree can be added to U-Boot"""
data = self._DoReadFile('26_pack_u_boot_dtb.dts')
self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
def testPackX86RomNoSize(self):
"""Test that the end-at-4gb property requires a size property"""
with self.assertRaises(ValueError) as e:
self._DoTestFile('27_pack_4gb_no_size.dts')
self.assertIn("Image '/binman': Image size must be provided when "
"using end-at-4gb", str(e.exception))
def testPackX86RomOutside(self):
"""Test that the end-at-4gb property checks for position boundaries"""
with self.assertRaises(ValueError) as e:
self._DoTestFile('28_pack_4gb_outside.dts')
self.assertIn("Node '/binman/u-boot': Position 0x0 (0) is outside "
"the image starting at 0xfffffff0 (4294967280)",
str(e.exception))
def testPackX86Rom(self):
"""Test that a basic x86 ROM can be created"""
data = self._DoReadFile('29_x86-rom.dts')
self.assertEqual(U_BOOT_DATA + chr(0) * 3 + U_BOOT_SPL_DATA +
chr(0) * 6, data)
def testPackX86RomMeNoDesc(self):
"""Test that an invalid Intel descriptor entry is detected"""
TestFunctional._MakeInputFile('descriptor.bin', '')
with self.assertRaises(ValueError) as e:
self._DoTestFile('31_x86-rom-me.dts')
self.assertIn("Node '/binman/intel-descriptor': Cannot find FD "
"signature", str(e.exception))
def testPackX86RomBadDesc(self):
"""Test that the Intel requires a descriptor entry"""
with self.assertRaises(ValueError) as e:
self._DoTestFile('30_x86-rom-me-no-desc.dts')
self.assertIn("Node '/binman/intel-me': No position set with "
"pos-unset: should another entry provide this correct "
"position?", str(e.exception))
def testPackX86RomMe(self):
"""Test that an x86 ROM with an ME region can be created"""
data = self._DoReadFile('31_x86-rom-me.dts')
self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
def testPackVga(self):
"""Test that an image with a VGA binary can be created"""
data = self._DoReadFile('32_intel-vga.dts')
self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
def testPackStart16(self):
"""Test that an image with an x86 start16 region can be created"""
data = self._DoReadFile('33_x86-start16.dts')
self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
def testPackUbootMicrocode(self):
"""Test that x86 microcode can be handled correctly
We expect to see the following in the image, in order:
u-boot-nodtb.bin with a microcode pointer inserted at the correct
place
u-boot.dtb with the microcode removed
the microcode
"""
data = self._DoReadFile('34_x86_ucode.dts', True)
# Now check the device tree has no microcode
second = data[len(U_BOOT_NODTB_DATA):]
fname = tools.GetOutputFilename('test.dtb')
with open(fname, 'wb') as fd:
fd.write(second)
fdt = fdt_select.FdtScan(fname)
ucode = fdt.GetNode('/microcode')
self.assertTrue(ucode)
for node in ucode.subnodes:
self.assertFalse(node.props.get('data'))
fdt_len = self.GetFdtLen(second)
third = second[fdt_len:]
# Check that the microcode appears immediately after the Fdt
# This matches the concatenation of the data properties in
# the /microcode/update@xxx nodes in x86_ucode.dts.
ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
0x78235609)
self.assertEqual(ucode_data, third[:len(ucode_data)])
ucode_pos = len(U_BOOT_NODTB_DATA) + fdt_len
# Check that the microcode pointer was inserted. It should match the
# expected position and size
pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
len(ucode_data))
first = data[:len(U_BOOT_NODTB_DATA)]
self.assertEqual('nodtb with microcode' + pos_and_size +
' somewhere in here', first)
def _RunPackUbootSingleMicrocode(self, collate):
"""Test that x86 microcode can be handled correctly
We expect to see the following in the image, in order:
u-boot-nodtb.bin with a microcode pointer inserted at the correct
place
u-boot.dtb with the microcode
an empty microcode region
"""
# We need the libfdt library to run this test since only that allows
# finding the offset of a property. This is required by
# Entry_u_boot_dtb_with_ucode.ObtainContents().
if not fdt_select.have_libfdt:
return
data = self._DoReadFile('35_x86_single_ucode.dts', True)
second = data[len(U_BOOT_NODTB_DATA):]
fdt_len = self.GetFdtLen(second)
third = second[fdt_len:]
second = second[:fdt_len]
if not collate:
ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
self.assertIn(ucode_data, second)
ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
# Check that the microcode pointer was inserted. It should match the
# expected position and size
pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
len(ucode_data))
first = data[:len(U_BOOT_NODTB_DATA)]
self.assertEqual('nodtb with microcode' + pos_and_size +
' somewhere in here', first)

View File

@ -0,0 +1,18 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
sort-by-pos;
end-at-4gb;
u-boot {
pos = <0xfffffff0>;
};
u-boot-spl {
pos = <0xfffffff7>;
};
};
};

View File

@ -0,0 +1,19 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
sort-by-pos;
end-at-4gb;
size = <16>;
u-boot {
pos = <0>;
};
u-boot-spl {
pos = <0xfffffff7>;
};
};
};

View File

@ -0,0 +1,19 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
sort-by-pos;
end-at-4gb;
size = <16>;
u-boot {
pos = <0xfffffff0>;
};
u-boot-spl {
pos = <0xfffffff7>;
};
};
};

View File

@ -0,0 +1,15 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
sort-by-pos;
end-at-4gb;
size = <16>;
intel-me {
pos-unset;
};
};
};

View File

@ -0,0 +1,18 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
sort-by-pos;
end-at-4gb;
size = <0x800000>;
intel-descriptor {
};
intel-me {
pos-unset;
};
};
};

View File

@ -0,0 +1,13 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
size = <16>;
intel-vga {
};
};
};

View File

@ -0,0 +1,13 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
size = <16>;
x86-start16 {
};
};
};

View File

@ -0,0 +1,29 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
sort-by-pos;
end-at-4gb;
size = <0x200>;
u-boot-with-ucode-ptr {
};
u-boot-dtb-with-ucode {
};
u-boot-ucode {
};
};
microcode {
update@0 {
data = <0x12345678 0x12345679>;
};
update@1 {
data = <0xabcd0000 0x78235609>;
};
};
};

View File

@ -0,0 +1,26 @@
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
sort-by-pos;
end-at-4gb;
size = <0x200>;
u-boot-with-ucode-ptr {
};
u-boot-dtb-with-ucode {
};
u-boot-ucode {
};
};
microcode {
update@0 {
data = <0x12345678 0x12345679>;
};
};
};

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) 2016 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*
* Simple program to create a _dt_ucode_base_size symbol which can be read
* by 'nm'. This is used by binman tests.
*
* Build with:
* cc -march=i386 -m32 -o u_boot_ucode_ptr -T u_boot_ucode_ptr.lds -nostdlib \
u_boot_ucode_ptr.c
*/
static unsigned long _dt_ucode_base_size[2]
__attribute__((section(".ucode"))) = {1, 2};

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2016 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SECTIONS
{
. = 0xfffffdf0;
_start = .;
.ucode : {
*(.ucode)
}
}