Initial refactor commit

Added AMI UCP BIOS Extractor v2.0_a1

Added AMI BIOS Guard Extractor v4.0_a1
This commit is contained in:
platomav 2022-04-01 17:43:22 +03:00
parent 2029ffc8b7
commit 132457afda
14 changed files with 1240 additions and 731 deletions

352
AMI_PFAT_Extract.py Normal file
View file

@ -0,0 +1,352 @@
#!/usr/bin/env python3
#coding=utf-8
"""
AMI PFAT Extract
AMI BIOS Guard Extractor
Copyright (C) 2018-2022 Plato Mavropoulos
"""
title = 'AMI BIOS Guard Extractor v4.0_a1'
import os
import re
import sys
import shutil
import ctypes
# Stop __pycache__ generation
sys.dont_write_bytecode = True
from common.patterns import PAT_AMI_PFAT
from common.externals import get_bgs_tool
from common.num_ops import get_ordinal
from common.text_ops import padder
from common.path_ops import argparse_init, process_input_files, safe_name
from common.struct_ops import get_struct, char, uint8_t, uint16_t, uint32_t
from common.system import nice_exc_handler, check_sys_py, check_sys_os, show_title, print_input
class AmiBiosGuardHeader(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
('Size', uint32_t), # 0x00 Header + Entries
('Checksum', uint32_t), # 0x04 ?
('Tag', char*8), # 0x04 _AMIPFAT
('Flags', uint8_t), # 0x10 ?
# 0x11
]
def struct_print(self, padding):
p = padder(padding)
print(p + 'Size :', '0x%X' % self.Size)
print(p + 'Checksum:', '0x%0.4X' % self.Checksum)
print(p + 'Tag :', self.Tag.decode('utf-8'))
print(p + 'Flags :', '0x%0.2X' % self.Flags)
class IntelBiosGuardHeader(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
('BGVerMajor', uint16_t), # 0x00
('BGVerMinor', uint16_t), # 0x02
('PlatformID', uint8_t*16), # 0x04
('Attributes', uint32_t), # 0x14
('ScriptVerMajor', uint16_t), # 0x16
('ScriptVerMinor', uint16_t), # 0x18
('ScriptSize', uint32_t), # 0x1C
('DataSize', uint32_t), # 0x20
('BIOSSVN', uint32_t), # 0x24
('ECSVN', uint32_t), # 0x28
('VendorInfo', uint32_t), # 0x2C
# 0x30
]
def get_platform_id(self):
id_byte = bytes(self.PlatformID)
id_text = re.sub(r'[\n\t\r\x00 ]', '', id_byte.decode('utf-8','ignore'))
id_hexs = '%0.*X' % (0x10 * 2, int.from_bytes(id_byte, 'big'))
id_guid = '{%s-%s-%s-%s-%s}' % (id_hexs[:8], id_hexs[8:12], id_hexs[12:16], id_hexs[16:20], id_hexs[20:])
return '%s %s' % (id_text, id_guid)
def get_flags(self):
attr = IntelBiosGuardHeaderGetAttributes()
attr.asbytes = self.Attributes
return attr.b.SFAM, attr.b.ProtectEC, attr.b.GFXMitDis, attr.b.FTU, attr.b.Reserved
def struct_print(self, padding):
p = padder(padding)
no_yes = ['No','Yes']
f1,f2,f3,f4,f5 = self.get_flags()
print(p + 'BIOS Guard Version :', '%d.%d' % (self.BGVerMajor, self.BGVerMinor))
print(p + 'Platform Identity :', self.get_platform_id())
print(p + 'Signed Flash Address Map :', no_yes[f1])
print(p + 'Protected EC OpCodes :', no_yes[f2])
print(p + 'Graphics Security Disable :', no_yes[f3])
print(p + 'Fault Tolerant Update :', no_yes[f4])
print(p + 'Attributes Reserved :', '0x%X' % f5)
print(p + 'Script Version :', '%d.%d' % (self.ScriptVerMajor, self.ScriptVerMinor))
print(p + 'Script Size :', '0x%X' % self.ScriptSize)
print(p + 'Data Size :', '0x%X' % self.DataSize)
print(p + 'BIOS Security Version Number:', '0x%X' % self.BIOSSVN)
print(p + 'EC Security Version Number :', '0x%X' % self.ECSVN)
print(p + 'Vendor Information :', '0x%X' % self.VendorInfo)
class IntelBiosGuardHeaderAttributes(ctypes.LittleEndianStructure):
_fields_ = [
('SFAM', uint32_t, 1), # Signed Flash Address Map
('ProtectEC', uint32_t, 1), # Protected EC OpCodes
('GFXMitDis', uint32_t, 1), # GFX Security Disable
('FTU', uint32_t, 1), # Fault Tolerant Update
('Reserved', uint32_t, 28) # Reserved/Unknown
]
class IntelBiosGuardHeaderGetAttributes(ctypes.Union):
_fields_ = [
('b', IntelBiosGuardHeaderAttributes),
('asbytes', uint32_t)
]
class IntelBiosGuardSignature2k(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
('Unknown0', uint32_t), # 0x000
('Unknown1', uint32_t), # 0x004
('Modulus', uint32_t*64), # 0x008
('Exponent', uint32_t), # 0x108
('Signature', uint32_t*64), # 0x10C
# 0x20C
]
def struct_print(self, padding):
p = padder(padding)
Modulus = '%0.*X' % (0x100 * 2, int.from_bytes(self.Modulus, 'little'))
Signature = '%0.*X' % (0x100 * 2, int.from_bytes(self.Signature, 'little'))
print(p + 'Unknown 0:', '0x%X' % self.Unknown0)
print(p + 'Unknown 1:', '0x%X' % self.Unknown1)
print(p + 'Modulus :', '%s [...]' % Modulus[:32])
print(p + 'Exponent :', '0x%X' % self.Exponent)
print(p + 'Signature:', '%s [...]' % Signature[:32])
def get_ami_pfat(input_buffer):
match = PAT_AMI_PFAT.search(input_buffer)
buffer = input_buffer[match.start() - 0x8:] if match else b''
return match, buffer
def get_file_name(index, title):
return safe_name('%0.2d -- %s' % (index, title))
def parse_bg_script(script_data, padding):
is_opcode_div = len(script_data) % 8 == 0
if not is_opcode_div:
print('%sError: Script not divisible by OpCode length!' % padder(padding))
return 1
is_begin_end = script_data[:8] + script_data[-8:] == b'\x01' + b'\x00' * 7 + b'\xFF' + b'\x00' * 7
if not is_begin_end:
print('%sError: Script lacks Begin and/or End OpCodes!' % padder(padding))
return 2
BigScript = get_bgs_tool()
if not BigScript:
print('%sError: BIOS Guard Script Tool dependency missing!' % padder(padding))
return 3
script = BigScript(code_bytes=script_data).to_string().replace('\t',' ').split('\n')
for opcode in script:
if opcode.endswith(('begin','end')): spacing = padder(padding)
elif opcode.endswith(':'): spacing = padder(padding + 4)
else: spacing = padder(padding + 12)
operands = [operand for operand in opcode.split(' ') if operand]
print(spacing + ('{:<12s}' + '{:<11s}' * (len(operands) - 1)).format(*operands))
return 0
def parse_pfat_hdr(buffer, padding):
block_all = []
pfat_hdr = get_struct(buffer, 0x0, AmiBiosGuardHeader)
hdr_size = pfat_hdr.Size
hdr_data = buffer[PFAT_AMI_HDR_LEN:hdr_size]
hdr_text = hdr_data.decode('utf-8').splitlines()
print('\n%sAMI BIOS Guard Header:\n' % padder(padding))
pfat_hdr.struct_print(padding + 4)
hdr_title,*hdr_files = hdr_text
files_count = len(hdr_files)
hdr_tag,*hdr_indexes = hdr_title.split('II')
print('\n%s%s\n' % (padder(padding + 4), hdr_tag))
bgt_indexes = [int(h, 16) for h in re.findall(r'.{1,4}', hdr_indexes[0])] if hdr_indexes else []
for index,entry in enumerate(hdr_files):
entry_parts = entry.split(';')
info = entry_parts[0].split()
name = entry_parts[1]
flags = int(info[0])
param = info[1]
count = int(info[2])
order = get_ordinal((bgt_indexes[index] if bgt_indexes else index) + 1)
desc = '%s (Index: %0.2d, Flash: %s, Parameter: %s, Flags: 0x%X, Blocks: %d)' % (name, index + 1, order, param, flags, count)
block_all += [(desc, name, order, param, flags, index, i, count) for i in range(count)]
_ = [print(padder(padding + 8) + block[0]) for block in block_all if block[6] == 0]
return block_all, hdr_size, files_count
def parse_pfat_file(buffer, output_path, padding):
file_path = ''
all_blocks_dict = {}
extract_name = os.path.basename(output_path)
extract_path = os.path.join(output_path + '_extracted', '')
if os.path.isdir(extract_path): shutil.rmtree(extract_path)
os.mkdir(extract_path)
block_all,block_off,file_count = parse_pfat_hdr(buffer, padding)
for block in block_all:
file_desc,file_name,_,_,_,file_index,block_index,block_count = block
if block_index == 0:
print('\n%s%s' % (padder(padding + 4), file_desc))
file_path = os.path.join(extract_path, get_file_name(file_index + 1, file_name))
all_blocks_dict[file_index] = b''
block_status = '%d/%d' % (block_index + 1, block_count)
bg_hdr = get_struct(buffer, block_off, IntelBiosGuardHeader)
print('\n%sIntel BIOS Guard %s Header:\n' % (padder(padding + 8), block_status))
bg_hdr.struct_print(padding + 12)
bg_script_bgn = block_off + PFAT_BLK_HDR_LEN
bg_script_end = bg_script_bgn + bg_hdr.ScriptSize
bg_script_bin = buffer[bg_script_bgn:bg_script_end]
bg_data_bgn = bg_script_end
bg_data_end = bg_data_bgn + bg_hdr.DataSize
bg_data_bin = buffer[bg_data_bgn:bg_data_end]
block_off = bg_data_end # Assume next block starts at data end
is_sfam,_,_,_,_ = bg_hdr.get_flags() # SFAM, ProtectEC, GFXMitDis, FTU, Reserved
if is_sfam:
bg_sig_bgn = bg_data_end
bg_sig_end = bg_sig_bgn + PFAT_BLK_S2K_LEN
bg_sig_bin = buffer[bg_sig_bgn:bg_sig_end]
if len(bg_sig_bin) == PFAT_BLK_S2K_LEN:
bg_sig = get_struct(bg_sig_bin, 0x0, IntelBiosGuardSignature2k)
print('\n%sIntel BIOS Guard %s Signature:\n' % (padder(padding + 8), block_status))
bg_sig.struct_print(padding + 12)
block_off = bg_sig_end # Adjust next block to start at data + signature end
print('\n%sIntel BIOS Guard %s Script:\n' % (padder(padding + 8), block_status))
_ = parse_bg_script(bg_script_bin, padding + 12)
with open(file_path, 'ab') as out_dat: out_dat.write(bg_data_bin)
all_blocks_dict[file_index] += bg_data_bin
pfat_oob_data = buffer[block_off:] # Store out-of-bounds data after the end of PFAT files
pfat_oob_path = os.path.join(extract_path, get_file_name(file_count + 1, extract_name + '_OOB.bin'))
with open(pfat_oob_path, 'wb') as out_oob: out_oob.write(pfat_oob_data)
oob_pfat_match,pfat_oob_buffer = get_ami_pfat(pfat_oob_data)
if oob_pfat_match: parse_pfat_file(pfat_oob_buffer, pfat_oob_path, padding)
in_all_data = b''.join([block[1] for block in sorted(all_blocks_dict.items())])
in_all_path = os.path.join(extract_path, get_file_name(0, extract_name + '_ALL.bin'))
with open(in_all_path, 'wb') as out_all: out_all.write(in_all_data + pfat_oob_data)
PFAT_AMI_HDR_LEN = ctypes.sizeof(AmiBiosGuardHeader)
PFAT_BLK_HDR_LEN = ctypes.sizeof(IntelBiosGuardHeader)
PFAT_BLK_S2K_LEN = ctypes.sizeof(IntelBiosGuardSignature2k)
if __name__ == '__main__':
# Show script title
show_title(title)
# Set argparse Arguments
argparser = argparse_init()
arguments = argparser.parse_args()
# Pretty Python exception handler (must be after argparse)
sys.excepthook = nice_exc_handler
# Check Python Version (must be after argparse)
check_sys_py()
# Check OS Platform (must be after argparse)
check_sys_os()
# Process input files and generate output path
input_files,output_path = process_input_files(arguments, sys.argv)
# Initial output padding count
padding = 4
for input_file in input_files:
input_name = os.path.basename(input_file)
print('\n*** %s' % input_name)
with open(input_file, 'rb') as in_file: input_buffer = in_file.read()
pfat_match,pfat_buffer = get_ami_pfat(input_buffer)
if not pfat_match:
print('\n%sError: This is not an AMI BIOS Guard (PFAT) image!' % padder(padding))
continue # Next input file
extract_path = os.path.join(output_path, input_name)
parse_pfat_file(pfat_buffer, extract_path, padding)
print_input('\nDone!')

514
AMI_UCP_Extract.py Normal file
View file

@ -0,0 +1,514 @@
#!/usr/bin/env python3
#coding=utf-8
"""
AMI UCP Extract
AMI UCP BIOS Extractor
Copyright (C) 2021-2022 Plato Mavropoulos
"""
title = 'AMI UCP BIOS Extractor v2.0_a1'
import os
import sys
import shutil
import struct
import ctypes
import contextlib
# Stop __pycache__ generation
sys.dont_write_bytecode = True
from common.patterns import PAT_AMI_UCP, PAT_INTEL_ENG
from common.checksums import checksum16
from common.text_ops import padder
from common.a7z_comp import a7z_decompress, is_7z_supported
from common.efi_comp import efi_decompress, is_efi_compressed
from common.path_ops import argparse_init, process_input_files, safe_name
from common.struct_ops import get_struct, char, uint8_t, uint16_t, uint32_t
from common.system import nice_exc_handler, check_sys_py, check_sys_os, show_title, print_input
from AMI_PFAT_Extract import get_ami_pfat, parse_pfat_file
class UafHeader(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
('ModuleTag', char*4), # 0x00
('ModuleSize', uint32_t), # 0x04
('Checksum', uint16_t), # 0x08
('Unknown0', uint8_t), # 0x0A
('Unknown1', uint8_t), # 0x0A
('Reserved', uint32_t), # 0x0C
# 0x10
]
def struct_print(self, padding):
p = padder(padding)
print(p + 'Tag :', self.ModuleTag.decode('utf-8'))
print(p + 'Size :', '0x%X' % self.ModuleSize)
print(p + 'Checksum :', '0x%0.4X' % self.Checksum)
print(p + 'Unknown 0 :', '0x%0.2X' % self.Unknown0)
print(p + 'Unknown 1 :', '0x%0.2X' % self.Unknown1)
print(p + 'Reserved :', '0x%0.8X' % self.Reserved)
class UafModule(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
('CompressSize', uint32_t), # 0x00
('OriginalSize', uint32_t), # 0x04
# 0x08
]
def struct_print(self, padding, filename):
p = padder(padding)
print(p + 'Compress Size:', '0x%X' % self.CompressSize)
print(p + 'Original Size:', '0x%X' % self.OriginalSize)
print(p + 'File Name :', filename)
class UiiHeader(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
('UIISize', uint16_t), # 0x00
('Checksum', uint16_t), # 0x02
('UtilityVersion', uint32_t), # 0x04 AFU|BGT (Unknown, Signed)
('InfoSize', uint16_t), # 0x08
('SupportBIOS', uint8_t), # 0x0A
('SupportOS', uint8_t), # 0x0B
('DataBusWidth', uint8_t), # 0x0C
('ProgramType', uint8_t), # 0x0D
('ProgramMode', uint8_t), # 0x0E
('SourceSafeRel', uint8_t), # 0x0F
# 0x10
]
SBI = {1: 'ALL', 2: 'AMIBIOS8', 3: 'UEFI', 4: 'AMIBIOS8/UEFI'}
SOS = {1: 'DOS', 2: 'EFI', 3: 'Windows', 4: 'Linux', 5: 'FreeBSD', 6: 'MacOS', 128: 'Multi-Platform'}
DBW = {1: '16b', 2: '16/32b', 3: '32b', 4: '64b'}
PTP = {1: 'Executable', 2: 'Library', 3: 'Driver'}
PMD = {1: 'API', 2: 'Console', 3: 'GUI', 4: 'Console/GUI'}
def struct_print(self, padding, description):
p = padder(padding)
SupportBIOS = self.SBI.get(self.SupportBIOS, 'Unknown (%d)' % self.SupportBIOS)
SupportOS = self.SOS.get(self.SupportOS, 'Unknown (%d)' % self.SupportOS)
DataBusWidth = self.DBW.get(self.DataBusWidth, 'Unknown (%d)' % self.DataBusWidth)
ProgramType = self.PTP.get(self.ProgramType, 'Unknown (%d)' % self.ProgramType)
ProgramMode = self.PMD.get(self.ProgramMode, 'Unknown (%d)' % self.ProgramMode)
print(p + 'UII Size :', '0x%X' % self.UIISize)
print(p + 'Checksum :', '0x%0.4X' % self.Checksum)
print(p + 'Tool Version :', '0x%0.8X' % self.UtilityVersion)
print(p + 'Info Size :', '0x%X' % self.InfoSize)
print(p + 'Supported BIOS:', SupportBIOS)
print(p + 'Supported OS :', SupportOS)
print(p + 'Data Bus Width:', DataBusWidth)
print(p + 'Program Type :', ProgramType)
print(p + 'Program Mode :', ProgramMode)
print(p + 'SourceSafe Tag:', '%0.2d' % self.SourceSafeRel)
print(p + 'Description :', description)
class DisHeader(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
('PasswordSize', uint16_t), # 0x00
('EntryCount', uint16_t), # 0x02
('Password', char*12), # 0x04
# 0x10
]
def struct_print(self, padding):
p = padder(padding)
print(p + 'Password Size:', '0x%X' % self.PasswordSize)
print(p + 'Entry Count :', self.EntryCount)
print(p + 'Password :', self.Password.decode('utf-8'))
class DisModule(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
('EnabledDisabled', uint8_t), # 0x00
('ShownHidden', uint8_t), # 0x01
('Command', char*32), # 0x02
('Description', char*256), # 0x22
# 0x122
]
ENDIS = {0: 'Disabled', 1: 'Enabled'}
SHOWN = {0: 'Hidden', 1: 'Shown', 2: 'Shown Only'}
def struct_print(self, padding):
p = padder(padding)
EnabledDisabled = self.ENDIS.get(self.EnabledDisabled, 'Unknown (%d)' % self.EnabledDisabled)
ShownHidden = self.SHOWN.get(self.ShownHidden, 'Unknown (%d)' % self.ShownHidden)
print(p + 'State :', EnabledDisabled)
print(p + 'Display :', ShownHidden)
print(p + 'Command :', self.Command.decode('utf-8').strip())
print(p + 'Description:', self.Description.decode('utf-8').strip())
# Validate @UAF Module Checksum-16
def chk16_validate(data, tag, padd=0):
if checksum16(data) != 0:
print_input('\n%sError: Invalid UCP Module %s Checksum!' % (padder(padd), tag))
else:
print('\n%sChecksum of UCP Module %s is valid!' % (padder(padd), tag))
# Get all input file AMI UCP patterns
def get_ami_ucp(buffer):
uaf_len_max = 0x0 # Length of largest detected @UAF
uaf_hdr_off = 0x0 # Offset of largest detected @UAF
uaf_buf_bin = b'' # Buffer of largest detected @UAF
for uaf in PAT_AMI_UCP.finditer(buffer):
uaf_len_cur = int.from_bytes(buffer[uaf.start() + 0x4:uaf.start() + 0x8], 'little')
if uaf_len_cur > uaf_len_max:
uaf_len_max = uaf_len_cur
uaf_hdr_off = uaf.start()
uaf_buf_bin = buffer[uaf_hdr_off:uaf_hdr_off + uaf_len_max]
return uaf_hdr_off, uaf_buf_bin
# Get list of @UAF Modules
def get_uaf_mod(buffer, uaf_off=0x0):
uaf_all = [] # Initialize list of all @UAF Modules
while buffer[uaf_off] == 0x40: # ASCII of @ is 0x40
uaf_hdr = get_struct(buffer, uaf_off, UafHeader) # Parse @UAF Module Structure
uaf_tag = uaf_hdr.ModuleTag.decode('utf-8') # Get unique @UAF Module Tag
uaf_all.append([uaf_tag, uaf_off, uaf_hdr]) # Store @UAF Module Info
uaf_off += uaf_hdr.ModuleSize # Adjust to next @UAF Module offset
if uaf_off >= len(buffer): break # Stop parsing at EOF
# Check if @UAF Module NAL exists and place it first
# Parsing NAL first allows naming all @UAF Modules
for mod_idx,mod_val in enumerate(uaf_all):
if mod_val[0] == '@NAL':
uaf_all.insert(1, uaf_all.pop(mod_idx)) # After UII for visual purposes
break # NAL found, skip the rest
return uaf_all
# Parse & Extract AMI UCP structures
def ucp_extract(buffer, output_path, padding=0, is_chk16=False):
nal_dict = {} # Initialize @NAL Dictionary per UCP
print('\n%sUtility Configuration Program' % padder(padding))
extract_path = os.path.join(output_path + '_extracted', '')
if os.path.isdir(extract_path): shutil.rmtree(extract_path)
os.mkdir(extract_path)
uaf_hdr = get_struct(buffer, 0, UafHeader) # Parse @UAF Header Structure
print('\n%sUtility Auxiliary File > @UAF:\n' % padder(padding + 4))
uaf_hdr.struct_print(padding + 8)
fake = struct.pack('<II', len(buffer), len(buffer)) # Generate UafModule Structure
uaf_mod = get_struct(fake, 0x0, UafModule) # Parse UAF Module EFI Structure
uaf_mod.struct_print(padding + 8, UAF_TAG_DICT['@UAF'][0]) # Print @UAF Module EFI Info
if is_chk16: chk16_validate(buffer, '@UAF', padding + 8)
uaf_all = get_uaf_mod(buffer, UAF_HDR_LEN)
for mod_info in uaf_all:
nal_dict = uaf_extract(buffer, extract_path, mod_info, padding + 8, is_chk16, nal_dict)
# Parse & Extract AMI UCP > @UAF Module/Section
def uaf_extract(buffer, extract_path, mod_info, padding=0, is_chk16=False, nal_dict=None):
if nal_dict is None: nal_dict = {}
uaf_tag,uaf_off,uaf_hdr = mod_info
uaf_data_all = buffer[uaf_off:uaf_off + uaf_hdr.ModuleSize] # @UAF Module Entire Data
uaf_data_mod = uaf_data_all[UAF_HDR_LEN:] # @UAF Module EFI Data
uaf_data_raw = uaf_data_mod[UAF_MOD_LEN:] # @UAF Module Raw Data
print('\n%sUtility Auxiliary File > %s:\n' % (padder(padding), uaf_tag))
uaf_hdr.struct_print(padding + 4) # Print @UAF Module Info
uaf_mod = get_struct(buffer, uaf_off + UAF_HDR_LEN, UafModule) # Parse UAF Module EFI Structure
is_comp = uaf_mod.CompressSize != uaf_mod.OriginalSize # Detect @UAF Module EFI Compression
if uaf_tag in nal_dict: uaf_name = nal_dict[uaf_tag] # Always prefer NAL naming first
elif uaf_tag in UAF_TAG_DICT: uaf_name = UAF_TAG_DICT[uaf_tag][0] # Otherwise use built-in naming
elif uaf_tag == '@ROM': uaf_name = 'BIOS.bin' # BIOS/PFAT Firmware (w/o Signature)
elif uaf_tag.startswith('@R0'): uaf_name = 'BIOS_0%s.bin' % uaf_tag[3:] # BIOS/PFAT Firmware
elif uaf_tag.startswith('@S0'): uaf_name = 'BIOS_0%s.sig' % uaf_tag[3:] # BIOS/PFAT Signature
elif uaf_tag.startswith('@DR'): uaf_name = 'DROM_0%s.bin' % uaf_tag[3:] # Thunderbolt Retimer Firmware
elif uaf_tag.startswith('@DS'): uaf_name = 'DROM_0%s.sig' % uaf_tag[3:] # Thunderbolt Retimer Signature
elif uaf_tag.startswith('@EC'): uaf_name = 'EC_0%s.bin' % uaf_tag[3:] # Embedded Controller Firmware
elif uaf_tag.startswith('@ME'): uaf_name = 'ME_0%s.bin' % uaf_tag[3:] # Management Engine Firmware
else: uaf_name = uaf_tag # Could not name the @UAF Module, use Tag instead
uaf_fext = '' if uaf_name != uaf_tag else '.bin'
uaf_mod.struct_print(padding + 4, uaf_name + uaf_fext) # Print @UAF Module EFI Info
# Check if unknown @UAF Module Tag is present in NAL but not in built-in dictionary
if uaf_tag in nal_dict and uaf_tag not in UAF_TAG_DICT and not uaf_tag.startswith(('@ROM','@R0','@S0','@DR','@DS')):
print_input('\n%sNote: Detected new AMI UCP Module %s (%s) in NAL!' % (padder(padding), uaf_tag, nal_dict[uaf_tag]))
# Generate @UAF Module File name, depending on whether decompression will be required
uaf_fname = os.path.join(extract_path, safe_name(uaf_name + ('.temp' if is_comp else uaf_fext)))
if is_chk16: chk16_validate(uaf_data_all, uaf_tag, padding + 4)
# Parse Utility Identification Information @UAF Module (@UII)
if uaf_tag == '@UII':
info_hdr = get_struct(uaf_data_raw, 0, UiiHeader) # Parse @UII Module Raw Structure
info_data = uaf_data_raw[max(UII_HDR_LEN,info_hdr.InfoSize):info_hdr.UIISize] # @UII Module Info Data
# Get @UII Module Info/Description text field
info_desc = info_data.decode('utf-8','ignore').strip('\x00 ')
print('\n%sUtility Identification Information:\n' % padder(padding + 4))
info_hdr.struct_print(padding + 8, info_desc) # Print @UII Module Info
if is_chk16: chk16_validate(uaf_data_raw, '@UII > Info', padding + 8)
# Store/Save @UII Module Info in file
with open(uaf_fname[:-4] + '.txt', 'a', encoding='utf-8') as uii_out:
with contextlib.redirect_stdout(uii_out):
info_hdr.struct_print(0, info_desc) # Store @UII Module Info
# Adjust @UAF Module Raw Data for extraction
if is_comp:
# Some Compressed @UAF Module EFI data lack necessary EOF padding
if uaf_mod.CompressSize > len(uaf_data_raw):
comp_padd = b'\x00' * (uaf_mod.CompressSize - len(uaf_data_raw))
uaf_data_raw = uaf_data_mod[:UAF_MOD_LEN] + uaf_data_raw + comp_padd # Add missing padding for decompression
else:
uaf_data_raw = uaf_data_mod[:UAF_MOD_LEN] + uaf_data_raw # Add the EFI/Tiano Compression info before Raw Data
else:
uaf_data_raw = uaf_data_raw[:uaf_mod.OriginalSize] # No compression, extend to end of Original @UAF Module size
# Store/Save @UAF Module file
if uaf_tag != '@UII': # Skip @UII binary, already parsed
with open(uaf_fname, 'wb') as uaf_out: uaf_out.write(uaf_data_raw)
# @UAF Module EFI/Tiano Decompression
if is_comp and is_efi_compressed(uaf_data_raw, False):
dec_fname = uaf_fname.replace('.temp', uaf_fext) # Decompressed @UAF Module file path
if efi_decompress(uaf_fname, dec_fname, padding + 4) == 0:
with open(dec_fname, 'rb') as dec: uaf_data_raw = dec.read() # Read back the @UAF Module decompressed Raw data
os.remove(uaf_fname) # Successful decompression, delete compressed @UAF Module file
uaf_fname = dec_fname # Adjust @UAF Module file path to the decompressed one
# Process and Print known text only @UAF Modules (after EFI/Tiano Decompression)
if uaf_tag in UAF_TAG_DICT and UAF_TAG_DICT[uaf_tag][2] == 'Text':
print('\n%s%s:' % (padder(padding + 4), UAF_TAG_DICT[uaf_tag][1]))
print('\n%s%s' % (padder(padding + 8), uaf_data_raw.decode('utf-8','ignore')))
# Parse Default Command Status @UAF Module (@DIS)
if len(uaf_data_raw) and uaf_tag == '@DIS':
dis_hdr = get_struct(uaf_data_raw, 0x0, DisHeader) # Parse @DIS Module Raw Header Structure
print('\n%sDefault Command Status Header:\n' % padder(padding + 4))
dis_hdr.struct_print(padding + 8) # Print @DIS Module Raw Header Info
# Store/Save @DIS Module Header Info in file
with open(uaf_fname[:-3] + 'txt', 'a', encoding='utf-8') as dis:
with contextlib.redirect_stdout(dis):
dis_hdr.struct_print(0) # Store @DIS Module Header Info
dis_data = uaf_data_raw[DIS_HDR_LEN:] # @DIS Module Entries Data
# Parse all @DIS Module Entries
for mod_idx in range(dis_hdr.EntryCount):
dis_mod = get_struct(dis_data, mod_idx * DIS_MOD_LEN, DisModule) # Parse @DIS Module Raw Entry Structure
print('\n%sDefault Command Status Entry %0.2d/%0.2d:\n' % (padder(padding + 8), mod_idx + 1, dis_hdr.EntryCount))
dis_mod.struct_print(padding + 12) # Print @DIS Module Raw Entry Info
# Store/Save @DIS Module Entry Info in file
with open(uaf_fname[:-3] + 'txt', 'a', encoding='utf-8') as dis:
with contextlib.redirect_stdout(dis):
print()
dis_mod.struct_print(4) # Store @DIS Module Entry Info
os.remove(uaf_fname) # Delete @DIS Module binary, info exported as text
# Parse Name|Non-AMI List (?) @UAF Module (@NAL)
if len(uaf_data_raw) >= 5 and (uaf_tag,uaf_data_raw[0],uaf_data_raw[4]) == ('@NAL',0x40,0x3A):
nal_info = uaf_data_raw.decode('utf-8','ignore').replace('\r','').strip().split('\n')
print('\n%s@UAF Module Name List:\n' % padder(padding + 4))
# Parse all @NAL Module Entries
for info in nal_info:
info_tag,info_val = info.split(':',1)
print('%s%s : %s' % (padder(padding + 8), info_tag, info_val)) # Print @NAL Module Tag-Path Info
nal_dict[info_tag] = os.path.basename(info_val) # Assign a file name (w/o path) to each Tag
# Parse Insyde BIOS @UAF Module (@INS)
if uaf_tag == '@INS' and is_7z_supported(uaf_fname):
ins_dir = os.path.join(extract_path, safe_name(uaf_tag + '_nested-SFX')) # Generate extraction directory
print('\n%sInsyde BIOS 7z SFX Archive:' % padder(padding + 4))
if a7z_decompress(uaf_fname, ins_dir, '7z SFX', padding + 8) == 0:
os.remove(uaf_fname) # Successful extraction, delete @INS Module file/archive
# Detect & Unpack AMI BIOS Guard (PFAT) BIOS image
pfat_match,pfat_buffer = get_ami_pfat(uaf_data_raw)
if pfat_match:
pfat_dir = os.path.join(extract_path, safe_name(uaf_name))
parse_pfat_file(pfat_buffer, pfat_dir, padding + 4)
os.remove(uaf_fname) # Delete PFAT Module file after extraction
# Detect Intel Engine firmware image and show ME Analyzer advice
if uaf_tag.startswith('@ME') and PAT_INTEL_ENG.search(uaf_data_raw):
print('\n%sIntel Management Engine (ME) Firmware:\n' % padder(padding + 4))
print('%sUse "ME Analyzer" from https://github.com/platomav/MEAnalyzer' % padder(padding + 8))
# Get best Nested AMI UCP Pattern match based on @UAF Size
nested_uaf_off,nested_uaf_bin = get_ami_ucp(uaf_data_raw)
# Parse Nested AMI UCP Structure
if nested_uaf_off:
uaf_dir = os.path.join(extract_path, safe_name(uaf_tag + '_nested-UCP')) # Generate extraction directory
ucp_extract(nested_uaf_bin, uaf_dir, padding + 4, is_chk16) # Call recursively
os.remove(uaf_fname) # Delete raw nested AMI UCP Structure after successful recursion/extraction
return nal_dict
# Get common ctypes Structure Sizes
UAF_HDR_LEN = ctypes.sizeof(UafHeader)
UAF_MOD_LEN = ctypes.sizeof(UafModule)
DIS_HDR_LEN = ctypes.sizeof(DisHeader)
DIS_MOD_LEN = ctypes.sizeof(DisModule)
UII_HDR_LEN = ctypes.sizeof(UiiHeader)
# AMI UCP Tag Dictionary
UAF_TAG_DICT = {
'@3FI' : ['HpBiosUpdate32.efi', '', ''],
'@3S2' : ['HpBiosUpdate32.s12', '', ''],
'@3S4' : ['HpBiosUpdate32.s14', '', ''],
'@3S9' : ['HpBiosUpdate32.s09', '', ''],
'@3SG' : ['HpBiosUpdate32.sig', '', ''],
'@AMI' : ['UCP_Nested.bin', 'Nested AMI UCP', ''],
'@B12' : ['BiosMgmt.s12', '', ''],
'@B14' : ['BiosMgmt.s14', '', ''],
'@B32' : ['BiosMgmt32.s12', '', ''],
'@B34' : ['BiosMgmt32.s14', '', ''],
'@B39' : ['BiosMgmt32.s09', '', ''],
'@B3E' : ['BiosMgmt32.efi', '', ''],
'@BM9' : ['BiosMgmt.s09', '', ''],
'@BME' : ['BiosMgmt.efi', '', ''],
'@CKV' : ['Check_Version.txt', 'Check Version', 'Text'],
'@CMD' : ['AFU_Command.txt', 'AMI AFU Command', 'Text'],
'@CPM' : ['AC_Message.txt', 'Confirm Power Message', ''],
'@DCT' : ['DevCon32.exe', 'Device Console WIN32', ''],
'@DCX' : ['DevCon64.exe', 'Device Console WIN64', ''],
'@DFE' : ['HpDevFwUpdate.efi', '', ''],
'@DFS' : ['HpDevFwUpdate.s12', '', ''],
'@DIS' : ['Command_Status.bin', 'Default Command Status', ''],
'@ENB' : ['ENBG64.exe', '', ''],
'@INS' : ['Insyde_Nested.bin', 'Nested Insyde SFX', ''],
'@M32' : ['HpBiosMgmt32.s12', '', ''],
'@M34' : ['HpBiosMgmt32.s14', '', ''],
'@M39' : ['HpBiosMgmt32.s09', '', ''],
'@M3I' : ['HpBiosMgmt32.efi', '', ''],
'@MEC' : ['FWUpdLcl.txt', 'Intel FWUpdLcl Command', 'Text'],
'@MED' : ['FWUpdLcl_DOS.exe', 'Intel FWUpdLcl DOS', ''],
'@MET' : ['FWUpdLcl_WIN32.exe', 'Intel FWUpdLcl WIN32', ''],
'@MFI' : ['HpBiosMgmt.efi', '', ''],
'@MS2' : ['HpBiosMgmt.s12', '', ''],
'@MS4' : ['HpBiosMgmt.s14', '', ''],
'@MS9' : ['HpBiosMgmt.s09', '', ''],
'@NAL' : ['UAF_List.txt', 'Name List', ''],
'@OKM' : ['OK_Message.txt', 'OK Message', ''],
'@PFC' : ['BGT_Command.txt', 'AMI BGT Command', 'Text'],
'@R3I' : ['CryptRSA32.efi', '', ''],
'@RFI' : ['CryptRSA.efi', '', ''],
'@UAF' : ['UCP_Main.bin', 'Utility Auxiliary File', ''],
'@UFI' : ['HpBiosUpdate.efi', '', ''],
'@UII' : ['UCP_Info.txt', 'Utility Identification Information', ''],
'@US2' : ['HpBiosUpdate.s12', '', ''],
'@US4' : ['HpBiosUpdate.s14', '', ''],
'@US9' : ['HpBiosUpdate.s09', '', ''],
'@USG' : ['HpBiosUpdate.sig', '', ''],
'@VER' : ['OEM_Version.txt', 'OEM Version', 'Text'],
'@VXD' : ['amifldrv.vxd', '', ''],
'@W32' : ['amifldrv32.sys', '', ''],
'@W64' : ['amifldrv64.sys', '', ''],
}
if __name__ == '__main__':
# Show script title
show_title(title)
# Set argparse Arguments
argparser = argparse_init()
argparser.add_argument('-c', '--checksum', help='verify AMI UCP Checksums (slow)', action='store_true')
arguments = argparser.parse_args()
# Pretty Python exception handler (must be after argparse)
sys.excepthook = nice_exc_handler
# Check Python Version (must be after argparse)
check_sys_py()
# Check OS Platform (must be after argparse)
check_sys_os()
# Process input files and generate output path
input_files,output_path = process_input_files(arguments, sys.argv)
# Initial output padding count
padding = 4
for input_file in input_files:
input_name = os.path.basename(input_file)
print('\n*** %s' % input_name)
with open(input_file, 'rb') as in_file: input_buffer = in_file.read()
# Get best AMI UCP Pattern match based on @UAF Size
main_uaf_off,main_uaf_bin = get_ami_ucp(input_buffer)
if not main_uaf_off:
print('\n%sError: This is not an AMI UCP BIOS executable!' % padder(padding))
continue # Next input file
extract_path = os.path.join(output_path, input_name)
ucp_extract(main_uaf_bin, extract_path, padding, arguments.checksum)
print('\n%sExtracted AMI UCP BIOS executable!' % padder(padding))
print_input('\nDone!')

759
README.md
View file

@ -5,175 +5,39 @@
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DJDZD3PRGCSCL"><img border="0" title="BIOS Utilities Donation via Paypal or Debit/Credit Card" alt="BIOS Utilities Donation via Paypal or Debit/Credit Card" src="https://user-images.githubusercontent.com/11527726/109392268-e0f68280-7923-11eb-83d8-0a63f0d20783.png"></a> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DJDZD3PRGCSCL"><img border="0" title="BIOS Utilities Donation via Paypal or Debit/Credit Card" alt="BIOS Utilities Donation via Paypal or Debit/Credit Card" src="https://user-images.githubusercontent.com/11527726/109392268-e0f68280-7923-11eb-83d8-0a63f0d20783.png"></a>
* [**Dell PFS Update Extractor**](#dell-pfs-update-extractor)
* [**AMI UCP BIOS Extractor**](#ami-ucp-bios-extractor) * [**AMI UCP BIOS Extractor**](#ami-ucp-bios-extractor)
* [**AMI BIOS Guard Extractor**](#ami-bios-guard-extractor) * [**AMI BIOS Guard Extractor**](#ami-bios-guard-extractor)
* [**Phoenix SCT BIOS Extractor**](#phoenix-sct-bios-extractor)
* [**Insyde iFlash Image Extractor**](#insyde-iflash-image-extractor)
* [**Portwell EFI BIOS Extractor**](#portwell-efi-bios-extractor)
* [**Panasonic BIOS Update Extractor**](#panasonic-bios-update-extractor)
* [**VAIO Packaging Manager Extractor**](#vaio-packaging-manager-extractor)
* [**Fujitsu UPC BIOS Extractor**](#fujitsu-upc-bios-extractor)
* [**Fujitsu SFX BIOS Extractor**](#fujitsu-sfx-bios-extractor)
* [**Award BIOS Module Extractor**](#award-bios-module-extractor)
* [**Apple EFI Package Grabber**](#apple-efi-package-grabber)
* [**Apple EFI File Renamer**](#apple-efi-file-renamer)
* [**Apple EFI IM4P Splitter**](#apple-efi-im4p-splitter)
* [**Apple EFI Package Extractor**](#apple-efi-package-extractor)
## **Dell PFS Update Extractor**
![](https://i.imgur.com/5WaGPPl.png)
#### **Description**
Parses Dell PFS Update images and extracts their Firmware (e.g. SPI, BIOS/UEFI, EC, ME etc) and Utilities (e.g. Flasher etc) component sections. It supports all Dell PFS revisions and formats, including those which are originally LZMA compressed in ThinOS packages, ZLIB compressed or Intel BIOS Guard (PFAT) protected. The output comprises only final firmware components which are directly usable by end users. An optional advanced user mode is available as well, which additionally extracts firmware Signatures and more Metadata.
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing Dell PFS BIOS images. Optional arguments:
* -h or --help : show help message and exit
* -a or --advanced : extract in advanced user mode
* -v or --verbose : show PFS structure information
* -e or --auto-exit : skip press enter to exit prompts
* -o or --output-dir : extract in given output directory
* -i or --input-dir : extract from given input directory
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To decompile the Intel BIOS Guard Scripts via the Python script, you need to additionally have the following 3rd party Python utility at the same directory:
* [BIOS Guard Script Tool](https://github.com/allowitsme/big-tool/tree/sdk-compat) (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.7.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Copy BIOS Guard Script Tool dependency to build directory:
> Dell_PFS_Extract.py, big_script_tool.py
4. Build/Freeze/Compile:
> pyinstaller --noupx --onefile Dell_PFS_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**
![](https://i.imgur.com/LCsUknA.png)
![](https://i.imgur.com/TcARQpk.png)
![](https://i.imgur.com/UWCx75g.png)
![](https://i.imgur.com/1rokMss.png)
## **AMI UCP BIOS Extractor** ## **AMI UCP BIOS Extractor**
![](https://i.imgur.com/6YWoMGk.png) ![]()
#### **Description** #### **Description**
Parses AMI UCP (Utility Configuration Program) BIOS images, extracts their SPI/BIOS/UEFI firmware components and shows all relevant info. It supports all AMI UCP revisions and formats, including those with nested AMI UCP or Insyde SFX structures. The output comprises only final firmware components and utilities which are directly usable by end users. Parses AMI UCP (Utility Configuration Program) BIOS executables, extracts their firmware components (e.g. SPI/BIOS/UEFI, EC, ME etc) and shows all relevant info. It supports all AMI UCP revisions and formats, including those with nested AMI PFAT, AMI UCP or Insyde SFX structures. The output comprises only final firmware components and utilities which are directly usable by end users.
Note that AMI UCP BIOS images are protected by various checksums but, due to algorithmic performance reasons, AMI UCP BIOS Extractor does not check them by default. An optional parameter is provided though, for verifying all checksums during extraction.
#### **Usage** #### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing AMI UCP BIOS images. Optional arguments: You can either Drag & Drop or manually enter AMI UCP BIOS executable file(s). Optional arguments:
* -h or --help : show help message and exit * -h or --help : show help message and exit
* -p or --path : parse files within given folder * -i or --input-dir : extract from given input directory
* -o or --output-dir : extract in given output directory
* -e or --auto-exit : skip press enter to exit prompts
* -c or --checksum : verify AMI UCP Checksums (slow) * -c or --checksum : verify AMI UCP Checksums (slow)
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility** #### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries. Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites** #### **Prerequisites**
To run the python script, you need to have the following 3rd party tools placed at the same directory: To run the utility, you must have the following 3rd party tools at the "external" project directory:
* [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (i.e. [TianoCompress.exe](https://github.com/tianocore/edk2-BaseTools-win32/)) * [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (e.g. [TianoCompress.exe for Windows](https://github.com/tianocore/edk2-BaseTools-win32/) or TianoCompress)
* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe) * [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zz|7zzs)
#### **Build/Freeze/Compile with PyInstaller** Optionally, to decompile the AMI UCP \> AMI PFAT \> Intel BIOS Guard Scripts (when applicable), you must have the following 3rd party utility at the "external" project directory:
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.7.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Build/Freeze/Compile:
> pyinstaller --noupx --onefile AMI_UCP_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**
![](https://i.imgur.com/3PaWy3M.png)
## **AMI BIOS Guard Extractor**
![](https://i.imgur.com/p0rrlqv.png)
#### **Description**
Parses AMI BIOS Guard (a.k.a. PFAT, Platform Firmware Armoring Technology) images, extracts their SPI/BIOS/UEFI firmware components and decompiles the Intel BIOS Guard Scripts. It supports all AMI PFAT revisions and formats, including those with nested AMI PFAT structures. The output comprises only final firmware components which are directly usable by end users.
Note that the AMI PFAT structure does not have an explicit component order. AMI's BIOS Guard Firmware Update Tool (AFUBGT) updates components based on the user/OEM provided Parameters and Options. That means that merging all the components together does not usually yield a proper SPI/BIOS/UEFI image. The utility does generate such a merged file with the name "X_00 -- AMI_PFAT_X_DATA_ALL.bin" but it is up to the end user to determine its usefulness. Moreover, any custom OEM data after the AMI PFAT structure are additionally stored in a file with the name "X_YY -- AMI_PFAT_X_DATA_END.bin" and it is once again up to the end user to determine its usefulness. In cases where the trailing custom OEM data include a nested AMI PFAT structure, the utility will process and extract it automatically as well.
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing AMI BIOS Guard (PFAT) images.
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To decompile the Intel BIOS Guard Scripts via the Python script, you need to additionally have the following 3rd party Python utility at the same directory:
* [BIOS Guard Script Tool](https://github.com/allowitsme/big-tool/tree/sdk-compat) (i.e. big_script_tool.py) * [BIOS Guard Script Tool](https://github.com/allowitsme/big-tool/tree/sdk-compat) (i.e. big_script_tool.py)
@ -189,13 +53,13 @@ PyInstaller can build/freeze/compile the utility at all three supported platform
> pip3 install pyinstaller > pip3 install pyinstaller
3. Copy BIOS Guard Script Tool dependency to build directory: 3. Place any appropriate prerequisite at the project directory:
> AMI_PFAT_Extract.py, big_script_tool.py > TianoCompress, 7-Zip Console, BIOS Guard Script Tool
4. Build/Freeze/Compile: 4. Build/Freeze/Compile:
> pyinstaller --noupx --onefile AMI_PFAT_Extract.py > pyinstaller --noupx --onefile \<path-to-project\>\/AMI_UCP_Extract.py
At dist folder you should find the final utility executable At dist folder you should find the final utility executable
@ -205,85 +69,26 @@ Some Anti-Virus software may claim that the built/frozen/compiled executable con
#### **Pictures** #### **Pictures**
![](https://i.imgur.com/iZD3GY0.png) ![]()
## **Phoenix SCT BIOS Extractor** ## **AMI BIOS Guard Extractor**
![](https://i.imgur.com/z4VM06J.png) ![]()
#### **Description** #### **Description**
Parses Phoenix SecureCore Technology (SCT) BIOS images and extracts their SPI/BIOS/UEFI firmware components. It supports all Phoenix SCT revisions and formats, including those which are originally LZMA compressed. The output comprises only final firmware components which are directly usable by end users. Parses AMI BIOS Guard (a.k.a. PFAT, Platform Firmware Armoring Technology) images, extracts their SPI/BIOS/UEFI firmware components and decompiles the Intel BIOS Guard Scripts. It supports all AMI PFAT revisions and formats, including those with Index Information tables or nested AMI PFAT structures. The output comprises only final firmware components which are directly usable by end users.
![](https://i.imgur.com/p6s8L6j.png) Note that the AMI PFAT structure may not have an explicit component order. AMI's BIOS Guard Firmware Update Tool (AFUBGT) updates components based on the user/OEM provided Parameters and Options or Index Information table, when applicable. That means that merging all the components together does not usually yield a proper SPI/BIOS/UEFI image. The utility does generate such a merged file with the name "00 -- \<filename\>\_ALL.bin" but it is up to the end user to determine its usefulness. Moreover, any custom OEM data after the AMI PFAT structure are additionally stored in the last file with the name "\<n+1\> -- \_OOB.bin" and it is once again up to the end user to determine its usefulness. In cases where the trailing custom OEM data include a nested AMI PFAT structure, the utility will process and extract it automatically as well.
<sub><sup>*Icon owned by Phoenix*</sup></sub>
#### **Usage** #### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing Phoenix SCT BIOS images. Optional arguments: You can either Drag & Drop or manually enter AMI BIOS Guard (PFAT) image file(s). Optional arguments:
* -h or --help : show help message and exit * -h or --help : show help message and exit
* -p or --path : parse files within given folder
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To run the utility, you do not need any 3rd party tool.
#### **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.7.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Build/Freeze/Compile:
> pyinstaller --noupx --onefile Phoenix_SCT_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**
![](https://i.imgur.com/Td6F5mm.png)
## **Insyde iFlash Image Extractor**
![](https://i.imgur.com/13GJjwO.png)
#### **Description**
Parses Insyde iFlash images and extracts their raw components (e.g. SPI/BIOS/UEFI, EC, ME, Flasher, Configuration etc).
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing Insyde iFlash images. Optional arguments:
* -h or --help : show help message and exit
* -v or --verbose : show iFlash structure information
* -e or --auto-exit : skip press enter to exit prompts
* -o or --output-dir : extract in given output directory
* -i or --input-dir : extract from given input directory * -i or --input-dir : extract from given input directory
* -o or --output-dir : extract in given output directory
#### **Download** * -e or --auto-exit : skip press enter to exit prompts
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility** #### **Compatibility**
@ -291,7 +96,9 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3
#### **Prerequisites** #### **Prerequisites**
To run the utility, you do not need any 3rd party tool. Optionally, to decompile the AMI PFAT \> Intel BIOS Guard Scripts, you must have the following 3rd party utility at the "external" project directory:
* [BIOS Guard Script Tool](https://github.com/allowitsme/big-tool/tree/sdk-compat) (i.e. big_script_tool.py)
#### **Build/Freeze/Compile with PyInstaller** #### **Build/Freeze/Compile with PyInstaller**
@ -305,74 +112,13 @@ PyInstaller can build/freeze/compile the utility at all three supported platform
> pip3 install pyinstaller > pip3 install pyinstaller
3. Build/Freeze/Compile: 3. Place any appropriate prerequisite at the project directory:
> pyinstaller --noupx --onefile Insyde_iFlash_Extract.py > BIOS Guard Script Tool
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**
![](https://i.imgur.com/Pn4JNiG.png)
## **Portwell EFI BIOS Extractor**
![](https://i.imgur.com/ySdUSgf.png)
#### **Description**
Parses Portwell UEFI Unpacker EFI images (usually named "Update.efi"), extracts their SPI/BIOS/UEFI/EC firmware components and shows all relevant info. It supports all Portwell UEFI Unpacker revisions and formats, including those which contain Tiano compressed files. The output comprises only final firmware components and utilities which are directly usable by end users.
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing Portwell UEFI Unpacker EFI images. Optional arguments:
* -h or --help : show help message and exit
* -p or --path : parse files within given folder
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To run the python script, you need to have the following 3rd party Python module installed:
* [pefile](https://pypi.org/project/pefile/)
> pip3 install pefile
To run the python script or its built/frozen/compiled binary, you need to additionally have the following 3rd party tool at the same directory:
* [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (i.e. [TianoCompress.exe](https://github.com/tianocore/edk2-BaseTools-win32/))
#### **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.7.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: 4. Build/Freeze/Compile:
> pyinstaller --noupx --onefile Portwell_EFI_Extract.py > pyinstaller --noupx --onefile \<path-to-project\>\/AMI_PFAT_Extract.py
At dist folder you should find the final utility executable At dist folder you should find the final utility executable
@ -382,456 +128,7 @@ Some Anti-Virus software may claim that the built/frozen/compiled executable con
#### **Pictures** #### **Pictures**
![](https://i.imgur.com/EhCzMLk.png) ![]()
## **Apple EFI Package Grabber**
![](https://i.imgur.com/BaHrjGi.png)
#### **Description**
Parses user-provided (DB) list of Apple Software Update CatalogURL .sucatalog links and saves all newer (since last run) EFI firmware package links into a text file. It removes any xml formatting, ignores false positives, removes duplicate links and sorts them in alphabetical order for easy comparison afterwards.
#### **Usage**
First, you need to familiarize a bit with the DB (i.e. Apple_EFI_Grab.dat file). It consists of 3 sections: Last run DateTime (YYYY-MM-DD HH:MM:SS), Sucatalog links to check and EFI Package links which have been gathered so far across all runs. Before running the utility for the fist time, you need to insert the Sucatalog links into the DB, below the 1st line (DateTime). The Sucatalog links in the DB are stored in partial form, starting from "index" string. For example: "https://swscan.apple.com/content/catalogs/others/index-12.merged-1.sucatalog" must be stored as "index-12.merged-1.sucatalog" in the DB. The Sucatalog links are not pre-included in the DB but you can find them online (e.g. https://github.com/zhangyoufu/swscan.apple.com/blob/master/url.txt).
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To run the utility, you do not need any 3rd party tool.
#### **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.7.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Build/Freeze/Compile:
> pyinstaller --noupx --onefile Apple_EFI_Grab.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.
## **Apple EFI File Renamer**
![](https://i.imgur.com/mWGhWja.png)
#### **Description**
Parses Apple EFI files and renames them based on Intel's official $IBIOSI$ tag as follows: Model_Version_Build_Year_Month_Day_Hour_Minute_Checksum. The checksum is calculated and added by the utility in order to differentiate any EFI files with the same $IBIOSI$ tag. In rare cases in which the $IBIOSI$ tag is compressed, the utility automatically first uses [LongSoft's UEFIFind and UEFIExtract](https://github.com/LongSoft/UEFITool) tools.
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing Apple EFI firmware.
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To run the python script or its built/frozen/compiled binary, you need to have the following 3rd party tools at the same directory:
* [UEFIFind](https://github.com/LongSoft/UEFITool) (i.e. UEFIFind.exe)
* [UEFIExtract](https://github.com/LongSoft/UEFITool) (i.e. UEFIExtract.exe)
#### **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.7.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Build/Freeze/Compile:
> pyinstaller --noupx --onefile Apple_EFI_Rename.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.
## **Apple EFI IM4P Splitter**
![](https://i.imgur.com/G5RkXQk.png)
#### **Description**
Parses Apple multiple EFI firmware .im4p files and splits all detected EFI firmware into separate SPI/BIOS images.
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing Apple EFI IM4P firmware.
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To run the utility, you do not need any 3rd party tool.
#### **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.7.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Build/Freeze/Compile:
> pyinstaller --noupx --onefile Apple_EFI_Split.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.
## **Apple EFI Package Extractor**
![](https://i.imgur.com/pufGuZ4.png)
#### **Description**
Parses Apple EFI firmware packages (i.e. FirmwareUpdate.pkg, BridgeOSUpdateCustomer.pkg), extracts their EFI images, splits those in IM4P format and renames the final SPI/BIOS images accordingly. The utility automatically uses the free version of [AnyToISO](https://www.crystalidea.com/anytoiso) to extract the EFI .pkg files. The subsequent IM4P splitting and EFI renaming requires the presence of "Apple EFI IM4P Splitter" and "Apple EFI File Renamer" utilities.
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing Apple EFI firmware package (.pkg) files. Depending on where AnyToISO is installed on your system, you must change the "anytoiso_path" variable accordingly.
#### **Download**
An already built/frozen/compiled binary is **not** provided because the script requires the user to set the AnyToISO executable path variable. Remember that you need to include prerequisites such as AnyToISO, Apple EFI IM4P Splitter and Apple EFI File Renamer for the utility to work.
#### **Compatibility**
Should work at all Windows & macOS operating systems which have Python 3.7 and AnyToISO support.
#### **Prerequisites**
To run the python script, you need to have the following 3rd party tools installed or placed at the same directory:
* [AnyToISO](https://www.crystalidea.com/anytoiso) (i.e. anytoiso.exe)
* [UEFIFind](https://github.com/LongSoft/UEFITool) (i.e. UEFIFind.exe)
* [UEFIExtract](https://github.com/LongSoft/UEFITool) (i.e. UEFIExtract.exe)
#### **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. Note that, due to this utility's nature, you may need to perform some small script changes for a built/frozen/compiled binary to work.
1. Make sure Python 3.7.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Build/Freeze/Compile:
> pyinstaller --noupx --onefile Apple_EFI_Package.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.
## **Panasonic BIOS Update Extractor**
![](https://i.imgur.com/uZAoMGR.png)
<sub><sup>*Icon owned by Panasonic*</sup></sub>
#### **Description**
Parses Panasonic BIOS Update executables and extracts their SPI/BIOS image. The utility automatically uses [Rustam Abdullaev's unpack_lznt1](https://github.com/rustyx/unpack_lznt1) tool in order to decompress the initially Microsoft LZNT1 compressed resource data.
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing Panasonic BIOS Update executables.
#### **Download**
An already built/frozen/compiled Windows binary is provided by me. Thus, **you don't need to manually build/freeze/compile it**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To run the python script, you need to have the following 3rd party Python module installed:
* [pefile](https://pypi.org/project/pefile/)
> pip3 install pefile
To run the python script or its built/frozen/compiled binary, you need to additionally have the following 3rd party tool at the same directory:
* [unpack_lznt1](https://github.com/rustyx/unpack_lznt1) (i.e. unpack_lznt1.exe)
#### **Build/Freeze/Compile with PyInstaller**
PyInstaller can build/freeze/compile the utility at Windows, it is simple to run and gets updated often.
1. Make sure Python 3.7.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 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.
## **VAIO Packaging Manager Extractor**
![](https://i.imgur.com/rg4xrxJ.png)
<sub><sup>*Icon owned by VAIO*</sup></sub>
#### **Description**
Parses VAIO Packaging Manager executables and extracts their contents. If direct extraction fails, it unlocks the executable in order to run at all systems and allow the user to choose the extraction location. The utility automatically uses [Igor Pavlov's 7-Zip](https://www.7-zip.org/) tool in order to decompress the initially obfuscated Microsoft CAB compressed contents.
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing VAIO Packaging Manager executables.
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To run the python script or its built/frozen/compiled binary, you need to have the following 3rd party tool at the same directory:
* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe)
#### **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.7.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Build/Freeze/Compile:
> pyinstaller --noupx --onefile 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.
## **Fujitsu UPC BIOS Extractor**
![](https://i.imgur.com/JqrlxfE.png)
#### **Description**
Parses Fujitsu UPC images and extracts their Tiano compressed SPI/BIOS firmware component. The output comprises only a final firmware component which is directly usable by end users.
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing Portwell UEFI Unpacker EFI images. Optional arguments:
* -h or --help : show help message and exit
* -p or --path : parse files within given folder
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To run the python script or its built/frozen/compiled binary, you need to additionally have the following 3rd party tool at the same directory:
* [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (i.e. [TianoCompress.exe](https://github.com/tianocore/edk2-BaseTools-win32/))
#### **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.7.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Build/Freeze/Compile:
> pyinstaller --noupx --onefile Fujitsu_UPC_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**
![](https://i.imgur.com/FE8MNi2.png)
## **Fujitsu SFX BIOS Extractor**
![](https://i.imgur.com/NlZGBsy.png)
<sub><sup>*Icon owned by FUJITSU*</sup></sub>
#### **Description**
Parses Fujitsu SFX BIOS executables and extracts their contents. The utility automatically uses [Igor Pavlov's 7-Zip](https://www.7-zip.org/) tool in order to decompress the initially obfuscated Microsoft CAB compressed contents.
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing Fujitsu SFX BIOS executables.
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To run the python script or its built/frozen/compiled binary, you need to have the following 3rd party tool at the same directory:
* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe)
#### **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.7.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Build/Freeze/Compile:
> pyinstaller --noupx --onefile 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.
## **Award BIOS Module Extractor**
#### **Description**
Parses Award BIOS images and extracts their modules. The utility automatically uses [Igor Pavlov's 7-Zip](https://www.7-zip.org/) tool in order to decompress the initially LZH compressed sub-modules.
#### **Usage**
You can either Drag & Drop or manually enter the full path of a folder containing Award BIOS firmware.
#### **Download**
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.7 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
#### **Prerequisites**
To run the python script or its built/frozen/compiled binary, you need to have the following 3rd party tool at the same directory:
* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe)
#### **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.7.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Build/Freeze/Compile:
> pyinstaller --noupx --onefile 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.
###### _Donate Button Card Image: [Credit and Loan Pack](https://flaticon.com/free-icon/credit-card_3898076) by **Freepik** under Flaticon license_ ###### _Donate Button Card Image: [Credit and Loan Pack](https://flaticon.com/free-icon/credit-card_3898076) by **Freepik** under Flaticon license_
###### _Donate Button Paypal Image: [Credit Cards Pack](https://flaticon.com/free-icon/paypal_349278) by **Freepik** under Flaticon license_ ###### _Donate Button Paypal Image: [Credit Cards Pack](https://flaticon.com/free-icon/paypal_349278) by **Freepik** under Flaticon license_

45
common/a7z_comp.py Normal file
View file

@ -0,0 +1,45 @@
#!/usr/bin/env python3
#coding=utf-8
import os
import subprocess
from common.script_get import get_script_dir
from common.system import get_os_ver
from common.text_ops import padder
# Get 7z path
def get_7z_path(static=False):
exec_name = '7z.exe' if get_os_ver()[1] else ('7zzs' if static else '7zz')
exec_path = os.path.join(get_script_dir(), '..', 'external', exec_name)
return exec_path
# Check if file is 7z supported
def is_7z_supported(in_path, static=False):
try:
subprocess.run([get_7z_path(static), 't', in_path, '-bso0', '-bse0', '-bsp0'], check=True)
except:
return False
return True
# Archive decompression via 7-Zip
def a7z_decompress(in_path, out_path, in_name, padding, static=False):
if not in_name: in_name = 'archive'
try:
subprocess.run([get_7z_path(static), 'x', '-aou', '-bso0', '-bse0', '-bsp0', '-o' + out_path, in_path], check=True)
if not os.path.isdir(out_path): raise Exception('EXTRACT_DIR_MISSING')
except:
print('\n%sError: 7-Zip could not extract %s file %s!' % (padder(padding), in_name, in_path))
return 1
print('\n%sSuccesfull %s decompression via 7-Zip!' % (padder(padding), in_name))
return 0

13
common/checksums.py Normal file
View file

@ -0,0 +1,13 @@
#!/usr/bin/env python3
#coding=utf-8
# Get Checksum 16-bit
def checksum16(data):
chk16 = 0
for idx in range(0, len(data), 2):
chk16 += int.from_bytes(data[idx:idx + 2], 'little')
chk16 &= 0xFFFF
return chk16

51
common/efi_comp.py Normal file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env python3
#coding=utf-8
import os
import subprocess
from common.script_get import get_script_dir
from common.system import get_os_ver
from common.text_ops import padder
def get_compress_sizes(data):
size_compress = int.from_bytes(data[0x0:0x4], 'little')
size_original = int.from_bytes(data[0x4:0x8], 'little')
return size_compress, size_original
def is_efi_compressed(data, strict=True):
size_comp,size_orig = get_compress_sizes(data)
check_diff = size_comp < size_orig
if strict: check_size = size_comp + 0x8 == len(data)
else: check_size = size_comp + 0x8 <= len(data)
return check_diff and check_size
# Get TianoCompress path
def tianocompress_path():
exec_name = 'TianoCompress' + ('.exe' if get_os_ver()[1] else '')
exec_path = os.path.join(get_script_dir(), '..', 'external', exec_name)
return exec_path
# EFI/Tiano Decompression via TianoCompress
def efi_decompress(in_path, out_path, padding, comp_type='--uefi'):
try:
subprocess.run([tianocompress_path(), '-d', in_path, '-o', out_path, '-q', comp_type], check=True, stdout=subprocess.DEVNULL)
with open(in_path, 'rb') as file: _,size_orig = get_compress_sizes(file.read())
if os.path.getsize(out_path) != size_orig: raise Exception('EFI_DECOMPRESS_ERROR')
except:
print('\n%sError: TianoCompress could not extract file %s!' % (padder(padding), in_path))
return 1
print('\n%sSuccesfull EFI/Tiano decompression via TianoCompress!' % padder(padding))
return 0

11
common/externals.py Normal file
View file

@ -0,0 +1,11 @@
#!/usr/bin/env python3
#coding=utf-8
# https://github.com/allowitsme/big-tool by Dmitry Frolov
def get_bgs_tool():
try:
from external.big_script_tool import BigScript
except:
BigScript = None
return BigScript

11
common/num_ops.py Normal file
View file

@ -0,0 +1,11 @@
#!/usr/bin/env python3
#coding=utf-8
# https://leancrew.com/all-this/2020/06/ordinals-in-python/ by Dr. Drang
def get_ordinal(number):
s = ('th', 'st', 'nd', 'rd') + ('th',) * 10
v = number % 100
return f'{number}{s[v % 10]}' if v > 13 else f'{number}{s[v]}'

79
common/path_ops.py Normal file
View file

@ -0,0 +1,79 @@
#!/usr/bin/env python3
#coding=utf-8
import os
import re
import argparse
from pathlib import Path
from common.script_get import get_script_dir
# Fix illegal/reserved Windows characters
def safe_name(in_name):
raw_name = repr(in_name).strip("'")
fix_name = re.sub(r'[\\/*?:"<>|]', '_', raw_name)
return fix_name
# Walk path to get all files
def get_path_files(in_path):
path_files = []
for root, _, files in os.walk(in_path):
for name in files:
path_files.append(os.path.join(root, name))
return path_files
# Get parent of path
def get_path_parent(in_path):
return Path(in_path).parent.absolute()
# Get absolute file path (argparse object)
def get_absolute_path(argparse_path):
script_dir = get_path_parent(get_script_dir())
if not argparse_path:
absolute_path = script_dir # Use input file directory if no user path is specified
else:
# Check if user specified path is absolute, otherwise convert it to input file relative
if Path(argparse_path).is_absolute(): absolute_path = argparse_path
else: absolute_path = os.path.join(script_dir, argparse_path)
return absolute_path
# 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('-o', '--output-dir', help='extract in given output directory')
argparser.add_argument('-i', '--input-dir', help='extract from given input directory')
return argparser
# Process input files (argparse object)
def process_input_files(argparse_args, sys_argv=None):
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_absolute_path(input_path_user) if input_path_user else ''
input_files = get_path_files(input_path_full)
else:
input_files = [file.name for file in argparse_args.files]
output_path = get_absolute_path(argparse_args.output_dir or argparse_args.input_dir)
else:
# Script w/o parameters
input_path_user = input('\nEnter input directory path: ')
input_path_full = get_absolute_path(input_path_user) if input_path_user else ''
input_files = get_path_files(input_path_full)
output_path = get_absolute_path(input('\nEnter output directory path: '))
return input_files, output_path

8
common/patterns.py Normal file
View file

@ -0,0 +1,8 @@
#!/usr/bin/env python3
#coding=utf-8
import re
PAT_AMI_PFAT = re.compile(b'_AMIPFAT.AMI_BIOS_GUARD_FLASH_CONFIGURATIONS', re.DOTALL)
PAT_AMI_UCP = re.compile(br'\x40\x55\x41\x46.{12}\x40', re.DOTALL)
PAT_INTEL_ENG = re.compile(br'\x04\x00{3}[\xA1\xE1]\x00{3}.{8}\x86\x80.{9}\x00\$((MN2)|(MAN))', re.DOTALL)

19
common/script_get.py Normal file
View file

@ -0,0 +1,19 @@
#!/usr/bin/env python3
#coding=utf-8
# https://stackoverflow.com/a/22881871 by jfs
import os
import sys
import inspect
def get_script_dir(follow_symlinks=True):
if getattr(sys, 'frozen', False):
path = os.path.abspath(sys.executable)
else:
path = inspect.getabsfile(get_script_dir)
if follow_symlinks:
path = os.path.realpath(path)
return os.path.dirname(path)

24
common/struct_ops.py Normal file
View file

@ -0,0 +1,24 @@
#!/usr/bin/env python3
#coding=utf-8
# https://github.com/skochinsky/me-tools/blob/master/me_unpack.py by Igor Skochinsky
import ctypes
char = ctypes.c_char
uint8_t = ctypes.c_ubyte
uint16_t = ctypes.c_ushort
uint32_t = ctypes.c_uint
uint64_t = ctypes.c_uint64
def get_struct(buffer, start_offset, class_name, param_list=None):
if param_list is None: param_list = []
structure = class_name(*param_list) # Unpack parameter list
struct_len = ctypes.sizeof(structure)
struct_data = buffer[start_offset:start_offset + struct_len]
fit_len = min(len(struct_data), struct_len)
ctypes.memmove(ctypes.addressof(structure), struct_data, fit_len)
return structure

79
common/system.py Normal file
View file

@ -0,0 +1,79 @@
#!/usr/bin/env python3
#coding=utf-8
import sys
import ctypes
import traceback
# Get Python Version (tuple)
def get_py_ver():
return sys.version_info
# Get OS Platform (string)
def get_os_ver():
sys_os = sys.platform
is_win = sys_os == 'win32'
is_lnx = sys_os.startswith('linux') or sys_os == 'darwin' or sys_os.find('bsd') != -1
return sys_os, is_win, is_win or is_lnx
# Check for --auto-exit|-e
def is_auto_exit():
return '--auto-exit' in sys.argv or '-e' in sys.argv
# Check Python Version
def check_sys_py():
sys_py = get_py_ver()
if sys_py < (3,7):
sys.stdout.write('\nError: Python >= 3.7 required, not %d.%d!' % (sys_py[0], sys_py[1]))
if not is_auto_exit():
# noinspection PyUnresolvedReferences
(raw_input if sys_py[0] <= 2 else input)('\nPress enter to exit') # pylint: disable=E0602
sys.exit(1)
# Check OS Platform
def check_sys_os():
os_tag,os_win,os_sup = get_os_ver()
if not os_sup:
print('\nError: Unsupported platform "%s"!' % os_tag)
if not is_auto_exit():
input('\nPress enter to exit')
sys.exit(2)
# Fix Windows Unicode console redirection
if os_win: sys.stdout.reconfigure(encoding='utf-8')
# Show Script Title
def show_title(title):
print('\n' + title)
_,os_win,_ = get_os_ver()
# Set console/shell window title
if os_win: ctypes.windll.kernel32.SetConsoleTitleW(title)
else: sys.stdout.write('\x1b]2;' + title + '\x07')
# https://stackoverflow.com/a/781074 by Torsten Marek
def nice_exc_handler(exc_type, exc_value, tb):
if exc_type is KeyboardInterrupt:
print('\n')
else:
print('\nError: 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(3)
# Print or Input Message based on --auto-exit|-e
def print_input(msg):
(print if is_auto_exit() else input)(msg)

6
common/text_ops.py Normal file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env python3
#coding=utf-8
# Generate padding (spaces or tabs)
def padder(count, tab=False):
return ('\t' if tab else ' ') * count