diff --git a/.gitignore b/.gitignore index a1b95bc..778ef46 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /.idea/ /.mypy_cache/ +/biosutilities/external/ /external/ /venv/ diff --git a/CHANGELOG b/CHANGELOG index d5ee313..ff3fb27 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +24.10.03 + +Added external executable dependencies non-PATH flow (#51) +Improved the README with Usage, Dependencies, Examples etc + 24.10.01 Complete repository overhaul into python project diff --git a/LICENSE b/LICENSE index 0265ddc..4c9a6fe 100644 --- a/LICENSE +++ b/LICENSE @@ -16,4 +16,4 @@ Except as expressly stated above, no rights or licenses from any copyright holde DISCLAIMER -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index a65e72c..c328114 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ from biosutilities.ami_pfat_extract import AmiPfatExtract ami_pfat_extractor = AmiPfatExtract() ami_pfat_extractor.check_format(input_object='/path/to/input/file.bin') -ami_pfat_extractor.parse_format(input_object='/path/to/input/file.bin') +ami_pfat_extractor.parse_format(input_object='/path/to/input/file.bin', extract_path='/path/to/output/folder/') ``` ``` python @@ -82,7 +82,23 @@ with open(file='/path/to/input/file.bin', mode='rb') as pfs_file: pfs_buffer = pfs_file.read() dell_pfs_extractor.check_format(input_object=pfs_buffer) -dell_pfs_extractor.parse_format(input_object=pfs_buffer) +dell_pfs_extractor.parse_format(input_object=pfs_buffer, extract_path='/path/to/output/directory/', padding=8) +``` + +``` python +from biosutilities.phoenix_tdk_extract import PhoenixTdkExtract + +phoenix_tdk_extractor = PhoenixTdkExtract(arguments=['-e', '/path/to/input/file.bin', '-o', '/path/to/output/folder/']) + +phoenix_tdk_extractor.run_utility(padding=4) +``` + +``` python +from biosutilities.apple_efi_pbzx import AppleEfiPbzxExtract + +apple_efi_pbzx_extractor = AppleEfiPbzxExtract() + +apple_efi_pbzx_extractor.show_version(is_boxed=False, padding=12) ``` It also allows to use directly the four public methods which are inherited by every utility from the base BIOSUtility class. @@ -135,9 +151,11 @@ python -m pip install --upgrade -r requirements.txt python -m pip install --upgrade pefile ``` -### External Executables / Python Scripts +### External Executables / Scripts -External executables (e.g. 7-Zip, TianoCompress, UEFIFind) and Python scripts (e.g. BIOS Guard Script Tool) need to be found via PATH. +External executables and/or scripts (e.g. TianoCompress.exe, big_script_tool.py, 7z.exe) need to be found via the "PATH" environment variable, which is configured differently depending on the operating system. + +Alternatively, if neither modifying PATH environment variable nor copying the executables in standard OS PATH directories is an option, you can create a folder "external" at the root of the "biosutilities" project. #### Linux @@ -146,13 +164,15 @@ External executables (e.g. 7-Zip, TianoCompress, UEFIFind) and Python scripts (e or ``` bash -sudo install "/path/to/downloaded/external/executable/to/install" +sudo install "/path/to/downloaded/external/executable/to/install" /usr/local/bin ``` #### Windows [Windows Path](https://www.computerhope.com/issues/ch000549.htm) +**Note:** In the "Environment Variables" window, you can modify the "Path" variable under "User variables" instead of "System variables", as many guides suggest. + #### MacOS [Mac Path](https://mac.install.guide/terminal/path) @@ -194,7 +214,7 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3 #### **Prerequisites** -Optionally, to decompile the AMI PFAT \> Intel BIOS Guard Scripts, you must have the following 3rd party python script at PATH: +Optionally, to decompile the AMI PFAT \> Intel BIOS Guard Scripts, you must have the following 3rd party python script at PATH or "external": * [BIOS Guard Script Tool](https://github.com/platomav/BGScriptTool) (i.e. big_script_tool.py) @@ -216,12 +236,12 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3 #### **Prerequisites** -To run the utility, you must have the following 3rd party tools at PATH: +To run the utility, you must have the following 3rd party tools at PATH or "external": -* [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (i.e. [TianoCompress.exe for Windows](https://github.com/tianocore/edk2-BaseTools-win32/) or TianoCompress for Linux) -* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zzs for Linux) +* [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (i.e. [TianoCompress.exe for Windows](https://github.com/tianocore/edk2-BaseTools-win32/) or TianoCompress for Linux/macOS) +* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zz for macOS or 7zz, 7zzs for Linux) -Optionally, to decompile the AMI UCP \> AMI PFAT \> Intel BIOS Guard Scripts (when applicable), you must have the following 3rd party python script at PATH: +Optionally, to decompile the AMI UCP \> AMI PFAT \> Intel BIOS Guard Scripts (when applicable), you must have the following 3rd party python script at PATH or "external": * [BIOS Guard Script Tool](https://github.com/platomav/BGScriptTool) (i.e. big_script_tool.py) @@ -239,6 +259,8 @@ No additional optional arguments are provided for this utility. Should work at all Windows, Linux or macOS operating systems which have Python 3.10 or newer support. +Note: On Linux and macOS, you'll need to compile TianoCompress from sources as no pre-built binary exists. + #### **Prerequisites** To run the utility, you do not need any prerequisites. @@ -259,10 +281,10 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3 #### **Prerequisites** -To run the utility, you must have the following 3rd party tools at PATH: +To run the utility, you must have the following 3rd party tools at PATH or "external": -* [UEFIFind](https://github.com/LongSoft/UEFITool/) (i.e. [UEFIFind.exe for Windows or UEFIFind for Linux](https://github.com/LongSoft/UEFITool/releases)) -* [UEFIExtract](https://github.com/LongSoft/UEFITool/) (i.e. [UEFIExtract.exe for Windows or UEFIExtract for Linux](https://github.com/LongSoft/UEFITool/releases)) +* [UEFIFind](https://github.com/LongSoft/UEFITool/) (i.e. [UEFIFind.exe for Windows or UEFIFind for Linux/macOS](https://github.com/LongSoft/UEFITool/releases)) +* [UEFIExtract](https://github.com/LongSoft/UEFITool/) (i.e. [UEFIExtract.exe for Windows or UEFIExtract for Linux/macOS](https://github.com/LongSoft/UEFITool/releases)) ### **Apple EFI Package Extractor** @@ -280,9 +302,9 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3 #### **Prerequisites** -To run the utility, you must have the following 3rd party tools at PATH: +To run the utility, you must have the following 3rd party tools at PATH or "external": -* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zzs for Linux) +* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zz for macOS or 7zz, 7zzs for Linux) ### **Apple EFI PBZX Extractor** @@ -300,9 +322,9 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3 #### **Prerequisites** -To run the utility, you must have the following 3rd party tools at PATH: +To run the utility, you must have the following 3rd party tools at PATH or "external": -* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zzs for Linux) +* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zz for macOS or 7zz, 7zzs for Linux) ### **Award BIOS Module Extractor** @@ -320,9 +342,9 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3 #### **Prerequisites** -To run the utility, you must have the following 3rd party tool at PATH: +To run the utility, you must have the following 3rd party tool at PATH or "external": -* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zzs for Linux) +* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zz for macOS or 7zz, 7zzs for Linux) ### **Dell PFS Update Extractor** @@ -343,7 +365,7 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3 #### **Prerequisites** -Optionally, to decompile the Intel BIOS Guard (PFAT) Scripts, you must have the following 3rd party utility at PATH: +Optionally, to decompile the Intel BIOS Guard (PFAT) Scripts, you must have the following 3rd party utility at PATH or "external": * [BIOS Guard Script Tool](https://github.com/platomav/BGScriptTool) (i.e. big_script_tool.py) @@ -363,9 +385,9 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3 #### **Prerequisites** -To run the utility, you must have the following 3rd party tool at PATH: +To run the utility, you must have the following 3rd party tool at PATH or "external": -* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zzs for Linux) +* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zz for macOS or 7zz, 7zzs for Linux) ### **Fujitsu UPC BIOS Extractor** @@ -383,9 +405,9 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3 #### **Prerequisites** -To run the utility, you must have the following 3rd party tool at PATH: +To run the utility, you must have the following 3rd party tool at PATH or "external": -* [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (i.e. [TianoCompress.exe for Windows](https://github.com/tianocore/edk2-BaseTools-win32/) or TianoCompress for Linux) +* [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (i.e. [TianoCompress.exe for Windows](https://github.com/tianocore/edk2-BaseTools-win32/) or TianoCompress for Linux/macOS) ### **Insyde iFlash/iFdPacker Extractor** @@ -401,6 +423,8 @@ No additional optional arguments are provided for this utility. Should work at all Windows, Linux or macOS operating systems which have Python 3.10 or newer support. +Note: On Linux and macOS, you'll need to compile TianoCompress from sources as no pre-built binary exists. + #### **Prerequisites** To run the utility, you do not need any prerequisites. @@ -426,9 +450,9 @@ To run the utility, you must have the following 3rd party Python modules install * [pefile](https://pypi.org/project/pefile/) * [dissect.util](https://pypi.org/project/dissect.util/) -Moreover, you must have the following 3rd party tool at PATH: +Moreover, you must have the following 3rd party tool at PATH or "external": -* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zzs for Linux) +* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zz for macOS or 7zz, 7zzs for Linux) ### **Phoenix TDK Packer Extractor** @@ -470,9 +494,9 @@ To run the utility, you must have the following 3rd party Python module installe * [pefile](https://pypi.org/project/pefile/) -Moreover, you must have the following 3rd party tool at PATH: +Moreover, you must have the following 3rd party tool at PATH or "external": -* [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (i.e. [TianoCompress.exe for Windows](https://github.com/tianocore/edk2-BaseTools-win32/) or TianoCompress for Linux) +* [TianoCompress](https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/TianoCompress/) (i.e. [TianoCompress.exe for Windows](https://github.com/tianocore/edk2-BaseTools-win32/) or TianoCompress for Linux/macOS) ### **Toshiba BIOS COM Extractor** @@ -488,11 +512,13 @@ No additional optional arguments are provided for this utility. Should work at all Windows, Linux or macOS operating systems which have Python 3.10 or newer support. +Note: On Linux and macOS, you'll need to compile TianoCompress from sources as no pre-built binary exists. + #### **Prerequisites** -To run the utility, you must have the following 3rd party tool at PATH: +To run the utility, you must have the following 3rd party tool at PATH or "external": -* [ToshibaComExtractor](https://github.com/LongSoft/ToshibaComExtractor) (i.e. [comextract.exe for Windows or comextract for Linux](https://github.com/LongSoft/ToshibaComExtractor/releases)) +* [ToshibaComExtractor](https://github.com/LongSoft/ToshibaComExtractor) (i.e. [comextract.exe for Windows or comextract for Linux/macOS](https://github.com/LongSoft/ToshibaComExtractor/releases)) ### **VAIO Packaging Manager Extractor** @@ -508,8 +534,10 @@ No additional optional arguments are provided for this utility. Should work at all Windows, Linux or macOS operating systems which have Python 3.10 or newer support. +Note: On Linux, you'll need to compile comextract from sources as no pre-built binary exists. + #### **Prerequisites** -To run the utility, you must have the following 3rd party tool at PATH: +To run the utility, you must have the following 3rd party tool at PATH or "external": -* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zzs for Linux) +* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zz for macOS or 7zz, 7zzs for Linux) diff --git a/biosutilities/__init__.py b/biosutilities/__init__.py index a89b9e6..4398cec 100644 --- a/biosutilities/__init__.py +++ b/biosutilities/__init__.py @@ -5,4 +5,4 @@ Copyright (C) 2018-2024 Plato Mavropoulos """ -__version__ = '24.10.01' +__version__ = '24.10.03' diff --git a/biosutilities/common/externals.py b/biosutilities/common/externals.py index 370e558..2dc76f4 100644 --- a/biosutilities/common/externals.py +++ b/biosutilities/common/externals.py @@ -16,13 +16,35 @@ from importlib.util import module_from_spec, spec_from_file_location from types import ModuleType from typing import Type +from biosutilities.common.paths import project_root +from biosutilities.common.texts import to_string + + +def get_external_path(cmd: str | list | tuple, raise_on_error: bool = True) -> str | None: + """ Get external dependency path (PATH environment variable or "external" directory) """ + + external_root: str = os.path.join(project_root(), 'external') + + external_path: str | None = external_root if os.path.isdir(external_root) else None + + for command in cmd if isinstance(cmd, (list, tuple)) else [to_string(in_object=cmd)]: + command_path: str | None = shutil.which(cmd=command, path=external_path) + + if command_path and os.path.isfile(path=command_path): + return command_path + + if raise_on_error: + raise OSError(f'{to_string(in_object=cmd, sep_char=", ")} could not be found!') + + return None + def big_script_tool() -> Type | None: """ Get Intel BIOS Guard Script Tool class """ - bgst: str | None = shutil.which(cmd='big_script_tool') + bgst: str | None = get_external_path(cmd='big_script_tool', raise_on_error=False) - if bgst and os.path.isfile(path=bgst): + if bgst is not None: bgst_spec: ModuleSpec | None = spec_from_file_location( name='big_script_tool', location=re.sub(r'\.PY$', '.py', bgst)) @@ -39,56 +61,31 @@ def big_script_tool() -> Type | None: return None -def comextract_path() -> str: +def comextract_path() -> str | None: """ Get ToshibaComExtractor path """ - comextract: str | None = shutil.which(cmd='comextract') - - if not (comextract and os.path.isfile(path=comextract)): - raise OSError('comextract executable not found!') - - return comextract + return get_external_path(cmd='comextract') -def szip_path() -> str: +def szip_path() -> str | None: """ Get 7-Zip path """ - szip: str | None = shutil.which(cmd='7zzs') or shutil.which(cmd='7z') - - if not (szip and os.path.isfile(path=szip)): - raise OSError('7zzs or 7z executable not found!') - - return szip + return get_external_path(cmd=['7zzs', '7zz', '7z']) -def tiano_path() -> str: +def tiano_path() -> str | None: """ Get TianoCompress path """ - tiano: str | None = shutil.which(cmd='TianoCompress') - - if not (tiano and os.path.isfile(path=tiano)): - raise OSError('TianoCompress executable not found!') - - return tiano + return get_external_path(cmd='TianoCompress') -def uefifind_path() -> str: +def uefifind_path() -> str | None: """ Get UEFIFind path """ - uefifind: str | None = shutil.which(cmd='UEFIFind') - - if not (uefifind and os.path.isfile(path=uefifind)): - raise OSError('UEFIFind executable not found!') - - return uefifind + return get_external_path(cmd='UEFIFind') -def uefiextract_path() -> str: +def uefiextract_path() -> str | None: """ Get UEFIExtract path """ - uefiextract: str | None = shutil.which(cmd='UEFIExtract') - - if not (uefiextract and os.path.isfile(path=uefiextract)): - raise OSError('UEFIExtract executable not found!') - - return uefiextract + return get_external_path(cmd='UEFIExtract')