Skip to content

Commit

Permalink
Replace TianoCompress binary dependency with efi_compressor.EfiDecomp…
Browse files Browse the repository at this point in the history
…ress from uefi_firmware
  • Loading branch information
yeggor committed Nov 22, 2022
1 parent 03ae0cf commit 3bd5d76
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 44 deletions.
19 changes: 9 additions & 10 deletions AMI_UCP_Extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def uaf_extract(buffer, extract_path, mod_info, padding=0, checksum=False, nal_d
printer(f'Note: Detected new AMI UCP Module {uaf_tag} ({nal_dict[uaf_tag][1]}) in @NAL!', padding + 4, pause=True)

# Generate @UAF|@HPU Module File name, depending on whether decompression will be required
uaf_sname = safe_name(uaf_name + ('.temp' if is_comp else uaf_fext))
uaf_sname = safe_name(uaf_name + uaf_fext)
if uaf_tag in nal_dict:
uaf_npath = safe_path(extract_path, nal_dict[uaf_tag][0])
make_dirs(uaf_npath, exist_ok=True)
Expand Down Expand Up @@ -350,15 +350,14 @@ def uaf_extract(buffer, extract_path, mod_info, padding=0, checksum=False, nal_d

# @UAF|@HPU 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|@HPU 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|@HPU Module decompressed Raw data

os.remove(uaf_fname) # Successful decompression, delete compressed @UAF|@HPU Module file

uaf_fname = dec_fname # Adjust @UAF|@HPU Module file path to the decompressed one
decompressed_data = efi_decompress(uaf_data_raw, padding + 4)
if len(decompressed_data):
uaf_data_raw = decompressed_data # Save @UAF|@HPU Module decompressed Raw data
with open(uaf_fname, 'wb') as f:
f.write(uaf_data_raw)
else:
with open(f'{uaf_fname}.temp', 'wb') as f: # Create .temp file with compressed data
f.write(uaf_data_raw)

# Process and Print known text only @UAF|@HPU Modules (after EFI/Tiano Decompression)
if uaf_tag in UAF_TAG_DICT and UAF_TAG_DICT[uaf_tag][2] == 'Text':
Expand Down
14 changes: 10 additions & 4 deletions Fujitsu_UPC_Extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,18 @@ def is_fujitsu_upc(in_file):
# Parse & Extract Fujitsu UPC image
def fujitsu_upc_extract(input_file, extract_path, padding=0):
make_dirs(extract_path, delete=True)

image_base = os.path.basename(input_file)
image_name = image_base[:-4] if image_base.upper().endswith('.UPC') else image_base
image_path = os.path.join(extract_path, f'{image_name}.bin')

return efi_decompress(input_file, image_path, padding)


with open(input_file, 'rb') as f:
compressed_buffer = f.read()

decompressed_data = efi_decompress(compressed_buffer, padding)
if len(decompressed_data):
with open(image_path, 'wb') as f:
f.write(decompressed_data)

if __name__ == '__main__':
BIOSUtility(TITLE, is_fujitsu_upc, fujitsu_upc_extract).run_utility()
10 changes: 4 additions & 6 deletions Portwell_EFI_Extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,10 @@ def parse_efi_files(extract_path, efi_files, padding):

# Attempt to detect EFI compression & decompress when applicable
if is_efi_compressed(file_data):
comp_fname = file_path + '.temp' # Store temporary compressed file name

os.replace(file_path, comp_fname) # Rename initial/compressed file

if efi_decompress(comp_fname, file_path, padding + 8) == 0:
os.remove(comp_fname) # Successful decompression, delete compressed file
decompressed_data = efi_decompress(file_data, padding + 8)
if len(decompressed_data):
with open(file_path, 'wb') as out_file:
out_file.write(decompressed_data) # Overwrite a file with decompressed data

if __name__ == '__main__':
BIOSUtility(TITLE, is_portwell_efi, portwell_efi_extract).run_utility()
40 changes: 16 additions & 24 deletions common/comp_efi.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
Copyright (C) 2022 Plato Mavropoulos
"""

import os
import subprocess
from uefi_firmware import efi_compressor

from common.system import printer

from common.path_ops import project_root, safe_path
from common.system import get_os_ver, printer

def get_compress_sizes(data):
size_compress = int.from_bytes(data[0x0:0x4], 'little')
Expand All @@ -29,29 +28,22 @@ def is_efi_compressed(data, strict=True):

return check_diff and check_size

# Get TianoCompress path
def get_tiano_path():
exec_name = f'TianoCompress{".exe" if get_os_ver()[1] else ""}'

return safe_path(project_root(), ['external',exec_name])

# EFI/Tiano Decompression via TianoCompress
def efi_decompress(in_path, out_path, padding=0, silent=False, comp_type='--uefi'):
def efi_decompress(compressed_buffer, padding=0, silent=False):
if len(compressed_buffer) < 8:
raise Exception('EFI_DECOMPRESS_ERROR')

_, size_orig = get_compress_sizes(compressed_buffer)
try:
subprocess.run([get_tiano_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:
decompressed_data = efi_compressor.EfiDecompress(compressed_buffer, len(compressed_buffer))
if len(decompressed_data) != size_orig:
raise Exception('EFI_DECOMPRESS_ERROR')
except Exception:
if not silent:
printer(f'Error: TianoCompress could not extract file {in_path}!', padding)

return 1

printer(f'Error: efi_compressor.EfiDecompress could not decompress file content!', padding)
return bytes()

if not silent:
printer('Succesfull EFI decompression via TianoCompress!', padding)
return 0
printer('Succesfull EFI decompression via efi_compressor.EfiDecompress!', padding)

return decompressed_data
1 change: 1 addition & 0 deletions external/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
lznt1 >= 0.2
pefile >= 2022.5.30
uefi-firmware >= 1.9

0 comments on commit 3bd5d76

Please sign in to comment.