<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>