mirror of
https://github.com/platomav/BIOSUtilities.git
synced 2025-05-13 14:44:46 -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
|
@ -2,12 +2,12 @@
|
|||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Apple EFI Identify
|
||||
Apple EFI ID
|
||||
Apple EFI Image Identifier
|
||||
Copyright (C) 2018-2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
TITLE = 'Apple EFI Image Identifier v2.0_a3'
|
||||
TITLE = 'Apple EFI Image Identifier v2.0_a4'
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -143,7 +143,7 @@ def apple_efi_identify(input_file, output_path, padding=0, rename=False):
|
|||
if rename:
|
||||
input_parent = path_parent(input_file)
|
||||
|
||||
input_suffix = path_suffixes(input_file)[0]
|
||||
input_suffix = path_suffixes(input_file)[-1]
|
||||
|
||||
input_adler32 = zlib.adler32(input_buffer)
|
||||
|
||||
|
@ -156,7 +156,7 @@ def apple_efi_identify(input_file, output_path, padding=0, rename=False):
|
|||
if not os.path.isfile(output_file):
|
||||
os.replace(input_file, output_file) # Rename input file based on its EFI tag
|
||||
|
||||
printer(f'Renamed input to {output_name}', padding)
|
||||
printer(f'Renamed to {output_name}', padding)
|
||||
|
||||
return 0
|
||||
|
|
@ -2,12 +2,12 @@
|
|||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Apple EFI Split
|
||||
Apple EFI IM4P
|
||||
Apple EFI IM4P Splitter
|
||||
Copyright (C) 2018-2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
TITLE = 'Apple EFI IM4P Splitter v3.0_a2'
|
||||
TITLE = 'Apple EFI IM4P Splitter v3.0_a4'
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -32,6 +32,8 @@ def is_apple_im4p(input_file):
|
|||
|
||||
# Parse & Split Apple EFI IM4P image
|
||||
def apple_im4p_split(input_file, output_path, padding=0):
|
||||
exit_codes = []
|
||||
|
||||
input_buffer = file_to_bytes(input_file)
|
||||
|
||||
extract_path = os.path.join(f'{output_path}_extracted')
|
||||
|
@ -48,7 +50,7 @@ def apple_im4p_split(input_file, output_path, padding=0):
|
|||
mefi_data_bgn = im4p_match.start() + input_buffer[im4p_match.start() - 0x1]
|
||||
|
||||
# IM4P mefi payload size
|
||||
mefi_data_len = int.from_bytes(input_buffer[im4p_match.end() + 0x9:im4p_match.end() + 0xD], 'big')
|
||||
mefi_data_len = int.from_bytes(input_buffer[im4p_match.end() + 0x5:im4p_match.end() + 0x9], 'big')
|
||||
|
||||
# Check if mefi is followed by _MEFIBIN
|
||||
mefibin_exist = input_buffer[mefi_data_bgn:mefi_data_bgn + 0x8] == b'_MEFIBIN'
|
||||
|
@ -119,6 +121,8 @@ def apple_im4p_split(input_file, output_path, padding=0):
|
|||
|
||||
output_data = input_buffer[ifd_data_bgn:ifd_data_end]
|
||||
|
||||
output_size = len(output_data)
|
||||
|
||||
output_name = path_stem(input_file) if os.path.isfile(input_file) else 'Part'
|
||||
|
||||
output_path = os.path.join(extract_path, f'{output_name}_[{ifd_data_txt}].fd')
|
||||
|
@ -127,6 +131,13 @@ def apple_im4p_split(input_file, output_path, padding=0):
|
|||
output_image.write(output_data)
|
||||
|
||||
printer(f'Split Apple EFI image at {ifd_data_txt}!', padding)
|
||||
|
||||
if output_size != ifd_comp_all_size:
|
||||
printer(f'Error: Bad image size 0x{output_size:07X}, expected 0x{ifd_comp_all_size:07X}!', padding + 4)
|
||||
|
||||
exit_codes.append(1)
|
||||
|
||||
return sum(exit_codes)
|
||||
|
||||
# Intel Flash Descriptor Component Sizes (4MB, 8MB, 16MB and 32MB)
|
||||
IFD_COMP_LEN = {3: 0x400000, 4: 0x800000, 5: 0x1000000, 6: 0x2000000}
|
||||
|
@ -151,9 +162,8 @@ if __name__ == '__main__':
|
|||
|
||||
extract_path = os.path.join(output_path, input_name)
|
||||
|
||||
apple_im4p_split(input_file, extract_path, padding)
|
||||
|
||||
exit_code -= 1
|
||||
if apple_im4p_split(input_file, extract_path, padding) == 0:
|
||||
exit_code -= 1
|
||||
|
||||
printer('Done!', pause=True)
|
||||
|
143
Apple_EFI_PBZX.py
Normal file
143
Apple_EFI_PBZX.py
Normal file
|
@ -0,0 +1,143 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Apple PBZX Extract
|
||||
Apple EFI PBZX Extractor
|
||||
Copyright (C) 2021-2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
TITLE = 'Apple EFI PBZX Extractor v1.0_a4'
|
||||
|
||||
import os
|
||||
import sys
|
||||
import lzma
|
||||
import ctypes
|
||||
|
||||
# Stop __pycache__ generation
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
from common.comp_szip import is_szip_supported, szip_decompress
|
||||
from common.path_ops import make_dirs, path_stem
|
||||
from common.patterns import PAT_APPLE_PBZX
|
||||
from common.struct_ops import get_struct, uint32_t
|
||||
from common.system import argparse_init, printer, script_init
|
||||
from common.text_ops import file_to_bytes
|
||||
|
||||
class PbzxChunk(ctypes.BigEndianStructure):
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('Reserved0', uint32_t), # 0x00
|
||||
('InitSize', uint32_t), # 0x04
|
||||
('Reserved1', uint32_t), # 0x08
|
||||
('CompSize', uint32_t), # 0x0C
|
||||
# 0x10
|
||||
]
|
||||
|
||||
def struct_print(self, p):
|
||||
printer(['Reserved 0 :', f'0x{self.Reserved0:X}'], p, False)
|
||||
printer(['Initial Size :', f'0x{self.InitSize:X}'], p, False)
|
||||
printer(['Reserved 1 :', f'0x{self.Reserved1:X}'], p, False)
|
||||
printer(['Compressed Size:', f'0x{self.CompSize:X}'], p, False)
|
||||
|
||||
# Check if input is Apple PBZX image
|
||||
def is_apple_pbzx(input_file):
|
||||
input_buffer = file_to_bytes(input_file)
|
||||
|
||||
return bool(PAT_APPLE_PBZX.search(input_buffer[:0x4]))
|
||||
|
||||
# Parse & Extract Apple PBZX image
|
||||
def apple_pbzx_extract(input_file, output_path, padding=0):
|
||||
input_buffer = file_to_bytes(input_file)
|
||||
|
||||
extract_path = os.path.join(f'{output_path}_extracted')
|
||||
|
||||
make_dirs(extract_path, delete=True)
|
||||
|
||||
cpio_bin = b'' # Initialize PBZX > CPIO Buffer
|
||||
cpio_len = 0x0 # Initialize PBZX > CPIO Length
|
||||
|
||||
chunk_off = 0xC # First PBZX Chunk starts at 0xC
|
||||
while chunk_off < len(input_buffer):
|
||||
chunk_hdr = get_struct(input_buffer, chunk_off, PbzxChunk)
|
||||
|
||||
printer(f'PBZX Chunk at 0x{chunk_off:08X}\n', padding)
|
||||
|
||||
chunk_hdr.struct_print(padding + 4)
|
||||
|
||||
# PBZX Chunk data starts after its Header
|
||||
comp_bgn = chunk_off + PBZX_CHUNK_HDR_LEN
|
||||
|
||||
# To avoid a potential infinite loop, double-check Compressed Size
|
||||
comp_end = comp_bgn + max(chunk_hdr.CompSize, PBZX_CHUNK_HDR_LEN)
|
||||
|
||||
comp_bin = input_buffer[comp_bgn:comp_end]
|
||||
|
||||
try:
|
||||
# Attempt XZ decompression, if applicable to Chunk data
|
||||
cpio_bin += lzma.LZMADecompressor().decompress(comp_bin)
|
||||
|
||||
printer('Successful LZMA decompression!', padding + 8)
|
||||
except:
|
||||
# Otherwise, Chunk data is not compressed
|
||||
cpio_bin += comp_bin
|
||||
|
||||
# Final CPIO size should match the sum of all Chunks > Initial Size
|
||||
cpio_len += chunk_hdr.InitSize
|
||||
|
||||
# Next Chunk starts at the end of current Chunk's data
|
||||
chunk_off = comp_end
|
||||
|
||||
# Check that CPIO size is valid based on all Chunks > Initial Size
|
||||
if cpio_len != len(cpio_bin):
|
||||
printer('Error: Unexpected CPIO archive size!', padding)
|
||||
|
||||
return 1
|
||||
|
||||
cpio_name = path_stem(input_file) if os.path.isfile(input_file) else 'Payload'
|
||||
|
||||
cpio_path = os.path.join(extract_path, f'{cpio_name}.cpio')
|
||||
|
||||
with open(cpio_path, 'wb') as cpio_object:
|
||||
cpio_object.write(cpio_bin)
|
||||
|
||||
# Decompress PBZX > CPIO archive with 7-Zip
|
||||
if is_szip_supported(cpio_path, padding, args=['-tCPIO'], check=True):
|
||||
if szip_decompress(cpio_path, extract_path, 'CPIO', padding, args=['-tCPIO'], check=True) == 0:
|
||||
os.remove(cpio_path) # Successful extraction, delete PBZX > CPIO archive
|
||||
else:
|
||||
return 3
|
||||
else:
|
||||
return 2
|
||||
|
||||
return 0
|
||||
|
||||
# Get common ctypes Structure Sizes
|
||||
PBZX_CHUNK_HDR_LEN = ctypes.sizeof(PbzxChunk)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Set argparse Arguments
|
||||
argparser = argparse_init()
|
||||
arguments = argparser.parse_args()
|
||||
|
||||
# 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_pbzx(input_file):
|
||||
printer('Error: This is not an Apple PBZX image!', padding)
|
||||
|
||||
continue # Next input file
|
||||
|
||||
extract_path = os.path.join(output_path, input_name)
|
||||
|
||||
if apple_pbzx_extract(input_file, extract_path, padding) == 0:
|
||||
exit_code -= 1
|
||||
|
||||
printer('Done!', pause=True)
|
||||
|
||||
sys.exit(exit_code)
|
172
Apple_EFI_PKG.py
Normal file
172
Apple_EFI_PKG.py
Normal file
|
@ -0,0 +1,172 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Apple EFI PKG
|
||||
Apple EFI Package Extractor
|
||||
Copyright (C) 2019-2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
TITLE = 'Apple EFI Package Extractor v2.0_a4'
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Stop __pycache__ generation
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
from common.comp_szip import is_szip_supported, szip_decompress
|
||||
from common.path_ops import copy_file, del_dirs, get_path_files, make_dirs, path_name, path_parent
|
||||
from common.patterns import PAT_APPLE_PKG
|
||||
from common.system import argparse_init, printer, script_init
|
||||
from common.text_ops import file_to_bytes
|
||||
|
||||
from Apple_EFI_ID import apple_efi_identify, is_apple_efi
|
||||
from Apple_EFI_IM4P import apple_im4p_split, is_apple_im4p
|
||||
from Apple_EFI_PBZX import apple_pbzx_extract, is_apple_pbzx
|
||||
|
||||
# Check if input is Apple EFI PKG package
|
||||
def is_apple_pkg(input_file):
|
||||
input_buffer = file_to_bytes(input_file)
|
||||
|
||||
return bool(PAT_APPLE_PKG.search(input_buffer[:0x4]))
|
||||
|
||||
# Split Apple EFI image (if applicable) and Rename
|
||||
def efi_split_rename(in_file, out_path, padding=0):
|
||||
exit_codes = []
|
||||
|
||||
working_dir = f'{in_file}_extracted'
|
||||
|
||||
if is_apple_im4p(in_file):
|
||||
printer(f'Splitting IM4P via {is_apple_im4p.__module__}...', padding)
|
||||
im4p_exit = apple_im4p_split(in_file, in_file, padding + 4)
|
||||
exit_codes.append(im4p_exit)
|
||||
else:
|
||||
make_dirs(working_dir, delete=True)
|
||||
copy_file(in_file, working_dir, True)
|
||||
|
||||
for efi_file in get_path_files(working_dir):
|
||||
if is_apple_efi(efi_file):
|
||||
printer(f'Renaming EFI via {is_apple_efi.__module__}...', padding)
|
||||
name_exit = apple_efi_identify(efi_file, efi_file, padding + 4, True)
|
||||
exit_codes.append(name_exit)
|
||||
|
||||
for named_file in get_path_files(working_dir):
|
||||
copy_file(named_file, out_path, True)
|
||||
|
||||
del_dirs(working_dir)
|
||||
|
||||
return sum(exit_codes)
|
||||
|
||||
# Parse & Extract Apple EFI PKG packages
|
||||
def apple_pkg_extract(input_file, output_path, padding=0):
|
||||
if not os.path.isfile(input_file):
|
||||
printer('Error: Could not find input file path!', padding)
|
||||
return 1
|
||||
|
||||
extract_path = os.path.join(f'{output_path}_extracted')
|
||||
|
||||
make_dirs(extract_path, delete=True)
|
||||
|
||||
xar_path = os.path.join(extract_path, 'xar')
|
||||
|
||||
# Decompress PKG > XAR archive with 7-Zip
|
||||
if is_szip_supported(input_file, padding, args=['-tXAR'], check=True):
|
||||
if szip_decompress(input_file, xar_path, 'XAR', padding, args=['-tXAR'], check=True) != 0:
|
||||
return 3
|
||||
else:
|
||||
return 2
|
||||
|
||||
for xar_file in get_path_files(xar_path):
|
||||
if path_name(xar_file) == 'Payload':
|
||||
pbzx_module = is_apple_pbzx.__module__
|
||||
if is_apple_pbzx(xar_file):
|
||||
printer(f'Extracting PBZX via {pbzx_module}...', padding + 4)
|
||||
if apple_pbzx_extract(xar_file, xar_file, padding + 8) == 0:
|
||||
printer(f'Succesfull PBZX extraction via {pbzx_module}!', padding + 4)
|
||||
for pbzx_file in get_path_files(f'{xar_file}_extracted'):
|
||||
if path_name(pbzx_file) == 'UpdateBundle.zip':
|
||||
if is_szip_supported(pbzx_file, padding + 8, args=['-tZIP'], check=True):
|
||||
zip_path = f'{pbzx_file}_extracted'
|
||||
if szip_decompress(pbzx_file, zip_path, 'ZIP', padding + 8, args=['-tZIP'], check=True) == 0:
|
||||
for zip_file in get_path_files(zip_path):
|
||||
if path_name(path_parent(zip_file)) == 'MacEFI':
|
||||
printer(path_name(zip_file), padding + 12)
|
||||
if efi_split_rename(zip_file, extract_path, padding + 16) != 0:
|
||||
printer(f'Error: Could not split and rename {path_name(zip_file)}!', padding)
|
||||
return 10
|
||||
else:
|
||||
return 9
|
||||
else:
|
||||
return 8
|
||||
break # ZIP found, stop
|
||||
else:
|
||||
printer('Error: Could not find "UpdateBundle.zip" file!', padding)
|
||||
return 7
|
||||
else:
|
||||
printer(f'Error: Failed to extract PBZX file via {pbzx_module}!', padding)
|
||||
return 6
|
||||
else:
|
||||
printer(f'Error: Failed to detect file as PBZX via {pbzx_module}!', padding)
|
||||
return 5
|
||||
|
||||
break # Payload found, stop searching
|
||||
|
||||
if path_name(xar_file) == 'Scripts':
|
||||
if is_szip_supported(xar_file, padding + 4, args=['-tGZIP'], check=True):
|
||||
gzip_path = f'{xar_file}_extracted'
|
||||
if szip_decompress(xar_file, gzip_path, 'GZIP', padding + 4, args=['-tGZIP'], check=True) == 0:
|
||||
for gzip_file in get_path_files(gzip_path):
|
||||
if is_szip_supported(gzip_file, padding + 8, args=['-tCPIO'], check=True):
|
||||
cpio_path = f'{gzip_file}_extracted'
|
||||
if szip_decompress(gzip_file, cpio_path, 'CPIO', padding + 8, args=['-tCPIO'], check=True) == 0:
|
||||
for cpio_file in get_path_files(cpio_path):
|
||||
if path_name(path_parent(cpio_file)) == 'EFIPayloads':
|
||||
printer(path_name(cpio_file), padding + 12)
|
||||
if efi_split_rename(cpio_file, extract_path, padding + 16) != 0:
|
||||
printer(f'Error: Could not split and rename {path_name(cpio_file)}!', padding)
|
||||
return 15
|
||||
else:
|
||||
return 14
|
||||
else:
|
||||
return 13
|
||||
else:
|
||||
return 12
|
||||
else:
|
||||
return 11
|
||||
|
||||
break # Scripts found, stop searching
|
||||
else:
|
||||
printer('Error: Could not find "Payload" or "Scripts" file!', padding)
|
||||
return 4
|
||||
|
||||
del_dirs(xar_path) # Delete temporary/working XAR folder
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Set argparse Arguments
|
||||
argparser = argparse_init()
|
||||
arguments = argparser.parse_args()
|
||||
|
||||
# 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_pkg(input_file):
|
||||
printer('Error: This is not an Apple EFI PKG package!', padding)
|
||||
|
||||
continue # Next input file
|
||||
|
||||
extract_path = os.path.join(output_path, input_name)
|
||||
|
||||
if apple_pkg_extract(input_file, extract_path, padding) == 0:
|
||||
exit_code -= 1
|
||||
|
||||
printer('Done!', pause=True)
|
||||
|
||||
sys.exit(exit_code)
|
|
@ -7,7 +7,7 @@ Insyde iFlash/iFdPacker Extractor
|
|||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
TITLE = 'Insyde iFlash/iFdPacker Extractor v2.0_a9'
|
||||
TITLE = 'Insyde iFlash/iFdPacker Extractor v2.0_a10'
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -175,9 +175,9 @@ def insyde_packer_extract(input_buffer, extract_path, padding=0):
|
|||
with open(sfx_path, 'wb') as sfx_file:
|
||||
sfx_file.write(sfx_buffer)
|
||||
|
||||
if is_szip_supported(sfx_path, padding + 8, password=INS_SFX_PWD, check=True):
|
||||
if is_szip_supported(sfx_path, padding + 8, args=[f'-p{INS_SFX_PWD}'], check=True):
|
||||
if szip_decompress(sfx_path, extract_path, 'Insyde iFdPacker > 7-Zip SFX',
|
||||
padding + 8, password=INS_SFX_PWD, check=True) == 0:
|
||||
padding + 8, args=[f'-p{INS_SFX_PWD}'], check=True) == 0:
|
||||
os.remove(sfx_path)
|
||||
else:
|
||||
return 125
|
||||
|
|
124
README.md
124
README.md
|
@ -7,6 +7,8 @@
|
|||
* [**AMI UCP Update Extractor**](#ami-ucp-update-extractor)
|
||||
* [**Apple EFI IM4P Splitter**](#apple-efi-im4p-splitter)
|
||||
* [**Apple EFI Image Identifier**](#apple-efi-image-identifier)
|
||||
* [**Apple EFI Package Extractor**](#apple-efi-package-extractor)
|
||||
* [**Apple EFI PBZX Extractor**](#apple-efi-pbzx-extractor)
|
||||
* [**Award BIOS Module Extractor**](#award-bios-module-extractor)
|
||||
* [**Dell PFS/PKG Update Extractor**](#dell-pfspkg-update-extractor)
|
||||
* [**Fujitsu SFX BIOS Extractor**](#fujitsu-sfx-bios-extractor)
|
||||
|
@ -150,7 +152,7 @@ Some Anti-Virus software may claim that the built/frozen/compiled executable con
|
|||
|
||||
#### **Description**
|
||||
|
||||
Parses Apple IM4P multi-EFI files and splits all detected EFI firmware into separate Intel SPI/BIOS images.
|
||||
Parses Apple IM4P multi-EFI files and splits all detected EFI firmware into separate Intel SPI/BIOS images. The output comprises only final firmware components and utilities which are directly usable by end users.
|
||||
|
||||
#### **Usage**
|
||||
|
||||
|
@ -184,7 +186,7 @@ PyInstaller can build/freeze/compile the utility at all three supported platform
|
|||
|
||||
3. Build/Freeze/Compile:
|
||||
|
||||
> pyinstaller --noupx --onefile \<path-to-project\>\/Apple_EFI_Split.py
|
||||
> pyinstaller --noupx --onefile \<path-to-project\>\/Apple_EFI_IM4P.py
|
||||
|
||||
At dist folder you should find the final utility executable
|
||||
|
||||
|
@ -245,7 +247,123 @@ PyInstaller can build/freeze/compile the utility at all three supported platform
|
|||
|
||||
4. Build/Freeze/Compile:
|
||||
|
||||
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Apple_EFI_Identify.py
|
||||
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Apple_EFI_ID.py
|
||||
|
||||
You should find the final utility executable at "dist" folder
|
||||
|
||||
#### **Anti-Virus False Positives**
|
||||
|
||||
Some Anti-Virus software may claim that the built/frozen/compiled executable contains viruses. Any such detections are false positives, usually of PyInstaller. You can switch to a better Anti-Virus software, report the false positive to their support, add the executable to the exclusions, build/freeze/compile yourself or use the Python script directly.
|
||||
|
||||
#### **Pictures**
|
||||
|
||||
![]()
|
||||
|
||||
## **Apple EFI Package Extractor**
|
||||
|
||||
![]()
|
||||
|
||||
#### **Description**
|
||||
|
||||
Parses Apple EFI PKG firmware packages (i.e. FirmwareUpdate.pkg, BridgeOSUpdateCustomer.pkg), extracts their EFI images, splits those in IM4P format and identifies/renames the final Intel SPI/BIOS images accordingly. The output comprises only final firmware components which are directly usable by end users.
|
||||
|
||||
#### **Usage**
|
||||
|
||||
You can either Drag & Drop or manually enter Apple EFI PKG package file(s). Optional arguments:
|
||||
|
||||
* -h or --help : show help message and exit
|
||||
* -v or --version : show utility name and version
|
||||
* -i or --input-dir : extract from given input directory
|
||||
* -o or --output-dir : extract in given output directory
|
||||
* -e or --auto-exit : skip press enter to exit prompts
|
||||
|
||||
#### **Compatibility**
|
||||
|
||||
Should work at all Windows, Linux or macOS operating systems which have Python 3.10 support.
|
||||
|
||||
#### **Prerequisites**
|
||||
|
||||
To run the utility, you must have the following 3rd party tools at the "external" project directory:
|
||||
|
||||
* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zzs for Linux)
|
||||
|
||||
#### **Build/Freeze/Compile with PyInstaller**
|
||||
|
||||
PyInstaller can build/freeze/compile the utility at all three supported platforms, it is simple to run and gets updated often.
|
||||
|
||||
1. Make sure Python 3.10.0 or newer is installed:
|
||||
|
||||
> python --version
|
||||
|
||||
2. Use pip to install PyInstaller:
|
||||
|
||||
> pip3 install pyinstaller
|
||||
|
||||
3. Place prerequisites at the "external" project directory:
|
||||
|
||||
> 7-Zip Console
|
||||
|
||||
4. Build/Freeze/Compile:
|
||||
|
||||
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Apple_EFI_PKG.py
|
||||
|
||||
You should find the final utility executable at "dist" folder
|
||||
|
||||
#### **Anti-Virus False Positives**
|
||||
|
||||
Some Anti-Virus software may claim that the built/frozen/compiled executable contains viruses. Any such detections are false positives, usually of PyInstaller. You can switch to a better Anti-Virus software, report the false positive to their support, add the executable to the exclusions, build/freeze/compile yourself or use the Python script directly.
|
||||
|
||||
#### **Pictures**
|
||||
|
||||
![]()
|
||||
|
||||
## **Apple EFI PBZX Extractor**
|
||||
|
||||
![]()
|
||||
|
||||
#### **Description**
|
||||
|
||||
Parses Apple EFI PBZX images, re-assembles their CPIO payload and extracts its firmware components (e.g. IM4P, EFI, Utilities, Scripts etc). It supports CPIO re-assembly from both Raw and XZ compressed PBZX Chunks. The output comprises only final firmware components and utilities which are directly usable by end users.
|
||||
|
||||
#### **Usage**
|
||||
|
||||
You can either Drag & Drop or manually enter Apple EFI PBZX image file(s). Optional arguments:
|
||||
|
||||
* -h or --help : show help message and exit
|
||||
* -v or --version : show utility name and version
|
||||
* -i or --input-dir : extract from given input directory
|
||||
* -o or --output-dir : extract in given output directory
|
||||
* -e or --auto-exit : skip press enter to exit prompts
|
||||
|
||||
#### **Compatibility**
|
||||
|
||||
Should work at all Windows, Linux or macOS operating systems which have Python 3.10 support.
|
||||
|
||||
#### **Prerequisites**
|
||||
|
||||
To run the utility, you must have the following 3rd party tools at the "external" project directory:
|
||||
|
||||
* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zzs for Linux)
|
||||
|
||||
#### **Build/Freeze/Compile with PyInstaller**
|
||||
|
||||
PyInstaller can build/freeze/compile the utility at all three supported platforms, it is simple to run and gets updated often.
|
||||
|
||||
1. Make sure Python 3.10.0 or newer is installed:
|
||||
|
||||
> python --version
|
||||
|
||||
2. Use pip to install PyInstaller:
|
||||
|
||||
> pip3 install pyinstaller
|
||||
|
||||
3. Place prerequisites at the "external" project directory:
|
||||
|
||||
> 7-Zip Console
|
||||
|
||||
4. Build/Freeze/Compile:
|
||||
|
||||
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Apple_EFI_PBZX.py
|
||||
|
||||
You should find the final utility executable at "dist" folder
|
||||
|
||||
|
|
|
@ -23,9 +23,12 @@ def check_bad_exit_code(exit_code):
|
|||
raise Exception(f'BAD_EXIT_CODE_{exit_code}')
|
||||
|
||||
# Check if file is 7-Zip supported
|
||||
def is_szip_supported(in_path, padding=0, password='', check=False, silent=False):
|
||||
def is_szip_supported(in_path, padding=0, args=None, check=False, silent=False):
|
||||
try:
|
||||
szip_c = [get_szip_path(), 't', in_path, f'-p{password}', '-bso0', '-bse0', '-bsp0']
|
||||
if args is None:
|
||||
args = []
|
||||
|
||||
szip_c = [get_szip_path(), 't', in_path, *args, '-bso0', '-bse0', '-bsp0']
|
||||
|
||||
szip_t = subprocess.run(szip_c, check=False)
|
||||
|
||||
|
@ -40,12 +43,15 @@ def is_szip_supported(in_path, padding=0, password='', check=False, silent=False
|
|||
return True
|
||||
|
||||
# Archive decompression via 7-Zip
|
||||
def szip_decompress(in_path, out_path, in_name, padding=0, password='', check=False, silent=False):
|
||||
def szip_decompress(in_path, out_path, in_name, padding=0, args=None, check=False, silent=False):
|
||||
if not in_name:
|
||||
in_name = 'archive'
|
||||
|
||||
try:
|
||||
szip_c = [get_szip_path(), 'x', f'-p{password}', '-aou', '-bso0', '-bse0', '-bsp0', f'-o{out_path}', in_path]
|
||||
if args is None:
|
||||
args = []
|
||||
|
||||
szip_c = [get_szip_path(), 'x', *args, '-aou', '-bso0', '-bse0', '-bsp0', f'-o{out_path}', in_path]
|
||||
|
||||
szip_x = subprocess.run(szip_c, check=False)
|
||||
|
||||
|
|
|
@ -71,6 +71,10 @@ def agnostic_path(in_path):
|
|||
def path_parent(in_path):
|
||||
return Path(in_path).parent.absolute()
|
||||
|
||||
# Get final path component, with suffix
|
||||
def path_name(in_path):
|
||||
return PurePath(in_path).name
|
||||
|
||||
# Get final path component, w/o suffix
|
||||
def path_stem(in_path):
|
||||
return PurePath(in_path).stem
|
||||
|
@ -95,6 +99,13 @@ def del_dirs(in_path):
|
|||
if Path(in_path).is_dir():
|
||||
shutil.rmtree(in_path, onerror=clear_readonly)
|
||||
|
||||
# Copy file to path with or w/o metadata
|
||||
def copy_file(in_path, out_path, meta=False):
|
||||
if meta:
|
||||
shutil.copy2(in_path, out_path)
|
||||
else:
|
||||
shutil.copy(in_path, out_path)
|
||||
|
||||
# Clear read-only file attribute (on shutil.rmtree error)
|
||||
def clear_readonly(in_func, in_path, _):
|
||||
os.chmod(in_path, stat.S_IWRITE)
|
||||
|
|
|
@ -11,6 +11,8 @@ PAT_AMI_PFAT = re.compile(br'_AMIPFAT.AMI_BIOS_GUARD_FLASH_CONFIGURATIONS', re.D
|
|||
PAT_AMI_UCP = re.compile(br'@(UAF|HPU).{12}@', re.DOTALL)
|
||||
PAT_APPLE_EFI = re.compile(br'\$IBIOSI\$.{16}\x2E\x00.{6}\x2E\x00.{8}\x2E\x00.{6}\x2E\x00.{20}\x00{2}', re.DOTALL)
|
||||
PAT_APPLE_IM4P = re.compile(br'\x16\x04IM4P\x16\x04mefi')
|
||||
PAT_APPLE_PBZX = re.compile(br'pbzx')
|
||||
PAT_APPLE_PKG = re.compile(br'xar!')
|
||||
PAT_AWARD_LZH = re.compile(br'-lh[04567]-')
|
||||
PAT_DELL_FTR = re.compile(br'\xEE\xAA\xEE\x8F\x49\x1B\xE8\xAE\x14\x37\x90')
|
||||
PAT_DELL_HDR = re.compile(br'\xEE\xAA\x76\x1B\xEC\xBB\x20\xF1\xE6\x51.\x78\x9C', re.DOTALL)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue