mirror of
https://github.com/platomav/BIOSUtilities.git
synced 2025-05-13 06:34:42 -04:00
Created common template for executing all utilities
Unified extracted output directory naming logic Multiple code fixes, refactors and improvements
This commit is contained in:
parent
5f364f4759
commit
6de50c422f
26 changed files with 377 additions and 1169 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Skip all external files
|
||||
external/*
|
||||
|
||||
# Keep external > requirements file
|
||||
!external/requirements.txt
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
@ -995,51 +1018,7 @@ 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)
|
||||
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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
419
README.md
|
@ -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**
|
||||
|
||||
![]()
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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)
|
||||
# Set utility extraction stem
|
||||
def extract_suffix():
|
||||
return '_extracted'
|
||||
|
||||
return absolute_path
|
||||
|
||||
# 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():
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
152
common/templates.py
Normal 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)
|
4
external/requirements.txt
vendored
4
external/requirements.txt
vendored
|
@ -1,2 +1,2 @@
|
|||
lznt1==0.2
|
||||
pefile==2022.5.30
|
||||
lznt1 >= 0.2
|
||||
pefile >= 2022.5.30
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue