summaryrefslogtreecommitdiff
path: root/tools/binman/func_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/binman/func_test.py')
-rw-r--r--tools/binman/func_test.py179
1 files changed, 176 insertions, 3 deletions
diff --git a/tools/binman/func_test.py b/tools/binman/func_test.py
index bf6e9ed..341957b 100644
--- a/tools/binman/func_test.py
+++ b/tools/binman/func_test.py
@@ -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)