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