From 5dd940a5ac6b66d7557059a915728d1676767a66 Mon Sep 17 00:00:00 2001 From: dt-zero <51839103+dt-zero@users.noreply.github.com> Date: Sat, 15 Jun 2019 00:53:51 +0200 Subject: [PATCH 1/5] Adding soft-disable support for IFWI/ME12 Based on the work of @davidmartinzeus --- me_cleaner.py | 298 +++++++++++++++++++++++++++----------------------- 1 file changed, 164 insertions(+), 134 deletions(-) diff --git a/me_cleaner.py b/me_cleaner.py index c2adf0e..cf511eb 100755 --- a/me_cleaner.py +++ b/me_cleaner.py @@ -22,6 +22,7 @@ import itertools import shutil import sys +import re from struct import pack, unpack @@ -44,6 +45,7 @@ "2011ae6df87c40fba09e3f20459b1ce0": ("ME", ("9.0.x.x", "9.1.x.x")), "e8427c5691cf8b56bc5cdd82746957ed": ("ME", ("9.5.x.x", "10.x.x.x")), "986a78e481f185f7d54e4af06eb413f6": ("ME", ("11.x.x.x",)), + "3efc26920b4bee901b624771c742887b": ("ME", ("12.x.x.x",)), "bda0b6bb8ca0bf0cac55ac4c4d55e0f2": ("TXE", ("1.x.x.x",)), "b726a2ab9cd59d4e62fe2bead7cf6997": ("TXE", ("1.x.x.x",)), "0633d7f951a3e7968ae7460861be9cfb": ("TXE", ("2.x.x.x",)), @@ -64,6 +66,13 @@ def __init__(self, f, region_start, region_end): self.region_start = region_start self.region_end = region_end + def readall(self): + currentpos = self.f.tell() + self.f.seek(self.region_start) + toret = self.f.read(self.region_end - self.region_start) + self.f.seek(currentpos) + return toret + def read(self, n): if f.tell() + n <= self.region_end: return self.f.read(n) @@ -596,19 +605,16 @@ def start_end_to_flreg(start, end): sys.exit("Unknown image") if me_start < me_end: - mef.seek(0) - if mef.read(4) == b"$FPT": - fpt_offset = 0 - else: - mef.seek(0x10) - if mef.read(4) == b"$FPT": - fpt_offset = 0x10 - else: - if me_start > 0: - sys.exit("The ME/TXE region is valid but the firmware is " - "corrupted or missing") - else: - sys.exit("Unknown error") + medata = mef.readall() + fpt_matches = list((re.compile(br'\x24\x46\x50\x54.\x00\x00\x00', re.DOTALL)).finditer(medata)) + if (len(fpt_matches) == 0): + sys.exit("$FPT not found") + + if (len(fpt_matches) > 1): + sys.exit("more than one $FPT found") + + for fpt_match in fpt_matches: + fpt_offset = fpt_match.span()[0] if gen == 1: end_addr = 0 @@ -633,13 +639,21 @@ def start_end_to_flreg(start, end): break if ftpr_header == b"": - sys.exit("FTPR header not found, this image doesn't seem to be " - "valid") + # We might be dealing with IFWI firmware, look for $CPD with FPTR + ftpr_matches = list((re.compile(br'\x24\x43\x50\x44........\x46\x54\x50\x52', re.DOTALL)).finditer(medata)) - if ftpr_header[0x0:0x4] == b"CODE": - gen = 1 + if (len(ftpr_matches) == 1): + ftpr_offset = ftpr_matches[0].span()[0] + ftpr_length = 0 # As long as we only do soft-disable on IFWI, should be okay + else: + sys.exit("FTPR header not found, this image doesn't seem to be " + "valid") + else: + if ftpr_header[0x0:0x4] == b"CODE": + gen = 1 + + ftpr_offset, ftpr_length = unpack(" me_end: - print(" {:<4} ({:^24}, 0x{:08x} total bytes): nothing to " - "remove" - .format(part_name, "no data here", part_length)) - else: - print(" {:<4} (0x{:08x} - 0x{:09x}, 0x{:08x} total bytes): " - .format(part_name, part_start, part_end, part_length), - end="") - if part_name in whitelist or (blacklist and - part_name not in blacklist): - unremovable_part_fpt += partition - if part_name != "FTPR": - extra_part_end = max(extra_part_end, part_end) - print("NOT removed") - else: - mef.fill_range(part_start, part_end, b"\xff") - print("removed") - - print("Removing partition entries in FPT...") - mef.write_to(0x30, unremovable_part_fpt) - mef.write_to(0x14, - pack("= 11 (except for - # 0x1b, the checksum itself). In other words, the sum of those - # bytes must be always 0x00. - mef.write_to(0x1b, pack("B", checksum)) - - print("Reading FTPR modules list...") - if gen == 3: - end_addr, ftpr_offset = \ - check_and_remove_modules_gen3(mef, me_end, - ftpr_offset, ftpr_length, - min_ftpr_offset, - args.relocate, - args.keep_modules) + if gen == 4: + print("Module removal is not currently supported on IFWI firmware.") else: - end_addr, ftpr_offset = \ - check_and_remove_modules(mef, me_end, ftpr_offset, - min_ftpr_offset, args.relocate, - args.keep_modules) - - if end_addr > 0: - end_addr = max(end_addr, extra_part_end) - 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)) - - if me_start > 0: - print("The ME region can be reduced up to:\n" - " {:08x}:{:08x} me" - .format(me_start, me_start + end_addr - 1)) - elif args.truncate: - print("Truncating file at {:#x}...".format(end_addr)) - f.truncate(end_addr) + print("Reading partitions list...") + unremovable_part_fpt = b"" + extra_part_end = 0 + whitelist = [] + blacklist = [] + + whitelist += unremovable_partitions + + if args.blacklist: + blacklist = args.blacklist.split(",") + elif args.whitelist: + whitelist += args.whitelist.split(",") + + for i in range(entries): + partition = partitions[i * 0x20:(i + 1) * 0x20] + flags = unpack(" me_end: + print(" {:<4} ({:^24}, 0x{:08x} total bytes): nothing to " + "remove" + .format(part_name, "no data here", part_length)) + else: + print(" {:<4} (0x{:08x} - 0x{:09x}, 0x{:08x} total bytes): " + .format(part_name, part_start, part_end, part_length), + end="") + if part_name in whitelist or (blacklist and + part_name not in blacklist): + unremovable_part_fpt += partition + if part_name != "FTPR": + extra_part_end = max(extra_part_end, part_end) + print("NOT removed") + else: + mef.fill_range(part_start, part_end, b"\xff") + print("removed") + + print("Removing partition entries in FPT...") + mef.write_to(0x30, unremovable_part_fpt) + mef.write_to(0x14, + pack("= 11 (except for + # 0x1b, the checksum itself). In other words, the sum of those + # bytes must be always 0x00. + mef.write_to(0x1b, pack("B", checksum)) + + print("Reading FTPR modules list...") + if gen == 3: + end_addr, ftpr_offset = \ + check_and_remove_modules_gen3(mef, me_end, + ftpr_offset, ftpr_length, + min_ftpr_offset, + args.relocate, + args.keep_modules) + else: + end_addr, ftpr_offset = \ + check_and_remove_modules(mef, me_end, ftpr_offset, + min_ftpr_offset, args.relocate, + args.keep_modules) + + if end_addr > 0: + end_addr = max(end_addr, extra_part_end) + 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)) + + if me_start > 0: + print("The ME region can be reduced up to:\n" + " {:08x}:{:08x} me" + .format(me_start, me_start + end_addr - 1)) + elif args.truncate: + print("Truncating file at {:#x}...".format(end_addr)) + f.truncate(end_addr) if args.soft_disable or args.soft_disable_only: if gen == 3: print("Setting the HAP bit in PCHSTRP0 to disable Intel ME...") pchstrp0 |= (1 << 16) fdf.write_to(fpsba, pack(" Date: Sat, 18 Jun 2022 04:39:30 +0200 Subject: [PATCH 2/5] added intel alderlake support --- me_cleaner.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/me_cleaner.py b/me_cleaner.py index cf511eb..596dd0c 100755 --- a/me_cleaner.py +++ b/me_cleaner.py @@ -46,6 +46,7 @@ "e8427c5691cf8b56bc5cdd82746957ed": ("ME", ("9.5.x.x", "10.x.x.x")), "986a78e481f185f7d54e4af06eb413f6": ("ME", ("11.x.x.x",)), "3efc26920b4bee901b624771c742887b": ("ME", ("12.x.x.x",)), + "8e4f834644da2bef03039d69d41ecf02": ("ME", ("14.x.x.x",)), "bda0b6bb8ca0bf0cac55ac4c4d55e0f2": ("TXE", ("1.x.x.x",)), "b726a2ab9cd59d4e62fe2bead7cf6997": ("TXE", ("1.x.x.x",)), "0633d7f951a3e7968ae7460861be9cfb": ("TXE", ("2.x.x.x",)), @@ -692,6 +693,8 @@ def start_end_to_flreg(start, end): if version[0] == 12: gen = 4 + elif version[0] == 14: + gen = 5 print("ME/TXE firmware version {} (generation {})" .format('.'.join(str(i) for i in version), gen)) @@ -743,6 +746,11 @@ def start_end_to_flreg(start, end): print("The AltMeDisable bit is " + ("SET" if pchstrp10 & 1 << 7 else "NOT SET")) elif gen == 4: + fdf.seek(fpsba + 0x70) + pchstrp28 = unpack("= 4: print("Module removal is not currently supported on IFWI firmware.") else: print("Reading partitions list...") @@ -906,6 +914,10 @@ def start_end_to_flreg(start, end): pchstrp0 |= (1 << 16) fdf.write_to(fpsba, pack(" Date: Sun, 24 Jul 2022 00:33:47 +0200 Subject: [PATCH 3/5] Added support for Tiger Lake (Intel ME 15) --- me_cleaner.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/me_cleaner.py b/me_cleaner.py index 596dd0c..6918f7a 100755 --- a/me_cleaner.py +++ b/me_cleaner.py @@ -47,6 +47,7 @@ "986a78e481f185f7d54e4af06eb413f6": ("ME", ("11.x.x.x",)), "3efc26920b4bee901b624771c742887b": ("ME", ("12.x.x.x",)), "8e4f834644da2bef03039d69d41ecf02": ("ME", ("14.x.x.x",)), + "b29411f89bf20ed177d411c46e8ec185": ("ME", ("15.x.x.x",)), "bda0b6bb8ca0bf0cac55ac4c4d55e0f2": ("TXE", ("1.x.x.x",)), "b726a2ab9cd59d4e62fe2bead7cf6997": ("TXE", ("1.x.x.x",)), "0633d7f951a3e7968ae7460861be9cfb": ("TXE", ("2.x.x.x",)), @@ -664,6 +665,12 @@ def start_end_to_flreg(start, end): num_entries = unpack("= 128: + mef.seek(ftpr_offset + 0x14) + ftpr_mn2_offset = -1 for i in range(0, num_entries): @@ -695,6 +702,8 @@ def start_end_to_flreg(start, end): gen = 4 elif version[0] == 14: gen = 5 + elif version[0] == 15: + gen = 6 print("ME/TXE firmware version {} (generation {})" .format('.'.join(str(i) for i in version), gen)) @@ -755,6 +764,11 @@ def start_end_to_flreg(start, end): pchstrp32 = unpack(" Date: Thu, 4 Aug 2022 23:02:08 +0200 Subject: [PATCH 4/5] Added support for Alder Lake (Intel ME 16) Needs testing --- me_cleaner.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/me_cleaner.py b/me_cleaner.py index 6918f7a..f4bc610 100755 --- a/me_cleaner.py +++ b/me_cleaner.py @@ -48,6 +48,7 @@ "3efc26920b4bee901b624771c742887b": ("ME", ("12.x.x.x",)), "8e4f834644da2bef03039d69d41ecf02": ("ME", ("14.x.x.x",)), "b29411f89bf20ed177d411c46e8ec185": ("ME", ("15.x.x.x",)), + "5887caf9b677601ffb257cc98a13d2a9": ("ME", ("16.x.x.x",)), "bda0b6bb8ca0bf0cac55ac4c4d55e0f2": ("TXE", ("1.x.x.x",)), "b726a2ab9cd59d4e62fe2bead7cf6997": ("TXE", ("1.x.x.x",)), "0633d7f951a3e7968ae7460861be9cfb": ("TXE", ("2.x.x.x",)), @@ -667,8 +668,11 @@ def start_end_to_flreg(start, end): mef.seek(ftpr_offset + 0x10) data = mef.read(0x18) - ## Intel ME version 15 seems to have 4 more bytes ## - if data[0] >= 128: + ## Intel ME version >= 15 seems to have 4 more bytes ## + intel_me_15 = bytes([0xDA, 0x3D, 0xC8, 0xE5]) + intel_me_16 = bytes([0x0D, 0xA2, 0xFA, 0xED]) + + if intel_me_15 in data or intel_me_16 in data: mef.seek(ftpr_offset + 0x14) ftpr_mn2_offset = -1 @@ -704,6 +708,8 @@ def start_end_to_flreg(start, end): gen = 5 elif version[0] == 15: gen = 6 + elif version[0] == 16: + gen = 7 print("ME/TXE firmware version {} (generation {})" .format('.'.join(str(i) for i in version), gen)) @@ -769,6 +775,11 @@ def start_end_to_flreg(start, end): pchstrp31 = unpack(" Date: Fri, 5 Aug 2022 14:06:31 +0200 Subject: [PATCH 5/5] Fixed possible errors for Intel ME 15 and 16 --- me_cleaner.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/me_cleaner.py b/me_cleaner.py index f4bc610..473e761 100755 --- a/me_cleaner.py +++ b/me_cleaner.py @@ -665,15 +665,17 @@ def start_end_to_flreg(start, end): gen = 3 num_entries = unpack("= 15 seems to have 4 more bytes ## - intel_me_15 = bytes([0xDA, 0x3D, 0xC8, 0xE5]) - intel_me_16 = bytes([0x0D, 0xA2, 0xFA, 0xED]) - - if intel_me_15 in data or intel_me_16 in data: + ## I think the 4 bytes have to do something with Intel ME version or date, ## + ## but not sure. ## + ## Check for 'FTPR.man' ## + if bytes([0x46, 0x54, 0x50, 0x52, 0x2E, 0x6D, 0x61, 0x6E]) == data: mef.seek(ftpr_offset + 0x14) + else: + mef.seek(ftpr_offset + 0x10) ftpr_mn2_offset = -1