From 75db0860b1cee8c3b2539878a227c37bfce00046 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 25 Nov 2016 20:15:55 -0700 Subject: binman: Add support for building x86 ROMs with SPL When building for 64-bit x86 we need an SPL binary in the ROM. Add support for this. Also increase entry test code coverage to 100%. Signed-off-by: Simon Glass Tested-by: Bin Meng diff --git a/tools/binman/etype/u_boot_dtb_with_ucode.py b/tools/binman/etype/u_boot_dtb_with_ucode.py index 732d10a..fc02c67 100644 --- a/tools/binman/etype/u_boot_dtb_with_ucode.py +++ b/tools/binman/etype/u_boot_dtb_with_ucode.py @@ -31,7 +31,9 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob): 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') + ucode_dest_entry = self.image.FindEntryType('u-boot-spl-with-ucode-ptr') + if not ucode_dest_entry or not ucode_dest_entry.target_pos: + 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 diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py new file mode 100644 index 0000000..c005f28 --- /dev/null +++ b/tools/binman/etype/u_boot_spl_bss_pad.py @@ -0,0 +1,26 @@ +# Copyright (c) 2016 Google, Inc +# Written by Simon Glass +# +# SPDX-License-Identifier: GPL-2.0+ +# +# Entry-type module for BSS padding for spl/u-boot-spl.bin. This padding +# can be added after the SPL binary to ensure that anything concatenated +# to it will appear to SPL to be at the end of BSS rather than the start. +# + +import command +from entry import Entry +from blob import Entry_blob +import tools + +class Entry_u_boot_spl_bss_pad(Entry_blob): + def __init__(self, image, etype, node): + Entry_blob.__init__(self, image, etype, node) + + def ObtainContents(self): + fname = tools.GetInputFilename('spl/u-boot-spl') + args = [['nm', fname], ['grep', '__bss_size']] + out = command.RunPipe(args, capture=True).stdout.splitlines() + bss_size = int(out[0].split()[0], 16) + self.data = chr(0) * bss_size + self.contents_size = bss_size diff --git a/tools/binman/etype/u_boot_spl_with_ucode_ptr.py b/tools/binman/etype/u_boot_spl_with_ucode_ptr.py new file mode 100644 index 0000000..764c282 --- /dev/null +++ b/tools/binman/etype/u_boot_spl_with_ucode_ptr.py @@ -0,0 +1,28 @@ +# Copyright (c) 2016 Google, Inc +# Written by Simon Glass +# +# SPDX-License-Identifier: GPL-2.0+ +# +# Entry-type module for an SPL binary with an embedded microcode pointer +# + +import struct + +import command +from entry import Entry +from blob import Entry_blob +from u_boot_with_ucode_ptr import Entry_u_boot_with_ucode_ptr +import tools + +class Entry_u_boot_spl_with_ucode_ptr(Entry_u_boot_with_ucode_ptr): + """U-Boot SPL with embedded microcode pointer + + See Entry_u_boot_ucode for full details of the entries involved in this + process. + """ + def __init__(self, image, etype, node): + Entry_blob.__init__(self, image, etype, node) + self.elf_fname = 'spl/u-boot-spl' + + def GetDefaultFilename(self): + return 'spl/u-boot-spl.bin' diff --git a/tools/binman/etype/x86_start16_spl.py b/tools/binman/etype/x86_start16_spl.py new file mode 100644 index 0000000..3679a43 --- /dev/null +++ b/tools/binman/etype/x86_start16_spl.py @@ -0,0 +1,17 @@ +# Copyright (c) 2016 Google, Inc +# Written by Simon Glass +# +# SPDX-License-Identifier: GPL-2.0+ +# +# Entry-type module for the 16-bit x86 start-up code for U-Boot SPL +# + +from entry import Entry +from blob import Entry_blob + +class Entry_x86_start16_spl(Entry_blob): + def __init__(self, image, etype, node): + Entry_blob.__init__(self, image, etype, node) + + def GetDefaultFilename(self): + return 'spl/u-boot-x86-16bit-spl.bin' diff --git a/tools/binman/func_test.py b/tools/binman/func_test.py index 8dd118b..cb8bd31 100644 --- a/tools/binman/func_test.py +++ b/tools/binman/func_test.py @@ -714,7 +714,95 @@ class TestFunctional(unittest.TestCase): self.assertEqual('nodtb with microcode' + pos_and_size + ' somewhere in here', first) + def testPackUbootSingleMicrocode(self): + """Test that x86 microcode can be handled correctly with fdt_normal. + """ + self._RunPackUbootSingleMicrocode(False) + + def testPackUbootSingleMicrocodeFallback(self): + """Test that x86 microcode can be handled correctly with fdt_fallback. + + This only supports collating the microcode. + """ + try: + old_val = fdt_select.UseFallback(True) + self._RunPackUbootSingleMicrocode(True) + finally: + fdt_select.UseFallback(old_val) + def testUBootImg(self): """Test that u-boot.img can be put in a file""" data = self._DoReadFile('36_u_boot_img.dts') self.assertEqual(U_BOOT_IMG_DATA, data) + + def testNoMicrocode(self): + """Test that a missing microcode region is detected""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('37_x86_no_ucode.dts', True) + self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode " + "node found in ", str(e.exception)) + + def testMicrocodeWithoutNode(self): + """Test that a missing u-boot-dtb-with-ucode node is detected""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('38_x86_ucode_missing_node.dts', True) + self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find " + "microcode region u-boot-dtb-with-ucode", str(e.exception)) + + def testMicrocodeWithoutNode2(self): + """Test that a missing u-boot-ucode node is detected""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('39_x86_ucode_missing_node2.dts', True) + self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find " + "microcode region u-boot-ucode", str(e.exception)) + + def testMicrocodeWithoutPtrInElf(self): + """Test that a U-Boot binary without the microcode symbol is detected""" + # ELF file without a '_dt_ucode_base_size' symbol + if not fdt_select.have_libfdt: + return + try: + with open(self.TestFile('u_boot_no_ucode_ptr')) as fd: + TestFunctional._MakeInputFile('u-boot', fd.read()) + + with self.assertRaises(ValueError) as e: + self._RunPackUbootSingleMicrocode(False) + self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate " + "_dt_ucode_base_size symbol in u-boot", str(e.exception)) + + finally: + # Put the original file back + with open(self.TestFile('u_boot_ucode_ptr')) as fd: + TestFunctional._MakeInputFile('u-boot', fd.read()) + + def testMicrocodeNotInImage(self): + """Test that microcode must be placed within the image""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('40_x86_ucode_not_in_image.dts', True) + self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode " + "pointer _dt_ucode_base_size at fffffe14 is outside the " + "image ranging from 00000000 to 0000002e", str(e.exception)) + + def testWithoutMicrocode(self): + """Test that we can cope with an image without microcode (e.g. qemu)""" + with open(self.TestFile('u_boot_no_ucode_ptr')) as fd: + TestFunctional._MakeInputFile('u-boot', fd.read()) + data, dtb = self._DoReadFileDtb('44_x86_optional_ucode.dts', True) + + # Now check the device tree has no microcode + self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)]) + second = data[len(U_BOOT_NODTB_DATA):] + + fdt_len = self.GetFdtLen(second) + self.assertEqual(dtb, second[:fdt_len]) + + used_len = len(U_BOOT_NODTB_DATA) + fdt_len + third = data[used_len:] + self.assertEqual(chr(0) * (0x200 - used_len), third) + + def testUnknownPosSize(self): + """Test that microcode must be placed within the image""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('41_unknown_pos_size.dts', True) + self.assertIn("Image '/binman': Unable to set pos/size for unknown " + "entry 'invalid-entry'", str(e.exception)) diff --git a/tools/binman/test/37_x86_no_ucode.dts b/tools/binman/test/37_x86_no_ucode.dts new file mode 100644 index 0000000..9e12156 --- /dev/null +++ b/tools/binman/test/37_x86_no_ucode.dts @@ -0,0 +1,20 @@ +/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 { + }; + }; +}; diff --git a/tools/binman/test/38_x86_ucode_missing_node.dts b/tools/binman/test/38_x86_ucode_missing_node.dts new file mode 100644 index 0000000..d6cf0d8 --- /dev/null +++ b/tools/binman/test/38_x86_ucode_missing_node.dts @@ -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-ucode { + }; + }; + + microcode { + update@0 { + data = <0x12345678 0x12345679>; + }; + update@1 { + data = <0xabcd0000 0x78235609>; + }; + }; +}; diff --git a/tools/binman/test/39_x86_ucode_missing_node2.dts b/tools/binman/test/39_x86_ucode_missing_node2.dts new file mode 100644 index 0000000..b7e26c5 --- /dev/null +++ b/tools/binman/test/39_x86_ucode_missing_node2.dts @@ -0,0 +1,23 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-pos; + end-at-4gb; + size = <0x200>; + u-boot-with-ucode-ptr { + }; + }; + + microcode { + update@0 { + data = <0x12345678 0x12345679>; + }; + update@1 { + data = <0xabcd0000 0x78235609>; + }; + }; +}; diff --git a/tools/binman/test/40_x86_ucode_not_in_image.dts b/tools/binman/test/40_x86_ucode_not_in_image.dts new file mode 100644 index 0000000..67d17d3 --- /dev/null +++ b/tools/binman/test/40_x86_ucode_not_in_image.dts @@ -0,0 +1,28 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-pos; + 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>; + }; + }; +}; diff --git a/tools/binman/test/41_unknown_pos_size.dts b/tools/binman/test/41_unknown_pos_size.dts new file mode 100644 index 0000000..a8e7d8a --- /dev/null +++ b/tools/binman/test/41_unknown_pos_size.dts @@ -0,0 +1,11 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + _testing { + }; + }; +}; diff --git a/tools/binman/test/44_x86_optional_ucode.dts b/tools/binman/test/44_x86_optional_ucode.dts new file mode 100644 index 0000000..abe1322 --- /dev/null +++ b/tools/binman/test/44_x86_optional_ucode.dts @@ -0,0 +1,30 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-pos; + end-at-4gb; + size = <0x200>; + u-boot-with-ucode-ptr { + optional-ucode; + }; + + u-boot-dtb-with-ucode { + }; + + u-boot-ucode { + }; + }; + + microcode { + update@0 { + data = <0x12345678 0x12345679>; + }; + update@1 { + data = <0xabcd0000 0x78235609>; + }; + }; +}; diff --git a/tools/binman/test/u_boot_no_ucode_ptr b/tools/binman/test/u_boot_no_ucode_ptr new file mode 100755 index 0000000..f72462f Binary files /dev/null and b/tools/binman/test/u_boot_no_ucode_ptr differ diff --git a/tools/binman/test/u_boot_no_ucode_ptr.c b/tools/binman/test/u_boot_no_ucode_ptr.c new file mode 100644 index 0000000..a17bb4c --- /dev/null +++ b/tools/binman/test/u_boot_no_ucode_ptr.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Simple program to create a bad _dt_ucode_base_size symbol to create an + * error when it is used. This is used by binman tests. + * + * Build with: + * cc -march=i386 -m32 -o u_boot_no_ucode_ptr -T u_boot_ucode_ptr.lds \ + -nostdlib u_boot_no_ucode_ptr.c + */ + +static unsigned long not__dt_ucode_base_size[2] + __attribute__((section(".ucode"))) = {1, 2}; -- cgit v0.10.2