Created common template for executing all utilities

Unified extracted output directory naming logic

Multiple code fixes, refactors and improvements
This commit is contained in:
platomav 2022-09-12 23:09:12 +03:00
parent 5f364f4759
commit 6de50c422f
26 changed files with 377 additions and 1169 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
# Skip all external files
external/*
# Keep external > requirements file
!external/requirements.txt

View file

@ -7,7 +7,7 @@ AMI BIOS Guard Extractor
Copyright (C) 2018-2022 Plato Mavropoulos
"""
TITLE = 'AMI BIOS Guard Extractor v4.0_a11'
TITLE = 'AMI BIOS Guard Extractor v4.0_a12'
import os
import re
@ -19,10 +19,11 @@ sys.dont_write_bytecode = True
from common.externals import get_bgs_tool
from common.num_ops import get_ordinal
from common.path_ops import make_dirs, safe_name
from common.path_ops import make_dirs, safe_name, get_extract_path, extract_suffix
from common.patterns import PAT_AMI_PFAT
from common.struct_ops import char, get_struct, uint8_t, uint16_t, uint32_t
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
class AmiBiosGuardHeader(ctypes.LittleEndianStructure):
@ -147,7 +148,7 @@ def parse_bg_script(script_data, padding=0):
is_opcode_div = len(script_data) % 8 == 0
if not is_opcode_div:
printer('Error: Script not divisible by OpCode length!', padding, False)
printer('Error: Script is not divisible by OpCode length!', padding, False)
return 1
@ -161,7 +162,7 @@ def parse_bg_script(script_data, padding=0):
BigScript = get_bgs_tool()
if not BigScript:
printer('Error: BIOS Guard Script Tool dependency missing!', padding, False)
printer('Note: BIOS Guard Script Tool optional dependency is missing!', padding, False)
return 3
@ -220,7 +221,7 @@ def parse_pfat_hdr(buffer, padding=0):
return block_all, hdr_size, files_count
def parse_pfat_file(input_file, output_path, padding=0):
def parse_pfat_file(input_file, extract_path, padding=0):
input_buffer = file_to_bytes(input_file)
pfat_buffer = get_ami_pfat(input_buffer)
@ -228,9 +229,7 @@ def parse_pfat_file(input_file, output_path, padding=0):
file_path = ''
all_blocks_dict = {}
extract_name = os.path.basename(output_path)
extract_path = os.path.join(f'{output_path}_extracted')
extract_name = os.path.basename(extract_path).rstrip(extract_suffix())
make_dirs(extract_path, delete=True)
@ -299,7 +298,7 @@ def parse_pfat_file(input_file, output_path, padding=0):
out_oob.write(pfat_oob_data)
if is_ami_pfat(pfat_oob_data):
parse_pfat_file(pfat_oob_data, pfat_oob_path, padding)
parse_pfat_file(pfat_oob_data, get_extract_path(pfat_oob_path), padding)
in_all_data = b''.join([block[1] for block in sorted(all_blocks_dict.items())])
@ -317,32 +316,4 @@ PFAT_BLK_HDR_LEN = ctypes.sizeof(IntelBiosGuardHeader)
PFAT_BLK_S2K_LEN = ctypes.sizeof(IntelBiosGuardSignature2k)
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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
if not is_ami_pfat(input_buffer):
printer('Error: This is not an AMI BIOS Guard (PFAT) image!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
parse_pfat_file(input_buffer, extract_path, padding)
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
BIOSUtility(TITLE, is_ami_pfat, parse_pfat_file).run_utility()

View file

@ -7,7 +7,7 @@ AMI UCP Update Extractor
Copyright (C) 2021-2022 Plato Mavropoulos
"""
TITLE = 'AMI UCP Update Extractor v2.0_a19'
TITLE = 'AMI UCP Update Extractor v2.0_a20'
import os
import re
@ -21,10 +21,11 @@ sys.dont_write_bytecode = True
from common.checksums import get_chk_16
from common.comp_efi import efi_decompress, is_efi_compressed
from common.path_ops import agnostic_path, make_dirs, safe_name, safe_path
from common.path_ops import agnostic_path, make_dirs, safe_name, safe_path, get_extract_path
from common.patterns import PAT_AMI_UCP, PAT_INTEL_ENG
from common.struct_ops import char, get_struct, uint8_t, uint16_t, uint32_t
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes, to_string
from AMI_PFAT_Extract import is_ami_pfat, parse_pfat_file
@ -211,15 +212,13 @@ def get_uaf_mod(buffer, uaf_off=0x0):
return uaf_all
# Parse & Extract AMI UCP structures
def ucp_extract(in_file, out_path, padding=0, checksum=False):
def ucp_extract(in_file, extract_path, padding=0, checksum=False):
input_buffer = file_to_bytes(in_file)
nal_dict = {} # Initialize @NAL Dictionary per UCP
printer('Utility Configuration Program', padding)
extract_path = os.path.join(f'{out_path}_extracted')
make_dirs(extract_path, delete=True)
# Get best AMI UCP Pattern match based on @UAF|@HPU Size
@ -419,14 +418,14 @@ def uaf_extract(buffer, extract_path, mod_info, padding=0, checksum=False, nal_d
if uaf_tag == '@INS' and is_insyde_ifd(uaf_fname):
ins_dir = os.path.join(extract_path, safe_name(f'{uaf_tag}_nested-IFD')) # Generate extraction directory
if insyde_ifd_extract(uaf_fname, ins_dir, padding + 4) == 0:
if insyde_ifd_extract(uaf_fname, get_extract_path(ins_dir), padding + 4) == 0:
os.remove(uaf_fname) # Delete raw nested Insyde IFD image after successful extraction
# Detect & Unpack AMI BIOS Guard (PFAT) BIOS image
if is_ami_pfat(uaf_data_raw):
pfat_dir = os.path.join(extract_path, safe_name(uaf_name))
parse_pfat_file(uaf_data_raw, pfat_dir, padding + 4)
parse_pfat_file(uaf_data_raw, get_extract_path(pfat_dir), padding + 4)
os.remove(uaf_fname) # Delete raw PFAT BIOS image after successful extraction
@ -439,7 +438,7 @@ def uaf_extract(buffer, extract_path, mod_info, padding=0, checksum=False, nal_d
if is_ami_ucp(uaf_data_raw):
uaf_dir = os.path.join(extract_path, safe_name(f'{uaf_tag}_nested-UCP')) # Generate extraction directory
ucp_extract(uaf_data_raw, uaf_dir, padding + 4, checksum) # Call recursively
ucp_extract(uaf_data_raw, get_extract_path(uaf_dir), padding + 4, checksum) # Call recursively
os.remove(uaf_fname) # Delete raw nested AMI UCP image after successful extraction
@ -511,35 +510,6 @@ UAF_TAG_DICT = {
}
if __name__ == '__main__':
# Set argparse Arguments
argparser = argparse_init()
argparser.add_argument('-c', '--checksum', help='verify AMI UCP Checksums (slow)', action='store_true')
arguments = argparser.parse_args()
checksum = arguments.checksum # Set Checksum verification 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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
if not is_ami_ucp(input_buffer):
printer('Error: This is not an AMI UCP Update executable!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
ucp_extract(input_buffer, extract_path, padding, checksum)
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
utility = BIOSUtility(TITLE, is_ami_ucp, ucp_extract)
utility.parse_argument('-c', '--checksum', help='verify AMI UCP Checksums (slow)', action='store_true')
utility.run_utility()

View file

@ -7,7 +7,7 @@ Apple EFI Image Identifier
Copyright (C) 2018-2022 Plato Mavropoulos
"""
TITLE = 'Apple EFI Image Identifier v2.0_a4'
TITLE = 'Apple EFI Image Identifier v2.0_a5'
import os
import sys
@ -23,7 +23,8 @@ 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.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
class IntelBiosId(ctypes.LittleEndianStructure):
@ -92,11 +93,11 @@ def is_apple_efi(input_file):
check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return True
except:
except Exception:
return False
# Parse & Identify (or Rename) Apple EFI image
def apple_efi_identify(input_file, output_path, padding=0, rename=False):
def apple_efi_identify(input_file, extract_path, padding=0, rename=False):
if not os.path.isfile(input_file):
printer('Error: Could not find input file path!', padding)
@ -116,22 +117,20 @@ def apple_efi_identify(input_file, output_path, padding=0, rename=False):
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(extract_path) # UEFIExtract must create its output folder itself, make sure it is not present
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'],
_ = subprocess.run([get_uefiextract_path(), input_file, bios_id_res, '-o', extract_path, '-m', 'body'],
check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
with open(os.path.join(temp_dir, 'body.bin'), 'rb') as raw_body:
with open(os.path.join(extract_path, '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:
del_dirs(extract_path) # Successful UEFIExtract extraction, remove its output (temp) folder
except Exception:
printer('Error: Failed to parse compressed $IBIOSI$ pattern!', padding)
return 2
@ -163,31 +162,6 @@ def apple_efi_identify(input_file, output_path, padding=0, rename=False):
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)
utility = BIOSUtility(TITLE, is_apple_efi, apple_efi_identify)
utility.parse_argument('-r', '--rename', help='rename EFI image based on its tag', action='store_true')
utility.run_utility()

View file

@ -7,7 +7,7 @@ Apple EFI IM4P Splitter
Copyright (C) 2018-2022 Plato Mavropoulos
"""
TITLE = 'Apple EFI IM4P Splitter v3.0_a4'
TITLE = 'Apple EFI IM4P Splitter v3.0_a5'
import os
import sys
@ -17,7 +17,8 @@ sys.dont_write_bytecode = True
from common.path_ops import make_dirs, path_stem
from common.patterns import PAT_APPLE_IM4P, PAT_INTEL_IFD
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
# Check if input is Apple EFI IM4P image
@ -31,13 +32,11 @@ def is_apple_im4p(input_file):
return bool(is_im4p and is_ifd)
# Parse & Split Apple EFI IM4P image
def apple_im4p_split(input_file, output_path, padding=0):
def apple_im4p_split(input_file, extract_path, padding=0):
exit_codes = []
input_buffer = file_to_bytes(input_file)
extract_path = os.path.join(f'{output_path}_extracted')
make_dirs(extract_path, delete=True)
# Detect IM4P EFI pattern
@ -143,28 +142,4 @@ def apple_im4p_split(input_file, output_path, padding=0):
IFD_COMP_LEN = {3: 0x400000, 4: 0x800000, 5: 0x1000000, 6: 0x2000000}
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_im4p(input_file):
printer('Error: This is not an Apple EFI IM4P image!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
if apple_im4p_split(input_file, extract_path, padding) == 0:
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
BIOSUtility(TITLE, is_apple_im4p, apple_im4p_split).run_utility()

View file

@ -7,7 +7,7 @@ Apple EFI PBZX Extractor
Copyright (C) 2021-2022 Plato Mavropoulos
"""
TITLE = 'Apple EFI PBZX Extractor v1.0_a4'
TITLE = 'Apple EFI PBZX Extractor v1.0_a5'
import os
import sys
@ -21,7 +21,8 @@ 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.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
class PbzxChunk(ctypes.BigEndianStructure):
@ -47,11 +48,9 @@ def is_apple_pbzx(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):
def apple_pbzx_extract(input_file, extract_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
@ -78,7 +77,7 @@ def apple_pbzx_extract(input_file, output_path, padding=0):
cpio_bin += lzma.LZMADecompressor().decompress(comp_bin)
printer('Successful LZMA decompression!', padding + 8)
except:
except Exception:
# Otherwise, Chunk data is not compressed
cpio_bin += comp_bin
@ -116,28 +115,4 @@ def apple_pbzx_extract(input_file, output_path, padding=0):
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)
BIOSUtility(TITLE, is_apple_pbzx, apple_pbzx_extract).run_utility()

View file

@ -7,7 +7,7 @@ Apple EFI Package Extractor
Copyright (C) 2019-2022 Plato Mavropoulos
"""
TITLE = 'Apple EFI Package Extractor v2.0_a4'
TITLE = 'Apple EFI Package Extractor v2.0_a5'
import os
import sys
@ -16,9 +16,10 @@ import sys
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.path_ops import copy_file, del_dirs, get_path_files, make_dirs, path_name, path_parent, get_extract_path
from common.patterns import PAT_APPLE_PKG
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
from Apple_EFI_ID import apple_efi_identify, is_apple_efi
@ -35,11 +36,11 @@ def is_apple_pkg(input_file):
def efi_split_rename(in_file, out_path, padding=0):
exit_codes = []
working_dir = f'{in_file}_extracted'
working_dir = get_extract_path(in_file)
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)
im4p_exit = apple_im4p_split(in_file, working_dir, padding + 4)
exit_codes.append(im4p_exit)
else:
make_dirs(working_dir, delete=True)
@ -59,13 +60,11 @@ def efi_split_rename(in_file, out_path, padding=0):
return sum(exit_codes)
# Parse & Extract Apple EFI PKG packages
def apple_pkg_extract(input_file, output_path, padding=0):
def apple_pkg_extract(input_file, extract_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')
@ -82,12 +81,13 @@ def apple_pkg_extract(input_file, output_path, padding=0):
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:
pbzx_path = get_extract_path(xar_file)
if apple_pbzx_extract(xar_file, pbzx_path, padding + 8) == 0:
printer(f'Succesfull PBZX extraction via {pbzx_module}!', padding + 4)
for pbzx_file in get_path_files(f'{xar_file}_extracted'):
for pbzx_file in get_path_files(pbzx_path):
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'
zip_path = get_extract_path(pbzx_file)
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':
@ -114,11 +114,11 @@ def apple_pkg_extract(input_file, output_path, padding=0):
if path_name(xar_file) == 'Scripts':
if is_szip_supported(xar_file, padding + 4, args=['-tGZIP'], check=True):
gzip_path = f'{xar_file}_extracted'
gzip_path = get_extract_path(xar_file)
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'
cpio_path = get_extract_path(gzip_file)
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':
@ -145,28 +145,4 @@ def apple_pkg_extract(input_file, output_path, padding=0):
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)
BIOSUtility(TITLE, is_apple_pkg, apple_pkg_extract).run_utility()

View file

@ -7,7 +7,7 @@ Award BIOS Module Extractor
Copyright (C) 2018-2022 Plato Mavropoulos
"""
TITLE = 'Award BIOS Module Extractor v2.0_a4'
TITLE = 'Award BIOS Module Extractor v2.0_a5'
import os
import sys
@ -16,9 +16,10 @@ import sys
sys.dont_write_bytecode = True
from common.comp_szip import szip_decompress
from common.path_ops import make_dirs, safe_name
from common.path_ops import make_dirs, safe_name, get_extract_path
from common.patterns import PAT_AWARD_LZH
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
# Check if input is Award BIOS image
@ -28,11 +29,9 @@ def is_award_bios(in_file):
return bool(PAT_AWARD_LZH.search(in_buffer))
# Parse & Extract Award BIOS image
def award_bios_extract(input_file, output_path, padding=0):
def award_bios_extract(input_file, extract_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)
for lzh_match in PAT_AWARD_LZH.finditer(input_buffer):
@ -69,35 +68,7 @@ def award_bios_extract(input_file, output_path, padding=0):
# Extract any nested LZH archives
if is_award_bios(mod_path):
# Recursively extract nested Award BIOS modules
award_bios_extract(mod_path, mod_path, padding + 8)
award_bios_extract(mod_path, get_extract_path(mod_path), padding + 8)
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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
if not is_award_bios(input_buffer):
printer('Error: This is not an Award BIOS image!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
award_bios_extract(input_buffer, extract_path, padding)
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
BIOSUtility(TITLE, is_award_bios, award_bios_extract).run_utility()

View file

@ -7,7 +7,7 @@ Dell PFS/PKG Update Extractor
Copyright (C) 2018-2022 Plato Mavropoulos
"""
TITLE = 'Dell PFS/PKG Update Extractor v6.0_a12'
TITLE = 'Dell PFS/PKG Update Extractor v6.0_a13'
import os
import io
@ -25,7 +25,8 @@ from common.comp_szip import is_szip_supported, szip_decompress
from common.path_ops import del_dirs, get_path_files, make_dirs, path_name, path_parent, path_stem, safe_name
from common.patterns import PAT_DELL_FTR, PAT_DELL_HDR, PAT_DELL_PKG
from common.struct_ops import char, get_struct, uint8_t, uint16_t, uint32_t, uint64_t
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
from AMI_PFAT_Extract import IntelBiosGuardHeader, IntelBiosGuardSignature2k, parse_bg_script
@ -225,6 +226,28 @@ def is_dell_pfs(in_file):
return bool(is_pkg or is_hdr and is_ftr)
# Parse & Extract Dell PFS/PKG Update image
def pfs_pkg_parse(in_file, output_path, padding=0, structure=True, advanced=True):
in_buffer = file_to_bytes(in_file)
make_dirs(output_path, delete=True)
is_dell_pkg = is_pfs_pkg(in_buffer)
if is_dell_pkg:
pfs_results = thinos_pkg_extract(in_buffer, output_path)
else:
pfs_results = {path_stem(in_file) if os.path.isfile(in_file) else 'Image': in_buffer}
# Parse each Dell PFS image contained in the input file
for pfs_index,(pfs_name,pfs_buffer) in enumerate(pfs_results.items(), start=1):
# At ThinOS PKG packages, multiple PFS images may be included in separate model-named folders
pfs_path = os.path.join(output_path, f'{pfs_index} {pfs_name}') if is_dell_pkg else output_path
# Parse each PFS ZLIB section
for zlib_offset in get_section_offsets(pfs_buffer):
# Call the PFS ZLIB section parser function
pfs_section_parse(pfs_buffer, zlib_offset, pfs_path, pfs_name, pfs_index, 1, False, padding, structure, advanced)
# Extract Dell ThinOS PKG 7zXZ
def thinos_pkg_extract(in_file, output_path):
in_buffer = file_to_bytes(in_file)
@ -296,7 +319,7 @@ def get_section_offsets(buffer):
return pfs_zlib_list
# Dell PFS ZLIB Section Parser
def pfs_section_parse(zlib_data, zlib_start, output_path, pfs_name, pfs_index, pfs_count, is_rec, padding, structure=True, advanced=True):
def pfs_section_parse(zlib_data, zlib_start, output_path, pfs_name, pfs_index, pfs_count, is_rec, padding=0, structure=True, advanced=True):
is_zlib_error = False # Initialize PFS ZLIB-related error state
section_type = zlib_data[zlib_start - 0x1] # Byte before PFS ZLIB Section pattern is Section Type (e.g. AA, BB)
@ -365,34 +388,34 @@ def pfs_section_parse(zlib_data, zlib_start, output_path, pfs_name, pfs_index, p
if is_zlib_error:
raise Exception('ZLIB_ERROR') # ZLIB errors are critical
section_data = zlib.decompress(compressed_data) # ZLIB decompression
except:
except Exception:
section_data = zlib_data # Fallback to raw ZLIB data upon critical error
# Call the PFS Extract function on the decompressed PFS ZLIB Section
pfs_extract(section_data, pfs_index, pfs_name, pfs_count, section_path, padding, structure, advanced)
# Parse & Extract Dell PFS Volume
def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, structure=True, advanced=True):
def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, padding=0, structure=True, advanced=True):
# Show PFS Volume indicator
if structure:
printer('PFS Volume:', pfs_padd)
printer('PFS Volume:', padding)
# Get PFS Header Structure values
pfs_hdr = get_struct(buffer, 0, DellPfsHeader)
# Validate that a PFS Header was parsed
if pfs_hdr.Tag != b'PFS.HDR.':
printer('Error: PFS Header could not be found!', pfs_padd + 4)
printer('Error: PFS Header could not be found!', padding + 4)
return # Critical error, abort
# Show PFS Header Structure info
if structure:
printer('PFS Header:\n', pfs_padd + 4)
pfs_hdr.struct_print(pfs_padd + 8)
printer('PFS Header:\n', padding + 4)
pfs_hdr.struct_print(padding + 8)
# Validate that a known PFS Header Version was encountered
chk_hdr_ver(pfs_hdr.HeaderVersion, 'PFS', pfs_padd + 8)
chk_hdr_ver(pfs_hdr.HeaderVersion, 'PFS', padding + 8)
# Get PFS Payload Data
pfs_payload = buffer[PFS_HEAD_LEN:PFS_HEAD_LEN + pfs_hdr.PayloadSize]
@ -407,7 +430,7 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, s
while len(pfs_payload[entry_start:entry_start + pfs_entry_size]) == pfs_entry_size:
# Analyze PFS Entry Structure and get relevant info
_,entry_version,entry_guid,entry_data,entry_data_sig,entry_met,entry_met_sig,next_entry = \
parse_pfs_entry(pfs_payload, entry_start, pfs_entry_size, pfs_entry_struct, 'PFS Entry', pfs_padd, structure)
parse_pfs_entry(pfs_payload, entry_start, pfs_entry_size, pfs_entry_struct, 'PFS Entry', padding, structure)
entry_type = 'OTHER' # Adjusted later if PFS Entry is Zlib, PFAT, PFS Info, Model Info
@ -444,12 +467,12 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, s
# Show PFS Information Header Structure info
if structure:
printer('PFS Information Header:\n', pfs_padd + 4)
entry_info_hdr.struct_print(pfs_padd + 8)
printer('PFS Information Header:\n', padding + 4)
entry_info_hdr.struct_print(padding + 8)
# Validate that a known PFS Information Header Version was encountered
if entry_info_hdr.HeaderVersion != 1:
printer(f'Error: Unknown PFS Information Header Version {entry_info_hdr.HeaderVersion}!', pfs_padd + 8)
printer(f'Error: Unknown PFS Information Header Version {entry_info_hdr.HeaderVersion}!', padding + 8)
break # Skip PFS Information Entries/Descriptors in case of unknown PFS Information Header Version
# Get PFS Information Header GUID in Big Endian format to match each Info to the equivalent stored PFS Entry details
@ -468,8 +491,8 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, s
# Show PFS FileName Structure info
if structure:
printer('PFS FileName Entry:\n', pfs_padd + 8)
entry_info_mod.struct_print(pfs_padd + 12, entry_name)
printer('PFS FileName Entry:\n', padding + 8)
entry_info_mod.struct_print(padding + 12, entry_name)
# Get PFS FileName Version string via "Version" and "VersionType" fields
# PFS FileName Version string must be preferred over PFS Entry's Version
@ -496,8 +519,8 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, s
# Show Nested PFS Metadata Structure info
if structure:
printer('PFS Metadata Information:\n', pfs_padd + 4)
entry_info.struct_print(pfs_padd + 8)
printer('PFS Metadata Information:\n', padding + 4)
entry_info.struct_print(padding + 8)
# As Nested PFS Entry Name, we'll use the actual PFS File Name
# Replace common Windows reserved/illegal filename characters
@ -520,12 +543,12 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, s
# Show PFS Information Header Structure info
if structure:
printer('PFS Information Header:\n', pfs_padd + 4)
entry_info_hdr.struct_print(pfs_padd + 8)
printer('PFS Information Header:\n', padding + 4)
entry_info_hdr.struct_print(padding + 8)
# Validate that a known PFS Information Header Version was encountered
if entry_info_hdr.HeaderVersion != 1:
printer(f'Error: Unknown PFS Information Header Version {entry_info_hdr.HeaderVersion}!', pfs_padd + 8)
printer(f'Error: Unknown PFS Information Header Version {entry_info_hdr.HeaderVersion}!', padding + 8)
break # Skip PFS Signature Entries/Descriptors in case of unknown Header Version
# PFS Signature Entries/Descriptors have DellPfsInfo + DellPfsEntryR* + Sign Size [0x2] + Sign Data [Sig Size]
@ -536,8 +559,8 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, s
# Show PFS Information Header Structure info
if structure:
printer('PFS Information Entry:\n', pfs_padd + 8)
entry_hdr.struct_print(pfs_padd + 12)
printer('PFS Information Entry:\n', padding + 8)
entry_hdr.struct_print(padding + 12)
# Show PFS Signature Size & Data (after DellPfsEntryR*)
sign_info_start = sign_start + PFS_INFO_LEN + pfs_entry_size
@ -546,9 +569,9 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, s
sign_data_txt = f'{int.from_bytes(sign_data_raw, "little"):0{sign_size * 2}X}'
if structure:
printer('Signature Information:\n', pfs_padd + 8)
printer(f'Signature Size: 0x{sign_size:X}', pfs_padd + 12, False)
printer(f'Signature Data: {sign_data_txt[:32]} [...]', pfs_padd + 12, False)
printer('Signature Information:\n', padding + 8)
printer(f'Signature Size: 0x{sign_size:X}', padding + 12, False)
printer(f'Signature Data: {sign_data_txt[:32]} [...]', padding + 12, False)
# The next PFS Signature Entry/Descriptor starts after the previous Signature Data
sign_start += (PFS_INFO_LEN + pfs_entry_size + 0x2 + sign_size)
@ -578,7 +601,7 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, s
if pfat_entry_hdr.Tag == b'PFS.HDR.' and is_pfat:
entry_type = 'PFAT' # Re-set PFS Entry Type from OTHER to PFAT, to use such info afterwards
entry_data = parse_pfat_pfs(pfat_entry_hdr, entry_data, pfs_padd, structure) # Parse sub-PFS PFAT Volume
entry_data = parse_pfat_pfs(pfat_entry_hdr, entry_data, padding, structure) # Parse sub-PFS PFAT Volume
# Parse PFS Entry which contains zlib-compressed sub-PFS Volume
elif pfs_zlib_offsets:
@ -599,7 +622,7 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, s
sub_pfs_path = os.path.join(output_path, f'{pfs_count} {safe_name(sub_pfs_name)}')
# Recursively call the PFS ZLIB Section Parser function for the sub-PFS Volume (pfs_index = pfs_count)
pfs_section_parse(entry_data, offset, sub_pfs_path, sub_pfs_name, pfs_count, pfs_count, True, pfs_padd + 4, structure, advanced)
pfs_section_parse(entry_data, offset, sub_pfs_path, sub_pfs_name, pfs_count, pfs_count, True, padding + 4, structure, advanced)
entries_all[index][4] = entry_data # Adjust PFS Entry Data after parsing PFAT (same ZLIB raw data, not stored afterwards)
entries_all[index][3] = entry_type # Adjust PFS Entry Type from OTHER to PFAT or ZLIB (ZLIB is ignored at file extraction)
@ -668,16 +691,16 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, s
# Write/Extract PFS Entry files
for file in write_files:
full_name = f'{pfs_index} {pfs_name} -- {file_index} {file_name} v{file_version}' # Full PFS Entry Name
pfs_file_write(file[0], file[1], file_type, full_name, output_path, pfs_padd, structure, advanced)
pfs_file_write(file[0], file[1], file_type, full_name, output_path, padding, structure, advanced)
# Get PFS Footer Data after PFS Header Payload
pfs_footer = buffer[PFS_HEAD_LEN + pfs_hdr.PayloadSize:PFS_HEAD_LEN + pfs_hdr.PayloadSize + PFS_FOOT_LEN]
# Analyze PFS Footer Structure
chk_pfs_ftr(pfs_footer, pfs_payload, pfs_hdr.PayloadSize, 'PFS', pfs_padd, structure)
chk_pfs_ftr(pfs_footer, pfs_payload, pfs_hdr.PayloadSize, 'PFS', padding, structure)
# Analyze Dell PFS Entry Structure
def parse_pfs_entry(entry_buffer, entry_start, entry_size, entry_struct, text, padding, structure=True):
def parse_pfs_entry(entry_buffer, entry_start, entry_size, entry_struct, text, padding=0, structure=True):
# Get PFS Entry Structure values
pfs_entry = get_struct(entry_buffer, entry_start, entry_struct)
@ -723,7 +746,7 @@ def parse_pfs_entry(entry_buffer, entry_start, entry_size, entry_struct, text, p
return pfs_entry, entry_version, entry_guid, entry_data, entry_data_sig, entry_met, entry_met_sig, entry_met_sig_end
# Parse Dell PFS Volume with PFAT Payload
def parse_pfat_pfs(entry_hdr, entry_data, padding, structure=True):
def parse_pfat_pfs(entry_hdr, entry_data, padding=0, structure=True):
# Show PFS Volume indicator
if structure:
printer('PFS Volume:', padding + 4)
@ -886,7 +909,7 @@ def get_entry_ver(version_fields, version_types):
return version
# Check if Dell PFS Header Version is known
def chk_hdr_ver(version, text, padding):
def chk_hdr_ver(version, text, padding=0):
if version in (1,2):
return
@ -895,7 +918,7 @@ def chk_hdr_ver(version, text, padding):
return
# Analyze Dell PFS Footer Structure
def chk_pfs_ftr(footer_buffer, data_buffer, data_size, text, padding, structure=True):
def chk_pfs_ftr(footer_buffer, data_buffer, data_size, text, padding=0, structure=True):
# Get PFS Footer Structure values
pfs_ftr = get_struct(footer_buffer, 0, DellPfsFooter)
@ -920,7 +943,7 @@ def chk_pfs_ftr(footer_buffer, data_buffer, data_size, text, padding, structure=
printer(f'Error: Invalid {text} Footer Payload Checksum!', padding + 4)
# Write/Extract Dell PFS Entry Files (Data, Metadata, Signature)
def pfs_file_write(bin_buff, bin_name, bin_type, full_name, out_path, padding, structure=True, advanced=True):
def pfs_file_write(bin_buff, bin_name, bin_type, full_name, out_path, padding=0, structure=True, advanced=True):
# Store Data/Metadata Signature (advanced users only)
if bin_name.startswith('sign'):
final_name = f'{safe_name(full_name)}.{bin_name.split("_")[1]}.sig'
@ -944,7 +967,7 @@ def pfs_file_write(bin_buff, bin_name, bin_type, full_name, out_path, padding, s
pfs_out.write(final_data) # Write final Data/Metadata Payload
# Check if Dell PFS Entry file/data is Text/XML and Convert
def bin_is_text(buffer, file_type, is_metadata, pfs_padd, structure=True, advanced=True):
def bin_is_text(buffer, file_type, is_metadata, padding=0, structure=True, advanced=True):
is_text = False
write_mode = 'wb'
extension = '.bin'
@ -975,8 +998,8 @@ def bin_is_text(buffer, file_type, is_metadata, pfs_padd, structure=True, advanc
# Show Model/PCR XML Information, if applicable
if structure and is_text and not is_metadata: # Metadata is shown at initial DellPfsMetadata analysis
printer(f'PFS { {".txt": "Model", ".xml": "PCR XML"}[extension] } Information:\n', pfs_padd + 8)
_ = [printer(line.strip('\r'), pfs_padd + 12, False) for line in buffer.split('\n') if line]
printer(f'PFS { {".txt": "Model", ".xml": "PCR XML"}[extension] } Information:\n', padding + 8)
_ = [printer(line.strip('\r'), padding + 12, False) for line in buffer.split('\n') if line]
# Only for non-advanced users due to signature (.sig) invalidation
if advanced:
@ -994,52 +1017,8 @@ PFS_PFAT_LEN = ctypes.sizeof(DellPfsPfatMetadata)
PFAT_HDR_LEN = ctypes.sizeof(IntelBiosGuardHeader)
PFAT_SIG_LEN = ctypes.sizeof(IntelBiosGuardSignature2k)
if __name__ == '__main__':
# Set argparse arguments
argparser = argparse_init()
argparser.add_argument('-a', '--advanced', help='extract signatures and metadata', action='store_true')
argparser.add_argument('-s', '--structure', help='show PFS structure information', action='store_true')
arguments = argparser.parse_args()
advanced = arguments.advanced # Set Advanced user mode optional argument
structure = arguments.structure # Set Structure output mode 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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
if not is_dell_pfs(input_buffer):
printer('Error: This is not a Dell PFS/PKG Update image!', padding)
continue # Next input file
extract_path = os.path.join(output_path, f'{input_name}_extracted')
is_dell_pkg = is_pfs_pkg(input_buffer)
if is_dell_pkg:
pfs_results = thinos_pkg_extract(input_buffer, extract_path)
else:
pfs_results = {path_stem(input_file): input_buffer}
# Parse each Dell PFS image contained in the input file
for pfs_index,(pfs_name,pfs_buffer) in enumerate(pfs_results.items(), start=1):
# At ThinOS PKG packages, multiple PFS images may be included in separate model-named folders
pfs_path = os.path.join(extract_path, f'{pfs_index} {pfs_name}') if is_dell_pkg else extract_path
# Parse each PFS ZLIB section
for zlib_offset in get_section_offsets(pfs_buffer):
# Call the PFS ZLIB section parser function
pfs_section_parse(pfs_buffer, zlib_offset, pfs_path, pfs_name, pfs_index, 1, False, padding, structure, advanced)
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
if __name__ == '__main__':
utility = BIOSUtility(TITLE, is_dell_pfs, pfs_pkg_parse)
utility.parse_argument('-a', '--advanced', help='extract signatures and metadata', action='store_true')
utility.parse_argument('-s', '--structure', help='show PFS structure information', action='store_true')
utility.run_utility()

View file

@ -7,7 +7,7 @@ Fujitsu SFX BIOS Extractor
Copyright (C) 2019-2022 Plato Mavropoulos
"""
TITLE = 'Fujitsu SFX BIOS Extractor v3.0_a2'
TITLE = 'Fujitsu SFX BIOS Extractor v3.0_a3'
import os
import sys
@ -18,7 +18,8 @@ sys.dont_write_bytecode = True
from common.comp_szip import is_szip_supported, szip_decompress
from common.path_ops import make_dirs
from common.patterns import PAT_FUJITSU_SFX
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
# Check if input is Fujitsu SFX image
@ -71,11 +72,9 @@ def fujitsu_cabinet(in_file, extract_path, padding=0):
return 0
# Parse & Extract Fujitsu SFX image
def fujitsu_sfx_extract(in_file, output_path, padding=0):
def fujitsu_sfx_extract(in_file, extract_path, padding=0):
buffer = file_to_bytes(in_file)
extract_path = os.path.join(f'{output_path}_extracted')
make_dirs(extract_path, delete=True)
if fujitsu_cabinet(buffer, extract_path, padding) == 0:
@ -87,32 +86,4 @@ def fujitsu_sfx_extract(in_file, output_path, padding=0):
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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
# Check if Fujitsu SFX pattern was found on image
if not is_fujitsu_sfx(input_buffer):
printer('Error: This is not a Fujitsu SFX image!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
if fujitsu_sfx_extract(input_buffer, extract_path, padding) == 0:
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
BIOSUtility(TITLE, is_fujitsu_sfx, fujitsu_sfx_extract).run_utility()

View file

@ -7,7 +7,7 @@ Fujitsu UPC BIOS Extractor
Copyright (C) 2021-2022 Plato Mavropoulos
"""
TITLE = 'Fujitsu UPC BIOS Extractor v2.0_a4'
TITLE = 'Fujitsu UPC BIOS Extractor v2.0_a5'
import os
import sys
@ -17,7 +17,7 @@ sys.dont_write_bytecode = True
from common.comp_efi import efi_decompress, is_efi_compressed
from common.path_ops import make_dirs, path_suffixes
from common.system import argparse_init, printer, script_init
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
# Check if input is Fujitsu UPC image
@ -31,9 +31,7 @@ def is_fujitsu_upc(in_file):
return is_ext and is_efi
# Parse & Extract Fujitsu UPC image
def fujitsu_upc_extract(input_file, output_path, padding=0):
extract_path = os.path.join(f'{output_path}_extracted')
def fujitsu_upc_extract(input_file, extract_path, padding=0):
make_dirs(extract_path, delete=True)
image_base = os.path.basename(input_file)
@ -43,31 +41,4 @@ def fujitsu_upc_extract(input_file, output_path, padding=0):
return efi_decompress(input_file, image_path, padding)
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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
if not is_fujitsu_upc(input_buffer):
printer('Error: This is not a Fujitsu UPC BIOS image!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
if fujitsu_upc_extract(input_file, extract_path, padding) == 0:
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
BIOSUtility(TITLE, is_fujitsu_upc, fujitsu_upc_extract).run_utility()

View file

@ -7,7 +7,7 @@ Insyde iFlash/iFdPacker Extractor
Copyright (C) 2022 Plato Mavropoulos
"""
TITLE = 'Insyde iFlash/iFdPacker Extractor v2.0_a10'
TITLE = 'Insyde iFlash/iFdPacker Extractor v2.0_a11'
import os
import sys
@ -17,10 +17,11 @@ import ctypes
sys.dont_write_bytecode = True
from common.comp_szip import is_szip_supported, szip_decompress
from common.path_ops import get_path_files, make_dirs, safe_name
from common.path_ops import get_path_files, make_dirs, safe_name, get_extract_path
from common.patterns import PAT_INSYDE_IFL, PAT_INSYDE_SFX
from common.struct_ops import char, get_struct, uint32_t
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
class IflashHeader(ctypes.LittleEndianStructure):
@ -57,11 +58,9 @@ def is_insyde_ifd(input_file):
return is_ifl or is_sfx
# Parse & Extract Insyde iFlash/iFdPacker Update images
def insyde_ifd_extract(input_file, output_path, padding=0):
def insyde_ifd_extract(input_file, extract_path, padding=0):
input_buffer = file_to_bytes(input_file)
extract_path = os.path.join(f'{output_path}_extracted')
iflash_code = insyde_iflash_extract(input_buffer, extract_path, padding)
ifdpack_path = os.path.join(extract_path, 'Insyde iFdPacker SFX')
@ -190,7 +189,7 @@ def insyde_packer_extract(input_buffer, extract_path, padding=0):
if is_insyde_ifd(sfx_file):
printer(f'{os.path.basename(sfx_file)}', padding + 12)
ifd_code = insyde_ifd_extract(sfx_file, sfx_file, padding + 16)
ifd_code = insyde_ifd_extract(sfx_file, get_extract_path(sfx_file), padding + 16)
exit_codes.append(ifd_code)
@ -215,32 +214,4 @@ INS_IFL_IMG = {
INS_IFL_LEN = ctypes.sizeof(IflashHeader)
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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
if not is_insyde_ifd(input_buffer):
printer('Error: This is not an Insyde iFlash/iFdPacker Update image!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
insyde_ifd_extract(input_buffer, extract_path, padding)
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
BIOSUtility(TITLE, is_insyde_ifd, insyde_ifd_extract).run_utility()

View file

@ -7,7 +7,7 @@ Panasonic BIOS Package Extractor
Copyright (C) 2018-2022 Plato Mavropoulos
"""
TITLE = 'Panasonic BIOS Package Extractor v2.0_a9'
TITLE = 'Panasonic BIOS Package Extractor v2.0_a10'
import os
import io
@ -22,7 +22,8 @@ from common.comp_szip import is_szip_supported, szip_decompress
from common.path_ops import get_path_files, make_dirs, path_stem, safe_name
from common.pe_ops import get_pe_file, get_pe_info, is_pe_file, show_pe_info
from common.patterns import PAT_MICROSOFT_CAB
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
from AMI_PFAT_Extract import is_ami_pfat, parse_pfat_file
@ -111,7 +112,7 @@ def panasonic_res_extract(pe_name, pe_file, extract_path, padding=0):
res_raw = lznt1.decompress(res_bin[0x8:])
printer('Succesfull LZNT1 decompression via lznt1!', padding + 8)
except:
except Exception:
res_raw = res_bin
printer('Succesfull PE Resource extraction!', padding + 8)
@ -161,10 +162,8 @@ def panasonic_img_extract(pe_name, pe_path, pe_file, extract_path, padding=0):
return bool(img_bin)
# Parse & Extract Panasonic BIOS Package PE
def panasonic_pkg_extract(input_path, input_buffer, output_path, padding=0):
is_upd_res,is_upd_img = [False] * 2
extract_path = os.path.join(f'{output_path}_extracted')
def panasonic_pkg_extract(input_file, extract_path, padding=0):
input_buffer = file_to_bytes(input_file)
make_dirs(extract_path, delete=True)
@ -178,7 +177,7 @@ def panasonic_pkg_extract(input_path, input_buffer, output_path, padding=0):
if not pkg_pe_info:
return 3
pkg_pe_name = path_stem(input_path)
pkg_pe_name = path_stem(input_file)
printer(f'Panasonic BIOS Package > PE ({pkg_pe_name})\n', padding)
@ -195,6 +194,8 @@ def panasonic_pkg_extract(input_path, input_buffer, output_path, padding=0):
show_pe_info(upd_pe_info, padding + 16)
is_upd_res, is_upd_img = False, False
is_upd_res = panasonic_res_extract(upd_pe_name, upd_pe_file, extract_path, padding + 16)
if not is_upd_res:
@ -205,32 +206,4 @@ def panasonic_pkg_extract(input_path, input_buffer, output_path, padding=0):
return 0 if is_upd_res or is_upd_img else 1
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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
# Check if Panasonic BIOS Package pattern was found on executable
if not is_panasonic_pkg(input_buffer):
printer('Error: This is not a Panasonic BIOS Package executable!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
if panasonic_pkg_extract(input_file, input_buffer, extract_path, padding) == 0:
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
BIOSUtility(TITLE, is_panasonic_pkg, panasonic_pkg_extract).run_utility()

View file

@ -7,7 +7,7 @@ Phoenix TDK Packer Extractor
Copyright (C) 2021-2022 Plato Mavropoulos
"""
TITLE = 'Phoenix TDK Packer Extractor v2.0_a9'
TITLE = 'Phoenix TDK Packer Extractor v2.0_a10'
import os
import sys
@ -21,7 +21,8 @@ from common.path_ops import make_dirs, safe_name
from common.pe_ops import get_pe_file, get_pe_info
from common.patterns import PAT_MICROSOFT_MZ, PAT_MICROSOFT_PE, PAT_PHOENIX_TDK
from common.struct_ops import char, get_struct, uint32_t
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
class PhoenixTdkHeader(ctypes.LittleEndianStructure):
@ -110,7 +111,7 @@ def get_tdk_base(in_buffer, pack_off):
# Parse detected MZ > PE > Info > Product Name
pe_name = pe_info.get(b'ProductName',b'')
except:
except Exception:
# Any error means no MZ > PE > Info > Product Name
pe_name = b''
@ -152,12 +153,10 @@ def is_phoenix_tdk(in_file):
return bool(get_phoenix_tdk(buffer)[1] is not None)
# Parse & Extract Phoenix Tools Development Kit (TDK) Packer
def phoenix_tdk_extract(input_file, output_path, padding=0):
input_buffer = file_to_bytes(input_file)
def phoenix_tdk_extract(input_file, extract_path, padding=0):
exit_code = 0
extract_path = os.path.join(f'{output_path}_extracted')
input_buffer = file_to_bytes(input_file)
make_dirs(extract_path, delete=True)
@ -214,7 +213,7 @@ def phoenix_tdk_extract(input_file, output_path, padding=0):
if tdk_mod.get_compression() == 'LZMA':
try:
mod_data = lzma.LZMADecompressor().decompress(mod_data)
except:
except Exception:
printer('Error: Phoenix TDK Entry > LZMA decompression failed!\n', padding + 12, pause=True)
exit_code = 5
@ -241,32 +240,4 @@ TDK_MOD_LEN = ctypes.sizeof(PhoenixTdkEntry)
TDK_DUMMY_LEN = 0x200
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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
# Check if Phoenix TDK Packer pattern was found on executable
if not is_phoenix_tdk(input_buffer):
printer('Error: This is not a Phoenix TDK Packer executable!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
if phoenix_tdk_extract(input_buffer, extract_path, padding) == 0:
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
BIOSUtility(TITLE, is_phoenix_tdk, phoenix_tdk_extract).run_utility()

View file

@ -7,7 +7,7 @@ Portwell EFI Update Extractor
Copyright (C) 2021-2022 Plato Mavropoulos
"""
TITLE = 'Portwell EFI Update Extractor v2.0_a11'
TITLE = 'Portwell EFI Update Extractor v2.0_a12'
import os
import sys
@ -19,7 +19,8 @@ from common.comp_efi import efi_decompress, is_efi_compressed
from common.path_ops import make_dirs, safe_name
from common.pe_ops import get_pe_file
from common.patterns import PAT_MICROSOFT_MZ, PAT_PORTWELL_EFI
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
FILE_NAMES = {
@ -36,7 +37,7 @@ def is_portwell_efi(in_file):
try:
pe_buffer = get_portwell_pe(in_buffer)[1]
except:
except Exception:
pe_buffer = b''
is_mz = PAT_MICROSOFT_MZ.search(in_buffer[:0x2]) # EFI images start with PE Header MZ
@ -54,10 +55,10 @@ def get_portwell_pe(in_buffer):
return pe_file, pe_data
# Parse & Extract Portwell UEFI Unpacker
def portwell_efi_extract(input_buffer, output_path, padding=0):
def portwell_efi_extract(input_file, extract_path, padding=0):
efi_files = [] # Initialize EFI Payload file chunks
extract_path = os.path.join(f'{output_path}_extracted')
input_buffer = file_to_bytes(input_file)
make_dirs(extract_path, delete=True)
@ -132,32 +133,4 @@ def parse_efi_files(extract_path, efi_files, padding):
os.remove(comp_fname) # Successful decompression, delete compressed file
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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
if not is_portwell_efi(input_buffer):
printer('Error: This is not a Portwell EFI Update Package!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
portwell_efi_extract(input_buffer, extract_path, padding)
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
BIOSUtility(TITLE, is_portwell_efi, portwell_efi_extract).run_utility()

419
README.md
View file

@ -50,32 +50,6 @@ Optionally, to decompile the AMI PFAT \> Intel BIOS Guard Scripts, you must have
* [BIOS Guard Script Tool](https://github.com/platomav/BGScriptTool) (i.e. big_script_tool.py)
#### **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:
> BIOS Guard Script Tool (optional)
4. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/AMI_PFAT_Extract.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**
![]()
@ -114,34 +88,6 @@ Optionally, to decompile the AMI UCP \> AMI PFAT \> Intel BIOS Guard Scripts (wh
* [BIOS Guard Script Tool](https://github.com/platomav/BGScriptTool) (i.e. big_script_tool.py)
#### **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:
> TianoCompress\
> 7-Zip Console\
> BIOS Guard Script Tool (optional)
4. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/AMI_UCP_Extract.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**
![]()
@ -172,28 +118,6 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3
To run the utility, you do not need any prerequisites.
#### **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. Build/Freeze/Compile:
> pyinstaller --noupx --onefile \<path-to-project\>\/Apple_EFI_IM4P.py
At dist folder you should find the final utility executable
#### **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**
![]()
@ -228,33 +152,6 @@ To run the utility, you must have the following 3rd party tools at the "external
* [UEFIFind](https://github.com/LongSoft/UEFITool/) (i.e. [UEFIFind.exe for Windows or UEFIFind for Linux](https://github.com/LongSoft/UEFITool/releases))
* [UEFIExtract](https://github.com/LongSoft/UEFITool/) (i.e. [UEFIExtract.exe for Windows or UEFIExtract for Linux](https://github.com/LongSoft/UEFITool/releases))
#### **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:
> UEFIFind\
> UEFIExtract
4. Build/Freeze/Compile:
> 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**
![]()
@ -287,32 +184,6 @@ To run the utility, you must have the following 3rd party tools at the "external
* [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**
![]()
@ -345,32 +216,6 @@ To run the utility, you must have the following 3rd party tools at the "external
* [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
#### **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**
![]()
@ -403,32 +248,6 @@ To run the utility, you must have the following 3rd party tool at the "external"
* [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 prerequisite at the "external" project directory:
> 7-Zip Console
4. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Award_BIOS_Extract.py
At dist folder you should find the final utility executable
#### **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**
![]()
@ -463,32 +282,6 @@ Optionally, to decompile the Intel BIOS Guard (PFAT) Scripts, you must have the
* [BIOS Guard Script Tool](https://github.com/platomav/BGScriptTool) (i.e. big_script_tool.py)
#### **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:
> BIOS Guard Script Tool (optional)
4. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Dell_PFS_Extract.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**
![]()
@ -521,32 +314,6 @@ To run the utility, you must have the following 3rd party tool at the "external"
* [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 prerequisite at the "external" project directory:
> 7-Zip Console
4. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Fujitsu_SFX_Extract.py
At dist folder you should find the final utility executable
#### **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**
![]()
@ -579,32 +346,6 @@ To run the utility, you must have the following 3rd party tool at the "external"
* [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (i.e. [TianoCompress.exe for Windows](https://github.com/tianocore/edk2-BaseTools-win32/) or TianoCompress 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 prerequisite at the "external" project directory:
> TianoCompress
4. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Fujitsu_UPC_Extract.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**
![]()
@ -635,28 +376,6 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3
To run the utility, you do not need any prerequisites.
#### **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. Build/Freeze/Compile:
> pyinstaller --noupx --onefile \<path-to-project\>\/Insyde_IFD_Extract.py
At dist folder you should find the final utility executable
#### **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**
![]()
@ -694,36 +413,6 @@ Moreover, you must have the following 3rd party tool at the "external" project d
* [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. Use pip to install pefile and lznt1:
> pip3 install pefile lznt1
4. Place prerequisite at the "external" project directory:
> 7-Zip Console
5. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Panasonic_BIOS_Extract.py
At dist folder you should find the final utility executable
#### **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**
![]()
@ -756,32 +445,6 @@ To run the utility, you must have the following 3rd party Python module installe
* [pefile](https://pypi.org/project/pefile/)
#### **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. Use pip to install pefile:
> pip3 install pefile
4. Build/Freeze/Compile:
> pyinstaller --noupx --onefile \<path-to-project\>\/Phoenix_TDK_Extract.py
At dist folder you should find the final utility executable
#### **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**
![]()
@ -820,36 +483,6 @@ Moreover, you must have the following 3rd party tool at the "external" project d
* [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (i.e. [TianoCompress.exe for Windows](https://github.com/tianocore/edk2-BaseTools-win32/) or TianoCompress 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. Use pip to install pefile:
> pip3 install pefile
4. Place prerequisite at the "external" project directory:
> TianoCompress
5. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Portwell_EFI_Extract.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**
![]()
@ -882,32 +515,6 @@ To run the utility, you must have the following 3rd party tool at the "external"
* [ToshibaComExtractor](https://github.com/LongSoft/ToshibaComExtractor) (i.e. [comextract.exe for Windows or comextract for Linux](https://github.com/LongSoft/ToshibaComExtractor/releases))
#### **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 prerequisite at the "external" project directory:
> ToshibaComExtractor
4. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Toshiba_COM_Extract.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**
![]()
@ -940,32 +547,6 @@ To run the utility, you must have the following 3rd party tool at the "external"
* [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 prerequisite at the "external" project directory:
> 7-Zip Console
4. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/VAIO_Package_Extract.py
At dist folder you should find the final utility executable
#### **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**
![]()

View file

@ -7,7 +7,7 @@ Toshiba BIOS COM Extractor
Copyright (C) 2018-2022 Plato Mavropoulos
"""
TITLE = 'Toshiba BIOS COM Extractor v2.0_a3'
TITLE = 'Toshiba BIOS COM Extractor v2.0_a4'
import os
import sys
@ -16,9 +16,11 @@ import subprocess
# Stop __pycache__ generation
sys.dont_write_bytecode = True
from common.path_ops import make_dirs, path_stem, path_suffixes, project_root, safe_path
from common.externals import get_comextract_path
from common.path_ops import make_dirs, path_stem, path_suffixes
from common.patterns import PAT_TOSHIBA_COM
from common.system import argparse_init, get_os_ver, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
# Check if input is Toshiba BIOS COM image
@ -31,15 +33,12 @@ def is_toshiba_com(in_file):
return is_ext and is_com
# Get ToshibaComExtractor path
def get_comextract_path():
exec_name = 'comextract.exe' if get_os_ver()[1] else 'comextract'
return safe_path(project_root(), ['external',exec_name])
# Parse & Extract Toshiba BIOS COM image
def toshiba_com_extract(input_file, output_path, padding=0):
extract_path = os.path.join(f'{output_path}_extracted')
def toshiba_com_extract(input_file, extract_path, padding=0):
if not os.path.isfile(input_file):
printer('Error: Could not find input file path!', padding)
return 1
make_dirs(extract_path, delete=True)
@ -51,41 +50,14 @@ def toshiba_com_extract(input_file, output_path, padding=0):
if not os.path.isfile(output_file):
raise Exception('EXTRACT_FILE_MISSING')
except:
except Exception:
printer(f'Error: ToshibaComExtractor could not extract file {input_file}!', padding)
return 1
return 2
printer(f'Succesfull {output_name} extraction via ToshibaComExtractor!', padding)
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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
if not is_toshiba_com(input_file):
printer('Error: This is not a Toshiba BIOS COM image!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
if toshiba_com_extract(input_file, extract_path, padding) == 0:
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
BIOSUtility(TITLE, is_toshiba_com, toshiba_com_extract).run_utility()

View file

@ -7,7 +7,7 @@ VAIO Packaging Manager Extractor
Copyright (C) 2019-2022 Plato Mavropoulos
"""
TITLE = 'VAIO Packaging Manager Extractor v3.0_a7'
TITLE = 'VAIO Packaging Manager Extractor v3.0_a8'
import os
import sys
@ -18,7 +18,8 @@ sys.dont_write_bytecode = True
from common.comp_szip import is_szip_supported, szip_decompress
from common.path_ops import make_dirs
from common.patterns import PAT_VAIO_CAB, PAT_VAIO_CFG, PAT_VAIO_CHK, PAT_VAIO_EXT
from common.system import argparse_init, printer, script_init
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
# Check if input is VAIO Packaging Manager
@ -125,14 +126,16 @@ def vaio_unlock(name, buffer, extract_path, padding=0):
return 0
# Parse & Extract or Unlock VAIO Packaging Manager
def vaio_pkg_extract(name, buffer, output_path, padding=0):
extract_path = os.path.join(f'{output_path}_extracted')
def vaio_pkg_extract(input_file, extract_path, padding=0):
input_buffer = file_to_bytes(input_file)
input_name = os.path.basename(input_file)
make_dirs(extract_path, delete=True)
if vaio_cabinet(name, buffer, extract_path, padding) == 0:
if vaio_cabinet(input_name, input_buffer, extract_path, padding) == 0:
printer('Successfully Extracted!', padding)
elif vaio_unlock(name, bytearray(buffer), extract_path, padding) == 0:
elif vaio_unlock(input_name, bytearray(input_buffer), extract_path, padding) == 0:
printer('Successfully Unlocked!', padding)
else:
printer('Error: Failed to Extract or Unlock executable!', padding)
@ -141,32 +144,4 @@ def vaio_pkg_extract(name, buffer, output_path, padding=0):
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)
with open(input_file, 'rb') as in_file:
input_buffer = in_file.read()
# Check if VAIO Packaging Manager pattern was found on executable
if not is_vaio_pkg(input_buffer):
printer('Error: This is not a VAIO Packaging Manager executable!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
if vaio_pkg_extract(input_name, input_buffer, extract_path, padding) == 0:
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)
BIOSUtility(TITLE, is_vaio_pkg, vaio_pkg_extract).run_utility()

View file

@ -45,7 +45,7 @@ def efi_decompress(in_path, out_path, padding=0, silent=False, comp_type='--uefi
if os.path.getsize(out_path) != size_orig:
raise Exception('EFI_DECOMPRESS_ERROR')
except:
except Exception:
if not silent:
printer(f'Error: TianoCompress could not extract file {in_path}!', padding)

View file

@ -34,7 +34,7 @@ def is_szip_supported(in_path, padding=0, args=None, check=False, silent=False):
if check:
check_bad_exit_code(szip_t.returncode)
except:
except Exception:
if not silent:
printer(f'Error: 7-Zip could not check support for file {in_path}!', padding)
@ -60,7 +60,7 @@ def szip_decompress(in_path, out_path, in_name, padding=0, args=None, check=Fals
if not os.path.isdir(out_path):
raise Exception('EXTRACT_DIR_MISSING')
except:
except Exception:
if not silent:
printer(f'Error: 7-Zip could not extract {in_name} file {in_path}!', padding)

View file

@ -12,8 +12,9 @@ from common.system import get_os_ver
# https://github.com/platomav/BGScriptTool by Plato Mavropoulos
def get_bgs_tool():
try:
from external.big_script_tool import BigScript
except:
# noinspection PyUnresolvedReferences
from external.big_script_tool import BigScript # pylint: disable=E0401,E0611
except Exception:
BigScript = None
return BigScript
@ -22,10 +23,16 @@ def get_bgs_tool():
def get_uefifind_path():
exec_name = f'UEFIFind{".exe" if get_os_ver()[1] else ""}'
return safe_path(project_root(), ['external',exec_name])
return safe_path(project_root(), ['external', exec_name])
# Get UEFIExtract path
def get_uefiextract_path():
exec_name = f'UEFIExtract{".exe" if get_os_ver()[1] else ""}'
return safe_path(project_root(), ['external',exec_name])
return safe_path(project_root(), ['external', exec_name])
# Get ToshibaComExtractor path
def get_comextract_path():
exec_name = f'comextract{".exe" if get_os_ver()[1] else ""}'
return safe_path(project_root(), ['external', exec_name])

View file

@ -130,58 +130,13 @@ def get_dequoted_path(in_path):
return out_path
# Get absolute file path of argparse object
def get_argparse_path(argparse_path):
if not argparse_path:
# Use runtime directory if no user path is specified
absolute_path = runtime_root()
else:
# Check if user specified path is absolute
if is_path_absolute(argparse_path):
absolute_path = argparse_path
# Otherwise, make it runtime directory relative
else:
absolute_path = safe_path(runtime_root(), argparse_path)
return absolute_path
# Set utility extraction stem
def extract_suffix():
return '_extracted'
# Process input files (argparse object)
def process_input_files(argparse_args, sys_argv=None):
input_files = []
if sys_argv is None:
sys_argv = []
if len(sys_argv) >= 2:
# Drag & Drop or CLI
if argparse_args.input_dir:
input_path_user = argparse_args.input_dir
input_path_full = get_argparse_path(input_path_user) if input_path_user else ''
input_files = get_path_files(input_path_full)
else:
# Parse list of input files (i.e. argparse FileType objects)
for file_object in argparse_args.files:
# Store each argparse FileType object's name (i.e. path)
input_files.append(file_object.name)
# Close each argparse FileType object (i.e. allow input file changes)
file_object.close()
# Set output fallback value for missing argparse Output and Input Path
output_fallback = path_parent(input_files[0]) if input_files else None
# Set output path via argparse Output path or argparse Input path or first input file path
output_path = argparse_args.output_dir or argparse_args.input_dir or output_fallback
else:
# Script w/o parameters
input_path_user = get_dequoted_path(input('\nEnter input directory path: '))
input_path_full = get_argparse_path(input_path_user) if input_path_user else ''
input_files = get_path_files(input_path_full)
output_path = get_dequoted_path(input('\nEnter output directory path: '))
output_path_final = get_argparse_path(output_path)
return input_files, output_path_final
# Get utility extraction path
def get_extract_path(in_path, suffix=extract_suffix()):
return f'{in_path}{suffix}'
# Get project's root directory
def project_root():

View file

@ -21,7 +21,7 @@ def get_pe_file(in_file, fast=True):
try:
# Analyze detected MZ > PE image buffer
pe_file = pefile.PE(data=in_buffer, fast_load=fast)
except:
except Exception:
pe_file = None
return pe_file
@ -34,7 +34,7 @@ def get_pe_info(pe_file):
# Retrieve MZ > PE > FileInfo > StringTable information
pe_info = pe_file.FileInfo[0][0].StringTable[0].entries
except:
except Exception:
pe_info = {}
return pe_info

View file

@ -6,12 +6,8 @@ Copyright (C) 2022 Plato Mavropoulos
"""
import sys
import ctypes
import argparse
import traceback
from common.text_ops import padder, to_string
from common.path_ops import process_input_files
# Get Python Version (tuple)
def get_py_ver():
@ -59,62 +55,6 @@ def check_sys_os():
if os_win:
sys.stdout.reconfigure(encoding='utf-8')
# Initialize common argparse arguments
def argparse_init():
argparser = argparse.ArgumentParser()
argparser.add_argument('files', type=argparse.FileType('r'), nargs='*')
argparser.add_argument('-e', '--auto-exit', help='skip press enter to exit prompts', action='store_true')
argparser.add_argument('-v', '--version', help='show utility name and version', action='store_true')
argparser.add_argument('-o', '--output-dir', help='extract in given output directory')
argparser.add_argument('-i', '--input-dir', help='extract from given input directory')
return argparser
# Initialize Script (must be after argparse)
def script_init(title, arguments, padding=0):
# Pretty Python exception handler
sys.excepthook = nice_exc_handler
# Check Python Version
check_sys_py()
# Check OS Platform
check_sys_os()
# Show Script Title
printer(title, new_line=False)
# Show Utility Version on demand
if arguments.version:
sys.exit(0)
# Set console/terminal window title (Windows only)
if get_os_ver()[1]:
ctypes.windll.kernel32.SetConsoleTitleW(title)
# Process input files and generate output path
input_files,output_path = process_input_files(arguments, sys.argv)
# Count input files for exit code
input_count = len(input_files)
return input_count, input_files, output_path, padding
# https://stackoverflow.com/a/781074 by Torsten Marek
def nice_exc_handler(exc_type, exc_value, tb):
if exc_type is KeyboardInterrupt:
printer('')
else:
printer('Error: Script crashed, please report the following:\n')
traceback.print_exception(exc_type, exc_value, tb)
if not is_auto_exit():
input('\nPress enter to exit')
sys.exit(127)
# Show message(s) while controlling padding, newline, pausing & separator
def printer(in_message='', padd_count=0, new_line=True, pause=False, sep_char=' '):
message = to_string(in_message, sep_char)

152
common/templates.py Normal file
View file

@ -0,0 +1,152 @@
#!/usr/bin/env python3
#coding=utf-8
"""
Copyright (C) 2022 Plato Mavropoulos
"""
import os
import sys
import ctypes
import argparse
import traceback
from common.path_ops import runtime_root, is_path_absolute, safe_path, get_dequoted_path, get_path_files, path_parent, get_extract_path
from common.system import check_sys_py, check_sys_os, get_os_ver, printer, is_auto_exit
class BIOSUtility:
def __init__(self, title, check, main, padding=0):
self._title = title
self._main = main
self._check = check
self._padding = padding
self._arguments_kw = {}
# Initialize argparse argument parser
self._argparser = argparse.ArgumentParser()
self._argparser.add_argument('files', type=argparse.FileType('r', encoding='utf-8'), nargs='*')
self._argparser.add_argument('-e', '--auto-exit', help='skip press enter to exit prompts', action='store_true')
self._argparser.add_argument('-v', '--version', help='show utility name and version', action='store_true')
self._argparser.add_argument('-o', '--output-dir', help='extract in given output directory')
self._argparser.add_argument('-i', '--input-dir', help='extract from given input directory')
self._arguments,self._arguments_unk = self._argparser.parse_known_args()
# Managed Python exception handler
sys.excepthook = self._exception_handler
# Check Python Version
check_sys_py()
# Check OS Platform
check_sys_os()
# Show Script Title
printer(self._title, new_line=False)
# Show Utility Version on demand
if self._arguments.version:
sys.exit(0)
# Set console/terminal window title (Windows only)
if get_os_ver()[1]:
ctypes.windll.kernel32.SetConsoleTitleW(self._title)
# Process input files and generate output path
self._process_input_files()
# Count input files for exit code
self.exit_code = len(self._input_files)
def parse_argument(self, *args, **kwargs):
_dest = self._argparser.add_argument(*args, **kwargs).dest
self._arguments = self._argparser.parse_known_args(self._arguments_unk)[0]
self._arguments_kw.update({_dest: self._arguments.__dict__[_dest]})
def run_utility(self):
for _input_file in self._input_files:
_input_name = os.path.basename(_input_file)
printer(['***', _input_name], self._padding)
if not self._check(_input_file):
printer('Error: This is not a supported input!', self._padding + 4)
continue # Next input file
_extract_path = os.path.join(self._output_path, get_extract_path(_input_name))
if self._main(_input_file, _extract_path, self._padding + 4, **self._arguments_kw) in [0, None]:
self.exit_code -= 1
#print(self.exit_code)
printer('Done!', pause=True)
sys.exit(self.exit_code)
# Process input files
def _process_input_files(self):
self._input_files = []
if len(sys.argv) >= 2:
# Drag & Drop or CLI
if self._arguments.input_dir:
_input_path_user = self._arguments.input_dir
_input_path_full = self._get_input_path(_input_path_user) if _input_path_user else ''
self._input_files = get_path_files(_input_path_full)
else:
# Parse list of input files (i.e. argparse FileType objects)
for _file_object in self._arguments.files:
# Store each argparse FileType object's name (i.e. path)
self._input_files.append(_file_object.name)
# Close each argparse FileType object (i.e. allow input file changes)
_file_object.close()
# Set output fallback value for missing argparse Output and Input Path
_output_fallback = path_parent(self._input_files[0]) if self._input_files else None
# Set output path via argparse Output path or argparse Input path or first input file path
_output_path = self._arguments.output_dir or self._arguments.input_dir or _output_fallback
else:
# Script w/o parameters
_input_path_user = get_dequoted_path(input('\nEnter input directory path: '))
_input_path_full = self._get_input_path(_input_path_user) if _input_path_user else ''
self._input_files = get_path_files(_input_path_full)
_output_path = get_dequoted_path(input('\nEnter output directory path: '))
self._output_path = self._get_input_path(_output_path)
# Get absolute input file path
@staticmethod
def _get_input_path(input_path):
if not input_path:
# Use runtime directory if no user path is specified
absolute_path = runtime_root()
else:
# Check if user specified path is absolute
if is_path_absolute(input_path):
absolute_path = input_path
# Otherwise, make it runtime directory relative
else:
absolute_path = safe_path(runtime_root(), input_path)
return absolute_path
# https://stackoverflow.com/a/781074 by Torsten Marek
@staticmethod
def _exception_handler(exc_type, exc_value, exc_traceback):
if exc_type is KeyboardInterrupt:
printer('')
else:
printer('Error: Utility crashed, please report the following:\n')
traceback.print_exception(exc_type, exc_value, exc_traceback)
if not is_auto_exit():
input('\nPress enter to exit')
sys.exit(127)

View file

@ -1,2 +1,2 @@
lznt1==0.2
pefile==2022.5.30
lznt1 >= 0.2
pefile >= 2022.5.30