<p>Jean Lucas has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/21312">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">util/me_cleaner: Merge upstream, add HAP/AltMeDisable menu option<br><br>Update me_cleaner to commit 72fff7a which includes the HAP/AltMeDisable<br>bit flipping function, and add a menu option to only flip this bit while<br>leaving the rest of the Intel ME/TXT firmware intact. Miscellaneous<br>language cleanup in the Kconfig as well.<br><br>Signed-off-by: Jean Lucas <jean@4ray.co><br><br>Change-Id: I0ebc5def2b9c01b2cc75f5b1541911a05f95c1ba<br>---<br>M src/southbridge/intel/common/firmware/Kconfig<br>M src/southbridge/intel/common/firmware/Makefile.inc<br>M util/me_cleaner/README.md<br>M util/me_cleaner/me_cleaner.py<br>4 files changed, 164 insertions(+), 107 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/12/21312/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/src/southbridge/intel/common/firmware/Kconfig b/src/southbridge/intel/common/firmware/Kconfig<br>index 6d33711..2aed690 100644<br>--- a/src/southbridge/intel/common/firmware/Kconfig<br>+++ b/src/southbridge/intel/common/firmware/Kconfig<br>@@ -45,7 +45,7 @@<br>       depends on HAVE_IFD_BIN<br>       help<br>    The Intel processor in the selected system requires a special firmware<br>-       for an integrated controller.  This might be called the Management<br>+   for an integrated controller. This might be called the Management<br>     Engine (ME), the Trusted Execution Engine (TXE) or something else<br>     depending on the chip. This firmware might or might not be available<br>          in coreboot's 3rdparty/blobs repository. If it is not and if you don't<br>@@ -68,51 +68,85 @@<br>                 SOC_INTEL_BAYTRAIL || SOC_INTEL_BRASWELL)<br>     help<br>    Verify the integrity of the supplied Intel ME/TXE firmware before<br>-    proceeding with the build, in order to prevent an accidental loading<br>-         of a corrupted ME/TXE image.<br>+         proceeding with the build, in order to prevent accidental loading of<br>+         a corrupted ME/TXE image.<br> <br> config USE_ME_CLEANER<br>-       bool "Strip down the Intel ME/TXE firmware"<br>+        bool "Strip down Intel ME/TXE firmware and enable HAP/AltMeDisable bit in IFD"<br>      depends on HAVE_ME_BIN && (NORTHBRIDGE_INTEL_SANDYBRIDGE || \<br>                 NORTHBRIDGE_INTEL_IVYBRIDGE || NORTHBRIDGE_INTEL_HASWELL || \<br>                 SOC_INTEL_BROADWELL || SOC_INTEL_SKYLAKE || \<br>                 SOC_INTEL_BAYTRAIL || SOC_INTEL_BRASWELL)<br>     help<br>-   Use me_cleaner to remove all the non-fundamental code from the Intel<br>-         ME/TXE firmware.<br>-     The resulting Intel ME/TXE firmware will have only the code<br>-          responsible for the very basic hardware initialization, leaving the<br>-          ME/TXE subsystem essentially in a disabled state.<br>+    Use me_cleaner to remove all non-fundamental code from the Intel ME/TXT<br>+      firmware.<br>+<br>+         The resulting Intel ME/TXE firmware will only have the code responsible<br>+      for very basic hardware initialization, essentially leaving the ME/TXT<br>+       subsystem in a disabled state.<br> <br>     Don't flash a modified ME/TXE firmware and a new coreboot image at the<br>    same time, test them in two different steps.<br> <br>-      WARNING: this tool isn't based on any official Intel documentation but<br>-            only on reverse engineering and trial & error.<br>+          WARNING: This tool isn't based on any official Intel documentation, but<br>+                   on reverse engineering and trial & error.<br> <br>     See the project's page<br>-    https://github.com/corna/me_cleaner<br>+           https://github.com/corna/me_cleaner<br>         or the wiki<br>-           https://github.com/corna/me_cleaner/wiki/How-to-apply-me_cleaner<br>-     https://github.com/corna/me_cleaner/wiki/How-does-it-work%3F<br>-         https://github.com/corna/me_cleaner/wiki/me_cleaner-status<br>-          for more info about this tool<br>+          https://github.com/corna/me_cleaner/wiki/How-to-apply-me_cleaner<br>+     https://github.com/corna/me_cleaner/wiki/How-does-it-work%3F<br>+         https://github.com/corna/me_cleaner/wiki/me_cleaner-status<br>+         for more info about this tool.<br> <br>     If unsure, say N.<br> <br> comment "Please test the modified ME/TXE firmware and coreboot in two steps"<br>       depends on USE_ME_CLEANER<br> <br>+config USE_ME_CLEANER_BIT_FLIP<br>+        bool "Only enable HAP/AltMeDisable bit in IFD"<br>+     depends on HAVE_ME_BIN && (NORTHBRIDGE_INTEL_SANDYBRIDGE || \<br>+                NORTHBRIDGE_INTEL_IVYBRIDGE || NORTHBRIDGE_INTEL_HASWELL || \<br>+                SOC_INTEL_BROADWELL || SOC_INTEL_SKYLAKE || \<br>+                SOC_INTEL_BAYTRAIL || SOC_INTEL_BRASWELL) && !USE_ME_CLEANER<br>+ help<br>+   Use me_cleaner to only enable the HAP (ME >= 11) or AltMeDisable<br>+          (ME < 11) bit in the flash descriptor, which should completely disable<br>+    the Intel ME after it initializes.<br>+<br>+        Enabling this option will leave the Intel ME/TXT firmware code intact.<br>+<br>+    Don't flash a modified image and a new coreboot image at the same time,<br>+          test them in two different steps.<br>+<br>+         WARNING: This tool isn't based on any official Intel documentation, but<br>+                   on reverse engineering and trial & error.<br>+<br>+    See the project's page<br>+     https://github.com/corna/me_cleaner<br>+        or the wiki<br>+            https://github.com/corna/me_cleaner/wiki/How-to-apply-me_cleaner<br>+     https://github.com/corna/me_cleaner/wiki/How-does-it-work%3F<br>+         https://github.com/corna/me_cleaner/wiki/me_cleaner-status<br>+         for more info about this tool.<br>+<br>+    If unsure, say N.<br>+<br>+comment "Please test the modified image and coreboot in two steps"<br>+        depends on USE_ME_CLEANER_BIT_FLIP<br>+<br> config HAVE_GBE_BIN<br>-  bool "Add gigabit ethernet firmware"<br>+       bool "Add Gigabit Ethernet firmware"<br>        depends on HAVE_IFD_BIN<br>       help<br>-   The integrated gigabit ethernet controller needs a firmware file.<br>+    The integrated Gigabit Ethernet controller needs a firmware file.<br>+<br>          Select this if you are going to use the PCH integrated controller<br>     and have the firmware.<br> <br> config GBE_BIN_PATH<br>-    string "Path to gigabit ethernet firmware"<br>+ string "Path to Gigabit Ethernet firmware"<br>  depends on HAVE_GBE_BIN<br>       default "3rdparty/blobs/mainboard/$(MAINBOARDDIR)/gbe.bin"<br> <br>@@ -177,8 +211,8 @@<br>  default ""<br>  help<br>    The Gigabit Ethernet ROM region is used when an Intel NIC is built into<br>-      the Southbridge/SOC and the platform uses this device instead of an external<br>-         PCIe NIC.  It will be located between the ME/TXE and the BIOS region.<br>+        the southbridge/SoC and the platform uses this device instead of an external<br>+         PCIe NIC. It will be located between the ME/TXE and the BIOS region.<br> <br>       Leave this empty if you're unsure.<br> <br>diff --git a/src/southbridge/intel/common/firmware/Makefile.inc b/src/southbridge/intel/common/firmware/Makefile.inc<br>index d6e6296..a20acce 100644<br>--- a/src/southbridge/intel/common/firmware/Makefile.inc<br>+++ b/src/southbridge/intel/common/firmware/Makefile.inc<br>@@ -66,6 +66,11 @@<br>      util/me_cleaner/me_cleaner.py $(obj)/coreboot.pre > \<br>              $(obj)/me_cleaner.log<br> endif<br>+ifeq ($(CONFIG_USE_ME_CLEANER_BIT_FLIP),y)<br>+   printf "    ME_CLEANER coreboot.pre\n"<br>+     util/me_cleaner/me_cleaner.py -s $(obj)/coreboot.pre > \<br>+          $(obj)/me_cleaner.log<br>+endif<br> ifeq ($(CONFIG_HAVE_GBE_BIN),y)<br>       printf "    IFDTOOL    gbe.bin -> coreboot.pre\n"<br>        $(objutil)/ifdtool/ifdtool \<br>diff --git a/util/me_cleaner/README.md b/util/me_cleaner/README.md<br>index 72c1598..a8bee6d 100644<br>--- a/util/me_cleaner/README.md<br>+++ b/util/me_cleaner/README.md<br>@@ -1,4 +1,4 @@<br>-# me_cleaner<br>+# me_cleaner [![Donation](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=B5HCXCLZVCVZ8)<br> <br> Intel ME is a coprocessor integrated in all post-2006 Intel boards, for which<br> this [Libreboot page](https://libreboot.org/faq.html#intelme) has an excellent<br>diff --git a/util/me_cleaner/me_cleaner.py b/util/me_cleaner/me_cleaner.py<br>index e8a89cc..a415f2b 100755<br>--- a/util/me_cleaner/me_cleaner.py<br>+++ b/util/me_cleaner/me_cleaner.py<br>@@ -74,7 +74,7 @@<br>            offset_to + size <= self.region_end:<br>             for i in range(0, size, 4096):<br>                 self.f.seek(offset_from + i, 0)<br>-                block = self.f.read(4096 if size - i >= 4096 else size - i)<br>+                block = self.f.read(min(size - i, 4096))<br>                 self.f.seek(offset_from + i, 0)<br>                 self.f.write(fill * len(block))<br>                 self.f.seek(offset_to + i, 0)<br>@@ -86,7 +86,7 @@<br>         self.f.seek(self.region_start)<br>         copyf = open(filename, "w+b")<br>         for i in range(0, size, 4096):<br>-            copyf.write(self.f.read(4096 if size - i >= 4096 else size - i))<br>+            copyf.write(self.f.read(min(size - i, 4096)))<br>         return copyf<br> <br> <br>@@ -437,9 +437,13 @@<br>                                      "as possible from Intel ME/TXE firmware "<br>                                      "images")<br>     parser.add_argument("file", help="ME/TXE image or full dump")<br>-    parser.add_argument("-O", "--output", help="save the modified image in a "<br>-                        "separate file, instead of modifying the original "<br>-                        "file")<br>+    parser.add_argument("-O", "--output", metavar='output_file', help="save "<br>+                        "the modified image in a separate file, instead of "<br>+                        "modifying the original file")<br>+    parser.add_argument("-s", "--soft-disable", help="instead of modifying "<br>+                        "the Intel ME firmware, just disable it by setting "<br>+                        "the MeAltDisable bit or the HAP bit (requires a full "<br>+                        "dump)", action="store_true")<br>     parser.add_argument("-r", "--relocate", help="relocate the FTPR partition "<br>                         "to the top of the ME region to save even more space",<br>                         action="store_true")<br>@@ -455,21 +459,23 @@<br>     parser.add_argument("-c", "--check", help="verify the integrity of the "<br>                         "fundamental parts of the firmware and exit",<br>                         action="store_true")<br>-    parser.add_argument("-D", "--extract-descriptor", help="extract the "<br>-                        "flash descriptor from a full dump; when used with "<br>+    parser.add_argument("-D", "--extract-descriptor",<br>+                        metavar='output_descriptor', help="extract the flash "<br>+                        "descriptor from a full dump; when used with "<br>                         "--truncate save a descriptor with adjusted regions "<br>                         "start and end")<br>-    parser.add_argument("-M", "--extract-me", help="extract the ME firmware "<br>-                        "from a full dump; when used with --truncate save a "<br>-                        "truncated ME/TXE image")<br>+    parser.add_argument("-M", "--extract-me", metavar='output_me_image',<br>+                        help="extract the ME firmware from a full dump; when "<br>+                        "used with --truncate save a truncated ME/TXE image")<br> <br>     args = parser.parse_args()<br> <br>-    if args.check:<br>-        if args.relocate:<br>-            sys.exit("-c and -r can't be used together")<br>-        elif args.truncate:<br>-            sys.exit("-c and -t can't be used together")<br>+    if args.check and (args.soft_disable or args.relocate or \<br>+       args.descriptor or args.truncate or args.output):<br>+        sys.exit("-c can't be used with -s, -r, -d, -t or -O")<br>+<br>+    if args.soft_disable and (args.relocate or args.truncate):<br>+        sys.exit("-s can't be used with -r or -t")<br> <br>     f = open(args.file, "rb" if args.check or args.output else "r+b")<br>     f.seek(0x10)<br>@@ -478,14 +484,9 @@<br>     if magic == b"$FPT":<br>         print("ME/TXE image detected")<br> <br>-        if args.descriptor:<br>-            sys.exit("-d requires a full dump")<br>-<br>-        if args.extract_descriptor:<br>-            sys.exit("-D requires a full dump")<br>-<br>-        if args.extract_me:<br>-            sys.exit("-M requires a full dump")<br>+        if args.descriptor or args.extract_descriptor or args.extract_me or \<br>+           args.soft_disable:<br>+            sys.exit("-d, -D, -M and -s require a full dump")<br> <br>         me_start = 0<br>         f.seek(0, 2)<br>@@ -501,6 +502,7 @@<br>         flmap0, flmap1 = unpack("<II", f.read(8))<br>         frba = flmap0 >> 12 & 0xff0<br>         fmba = (flmap1 & 0xff) << 4<br>+        fpsba = flmap1 >> 12 & 0xff0<br> <br>         f.seek(frba)<br>         flreg = unpack("<III", f.read(12))<br>@@ -582,74 +584,90 @@<br>     print("ME/TXE firmware version {}"<br>           .format('.'.join(str(i) for i in version)))<br> <br>+    if not args.check and args.output:<br>+        f.close()<br>+        shutil.copy(args.file, args.output)<br>+        f = open(args.output, "r+b")<br>+<br>+    mef = RegionFile(f, me_start, me_end)<br>+<br>+    if me_start > 0:<br>+        fdf = RegionFile(f, fd_start, fd_end)<br>+<br>     if not args.check:<br>-        if args.output:<br>-            f.close()<br>-            shutil.copy(args.file, args.output)<br>-            f = open(args.output, "r+b")<br>+        if not args.soft_disable:<br>+            print("Removing extra partitions...")<br>+            mef.fill_range(me_start + 0x30, ftpr_offset, b"\xff")<br>+            mef.fill_range(ftpr_offset + ftpr_lenght, me_end, b"\xff")<br> <br>-        mef = RegionFile(f, me_start, me_end)<br>+            print("Removing extra partition entries in FPT...")<br>+            mef.write_to(me_start + 0x30, ftpr_header)<br>+            mef.write_to(me_start + 0x14, pack("<I", 1))<br> <br>-        if args.descriptor or args.extract_descriptor:<br>-            fdf = RegionFile(f, fd_start, fd_end)<br>+            print("Removing EFFS presence flag...")<br>+            mef.seek(me_start + 0x24)<br>+            flags = unpack("<I", mef.read(4))[0]<br>+            flags &= ~(0x00000001)<br>+            mef.write_to(me_start + 0x24, pack("<I", flags))<br> <br>-        print("Removing extra partitions...")<br>-        mef.fill_range(me_start + 0x30, ftpr_offset, b"\xff")<br>-        mef.fill_range(ftpr_offset + ftpr_lenght, me_end, b"\xff")<br>+            if me11:<br>+                mef.seek(me_start + 0x10)<br>+                header = bytearray(mef.read(0x20))<br>+                header[0x0b] = 0x00<br>+            else:<br>+                mef.seek(me_start)<br>+                header = bytearray(mef.read(0x30))<br>+                header[0x1b] = 0x00<br>+            checksum = (0x100 - sum(header) & 0xff) & 0xff<br> <br>-        print("Removing extra partition entries in FPT...")<br>-        mef.write_to(me_start + 0x30, ftpr_header)<br>-        mef.write_to(me_start + 0x14, pack("<I", 1))<br>+            print("Correcting checksum (0x{:02x})...".format(checksum))<br>+            # The checksum is just the two's complement of the sum of the first<br>+            # 0x30 bytes in ME < 11 or bytes 0x10:0x30 in ME >= 11 (except for<br>+            # 0x1b, the checksum itself). In other words, the sum of those<br>+            # bytes must be always 0x00.<br>+            mef.write_to(me_start + 0x1b, pack("B", checksum))<br> <br>-        print("Removing EFFS presence flag...")<br>-        mef.seek(me_start + 0x24)<br>-        flags = unpack("<I", mef.read(4))[0]<br>-        flags &= ~(0x00000001)<br>-        mef.write_to(me_start + 0x24, pack("<I", flags))<br>+            print("Reading FTPR modules list...")<br>+            if me11:<br>+                end_addr, ftpr_offset = \<br>+                    check_and_remove_modules_me11(mef, me_start, me_end,<br>+                                                  ftpr_offset, ftpr_lenght,<br>+                                                  min_ftpr_offset,<br>+                                                  args.relocate,<br>+                                                  args.keep_modules)<br>+            else:<br>+                end_addr, ftpr_offset = \<br>+                    check_and_remove_modules(mef, me_start, me_end, ftpr_offset,<br>+                                             min_ftpr_offset, args.relocate,<br>+                                             args.keep_modules)<br>+<br>+            if end_addr > 0:<br>+                end_addr = (end_addr // 0x1000 + 1) * 0x1000<br>+                end_addr += spared_blocks * 0x1000<br>+<br>+                print("The ME minimum size should be {0} bytes "<br>+                      "({0:#x} bytes)".format(end_addr - me_start))<br>+<br>+                if me_start > 0:<br>+                    print("The ME region can be reduced up to:\n"<br>+                          " {:08x}:{:08x} me".format(me_start, end_addr - 1))<br>+                elif args.truncate:<br>+                    print("Truncating file at {:#x}...".format(end_addr))<br>+                    f.truncate(end_addr)<br> <br>         if me11:<br>-            mef.seek(me_start + 0x10)<br>-            header = bytearray(mef.read(0x20))<br>-            header[0x0b] = 0x00<br>+            print("Setting the HAP bit in PCHSTRP0 to disable Intel ME...")<br>+            fdf.seek(fpsba)<br>+            pchstrp0 = unpack("<I", fdf.read(4))[0]<br>+            pchstrp0 |= (1 << 16)<br>+            fdf.write_to(fpsba, pack("<I", pchstrp0))<br>         else:<br>-            mef.seek(me_start)<br>-            header = bytearray(mef.read(0x30))<br>-            header[0x1b] = 0x00<br>-        checksum = (0x100 - sum(header) & 0xff) & 0xff<br>-<br>-        print("Correcting checksum (0x{:02x})...".format(checksum))<br>-        # The checksum is just the two's complement of the sum of the first<br>-        # 0x30 bytes in ME < 11 or bytes 0x10:0x30 in ME >= 11 (except for<br>-        # 0x1b, the checksum itself). In other words, the sum of those bytes<br>-        # must be always 0x00.<br>-        mef.write_to(me_start + 0x1b, pack("B", checksum))<br>-<br>-        print("Reading FTPR modules list...")<br>-        if me11:<br>-            end_addr, ftpr_offset = \<br>-                check_and_remove_modules_me11(mef, me_start, me_end,<br>-                                              ftpr_offset, ftpr_lenght,<br>-                                              min_ftpr_offset, args.relocate,<br>-                                              args.keep_modules)<br>-        else:<br>-            end_addr, ftpr_offset = \<br>-                check_and_remove_modules(mef, me_start, me_end, ftpr_offset,<br>-                                         min_ftpr_offset, args.relocate,<br>-                                         args.keep_modules)<br>-<br>-        if end_addr > 0:<br>-            end_addr = (end_addr // 0x1000 + 1) * 0x1000<br>-            end_addr += spared_blocks * 0x1000<br>-<br>-            print("The ME minimum size should be {0} bytes "<br>-                  "({0:#x} bytes)".format(end_addr - me_start))<br>-<br>-            if me_start > 0:<br>-                print("The ME region can be reduced up to:\n"<br>-                      " {:08x}:{:08x} me".format(me_start, end_addr - 1))<br>-            elif args.truncate:<br>-                print("Truncating file at {:#x}...".format(end_addr))<br>-                f.truncate(end_addr)<br>+            print("Setting the AltMeDisable bit in PCHSTRP10 to disable Intel "<br>+                  "ME...")<br>+            fdf.seek(fpsba + 0x28)<br>+            pchstrp10 = unpack("<I", fdf.read(4))[0]<br>+            pchstrp10 |= (1 << 7)<br>+            fdf.write_to(fpsba + 0x28, pack("<I", pchstrp10))<br> <br>     if args.descriptor:<br>         print("Removing ME/TXE R/W access to the other flash regions...")<br>@@ -678,12 +696,12 @@<br>                       "isn't equal to the end address of the ME\n region: if "<br>                       "you want to recover the space from the ME region you "<br>                       "have to\n manually modify the descriptor.\n")<br>-<br>-            fdf_copy.close()<br>         else:<br>             print("Extracting the descriptor to \"{}\"..."<br>                   .format(args.extract_descriptor))<br>-            fdf.save(args.extract_descriptor, fd_end - fd_start).close()<br>+            fdf_copy = fdf.save(args.extract_descriptor, fd_end - fd_start)<br>+<br>+        fdf_copy.close()<br> <br>     if args.extract_me:<br>         if args.truncate:<br></pre><p>To view, visit <a href="https://review.coreboot.org/21312">change 21312</a>. To unsubscribe, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/21312"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I0ebc5def2b9c01b2cc75f5b1541911a05f95c1ba </div>
<div style="display:none"> Gerrit-Change-Number: 21312 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Jean Lucas <jean@4ray.co> </div>