mirror of
https://github.com/platomav/BIOSUtilities.git
synced 2025-05-14 15:15:03 -04:00
Added Apple EFI Package Extractor v2.0_a4
Added Apple EFI PBZX Extractor v1.0_a4 Updated Apple EFI Image Identifier v2.0_a4 Updated Apple EFI IM4P Splitter v3.0_a4 Updated Insyde iFlash/iFdPacker Extractor v2.0_a10 Improved 7-Zip parameter control
This commit is contained in:
parent
389c30bb65
commit
0e170334c6
9 changed files with 482 additions and 20 deletions
193
Apple_EFI_ID.py
Normal file
193
Apple_EFI_ID.py
Normal file
|
@ -0,0 +1,193 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Apple EFI ID
|
||||
Apple EFI Image Identifier
|
||||
Copyright (C) 2018-2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
TITLE = 'Apple EFI Image Identifier v2.0_a4'
|
||||
|
||||
import os
|
||||
import sys
|
||||
import zlib
|
||||
import struct
|
||||
import ctypes
|
||||
import subprocess
|
||||
|
||||
# Stop __pycache__ generation
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
from common.externals import get_uefifind_path, get_uefiextract_path
|
||||
from common.path_ops import del_dirs, path_parent, path_suffixes
|
||||
from common.patterns import PAT_APPLE_EFI
|
||||
from common.struct_ops import char, get_struct, uint8_t
|
||||
from common.system import argparse_init, printer, script_init
|
||||
from common.text_ops import file_to_bytes
|
||||
|
||||
class IntelBiosId(ctypes.LittleEndianStructure):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('Signature', char*8), # 0x00
|
||||
('BoardID', uint8_t*16), # 0x08
|
||||
('Dot1', uint8_t*2), # 0x18
|
||||
('BoardExt', uint8_t*6), # 0x1A
|
||||
('Dot2', uint8_t*2), # 0x20
|
||||
('VersionMajor', uint8_t*8), # 0x22
|
||||
('Dot3', uint8_t*2), # 0x2A
|
||||
('BuildType', uint8_t*2), # 0x2C
|
||||
('VersionMinor', uint8_t*4), # 0x2E
|
||||
('Dot4', uint8_t*2), # 0x32
|
||||
('Year', uint8_t*4), # 0x34
|
||||
('Month', uint8_t*4), # 0x38
|
||||
('Day', uint8_t*4), # 0x3C
|
||||
('Hour', uint8_t*4), # 0x40
|
||||
('Minute', uint8_t*4), # 0x44
|
||||
('NullTerminator', uint8_t*2), # 0x48
|
||||
# 0x4A
|
||||
]
|
||||
|
||||
# https://github.com/tianocore/edk2-platforms/blob/master/Platform/Intel/BoardModulePkg/Include/Guid/BiosId.h
|
||||
|
||||
@staticmethod
|
||||
def decode(field):
|
||||
return struct.pack('B' * len(field), *field).decode('utf-16','ignore').strip('\x00 ')
|
||||
|
||||
def get_bios_id(self):
|
||||
BoardID = self.decode(self.BoardID)
|
||||
BoardExt = self.decode(self.BoardExt)
|
||||
VersionMajor = self.decode(self.VersionMajor)
|
||||
BuildType = self.decode(self.BuildType)
|
||||
VersionMinor = self.decode(self.VersionMinor)
|
||||
BuildDate = f'20{self.decode(self.Year)}-{self.decode(self.Month)}-{self.decode(self.Day)}'
|
||||
BuildTime = f'{self.decode(self.Hour)}-{self.decode(self.Minute)}'
|
||||
|
||||
return BoardID, BoardExt, VersionMajor, BuildType, VersionMinor, BuildDate, BuildTime
|
||||
|
||||
def struct_print(self, p):
|
||||
BoardID,BoardExt,VersionMajor,BuildType,VersionMinor,BuildDate,BuildTime = self.get_bios_id()
|
||||
|
||||
printer(['Intel Signature:', self.Signature.decode('utf-8')], p, False)
|
||||
printer(['Board Identity: ', BoardID], p, False)
|
||||
printer(['Apple Identity: ', BoardExt], p, False)
|
||||
printer(['Major Version: ', VersionMajor], p, False)
|
||||
printer(['Minor Version: ', VersionMinor], p, False)
|
||||
printer(['Build Type: ', BuildType], p, False)
|
||||
printer(['Build Date: ', BuildDate], p, False)
|
||||
printer(['Build Time: ', BuildTime.replace('-',':')], p, False)
|
||||
|
||||
# Check if input is Apple EFI image
|
||||
def is_apple_efi(input_file):
|
||||
input_buffer = file_to_bytes(input_file)
|
||||
|
||||
if PAT_APPLE_EFI.search(input_buffer):
|
||||
return True
|
||||
|
||||
if not os.path.isfile(input_file):
|
||||
return False
|
||||
|
||||
try:
|
||||
_ = subprocess.run([get_uefifind_path(), input_file, 'body', 'list', PAT_UEFIFIND],
|
||||
check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
# Parse & Identify (or Rename) Apple EFI image
|
||||
def apple_efi_identify(input_file, output_path, padding=0, rename=False):
|
||||
if not os.path.isfile(input_file):
|
||||
printer('Error: Could not find input file path!', padding)
|
||||
|
||||
return 1
|
||||
|
||||
input_buffer = file_to_bytes(input_file)
|
||||
|
||||
bios_id_match = PAT_APPLE_EFI.search(input_buffer) # Detect $IBIOSI$ pattern
|
||||
|
||||
if bios_id_match:
|
||||
bios_id_res = f'0x{bios_id_match.start():X}'
|
||||
|
||||
bios_id_hdr = get_struct(input_buffer, bios_id_match.start(), IntelBiosId)
|
||||
else:
|
||||
# The $IBIOSI$ pattern is within EFI compressed modules so we need to use UEFIFind and UEFIExtract
|
||||
try:
|
||||
bios_id_res = subprocess.check_output([get_uefifind_path(), input_file, 'body', 'list', PAT_UEFIFIND],
|
||||
text=True)[:36]
|
||||
|
||||
temp_dir = os.path.join(f'{output_path}_uefiextract')
|
||||
|
||||
del_dirs(temp_dir) # UEFIExtract must create its output folder itself, make sure it is not present
|
||||
|
||||
_ = subprocess.run([get_uefiextract_path(), input_file, bios_id_res, '-o', temp_dir, '-m', 'body'],
|
||||
check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
|
||||
with open(os.path.join(temp_dir, 'body.bin'), 'rb') as raw_body:
|
||||
body_buffer = raw_body.read()
|
||||
|
||||
bios_id_match = PAT_APPLE_EFI.search(body_buffer) # Detect decompressed $IBIOSI$ pattern
|
||||
|
||||
bios_id_hdr = get_struct(body_buffer, bios_id_match.start(), IntelBiosId)
|
||||
|
||||
del_dirs(temp_dir) # Successful UEFIExtract extraction, remove its output (temp) folder
|
||||
except:
|
||||
printer('Error: Failed to parse compressed $IBIOSI$ pattern!', padding)
|
||||
|
||||
return 2
|
||||
|
||||
printer(f'Detected $IBIOSI$ at {bios_id_res}\n', padding)
|
||||
|
||||
bios_id_hdr.struct_print(padding + 4)
|
||||
|
||||
if rename:
|
||||
input_parent = path_parent(input_file)
|
||||
|
||||
input_suffix = path_suffixes(input_file)[-1]
|
||||
|
||||
input_adler32 = zlib.adler32(input_buffer)
|
||||
|
||||
ID,Ext,Major,Type,Minor,Date,Time = bios_id_hdr.get_bios_id()
|
||||
|
||||
output_name = f'{ID}_{Ext}_{Major}_{Type}{Minor}_{Date}_{Time}_{input_adler32:08X}{input_suffix}'
|
||||
|
||||
output_file = os.path.join(input_parent, output_name)
|
||||
|
||||
if not os.path.isfile(output_file):
|
||||
os.replace(input_file, output_file) # Rename input file based on its EFI tag
|
||||
|
||||
printer(f'Renamed to {output_name}', padding)
|
||||
|
||||
return 0
|
||||
|
||||
PAT_UEFIFIND = f'244942494F534924{"."*32}2E00{"."*12}2E00{"."*16}2E00{"."*12}2E00{"."*40}0000'
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Set argparse Arguments
|
||||
argparser = argparse_init()
|
||||
argparser.add_argument('-r', '--rename', help='rename EFI image based on its tag', action='store_true')
|
||||
arguments = argparser.parse_args()
|
||||
|
||||
rename = arguments.rename # Set EFI image tag renaming optional argument
|
||||
|
||||
# Initialize script (must be after argparse)
|
||||
exit_code,input_files,output_path,padding = script_init(TITLE, arguments, 4)
|
||||
|
||||
for input_file in input_files:
|
||||
input_name = os.path.basename(input_file)
|
||||
|
||||
printer(['***', input_name], padding - 4)
|
||||
|
||||
if not is_apple_efi(input_file):
|
||||
printer('Error: This is not an Apple EFI image!', padding)
|
||||
|
||||
continue # Next input file
|
||||
|
||||
extract_path = os.path.join(output_path, input_name)
|
||||
|
||||
if apple_efi_identify(input_file, extract_path, padding, rename) == 0:
|
||||
exit_code -= 1
|
||||
|
||||
printer('Done!', pause=True)
|
||||
|
||||
sys.exit(exit_code)
|
Loading…
Add table
Add a link
Reference in a new issue