Added AMI PFAT RSA 3K signed blocks support

Added AMI PFAT nested detection at each file

Added Award BIOS payload naming at each file

Switched Panasonic BIOS LZNT1 external library

Improved Panasonic LZNT1 detection and length

Improved Dell PFS code structure and fixed bugs

Improved code exception handling (raise, catch)

Improved code definitions (PEP8, docs, types)

Fixed some arguments missing from help screens
This commit is contained in:
Plato Mavropoulos 2024-04-24 01:22:53 +03:00
parent 03ae0cf070
commit d85a7f82dc
37 changed files with 2897 additions and 2174 deletions

View file

@ -1,319 +1,434 @@
#!/usr/bin/env python3
#coding=utf-8
#!/usr/bin/env python3 -B
# coding=utf-8
"""
AMI PFAT Extract
AMI BIOS Guard Extractor
Copyright (C) 2018-2022 Plato Mavropoulos
Copyright (C) 2018-2024 Plato Mavropoulos
"""
TITLE = 'AMI BIOS Guard Extractor v4.0_a12'
import ctypes
import os
import re
import sys
import ctypes
# Stop __pycache__ generation
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, get_extract_path, extract_suffix
from common.path_ops import extract_suffix, get_extract_path, make_dirs, path_name, safe_name
from common.patterns import PAT_AMI_PFAT
from common.struct_ops import char, get_struct, uint8_t, uint16_t, uint32_t
from common.struct_ops import Char, get_struct, UInt8, UInt16, UInt32
from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import file_to_bytes
from common.text_ops import bytes_to_hex, file_to_bytes
TITLE = 'AMI BIOS Guard Extractor v5.0'
class AmiBiosGuardHeader(ctypes.LittleEndianStructure):
""" AMI BIOS Guard Header """
_pack_ = 1
# noinspection PyTypeChecker
_fields_ = [
('Size', uint32_t), # 0x00 Header + Entries
('Checksum', uint32_t), # 0x04 ?
('Tag', char*8), # 0x04 _AMIPFAT
('Flags', uint8_t), # 0x10 ?
('Size', UInt32), # 0x00 Header + Entries
('Checksum', UInt32), # 0x04 ?
('Tag', Char * 8), # 0x04 _AMIPFAT
('Flags', UInt8), # 0x10 ?
# 0x11
]
def struct_print(self, p):
printer(['Size :', f'0x{self.Size:X}'], p, False)
printer(['Checksum:', f'0x{self.Checksum:04X}'], p, False)
printer(['Tag :', self.Tag.decode('utf-8')], p, False)
printer(['Flags :', f'0x{self.Flags:02X}'], p, False)
def struct_print(self, padd: int) -> None:
""" Display structure information """
printer(['Size :', f'0x{self.Size:X}'], padd, False)
printer(['Checksum:', f'0x{self.Checksum:04X}'], padd, False)
printer(['Tag :', self.Tag.decode('utf-8')], padd, False)
printer(['Flags :', f'0x{self.Flags:02X}'], padd, False)
class IntelBiosGuardHeader(ctypes.LittleEndianStructure):
""" Intel BIOS Guard Header """
_pack_ = 1
# noinspection PyTypeChecker
_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
('BGVerMajor', UInt16), # 0x00
('BGVerMinor', UInt16), # 0x02
('PlatformID', UInt8 * 16), # 0x04
('Attributes', UInt32), # 0x14
('ScriptVerMajor', UInt16), # 0x16
('ScriptVerMinor', UInt16), # 0x18
('ScriptSize', UInt32), # 0x1C
('DataSize', UInt32), # 0x20
('BIOSSVN', UInt32), # 0x24
('ECSVN', UInt32), # 0x28
('VendorInfo', UInt32), # 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 = f'{int.from_bytes(id_byte, "big"):0{0x10 * 2}X}'
id_guid = f'{{{id_hexs[:8]}-{id_hexs[8:12]}-{id_hexs[12:16]}-{id_hexs[16:20]}-{id_hexs[20:]}}}'
def get_platform_id(self) -> str:
""" Get Intel BIOS Guard Platform ID """
id_byte: bytes = bytes(self.PlatformID)
id_text: str = re.sub(r'[\n\t\r\x00 ]', '', id_byte.decode('utf-8', 'ignore'))
id_hexs: str = f'{int.from_bytes(id_byte, "big"):0{0x10 * 2}X}'
id_guid: str = f'{{{id_hexs[:8]}-{id_hexs[8:12]}-{id_hexs[12:16]}-{id_hexs[16:20]}-{id_hexs[20:]}}}'
return f'{id_text} {id_guid}'
def get_flags(self):
def get_flags(self) -> tuple:
""" Get Intel BIOS Guard Header Attributes """
attr = IntelBiosGuardHeaderGetAttributes()
attr.asbytes = self.Attributes
attr.asbytes = self.Attributes # pylint: disable=W0201
return attr.b.SFAM, attr.b.ProtectEC, attr.b.GFXMitDis, attr.b.FTU, attr.b.Reserved
def struct_print(self, p):
no_yes = ['No','Yes']
f1,f2,f3,f4,f5 = self.get_flags()
printer(['BIOS Guard Version :', f'{self.BGVerMajor}.{self.BGVerMinor}'], p, False)
printer(['Platform Identity :', self.get_platform_id()], p, False)
printer(['Signed Flash Address Map :', no_yes[f1]], p, False)
printer(['Protected EC OpCodes :', no_yes[f2]], p, False)
printer(['Graphics Security Disable :', no_yes[f3]], p, False)
printer(['Fault Tolerant Update :', no_yes[f4]], p, False)
printer(['Attributes Reserved :', f'0x{f5:X}'], p, False)
printer(['Script Version :', f'{self.ScriptVerMajor}.{self.ScriptVerMinor}'], p, False)
printer(['Script Size :', f'0x{self.ScriptSize:X}'], p, False)
printer(['Data Size :', f'0x{self.DataSize:X}'], p, False)
printer(['BIOS Security Version Number:', f'0x{self.BIOSSVN:X}'], p, False)
printer(['EC Security Version Number :', f'0x{self.ECSVN:X}'], p, False)
printer(['Vendor Information :', f'0x{self.VendorInfo:X}'], p, False)
def struct_print(self, padd: int) -> None:
""" Display structure information """
no_yes: dict[int, str] = {0: 'No', 1: 'Yes'}
sfam, ec_opc, gfx_dis, ft_upd, attr_res = self.get_flags()
printer(['BIOS Guard Version :', f'{self.BGVerMajor}.{self.BGVerMinor}'], padd, False)
printer(['Platform Identity :', self.get_platform_id()], padd, False)
printer(['Signed Flash Address Map :', no_yes[sfam]], padd, False)
printer(['Protected EC OpCodes :', no_yes[ec_opc]], padd, False)
printer(['Graphics Security Disable :', no_yes[gfx_dis]], padd, False)
printer(['Fault Tolerant Update :', no_yes[ft_upd]], padd, False)
printer(['Attributes Reserved :', f'0x{attr_res:X}'], padd, False)
printer(['Script Version :', f'{self.ScriptVerMajor}.{self.ScriptVerMinor}'], padd, False)
printer(['Script Size :', f'0x{self.ScriptSize:X}'], padd, False)
printer(['Data Size :', f'0x{self.DataSize:X}'], padd, False)
printer(['BIOS Security Version Number:', f'0x{self.BIOSSVN:X}'], padd, False)
printer(['EC Security Version Number :', f'0x{self.ECSVN:X}'], padd, False)
printer(['Vendor Information :', f'0x{self.VendorInfo:X}'], padd, False)
class IntelBiosGuardHeaderAttributes(ctypes.LittleEndianStructure):
""" Intel BIOS Guard Header Attributes """
_pack_ = 1
_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
('SFAM', UInt32, 1), # Signed Flash Address Map
('ProtectEC', UInt32, 1), # Protected EC OpCodes
('GFXMitDis', UInt32, 1), # GFX Security Disable
('FTU', UInt32, 1), # Fault Tolerant Update
('Reserved', UInt32, 28) # Reserved/Unknown
]
class IntelBiosGuardHeaderGetAttributes(ctypes.Union):
""" Intel BIOS Guard Header Attributes Getter """
_pack_ = 1
_fields_ = [
('b', IntelBiosGuardHeaderAttributes),
('asbytes', uint32_t)
('asbytes', UInt32)
]
class IntelBiosGuardSignature2k(ctypes.LittleEndianStructure):
class IntelBiosGuardSignatureHeader(ctypes.LittleEndianStructure):
""" Intel BIOS Guard Signature Header """
_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, p):
Modulus = f'{int.from_bytes(self.Modulus, "little"):0{0x100 * 2}X}'
Signature = f'{int.from_bytes(self.Signature, "little"):0{0x100 * 2}X}'
printer(['Unknown 0:', f'0x{self.Unknown0:X}'], p, False)
printer(['Unknown 1:', f'0x{self.Unknown1:X}'], p, False)
printer(['Modulus :', f'{Modulus[:32]} [...]'], p, False)
printer(['Exponent :', f'0x{self.Exponent:X}'], p, False)
printer(['Signature:', f'{Signature[:32]} [...]'], p, False)
def is_ami_pfat(input_file):
input_buffer = file_to_bytes(input_file)
_fields_ = [
('Unknown0', UInt32), # 0x000
('Unknown1', UInt32), # 0x004
# 0x8
]
def struct_print(self, padd: int) -> None:
""" Display structure information """
printer(['Unknown 0:', f'0x{self.Unknown0:X}'], padd, False)
printer(['Unknown 1:', f'0x{self.Unknown1:X}'], padd, False)
class IntelBiosGuardSignatureRsa2k(ctypes.LittleEndianStructure):
""" Intel BIOS Guard Signature Block 2048-bit """
_pack_ = 1
# noinspection PyTypeChecker
_fields_ = [
('Modulus', UInt8 * 256), # 0x000
('Exponent', UInt32), # 0x100
('Signature', UInt8 * 256), # 0x104
# 0x204
]
def struct_print(self, padd: int) -> None:
""" Display structure information """
printer(['Modulus :', f'{bytes_to_hex(self.Modulus, "little", 0x100, 32)} [...]'], padd, False)
printer(['Exponent :', f'0x{self.Exponent:X}'], padd, False)
printer(['Signature:', f'{bytes_to_hex(self.Signature, "little", 0x100, 32)} [...]'], padd, False)
class IntelBiosGuardSignatureRsa3k(ctypes.LittleEndianStructure):
""" Intel BIOS Guard Signature Block 3072-bit """
_pack_ = 1
# noinspection PyTypeChecker
_fields_ = [
('Modulus', UInt8 * 384), # 0x000
('Exponent', UInt32), # 0x180
('Signature', UInt8 * 384), # 0x184
# 0x304
]
def struct_print(self, padd: int) -> None:
""" Display structure information """
printer(['Modulus :', f'{int.from_bytes(self.Modulus, "little"):0{0x180 * 2}X}'[:64]], padd, False)
printer(['Exponent :', f'0x{self.Exponent:X}'], padd, False)
printer(['Signature:', f'{int.from_bytes(self.Signature, "little"):0{0x180 * 2}X}'[:64]], padd, False)
def is_ami_pfat(input_object: str | bytes | bytearray) -> bool:
""" Check if input is AMI BIOS Guard """
input_buffer: bytes = file_to_bytes(input_object)
return bool(get_ami_pfat(input_buffer))
def get_ami_pfat(input_file):
input_buffer = file_to_bytes(input_file)
def get_ami_pfat(input_object: str | bytes | bytearray) -> bytes:
""" Get actual AMI BIOS Guard buffer """
input_buffer: bytes = file_to_bytes(input_object)
match = PAT_AMI_PFAT.search(input_buffer)
return input_buffer[match.start() - 0x8:] if match else b''
def get_file_name(index, name):
def get_file_name(index: int, name: str) -> str:
""" Create AMI BIOS Guard output filename """
return safe_name(f'{index:02d} -- {name}')
def parse_bg_script(script_data, padding=0):
is_opcode_div = len(script_data) % 8 == 0
def parse_bg_script(script_data: bytes, padding: int = 0) -> int:
""" Process Intel BIOS Guard Script """
is_opcode_div: bool = len(script_data) % 8 == 0
if not is_opcode_div:
printer('Error: Script is not divisible by OpCode length!', padding, False)
printer('Error: BIOS Guard script is not divisible by OpCode length!', padding, False)
return 1
is_begin_end = script_data[:8] + script_data[-8:] == b'\x01' + b'\x00' * 7 + b'\xFF' + b'\x00' * 7
is_begin_end: bool = script_data[:8] + script_data[-8:] == b'\x01' + b'\x00' * 7 + b'\xFF' + b'\x00' * 7
if not is_begin_end:
printer('Error: Script lacks Begin and/or End OpCodes!', padding, False)
printer('Error: BIOS Guard script lacks Begin and/or End OpCodes!', padding, False)
return 2
BigScript = get_bgs_tool()
if not BigScript:
big_script = get_bgs_tool()
if not big_script:
printer('Note: BIOS Guard Script Tool optional dependency is missing!', padding, False)
return 3
script = BigScript(code_bytes=script_data).to_string().replace('\t',' ').split('\n')
script = big_script(code_bytes=script_data).to_string().replace('\t', ' ').split('\n')
for opcode in script:
if opcode.endswith(('begin','end')): spacing = padding
elif opcode.endswith(':'): spacing = padding + 4
else: spacing = padding + 12
if opcode.endswith(('begin', 'end')):
spacing: int = padding
elif opcode.endswith(':'):
spacing = padding + 4
else:
spacing = padding + 12
operands = [operand for operand in opcode.split(' ') if operand]
printer(('{:<12s}' + '{:<11s}' * (len(operands) - 1)).format(*operands), spacing, False)
# Largest opcode length is 11 (erase64kblk) and largest operand length is 10 (0xAABBCCDD).
printer(f'{operands[0]:11s}{"".join((f" {o:10s}" for o in operands[1:]))}', spacing, False)
return 0
def parse_pfat_hdr(buffer, padding=0):
block_all = []
def parse_bg_sign(input_data: bytes, sign_offset: int, print_info: bool = False, padding: int = 0) -> int:
""" Process Intel BIOS Guard Signature """
bg_sig_hdr = get_struct(input_data, sign_offset, IntelBiosGuardSignatureHeader)
if bg_sig_hdr.Unknown0 == 1:
# Unknown0 = 1, Unknown1 = 1
bg_sig_rsa_struct = IntelBiosGuardSignatureRsa2k
else:
# Unknown0 = 2, Unknown1 = 3
bg_sig_rsa_struct = IntelBiosGuardSignatureRsa3k
bg_sig_rsa = get_struct(input_data, sign_offset + PFAT_BLK_SIG_LEN, bg_sig_rsa_struct)
if print_info:
bg_sig_hdr.struct_print(padding)
bg_sig_rsa.struct_print(padding)
# Total size of Signature Header and RSA Structure
return PFAT_BLK_SIG_LEN + ctypes.sizeof(bg_sig_rsa_struct)
def parse_pfat_hdr(buffer: bytes | bytearray, padding: int = 0) -> tuple:
""" Parse AMI BIOS Guard Header """
block_all: list = []
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()
hdr_size: int = pfat_hdr.Size
hdr_data: bytes = buffer[PFAT_AMI_HDR_LEN:hdr_size]
hdr_text: list[str] = hdr_data.decode('utf-8').splitlines()
printer('AMI BIOS Guard Header:\n', 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')
hdr_title, *hdr_files = hdr_text
files_count: int = len(hdr_files)
hdr_tag, *hdr_indexes = hdr_title.split('II')
printer(hdr_tag + '\n', padding + 4)
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 = f'{name} (Index: {index + 1:02d}, Flash: {order}, Parameter: {param}, Flags: 0x{flags:X}, Blocks: {count})'
bgt_indexes: list = [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: list = entry.split(';')
info: list = entry_parts[0].split()
name: str = entry_parts[1]
flags: int = int(info[0])
param: str = info[1]
count: int = int(info[2])
order: str = get_ordinal((bgt_indexes[index] if bgt_indexes else index) + 1)
desc = f'{name} (Index: {index + 1:02d}, Flash: {order}, ' \
f'Parameter: {param}, Flags: 0x{flags:X}, Blocks: {count})'
block_all += [(desc, name, order, param, flags, index, i, count) for i in range(count)]
_ = [printer(block[0], padding + 8, False) for block in block_all if block[6] == 0]
return block_all, hdr_size, files_count
def parse_pfat_file(input_file, extract_path, padding=0):
input_buffer = file_to_bytes(input_file)
pfat_buffer = get_ami_pfat(input_buffer)
file_path = ''
all_blocks_dict = {}
extract_name = os.path.basename(extract_path).rstrip(extract_suffix())
def parse_pfat_file(input_object: str | bytes | bytearray, extract_path: str, padding: int = 0) -> int:
""" Process and store AMI BIOS Guard output file """
input_buffer: bytes = file_to_bytes(input_object)
pfat_buffer: bytes = get_ami_pfat(input_buffer)
file_path: str = ''
all_blocks_dict: dict = {}
extract_name: str = path_name(extract_path).removesuffix(extract_suffix())
make_dirs(extract_path, delete=True)
block_all,block_off,file_count = parse_pfat_hdr(pfat_buffer, padding)
block_all, block_off, file_count = parse_pfat_hdr(pfat_buffer, padding)
for block in block_all:
file_desc,file_name,_,_,_,file_index,block_index,block_count = block
file_desc, file_name, _, _, _, file_index, block_index, block_count = block
if block_index == 0:
printer(file_desc, padding + 4)
file_path = os.path.join(extract_path, get_file_name(file_index + 1, file_name))
all_blocks_dict[file_index] = b''
block_status = f'{block_index + 1}/{block_count}'
block_status: str = f'{block_index + 1}/{block_count}'
bg_hdr = get_struct(pfat_buffer, block_off, IntelBiosGuardHeader)
printer(f'Intel BIOS Guard {block_status} Header:\n', padding + 8)
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 = pfat_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 = pfat_buffer[bg_data_bgn:bg_data_end]
block_off = bg_data_end # Assume next block starts at data end
bg_script_bgn: int = block_off + PFAT_BLK_HDR_LEN
bg_script_end: int = bg_script_bgn + bg_hdr.ScriptSize
bg_data_bgn: int = bg_script_end
bg_data_end: int = bg_data_bgn + bg_hdr.DataSize
bg_data_bin: bytes = pfat_buffer[bg_data_bgn:bg_data_end]
block_off: int = bg_data_end # Assume next block starts at data end
is_sfam, _, _, _, _ = bg_hdr.get_flags() # SFAM, ProtectEC, GFXMitDis, FTU, Reserved
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 = pfat_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)
printer(f'Intel BIOS Guard {block_status} Signature:\n', padding + 8)
bg_sig.struct_print(padding + 12)
printer(f'Intel BIOS Guard {block_status} Signature:\n', padding + 8)
# Adjust next block to start after current block Data + Signature
block_off += parse_bg_sign(pfat_buffer, bg_data_end, True, padding + 12)
block_off = bg_sig_end # Adjust next block to start at data + signature end
printer(f'Intel BIOS Guard {block_status} Script:\n', padding + 8)
_ = parse_bg_script(bg_script_bin, padding + 12)
_ = parse_bg_script(pfat_buffer[bg_script_bgn:bg_script_end], 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 = pfat_buffer[block_off:] # Store out-of-bounds data after the end of PFAT files
pfat_oob_name = get_file_name(file_count + 1, f'{extract_name}_OOB.bin')
pfat_oob_path = os.path.join(extract_path, pfat_oob_name)
if block_index + 1 == block_count:
if is_ami_pfat(all_blocks_dict[file_index]):
parse_pfat_file(all_blocks_dict[file_index], get_extract_path(file_path), padding + 8)
pfat_oob_data: bytes = pfat_buffer[block_off:] # Store out-of-bounds data after the end of PFAT files
pfat_oob_name: str = get_file_name(file_count + 1, f'{extract_name}_OOB.bin')
pfat_oob_path: str = os.path.join(extract_path, pfat_oob_name)
with open(pfat_oob_path, 'wb') as out_oob:
out_oob.write(pfat_oob_data)
if is_ami_pfat(pfat_oob_data):
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())])
in_all_name = get_file_name(0, f'{extract_name}_ALL.bin')
in_all_path = os.path.join(extract_path, in_all_name)
in_all_data: bytes = b''.join([block[1] for block in sorted(all_blocks_dict.items())])
in_all_name: str = get_file_name(0, f'{extract_name}_ALL.bin')
in_all_path: str = os.path.join(extract_path, in_all_name)
with open(in_all_path, 'wb') as out_all:
out_all.write(in_all_data + pfat_oob_data)
return 0
PFAT_AMI_HDR_LEN = ctypes.sizeof(AmiBiosGuardHeader)
PFAT_BLK_HDR_LEN = ctypes.sizeof(IntelBiosGuardHeader)
PFAT_BLK_S2K_LEN = ctypes.sizeof(IntelBiosGuardSignature2k)
PFAT_AMI_HDR_LEN: int = ctypes.sizeof(AmiBiosGuardHeader)
PFAT_BLK_HDR_LEN: int = ctypes.sizeof(IntelBiosGuardHeader)
PFAT_BLK_SIG_LEN: int = ctypes.sizeof(IntelBiosGuardSignatureHeader)
if __name__ == '__main__':
BIOSUtility(TITLE, is_ami_pfat, parse_pfat_file).run_utility()
BIOSUtility(title=TITLE, check=is_ami_pfat, main=parse_pfat_file).run_utility()