diff --git a/Fujitsu_UPC_Extract.py b/Fujitsu_UPC_Extract.py new file mode 100644 index 0000000..55929a8 --- /dev/null +++ b/Fujitsu_UPC_Extract.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +#coding=utf-8 + +""" +Fujitsu UPC Extract +Fujitsu UPC BIOS Extractor +Copyright (C) 2021-2022 Plato Mavropoulos +""" + +TITLE = 'Fujitsu UPC BIOS Extractor v2.0_a2' + +import os +import sys + +# Stop __pycache__ generation +sys.dont_write_bytecode = True + +from common.comp_efi import efi_decompress, is_efi_compressed +from common.path_ops import make_dirs, path_suffixes +from common.system import script_init, argparse_init, printer +from common.text_ops import file_to_bytes + +# Check if input is Fujitsu UPC image +def is_fujitsu_upc(in_file): + in_buffer = file_to_bytes(in_file) + + is_upc = path_suffixes(in_file)[-1].upper() == '.UPC' if os.path.isfile(in_file) else True + + is_efi = is_efi_compressed(in_buffer) + + return is_upc and is_efi + +# Parse & Extract Fujitsu UPC image +def fujitsu_upc_extract(input_file, output_path, padding=0): + extract_path = os.path.join(f'{output_path}_extracted') + + 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) + +if __name__ == '__main__': + # Set argparse Arguments + argparser = argparse_init() + arguments = argparser.parse_args() + + # Initialize script (must be after argparse) + exit_code,input_files,output_path,padding = script_init(TITLE, arguments, 4) + + for input_file in input_files: + input_name = os.path.basename(input_file) + + printer(['***', input_name], padding - 4) + + with open(input_file, 'rb') as in_file: input_buffer = in_file.read() + + if not is_fujitsu_upc(input_buffer): + printer('Error: This is not a Fujitsu UPC BIOS image!', padding) + + continue # Next input file + + extract_path = os.path.join(output_path, input_name) + + if fujitsu_upc_extract(input_file, extract_path, padding) == 0: + exit_code -= 1 + + printer('Done!', pause=True) + + sys.exit(exit_code) diff --git a/README.md b/README.md index 88851a7..27d926b 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ * [**AMI UCP Update Extractor**](#ami-ucp-update-extractor) * [**Award BIOS Module Extractor**](#award-bios-module-extractor) * [**Dell PFS Update Extractor**](#dell-pfs-update-extractor) +* [**Fujitsu UPC BIOS Extractor**](#fujitsu-upc-bios-extractor) * [**Panasonic BIOS Package Extractor**](#panasonic-bios-package-extractor) * [**Phoenix TDK Packer Extractor**](#phoenix-tdk-packer-extractor) * [**Portwell EFI Update Extractor**](#portwell-efi-update-extractor) @@ -256,6 +257,64 @@ Some Anti-Virus software may claim that the built/frozen/compiled executable con ![]() +## **Fujitsu UPC BIOS Extractor** + +![]() + +#### **Description** + +Parses Fujitsu UPC images and extracts their EFI compressed SPI/BIOS/UEFI 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 Panasonic BIOS Package executable file(s). Optional arguments: + +* -h or --help : show help message and exit +* -v or --version : show utility name and version +* -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 + +#### **Compatibility** + +Should work at all Windows, Linux or macOS operating systems which have Python 3.8 support. + +#### **Prerequisites** + +To run the utility, you must have the following 3rd party tool at the "external" project directory: + +* [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 for Linux) + +#### **Build/Freeze/Compile with PyInstaller** + +PyInstaller can build/freeze/compile the utility at all three supported platforms, it is simple to run and gets updated often. + +1. Make sure Python 3.8.0 or newer is installed: + +> python --version + +2. Use pip to install PyInstaller: + +> pip3 install pyinstaller + +3. Place prerequisite at the "external" project directory: + +> TianoCompress + +4. Build/Freeze/Compile: + +> pyinstaller --add-data="external/*;external/" --noupx --onefile \\/Fujitsu_UPC_Extract.py + +You should find the final utility executable at "dist" folder + +#### **Anti-Virus False Positives** + +Some Anti-Virus software may claim that the built/frozen/compiled executable contains viruses. Any such detections are false positives, usually of PyInstaller. You can switch to a better Anti-Virus software, report the false positive to their support, add the executable to the exclusions, build/freeze/compile yourself or use the Python script directly. + +#### **Pictures** + +![]() + ## **Panasonic BIOS Package Extractor** ![]() diff --git a/common/path_ops.py b/common/path_ops.py index 5cc4ebd..5e76eef 100644 --- a/common/path_ops.py +++ b/common/path_ops.py @@ -74,6 +74,10 @@ def path_parent(in_path): def path_stem(in_path): return PurePath(in_path).stem +# Get list of path file extensions +def path_suffixes(in_path): + return PurePath(in_path).suffixes + # Check if path is absolute def is_path_absolute(in_path): return Path(in_path).is_absolute()