binman: Support x86 microcode in TPL
authorSimon Glass <sjg@chromium.org>
Fri, 14 Sep 2018 10:57:32 +0000 (04:57 -0600)
committerSimon Glass <sjg@chromium.org>
Sat, 29 Sep 2018 17:49:35 +0000 (11:49 -0600)
When TPL is used on x86 we may want to program the microcode (at least for
the first CPU) early in boot. Add support for this by refactoring the
existing code to be more generic.

Signed-off-by: Simon Glass <sjg@chromium.org>
tools/binman/README.entries
tools/binman/etype/u_boot_dtb_with_ucode.py
tools/binman/etype/u_boot_spl_with_ucode_ptr.py
tools/binman/etype/u_boot_tpl_dtb_with_ucode.py [new file with mode: 0644]
tools/binman/etype/u_boot_tpl_with_ucode_ptr.py [new file with mode: 0644]
tools/binman/etype/u_boot_ucode.py
tools/binman/etype/u_boot_with_ucode_ptr.py
tools/binman/ftest.py
tools/binman/test/93_x86_tpl_ucode.dts [new file with mode: 0644]

index 3afc560052ac7d953570c791c7487437aeeb768b..4dd67d64fa7e4434ea8db8f4e7b9db226f8e37ce 100644 (file)
@@ -462,6 +462,8 @@ both SPL and the device tree).
 Entry: u-boot-spl-with-ucode-ptr: U-Boot SPL with embedded microcode pointer
 ----------------------------------------------------------------------------
 
+This is used when SPL must set up the microcode for U-Boot.
+
 See Entry_u_boot_ucode for full details of the entries involved in this
 process.
 
@@ -503,6 +505,24 @@ to activate.
 
 
 
+Entry: u-boot-tpl-dtb-with-ucode: U-Boot TPL with embedded microcode pointer
+----------------------------------------------------------------------------
+
+This is used when TPL must set up the microcode for U-Boot.
+
+See Entry_u_boot_ucode for full details of the entries involved in this
+process.
+
+
+
+Entry: u-boot-tpl-with-ucode-ptr: U-Boot TPL with embedded microcode pointer
+----------------------------------------------------------------------------
+
+See Entry_u_boot_ucode for full details of the entries involved in this
+process.
+
+
+
 Entry: u-boot-ucode: U-Boot microcode block
 -------------------------------------------
 
index 73f5fbf903302ab83014abc9baa56a4c2184fafc..444c51b8b726f831dde1c1f59d6b1319fb8a0ba7 100644 (file)
@@ -43,6 +43,9 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob_dtb):
         # If the section does not need microcode, there is nothing to do
         ucode_dest_entry = self.section.FindEntryType(
             'u-boot-spl-with-ucode-ptr')
+        if not ucode_dest_entry or not ucode_dest_entry.target_offset:
+            ucode_dest_entry = self.section.FindEntryType(
+                'u-boot-tpl-with-ucode-ptr')
         if not ucode_dest_entry or not ucode_dest_entry.target_offset:
             ucode_dest_entry = self.section.FindEntryType(
                 'u-boot-with-ucode-ptr')
@@ -70,14 +73,14 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob_dtb):
     def ObtainContents(self):
         # Call the base class just in case it does something important.
         Entry_blob_dtb.ObtainContents(self)
-        self._pathname = state.GetFdtPath(self._filename)
-        self.ReadBlobContents()
-        if self.ucode:
+        if self.ucode and not self.collate:
             for node in self.ucode.subnodes:
                 data_prop = node.props.get('data')
-                if data_prop and not self.collate:
+                if data_prop:
                     # Find the offset in the device tree of the ucode data
                     self.ucode_offset = data_prop.GetOffset() + 12
                     self.ucode_size = len(data_prop.bytes)
-        self.ready = True
-        return True
+                    self.ready = True
+        else:
+            self.ready = True
+        return self.ready
index 0dfe268a568acd37dd1f67d0e9dbf55d988baf6a..b650cf0146c8aac16d1e6ddb1d4a37ed81dcd69f 100644 (file)
@@ -16,6 +16,8 @@ import tools
 class Entry_u_boot_spl_with_ucode_ptr(Entry_u_boot_with_ucode_ptr):
     """U-Boot SPL with embedded microcode pointer
 
+    This is used when SPL must set up the microcode for U-Boot.
+
     See Entry_u_boot_ucode for full details of the entries involved in this
     process.
     """
diff --git a/tools/binman/etype/u_boot_tpl_dtb_with_ucode.py b/tools/binman/etype/u_boot_tpl_dtb_with_ucode.py
new file mode 100644 (file)
index 0000000..71e04fc
--- /dev/null
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for U-Boot device tree with the microcode removed
+#
+
+import control
+from entry import Entry
+from u_boot_dtb_with_ucode import Entry_u_boot_dtb_with_ucode
+import tools
+
+class Entry_u_boot_tpl_dtb_with_ucode(Entry_u_boot_dtb_with_ucode):
+    """U-Boot TPL with embedded microcode pointer
+
+    This is used when TPL must set up the microcode for U-Boot.
+
+    See Entry_u_boot_ucode for full details of the entries involved in this
+    process.
+    """
+    def __init__(self, section, etype, node):
+        Entry_u_boot_dtb_with_ucode.__init__(self, section, etype, node)
+
+    def GetDefaultFilename(self):
+        return 'tpl/u-boot-tpl.dtb'
diff --git a/tools/binman/etype/u_boot_tpl_with_ucode_ptr.py b/tools/binman/etype/u_boot_tpl_with_ucode_ptr.py
new file mode 100644 (file)
index 0000000..8d94dde
--- /dev/null
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for an TPL 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_tpl_with_ucode_ptr(Entry_u_boot_with_ucode_ptr):
+    """U-Boot TPL with embedded microcode pointer
+
+    See Entry_u_boot_ucode for full details of the entries involved in this
+    process.
+    """
+    def __init__(self, section, etype, node):
+        Entry_u_boot_with_ucode_ptr.__init__(self, section, etype, node)
+        self.elf_fname = 'tpl/u-boot-tpl'
+
+    def GetDefaultFilename(self):
+        return 'tpl/u-boot-tpl-nodtb.bin'
index 6acf94d8cbc557ae0136c1157c518eb1408bf903..a00e530295b6323b083c3b8e78635db9ee037c4f 100644 (file)
@@ -62,19 +62,24 @@ class Entry_u_boot_ucode(Entry_blob):
 
     def ObtainContents(self):
         # If the section does not need microcode, there is nothing to do
-        ucode_dest_entry = self.section.FindEntryType('u-boot-with-ucode-ptr')
-        ucode_dest_entry_spl = self.section.FindEntryType(
-            'u-boot-spl-with-ucode-ptr')
-        if ((not ucode_dest_entry or not ucode_dest_entry.target_offset) and
-            (not ucode_dest_entry_spl or not ucode_dest_entry_spl.target_offset)):
+        found = False
+        for suffix in ['', '-spl', '-tpl']:
+            name = 'u-boot%s-with-ucode-ptr' % suffix
+            entry = self.section.FindEntryType(name)
+            if entry and entry.target_offset:
+                found = True
+        if not found:
             self.data = ''
             return True
-
         # Get the microcode from the device tree entry. If it is not available
         # yet, return False so we will be called later. If the section simply
         # doesn't exist, then we may as well return True, since we are going to
         # get an error anyway.
-        fdt_entry = self.section.FindEntryType('u-boot-dtb-with-ucode')
+        for suffix in ['', '-spl', '-tpl']:
+            name = 'u-boot%s-dtb-with-ucode' % suffix
+            fdt_entry = self.section.FindEntryType(name)
+            if fdt_entry:
+                break
         if not fdt_entry:
             return True
         if not fdt_entry.ready:
@@ -86,12 +91,9 @@ class Entry_u_boot_ucode(Entry_blob):
             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 = tools.GetOutputFilename('u-boot-ucode.bin')
+        tools.WriteFile(self._pathname, fdt_entry.ucode_data)
 
-        self._pathname = fname
         self.ReadBlobContents()
 
         return True
index c850b59a1e1fe98b38239d7a530c2d9f24b53734..01f3513e7d3eb5c47feee3c6d7d3734e6b296c93 100644 (file)
@@ -74,13 +74,16 @@ class Entry_u_boot_with_ucode_ptr(Entry_blob):
 
         # 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.
+        # 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 or not dtb_entry.ready:
+            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
index c46a065382703d5546f06834b7a1b07755a9b9dd..f8faef189352d418478f1827673109e07de8e893 100644 (file)
@@ -44,6 +44,7 @@ X86_START16_SPL_DATA  = 'start16spl'
 X86_START16_TPL_DATA  = 'start16tpl'
 U_BOOT_NODTB_DATA     = 'nodtb with microcode pointer somewhere in here'
 U_BOOT_SPL_NODTB_DATA = 'splnodtb with microcode pointer somewhere in here'
+U_BOOT_TPL_NODTB_DATA = 'tplnodtb with microcode pointer somewhere in here'
 FSP_DATA              = 'fsp'
 CMC_DATA              = 'cmc'
 VBT_DATA              = 'vbt'
@@ -103,6 +104,8 @@ class TestFunctional(unittest.TestCase):
         TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
         TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
                                       U_BOOT_SPL_NODTB_DATA)
+        TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
+                                      U_BOOT_TPL_NODTB_DATA)
         TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
         TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
         TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
@@ -1644,6 +1647,22 @@ class TestFunctional(unittest.TestCase):
         m.update(16 * 'a')
         self.assertEqual(m.digest(), ''.join(hash_node.value))
 
+    def testPackUBootTplMicrocode(self):
+        """Test that x86 microcode can be handled correctly in TPL
+
+        We expect to see the following in the image, in order:
+            u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
+                place
+            u-boot-tpl.dtb with the microcode removed
+            the microcode
+        """
+        with open(self.TestFile('u_boot_ucode_ptr')) as fd:
+            TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
+        first, pos_and_size = self._RunMicrocodeTest('93_x86_tpl_ucode.dts',
+                                                     U_BOOT_TPL_NODTB_DATA)
+        self.assertEqual('tplnodtb with microc' + pos_and_size +
+                         'ter somewhere in here', first)
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/93_x86_tpl_ucode.dts b/tools/binman/test/93_x86_tpl_ucode.dts
new file mode 100644 (file)
index 0000000..d7ed9fc
--- /dev/null
@@ -0,0 +1,29 @@
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               sort-by-offset;
+               end-at-4gb;
+               size = <0x200>;
+               u-boot-tpl-with-ucode-ptr {
+               };
+
+               u-boot-tpl-dtb-with-ucode {
+               };
+
+               u-boot-ucode {
+               };
+       };
+
+       microcode {
+               update@0 {
+                       data = <0x12345678 0x12345679>;
+               };
+               update@1 {
+                       data = <0xabcd0000 0x78235609>;
+               };
+       };
+};