Browse Source

Relocate FTPR to the top of the ME region

Nicola Corna 7 years ago
parent
commit
61f85bad19
2 changed files with 76 additions and 1 deletions
  1. 2 1
      README.md
  2. 74 0
      me_cleaner.py

+ 2 - 1
README.md

@@ -12,7 +12,8 @@ Currently this tool:
  * Removes any partition except for the fundamental one (FTPR)
  * Removes the EFFS presence flag
  * Corrects the FPT checksum
- * Removes any non-essential LZMA or Huffman compressed module (pre-Skylake only)
+ * Removes any non-essential LZMA or Huffman compressed module from the FTPR partition (pre-Skylake only)
+ * Relocates the remaining parts of the FTPR partition to the top of the ME region (pre-Skylake only)
  * Checks the validity of the RSA signature of the FTPR partition
 
 Don't forget to power cycle your PC after flashing the modified ME/TXE image

+ 74 - 0
me_cleaner.py

@@ -21,6 +21,7 @@ import hashlib
 from struct import pack, unpack
 
 
+new_ftpr_offset = 0x1000
 unremovable_modules = ("BUP", "ROMP")
 
 
@@ -152,6 +153,74 @@ def check_partition_signature(f, offset):
     return "{:#x}".format(decrypted_sig).endswith(sha256.hexdigest())   # FIXME
 
 
+def move_range(f, offset_from, size, offset_to, fill):
+    for i in range(0, size, 4096):
+        f.seek(offset_from + i, 0)
+        block = f.read(4096 if size - i >= 4096 else size - i)
+        f.seek(offset_from + i, 0)
+        f.write(fill * 4096 if size - i >= 4096 else fill * (size - i))
+        f.seek(offset_to + i, 0)
+        f.write(block)
+
+
+def relocate_partition(f, me_start, partition_header_offset, new_offset,
+                       mod_headers):
+    f.seek(partition_header_offset)
+    name = f.read(4).rstrip(b"\x00").decode("ascii")
+    f.seek(partition_header_offset + 0x8)
+    old_offset, partition_size = unpack("<II", f.read(0x8))
+    old_offset += me_start
+    offset_diff = new_offset - old_offset
+    print("Relocating {} to {:#x} - {:#x}..."
+          .format(name, new_offset, new_offset + partition_size))
+
+    print(" Adjusting FPT entry...")
+    f.seek(partition_header_offset + 0x8)
+    f.write(pack("<I", new_offset - me_start))
+
+    llut_start = 0
+    for mod_header in mod_headers:
+        if (unpack("<I", mod_header[0x50:0x54])[0] >> 4) & 7 == 0x01:
+            llut_start = unpack("<I", mod_header[0x38:0x3C])[0] + old_offset
+            break
+
+    if llut_start != 0:
+        f.seek(llut_start, 0)
+        if f.read(4) == b"LLUT":
+            print(" Adjusting LUT start offset...")
+            f.seek(llut_start + 0x0c, 0)
+            old_lut_offset = unpack("<I", f.read(4))[0]
+            f.seek(llut_start + 0x0c, 0)
+            f.write(pack("<I", old_lut_offset + offset_diff))
+
+            print(" Adjusting Huffman start offset...")
+            f.seek(llut_start + 0x14, 0)
+            old_huff_offset = unpack("<I", f.read(4))[0]
+            f.seek(llut_start + 0x14, 0)
+            f.write(pack("<I", old_huff_offset + offset_diff))
+
+            print(" Adjusting chunks offsets...")
+            f.seek(llut_start + 0x4, 0)
+            chunk_count = unpack("<I", f.read(4))[0]
+            f.seek(llut_start + 0x40, 0)
+            chunks = bytearray(chunk_count * 4)
+            f.readinto(chunks)
+            for i in range(0, chunk_count * 4, 4):
+                if chunks[i + 3] != 0x80:
+                    chunks[i:i + 3] = \
+                        pack("<I", unpack("<I", chunks[i:i + 3] +
+                             b"\x00")[0] + offset_diff)[0:3]
+            f.seek(llut_start + 0x40, 0)
+            f.write(chunks)
+        else:
+            sys.exit("Huffman modules present but no LLUT found!")
+    else:
+        print(" No Huffman modules found")
+
+    print(" Moving data...")
+    move_range(f, old_offset, partition_size, new_offset, b"\xff")
+
+
 if len(sys.argv) != 2 or sys.argv[1] == "-h" or sys.argv[1] == "--help":
     print("Usage: \n"
           " me_cleaner.py me_or_txe_image.bin\n"
@@ -291,6 +360,11 @@ else:
 
                     if all(mod_h.startswith(b"$MME") for mod_h in mod_headers):
                         remove_modules(f, mod_headers, ftpr_offset)
+
+                        new_ftpr_offset += me_start
+                        relocate_partition(f, me_start, me_start + 0x30,
+                                           new_ftpr_offset, mod_headers)
+                        ftpr_offset = new_ftpr_offset
                     else:
                         print("Found less modules than expected in the FTPR "
                               "partition; skipping modules removal")