mirror of
https://github.com/outbackdingo/OpCore-Simplify.git
synced 2026-01-27 02:19:41 +00:00
Initial commit
This commit is contained in:
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
||||||
163
.gitignore
vendored
Normal file
163
.gitignore
vendored
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
*.DS_Store
|
||||||
|
OCK_Files
|
||||||
29
LICENSE
Executable file
29
LICENSE
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2024, lzhoang2601
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
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 HOLDER 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.
|
||||||
BIN
OcBinaryData/Resources/Font/Font_1x.bin
Executable file
BIN
OcBinaryData/Resources/Font/Font_1x.bin
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
BIN
OcBinaryData/Resources/Font/Font_1x.png
Executable file
BIN
OcBinaryData/Resources/Font/Font_1x.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
OcBinaryData/Resources/Font/Font_2x.bin
Executable file
BIN
OcBinaryData/Resources/Font/Font_2x.bin
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
BIN
OcBinaryData/Resources/Font/Font_2x.png
Executable file
BIN
OcBinaryData/Resources/Font/Font_2x.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/AppleRecv.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/AppleRecv.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/AppleTM.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/AppleTM.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Background.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Background.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/BtnFocus.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/BtnFocus.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Cursor.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Cursor.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Dot.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Dot.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Enter.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Enter.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/ExtAppleRecv.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/ExtAppleRecv.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/ExtAppleTM.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/ExtAppleTM.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/ExtHardDrive.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/ExtHardDrive.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/HardDrive.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/HardDrive.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Left.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Left.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Lock.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Lock.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Password.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Password.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Restart.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Restart.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Right.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Right.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Selected.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Selected.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Selector.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Selector.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/SetDefault.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/SetDefault.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Shell.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Shell.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/ShutDown.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/ShutDown.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Tool.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Tool.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Windows.icns
Executable file
BIN
OcBinaryData/Resources/Image/Acidanthera/GoldenGate/Windows.icns
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/Apple.l2x
Executable file
BIN
OcBinaryData/Resources/Label/Apple.l2x
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/Apple.lbl
Executable file
BIN
OcBinaryData/Resources/Label/Apple.lbl
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/AppleRecv.l2x
Executable file
BIN
OcBinaryData/Resources/Label/AppleRecv.l2x
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/AppleRecv.lbl
Executable file
BIN
OcBinaryData/Resources/Label/AppleRecv.lbl
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/AppleTM.l2x
Executable file
BIN
OcBinaryData/Resources/Label/AppleTM.l2x
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/AppleTM.lbl
Executable file
BIN
OcBinaryData/Resources/Label/AppleTM.lbl
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/EFIBoot.l2x
Executable file
BIN
OcBinaryData/Resources/Label/EFIBoot.l2x
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/EFIBoot.lbl
Executable file
BIN
OcBinaryData/Resources/Label/EFIBoot.lbl
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/Other.l2x
Executable file
BIN
OcBinaryData/Resources/Label/Other.l2x
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/Other.lbl
Executable file
BIN
OcBinaryData/Resources/Label/Other.lbl
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/ResetNVRAM.l2x
Executable file
BIN
OcBinaryData/Resources/Label/ResetNVRAM.l2x
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/ResetNVRAM.lbl
Executable file
BIN
OcBinaryData/Resources/Label/ResetNVRAM.lbl
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/SIPDisabled.l2x
Executable file
BIN
OcBinaryData/Resources/Label/SIPDisabled.l2x
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/SIPDisabled.lbl
Executable file
BIN
OcBinaryData/Resources/Label/SIPDisabled.lbl
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/SIPEnabled.l2x
Executable file
BIN
OcBinaryData/Resources/Label/SIPEnabled.l2x
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/SIPEnabled.lbl
Executable file
BIN
OcBinaryData/Resources/Label/SIPEnabled.lbl
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/Shell.l2x
Executable file
BIN
OcBinaryData/Resources/Label/Shell.l2x
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/Shell.lbl
Executable file
BIN
OcBinaryData/Resources/Label/Shell.lbl
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/Tool.l2x
Executable file
BIN
OcBinaryData/Resources/Label/Tool.l2x
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/Tool.lbl
Executable file
BIN
OcBinaryData/Resources/Label/Tool.lbl
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/Windows.l2x
Executable file
BIN
OcBinaryData/Resources/Label/Windows.l2x
Executable file
Binary file not shown.
BIN
OcBinaryData/Resources/Label/Windows.lbl
Executable file
BIN
OcBinaryData/Resources/Label/Windows.lbl
Executable file
Binary file not shown.
397
OpCore-Simplify.bat
Executable file
397
OpCore-Simplify.bat
Executable file
@@ -0,0 +1,397 @@
|
|||||||
|
@echo off
|
||||||
|
REM Get our local path before delayed expansion - allows ! in path
|
||||||
|
set "thisDir=%~dp0"
|
||||||
|
|
||||||
|
setlocal enableDelayedExpansion
|
||||||
|
REM Setup initial vars
|
||||||
|
set "script_name="
|
||||||
|
set /a tried=0
|
||||||
|
set "toask=yes"
|
||||||
|
set "pause_on_error=yes"
|
||||||
|
set "py2v="
|
||||||
|
set "py2path="
|
||||||
|
set "py3v="
|
||||||
|
set "py3path="
|
||||||
|
set "pypath="
|
||||||
|
set "targetpy=3"
|
||||||
|
|
||||||
|
REM use_py3:
|
||||||
|
REM TRUE = Use if found, use py2 otherwise
|
||||||
|
REM FALSE = Use py2
|
||||||
|
REM FORCE = Use py3
|
||||||
|
set "use_py3=TRUE"
|
||||||
|
|
||||||
|
REM We'll parse if the first argument passed is
|
||||||
|
REM --install-python and if so, we'll just install
|
||||||
|
set "just_installing=FALSE"
|
||||||
|
|
||||||
|
REM Get the system32 (or equivalent) path
|
||||||
|
call :getsyspath "syspath"
|
||||||
|
|
||||||
|
REM Make sure the syspath exists
|
||||||
|
if "!syspath!" == "" (
|
||||||
|
if exist "%SYSTEMROOT%\system32\cmd.exe" (
|
||||||
|
if exist "%SYSTEMROOT%\system32\reg.exe" (
|
||||||
|
if exist "%SYSTEMROOT%\system32\where.exe" (
|
||||||
|
REM Fall back on the default path if it exists
|
||||||
|
set "ComSpec=%SYSTEMROOT%\system32\cmd.exe"
|
||||||
|
set "syspath=%SYSTEMROOT%\system32\"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if "!syspath!" == "" (
|
||||||
|
cls
|
||||||
|
echo ### ###
|
||||||
|
echo # Warning #
|
||||||
|
echo ### ###
|
||||||
|
echo.
|
||||||
|
echo Could not locate cmd.exe, reg.exe, or where.exe
|
||||||
|
echo.
|
||||||
|
echo Please ensure your ComSpec environment variable is properly configured and
|
||||||
|
echo points directly to cmd.exe, then try again.
|
||||||
|
echo.
|
||||||
|
echo Current CompSpec Value: "%ComSpec%"
|
||||||
|
echo.
|
||||||
|
echo Press [enter] to quit.
|
||||||
|
pause > nul
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%~1" == "--install-python" (
|
||||||
|
set "just_installing=TRUE"
|
||||||
|
goto installpy
|
||||||
|
)
|
||||||
|
|
||||||
|
goto checkscript
|
||||||
|
|
||||||
|
:checkscript
|
||||||
|
REM Check for our script first
|
||||||
|
set "looking_for=!script_name!"
|
||||||
|
if "!script_name!" == "" (
|
||||||
|
set "looking_for=%~n0.py or %~n0.command"
|
||||||
|
set "script_name=%~n0.py"
|
||||||
|
if not exist "!thisDir!\!script_name!" (
|
||||||
|
set "script_name=%~n0.command"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if not exist "!thisDir!\!script_name!" (
|
||||||
|
echo Could not find !looking_for!.
|
||||||
|
echo Please make sure to run this script from the same directory
|
||||||
|
echo as !looking_for!.
|
||||||
|
echo.
|
||||||
|
echo Press [enter] to quit.
|
||||||
|
pause > nul
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
goto checkpy
|
||||||
|
|
||||||
|
:checkpy
|
||||||
|
call :updatepath
|
||||||
|
for /f "USEBACKQ tokens=*" %%x in (`!syspath!where.exe python 2^> nul`) do ( call :checkpyversion "%%x" "py2v" "py2path" "py3v" "py3path" )
|
||||||
|
for /f "USEBACKQ tokens=*" %%x in (`!syspath!where.exe python3 2^> nul`) do ( call :checkpyversion "%%x" "py2v" "py2path" "py3v" "py3path" )
|
||||||
|
for /f "USEBACKQ tokens=*" %%x in (`!syspath!where.exe py 2^> nul`) do ( call :checkpylauncher "%%x" "py2v" "py2path" "py3v" "py3path" )
|
||||||
|
REM Walk our returns to see if we need to install
|
||||||
|
if /i "!use_py3!" == "FALSE" (
|
||||||
|
set "targetpy=2"
|
||||||
|
set "pypath=!py2path!"
|
||||||
|
) else if /i "!use_py3!" == "FORCE" (
|
||||||
|
set "pypath=!py3path!"
|
||||||
|
) else if /i "!use_py3!" == "TRUE" (
|
||||||
|
set "pypath=!py3path!"
|
||||||
|
if "!pypath!" == "" set "pypath=!py2path!"
|
||||||
|
)
|
||||||
|
if not "!pypath!" == "" (
|
||||||
|
goto runscript
|
||||||
|
)
|
||||||
|
if !tried! lss 1 (
|
||||||
|
if /i "!toask!"=="yes" (
|
||||||
|
REM Better ask permission first
|
||||||
|
goto askinstall
|
||||||
|
) else (
|
||||||
|
goto installpy
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
cls
|
||||||
|
echo ### ###
|
||||||
|
echo # Warning #
|
||||||
|
echo ### ###
|
||||||
|
echo.
|
||||||
|
REM Couldn't install for whatever reason - give the error message
|
||||||
|
echo Python is not installed or not found in your PATH var.
|
||||||
|
echo Please install it from https://www.python.org/downloads/windows/
|
||||||
|
echo.
|
||||||
|
echo Make sure you check the box labeled:
|
||||||
|
echo.
|
||||||
|
echo "Add Python X.X to PATH"
|
||||||
|
echo.
|
||||||
|
echo Where X.X is the py version you're installing.
|
||||||
|
echo.
|
||||||
|
echo Press [enter] to quit.
|
||||||
|
pause > nul
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
goto runscript
|
||||||
|
|
||||||
|
:checkpylauncher <path> <py2v> <py2path> <py3v> <py3path>
|
||||||
|
REM Attempt to check the latest python 2 and 3 versions via the py launcher
|
||||||
|
for /f "USEBACKQ tokens=*" %%x in (`%~1 -2 -c "import sys; print(sys.executable)" 2^> nul`) do ( call :checkpyversion "%%x" "%~2" "%~3" "%~4" "%~5" )
|
||||||
|
for /f "USEBACKQ tokens=*" %%x in (`%~1 -3 -c "import sys; print(sys.executable)" 2^> nul`) do ( call :checkpyversion "%%x" "%~2" "%~3" "%~4" "%~5" )
|
||||||
|
goto :EOF
|
||||||
|
|
||||||
|
:checkpyversion <path> <py2v> <py2path> <py3v> <py3path>
|
||||||
|
set "version="&for /f "tokens=2* USEBACKQ delims= " %%a in (`"%~1" -V 2^>^&1`) do (
|
||||||
|
REM Ensure we have a version number
|
||||||
|
call :isnumber "%%a"
|
||||||
|
if not "!errorlevel!" == "0" goto :EOF
|
||||||
|
set "version=%%a"
|
||||||
|
)
|
||||||
|
if not defined version goto :EOF
|
||||||
|
if "!version:~0,1!" == "2" (
|
||||||
|
REM Python 2
|
||||||
|
call :comparepyversion "!version!" "!%~2!"
|
||||||
|
if "!errorlevel!" == "1" (
|
||||||
|
set "%~2=!version!"
|
||||||
|
set "%~3=%~1"
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
REM Python 3
|
||||||
|
call :comparepyversion "!version!" "!%~4!"
|
||||||
|
if "!errorlevel!" == "1" (
|
||||||
|
set "%~4=!version!"
|
||||||
|
set "%~5=%~1"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
goto :EOF
|
||||||
|
|
||||||
|
:isnumber <check_value>
|
||||||
|
set "var="&for /f "delims=0123456789." %%i in ("%~1") do set var=%%i
|
||||||
|
if defined var (exit /b 1)
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:comparepyversion <version1> <version2> <return>
|
||||||
|
REM Exits with status 0 if equal, 1 if v1 gtr v2, 2 if v1 lss v2
|
||||||
|
for /f "tokens=1,2,3 delims=." %%a in ("%~1") do (
|
||||||
|
set a1=%%a
|
||||||
|
set a2=%%b
|
||||||
|
set a3=%%c
|
||||||
|
)
|
||||||
|
for /f "tokens=1,2,3 delims=." %%a in ("%~2") do (
|
||||||
|
set b1=%%a
|
||||||
|
set b2=%%b
|
||||||
|
set b3=%%c
|
||||||
|
)
|
||||||
|
if not defined a1 set a1=0
|
||||||
|
if not defined a2 set a2=0
|
||||||
|
if not defined a3 set a3=0
|
||||||
|
if not defined b1 set b1=0
|
||||||
|
if not defined b2 set b2=0
|
||||||
|
if not defined b3 set b3=0
|
||||||
|
if %a1% gtr %b1% exit /b 1
|
||||||
|
if %a1% lss %b1% exit /b 2
|
||||||
|
if %a2% gtr %b2% exit /b 1
|
||||||
|
if %a2% lss %b2% exit /b 2
|
||||||
|
if %a3% gtr %b3% exit /b 1
|
||||||
|
if %a3% lss %b3% exit /b 2
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:askinstall
|
||||||
|
cls
|
||||||
|
echo ### ###
|
||||||
|
echo # Python Not Found #
|
||||||
|
echo ### ###
|
||||||
|
echo.
|
||||||
|
echo Python !targetpy! was not found on the system or in the PATH var.
|
||||||
|
echo.
|
||||||
|
set /p "menu=Would you like to install it now? [y/n]: "
|
||||||
|
if /i "!menu!"=="y" (
|
||||||
|
REM We got the OK - install it
|
||||||
|
goto installpy
|
||||||
|
) else if "!menu!"=="n" (
|
||||||
|
REM No OK here...
|
||||||
|
set /a tried=!tried!+1
|
||||||
|
goto checkpy
|
||||||
|
)
|
||||||
|
REM Incorrect answer - go back
|
||||||
|
goto askinstall
|
||||||
|
|
||||||
|
:installpy
|
||||||
|
REM This will attempt to download and install python
|
||||||
|
REM First we get the html for the python downloads page for Windows
|
||||||
|
set /a tried=!tried!+1
|
||||||
|
cls
|
||||||
|
echo ### ###
|
||||||
|
echo # Installing Python #
|
||||||
|
echo ### ###
|
||||||
|
echo.
|
||||||
|
echo Gathering info from https://www.python.org/downloads/windows/...
|
||||||
|
powershell -command "[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;(new-object System.Net.WebClient).DownloadFile('https://www.python.org/downloads/windows/','%TEMP%\pyurl.txt')"
|
||||||
|
REM Extract it if it's gzip compressed
|
||||||
|
powershell -command "$infile='%TEMP%\pyurl.txt';$outfile='%TEMP%\pyurl.temp';try{$input=New-Object System.IO.FileStream $infile,([IO.FileMode]::Open),([IO.FileAccess]::Read),([IO.FileShare]::Read);$output=New-Object System.IO.FileStream $outfile,([IO.FileMode]::Create),([IO.FileAccess]::Write),([IO.FileShare]::None);$gzipStream=New-Object System.IO.Compression.GzipStream $input,([IO.Compression.CompressionMode]::Decompress);$buffer=New-Object byte[](1024);while($true){$read=$gzipstream.Read($buffer,0,1024);if($read -le 0){break};$output.Write($buffer,0,$read)};$gzipStream.Close();$output.Close();$input.Close();Move-Item -Path $outfile -Destination $infile -Force}catch{}"
|
||||||
|
if not exist "%TEMP%\pyurl.txt" (
|
||||||
|
if /i "!just_installing!" == "TRUE" (
|
||||||
|
echo Failed to get info
|
||||||
|
exit /b 1
|
||||||
|
) else (
|
||||||
|
goto checkpy
|
||||||
|
)
|
||||||
|
)
|
||||||
|
echo Parsing for latest...
|
||||||
|
pushd "%TEMP%"
|
||||||
|
:: Version detection code slimmed by LussacZheng (https://github.com/corpnewt/gibMacOS/issues/20)
|
||||||
|
for /f "tokens=9 delims=< " %%x in ('findstr /i /c:"Latest Python !targetpy! Release" pyurl.txt') do ( set "release=%%x" )
|
||||||
|
popd
|
||||||
|
if "!release!" == "" (
|
||||||
|
if /i "!just_installing!" == "TRUE" (
|
||||||
|
echo Failed to get python version
|
||||||
|
exit /b 1
|
||||||
|
) else (
|
||||||
|
goto checkpy
|
||||||
|
)
|
||||||
|
)
|
||||||
|
echo Found Python !release! - Downloading...
|
||||||
|
REM Let's delete our txt file now - we no longer need it
|
||||||
|
del "%TEMP%\pyurl.txt"
|
||||||
|
REM At this point - we should have the version number.
|
||||||
|
REM We can build the url like so: "https://www.python.org/ftp/python/[version]/python-[version]-amd64.exe"
|
||||||
|
set "url=https://www.python.org/ftp/python/!release!/python-!release!-amd64.exe"
|
||||||
|
set "pytype=exe"
|
||||||
|
if "!targetpy!" == "2" (
|
||||||
|
set "url=https://www.python.org/ftp/python/!release!/python-!release!.amd64.msi"
|
||||||
|
set "pytype=msi"
|
||||||
|
)
|
||||||
|
REM Now we download it with our slick powershell command
|
||||||
|
powershell -command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (new-object System.Net.WebClient).DownloadFile('!url!','%TEMP%\pyinstall.!pytype!')"
|
||||||
|
REM If it doesn't exist - we bail
|
||||||
|
if not exist "%TEMP%\pyinstall.!pytype!" (
|
||||||
|
if /i "!just_installing!" == "TRUE" (
|
||||||
|
echo Failed to download installer
|
||||||
|
exit /b 1
|
||||||
|
) else (
|
||||||
|
goto checkpy
|
||||||
|
)
|
||||||
|
)
|
||||||
|
REM It should exist at this point - let's run it to install silently
|
||||||
|
echo Installing...
|
||||||
|
pushd "%TEMP%"
|
||||||
|
if /i "!pytype!" == "exe" (
|
||||||
|
echo pyinstall.exe /quiet PrependPath=1 Include_test=0 Shortcuts=0 Include_launcher=0
|
||||||
|
pyinstall.exe /quiet PrependPath=1 Include_test=0 Shortcuts=0 Include_launcher=0
|
||||||
|
) else (
|
||||||
|
set "foldername=!release:.=!"
|
||||||
|
echo msiexec /i pyinstall.msi /qb ADDLOCAL=ALL TARGETDIR="%LocalAppData%\Programs\Python\Python!foldername:~0,2!"
|
||||||
|
msiexec /i pyinstall.msi /qb ADDLOCAL=ALL TARGETDIR="%LocalAppData%\Programs\Python\Python!foldername:~0,2!"
|
||||||
|
)
|
||||||
|
popd
|
||||||
|
echo Installer finished with %ERRORLEVEL% status.
|
||||||
|
REM Now we should be able to delete the installer and check for py again
|
||||||
|
del "%TEMP%\pyinstall.!pytype!"
|
||||||
|
REM If it worked, then we should have python in our PATH
|
||||||
|
REM this does not get updated right away though - let's try
|
||||||
|
REM manually updating the local PATH var
|
||||||
|
call :updatepath
|
||||||
|
if /i "!just_installing!" == "TRUE" (
|
||||||
|
echo.
|
||||||
|
echo Done.
|
||||||
|
) else (
|
||||||
|
goto checkpy
|
||||||
|
)
|
||||||
|
exit /b
|
||||||
|
|
||||||
|
:runscript
|
||||||
|
REM Python found
|
||||||
|
cls
|
||||||
|
set "args=%*"
|
||||||
|
set "args=!args:"=!"
|
||||||
|
"!pypath!" -m pip install -r "!thisDir!\requirements.txt"
|
||||||
|
if "!args!"=="" (
|
||||||
|
"!pypath!" "!thisDir!!script_name!"
|
||||||
|
) else (
|
||||||
|
"!pypath!" "!thisDir!!script_name!" %*
|
||||||
|
)
|
||||||
|
if /i "!pause_on_error!" == "yes" (
|
||||||
|
if not "%ERRORLEVEL%" == "0" (
|
||||||
|
echo Script exited with error code: %ERRORLEVEL%
|
||||||
|
echo.
|
||||||
|
)
|
||||||
|
echo Press Enter to exit...
|
||||||
|
pause > nul
|
||||||
|
)
|
||||||
|
goto :EOF
|
||||||
|
|
||||||
|
:undouble <string_name> <string_value> <character>
|
||||||
|
REM Helper function to strip doubles of a single character out of a string recursively
|
||||||
|
set "string_value=%~2"
|
||||||
|
:undouble_continue
|
||||||
|
set "check=!string_value:%~3%~3=%~3!"
|
||||||
|
if not "!check!" == "!string_value!" (
|
||||||
|
set "string_value=!check!"
|
||||||
|
goto :undouble_continue
|
||||||
|
)
|
||||||
|
set "%~1=!check!"
|
||||||
|
goto :EOF
|
||||||
|
|
||||||
|
:updatepath
|
||||||
|
set "spath="
|
||||||
|
set "upath="
|
||||||
|
for /f "USEBACKQ tokens=2* delims= " %%i in (`!syspath!reg.exe query "HKCU\Environment" /v "Path" 2^> nul`) do ( if not "%%j" == "" set "upath=%%j" )
|
||||||
|
for /f "USEBACKQ tokens=2* delims= " %%i in (`!syspath!reg.exe query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v "Path" 2^> nul`) do ( if not "%%j" == "" set "spath=%%j" )
|
||||||
|
if not "%spath%" == "" (
|
||||||
|
REM We got something in the system path
|
||||||
|
set "PATH=%spath%"
|
||||||
|
if not "%upath%" == "" (
|
||||||
|
REM We also have something in the user path
|
||||||
|
set "PATH=%PATH%;%upath%"
|
||||||
|
)
|
||||||
|
) else if not "%upath%" == "" (
|
||||||
|
set "PATH=%upath%"
|
||||||
|
)
|
||||||
|
REM Remove double semicolons from the adjusted PATH
|
||||||
|
call :undouble "PATH" "%PATH%" ";"
|
||||||
|
goto :EOF
|
||||||
|
|
||||||
|
:getsyspath <variable_name>
|
||||||
|
REM Helper method to return a valid path to cmd.exe, reg.exe, and where.exe by
|
||||||
|
REM walking the ComSpec var - will also repair it in memory if need be
|
||||||
|
REM Strip double semi-colons
|
||||||
|
call :undouble "temppath" "%ComSpec%" ";"
|
||||||
|
|
||||||
|
REM Dirty hack to leverage the "line feed" approach - there are some odd side
|
||||||
|
REM effects with this. Do not use this variable name in comments near this
|
||||||
|
REM line - as it seems to behave erradically.
|
||||||
|
(set LF=^
|
||||||
|
%=this line is empty=%
|
||||||
|
)
|
||||||
|
REM Replace instances of semi-colons with a line feed and wrap
|
||||||
|
REM in parenthesis to work around some strange batch behavior
|
||||||
|
set "testpath=%temppath:;=!LF!%"
|
||||||
|
|
||||||
|
REM Let's walk each path and test if cmd.exe, reg.exe, and where.exe exist there
|
||||||
|
set /a found=0
|
||||||
|
for /f "tokens=* delims=" %%i in ("!testpath!") do (
|
||||||
|
REM Only continue if we haven't found it yet
|
||||||
|
if not "%%i" == "" (
|
||||||
|
if !found! lss 1 (
|
||||||
|
set "checkpath=%%i"
|
||||||
|
REM Remove "cmd.exe" from the end if it exists
|
||||||
|
if /i "!checkpath:~-7!" == "cmd.exe" (
|
||||||
|
set "checkpath=!checkpath:~0,-7!"
|
||||||
|
)
|
||||||
|
REM Pad the end with a backslash if needed
|
||||||
|
if not "!checkpath:~-1!" == "\" (
|
||||||
|
set "checkpath=!checkpath!\"
|
||||||
|
)
|
||||||
|
REM Let's see if cmd, reg, and where exist there - and set it if so
|
||||||
|
if EXIST "!checkpath!cmd.exe" (
|
||||||
|
if EXIST "!checkpath!reg.exe" (
|
||||||
|
if EXIST "!checkpath!where.exe" (
|
||||||
|
set /a found=1
|
||||||
|
set "ComSpec=!checkpath!cmd.exe"
|
||||||
|
set "%~1=!checkpath!"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
goto :EOF
|
||||||
302
OpCore-Simplify.command
Executable file
302
OpCore-Simplify.command
Executable file
@@ -0,0 +1,302 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Get the curent directory, the script name
|
||||||
|
# and the script name with "py" substituted for the extension.
|
||||||
|
args=( "$@" )
|
||||||
|
dir="${0%/*}"
|
||||||
|
script="${0##*/}"
|
||||||
|
target="${script%.*}.py"
|
||||||
|
|
||||||
|
# use_py3:
|
||||||
|
# TRUE = Use if found, use py2 otherwise
|
||||||
|
# FALSE = Use py2
|
||||||
|
# FORCE = Use py3
|
||||||
|
use_py3="TRUE"
|
||||||
|
|
||||||
|
tempdir=""
|
||||||
|
|
||||||
|
compare_to_version () {
|
||||||
|
# Compares our OS version to the passed OS version, and
|
||||||
|
# return a 1 if we match the passed compare type, or a 0 if we don't.
|
||||||
|
# $1 = 0 (equal), 1 (greater), 2 (less), 3 (gequal), 4 (lequal)
|
||||||
|
# $2 = OS version to compare ours to
|
||||||
|
if [ -z "$1" ] || [ -z "$2" ]; then
|
||||||
|
# Missing info - bail.
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
local current_os= comp=
|
||||||
|
current_os="$(sw_vers -productVersion)"
|
||||||
|
comp="$(vercomp "$current_os" "$2")"
|
||||||
|
# Check gequal and lequal first
|
||||||
|
if [[ "$1" == "3" && ("$comp" == "1" || "$comp" == "0") ]] || [[ "$1" == "4" && ("$comp" == "2" || "$comp" == "0") ]] || [[ "$comp" == "$1" ]]; then
|
||||||
|
# Matched
|
||||||
|
echo "1"
|
||||||
|
else
|
||||||
|
# No match
|
||||||
|
echo "0"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
set_use_py3_if () {
|
||||||
|
# Auto sets the "use_py3" variable based on
|
||||||
|
# conditions passed
|
||||||
|
# $1 = 0 (equal), 1 (greater), 2 (less), 3 (gequal), 4 (lequal)
|
||||||
|
# $2 = OS version to compare
|
||||||
|
# $3 = TRUE/FALSE/FORCE in case of match
|
||||||
|
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
|
||||||
|
# Missing vars - bail with no changes.
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [ "$(compare_to_version "$1" "$2")" == "1" ]; then
|
||||||
|
use_py3="$3"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_remote_py_version () {
|
||||||
|
local pyurl= py_html= py_vers= py_num="3"
|
||||||
|
pyurl="https://www.python.org/downloads/macos/"
|
||||||
|
py_html="$(curl -L $pyurl 2>&1)"
|
||||||
|
if [ -z "$use_py3" ]; then
|
||||||
|
use_py3="TRUE"
|
||||||
|
fi
|
||||||
|
if [ "$use_py3" == "FALSE" ]; then
|
||||||
|
py_num="2"
|
||||||
|
fi
|
||||||
|
py_vers="$(echo "$py_html" | grep -i "Latest Python $py_num Release" | awk '{print $8}' | cut -d'<' -f1)"
|
||||||
|
echo "$py_vers"
|
||||||
|
}
|
||||||
|
|
||||||
|
download_py () {
|
||||||
|
local vers="$1" url=
|
||||||
|
clear
|
||||||
|
echo " ### ###"
|
||||||
|
echo " # Downloading Python #"
|
||||||
|
echo "### ###"
|
||||||
|
echo
|
||||||
|
if [ -z "$vers" ]; then
|
||||||
|
echo "Gathering latest version..."
|
||||||
|
vers="$(get_remote_py_version)"
|
||||||
|
fi
|
||||||
|
if [ -z "$vers" ]; then
|
||||||
|
# Didn't get it still - bail
|
||||||
|
print_error
|
||||||
|
fi
|
||||||
|
echo "Located Version: $vers"
|
||||||
|
echo
|
||||||
|
echo "Building download url..."
|
||||||
|
url="$(curl -L https://www.python.org/downloads/release/python-${vers//./}/ 2>&1 | grep -iE "python-$vers-macos.*.pkg\"" | awk -F'"' '{ print $2 }')"
|
||||||
|
if [ -z "$url" ]; then
|
||||||
|
# Couldn't get the URL - bail
|
||||||
|
print_error
|
||||||
|
fi
|
||||||
|
echo " - $url"
|
||||||
|
echo
|
||||||
|
echo "Downloading..."
|
||||||
|
echo
|
||||||
|
# Create a temp dir and download to it
|
||||||
|
tempdir="$(mktemp -d 2>/dev/null || mktemp -d -t 'tempdir')"
|
||||||
|
curl "$url" -o "$tempdir/python.pkg"
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
echo
|
||||||
|
echo " - Failed to download python installer!"
|
||||||
|
echo
|
||||||
|
exit $?
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
echo "Running python install package..."
|
||||||
|
sudo installer -pkg "$tempdir/python.pkg" -target /
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
echo
|
||||||
|
echo " - Failed to install python!"
|
||||||
|
echo
|
||||||
|
exit $?
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
vers_folder="Python $(echo "$vers" | cut -d'.' -f1 -f2)"
|
||||||
|
if [ -f "/Applications/$vers_folder/Install Certificates.command" ]; then
|
||||||
|
# Certs script exists - let's execute that to make sure our certificates are updated
|
||||||
|
echo "Updating Certificates..."
|
||||||
|
echo
|
||||||
|
"/Applications/$vers_folder/Install Certificates.command"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
echo "Cleaning up..."
|
||||||
|
cleanup
|
||||||
|
echo
|
||||||
|
# Now we check for py again
|
||||||
|
echo "Rechecking py..."
|
||||||
|
downloaded="TRUE"
|
||||||
|
clear
|
||||||
|
main
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup () {
|
||||||
|
if [ -d "$tempdir" ]; then
|
||||||
|
rm -Rf "$tempdir"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
print_error() {
|
||||||
|
clear
|
||||||
|
cleanup
|
||||||
|
echo " ### ###"
|
||||||
|
echo " # Python Not Found #"
|
||||||
|
echo "### ###"
|
||||||
|
echo
|
||||||
|
echo "Python is not installed or not found in your PATH var."
|
||||||
|
echo
|
||||||
|
echo "Please go to https://www.python.org/downloads/macos/"
|
||||||
|
echo "to download and install the latest version."
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
print_target_missing() {
|
||||||
|
clear
|
||||||
|
cleanup
|
||||||
|
echo " ### ###"
|
||||||
|
echo " # Target Not Found #"
|
||||||
|
echo "### ###"
|
||||||
|
echo
|
||||||
|
echo "Could not locate $target!"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
format_version () {
|
||||||
|
local vers="$1"
|
||||||
|
echo "$(echo "$1" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }')"
|
||||||
|
}
|
||||||
|
|
||||||
|
vercomp () {
|
||||||
|
# Modified from: https://apple.stackexchange.com/a/123408/11374
|
||||||
|
local ver1="$(format_version "$1")" ver2="$(format_version "$2")"
|
||||||
|
if [ $ver1 -gt $ver2 ]; then
|
||||||
|
echo "1"
|
||||||
|
elif [ $ver1 -lt $ver2 ]; then
|
||||||
|
echo "2"
|
||||||
|
else
|
||||||
|
echo "0"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_local_python_version() {
|
||||||
|
# $1 = Python bin name (defaults to python3)
|
||||||
|
# Echoes the path to the highest version of the passed python bin if any
|
||||||
|
local py_name="$1" max_version= python= python_version= python_path=
|
||||||
|
if [ -z "$py_name" ]; then
|
||||||
|
py_name="python3"
|
||||||
|
fi
|
||||||
|
py_list="$(which -a "$py_name" 2>/dev/null)"
|
||||||
|
# Walk that newline separated list
|
||||||
|
while read python; do
|
||||||
|
if [ -z "$python" ]; then
|
||||||
|
# Got a blank line - skip
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$check_py3_stub" == "1" ] && [ "$python" == "/usr/bin/python3" ]; then
|
||||||
|
# See if we have a valid developer path
|
||||||
|
xcode-select -p > /dev/null 2>&1
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
# /usr/bin/python3 path - but no valid developer dir
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
python_version="$(get_python_version $python)"
|
||||||
|
if [ -z "$python_version" ]; then
|
||||||
|
# Didn't find a py version - skip
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# Got the py version - compare to our max
|
||||||
|
if [ -z "$max_version" ] || [ "$(vercomp "$python_version" "$max_version")" == "1" ]; then
|
||||||
|
# Max not set, or less than the current - update it
|
||||||
|
max_version="$python_version"
|
||||||
|
python_path="$python"
|
||||||
|
fi
|
||||||
|
done <<< "$py_list"
|
||||||
|
echo "$python_path"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_python_version() {
|
||||||
|
local py_path="$1" py_version=
|
||||||
|
# Get the python version by piping stderr into stdout (for py2), then grepping the output for
|
||||||
|
# the word "python", getting the second element, and grepping for an alphanumeric version number
|
||||||
|
py_version="$($py_path -V 2>&1 | grep -i python | cut -d' ' -f2 | grep -E "[A-Za-z\d\.]+")"
|
||||||
|
if [ ! -z "$py_version" ]; then
|
||||||
|
echo "$py_version"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_and_download() {
|
||||||
|
if [ "$downloaded" != "FALSE" ]; then
|
||||||
|
# We already tried to download - just bail
|
||||||
|
print_error
|
||||||
|
fi
|
||||||
|
clear
|
||||||
|
echo " ### ###"
|
||||||
|
echo " # Python Not Found #"
|
||||||
|
echo "### ###"
|
||||||
|
echo
|
||||||
|
target_py="Python 3"
|
||||||
|
printed_py="Python 2 or 3"
|
||||||
|
if [ "$use_py3" == "FORCE" ]; then
|
||||||
|
printed_py="Python 3"
|
||||||
|
elif [ "$use_py3" == "FALSE" ]; then
|
||||||
|
target_py="Python 2"
|
||||||
|
printed_py="Python 2"
|
||||||
|
fi
|
||||||
|
echo "Could not locate $printed_py!"
|
||||||
|
echo
|
||||||
|
echo "This script requires $printed_py to run."
|
||||||
|
echo
|
||||||
|
while true; do
|
||||||
|
read -p "Would you like to install the latest $target_py now? (y/n): " yn
|
||||||
|
case $yn in
|
||||||
|
[Yy]* ) download_py;break;;
|
||||||
|
[Nn]* ) print_error;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local python= version=
|
||||||
|
# Verify our target exists
|
||||||
|
if [ ! -f "$dir/$target" ]; then
|
||||||
|
# Doesn't exist
|
||||||
|
print_target_missing
|
||||||
|
fi
|
||||||
|
if [ -z "$use_py3" ]; then
|
||||||
|
use_py3="TRUE"
|
||||||
|
fi
|
||||||
|
if [ "$use_py3" != "FALSE" ]; then
|
||||||
|
# Check for py3 first
|
||||||
|
python="$(get_local_python_version python3)"
|
||||||
|
fi
|
||||||
|
if [ "$use_py3" != "FORCE" ] && [ -z "$python" ]; then
|
||||||
|
# We aren't using py3 explicitly, and we don't already have a path
|
||||||
|
python="$(get_local_python_version python2)"
|
||||||
|
if [ -z "$python" ]; then
|
||||||
|
# Try just looking for "python"
|
||||||
|
python="$(get_local_python_version python)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ -z "$python" ]; then
|
||||||
|
# Didn't ever find it - prompt
|
||||||
|
prompt_and_download
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
# Found it - start our script and pass all args
|
||||||
|
"$python" -m pip install -r "$dir/requirements.txt"
|
||||||
|
"$python" "$dir/$target" "${args[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check to see if we need to force based on
|
||||||
|
# macOS version. 10.15 has a dummy python3 version
|
||||||
|
# that can trip up some py3 detection in other scripts.
|
||||||
|
# set_use_py3_if "3" "10.15" "FORCE"
|
||||||
|
downloaded="FALSE"
|
||||||
|
# Check for the aforementioned /usr/bin/python3 stub if
|
||||||
|
# our OS version is 10.15 or greater.
|
||||||
|
check_py3_stub="$(compare_to_version "3" "10.15")"
|
||||||
|
trap cleanup EXIT
|
||||||
|
main
|
||||||
232
OpCore-Simplify.py
Executable file
232
OpCore-Simplify.py
Executable file
@@ -0,0 +1,232 @@
|
|||||||
|
from Scripts import aida64
|
||||||
|
from Scripts import compatibility_checker
|
||||||
|
from Scripts import efi_builder
|
||||||
|
from Scripts import gathering_files
|
||||||
|
from Scripts import utils
|
||||||
|
import os
|
||||||
|
|
||||||
|
class OCPE:
|
||||||
|
def __init__(self):
|
||||||
|
self.u = utils.Utils("OpCore Simplify")
|
||||||
|
self.o = gathering_files.gatheringFiles()
|
||||||
|
self.a = aida64.AIDA64()
|
||||||
|
self.c = compatibility_checker.CompatibilityChecker()
|
||||||
|
self.b = efi_builder.builder()
|
||||||
|
self.u = utils.Utils()
|
||||||
|
self.current_version = "0.0.1"
|
||||||
|
self.hardware = None
|
||||||
|
self.compatibility = None
|
||||||
|
self.macos_version = None
|
||||||
|
self.macos_version_data = {
|
||||||
|
"24": "macOS Sequoia 15 (Beta)",
|
||||||
|
"23": "macOS Sonoma 14 (14.4+)",
|
||||||
|
"22": "macOS Ventura 13",
|
||||||
|
"21": "macOS Monterey 12",
|
||||||
|
"20": "macOS Big Sur 11",
|
||||||
|
"19": "macOS Catalina 10.15",
|
||||||
|
"18": "macOS Mojave 10.14",
|
||||||
|
"17": "macOS High Sierra 10.13"
|
||||||
|
}
|
||||||
|
self.result_dir = os.path.join(os.getcwd(), "Results")
|
||||||
|
|
||||||
|
def check_for_update(self):
|
||||||
|
self.u.head("Check for update")
|
||||||
|
print("")
|
||||||
|
print(f"Current script version: {self.current_version}")
|
||||||
|
latest_version = self.u.check_latest_version()
|
||||||
|
print(f"Latest script version: {latest_version}")
|
||||||
|
print("")
|
||||||
|
if latest_version and latest_version > self.current_version:
|
||||||
|
print(self.u.message("An update is available at \"https://github.com/lzhoang2801/OpCore-Simplify\"", "reminder"))
|
||||||
|
print(self.u.message("Please download the latest version to ensure the best experience.", "reminder"))
|
||||||
|
print("")
|
||||||
|
self.u.request_input()
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
self.u.exit_program()
|
||||||
|
|
||||||
|
def gathering_files(self):
|
||||||
|
self.u.head("Gathering Files")
|
||||||
|
print("")
|
||||||
|
print("Please wait for download OpenCore NO ACPI, kexts and macserial...")
|
||||||
|
print("")
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.o.gathering_bootloader_kexts()
|
||||||
|
except Exception as e:
|
||||||
|
print("")
|
||||||
|
print(self.u.message(e, "warning"))
|
||||||
|
print("")
|
||||||
|
self.u.request_input()
|
||||||
|
if len(os.listdir(self.o.ock_files_dir)) < 54:
|
||||||
|
os.remove(self.o.download_history_file)
|
||||||
|
raise Exception("The download process was not completed. Please try again once the REST API request quota is reset in about an hour")
|
||||||
|
return
|
||||||
|
|
||||||
|
def select_aida64_report(self):
|
||||||
|
while True:
|
||||||
|
self.u.head("Select your AIDA64 report")
|
||||||
|
print("")
|
||||||
|
print("To ensure the best results, please follow these instructions before generating the AIDA64 report:")
|
||||||
|
print("")
|
||||||
|
print(" 1. Install all available drivers if possible (skip this step when using Windows PE)")
|
||||||
|
print(" 2. Use the latest version of AIDA64 Extreme, available at \"https://aida64.com/downloads\"")
|
||||||
|
print(" 3. In the Report Wizard, ensure \"Hardware-related pages\" is selected on the Report Profiles\n and choose the \"HTML\" format")
|
||||||
|
print("")
|
||||||
|
print("Q. Quit")
|
||||||
|
print("")
|
||||||
|
user_input = self.u.request_input("Please drag and drop your AIDA64 report here: (*HTML/.htm) ")
|
||||||
|
if user_input.lower() == "q":
|
||||||
|
self.u.exit_program()
|
||||||
|
path = self.u.normalize_path(user_input)
|
||||||
|
if not path:
|
||||||
|
continue
|
||||||
|
self.hardware = self.a.dump(path)
|
||||||
|
return
|
||||||
|
|
||||||
|
def hardware_report(self):
|
||||||
|
if not self.hardware:
|
||||||
|
self.select_aida64_report()
|
||||||
|
|
||||||
|
self.u.head("Review the hardware information")
|
||||||
|
contents = ["\n"]
|
||||||
|
for index, device_type in enumerate(self.hardware, start=1):
|
||||||
|
contents.append("{}. {}{}".format(index, device_type, "" if device_type == "Intel MEI" else ":"))
|
||||||
|
|
||||||
|
if device_type == "SD Controller":
|
||||||
|
contents.append("{}* {}".format(" "*4, self.hardware.get(device_type).get("Device Description")))
|
||||||
|
elif device_type == "Intel MEI":
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
for device_name, device_props in self.hardware.get(device_type).items():
|
||||||
|
if "Controllers" in device_name or "Devices" in device_name or "Drives" in device_name:
|
||||||
|
contents.append("{}* {}:".format(" "*4, device_name))
|
||||||
|
for device_name_child, device_props_child in device_props.items():
|
||||||
|
contents.append("{}- {}".format(" "*8, device_name_child))
|
||||||
|
else:
|
||||||
|
contents.append("{}* {}{}".format(" "*4, device_name, f": {device_props}" if isinstance(device_props, str) else ""))
|
||||||
|
content = "\n".join(contents) + "\n"
|
||||||
|
print(content, end="")
|
||||||
|
self.u.adjust_window_size(content)
|
||||||
|
self.u.request_input()
|
||||||
|
return
|
||||||
|
|
||||||
|
def compatibility_check(self):
|
||||||
|
if not self.hardware:
|
||||||
|
self.select_aida64_report()
|
||||||
|
|
||||||
|
self.hardware = self.c.check_compatibility(self.hardware)
|
||||||
|
self.compatibility = self.hardware.get("Compatibility")
|
||||||
|
supported_macOS_version = self.compatibility.get("macOS Version")
|
||||||
|
min_verion = supported_macOS_version.get("Min Version")
|
||||||
|
max_verion = supported_macOS_version.get("Max Version")
|
||||||
|
|
||||||
|
self.u.head("Compatibility Checker")
|
||||||
|
print("")
|
||||||
|
if max_verion == -1:
|
||||||
|
self.u.request_input("Your hardware is not compatible with macOS!")
|
||||||
|
self.u.exit_program()
|
||||||
|
print("* Supported macOS Version:")
|
||||||
|
print("{}Max Version: {}".format(" "*4, self.macos_version_data[str(max_verion)]))
|
||||||
|
print("{}Min Version: {}".format(" "*4, self.macos_version_data[str(min_verion)]))
|
||||||
|
if self.compatibility.get("Unsupported Devices"):
|
||||||
|
print("* Unsupported devices:")
|
||||||
|
for index, device in enumerate(self.compatibility.get("Unsupported Devices"), start=1):
|
||||||
|
print("{}{}. {}".format(" "*4, index, device))
|
||||||
|
print("")
|
||||||
|
self.u.request_input()
|
||||||
|
return
|
||||||
|
|
||||||
|
def select_macos_version(self):
|
||||||
|
if not self.compatibility:
|
||||||
|
self.compatibility_check()
|
||||||
|
|
||||||
|
supported_macOS_version = self.compatibility.get("macOS Version")
|
||||||
|
min_verion = supported_macOS_version.get("Min Version")
|
||||||
|
max_verion = supported_macOS_version.get("Max Version")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
self.u.head("Select macOS Version")
|
||||||
|
print("")
|
||||||
|
for index, macos_version in enumerate(range(max_verion, min_verion - 1, -1), start=1):
|
||||||
|
print("{}. {}".format(index, self.macos_version_data[str(macos_version)]))
|
||||||
|
print("")
|
||||||
|
print("Q. Quit")
|
||||||
|
print("")
|
||||||
|
option = self.u.request_input("Please select the macOS version you wish to install: ")
|
||||||
|
if option.lower() == "q":
|
||||||
|
self.u.exit_program()
|
||||||
|
if "1" <= option <= str(max_verion - min_verion + 1):
|
||||||
|
self.macos_version = max_verion - int(option) + 1
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
|
def show_result(self):
|
||||||
|
def generate_tree_content(dir_path, prefix=''):
|
||||||
|
contents = sorted(os.listdir(dir_path))
|
||||||
|
pointers = ['├── '] * (len(contents) - 1) + ['└── ']
|
||||||
|
content = ""
|
||||||
|
|
||||||
|
if not contents:
|
||||||
|
content += prefix + '└── (empty)\n'
|
||||||
|
elif ".kext" in ", ".join(contents):
|
||||||
|
pointers = pointers[:-1] + ['├── '] + ['└── ']
|
||||||
|
contents.append("USBMap.kext ({})".format(self.u.message("use USBToolBox with the 'Use Native Class' option enabled to create this kext", "reminder")))
|
||||||
|
|
||||||
|
for pointer, path in zip(pointers, contents):
|
||||||
|
if path.startswith("."):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if path.endswith(".dsl"):
|
||||||
|
path += " ({})".format(self.u.message("adjust the ACPI path accordingly before compiling and using it", "reminder"))
|
||||||
|
elif path.startswith("itlwm"):
|
||||||
|
path += " ({})".format(self.u.message("use the HeliPort app to connect to WiFi", "reminder"))
|
||||||
|
full_path = os.path.join(dir_path, path)
|
||||||
|
content += f"{prefix + pointer + path}\n"
|
||||||
|
if os.path.isdir(full_path) and not ".kext" in os.path.splitext(path)[1]:
|
||||||
|
extension = '│ ' if pointer == '├── ' else ' '
|
||||||
|
if "Resources" in path:
|
||||||
|
content += prefix + extension + '└── ...hidden\n'
|
||||||
|
else:
|
||||||
|
content += generate_tree_content(full_path, prefix + extension)
|
||||||
|
|
||||||
|
return content
|
||||||
|
|
||||||
|
efi_dir = os.path.join(self.result_dir, "EFI")
|
||||||
|
content = "\nYour OpenCore EFI for {} has been built at:".format(self.hardware.get("Motherboard").get("Motherboard Name"))
|
||||||
|
content += f"\n\t{self.result_dir}\n"
|
||||||
|
content += "\nEFI\n{}\n".format(generate_tree_content(efi_dir))
|
||||||
|
self.u.adjust_window_size(content)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
self.u.head("Results", resize=False)
|
||||||
|
print(content)
|
||||||
|
option = self.u.request_input("Do you want to open the OpenCore EFI folder? (yes/no): ")
|
||||||
|
if option.lower() == "yes":
|
||||||
|
self.u.open_folder(self.result_dir)
|
||||||
|
break
|
||||||
|
elif option.lower() == "no":
|
||||||
|
break
|
||||||
|
return
|
||||||
|
|
||||||
|
def main(self):
|
||||||
|
self.check_for_update()
|
||||||
|
self.gathering_files()
|
||||||
|
self.select_aida64_report()
|
||||||
|
self.hardware_report()
|
||||||
|
self.compatibility_check()
|
||||||
|
self.select_macos_version()
|
||||||
|
self.b.build_efi(self.hardware, self.macos_version)
|
||||||
|
self.show_result()
|
||||||
|
reminder_message = "\n\nIMPORTANT REMINDER: Please make sure you add the USBMap.kext to /EFI/OC/Kext before using this\nOpenCore EFI.\n\n"
|
||||||
|
self.u.exit_program(o.u.message(reminder_message, "reminder"))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
o = OCPE()
|
||||||
|
try:
|
||||||
|
o.main()
|
||||||
|
except SystemExit:
|
||||||
|
raise
|
||||||
|
except BaseException as e:
|
||||||
|
o.u.exit_program(o.u.message("\nAn error occurred: {}\n".format(e)))
|
||||||
79
README.md
Normal file
79
README.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<br/>
|
||||||
|
<div align="center">
|
||||||
|
<h3 align="center">OpCore Simplify</h3>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
A tool designed to simplify the creation of <a href="https://github.com/acidanthera/OpenCorePkg">OpenCore</a> EFI. It includes features such as auto-patching DSDT, adding suitable kexts, and customizing the config.plist to make Hackintosh installation easy for beginners.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<a href="https://github.com/lzhoang2601/OpCore-Simplify/issues">Report Bug</a>
|
||||||
|
·
|
||||||
|
<a href="https://github.com/lzhoang2601/OpCore-Simplify/issues">Request Feature</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Table of Contents</summary>
|
||||||
|
<ol>
|
||||||
|
<li><a href="#features">Features</a></li>
|
||||||
|
<li><a href="#usage-guide">Usage Guide</a></li>
|
||||||
|
<li><a href="#contributing">Contributing</a></li>
|
||||||
|
<li><a href="#license">License</a></li>
|
||||||
|
<li><a href="#contact">Contact</a></li>
|
||||||
|
</ol>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
1. **Automatic Updates**: Check and update AMD Vanilla Patches, OpenCore NO ACPI, and kexts automatically.
|
||||||
|
2. **Hardware Information Gathering**: Use AIDA64 reports to collect detailed hardware information, utilizing USB ID and PCI ID for the most precise compatibility checks.
|
||||||
|
3. **Comprehensive Hardware Support**: Fully supports all available hardware (excluding legacy hardware). Try and view results on the Compatibility Checker screen.
|
||||||
|
4. **Enhanced ACPI Patching**: Add various ACPI patches with support from the [SSDTTime](https://github.com/corpnewt/SSDTTime).
|
||||||
|
5. **Device-Specific Kexts**: Identify and add the correct kexts for devices such as WiFi, ethernet, sound codec, bluetooth, keyboard, mouse, touchpad, USB controller, and SATA controller based on their IDs.
|
||||||
|
6. **Custom Tweaks**: Apply additional customizations based on a variety of sources and personal experience.
|
||||||
|
|
||||||
|
## Usage Guide
|
||||||
|
|
||||||
|
Follow the steps, customize as needed, and enjoy your optimized system!
|
||||||
|
|
||||||
|
1. Run `OpCore-Simplify.bat` on Windows or `OpCore-Simplify.command` on macOS.
|
||||||
|
|
||||||
|
2. **AIDA64 Report**: Enter the path or drag and drop your AIDA64 report.
|
||||||
|
- Ensure you follow any instructions on this screen.
|
||||||
|
|
||||||
|
3. **Review Hardware Information**: Verify the detected hardware information and receive compatibility results.
|
||||||
|
|
||||||
|
4. **Select macOS Version**: Choose the compatible macOS version you wish to install.
|
||||||
|
|
||||||
|
5. **Enter ACPI Tables Folder Path**:
|
||||||
|
- Select `P` to dump ACPI tables from the current machine if it is the same machine used for the AIDA64 report.
|
||||||
|
|
||||||
|
6. **Preview OpenCore EFI Results**:
|
||||||
|
- Review the generated OpenCore EFI for your hardware.
|
||||||
|
- Make sure to read any green-highlighted lines (in parentheses).
|
||||||
|
|
||||||
|
7. **USB Mapping**: Use USBToolBox with the 'Use Native Class' option enabled to map USBs and add the resulting kext to `OC/Kexts`.
|
||||||
|
|
||||||
|
8. **Create USB and Install macOS**: Follow the guide at [OpenCore Install Guide](https://dortania.github.io/OpenCore-Install-Guide/installer-guide/) and use the generated OpenCore EFI.
|
||||||
|
- For troubleshooting issues booting macOS, please refer to the [OpenCore Troubleshooting Guide](https://dortania.github.io/OpenCore-Install-Guide/troubleshooting/troubleshooting.html) or contact me for assistance.
|
||||||
|
|
||||||
|
#### Reference Resources
|
||||||
|
|
||||||
|
- [OpenCore Install Guide](https://dortania.github.io/OpenCore-Install-Guide) (some parts may be outdated)
|
||||||
|
- [ChefKissNext](https://chefkissnext.netlify.app/guides/hackintosh/) (dedicated to AMD CPU systems)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Any contributions you make are **greatly appreciated**.
|
||||||
|
|
||||||
|
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".
|
||||||
|
|
||||||
|
**Don't forget to give the project a star! Thanks again!**
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Distributed under the BSD 3-Clause License. See `LICENSE` for more information.
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
Hoang Hong Quan - [@facebook](https://facebook.com/macforce2601) - [@telegram](https://t.me/lzhoang2601) - lzhoang2601@gmail.com
|
||||||
2842
Scripts/acpi_guru.py
Executable file
2842
Scripts/acpi_guru.py
Executable file
File diff suppressed because it is too large
Load Diff
606
Scripts/aida64.py
Executable file
606
Scripts/aida64.py
Executable file
@@ -0,0 +1,606 @@
|
|||||||
|
from Scripts.datasets import pci_data
|
||||||
|
from Scripts import utils
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
class AIDA64:
|
||||||
|
def __init__(self):
|
||||||
|
self.aida64_download_url = "https://www.aida64.com/downloads"
|
||||||
|
self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
|
||||||
|
self.encodings = ['utf-8', 'latin-1', 'ISO-8859-1']
|
||||||
|
self.utils = utils.Utils()
|
||||||
|
|
||||||
|
def try_open(self, file_path):
|
||||||
|
for encoding in self.encodings:
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r', encoding=encoding) as file:
|
||||||
|
return file.read()
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
continue
|
||||||
|
raise UnicodeDecodeError(f"Unable to decode file {file_path} with given encodings")
|
||||||
|
|
||||||
|
def hardware_id(self, hardware_id):
|
||||||
|
if "VEN" in hardware_id:
|
||||||
|
return {
|
||||||
|
"Bus Type": hardware_id.split("\\")[0],
|
||||||
|
"Device ID": "{}-{}".format(hardware_id.split("VEN_")[-1].split("&")[0], hardware_id.split("DEV_")[-1].split("&")[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if "VID" in hardware_id:
|
||||||
|
return {
|
||||||
|
"Bus Type": hardware_id.split("\\")[0],
|
||||||
|
"Device ID": "{}-{}".format(hardware_id.split("VID_")[-1].split("&")[0], hardware_id.split("PID_")[-1].split("&")[0]),
|
||||||
|
"Revision": hardware_id.split("REV_")[-1].split("&")[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"Bus Type": hardware_id.split("\\")[0],
|
||||||
|
"Device": hardware_id.split("\\")[-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
def motherboard(self, motherboard_props, dmi):
|
||||||
|
motherboard_info = {}
|
||||||
|
|
||||||
|
# Extract motherboard name and chipset from provided properties
|
||||||
|
motherboard_info["Motherboard Name"] = motherboard_props.get("Motherboard Name", "Unknown").split("(")[0].strip()
|
||||||
|
motherboard_info["Motherboard Chipset"] = motherboard_props.get("Motherboard Chipset", "Unknown").split(", ")[0]
|
||||||
|
|
||||||
|
# If motherboard name is still unknown, attempt to derive it from DMI information
|
||||||
|
if "Unknown" in motherboard_info.get("Motherboard Name"):
|
||||||
|
motherboard_info["Motherboard Name"] = "Unknown"
|
||||||
|
merged_report = dmi.get("System", {}).copy()
|
||||||
|
merged_report.update(dmi.get("Motherboard", {}))
|
||||||
|
for device_key, device_value in merged_report.items():
|
||||||
|
motherboard_name = "{} {}".format(device_value.get("Manufacturer", "O.E.M."), device_value.get("Product", "O.E.M."))
|
||||||
|
if "O.E.M." not in motherboard_name and "System Product Name" not in motherboard_name and len(motherboard_name) > len(motherboard_info.get("Motherboard Name")):
|
||||||
|
motherboard_info["Motherboard Name"] = motherboard_name
|
||||||
|
|
||||||
|
# Extract platform type from chassis information
|
||||||
|
motherboard_info["Platform"] = dmi.get("Chassis", {}).get("Chassis Properties", {}).get("Chassis Type", "Unknown")
|
||||||
|
if any(word in motherboard_info["Platform"].lower() for word in ["convertible", "notebook", "laptop", "docking station"]):
|
||||||
|
motherboard_info["Platform"] = "Laptop"
|
||||||
|
elif any(word in motherboard_info["Platform"].lower() for word in ["desktop", "mini pc"]):
|
||||||
|
motherboard_info["Platform"] = "Desktop"
|
||||||
|
elif "NUC" in motherboard_info["Motherboard Name"]:
|
||||||
|
motherboard_info["Platform"] = "NUC"
|
||||||
|
|
||||||
|
# Count and format CPU configuration
|
||||||
|
motherboard_info["CPU Configuration"] = str(len(dmi.get("Processors", {}))).zfill(2)
|
||||||
|
|
||||||
|
return motherboard_info
|
||||||
|
|
||||||
|
def cpu(self, cpu_table):
|
||||||
|
cpu_info = {}
|
||||||
|
|
||||||
|
# Extract CPU Manufacturer
|
||||||
|
cpu_info["CPU Manufacturer"] = cpu_table.get("CPU Manufacturer", {}).get("Company Name", "Unknown")
|
||||||
|
|
||||||
|
# Extract Processor Name
|
||||||
|
cpu_props = cpu_table.get("CPU Properties", {})
|
||||||
|
cpu_info["Processor Name"] = cpu_props.get("CPU Type", "Unknown").split(",")[0]
|
||||||
|
|
||||||
|
# Determine CPU Manufacturer if still unknown
|
||||||
|
if "Intel" in cpu_info["CPU Manufacturer"]:
|
||||||
|
cpu_info["CPU Manufacturer"] = "Intel"
|
||||||
|
elif "Advanced Micro Devices" in cpu_info["CPU Manufacturer"]:
|
||||||
|
cpu_info["CPU Manufacturer"] = "AMD"
|
||||||
|
elif cpu_info["CPU Manufacturer"] == "Unknown":
|
||||||
|
processor_name = cpu_table.get("Multi CPU", {}).get("CPU #1", "Unknown").split("with")[0].split(",")[0]
|
||||||
|
if "Intel" in processor_name:
|
||||||
|
cpu_info["CPU Manufacturer"] = "Intel"
|
||||||
|
elif "AMD" in processor_name:
|
||||||
|
cpu_info["CPU Manufacturer"] = "AMD"
|
||||||
|
cpu_info["Processor Name"] += cpu_info["CPU Manufacturer"] + processor_name.split(cpu_info["CPU Manufacturer"])[-1]
|
||||||
|
|
||||||
|
# Extract CPU Codename
|
||||||
|
cpu_info["CPU Codename"] = cpu_props.get("CPU Alias", "Unknown")
|
||||||
|
|
||||||
|
# Extract CPU Cores count
|
||||||
|
core_indices = []
|
||||||
|
for key in list(cpu_table.get("CPU Utilization", {}).keys()):
|
||||||
|
core_index = key.split("#")[2].split(" ")[0]
|
||||||
|
if "CPU #1" in key and core_index not in core_indices:
|
||||||
|
core_indices.append(core_index)
|
||||||
|
cpu_info["CPU Cores"] = str(len(core_indices)).zfill(2)
|
||||||
|
|
||||||
|
# Extract Instruction Set
|
||||||
|
cpu_info["Instruction Set"] = cpu_props.get("Instruction Set", "Unknown")
|
||||||
|
|
||||||
|
return cpu_info
|
||||||
|
|
||||||
|
def memory(self, memory_arrays, memory_devices):
|
||||||
|
return {
|
||||||
|
"Memory Arrays": [
|
||||||
|
memory_array.get("Memory Array Properties", {})
|
||||||
|
for function, memory_array in memory_arrays.items()
|
||||||
|
],
|
||||||
|
"Memory Devices": [
|
||||||
|
memory_device.get("Memory Device Properties", {})
|
||||||
|
for device_locator, memory_device in memory_devices.items()
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
def storage(self, ata_controllers, storage_controllers, ata_devices):
|
||||||
|
storage_info = {
|
||||||
|
"Storage Controllers": {},
|
||||||
|
"Disk Drives": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
storage_controllers.update(ata_controllers)
|
||||||
|
for controller_name, controller_props in storage_controllers.items():
|
||||||
|
bus_type = controller_props.get("Bus Type", "Unknown")
|
||||||
|
if "PCI" in bus_type or "VID" in bus_type:
|
||||||
|
pci_device = controller_props.get("PCI Device")
|
||||||
|
if " SD " in pci_device or "MMC" in pci_device:
|
||||||
|
continue
|
||||||
|
|
||||||
|
storage_info["Storage Controllers"][controller_name] = {
|
||||||
|
"Bus Type": controller_props.get("Bus Type", "Unknown"),
|
||||||
|
"Device ID": controller_props.get("Device ID", "Unknown"),
|
||||||
|
"Device Description": controller_props.get("PCI Device", "Unknown")
|
||||||
|
}
|
||||||
|
|
||||||
|
device_categories = ["NVMe Device Properties", "SSD Physical Info", "ATA Device Properties", "Disk Device Physical Info", "Device Properties"]
|
||||||
|
|
||||||
|
for device_name, device_props in ata_devices.items():
|
||||||
|
disk_props = {}
|
||||||
|
relevant_categories = [key for key in list(device_props.keys()) if key in device_categories]
|
||||||
|
for category in relevant_categories:
|
||||||
|
category_props = device_props[category]
|
||||||
|
|
||||||
|
disk_props["Controller"] = category_props.get("Controller Type", "Unknown")
|
||||||
|
disk_props["Interface"] = category_props.get("Interface", "Unknown")
|
||||||
|
if category_props.get("Device Type", None):
|
||||||
|
disk_props["Interface"] = category_props.get("Device Type")
|
||||||
|
|
||||||
|
storage_info["Disk Drives"][device_name] = disk_props
|
||||||
|
|
||||||
|
return storage_info
|
||||||
|
|
||||||
|
def monitor(self, monitor):
|
||||||
|
return {
|
||||||
|
monitor_data["Monitor Properties"].get("Monitor Name", monitor_name): {
|
||||||
|
"Monitor Type": monitor_data["Monitor Properties"].get("Monitor Type", "Unknown"),
|
||||||
|
"Maximum Resolution": monitor_data["Monitor Properties"].get("Maximum Resolution", list(monitor_data.get("Supported Video Modes", {}).keys())[-1].split("_")[0] if "Supported Video Modes" in monitor_data else "Unknown")
|
||||||
|
}
|
||||||
|
for monitor_name, monitor_data in monitor.items()
|
||||||
|
if "Monitor Properties" in monitor_data
|
||||||
|
}
|
||||||
|
|
||||||
|
def acpi(self, acpi_tables):
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"ACPI Signature": acpi_table["ACPI Table Properties"].get("ACPI Signature", "Unknown"),
|
||||||
|
"Table Description": acpi_table["ACPI Table Properties"].get("Table Description", "Unknown"),
|
||||||
|
"Table Length": acpi_table["ACPI Table Properties"].get("Table Length", "Unknown"),
|
||||||
|
"OEM Table ID": acpi_table["ACPI Table Properties"].get("OEM Table ID", "Unknown")
|
||||||
|
}
|
||||||
|
for table_key, acpi_table in acpi_tables.items()
|
||||||
|
if "ACPI Table Properties" in acpi_table
|
||||||
|
]
|
||||||
|
|
||||||
|
def audio(self, windows_devices):
|
||||||
|
audio_devices_info = {}
|
||||||
|
audio_device_ids = []
|
||||||
|
|
||||||
|
for device_name, device_props in windows_devices.get("Audio inputs and outputs", {}).items():
|
||||||
|
driver_description = device_props.get("Driver Description", "Unknown")
|
||||||
|
|
||||||
|
if " (" not in driver_description:
|
||||||
|
continue
|
||||||
|
|
||||||
|
audio_endpoint = driver_description.split(" (")[0]
|
||||||
|
audio_controller_name = driver_description.split(" (")[-1].strip(" )").split("- ")[-1]
|
||||||
|
|
||||||
|
audio_controller_props = self.utils.search_dict_iter(windows_devices, audio_controller_name)
|
||||||
|
bus_type = audio_controller_props.get("Bus Type", "")
|
||||||
|
|
||||||
|
if audio_controller_name not in audio_devices_info and (bus_type.endswith("AUDIO") or bus_type.endswith("USB") or bus_type.endswith("ACP")):
|
||||||
|
audio_devices_info[audio_controller_name] = {
|
||||||
|
"Bus Type": bus_type,
|
||||||
|
"{} ID".format("USB" if bus_type.endswith("USB") else "Codec"): audio_controller_props.get("Device ID", "Unknown"),
|
||||||
|
"Audio Endpoints": [audio_endpoint]
|
||||||
|
}
|
||||||
|
audio_device_ids.append(audio_controller_props.get("Device ID", "Unknown"))
|
||||||
|
elif audio_controller_name in audio_devices_info:
|
||||||
|
audio_devices_info[audio_controller_name]["Audio Endpoints"].append(audio_endpoint)
|
||||||
|
|
||||||
|
detected_audio_devices = self.utils.search_dict_iter(windows_devices, "AUDIO", equal=False)
|
||||||
|
windows_audio_devices = self.utils.search_dict_iter(windows_devices, detected_audio_devices)
|
||||||
|
|
||||||
|
for device_name, device_props in windows_audio_devices.items():
|
||||||
|
bus_type = device_props.get("Bus Type", "")
|
||||||
|
if bus_type.endswith("AUDIO") or bus_type.endswith("USB"):
|
||||||
|
if device_props.get("Device ID", "Unknown") not in audio_device_ids:
|
||||||
|
occurrences = self.count_keys(audio_devices_info, device_name)
|
||||||
|
unique_device_name = f"{device_name}_#{occurrences}" if occurrences > 0 else device_name
|
||||||
|
audio_devices_info[unique_device_name] = {
|
||||||
|
"Bus Type": bus_type,
|
||||||
|
"{} ID".format("USB" if bus_type.endswith("USB") else "Codec"): device_props.get("Device ID", "Unknown")
|
||||||
|
}
|
||||||
|
|
||||||
|
return audio_devices_info
|
||||||
|
|
||||||
|
def gpu(self, gpu_data, vulkan_data, windows_devices):
|
||||||
|
gpu_info_dict = {}
|
||||||
|
|
||||||
|
for adapter_name, adapter_props in windows_devices.get("Display adapters", windows_devices.get("Display adaptors", {})).items():
|
||||||
|
device_id = adapter_props.get("Device ID")
|
||||||
|
if not device_id:
|
||||||
|
continue
|
||||||
|
manufacturer = "Intel" if device_id.startswith("8086") else "AMD" if device_id.startswith("1002") else "NVIDIA" if device_id.startswith("10DE") else "Unknown"
|
||||||
|
props_in_vulkan = self.utils.search_dict_iter(vulkan_data, device_id, equal=False)
|
||||||
|
gpu_props = self.utils.search_dict_iter(gpu_data, device_id, equal=False)
|
||||||
|
bus_type = gpu_props.get("Bus Type", "Unknown")
|
||||||
|
device_type = props_in_vulkan.get("Device Type", "Discrete GPU" if "PCI Express" in bus_type else "Integrated GPU" if "Integrated" in bus_type else "Unknown")
|
||||||
|
gpu_codename = gpu_props.get("GPU Code Name", props_in_vulkan.get("Device Code Name", "Unknown"))
|
||||||
|
|
||||||
|
gpu_info_dict[gpu_props.get("Video Adapter", adapter_name)] = {
|
||||||
|
"Manufacturer": manufacturer,
|
||||||
|
"GPU Codename": gpu_codename,
|
||||||
|
"Device ID": device_id,
|
||||||
|
"Device Type": device_type,
|
||||||
|
"Memory Size": gpu_props.get("Memory Size", "Unknown")
|
||||||
|
}
|
||||||
|
|
||||||
|
if not gpu_info_dict:
|
||||||
|
if gpu_data:
|
||||||
|
for gpu_name, gpu_props in gpu_data.items():
|
||||||
|
gpu_props = gpu_props.get("Graphics Processor Properties", {})
|
||||||
|
device_id = gpu_props.get("PCI Device", "Unknown").split(" / ")[0]
|
||||||
|
manufacturer = "Intel" if device_id.startswith("8086") else "AMD" if device_id.startswith("1002") else "NVIDIA" if device_id.startswith("10DE") else "Unknown"
|
||||||
|
bus_type = gpu_props.get("Bus Type", "Unknown")
|
||||||
|
device_type = "Discrete GPU" if "PCI Express" in bus_type else "Integrated GPU" if "Integrated" in bus_type else "Unknown"
|
||||||
|
gpu_codename = gpu_props.get("GPU Code Name", "Unknown")
|
||||||
|
|
||||||
|
gpu_info_dict[gpu_props.get("Video Adapter", gpu_name.split(": ")[-1])] = {
|
||||||
|
"Manufacturer": manufacturer,
|
||||||
|
"GPU Codename": gpu_codename,
|
||||||
|
"Device ID": device_id,
|
||||||
|
"Device Type": device_type,
|
||||||
|
"Memory Size": gpu_props.get("Memory Size", "Unknown")
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.utils.sort_dict_by_key(gpu_info_dict, "Device Type")
|
||||||
|
|
||||||
|
def input(self, human_interface_devices, keyboards, pointing_devices, usb_devices):
|
||||||
|
input_devices_info = {}
|
||||||
|
|
||||||
|
combined_devices = human_interface_devices.copy()
|
||||||
|
combined_devices.update(keyboards)
|
||||||
|
combined_devices.update(pointing_devices)
|
||||||
|
|
||||||
|
for device_name, device_props in combined_devices.items():
|
||||||
|
bus_type = device_props.get("Bus Type", "Unknown")
|
||||||
|
device_id = device_props.get("Device ID", "Unknown")
|
||||||
|
|
||||||
|
if "ACPI" in bus_type or "ROOT" in bus_type or "USB" in bus_type:
|
||||||
|
if "USB" in bus_type:
|
||||||
|
device_name = self.utils.search_dict_iter(usb_devices, device_props["Device ID"]).get("Device Description", device_name)
|
||||||
|
|
||||||
|
input_devices_info[device_name] = {
|
||||||
|
"Bus Type": bus_type,
|
||||||
|
"Device ID": device_id
|
||||||
|
}
|
||||||
|
|
||||||
|
return input_devices_info
|
||||||
|
|
||||||
|
def usb(self, usb_controllers, usb_devices, windows_devices):
|
||||||
|
usb_info = {
|
||||||
|
"USB Controllers": {
|
||||||
|
controller_name: {
|
||||||
|
"Bus Type": controller_props.get("Bus Type", "Unknown"),
|
||||||
|
"Device ID": controller_props.get("Device ID", "Unknown")
|
||||||
|
}
|
||||||
|
for controller_name, controller_props in usb_controllers.items()
|
||||||
|
if controller_props.get("Bus Type", "Unknown").startswith("PCI")
|
||||||
|
},
|
||||||
|
"USB Devices": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
for device_name, device_data in usb_devices.items():
|
||||||
|
device_props = device_data.get("Device Properties", {})
|
||||||
|
manufacturer = device_props.get("Manufacturer", None)
|
||||||
|
product = device_props.get("Product", None)
|
||||||
|
device_description = f"{manufacturer} {product}" if manufacturer and product else product if product else None
|
||||||
|
|
||||||
|
if not device_description:
|
||||||
|
device_id = device_props.get("Device ID", None)
|
||||||
|
revision = device_props.get("Revision", None)[:-1] if device_props.get("Revision") else None
|
||||||
|
hardware_id = f'USB\\VID_{device_id[:4]}&PID_{device_id[5:]}&REV_{revision}' if device_id and revision else None
|
||||||
|
|
||||||
|
if hardware_id:
|
||||||
|
device_description = self.utils.search_dict_iter(windows_devices, hardware_id + "&MI_00").get("Driver Description", None)
|
||||||
|
if not device_description:
|
||||||
|
device_description = self.utils.search_dict_iter(windows_devices, hardware_id).get("Driver Description", device_name)
|
||||||
|
|
||||||
|
occurrences = self.count_keys(usb_info["USB Devices"], device_description)
|
||||||
|
device_description = f"{device_description}_#{occurrences}" if occurrences > 0 else device_description
|
||||||
|
|
||||||
|
if "Hub" not in device_description and "Billboard" not in device_description and not "0000-0000" in device_props.get("Device ID"):
|
||||||
|
usb_info["USB Devices"][device_description] = {
|
||||||
|
"Device Description": device_description.split("_#")[0],
|
||||||
|
"Device Class": device_props.get("Device Class"),
|
||||||
|
"Device ID": device_props.get("Device ID"),
|
||||||
|
"Revision": device_props.get("Revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
return usb_info
|
||||||
|
|
||||||
|
def network(self, windows_devices, pci_devices):
|
||||||
|
network_info = {}
|
||||||
|
|
||||||
|
for device_name, device_props in pci_devices.items():
|
||||||
|
device_class = device_props.get("Device Properties", {}).get("Device Class", "Unknown")[6:-1]
|
||||||
|
|
||||||
|
if self.utils.contains_any(["Network", "Ethernet", "WiFi", "Wi-Fi", "Wireless"], device_class + device_name):
|
||||||
|
device_id = device_props.get("Device Properties").get("Device ID")
|
||||||
|
|
||||||
|
network_adapter = self.utils.search_dict_iter(windows_devices, device_id)
|
||||||
|
network_adapters = self.utils.search_dict_iter(windows_devices, network_adapter)
|
||||||
|
|
||||||
|
for adapter_name, adapter_props in network_adapters.items():
|
||||||
|
device_description = adapter_name + adapter_props.get("PCI Device", "Unknown")
|
||||||
|
connection_name = "WiFi" if "WiFi" in device_description or "Wi-Fi" in device_description or "Wireless" in device_description else \
|
||||||
|
"Ethernet" if "Network" in device_description or "Ethernet" in device_description else None
|
||||||
|
bus_type = adapter_props.get("Bus Type", "Unknown")
|
||||||
|
if (bus_type.startswith("PCI") or bus_type.startswith("USB")) and connection_name:
|
||||||
|
device_key = adapter_props.get("PCI Device") if not " - " in adapter_props.get("PCI Device", " - ") else adapter_name
|
||||||
|
network_info[device_key.split(" [")[0]] = {
|
||||||
|
"Connection Name": connection_name,
|
||||||
|
"Bus Type": bus_type,
|
||||||
|
"Device ID": adapter_props.get("Device ID", "Unknown")
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.utils.sort_dict_by_key(network_info, "Connection Name")
|
||||||
|
|
||||||
|
def sd_controller(self, pci_devices, usb_devices, hardware):
|
||||||
|
combined_devices = pci_devices.copy()
|
||||||
|
combined_devices.update(usb_devices)
|
||||||
|
|
||||||
|
for device_name, device_data in combined_devices.items():
|
||||||
|
device_props = device_data.get("Device Properties", device_data)
|
||||||
|
device_class = device_props.get("Device Class", "Unknown")
|
||||||
|
|
||||||
|
if self.utils.contains_any(["SD Host Controller", "Card Reader", "SDHC", "SDXC", "SDUC", " SD ", "MMC"], f"{device_name} {device_class}"):
|
||||||
|
hardware["SD Controller"] = {
|
||||||
|
"Device Description": device_name,
|
||||||
|
"Bus Type": "PCI" if device_props.get("Bus Type", "Unknown").startswith("PCI") else "USB",
|
||||||
|
"Device ID": device_props.get("Device ID", "Unknown")
|
||||||
|
}
|
||||||
|
|
||||||
|
return hardware
|
||||||
|
|
||||||
|
def intel_mei(self, cpu_codename, pci_devices, hardware):
|
||||||
|
if "Sandy Bridge" in cpu_codename or "Ivy Bridge" in cpu_codename:
|
||||||
|
intel_mei_data = self.utils.search_dict_iter(pci_devices, "HECI", equal=False)
|
||||||
|
|
||||||
|
if not intel_mei_data:
|
||||||
|
intel_mei_data = self.utils.search_dict_iter(pci_devices, "Management Engine Interface", equal=False)
|
||||||
|
|
||||||
|
if intel_mei_data:
|
||||||
|
intel_mei_props = intel_mei_data.get("Device Properties", {})
|
||||||
|
hardware["Intel MEI"] = {
|
||||||
|
"Bus Type": intel_mei_props.get("Bus Type", "Unknown"),
|
||||||
|
"Device ID": intel_mei_props.get("Device ID", "Unknown")
|
||||||
|
}
|
||||||
|
|
||||||
|
return hardware
|
||||||
|
|
||||||
|
def bluetooth(self, bluetooth, usb_devices, hardware):
|
||||||
|
bluetooth_info = {}
|
||||||
|
|
||||||
|
for device_name, device_props in bluetooth.items():
|
||||||
|
bus_type = device_props.get("Bus Type", "Unknown")
|
||||||
|
|
||||||
|
if bus_type.startswith("USB"):
|
||||||
|
bluetooth_info[device_name] = {
|
||||||
|
"Device ID": device_props.get("Device ID"),
|
||||||
|
"Revision": device_props.get("Revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
if not bluetooth_info:
|
||||||
|
for usb_device_name, usb_device_props in usb_devices.items():
|
||||||
|
device_class = usb_device_props.get("Device Class", {})
|
||||||
|
device_id = usb_device_props.get("Device ID", {})
|
||||||
|
|
||||||
|
if "bluetooth" in (usb_device_name + device_class).lower() or device_id in pci_data.BluetoothIDs:
|
||||||
|
bluetooth_info[usb_device_name] = usb_device_props
|
||||||
|
|
||||||
|
if bluetooth_info:
|
||||||
|
hardware["Bluetooth"] = bluetooth_info
|
||||||
|
|
||||||
|
return hardware
|
||||||
|
|
||||||
|
def biometric(self, biometric_devices, usb_devices, hardware):
|
||||||
|
biometric_info = {
|
||||||
|
device_name: {
|
||||||
|
"Bus Type": device_props.get("Bus Type", "Unknown"),
|
||||||
|
"Device ID": device_props.get("Device ID", "Unknown")
|
||||||
|
}
|
||||||
|
for device_name, device_props in biometric_devices.items()
|
||||||
|
}
|
||||||
|
|
||||||
|
if not biometric_info:
|
||||||
|
for device_name, device_data in usb_devices.items():
|
||||||
|
if "fingerprint" in device_name.lower():
|
||||||
|
device_props = device_data.get("Device Properties", {})
|
||||||
|
|
||||||
|
biometric_info[device_name] = {
|
||||||
|
"Bus Type": device_props.get("Bus Type", "Unknown"),
|
||||||
|
"Device ID": device_props.get("Device ID", "Unknown")
|
||||||
|
}
|
||||||
|
|
||||||
|
if biometric_info:
|
||||||
|
hardware["Biometric"] = biometric_info
|
||||||
|
|
||||||
|
return hardware
|
||||||
|
|
||||||
|
def parse_dmi(self, dmi_data):
|
||||||
|
parsed_dmi = {}
|
||||||
|
|
||||||
|
for full_key, item_value in dmi_data.items():
|
||||||
|
occurrence_suffix = ''
|
||||||
|
category_name = None
|
||||||
|
|
||||||
|
if '_#' in full_key:
|
||||||
|
suffix_idx = full_key.index('_#')
|
||||||
|
occurrence_suffix = full_key[suffix_idx:]
|
||||||
|
full_key = full_key[:suffix_idx]
|
||||||
|
|
||||||
|
if ' / ' in full_key:
|
||||||
|
category_idx = full_key.index(' / ')
|
||||||
|
category_name = full_key[:category_idx]
|
||||||
|
device_name = full_key[category_idx + 3:]
|
||||||
|
|
||||||
|
if not category_name:
|
||||||
|
parsed_dmi[f"{full_key}{occurrence_suffix}"] = item_value
|
||||||
|
else:
|
||||||
|
if category_name not in parsed_dmi:
|
||||||
|
parsed_dmi[category_name] = {}
|
||||||
|
parsed_dmi[category_name][f"{device_name}{occurrence_suffix}"] = item_value
|
||||||
|
|
||||||
|
return parsed_dmi
|
||||||
|
|
||||||
|
def parse_windows_devices(self, windows_devices):
|
||||||
|
parsed_windows_devices = {}
|
||||||
|
|
||||||
|
for full_key, item_value in windows_devices.items():
|
||||||
|
device_props = item_value.get("Device Properties", {})
|
||||||
|
|
||||||
|
# Update device properties with hardware ID if available
|
||||||
|
if "Hardware ID" in device_props:
|
||||||
|
device_props.update(self.hardware_id(device_props.get("Hardware ID")))
|
||||||
|
|
||||||
|
# Extract category name from the full key
|
||||||
|
category_name = full_key.split(" / ")[0]
|
||||||
|
|
||||||
|
# Initialize category dictionary if not already present
|
||||||
|
if category_name not in parsed_windows_devices:
|
||||||
|
parsed_windows_devices[category_name] = {}
|
||||||
|
|
||||||
|
# Extract device name from device properties
|
||||||
|
device_name = device_props.get("Driver Description")
|
||||||
|
|
||||||
|
# Count occurrences of device name within category
|
||||||
|
occurrences = self.count_keys(parsed_windows_devices[category_name], device_name)
|
||||||
|
device_name = f"{device_name}_#{occurrences}" if occurrences > 0 else device_name
|
||||||
|
|
||||||
|
# Add device to category dictionary
|
||||||
|
parsed_windows_devices[category_name][device_name] = device_props
|
||||||
|
|
||||||
|
return parsed_windows_devices
|
||||||
|
|
||||||
|
def count_keys(self, dictionary, target_key):
|
||||||
|
return sum(1 for key in dictionary if target_key in key)
|
||||||
|
|
||||||
|
def html_to_dict(self, html_content):
|
||||||
|
soup = BeautifulSoup(html_content, "html.parser")
|
||||||
|
tables = soup.find_all('table')
|
||||||
|
|
||||||
|
if not tables:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
root = {}
|
||||||
|
table_names = [
|
||||||
|
"Summary",
|
||||||
|
"DMI",
|
||||||
|
"CPU",
|
||||||
|
"GPU",
|
||||||
|
"Vulkan",
|
||||||
|
"ATA",
|
||||||
|
"Windows Devices",
|
||||||
|
"PCI Devices",
|
||||||
|
"USB Devices"
|
||||||
|
]
|
||||||
|
table = None
|
||||||
|
|
||||||
|
for table_content in tables:
|
||||||
|
# Find the table header to identify the table
|
||||||
|
pt_element = table_content.find("td", class_="pt")
|
||||||
|
if pt_element:
|
||||||
|
table = pt_element.text.strip()
|
||||||
|
elif table in table_names:
|
||||||
|
root[table] = {}
|
||||||
|
stack = [(root[table], -1)] # Stack holds (current_dict, current_level)
|
||||||
|
|
||||||
|
lines = str(table_content).strip().splitlines()
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
if line.startswith('<tr>'):
|
||||||
|
# Remove <tr> tag
|
||||||
|
line = line.replace('<tr>', '')
|
||||||
|
|
||||||
|
# Calculate the current level based on the number of <td> tags
|
||||||
|
level = (len(line) - len(line.lstrip('<td>'))) // 3 - 1
|
||||||
|
if level < 1:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Remove all <td> tags from the left
|
||||||
|
while line.startswith("<td>"):
|
||||||
|
line = line[line.find(">") + 1:]
|
||||||
|
|
||||||
|
if not line.startswith('<td') and '<td' in line:
|
||||||
|
idx = line.index('<td')
|
||||||
|
line = '{}{}{}{}'.format('<td>', line[:idx], '</td>', line[idx:])
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
|
soup_line = BeautifulSoup(line, "html.parser")
|
||||||
|
td_elements = soup_line.find_all('td')
|
||||||
|
key = td_elements[0].text.strip()
|
||||||
|
value = None if len(td_elements) < 2 else td_elements[-1].text.strip()
|
||||||
|
|
||||||
|
# Clean the key
|
||||||
|
key = key.rstrip(":").strip("[]").strip()
|
||||||
|
|
||||||
|
# Pop from stack to find the correct parent dictionary
|
||||||
|
while stack and stack[-1][1] >= level:
|
||||||
|
stack.pop()
|
||||||
|
|
||||||
|
# Add the new key-value pair
|
||||||
|
current_dict = stack[-1][0]
|
||||||
|
occurrences = self.count_keys(current_dict, key)
|
||||||
|
key = f"{key}_#{occurrences}" if occurrences > 0 else key
|
||||||
|
|
||||||
|
if value is None:
|
||||||
|
new_dict = {}
|
||||||
|
current_dict[key] = new_dict
|
||||||
|
stack.append((new_dict, level))
|
||||||
|
else:
|
||||||
|
if '<td class="cc">' not in line:
|
||||||
|
current_dict[key] = value
|
||||||
|
else:
|
||||||
|
if not current_dict.items():
|
||||||
|
current_dict[key] = []
|
||||||
|
current_dict[value] = []
|
||||||
|
else:
|
||||||
|
current_dict[list(current_dict.keys())[0]].append(key)
|
||||||
|
current_dict[list(current_dict.keys())[1]].append(value)
|
||||||
|
|
||||||
|
if len(table_names) - len(root) > 1:
|
||||||
|
raise Exception("Your AIDA64 report is missing some information. Please revise it according to the provided guidelines")
|
||||||
|
return root
|
||||||
|
|
||||||
|
def dump(self, report_path):
|
||||||
|
html_content = self.try_open(report_path)
|
||||||
|
report_dict = self.html_to_dict(html_content)
|
||||||
|
|
||||||
|
dmi = self.parse_dmi(report_dict.get("DMI", {}))
|
||||||
|
windows_devices = self.parse_windows_devices(report_dict.get("Windows Devices", {}))
|
||||||
|
|
||||||
|
hardware = {}
|
||||||
|
hardware["Motherboard"] = self.motherboard(report_dict.get("Summary", {}).get("Motherboard", {}), dmi)
|
||||||
|
hardware["CPU"] = self.cpu(report_dict.get("CPU", {}))
|
||||||
|
hardware["GPU"] = self.gpu(report_dict.get("GPU", {}), report_dict.get("Vulkan", {}), windows_devices)
|
||||||
|
hardware["Network"] = self.network(windows_devices, report_dict.get("PCI Devices", {}))
|
||||||
|
hardware["Storage"] = self.storage(windows_devices.get("IDE ATA/ATAPI controllers", {}), windows_devices.get("Storage controllers", {}), report_dict.get("ATA", {}))
|
||||||
|
hardware["Audio"] = self.audio(windows_devices)
|
||||||
|
hardware["USB"] = self.usb(windows_devices.get("Universal Serial Bus controllers", {}), report_dict.get("USB Devices", {}), windows_devices)
|
||||||
|
hardware["Input"] = self.input(windows_devices.get("Human Interface Devices", {}), windows_devices.get("Keyboards", {}), windows_devices.get("Mice and other pointing devices", {}), hardware["USB"].get("USB Devices", {}))
|
||||||
|
|
||||||
|
hardware = self.biometric(windows_devices.get("Biometric devices", {}), hardware["USB"].get("USB Devices", {}), hardware)
|
||||||
|
hardware = self.bluetooth(windows_devices.get("Bluetooth", {}), hardware["USB"].get("USB Devices", {}), hardware)
|
||||||
|
hardware = self.sd_controller(report_dict.get("PCI Devices", {}), hardware["USB"].get("USB Devices", {}), hardware)
|
||||||
|
hardware = self.intel_mei(hardware["CPU"].get("CPU Codename"), report_dict.get("PCI Devices", {}), hardware)
|
||||||
|
|
||||||
|
return hardware
|
||||||
951
Scripts/codec_layouts.py
Executable file
951
Scripts/codec_layouts.py
Executable file
@@ -0,0 +1,951 @@
|
|||||||
|
from Scripts import github
|
||||||
|
from Scripts import resource_fetcher
|
||||||
|
from Scripts import utils
|
||||||
|
import os
|
||||||
|
|
||||||
|
class CodecLayouts:
|
||||||
|
def __init__(self):
|
||||||
|
self.github = github.Github()
|
||||||
|
self.fetcher = resource_fetcher.ResourceFetcher(self.github.headers)
|
||||||
|
self.utils = utils.Utils()
|
||||||
|
self.vendors = {
|
||||||
|
"11D4": ["AD", "AnalogDevices"],
|
||||||
|
"10EC": ["ALC", "Realtek"],
|
||||||
|
"1102": ["CA", "Creative"],
|
||||||
|
"1013": ["CS", "CirrusLogic"],
|
||||||
|
"14F1": ["CX", "Conexant"],
|
||||||
|
"111D": ["IDT"],
|
||||||
|
"8384": ["STAC", "SigmaTel"],
|
||||||
|
"1106": ["VT", "VIA"]
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_layout_ids_from_applealc_repo(self):
|
||||||
|
# Define the GitHub API URL for the AppleALC repository contents
|
||||||
|
url = "https://api.github.com/repos/acidanthera/AppleALC/contents/Resources"
|
||||||
|
|
||||||
|
self.github.check_ratelimit()
|
||||||
|
|
||||||
|
# Dictionary to store sound codec information
|
||||||
|
sound_codec_info = {}
|
||||||
|
|
||||||
|
# Retrieve content information from the GitHub repository
|
||||||
|
content = self.fetcher.fetch_and_parse_content(url, "json")
|
||||||
|
|
||||||
|
# Iterate through folders in the content
|
||||||
|
for folder in content:
|
||||||
|
codec_folder_name = folder["name"]
|
||||||
|
|
||||||
|
if "." in codec_folder_name:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Identify vendor based on the vendor information
|
||||||
|
vendor_id = next((id for id, vendor in self.vendors.items() if vendor[0] in codec_folder_name), None)
|
||||||
|
|
||||||
|
if not vendor_id:
|
||||||
|
# Skip if vendor ID is not found
|
||||||
|
print(f"Unknown vendor for codec: {codec_folder_name}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Extract vendor name from vendor information
|
||||||
|
vendor_name = self.vendors[vendor_id][-1]
|
||||||
|
|
||||||
|
# Build the raw URL for the Info.plist file
|
||||||
|
raw_url = f"https://raw.githubusercontent.com/acidanthera/AppleALC/master/Resources/{codec_folder_name}/Info.plist"
|
||||||
|
|
||||||
|
# Retrieve content from the Info.plist file and parse as plist
|
||||||
|
info = self.fetcher.fetch_and_parse_content(raw_url, "json")
|
||||||
|
|
||||||
|
# Extract relevant information from the Info.plist
|
||||||
|
codec_id_hex = self.utils.int_to_hex(info["CodecID"]).zfill(4)
|
||||||
|
formatted_codec_name = "{} {}".format(vendor_name, info["CodecName"])
|
||||||
|
layout_ids = sorted([int(layouts["Id"]) for layouts in info["Files"]["Layouts"]])
|
||||||
|
pci_id = f"{vendor_id}-{codec_id_hex}".upper()
|
||||||
|
|
||||||
|
sound_codec_info[pci_id] = layout_ids
|
||||||
|
|
||||||
|
# Sort sound codec information by name
|
||||||
|
sorted_sound_codec_info = dict(sorted(sound_codec_info.items(), key=lambda item: item[1]["Name"]))
|
||||||
|
|
||||||
|
return sorted_sound_codec_info
|
||||||
|
|
||||||
|
def get_layout_ids_from_applealc_kext(self, applealc_path):
|
||||||
|
if not os.path.exists(applealc_path):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
plist_path = os.path.join(applealc_path, "Contents", "Info.plist")
|
||||||
|
plist_data = self.utils.read_file(plist_path)
|
||||||
|
|
||||||
|
if not plist_data:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
codec_layouts = {}
|
||||||
|
|
||||||
|
hda_config_defaults = plist_data.get("IOKitPersonalities", {}).get("as.vit9696.AppleALC", {}).get("HDAConfigDefault", [])
|
||||||
|
for layout in hda_config_defaults:
|
||||||
|
codec_id_hex = self.utils.int_to_hex(layout.get("CodecID", 0)).zfill(8)
|
||||||
|
formatted_codec_id = f"{codec_id_hex[:4]}-{codec_id_hex[-4:]}"
|
||||||
|
layout_id = layout.get("LayoutID")
|
||||||
|
if layout_id is not None:
|
||||||
|
if formatted_codec_id not in codec_layouts:
|
||||||
|
codec_layouts[formatted_codec_id] = []
|
||||||
|
codec_layouts[formatted_codec_id].append(layout_id)
|
||||||
|
|
||||||
|
# Sort the layout IDs for each codec
|
||||||
|
for codec_id in codec_layouts:
|
||||||
|
codec_layouts[codec_id] = sorted(codec_layouts[codec_id])
|
||||||
|
|
||||||
|
return codec_layouts
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"10EC-0295": [
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
11,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
28,
|
||||||
|
33,
|
||||||
|
69,
|
||||||
|
75,
|
||||||
|
77
|
||||||
|
],
|
||||||
|
"10EC-0298": [
|
||||||
|
3,
|
||||||
|
11,
|
||||||
|
13,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
25,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
32,
|
||||||
|
33,
|
||||||
|
47,
|
||||||
|
66,
|
||||||
|
72,
|
||||||
|
94,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"10EC-1168": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
11,
|
||||||
|
13,
|
||||||
|
15,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"10EC-0256": [
|
||||||
|
5,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
28,
|
||||||
|
33,
|
||||||
|
38,
|
||||||
|
56,
|
||||||
|
57,
|
||||||
|
66,
|
||||||
|
67,
|
||||||
|
68,
|
||||||
|
69,
|
||||||
|
70,
|
||||||
|
76,
|
||||||
|
77,
|
||||||
|
88,
|
||||||
|
95,
|
||||||
|
97,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"10EC-0282": [
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
13,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
41,
|
||||||
|
43,
|
||||||
|
51,
|
||||||
|
69,
|
||||||
|
76,
|
||||||
|
86,
|
||||||
|
127
|
||||||
|
],
|
||||||
|
"10EC-0269": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
32,
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
36,
|
||||||
|
37,
|
||||||
|
38,
|
||||||
|
39,
|
||||||
|
40,
|
||||||
|
44,
|
||||||
|
45,
|
||||||
|
47,
|
||||||
|
55,
|
||||||
|
58,
|
||||||
|
66,
|
||||||
|
69,
|
||||||
|
76,
|
||||||
|
77,
|
||||||
|
88,
|
||||||
|
91,
|
||||||
|
93,
|
||||||
|
99,
|
||||||
|
100,
|
||||||
|
111,
|
||||||
|
127,
|
||||||
|
128,
|
||||||
|
138,
|
||||||
|
188
|
||||||
|
],
|
||||||
|
"111D-7695": [
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
14
|
||||||
|
],
|
||||||
|
"14F1-5098": [
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
23,
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"1102-0011": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"1013-4210": [
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"1013-4213": [
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"11D4-1884": [
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"11D4-1984": [
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"11D4-194A": [
|
||||||
|
11,
|
||||||
|
13,
|
||||||
|
44
|
||||||
|
],
|
||||||
|
"11D4-1988": [
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"11D4-198B": [
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"11D4-989B": [
|
||||||
|
5,
|
||||||
|
7
|
||||||
|
],
|
||||||
|
"10EC-0215": [
|
||||||
|
18
|
||||||
|
],
|
||||||
|
"10EC-0221": [
|
||||||
|
11,
|
||||||
|
15,
|
||||||
|
88
|
||||||
|
],
|
||||||
|
"10EC-0222": [
|
||||||
|
11,
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"10EC-0225": [
|
||||||
|
28,
|
||||||
|
30,
|
||||||
|
33,
|
||||||
|
90
|
||||||
|
],
|
||||||
|
"10EC-0230": [
|
||||||
|
13,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"10EC-0233": [
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
11,
|
||||||
|
13,
|
||||||
|
21,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
32,
|
||||||
|
33
|
||||||
|
],
|
||||||
|
"10EC-0236": [
|
||||||
|
3,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
23,
|
||||||
|
36,
|
||||||
|
54,
|
||||||
|
55,
|
||||||
|
68,
|
||||||
|
69,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"10EC-0235": [
|
||||||
|
3,
|
||||||
|
8,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
24,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
33,
|
||||||
|
35,
|
||||||
|
36,
|
||||||
|
37,
|
||||||
|
72,
|
||||||
|
88,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"10EC-0245": [
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"10EC-0255": [
|
||||||
|
3,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
15,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
37,
|
||||||
|
66,
|
||||||
|
69,
|
||||||
|
71,
|
||||||
|
80,
|
||||||
|
82,
|
||||||
|
86,
|
||||||
|
96,
|
||||||
|
99,
|
||||||
|
100,
|
||||||
|
255
|
||||||
|
],
|
||||||
|
"10EC-0257": [
|
||||||
|
11,
|
||||||
|
18,
|
||||||
|
86,
|
||||||
|
96,
|
||||||
|
97,
|
||||||
|
99,
|
||||||
|
100,
|
||||||
|
101
|
||||||
|
],
|
||||||
|
"10EC-0260": [
|
||||||
|
11,
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"10EC-0262": [
|
||||||
|
7,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
28,
|
||||||
|
66
|
||||||
|
],
|
||||||
|
"10EC-0268": [
|
||||||
|
3,
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"10EC-0270": [
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
21,
|
||||||
|
27,
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"10EC-0272": [
|
||||||
|
3,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
18,
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"10EC-0274": [
|
||||||
|
21,
|
||||||
|
28,
|
||||||
|
35,
|
||||||
|
39
|
||||||
|
],
|
||||||
|
"10EC-0275": [
|
||||||
|
3,
|
||||||
|
13,
|
||||||
|
15,
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"10EC-0280": [
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
11,
|
||||||
|
13,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"10EC-0283": [
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
15,
|
||||||
|
44,
|
||||||
|
45,
|
||||||
|
66,
|
||||||
|
73,
|
||||||
|
88
|
||||||
|
],
|
||||||
|
"10EC-0284": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"10EC-0285": [
|
||||||
|
11,
|
||||||
|
21,
|
||||||
|
31,
|
||||||
|
52,
|
||||||
|
61,
|
||||||
|
66,
|
||||||
|
71,
|
||||||
|
88
|
||||||
|
],
|
||||||
|
"10EC-0286": [
|
||||||
|
3,
|
||||||
|
11,
|
||||||
|
69
|
||||||
|
],
|
||||||
|
"10EC-0287": [
|
||||||
|
11,
|
||||||
|
13,
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"10EC-0288": [
|
||||||
|
3,
|
||||||
|
13,
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"10EC-0289": [
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
15,
|
||||||
|
23,
|
||||||
|
33,
|
||||||
|
68,
|
||||||
|
69,
|
||||||
|
87,
|
||||||
|
93,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"10EC-0290": [
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
10,
|
||||||
|
15,
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"10EC-0292": [
|
||||||
|
12,
|
||||||
|
15,
|
||||||
|
18,
|
||||||
|
28,
|
||||||
|
32,
|
||||||
|
55,
|
||||||
|
59
|
||||||
|
],
|
||||||
|
"10EC-0293": [
|
||||||
|
11,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
31
|
||||||
|
],
|
||||||
|
"10EC-0294": [
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
15,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
28,
|
||||||
|
44,
|
||||||
|
66,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"10EC-0299": [
|
||||||
|
21,
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"10EC-0623": [
|
||||||
|
13,
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"10EC-0662": [
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
66
|
||||||
|
],
|
||||||
|
"10EC-0663": [
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
15,
|
||||||
|
28,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"10EC-0665": [
|
||||||
|
12,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"10EC-0668": [
|
||||||
|
3,
|
||||||
|
20,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29
|
||||||
|
],
|
||||||
|
"10EC-0670": [
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"10EC-0671": [
|
||||||
|
12,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
88
|
||||||
|
],
|
||||||
|
"10EC-0700": [
|
||||||
|
11,
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"10EC-0882": [
|
||||||
|
5,
|
||||||
|
7
|
||||||
|
],
|
||||||
|
"10EC-0883": [
|
||||||
|
7,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"10EC-0885": [
|
||||||
|
1,
|
||||||
|
12,
|
||||||
|
15
|
||||||
|
],
|
||||||
|
"10EC-0887": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
20,
|
||||||
|
33,
|
||||||
|
40,
|
||||||
|
50,
|
||||||
|
52,
|
||||||
|
53,
|
||||||
|
87,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"10EC-0888": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
11,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29
|
||||||
|
],
|
||||||
|
"10EC-0889": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
11,
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"10EC-0867": [
|
||||||
|
11,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"10EC-0892": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
28,
|
||||||
|
31,
|
||||||
|
32,
|
||||||
|
90,
|
||||||
|
92,
|
||||||
|
97,
|
||||||
|
98,
|
||||||
|
99,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"10EC-0897": [
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
66,
|
||||||
|
69,
|
||||||
|
77,
|
||||||
|
98,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"10EC-0899": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
11,
|
||||||
|
13,
|
||||||
|
28,
|
||||||
|
65,
|
||||||
|
66,
|
||||||
|
98,
|
||||||
|
99,
|
||||||
|
101
|
||||||
|
],
|
||||||
|
"10EC-0900": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
11,
|
||||||
|
99
|
||||||
|
],
|
||||||
|
"10EC-1220": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
11,
|
||||||
|
13,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
25,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
69,
|
||||||
|
98,
|
||||||
|
99,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"10EC-0B00": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
7,
|
||||||
|
11,
|
||||||
|
49,
|
||||||
|
50,
|
||||||
|
51,
|
||||||
|
52,
|
||||||
|
69
|
||||||
|
],
|
||||||
|
"14F1-1F72": [
|
||||||
|
3,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"14F1-1F86": [
|
||||||
|
15,
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"14F1-1FD6": [
|
||||||
|
21,
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"14F1-2008": [
|
||||||
|
3,
|
||||||
|
15,
|
||||||
|
21,
|
||||||
|
23,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"14F1-20D0": [
|
||||||
|
12,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"14F1-5051": [
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"14F1-5067": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"14F1-5069": [
|
||||||
|
3,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"14F1-506C": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"14F1-506E": [
|
||||||
|
3,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"14F1-50A1": [
|
||||||
|
11,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"14F1-50A2": [
|
||||||
|
11,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"14F1-50F2": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"14F1-50F4": [
|
||||||
|
3,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"14F1-510F": [
|
||||||
|
3,
|
||||||
|
21,
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"14F1-5111": [
|
||||||
|
3,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"14F1-5113": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"14F1-5114": [
|
||||||
|
3,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"14F1-5115": [
|
||||||
|
3,
|
||||||
|
28
|
||||||
|
],
|
||||||
|
"111D-76D1": [
|
||||||
|
12,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"111D-76D9": [
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"111D-76F3": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"111D-76B2": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"111D-7675": [
|
||||||
|
19,
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"111D-7676": [
|
||||||
|
15
|
||||||
|
],
|
||||||
|
"111D-76D5": [
|
||||||
|
3,
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"111D-7605": [
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
12,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
28,
|
||||||
|
76
|
||||||
|
],
|
||||||
|
"111D-7608": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"111D-7603": [
|
||||||
|
3,
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"111D-76E7": [
|
||||||
|
3,
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"111D-76E0": [
|
||||||
|
3,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
33,
|
||||||
|
84
|
||||||
|
],
|
||||||
|
"111D-76DF": [
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"111D-76E5": [
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"8384-7690": [
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"8384-76A0": [
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"8384-7662": [
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"1106-4760": [
|
||||||
|
21
|
||||||
|
],
|
||||||
|
"1106-8446": [
|
||||||
|
3,
|
||||||
|
33,
|
||||||
|
65
|
||||||
|
],
|
||||||
|
"1106-0441": [
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
9,
|
||||||
|
13
|
||||||
|
]
|
||||||
|
}
|
||||||
212
Scripts/compatibility_checker.py
Executable file
212
Scripts/compatibility_checker.py
Executable file
@@ -0,0 +1,212 @@
|
|||||||
|
from Scripts.datasets import chipset_data
|
||||||
|
from Scripts.datasets import cpu_data
|
||||||
|
from Scripts.datasets import pci_data
|
||||||
|
from Scripts import utils
|
||||||
|
|
||||||
|
class CompatibilityChecker:
|
||||||
|
def __init__(self):
|
||||||
|
self.utils = utils.Utils()
|
||||||
|
self.latest_macos_version = 24
|
||||||
|
|
||||||
|
def is_low_end_intel_cpu(self, processor_name):
|
||||||
|
return any(brand in processor_name for brand in ["Celeron", "Pentium"])
|
||||||
|
|
||||||
|
def check_cpu_compatibility(self, processor_name, instruction_set):
|
||||||
|
if "x86-64" not in instruction_set or "SSE4" not in instruction_set:
|
||||||
|
self.max_supported_macos_version = self.min_supported_macos_version = -1
|
||||||
|
self.unsupported_devices.append(f"CPU: {processor_name}")
|
||||||
|
return
|
||||||
|
|
||||||
|
if "SSE4.2" not in instruction_set:
|
||||||
|
self.min_supported_macos_version = 18
|
||||||
|
if "SSE4.1" in instruction_set:
|
||||||
|
self.max_supported_macos_version = 21
|
||||||
|
|
||||||
|
def check_gpu_compatibility(self, motherboard_chipset, processor_name, instruction_set, gpu_info):
|
||||||
|
supported_gpus = {}
|
||||||
|
is_supported_discrete_gpu = False
|
||||||
|
|
||||||
|
for gpu_name, gpu_props in gpu_info.items():
|
||||||
|
gpu_manufacturer = gpu_props.get("Manufacturer")
|
||||||
|
gpu_codename = gpu_props.get("GPU Codename")
|
||||||
|
device_type = gpu_props.get("Device Type")
|
||||||
|
is_supported_gpu = True
|
||||||
|
|
||||||
|
if "Integrated GPU" in device_type:
|
||||||
|
if "Intel" in gpu_manufacturer:
|
||||||
|
if self.utils.contains_any(cpu_data.IntelCPUGenerations, gpu_codename, end=12) and \
|
||||||
|
not self.is_low_end_intel_cpu(processor_name) and \
|
||||||
|
not "2000" in gpu_name and not "2500" in gpu_name:
|
||||||
|
self.min_supported_macos_version = max(17, self.min_supported_macos_version)
|
||||||
|
if "Sandy Bridge" in gpu_codename:
|
||||||
|
self.max_supported_macos_version = max(17, self.max_supported_macos_version if is_supported_discrete_gpu else -1)
|
||||||
|
elif "Ivy Bridge" in gpu_codename:
|
||||||
|
self.max_supported_macos_version = max(20, self.max_supported_macos_version if is_supported_discrete_gpu else -1)
|
||||||
|
elif "Haswell" in gpu_codename or "Broadwell" in gpu_codename:
|
||||||
|
self.max_supported_macos_version = max(21, self.max_supported_macos_version if is_supported_discrete_gpu else -1)
|
||||||
|
elif "Skylake" in gpu_codename or "Kaby Lake" in gpu_codename and not "-r" in gpu_codename.lower():
|
||||||
|
self.max_supported_macos_version = max(22, self.max_supported_macos_version if is_supported_discrete_gpu else -1)
|
||||||
|
elif "Amber Lake" in gpu_codename or "Whiskey Lake" in gpu_codename:
|
||||||
|
self.min_supported_macos_version = max(17, self.min_supported_macos_version if is_supported_discrete_gpu else -1)
|
||||||
|
self.max_supported_macos_version = self.latest_macos_version
|
||||||
|
elif not is_supported_discrete_gpu and "Comet Lake" in gpu_codename and self.utils.contains_any(chipset_data.IntelChipsets, motherboard_chipset, start=110, end=122):
|
||||||
|
self.max_supported_macos_version = self.min_supported_macos_version = -1
|
||||||
|
elif "Ice Lake" in gpu_codename:
|
||||||
|
self.min_supported_macos_version = max(19, self.min_supported_macos_version)
|
||||||
|
self.max_supported_macos_version = self.latest_macos_version
|
||||||
|
else:
|
||||||
|
self.max_supported_macos_version = self.latest_macos_version
|
||||||
|
else:
|
||||||
|
is_supported_gpu = False
|
||||||
|
if not is_supported_discrete_gpu:
|
||||||
|
self.max_supported_macos_version = self.min_supported_macos_version = -1
|
||||||
|
elif "AMD" in gpu_manufacturer:
|
||||||
|
is_supported_gpu = gpu_props.get("Device ID") in pci_data.AMDGPUIDs
|
||||||
|
if is_supported_gpu:
|
||||||
|
self.max_supported_macos_version = self.latest_macos_version
|
||||||
|
self.min_supported_macos_version = max(19, self.min_supported_macos_version)
|
||||||
|
elif "Discrete GPU" in device_type:
|
||||||
|
if "AMD" in gpu_manufacturer:
|
||||||
|
is_supported_discrete_gpu = True
|
||||||
|
|
||||||
|
if "Navi 2" in gpu_codename:
|
||||||
|
if not "AVX2" in instruction_set:
|
||||||
|
self.max_supported_macos_version = min(21, self.max_supported_macos_version)
|
||||||
|
else:
|
||||||
|
if "Navi 23" in gpu_codename or "Navi 22" in gpu_codename:
|
||||||
|
self.min_supported_macos_version = max(21, self.min_supported_macos_version)
|
||||||
|
elif "Navi 21" in gpu_codename:
|
||||||
|
self.min_supported_macos_version = max(20, self.min_supported_macos_version)
|
||||||
|
else:
|
||||||
|
self.max_supported_macos_version = self.min_supported_macos_version = -1
|
||||||
|
is_supported_discrete_gpu = is_supported_gpu = False
|
||||||
|
elif "Navi 10" in gpu_codename:
|
||||||
|
self.min_supported_macos_version = max(19, self.min_supported_macos_version)
|
||||||
|
elif "Vega 20" in gpu_codename:
|
||||||
|
self.min_supported_macos_version = max(17, self.min_supported_macos_version)
|
||||||
|
elif "Vega 10" in gpu_codename or "Polaris" in gpu_codename or "550" in gpu_name:
|
||||||
|
self.min_supported_macos_version = max(17, self.min_supported_macos_version)
|
||||||
|
else:
|
||||||
|
self.max_supported_macos_version = self.min_supported_macos_version = -1
|
||||||
|
is_supported_discrete_gpu = is_supported_gpu = False
|
||||||
|
elif "NVIDIA" in gpu_manufacturer:
|
||||||
|
is_supported_discrete_gpu = True
|
||||||
|
|
||||||
|
if "GK" in gpu_codename:
|
||||||
|
self.max_supported_macos_version = 20
|
||||||
|
elif "GP" in gpu_codename or "GM" in gpu_codename or "GF" in gpu_codename or "GT" in gpu_codename or gpu_codename.startswith("C"):
|
||||||
|
self.max_supported_macos_version = self.min_supported_macos_version = 17
|
||||||
|
else:
|
||||||
|
self.max_supported_macos_version = self.min_supported_macos_version = -1
|
||||||
|
is_supported_discrete_gpu = is_supported_gpu = False
|
||||||
|
|
||||||
|
if not is_supported_gpu:
|
||||||
|
self.unsupported_devices.append(f"{device_type}: {gpu_name}")
|
||||||
|
else:
|
||||||
|
supported_gpus[gpu_name] = gpu_props
|
||||||
|
|
||||||
|
return supported_gpus
|
||||||
|
|
||||||
|
def check_audio_compatibility(self, audio_info):
|
||||||
|
supported_audio = {}
|
||||||
|
audio_endpoint = None
|
||||||
|
|
||||||
|
for audio_device, audio_props in audio_info.items():
|
||||||
|
codec_id = audio_props.get("Codec ID")
|
||||||
|
if "USB" in audio_props.get("Bus Type") or \
|
||||||
|
codec_id.startswith("8086") or \
|
||||||
|
codec_id.startswith("1002") or \
|
||||||
|
codec_id in pci_data.CodecIDs:
|
||||||
|
if codec_id in pci_data.CodecIDs:
|
||||||
|
supported_audio = {**{audio_device: audio_props}, **supported_audio}
|
||||||
|
else:
|
||||||
|
supported_audio[audio_device] = audio_props
|
||||||
|
else:
|
||||||
|
if "Audio Endpoints" in audio_props:
|
||||||
|
audio_endpoint = ",".join(audio_props.get("Audio Endpoints"))
|
||||||
|
self.unsupported_devices.append("Audio: {}{}".format(audio_device, "" if not audio_endpoint else f" ({audio_endpoint})"))
|
||||||
|
|
||||||
|
return supported_audio
|
||||||
|
|
||||||
|
def check_biometric_compatibility(self, hardware):
|
||||||
|
biometric = hardware.get("Biometric", {})
|
||||||
|
if biometric:
|
||||||
|
for biometric_device, biometric_props in biometric.items():
|
||||||
|
self.unsupported_devices.append(f"Biometric: {biometric_device}")
|
||||||
|
|
||||||
|
del hardware["Biometric"]
|
||||||
|
|
||||||
|
def check_network_compatibility(self, network_info):
|
||||||
|
supported_network = {}
|
||||||
|
|
||||||
|
for device_name, device_props in network_info.items():
|
||||||
|
connection_name = device_props.get("Connection Name")
|
||||||
|
bus_type = device_props.get("Bus Type")
|
||||||
|
device_id = device_props.get("Device ID")
|
||||||
|
is_device_supported = device_id in pci_data.NetworkIDs
|
||||||
|
|
||||||
|
if bus_type.startswith("PCI"):
|
||||||
|
if device_id in ["8086-125B", "8086-125C", "8086-125D", "8086-3102"]:
|
||||||
|
self.min_supported_macos_version = 19
|
||||||
|
|
||||||
|
if not is_device_supported:
|
||||||
|
self.unsupported_devices.append(f"{connection_name}: {device_name}")
|
||||||
|
else:
|
||||||
|
supported_network[device_name] = device_props
|
||||||
|
|
||||||
|
return supported_network
|
||||||
|
|
||||||
|
def check_storage_compatibility(self, storage_controller_info):
|
||||||
|
supported_storage = {}
|
||||||
|
|
||||||
|
for controller_name, controller_props in storage_controller_info.items():
|
||||||
|
if "PCI" in controller_props.get("Bus Type"):
|
||||||
|
device_id = controller_props.get("Device ID")
|
||||||
|
if device_id in pci_data.IntelVMDIDs or device_id in pci_data.UnsupportedNVMeSSDIDs:
|
||||||
|
self.unsupported_devices.append("Storage: {}".format(pci_data.UnsupportedNVMeSSDIDs[device_id]))
|
||||||
|
else:
|
||||||
|
supported_storage[controller_name] = controller_props
|
||||||
|
|
||||||
|
return supported_storage
|
||||||
|
|
||||||
|
def check_sd_controller_compatibility(self, hardware):
|
||||||
|
sd_controller_props = hardware.get("SD Controller", {})
|
||||||
|
|
||||||
|
if sd_controller_props:
|
||||||
|
if sd_controller_props.get("Device ID") not in pci_data.RealtekCardReaderIDs:
|
||||||
|
self.unsupported_devices.append("SD Controller: {}".format(sd_controller_props.get("Device Description")))
|
||||||
|
hardware["SD Controller"] = {}
|
||||||
|
|
||||||
|
def check_compatibility(self, hardware):
|
||||||
|
self.max_supported_macos_version = self.latest_macos_version
|
||||||
|
self.min_supported_macos_version = 17
|
||||||
|
self.unsupported_devices = []
|
||||||
|
|
||||||
|
self.check_cpu_compatibility(
|
||||||
|
hardware.get("CPU").get("Processor Name"),
|
||||||
|
hardware.get("CPU").get("Instruction Set")
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.max_supported_macos_version != -1:
|
||||||
|
hardware["GPU"] = self.check_gpu_compatibility(
|
||||||
|
hardware.get("Motherboard").get("Motherboard Chipset"),
|
||||||
|
hardware.get("CPU").get("Processor Name"),
|
||||||
|
hardware.get("CPU").get("Instruction Set"),
|
||||||
|
hardware.get("GPU")
|
||||||
|
)
|
||||||
|
if hardware.get("GPU"):
|
||||||
|
hardware["Audio"] = self.check_audio_compatibility(hardware.get("Audio"))
|
||||||
|
self.check_biometric_compatibility(hardware)
|
||||||
|
hardware["Network"] = self.check_network_compatibility(hardware.get("Network"))
|
||||||
|
hardware["Storage"]["Storage Controllers"] = self.check_storage_compatibility(hardware.get("Storage").get("Storage Controllers"))
|
||||||
|
self.check_sd_controller_compatibility(hardware)
|
||||||
|
|
||||||
|
hardware["Compatibility"] = {
|
||||||
|
"macOS Version": {
|
||||||
|
"Max Version": self.max_supported_macos_version,
|
||||||
|
"Min Version": self.min_supported_macos_version
|
||||||
|
},
|
||||||
|
"Unsupported Devices": self.unsupported_devices
|
||||||
|
}
|
||||||
|
|
||||||
|
return hardware
|
||||||
364
Scripts/config_prodigy.py
Executable file
364
Scripts/config_prodigy.py
Executable file
@@ -0,0 +1,364 @@
|
|||||||
|
from Scripts.datasets import chipset_data
|
||||||
|
from Scripts.datasets import cpu_data
|
||||||
|
from Scripts import codec_layouts
|
||||||
|
from Scripts import gathering_files
|
||||||
|
from Scripts import smbios
|
||||||
|
from Scripts import utils
|
||||||
|
import random
|
||||||
|
|
||||||
|
class ConfigProdigy:
|
||||||
|
def __init__(self):
|
||||||
|
self.g = gathering_files.gatheringFiles()
|
||||||
|
self.smbios = smbios.SMBIOS()
|
||||||
|
self.utils = utils.Utils()
|
||||||
|
self.latest_macos_version = "24.99.99"
|
||||||
|
self.kernel_patches = {
|
||||||
|
"Force enable Hyper Threading": [
|
||||||
|
{
|
||||||
|
"Arch": "Any",
|
||||||
|
"Base": "_cpu_thread_alloc",
|
||||||
|
"Comment": "Force enable Hyper Threading for macOS Mojave or later",
|
||||||
|
"Count": 1,
|
||||||
|
"Enabled": True,
|
||||||
|
"Find": self.utils.hex_to_bytes("8B8894010000"),
|
||||||
|
"Identifier": "kernel",
|
||||||
|
"Limit": 0,
|
||||||
|
"Mask": self.utils.hex_to_bytes(""),
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": "18.0.0",
|
||||||
|
"Replace": self.utils.hex_to_bytes("B9FF00000090"),
|
||||||
|
"ReplaceMask": self.utils.hex_to_bytes(""),
|
||||||
|
"Skip": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"AMD Vanilla Patches": self.g.get_amd_kernel_patches()
|
||||||
|
}
|
||||||
|
self.cpuids = {
|
||||||
|
"Ivy Bridge": "A9060300",
|
||||||
|
"Haswell": "C3060300",
|
||||||
|
"Broadwell": "D4060300",
|
||||||
|
"Coffee Lake": "EB060800",
|
||||||
|
"Comet Lake": "55060A00"
|
||||||
|
}
|
||||||
|
|
||||||
|
def mmio_whitelist(self, cpu_codename):
|
||||||
|
booter_mmiowhitelist = []
|
||||||
|
|
||||||
|
if "Ice Lake" in cpu_codename:
|
||||||
|
booter_mmiowhitelist.append({
|
||||||
|
"Address": 4284481536,
|
||||||
|
"Comment": "MMIO 0xFF600000 Ice Lake",
|
||||||
|
"Enable": True
|
||||||
|
})
|
||||||
|
|
||||||
|
return booter_mmiowhitelist
|
||||||
|
|
||||||
|
def check_mats_support(self, cpu_manufacturer, motherboard_chipset, cpu_codename):
|
||||||
|
return "AMD" in cpu_manufacturer or \
|
||||||
|
(self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, start=7, end=9) is None and not self.utils.contains_any(chipset_data.IntelChipsets, motherboard_chipset, start=85) is None) or \
|
||||||
|
not self.utils.contains_any(chipset_data.IntelChipsets, motherboard_chipset, start=49, end=60) is None
|
||||||
|
|
||||||
|
def check_resizable_bar_support(self, motherboard_chipset, platform, cpu_codename, discrete_gpu):
|
||||||
|
return "Desktop" in platform and discrete_gpu and not (self.utils.contains_any(chipset_data.AMDChipsets, motherboard_chipset) is None or \
|
||||||
|
self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, start=10) is None)
|
||||||
|
|
||||||
|
def is_low_end_intel_cpu(self, processor_name):
|
||||||
|
return any(brand in processor_name for brand in ["Celeron", "Pentium"])
|
||||||
|
|
||||||
|
def deviceproperties(self, cpu_codename, intel_mei, igpu_properties):
|
||||||
|
deviceproperties_add = {}
|
||||||
|
|
||||||
|
if igpu_properties:
|
||||||
|
deviceproperties_add["PciRoot(0x0)/Pci(0x2,0x0)"] = igpu_properties
|
||||||
|
if intel_mei:
|
||||||
|
if "Sandy Bridge" in cpu_codename and intel_mei.get("Device ID") in "8086-1E3A":
|
||||||
|
deviceproperties_add["PciRoot(0x0)/Pci(0x16,0x0)"] = {
|
||||||
|
"device-id": "3A1C0000"
|
||||||
|
}
|
||||||
|
elif "Ivy Bridge" in cpu_codename and intel_mei.get("Device ID") in "8086-1C3A":
|
||||||
|
deviceproperties_add["PciRoot(0x0)/Pci(0x16,0x0)"] = {
|
||||||
|
"device-id": "3A1E0000"
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, value in deviceproperties_add.items():
|
||||||
|
for key_child, value_child in value.items():
|
||||||
|
if isinstance(value_child, str):
|
||||||
|
deviceproperties_add[key][key_child] = self.utils.hex_to_bytes(deviceproperties_add[key][key_child])
|
||||||
|
|
||||||
|
return deviceproperties_add
|
||||||
|
|
||||||
|
def block_kext_bundle(self, wifi_pci, macos_version):
|
||||||
|
kernel_block = []
|
||||||
|
|
||||||
|
if wifi_pci and macos_version > 22 and wifi_pci in ["14E4-43A0", "14E4-43A3", "14E4-43BA"]:
|
||||||
|
kernel_block.append({
|
||||||
|
"Arch": "x86_64",
|
||||||
|
"Comment": "Allow IOSkywalk Downgrade",
|
||||||
|
"Enable": True,
|
||||||
|
"Identifier": "com.apple.iokit.IOSkywalkFamily",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": "",
|
||||||
|
"Strategy": "Exclude"
|
||||||
|
})
|
||||||
|
|
||||||
|
return kernel_block
|
||||||
|
|
||||||
|
def is_low_end_haswell_plus(self, processor_name, cpu_codename):
|
||||||
|
return self.is_low_end_intel_cpu(processor_name) and not self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, start=2) is None
|
||||||
|
|
||||||
|
def is_intel_hedt_cpu(self, cpu_codename):
|
||||||
|
return "-E" in cpu_codename and not self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, end=4) is None or \
|
||||||
|
("-X" in cpu_codename or "-W" in cpu_codename) and not self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, start=4, end=6) is None
|
||||||
|
|
||||||
|
def spoof_cpuid(self, processor_name, cpu_codename, macos_version):
|
||||||
|
if self.is_low_end_haswell_plus(processor_name, cpu_codename):
|
||||||
|
return self.cpuids.get("Ivy Bridge")
|
||||||
|
elif "Haswell" in cpu_codename and self.is_intel_hedt_cpu(cpu_codename):
|
||||||
|
return self.cpuids.get("Haswell")
|
||||||
|
elif "Broadwell" in cpu_codename and self.is_intel_hedt_cpu(cpu_codename):
|
||||||
|
return self.cpuids.get("Broadwell")
|
||||||
|
elif "Ice Lake" not in cpu_codename and not self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, start=10) is None:
|
||||||
|
if not "Comet Lake" in cpu_codename:
|
||||||
|
return self.cpuids.get("Comet Lake")
|
||||||
|
if macos_version < 19:
|
||||||
|
return self.cpuids.get("Coffee Lake")
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def load_kernel_patch(self, motherboard_chipset, cpu_manufacturer, cpu_codename, cpu_cores, gpu_manufacturer, tsc_sync, macos_version):
|
||||||
|
kernel_patch = []
|
||||||
|
patches_to_remove = []
|
||||||
|
|
||||||
|
if "AMD" in cpu_manufacturer:
|
||||||
|
kernel_patch.extend(self.kernel_patches["AMD Vanilla Patches"])
|
||||||
|
elif tsc_sync:
|
||||||
|
kernel_patch.extend(self.kernel_patches["AMD Vanilla Patches"][-6:-4])
|
||||||
|
|
||||||
|
if not self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, start=13) is None:
|
||||||
|
kernel_patch.extend(self.kernel_patches["Force enable Hyper Threading"])
|
||||||
|
|
||||||
|
for index, patch in enumerate(kernel_patch):
|
||||||
|
max_supported_macos_version = patch.get("MaxKernel") or self.latest_macos_version
|
||||||
|
min_supported_macos_version = patch.get("MinKernel") or "17.0.0"
|
||||||
|
|
||||||
|
if "cpuid_cores_per_package" in patch["Comment"]:
|
||||||
|
patch["Replace"] = patch["Replace"].hex()
|
||||||
|
patch["Replace"] = self.utils.hex_to_bytes(patch["Replace"][:2] + self.utils.int_to_hex(int(cpu_cores)) + patch["Replace"][4:])
|
||||||
|
elif "IOPCIIsHotplugPort" in patch["Comment"]:
|
||||||
|
if not self.utils.contains_any(chipset_data.AMDChipsets, motherboard_chipset, start=6) is None:
|
||||||
|
patch["Enabled"] = True
|
||||||
|
if "_mtrr_update_action" in patch["Comment"]:
|
||||||
|
if chipset_data.AMDChipsets[0].lower() in motherboard_chipset:
|
||||||
|
patch["Enabled"] = False
|
||||||
|
elif "AMD" in gpu_manufacturer:
|
||||||
|
if "Algrey" in patch["Comment"]:
|
||||||
|
patch["Enabled"] = False
|
||||||
|
elif "Shaneee" in patch["Comment"]:
|
||||||
|
patch["Enabled"] = True
|
||||||
|
|
||||||
|
if not min_supported_macos_version[:2] <= str(macos_version) <= max_supported_macos_version[:2] or not patch["Enabled"]:
|
||||||
|
patches_to_remove.append(index)
|
||||||
|
|
||||||
|
for index in patches_to_remove[::-1]:
|
||||||
|
kernel_patch.pop(index)
|
||||||
|
|
||||||
|
return kernel_patch
|
||||||
|
|
||||||
|
def boot_args(self, motherboard_name, platform, cpu_manufacturer, cpu_codename, discrete_gpu_codename, integrated_gpu_name, ethernet_pci, codec_id, touchpad_communication, unsupported_devices, custom_cpu_name, macos_version):
|
||||||
|
boot_args = [
|
||||||
|
"-v",
|
||||||
|
"debug=0x100",
|
||||||
|
"keepsyms=1"
|
||||||
|
]
|
||||||
|
|
||||||
|
if codec_id in codec_layouts.data:
|
||||||
|
boot_args.append("alcid={}".format(random.choice(codec_layouts.data.get(codec_id))))
|
||||||
|
|
||||||
|
if "AMD" in cpu_manufacturer or self.is_intel_hedt_cpu(cpu_codename):
|
||||||
|
boot_args.append("npci=0x2000")
|
||||||
|
|
||||||
|
if macos_version > 22:
|
||||||
|
boot_args.append("revpatch=sbvmm{}".format(",cpuname" if custom_cpu_name else ""))
|
||||||
|
else:
|
||||||
|
boot_args.append("revpatch=cpuname")
|
||||||
|
|
||||||
|
if not self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, start=13) is None:
|
||||||
|
boot_args.append("-ctrsmt")
|
||||||
|
|
||||||
|
if ethernet_pci in ["8086-15F2", "8086-15F3", "8086-15F8"]:
|
||||||
|
if macos_version == 20:
|
||||||
|
boot_args.append("dk.e1000=0")
|
||||||
|
if macos_version == 21:
|
||||||
|
boot_args.append("e1000=0")
|
||||||
|
|
||||||
|
if "Intel" in cpu_manufacturer:
|
||||||
|
if "Laptop" in platform:
|
||||||
|
if not self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, start=6) is None:
|
||||||
|
boot_args.append("-igfxbl{}".format("t" if macos_version > 22 else "r"))
|
||||||
|
|
||||||
|
if "UHD" in integrated_gpu_name and macos_version > 18:
|
||||||
|
boot_args.append("igfxonln=1")
|
||||||
|
|
||||||
|
if "Ice Lake" in cpu_codename:
|
||||||
|
boot_args += ["-noDC9", "-igfxcdc", "-igfxdvmt", "-igfxdbeo"]
|
||||||
|
else:
|
||||||
|
if "Navi" in discrete_gpu_codename and not "Navi 2" in discrete_gpu_codename:
|
||||||
|
boot_args.append("agdpmod=pikera")
|
||||||
|
elif "UHD" in integrated_gpu_name and macos_version > 18:
|
||||||
|
boot_args.append("igfxonln=1")
|
||||||
|
|
||||||
|
if "Laptop" in platform and not "SURFACE" in motherboard_name and "I2C" in touchpad_communication:
|
||||||
|
boot_args.append("-vi2c-force-polling")
|
||||||
|
|
||||||
|
if macos_version > 23:
|
||||||
|
boot_args.append("-lilubetaall")
|
||||||
|
|
||||||
|
if self.utils.contains_any(unsupported_devices, "Discrete GPU"):
|
||||||
|
boot_args.append("-wegnoegpu")
|
||||||
|
|
||||||
|
return " ".join(boot_args)
|
||||||
|
|
||||||
|
def csr_active_config(self, macos_version):
|
||||||
|
if macos_version > 19:
|
||||||
|
return "03080000"
|
||||||
|
elif macos_version > 17:
|
||||||
|
return "FF070000"
|
||||||
|
else:
|
||||||
|
return "FF030000"
|
||||||
|
|
||||||
|
def load_drivers(self):
|
||||||
|
uefi_drivers = []
|
||||||
|
|
||||||
|
for driver_path in ["OpenCanopy.efi", "OpenHfsPlus.efi", "OpenRuntime.efi", "ResetNvramEntry.efi"]:
|
||||||
|
uefi_drivers.append({
|
||||||
|
"Arguments": "",
|
||||||
|
"Comment": "",
|
||||||
|
"Enabled": True,
|
||||||
|
"LoadEarly": False,
|
||||||
|
"Path": driver_path
|
||||||
|
})
|
||||||
|
|
||||||
|
return uefi_drivers
|
||||||
|
|
||||||
|
def genarate(self, hardware, efi_option, config):
|
||||||
|
del config["#WARNING - 1"]
|
||||||
|
del config["#WARNING - 2"]
|
||||||
|
del config["#WARNING - 3"]
|
||||||
|
del config["#WARNING - 4"]
|
||||||
|
config["ACPI"]["Add"] = efi_option.get("ACPI").get("Add")
|
||||||
|
if not self.is_intel_hedt_cpu(hardware.get("CPU Codename")) and not self.utils.contains_any(cpu_data.IntelCPUGenerations, hardware.get("CPU Codename"), end=2) is None:
|
||||||
|
for item in config["ACPI"]["Delete"]:
|
||||||
|
item.update({
|
||||||
|
"All": True,
|
||||||
|
"Enabled": True
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
config["ACPI"]["Delete"] = []
|
||||||
|
config["ACPI"]["Patch"] = efi_option.get("ACPI").get("Patch")
|
||||||
|
|
||||||
|
config["Booter"]["MmioWhitelist"] = self.mmio_whitelist(hardware.get("CPU Codename"))
|
||||||
|
config["Booter"]["Patch"] = []
|
||||||
|
config["Booter"]["Quirks"]["DevirtualiseMmio"] = self.check_mats_support(hardware.get("CPU Manufacturer"), hardware.get("Motherboard Chipset"), hardware.get("CPU Codename"))
|
||||||
|
if "AMD" in hardware.get("CPU Manufacturer") and not "TRX40" in hardware.get("Motherboard Chipset") or \
|
||||||
|
not "Desktop" in hardware.get("Platform") and "Coffee Lake" in hardware.get("CPU Codename"):
|
||||||
|
config["Booter"]["Quirks"]["DevirtualiseMmio"] = False
|
||||||
|
config["Booter"]["Quirks"]["EnableWriteUnprotector"] = False if "Coffee Lake" in hardware.get("CPU Codename") else False if "AMD" in hardware.get("CPU Manufacturer") else not config["Booter"]["Quirks"]["DevirtualiseMmio"]
|
||||||
|
config["Booter"]["Quirks"]["ProtectUefiServices"] = "Z390" in hardware.get("Motherboard Chipset") or \
|
||||||
|
not self.utils.contains_any(cpu_data.IntelCPUGenerations, hardware.get("CPU Codename"), start=10) is None
|
||||||
|
config["Booter"]["Quirks"]["RebuildAppleMemoryMap"] = not config["Booter"]["Quirks"]["EnableWriteUnprotector"]
|
||||||
|
config["Booter"]["Quirks"]["ResizeAppleGpuBars"] = 0 if self.check_resizable_bar_support(
|
||||||
|
hardware.get("Motherboard Chipset"),
|
||||||
|
hardware.get("Platform"),
|
||||||
|
hardware.get("CPU Codename"),
|
||||||
|
hardware.get("Discrete GPU")
|
||||||
|
) else -1
|
||||||
|
config["Booter"]["Quirks"]["SetupVirtualMap"] = not (not self.utils.contains_any(chipset_data.AMDChipsets, hardware.get("Motherboard Chipset"), end=5) is None or \
|
||||||
|
"ASUS" in hardware.get("Motherboard Name") and self.is_intel_hedt_cpu(hardware.get("CPU Codename")) and config["Booter"]["Quirks"]["DevirtualiseMmio"])
|
||||||
|
config["Booter"]["Quirks"]["SyncRuntimePermissions"] = config["Booter"]["Quirks"]["RebuildAppleMemoryMap"]
|
||||||
|
|
||||||
|
config["DeviceProperties"]["Add"] = self.deviceproperties(hardware.get("CPU Codename"), hardware.get("Intel MEI"), efi_option.get("iGPU Properties"))
|
||||||
|
|
||||||
|
config["Kernel"]["Add"] = efi_option.get("Kernel_Add")
|
||||||
|
config["Kernel"]["Block"] = self.block_kext_bundle(hardware.get("Wi-Fi (PCI)"), efi_option.get("macOS Version"))
|
||||||
|
spoof_cpuid = self.spoof_cpuid(
|
||||||
|
hardware.get("Processor Name"),
|
||||||
|
hardware.get("CPU Codename"),
|
||||||
|
efi_option.get("macOS Version")
|
||||||
|
)
|
||||||
|
if spoof_cpuid:
|
||||||
|
config["Kernel"]["Emulate"]["Cpuid1Data"] = self.utils.hex_to_bytes("{}{}".format(spoof_cpuid, "0"*8*3))
|
||||||
|
config["Kernel"]["Emulate"]["Cpuid1Mask"] = self.utils.hex_to_bytes("FFFFFFFF{}".format("0"*8*3))
|
||||||
|
config["Kernel"]["Emulate"]["DummyPowerManagement"] = "AMD" in hardware.get("CPU Manufacturer") or \
|
||||||
|
self.is_low_end_intel_cpu(hardware.get("Processor Name"))
|
||||||
|
config["Kernel"]["Force"] = []
|
||||||
|
config["Kernel"]["Patch"] = self.load_kernel_patch(
|
||||||
|
hardware.get("Motherboard Chipset"),
|
||||||
|
hardware.get("CPU Manufacturer"),
|
||||||
|
hardware.get("CPU Codename"),
|
||||||
|
hardware["CPU Cores"],
|
||||||
|
hardware["Discrete GPU Manufacturer"] or hardware["Integrated GPU Manufacturer"],
|
||||||
|
efi_option.get("Synchronize the TSC"),
|
||||||
|
efi_option.get("macOS Version"),
|
||||||
|
)
|
||||||
|
config["Kernel"]["Quirks"]["AppleCpuPmCfgLock"] = not self.utils.contains_any(cpu_data.IntelCPUGenerations, hardware.get("CPU Codename"), end=2) is None
|
||||||
|
config["Kernel"]["Quirks"]["AppleXcpmCfgLock"] = False if "AMD" in hardware.get("CPU Manufacturer") else not config["Kernel"]["Quirks"]["AppleCpuPmCfgLock"]
|
||||||
|
config["Kernel"]["Quirks"]["AppleXcpmExtraMsrs"] = self.is_intel_hedt_cpu(hardware.get("CPU Codename")) and not self.utils.contains_any(cpu_data.IntelCPUGenerations, hardware.get("CPU Codename"), end=4) is None
|
||||||
|
config["Kernel"]["Quirks"]["CustomSMBIOSGuid"] = True
|
||||||
|
config["Kernel"]["Quirks"]["DisableIoMapper"] = not "AMD" in hardware.get("CPU Manufacturer")
|
||||||
|
config["Kernel"]["Quirks"]["DisableRtcChecksum"] = "ASUS" in hardware.get("Motherboard Name") or "HP" in hardware.get("Motherboard Name")
|
||||||
|
config["Kernel"]["Quirks"]["LapicKernelPanic"] = "HP" in hardware.get("Motherboard Name")
|
||||||
|
config["Kernel"]["Quirks"]["PanicNoKextDump"] = config["Kernel"]["Quirks"]["PowerTimeoutKernelPanic"] = True
|
||||||
|
config["Kernel"]["Quirks"]["ProvideCurrentCpuInfo"] = "AMD" in hardware.get("CPU Manufacturer") or \
|
||||||
|
not self.utils.contains_any(cpu_data.IntelCPUGenerations, hardware.get("CPU Codename"), start=13) is None
|
||||||
|
config["Kernel"]["Quirks"]["SetApfsTrimTimeout"] = 0 if any(controller_props.get("Device ID").startswith("144D") for controller_name, controller_props in hardware.get("Storage Controllers").items()) else -1
|
||||||
|
|
||||||
|
config["Misc"]["BlessOverride"] = []
|
||||||
|
config["Misc"]["Boot"]["LauncherOption"] = "Full"
|
||||||
|
config["Misc"]["Boot"]["PickerMode"] = "External"
|
||||||
|
config["Misc"]["Boot"]["Timeout"] = 10
|
||||||
|
config["Misc"]["Debug"]["AppleDebug"] = config["Misc"]["Debug"]["ApplePanic"] = False
|
||||||
|
config["Misc"]["Debug"]["DisableWatchDog"] = True
|
||||||
|
config["Misc"]["Debug"]["Target"] = 0
|
||||||
|
config["Misc"]["Entries"] = []
|
||||||
|
config["Misc"]["Security"]["AllowSetDefault"] = True
|
||||||
|
config["Misc"]["Security"]["ScanPolicy"] = 0
|
||||||
|
config["Misc"]["Security"]["SecureBootModel"] = "Default" if 19 < efi_option.get("macOS Version") < 23 else "Disabled"
|
||||||
|
config["Misc"]["Security"]["Vault"] = "Optional"
|
||||||
|
config["Misc"]["Tools"] = []
|
||||||
|
|
||||||
|
if efi_option.get("Custom CPU Name"):
|
||||||
|
config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revcpu"] = 1
|
||||||
|
config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revcpuname"] = hardware.get("Processor Name")
|
||||||
|
del config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["#INFO (prev-lang:kbd)"]
|
||||||
|
config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] = self.boot_args(
|
||||||
|
hardware.get("Motherboard Name"),
|
||||||
|
hardware.get("Platform"),
|
||||||
|
hardware.get("CPU Manufacturer"),
|
||||||
|
hardware.get("CPU Codename"),
|
||||||
|
hardware.get("Discrete GPU Codename"),
|
||||||
|
hardware.get("Integrated GPU Name"),
|
||||||
|
hardware.get("Ethernet (PCI)"),
|
||||||
|
hardware.get("Codec ID"),
|
||||||
|
hardware.get("Touchpad Communication"),
|
||||||
|
hardware.get("Unsupported Devices"),
|
||||||
|
efi_option.get("Custom CPU Name"),
|
||||||
|
efi_option.get("macOS Version")
|
||||||
|
)
|
||||||
|
config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["csr-active-config"] = self.utils.hex_to_bytes(self.csr_active_config(efi_option.get("macOS Version")))
|
||||||
|
config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["prev-lang:kbd"] = "en:252"
|
||||||
|
if efi_option.get("Custom CPU Name"):
|
||||||
|
config["NVRAM"]["Delete"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"].extend(["revcpu", "revcpuname"])
|
||||||
|
|
||||||
|
config["PlatformInfo"]["Generic"].update(self.smbios.generate(efi_option.get("SMBIOS")))
|
||||||
|
if efi_option.get("Custom CPU Name"):
|
||||||
|
config["PlatformInfo"]["Generic"]["ProcessorType"] = 1537 if int(hardware["CPU Cores"]) < 8 else 3841
|
||||||
|
config["PlatformInfo"]["Generic"]["ROM"] = self.utils.hex_to_bytes(config["PlatformInfo"]["Generic"]["ROM"])
|
||||||
|
|
||||||
|
config["UEFI"]["APFS"]["MinDate"] = config["UEFI"]["APFS"]["MinVersion"] = -1
|
||||||
|
config["UEFI"]["Drivers"] = self.load_drivers()
|
||||||
|
config["UEFI"]["Quirks"]["IgnoreInvalidFlexRatio"] = not self.utils.contains_any(cpu_data.IntelCPUGenerations, hardware.get("CPU Codename"), end=4) is None
|
||||||
|
config["UEFI"]["Quirks"]["ReleaseUsbOwnership"] = True
|
||||||
|
config["UEFI"]["Quirks"]["UnblockFsConnect"] = "HP" in hardware.get("Motherboard Name")
|
||||||
|
config["UEFI"]["ReservedMemory"] = []
|
||||||
|
|
||||||
|
return config
|
||||||
161
Scripts/datasets/chipset_data.py
Executable file
161
Scripts/datasets/chipset_data.py
Executable file
@@ -0,0 +1,161 @@
|
|||||||
|
# Resource: https://en.wikipedia.org/wiki/List_of_Intel_chipsets
|
||||||
|
IntelChipsets = [
|
||||||
|
"H61",
|
||||||
|
"B65",
|
||||||
|
"Q65",
|
||||||
|
"P67",
|
||||||
|
"H67",
|
||||||
|
"Q67",
|
||||||
|
"Z68",
|
||||||
|
"HM65",
|
||||||
|
"HM67",
|
||||||
|
"UM67",
|
||||||
|
"QM67",
|
||||||
|
"QS67",
|
||||||
|
"Cougar Point",
|
||||||
|
"B75",
|
||||||
|
"Q75",
|
||||||
|
"Z75",
|
||||||
|
"H77",
|
||||||
|
"Q77",
|
||||||
|
"Z77",
|
||||||
|
"C216",
|
||||||
|
"NM70",
|
||||||
|
"HM70",
|
||||||
|
"HM75",
|
||||||
|
"HM76",
|
||||||
|
"UM77",
|
||||||
|
"HM77",
|
||||||
|
"QM77",
|
||||||
|
"QS77",
|
||||||
|
"X79",
|
||||||
|
"C602",
|
||||||
|
"Panther Point",
|
||||||
|
"Patsburg",
|
||||||
|
"H81",
|
||||||
|
"B85",
|
||||||
|
"Q85",
|
||||||
|
"Q87",
|
||||||
|
"H87",
|
||||||
|
"Z87",
|
||||||
|
"HM86",
|
||||||
|
"QM87",
|
||||||
|
"HM87",
|
||||||
|
"Lynx Point",
|
||||||
|
"H97",
|
||||||
|
"Z97",
|
||||||
|
"HM97",
|
||||||
|
"C612",
|
||||||
|
"X99",
|
||||||
|
"Wildcat Point",
|
||||||
|
"Wellsburg",
|
||||||
|
"X299",
|
||||||
|
"C422",
|
||||||
|
"C621",
|
||||||
|
"C622",
|
||||||
|
"C624",
|
||||||
|
"C625",
|
||||||
|
"C626",
|
||||||
|
"C627",
|
||||||
|
"C628",
|
||||||
|
"Basin Falls",
|
||||||
|
"Lewisburg",
|
||||||
|
"H110",
|
||||||
|
"B150",
|
||||||
|
"Q150",
|
||||||
|
"H170",
|
||||||
|
"Q170",
|
||||||
|
"Z170",
|
||||||
|
"HM170",
|
||||||
|
"QM170",
|
||||||
|
"QMS180",
|
||||||
|
"QMU185",
|
||||||
|
"HM175",
|
||||||
|
"QM175",
|
||||||
|
"B250",
|
||||||
|
"Q250",
|
||||||
|
"H270",
|
||||||
|
"Q270",
|
||||||
|
"Z270",
|
||||||
|
"C232",
|
||||||
|
"C236",
|
||||||
|
"CM236",
|
||||||
|
"CM238",
|
||||||
|
"B365",
|
||||||
|
"Sunrise Point",
|
||||||
|
"Kaby Point",
|
||||||
|
"Union Point",
|
||||||
|
"Z370",
|
||||||
|
"H310",
|
||||||
|
"B360",
|
||||||
|
"H370",
|
||||||
|
"Q370",
|
||||||
|
"Z390",
|
||||||
|
"C242",
|
||||||
|
"C246",
|
||||||
|
"HM370",
|
||||||
|
"QM370",
|
||||||
|
"CM246",
|
||||||
|
"Cannon Point",
|
||||||
|
"H410",
|
||||||
|
"B460",
|
||||||
|
"H470",
|
||||||
|
"Q470",
|
||||||
|
"Z490",
|
||||||
|
"W480",
|
||||||
|
"H420E",
|
||||||
|
"Q470E",
|
||||||
|
"W480E",
|
||||||
|
"HM470",
|
||||||
|
"QM480",
|
||||||
|
"WM490",
|
||||||
|
"Comet Point",
|
||||||
|
"H510",
|
||||||
|
"B560",
|
||||||
|
"H570",
|
||||||
|
"Z590",
|
||||||
|
"W580",
|
||||||
|
"HM570E",
|
||||||
|
"QM580E",
|
||||||
|
"RM590E",
|
||||||
|
"HM570",
|
||||||
|
"QM580",
|
||||||
|
"WM590",
|
||||||
|
"Tiger Point",
|
||||||
|
"495",
|
||||||
|
"Ice Point",
|
||||||
|
"Ice Lake",
|
||||||
|
"Z690",
|
||||||
|
"W680",
|
||||||
|
"Q670",
|
||||||
|
"H670",
|
||||||
|
"B660",
|
||||||
|
"H610",
|
||||||
|
"R680E",
|
||||||
|
"Q670E",
|
||||||
|
"H610E",
|
||||||
|
"HM670",
|
||||||
|
"WM690",
|
||||||
|
"Alder Point",
|
||||||
|
"Z790",
|
||||||
|
"H770",
|
||||||
|
"B760",
|
||||||
|
"HM770",
|
||||||
|
"WM790",
|
||||||
|
"Raptor Point",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Resource: https://en.wikipedia.org/wiki/List_of_AMD_chipsets
|
||||||
|
AMDChipsets = [
|
||||||
|
"TRX40",
|
||||||
|
"B450",
|
||||||
|
"X470",
|
||||||
|
"A520",
|
||||||
|
"B550",
|
||||||
|
"X570",
|
||||||
|
"A620",
|
||||||
|
"B650",
|
||||||
|
"X670",
|
||||||
|
"X870"
|
||||||
|
]
|
||||||
|
|
||||||
43
Scripts/datasets/cpu_data.py
Executable file
43
Scripts/datasets/cpu_data.py
Executable file
@@ -0,0 +1,43 @@
|
|||||||
|
AMDCPUGenerations = [
|
||||||
|
"Summit Ridge",
|
||||||
|
"Raven Ridge",
|
||||||
|
"Pinnacle Ridge",
|
||||||
|
"Dalí",
|
||||||
|
"Picasso",
|
||||||
|
"Matisse",
|
||||||
|
"Renoir",
|
||||||
|
"Lucienne",
|
||||||
|
"Vermeer",
|
||||||
|
"Cezanne",
|
||||||
|
"Barcelo",
|
||||||
|
"Rembrandt",
|
||||||
|
"Raphael",
|
||||||
|
"Mendocino",
|
||||||
|
"Phoenix",
|
||||||
|
"Dragon Range",
|
||||||
|
"Hawk Point",
|
||||||
|
"Granite Ridge",
|
||||||
|
"Whitehaven",
|
||||||
|
"Colfax",
|
||||||
|
"Castle Peak",
|
||||||
|
"Chagall",
|
||||||
|
"Storm Peak"
|
||||||
|
]
|
||||||
|
|
||||||
|
IntelCPUGenerations = [
|
||||||
|
"Sandy Bridge",
|
||||||
|
"Ivy Bridge",
|
||||||
|
"Haswell",
|
||||||
|
"Broadwell",
|
||||||
|
"Skylake",
|
||||||
|
"Cascade Lake",
|
||||||
|
"Kaby Lake",
|
||||||
|
"Amber Lake",
|
||||||
|
"Whiskey Lake",
|
||||||
|
"Coffee Lake",
|
||||||
|
"Comet Lake",
|
||||||
|
"Ice Lake",
|
||||||
|
"Rocket Lake",
|
||||||
|
"Alder Lake",
|
||||||
|
"Raptor Lake"
|
||||||
|
]
|
||||||
1157
Scripts/datasets/pci_data.py
Executable file
1157
Scripts/datasets/pci_data.py
Executable file
File diff suppressed because it is too large
Load Diff
728
Scripts/dsdt.py
Executable file
728
Scripts/dsdt.py
Executable file
@@ -0,0 +1,728 @@
|
|||||||
|
# Original source:
|
||||||
|
# https://github.com/corpnewt/SSDTTime/blob/7b3fb78112bf320a1bc6a7e50dddb2b375cb70b0/Scripts/dsdt.py
|
||||||
|
|
||||||
|
import os, errno, tempfile, shutil, plistlib, sys, binascii, zipfile, getpass, re
|
||||||
|
from Scripts import resource_fetcher
|
||||||
|
from Scripts import run
|
||||||
|
from Scripts import utils
|
||||||
|
|
||||||
|
class DSDT:
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
#self.dl = downloader.Downloader()
|
||||||
|
self.fetcher = resource_fetcher.ResourceFetcher()
|
||||||
|
self.r = run.Run()
|
||||||
|
#self.u = utils.Utils("SSDT Time")
|
||||||
|
self.u = utils.Utils()
|
||||||
|
self.iasl_url_macOS = "https://raw.githubusercontent.com/acidanthera/MaciASL/master/Dist/iasl-stable"
|
||||||
|
self.iasl_url_macOS_legacy = "https://raw.githubusercontent.com/acidanthera/MaciASL/master/Dist/iasl-legacy"
|
||||||
|
self.iasl_url_linux = "https://raw.githubusercontent.com/corpnewt/linux_iasl/main/iasl.zip"
|
||||||
|
self.iasl_url_linux_legacy = "https://raw.githubusercontent.com/corpnewt/iasl-legacy/main/iasl-legacy-linux.zip"
|
||||||
|
self.acpi_binary_tools = "https://www.intel.com/content/www/us/en/developer/topic-technology/open/acpica/download.html"
|
||||||
|
self.iasl_url_windows_legacy = "https://raw.githubusercontent.com/corpnewt/iasl-legacy/main/iasl-legacy-windows.zip"
|
||||||
|
self.h = {} # {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
|
||||||
|
self.iasl = self.check_iasl()
|
||||||
|
#self.iasl_legacy = self.check_iasl(legacy=True)
|
||||||
|
if not self.iasl:
|
||||||
|
url = self.acpi_binary_tools if os.name=="nt" else \
|
||||||
|
self.iasl_url_macOS if sys.platform=="darwin" else \
|
||||||
|
self.iasl_url_linux if sys.platform.startswith("linux") else None
|
||||||
|
exception = "Could not locate or download iasl!"
|
||||||
|
if url:
|
||||||
|
exception += "\n\nPlease manually download {} from:\n - {}\n\nAnd place in:\n - {}\n".format(
|
||||||
|
"and extract iasl.exe and acpidump.exe" if os.name=="nt" else "iasl",
|
||||||
|
url,
|
||||||
|
os.path.dirname(os.path.realpath(__file__))
|
||||||
|
)
|
||||||
|
raise Exception(exception)
|
||||||
|
self.allowed_signatures = ("APIC","DMAR","DSDT","SSDT")
|
||||||
|
self.mixed_listing = ("DSDT","SSDT")
|
||||||
|
self.acpi_tables = {}
|
||||||
|
# Setup regex matches
|
||||||
|
self.hex_match = re.compile(r"^\s*[0-9A-F]{4,}:(\s[0-9A-F]{2})+(\s+\/\/.*)?$")
|
||||||
|
self.type_match = re.compile(r".*(?P<type>Processor|Scope|Device|Method|Name) \((?P<name>[^,\)]+).*")
|
||||||
|
|
||||||
|
def _table_name_is_valid(self, table_name):
|
||||||
|
if table_name.startswith(".") or not table_name.lower().endswith(self.table_suffixes):
|
||||||
|
return False
|
||||||
|
if not table_name.lower().startswith(self.table_prefixes):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _table_signature(self, table_path, table_name = None):
|
||||||
|
path = os.path.join(table_path,table_name) if table_name else table_path
|
||||||
|
if not os.path.isfile(path):
|
||||||
|
return None
|
||||||
|
# Try to load it and read the first 4 bytes to verify the
|
||||||
|
# signature
|
||||||
|
with open(path,"rb") as f:
|
||||||
|
try:
|
||||||
|
sig = f.read(4)
|
||||||
|
if 2/3!=0: sig = sig.decode()
|
||||||
|
return sig
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
def table_is_valid(self, table_path, table_name = None):
|
||||||
|
return self._table_signature(table_path,table_name=table_name) in self.allowed_signatures
|
||||||
|
|
||||||
|
def load(self, table_path):
|
||||||
|
# Attempt to load the passed file - or if a directory
|
||||||
|
# was passed, load all .aml and .dat files within
|
||||||
|
cwd = os.getcwd()
|
||||||
|
temp = None
|
||||||
|
target_files = {}
|
||||||
|
failed = []
|
||||||
|
try:
|
||||||
|
if os.path.isdir(table_path):
|
||||||
|
# Got a directory - gather all files
|
||||||
|
# Gather valid files in the directory
|
||||||
|
valid_files = [x for x in os.listdir(table_path) if self.table_is_valid(table_path,x)]
|
||||||
|
elif os.path.isfile(table_path):
|
||||||
|
# Just loading the one table
|
||||||
|
valid_files = [table_path]
|
||||||
|
else:
|
||||||
|
# Not a valid path
|
||||||
|
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), table_path)
|
||||||
|
if not valid_files:
|
||||||
|
# No valid files were found
|
||||||
|
raise FileNotFoundError(
|
||||||
|
errno.ENOENT,
|
||||||
|
os.strerror(errno.ENOENT),
|
||||||
|
"No valid .aml/.dat files found at {}".format(table_path)
|
||||||
|
)
|
||||||
|
# Create a temp dir and copy all files there
|
||||||
|
temp = tempfile.mkdtemp()
|
||||||
|
for file in valid_files:
|
||||||
|
shutil.copy(
|
||||||
|
os.path.join(table_path,file),
|
||||||
|
temp
|
||||||
|
)
|
||||||
|
# Build a list of all target files in the temp folder - and save
|
||||||
|
# the disassembled_name for each to verify after
|
||||||
|
list_dir = os.listdir(temp)
|
||||||
|
for x in list_dir:
|
||||||
|
if len(list_dir) > 1 and not self.table_is_valid(temp,x):
|
||||||
|
continue # Skip invalid files when multiple are passed
|
||||||
|
name_ext = [y for y in os.path.basename(x).split(".") if y]
|
||||||
|
if name_ext and name_ext[-1].lower() in ("asl","dsl"):
|
||||||
|
continue # Skip any already disassembled files
|
||||||
|
target_files[x] = {
|
||||||
|
"assembled_name": os.path.basename(x),
|
||||||
|
"disassembled_name": ".".join(x.split(".")[:-1]) + ".dsl",
|
||||||
|
}
|
||||||
|
if not target_files:
|
||||||
|
# Somehow we ended up with none?
|
||||||
|
raise FileNotFoundError(
|
||||||
|
errno.ENOENT,
|
||||||
|
os.strerror(errno.ENOENT),
|
||||||
|
"No valid .aml/.dat files found at {}".format(table_path)
|
||||||
|
)
|
||||||
|
os.chdir(temp)
|
||||||
|
# Generate and run a command
|
||||||
|
dsdt_or_ssdt = [x for x in list(target_files) if self._table_signature(temp,x) in self.mixed_listing]
|
||||||
|
other_tables = [x for x in list(target_files) if not x in dsdt_or_ssdt]
|
||||||
|
out_d = ("","",0)
|
||||||
|
out_t = ("","",0)
|
||||||
|
|
||||||
|
def exists(folder_path,file_name):
|
||||||
|
# Helper to make sure the file exists and has a non-Zero size
|
||||||
|
check_path = os.path.join(folder_path,file_name)
|
||||||
|
if os.path.isfile(check_path) and os.stat(check_path).st_size > 0:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Check our DSDT and SSDTs first
|
||||||
|
if dsdt_or_ssdt:
|
||||||
|
args = [self.iasl,"-da","-dl","-l"]+list(dsdt_or_ssdt)
|
||||||
|
out_d = self.r.run({"args":args})
|
||||||
|
if out_d[2] != 0:
|
||||||
|
# Attempt to run without `-da` if the above failed
|
||||||
|
args = [self.iasl,"-dl","-l"]+list(dsdt_or_ssdt)
|
||||||
|
out_d = self.r.run({"args":args})
|
||||||
|
# Get a list of disassembled names that failed
|
||||||
|
fail_temp = []
|
||||||
|
for x in dsdt_or_ssdt:
|
||||||
|
if not exists(temp,target_files[x]["disassembled_name"]):
|
||||||
|
fail_temp.append(x)
|
||||||
|
# Let's try to disassemble any that failed individually
|
||||||
|
for x in fail_temp:
|
||||||
|
args = [self.iasl,"-dl","-l",x]
|
||||||
|
self.r.run({"args":args})
|
||||||
|
if not exists(temp,target_files[x]["disassembled_name"]):
|
||||||
|
failed.append(x)
|
||||||
|
# Check for other tables (DMAR, APIC, etc)
|
||||||
|
if other_tables:
|
||||||
|
args = [self.iasl]+list(other_tables)
|
||||||
|
out_t = self.r.run({"args":args})
|
||||||
|
# Get a list of disassembled names that failed
|
||||||
|
for x in other_tables:
|
||||||
|
if not exists(temp,target_files[x]["disassembled_name"]):
|
||||||
|
failed.append(x)
|
||||||
|
if len(failed) == len(target_files):
|
||||||
|
raise Exception("Failed to disassemble - {}".format(", ".join(failed)))
|
||||||
|
# Actually process the tables now
|
||||||
|
to_remove = []
|
||||||
|
for file in target_files:
|
||||||
|
# We need to load the .aml and .dsl into memory
|
||||||
|
# and get the paths and scopes
|
||||||
|
if not exists(temp,target_files[file]["disassembled_name"]):
|
||||||
|
to_remove.append(file)
|
||||||
|
continue
|
||||||
|
with open(os.path.join(temp,target_files[file]["disassembled_name"]),"r") as f:
|
||||||
|
target_files[file]["table"] = f.read()
|
||||||
|
# Remove the compiler info at the start
|
||||||
|
if target_files[file]["table"].startswith("/*"):
|
||||||
|
target_files[file]["table"] = "*/".join(target_files[file]["table"].split("*/")[1:]).strip()
|
||||||
|
# Check for "Table Header:" or "Raw Table Data: Length" and strip everything
|
||||||
|
# after the last occurrence
|
||||||
|
for h in ("\nTable Header:","\nRaw Table Data: Length"):
|
||||||
|
if h in target_files[file]["table"]:
|
||||||
|
target_files[file]["table"] = h.join(target_files[file]["table"].split(h)[:-1]).rstrip()
|
||||||
|
break # Bail on the first match
|
||||||
|
target_files[file]["lines"] = target_files[file]["table"].split("\n")
|
||||||
|
target_files[file]["scopes"] = self.get_scopes(table=target_files[file])
|
||||||
|
target_files[file]["paths"] = self.get_paths(table=target_files[file])
|
||||||
|
with open(os.path.join(temp,file),"rb") as f:
|
||||||
|
table_bytes = f.read()
|
||||||
|
target_files[file]["raw"] = table_bytes
|
||||||
|
# Let's read the table header and get the info we need
|
||||||
|
#
|
||||||
|
# [0:4] = Table Signature
|
||||||
|
# [4:8] = Length (little endian)
|
||||||
|
# [8] = Compliance Revision
|
||||||
|
# [9] = Checksum
|
||||||
|
# [10:16] = OEM ID (6 chars, padded to the right with \x00)
|
||||||
|
# [16:24] = Table ID (8 chars, padded to the right with \x00)
|
||||||
|
# [24:28] = OEM Revision (little endian)
|
||||||
|
#
|
||||||
|
target_files[file]["signature"] = table_bytes[0:4]
|
||||||
|
target_files[file]["revision"] = table_bytes[8]
|
||||||
|
target_files[file]["oem"] = table_bytes[10:16].rstrip(b"\x00")
|
||||||
|
target_files[file]["id"] = table_bytes[16:24].rstrip(b"\x00")
|
||||||
|
target_files[file]["oem_revision"] = int(binascii.hexlify(table_bytes[24:28][::-1]),16)
|
||||||
|
# Cast as int on py2, and decode bytes to strings on py3
|
||||||
|
if 2/3==0:
|
||||||
|
target_files[file]["revision"] = int(binascii.hexlify(target_files[file]["revision"]),16)
|
||||||
|
else:
|
||||||
|
for key in ("signature","oem","id"):
|
||||||
|
target_files[file][key] = target_files[file][key].decode()
|
||||||
|
# The disassembler omits the last line of hex data in a mixed listing
|
||||||
|
# file... convenient. However - we should be able to reconstruct this
|
||||||
|
# manually.
|
||||||
|
last_hex = next((l for l in target_files[file]["lines"][::-1] if self.is_hex(l)),None)
|
||||||
|
if last_hex:
|
||||||
|
# Get the address left of the colon
|
||||||
|
addr = int(last_hex.split(":")[0].strip(),16)
|
||||||
|
# Get the hex bytes right of the colon
|
||||||
|
hexs = last_hex.split(":")[1].split("//")[0].strip()
|
||||||
|
# Increment the address by the number of hex bytes
|
||||||
|
next_addr = addr+len(hexs.split())
|
||||||
|
# Now we need to get the bytes at the end
|
||||||
|
hexb = self.get_hex_bytes(hexs.replace(" ",""))
|
||||||
|
# Get the last occurrence after the split
|
||||||
|
remaining = target_files[file]["raw"].split(hexb)[-1]
|
||||||
|
# Iterate in chunks of 16
|
||||||
|
for chunk in [remaining[i:i+16] for i in range(0,len(remaining),16)]:
|
||||||
|
# Build a new byte string
|
||||||
|
hex_string = binascii.hexlify(chunk)
|
||||||
|
# Decode the bytes if we're on python 3
|
||||||
|
if 2/3!=0: hex_string = hex_string.decode()
|
||||||
|
# Ensure the bytes are all upper case
|
||||||
|
hex_string = hex_string.upper()
|
||||||
|
l = " {}: {}".format(
|
||||||
|
hex(next_addr)[2:].upper().rjust(4,"0"),
|
||||||
|
" ".join([hex_string[i:i+2] for i in range(0,len(hex_string),2)])
|
||||||
|
)
|
||||||
|
# Increment our address
|
||||||
|
next_addr += len(chunk)
|
||||||
|
# Append our line
|
||||||
|
target_files[file]["lines"].append(l)
|
||||||
|
target_files[file]["table"] += "\n"+l
|
||||||
|
# Remove any that didn't disassemble
|
||||||
|
for file in to_remove:
|
||||||
|
target_files.pop(file,None)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return ({},failed)
|
||||||
|
finally:
|
||||||
|
os.chdir(cwd)
|
||||||
|
if temp: shutil.rmtree(temp,ignore_errors=True)
|
||||||
|
# Add/update any tables we loaded
|
||||||
|
for table in target_files:
|
||||||
|
self.acpi_tables[table] = target_files[table]
|
||||||
|
# Only return the newly loaded results
|
||||||
|
return (target_files, failed,)
|
||||||
|
|
||||||
|
def get_latest_iasl(self):
|
||||||
|
# Helper to scrape https://www.intel.com/content/www/us/en/developer/topic-technology/open/acpica/download.html for the latest
|
||||||
|
# download binaries link - then scrape the contents of that page for the actual download
|
||||||
|
try:
|
||||||
|
#source = self.dl.get_string(self.acpi_binary_tools, headers=self.h)
|
||||||
|
source = self.fetcher.fetch_and_parse_content(self.acpi_binary_tools)
|
||||||
|
for line in source.split("\n"):
|
||||||
|
# <a href="/content/www/us/en/download/774881/acpi-component-architecture-downloads-windows-binary-tools.html">iASL Compiler and Windows ACPI Tools
|
||||||
|
if "windows-binary-tools" in line and ">iasl compiler and windows acpi tools" in line.lower():
|
||||||
|
# Try to scrape and load the next page
|
||||||
|
try:
|
||||||
|
dl_page_url = "https://www.intel.com" + line.split('<a href="')[1].split('"')[0]
|
||||||
|
#dl_page_source = self.dl.get_string(dl_page_url, headers=self.h)
|
||||||
|
dl_page_source = self.fetcher.fetch_and_parse_content(dl_page_url)
|
||||||
|
for line in dl_page_source.split("\n"):
|
||||||
|
if '"download-button"' in line: # Should have the right line
|
||||||
|
return line.split('data-href="')[1].split('"')[0]
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
except: pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
def check_iasl(self, legacy=False, try_downloading=True):
|
||||||
|
if sys.platform == "win32":
|
||||||
|
targets = (os.path.join(os.path.dirname(os.path.realpath(__file__)), "iasl-legacy.exe" if legacy else "iasl.exe"),)
|
||||||
|
else:
|
||||||
|
if legacy:
|
||||||
|
targets = (os.path.join(os.path.dirname(os.path.realpath(__file__)), "iasl-legacy"),)
|
||||||
|
else:
|
||||||
|
targets = (
|
||||||
|
os.path.join(os.path.dirname(os.path.realpath(__file__)), "iasl-dev"),
|
||||||
|
os.path.join(os.path.dirname(os.path.realpath(__file__)), "iasl-stable"),
|
||||||
|
os.path.join(os.path.dirname(os.path.realpath(__file__)), "iasl")
|
||||||
|
)
|
||||||
|
target = next((t for t in targets if os.path.exists(t)),None)
|
||||||
|
if target or not try_downloading:
|
||||||
|
# Either found it - or we didn't, and have already tried downloading
|
||||||
|
return target
|
||||||
|
# Need to download
|
||||||
|
temp = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
if sys.platform == "darwin":
|
||||||
|
self._download_and_extract(temp,self.iasl_url_macOS_legacy if legacy else self.iasl_url_macOS)
|
||||||
|
elif sys.platform.startswith("linux"):
|
||||||
|
self._download_and_extract(temp,self.iasl_url_linux_legacy if legacy else self.iasl_url_linux)
|
||||||
|
elif sys.platform == "win32":
|
||||||
|
iasl_url_windows = self.iasl_url_windows_legacy if legacy else self.get_latest_iasl()
|
||||||
|
if not iasl_url_windows: raise Exception("Could not get latest iasl for Windows")
|
||||||
|
self._download_and_extract(temp,iasl_url_windows)
|
||||||
|
else:
|
||||||
|
raise Exception("Unknown OS")
|
||||||
|
except Exception as e:
|
||||||
|
print("An error occurred :(\n - {}".format(e))
|
||||||
|
shutil.rmtree(temp, ignore_errors=True)
|
||||||
|
# Check again after downloading
|
||||||
|
return self.check_iasl(legacy=legacy,try_downloading=False)
|
||||||
|
|
||||||
|
def _download_and_extract(self, temp, url):
|
||||||
|
self.u.head("Gathering Files")
|
||||||
|
print("")
|
||||||
|
print("Please wait for download iasl...")
|
||||||
|
print("")
|
||||||
|
ztemp = tempfile.mkdtemp(dir=temp)
|
||||||
|
zfile = os.path.basename(url)
|
||||||
|
#print("Downloading {}".format(os.path.basename(url)))
|
||||||
|
#self.dl.stream_to_file(url, os.path.join(ztemp,zfile), progress=False, headers=self.h)
|
||||||
|
self.fetcher.download_and_save_file(url, os.path.join(ztemp,zfile), False)
|
||||||
|
search_dir = ztemp
|
||||||
|
if zfile.lower().endswith(".zip"):
|
||||||
|
print(" - Extracting")
|
||||||
|
search_dir = tempfile.mkdtemp(dir=temp)
|
||||||
|
# Extract with built-in tools \o/
|
||||||
|
with zipfile.ZipFile(os.path.join(ztemp,zfile)) as z:
|
||||||
|
z.extractall(search_dir)
|
||||||
|
script_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)))
|
||||||
|
for x in os.listdir(search_dir):
|
||||||
|
if x.lower().startswith(("iasl","acpidump")):
|
||||||
|
# Found one
|
||||||
|
print(" - Found {}".format(x))
|
||||||
|
if sys.platform != "win32":
|
||||||
|
print(" - Chmod +x")
|
||||||
|
self.r.run({"args":["chmod","+x",os.path.join(search_dir,x)]})
|
||||||
|
print(" - Copying to {} directory".format(os.path.basename(script_dir)))
|
||||||
|
shutil.copy(os.path.join(search_dir,x), os.path.join(script_dir,x))
|
||||||
|
|
||||||
|
def dump_tables(self, output, disassemble=False):
|
||||||
|
# Helper to dump all ACPI tables to the specified
|
||||||
|
# output path
|
||||||
|
self.u.head("Dumping ACPI Tables")
|
||||||
|
print("")
|
||||||
|
res = self.check_output(output)
|
||||||
|
if os.name == "nt":
|
||||||
|
target = os.path.join(os.path.dirname(os.path.realpath(__file__)),"acpidump.exe")
|
||||||
|
if os.path.exists(target):
|
||||||
|
# Dump to the target folder
|
||||||
|
print("Dumping tables to {}...".format(res))
|
||||||
|
cwd = os.getcwd()
|
||||||
|
os.chdir(res)
|
||||||
|
out = self.r.run({"args":[target, "-b"]})
|
||||||
|
os.chdir(cwd)
|
||||||
|
if out[2] != 0:
|
||||||
|
print(" - {}".format(out[1]))
|
||||||
|
return
|
||||||
|
# Iterate the dumped files and ensure the names are uppercase, and the
|
||||||
|
# extension used is .aml, not the default .dat
|
||||||
|
print("Updating names...")
|
||||||
|
for f in os.listdir(res):
|
||||||
|
new_name = f.upper()
|
||||||
|
if new_name.endswith(".DAT"):
|
||||||
|
new_name = new_name[:-4]+".aml"
|
||||||
|
if new_name != f:
|
||||||
|
# Something changed - print it and rename it
|
||||||
|
try:
|
||||||
|
os.rename(os.path.join(res,f),os.path.join(res,new_name))
|
||||||
|
except Exception as e:
|
||||||
|
print(" - {} -> {} failed: {}".format(f,new_name,e))
|
||||||
|
print("Dump successful!")
|
||||||
|
if disassemble:
|
||||||
|
return self.load(res)
|
||||||
|
return res
|
||||||
|
else:
|
||||||
|
print("Failed to locate acpidump.exe")
|
||||||
|
return
|
||||||
|
elif sys.platform.startswith("linux"):
|
||||||
|
table_dir = "/sys/firmware/acpi/tables"
|
||||||
|
if not os.path.isdir(table_dir):
|
||||||
|
print("Could not locate {}!".format(table_dir))
|
||||||
|
return
|
||||||
|
print("Copying tables to {}...".format(res))
|
||||||
|
copied_files = []
|
||||||
|
for table in os.listdir(table_dir):
|
||||||
|
if not os.path.isfile(os.path.join(table_dir,table)):
|
||||||
|
continue # We only want files
|
||||||
|
target_path = os.path.join(res,table.upper()+".aml")
|
||||||
|
out = self.r.run({"args":["sudo","cp",os.path.join(table_dir,table),target_path]})
|
||||||
|
if out[2] != 0:
|
||||||
|
print(" - {}".format(out[1]))
|
||||||
|
return
|
||||||
|
out = self.r.run({"args":["sudo","chown",getpass.getuser(), target_path]})
|
||||||
|
if out[2] != 0:
|
||||||
|
print(" - {}".format(out[1]))
|
||||||
|
return
|
||||||
|
print("Dump successful!")
|
||||||
|
if disassemble:
|
||||||
|
return self.load(res)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def check_output(self, output):
|
||||||
|
t_folder = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), output)
|
||||||
|
if not os.path.isdir(t_folder):
|
||||||
|
os.makedirs(t_folder)
|
||||||
|
return t_folder
|
||||||
|
|
||||||
|
def get_hex_from_int(self, total, pad_to = 4):
|
||||||
|
hex_str = hex(total)[2:].upper().rjust(pad_to,"0")
|
||||||
|
return "".join([hex_str[i:i + 2] for i in range(0, len(hex_str), 2)][::-1])
|
||||||
|
|
||||||
|
def get_hex(self, line):
|
||||||
|
# strip the header and commented end
|
||||||
|
return line.split(":")[1].split("//")[0].replace(" ","")
|
||||||
|
|
||||||
|
def get_line(self, line):
|
||||||
|
# Strip the header and commented end - no space replacing though
|
||||||
|
line = line.split("//")[0]
|
||||||
|
if ":" in line:
|
||||||
|
return line.split(":")[1]
|
||||||
|
return line
|
||||||
|
|
||||||
|
def get_hex_bytes(self, line):
|
||||||
|
return binascii.unhexlify(line)
|
||||||
|
|
||||||
|
def get_table_with_id(self, table_id):
|
||||||
|
return next((v for k,v in self.acpi_tables.items() if table_id == v.get("id")),None)
|
||||||
|
|
||||||
|
def get_table_with_signature(self, table_sig):
|
||||||
|
return next((v for k,v in self.acpi_tables.items() if table_sig == v.get("signature")),None)
|
||||||
|
|
||||||
|
def get_table(self, table_id_or_sig):
|
||||||
|
return next((v for k,v in self.acpi_tables.items() if table_id_or_sig in (v.get("signature"),v.get("id"))),None)
|
||||||
|
|
||||||
|
def get_dsdt(self):
|
||||||
|
return self.get_table_with_signature("DSDT")
|
||||||
|
|
||||||
|
def get_dsdt_or_only(self):
|
||||||
|
dsdt = self.get_dsdt()
|
||||||
|
if dsdt: return dsdt
|
||||||
|
# Make sure we have only one table
|
||||||
|
if len(self.acpi_tables) != 1:
|
||||||
|
return None
|
||||||
|
return list(self.acpi_tables.values())[0]
|
||||||
|
|
||||||
|
def find_previous_hex(self, index=0, table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: return ("",-1,-1)
|
||||||
|
# Returns the index of the previous set of hex digits before the passed index
|
||||||
|
start_index = -1
|
||||||
|
end_index = -1
|
||||||
|
old_hex = True
|
||||||
|
for i,line in enumerate(table.get("lines","")[index::-1]):
|
||||||
|
if old_hex:
|
||||||
|
if not self.is_hex(line):
|
||||||
|
# Broke out of the old hex
|
||||||
|
old_hex = False
|
||||||
|
continue
|
||||||
|
# Not old_hex territory - check if we got new hex
|
||||||
|
if self.is_hex(line): # Checks for a :, but not in comments
|
||||||
|
end_index = index-i
|
||||||
|
hex_text,start_index = self.get_hex_ending_at(end_index,table=table)
|
||||||
|
return (hex_text, start_index, end_index)
|
||||||
|
return ("",start_index,end_index)
|
||||||
|
|
||||||
|
def find_next_hex(self, index=0, table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: return ("",-1,-1)
|
||||||
|
# Returns the index of the next set of hex digits after the passed index
|
||||||
|
start_index = -1
|
||||||
|
end_index = -1
|
||||||
|
old_hex = True
|
||||||
|
for i,line in enumerate(table.get("lines","")[index:]):
|
||||||
|
if old_hex:
|
||||||
|
if not self.is_hex(line):
|
||||||
|
# Broke out of the old hex
|
||||||
|
old_hex = False
|
||||||
|
continue
|
||||||
|
# Not old_hex territory - check if we got new hex
|
||||||
|
if self.is_hex(line): # Checks for a :, but not in comments
|
||||||
|
start_index = i+index
|
||||||
|
hex_text,end_index = self.get_hex_starting_at(start_index,table=table)
|
||||||
|
return (hex_text, start_index, end_index)
|
||||||
|
return ("",start_index,end_index)
|
||||||
|
|
||||||
|
def is_hex(self, line):
|
||||||
|
return self.hex_match.match(line) is not None
|
||||||
|
|
||||||
|
def get_hex_starting_at(self, start_index, table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: return ("",-1)
|
||||||
|
# Returns a tuple of the hex, and the ending index
|
||||||
|
hex_text = ""
|
||||||
|
index = -1
|
||||||
|
for i,x in enumerate(table.get("lines","")[start_index:]):
|
||||||
|
if not self.is_hex(x):
|
||||||
|
break
|
||||||
|
hex_text += self.get_hex(x)
|
||||||
|
index = i+start_index
|
||||||
|
return (hex_text, index)
|
||||||
|
|
||||||
|
def get_hex_ending_at(self, start_index, table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: return ("",-1)
|
||||||
|
# Returns a tuple of the hex, and the ending index
|
||||||
|
hex_text = ""
|
||||||
|
index = -1
|
||||||
|
for i,x in enumerate(table.get("lines","")[start_index::-1]):
|
||||||
|
if not self.is_hex(x):
|
||||||
|
break
|
||||||
|
hex_text = self.get_hex(x)+hex_text
|
||||||
|
index = start_index-i
|
||||||
|
return (hex_text, index)
|
||||||
|
|
||||||
|
def get_shortest_unique_pad(self, current_hex, index, instance=0, table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: return None
|
||||||
|
try: left_pad = self.get_unique_pad(current_hex, index, False, instance, table=table)
|
||||||
|
except: left_pad = None
|
||||||
|
try: right_pad = self.get_unique_pad(current_hex, index, True, instance, table=table)
|
||||||
|
except: right_pad = None
|
||||||
|
try: mid_pad = self.get_unique_pad(current_hex, index, None, instance, table=table)
|
||||||
|
except: mid_pad = None
|
||||||
|
if left_pad == right_pad == mid_pad is None: raise Exception("No unique pad found!")
|
||||||
|
# We got at least one unique pad
|
||||||
|
min_pad = None
|
||||||
|
for x in (left_pad,right_pad,mid_pad):
|
||||||
|
if x is None: continue # Skip
|
||||||
|
if min_pad is None or len(x[0]+x[1]) < len(min_pad[0]+min_pad[1]):
|
||||||
|
min_pad = x
|
||||||
|
return min_pad
|
||||||
|
|
||||||
|
def get_unique_pad(self, current_hex, index, direction=None, instance=0, table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: raise Exception("No valid table passed!")
|
||||||
|
# Returns any pad needed to make the passed patch unique
|
||||||
|
# direction can be True = forward, False = backward, None = both
|
||||||
|
start_index = index
|
||||||
|
line,last_index = self.get_hex_starting_at(index,table=table)
|
||||||
|
if not current_hex in line:
|
||||||
|
raise Exception("{} not found in table at index {}-{}!".format(current_hex,start_index,last_index))
|
||||||
|
padl = padr = ""
|
||||||
|
parts = line.split(current_hex)
|
||||||
|
if instance >= len(parts)-1:
|
||||||
|
raise Exception("Instance out of range!")
|
||||||
|
linel = current_hex.join(parts[0:instance+1])
|
||||||
|
liner = current_hex.join(parts[instance+1:])
|
||||||
|
last_check = True # Default to forward
|
||||||
|
while True:
|
||||||
|
# Check if our hex string is unique
|
||||||
|
check_bytes = self.get_hex_bytes(padl+current_hex+padr)
|
||||||
|
if table["raw"].count(check_bytes) == 1: # Got it!
|
||||||
|
break
|
||||||
|
if direction == True or (direction is None and len(padr)<=len(padl)):
|
||||||
|
# Let's check a forward byte
|
||||||
|
if not len(liner):
|
||||||
|
# Need to grab more
|
||||||
|
liner, _index, last_index = self.find_next_hex(last_index, table=table)
|
||||||
|
if last_index == -1: raise Exception("Hit end of file before unique hex was found!")
|
||||||
|
padr = padr+liner[0:2]
|
||||||
|
liner = liner[2:]
|
||||||
|
continue
|
||||||
|
if direction == False or (direction is None and len(padl)<=len(padr)):
|
||||||
|
# Let's check a backward byte
|
||||||
|
if not len(linel):
|
||||||
|
# Need to grab more
|
||||||
|
linel, start_index, _index = self.find_previous_hex(start_index, table=table)
|
||||||
|
if _index == -1: raise Exception("Hit end of file before unique hex was found!")
|
||||||
|
padl = linel[-2:]+padl
|
||||||
|
linel = linel[:-2]
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
return (padl,padr)
|
||||||
|
|
||||||
|
def get_devices(self,search=None,types=("Device (","Scope ("),strip_comments=False,table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: return []
|
||||||
|
# Returns a list of tuples organized as (Device/Scope,d_s_index,matched_index)
|
||||||
|
if search is None:
|
||||||
|
return []
|
||||||
|
last_device = None
|
||||||
|
device_index = 0
|
||||||
|
devices = []
|
||||||
|
for index,line in enumerate(table.get("lines","")):
|
||||||
|
if self.is_hex(line):
|
||||||
|
continue
|
||||||
|
line = self.get_line(line) if strip_comments else line
|
||||||
|
if any ((x for x in types if x in line)):
|
||||||
|
# Got a last_device match
|
||||||
|
last_device = line
|
||||||
|
device_index = index
|
||||||
|
if search in line:
|
||||||
|
# Got a search hit - add it
|
||||||
|
devices.append((last_device,device_index,index))
|
||||||
|
return devices
|
||||||
|
|
||||||
|
def get_scope(self,starting_index=0,add_hex=False,strip_comments=False,table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: return []
|
||||||
|
# Walks the scope starting at starting_index, and returns when
|
||||||
|
# we've exited
|
||||||
|
brackets = None
|
||||||
|
scope = []
|
||||||
|
for line in table.get("lines","")[starting_index:]:
|
||||||
|
if self.is_hex(line):
|
||||||
|
if add_hex:
|
||||||
|
scope.append(line)
|
||||||
|
continue
|
||||||
|
line = self.get_line(line) if strip_comments else line
|
||||||
|
scope.append(line)
|
||||||
|
if brackets is None:
|
||||||
|
if line.count("{"):
|
||||||
|
brackets = line.count("{")
|
||||||
|
continue
|
||||||
|
brackets = brackets + line.count("{") - line.count("}")
|
||||||
|
if brackets <= 0:
|
||||||
|
# We've exited the scope
|
||||||
|
return scope
|
||||||
|
return scope
|
||||||
|
|
||||||
|
def get_scopes(self, table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: return []
|
||||||
|
scopes = []
|
||||||
|
for index,line in enumerate(table.get("lines","")):
|
||||||
|
if self.is_hex(line): continue
|
||||||
|
if any(x in line for x in ("Processor (","Scope (","Device (","Method (","Name (")):
|
||||||
|
scopes.append((line,index))
|
||||||
|
return scopes
|
||||||
|
|
||||||
|
def get_paths(self, table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: return []
|
||||||
|
# Set up lists for complete paths, as well
|
||||||
|
# as our current path reference
|
||||||
|
path_list = []
|
||||||
|
_path = []
|
||||||
|
brackets = 0
|
||||||
|
for i,line in enumerate(table.get("lines",[])):
|
||||||
|
line = self.get_line(line)
|
||||||
|
if self.is_hex(line):
|
||||||
|
# Skip hex
|
||||||
|
continue
|
||||||
|
brackets += line.count("{")-line.count("}")
|
||||||
|
while len(_path):
|
||||||
|
# Remove any path entries that are nested
|
||||||
|
# equal to or further than our current set
|
||||||
|
if _path[-1][-1] >= brackets:
|
||||||
|
del _path[-1]
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
type_match = self.type_match.match(line)
|
||||||
|
if type_match:
|
||||||
|
# Add our path entry and save the full path
|
||||||
|
# to the path list as needed
|
||||||
|
_path.append((type_match.group("name"),brackets))
|
||||||
|
if type_match.group("type") == "Scope":
|
||||||
|
continue
|
||||||
|
# Ensure that we only consider non-Scope paths that aren't
|
||||||
|
# already fully qualified with a \ prefix
|
||||||
|
path = []
|
||||||
|
for p in _path[::-1]:
|
||||||
|
path.append(p[0])
|
||||||
|
if p[0] in ("_SB","_SB_","_PR","_PR_") or p[0].startswith(("\\","_SB.","_SB_.","_PR.","_PR_.")):
|
||||||
|
# Fully qualified - bail here
|
||||||
|
break
|
||||||
|
path = ".".join(path[::-1]).split(".")
|
||||||
|
# Properly qualify the path
|
||||||
|
if len(path) and path[0] == "\\": path.pop(0)
|
||||||
|
if any("^" in x for x in path): # Accommodate caret notation
|
||||||
|
new_path = []
|
||||||
|
for x in path:
|
||||||
|
if x.count("^"):
|
||||||
|
# Remove the last Y paths to account for going up a level
|
||||||
|
del new_path[-1*x.count("^"):]
|
||||||
|
new_path.append(x.replace("^","")) # Add the original, removing any ^ chars
|
||||||
|
path = new_path
|
||||||
|
if not path:
|
||||||
|
continue
|
||||||
|
path_str = ".".join(path)
|
||||||
|
path_str = "\\"+path_str if path_str[0] != "\\" else path_str
|
||||||
|
path_list.append((path_str,i,type_match.group("type")))
|
||||||
|
return sorted(path_list)
|
||||||
|
|
||||||
|
def get_path_of_type(self, obj_type="Device", obj="HPET", table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: return []
|
||||||
|
paths = []
|
||||||
|
for path in table.get("paths",[]):
|
||||||
|
if path[2].lower() == obj_type.lower() and path[0].upper().endswith(obj.upper()):
|
||||||
|
paths.append(path)
|
||||||
|
return sorted(paths)
|
||||||
|
|
||||||
|
def get_device_paths(self, obj="HPET",table=None):
|
||||||
|
return self.get_path_of_type(obj_type="Device",obj=obj,table=table)
|
||||||
|
|
||||||
|
def get_method_paths(self, obj="_STA",table=None):
|
||||||
|
return self.get_path_of_type(obj_type="Method",obj=obj,table=table)
|
||||||
|
|
||||||
|
def get_name_paths(self, obj="CPU0",table=None):
|
||||||
|
return self.get_path_of_type(obj_type="Name",obj=obj,table=table)
|
||||||
|
|
||||||
|
def get_processor_paths(self, obj_type="Processor",table=None):
|
||||||
|
return self.get_path_of_type(obj_type=obj_type,obj="",table=table)
|
||||||
|
|
||||||
|
def get_device_paths_with_hid(self, hid="ACPI000E", table=None):
|
||||||
|
if not table: table = self.get_dsdt_or_only()
|
||||||
|
if not table: return []
|
||||||
|
starting_indexes = []
|
||||||
|
for index,line in enumerate(table.get("lines","")):
|
||||||
|
if self.is_hex(line): continue
|
||||||
|
if hid.upper() in line.upper():
|
||||||
|
starting_indexes.append(index)
|
||||||
|
if not starting_indexes: return starting_indexes
|
||||||
|
devices = []
|
||||||
|
for i in starting_indexes:
|
||||||
|
# Walk backwards and get the next parent device
|
||||||
|
pad = len(table.get("lines","")[i]) - len(table.get("lines","")[i].lstrip(" "))
|
||||||
|
for sub,line in enumerate(table.get("lines","")[i::-1]):
|
||||||
|
if "Device (" in line and len(line)-len(line.lstrip(" ")) < pad:
|
||||||
|
# Add it if it's already in our dsdt_paths - if not, add the current line
|
||||||
|
device = next((x for x in table.get("paths",[]) if x[1]==i-sub),None)
|
||||||
|
if device: devices.append(device)
|
||||||
|
else: devices.append((line,i-sub))
|
||||||
|
break
|
||||||
|
return devices
|
||||||
505
Scripts/efi_builder.py
Executable file
505
Scripts/efi_builder.py
Executable file
@@ -0,0 +1,505 @@
|
|||||||
|
from Scripts.datasets import cpu_data
|
||||||
|
from Scripts import acpi_guru
|
||||||
|
from Scripts import config_prodigy
|
||||||
|
from Scripts import kext_maestro
|
||||||
|
from Scripts import utils
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import re
|
||||||
|
|
||||||
|
class builder:
|
||||||
|
def __init__(self):
|
||||||
|
self.acpi = acpi_guru.ACPIGuru()
|
||||||
|
self.config = config_prodigy.ConfigProdigy()
|
||||||
|
self.kext = kext_maestro.KextMaestro()
|
||||||
|
self.utils = utils.Utils()
|
||||||
|
self.ock_files_dir = os.path.join(os.getcwd(), "OCK_Files")
|
||||||
|
self.oc_binary_data_dir = os.path.join(os.getcwd(), "OcBinaryData")
|
||||||
|
self.result_dir = os.path.join(os.getcwd(), "Results")
|
||||||
|
self.intel_igpu_properties = {
|
||||||
|
"Ice Lake": {
|
||||||
|
"Laptop": {
|
||||||
|
"AAPL,ig-platform-id": "0000528A",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Comet Lake": {
|
||||||
|
"Desktop": {
|
||||||
|
"AAPL,ig-platform-idEx": "0300C89B",
|
||||||
|
"AAPL,ig-platform-id": "07009B3E",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
},
|
||||||
|
"NUC": {
|
||||||
|
"AAPL,ig-platform-id": "07009B3E",
|
||||||
|
"device-id": "9B3E0000",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
},
|
||||||
|
"Laptop": {
|
||||||
|
"AAPL,ig-platform-id": "00009B3E",
|
||||||
|
"device-id": "9B3E0000",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Coffee Lake": {
|
||||||
|
"Desktop": {
|
||||||
|
"AAPL,ig-platform-idEx": "0300913E",
|
||||||
|
"AAPL,ig-platform-id": "07009B3E"
|
||||||
|
},
|
||||||
|
"NUC": {
|
||||||
|
"AAPL,ig-platform-id": "07009B3E",
|
||||||
|
"device-id": "9B3E0000",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
},
|
||||||
|
"Laptop": {
|
||||||
|
"AAPL,ig-platform-id": "0900A53E",
|
||||||
|
"device-id": "9B3E0000",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Whiskey Lake": {
|
||||||
|
"NUC": {
|
||||||
|
"AAPL,ig-platform-id": "07009B3E",
|
||||||
|
"device-id": "9B3E0000",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
},
|
||||||
|
"Laptop": {
|
||||||
|
"AAPL,ig-platform-id": "0900A53E",
|
||||||
|
"device-id": "9B3E0000",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Amber Lake": {
|
||||||
|
"Laptop": {
|
||||||
|
"AAPL,ig-platform-id": "0000C087",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Kaby Lake": {
|
||||||
|
"Desktop": {
|
||||||
|
"AAPL,ig-platform-idEx": "03001259",
|
||||||
|
"AAPL,ig-platform-id": "00001259",
|
||||||
|
"device-id": "12590000"
|
||||||
|
},
|
||||||
|
"NUC": {
|
||||||
|
"AAPL,ig-platform-id": "00001659",
|
||||||
|
"device-id": "16590000",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
},
|
||||||
|
"Laptop": {
|
||||||
|
"AAPL,ig-platform-id": "00001B59",
|
||||||
|
"device-id": "1B590000",
|
||||||
|
"framebuffer-con1-alldata": "01050A00 00080000 87010000 02040A00 00080000 87010000 FF000000 01000000 20000000",
|
||||||
|
"framebuffer-con1-enable": "01000000",
|
||||||
|
"#framebuffer-con2-alldata": "01050A00 00080000 87010000 03060A00 00040000 87010000 FF000000 01000000 20000000",
|
||||||
|
"#framebuffer-con2-enable": "01000000",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Skylake": {
|
||||||
|
"Desktop": {
|
||||||
|
"AAPL,ig-platform-idEx": "01001219",
|
||||||
|
"AAPL,ig-platform-id": "00001219"
|
||||||
|
},
|
||||||
|
"NUC": {
|
||||||
|
"AAPL,ig-platform-id": "05003B19",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
},
|
||||||
|
"Laptop": {
|
||||||
|
"AAPL,ig-platform-id": "00001619",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Broadwell": {
|
||||||
|
"Desktop": {
|
||||||
|
"AAPL,ig-platform-idEx": "07002216",
|
||||||
|
"AAPL,ig-platform-id": "07002216"
|
||||||
|
},
|
||||||
|
"NUC": {
|
||||||
|
"AAPL,ig-platform-id": "02001616",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
},
|
||||||
|
"Laptop": {
|
||||||
|
"AAPL,ig-platform-id": "06002616",
|
||||||
|
"framebuffer-fbmem": "00009000",
|
||||||
|
"framebuffer-stolenmem": "00003001"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Haswell": {
|
||||||
|
"Desktop": {
|
||||||
|
"AAPL,ig-platform-idEx": "04001204",
|
||||||
|
"AAPL,ig-platform-id": "0300220D"
|
||||||
|
},
|
||||||
|
"NUC": {
|
||||||
|
"AAPL,ig-platform-id": "0300220D",
|
||||||
|
"device-id": "12040000",
|
||||||
|
"framebuffer-cursormem": "00009000"
|
||||||
|
},
|
||||||
|
"Laptop": {
|
||||||
|
"AAPL,ig-platform-id": "0600260A",
|
||||||
|
"device-id": "12040000",
|
||||||
|
"framebuffer-cursormem": "00009000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Ivy Bridge": {
|
||||||
|
"Desktop": {
|
||||||
|
"AAPL,ig-platform-idEx": "07006201",
|
||||||
|
"AAPL,ig-platform-id": "0A006601"
|
||||||
|
},
|
||||||
|
"Laptop": {
|
||||||
|
"AAPL,ig-platform-id": "03006601"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Sandy Bridge": {
|
||||||
|
"Desktop": {
|
||||||
|
"AAPL,snb-platform-idEx": "00000500",
|
||||||
|
"AAPL,snb-platform-id": "10000300",
|
||||||
|
"device-id": "26010000"
|
||||||
|
},
|
||||||
|
"Laptop": {
|
||||||
|
"AAPL,snb-platform-id": "00000100"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def is_low_end_intel_cpu(self, processor_name):
|
||||||
|
return any(cpu_branding in processor_name for cpu_branding in ["Celeron", "Pentium"])
|
||||||
|
|
||||||
|
def check_igpu_compatibility(self, cpu_codename, macos_version):
|
||||||
|
return not (("Sandy Bridge" in cpu_codename and macos_version > 17) or ("Ivy Bridge" in cpu_codename and macos_version > 20) or (("Haswell" in cpu_codename or "Broadwell" in cpu_codename) and macos_version > 21) or (("Skylake" in cpu_codename or "Kaby Lake" in cpu_codename) and macos_version > 22) or (("Amber Lake" in cpu_codename or "Whiskey Lake" in cpu_codename) and macos_version == 17) or ("Ice Lake" in cpu_codename and 19 > macos_version))
|
||||||
|
|
||||||
|
def igpu_properties(self, platform, processor_name, gpu_codename, discrete_gpu, integrated_gpu_manufacturer, integrated_gpu_name, macos_version):
|
||||||
|
if "Skylake".lower() in gpu_codename.lower() and macos_version > 21:
|
||||||
|
gpu_codename = "Kaby Lake"
|
||||||
|
if "Kaby Lake-R".upper() in gpu_codename.upper() and macos_version > 22:
|
||||||
|
gpu_codename = "Coffee Lake"
|
||||||
|
|
||||||
|
gpu_codename = self.utils.contains_any(cpu_data.IntelCPUGenerations, gpu_codename)
|
||||||
|
if not "Intel" in integrated_gpu_manufacturer or not integrated_gpu_name or self.is_low_end_intel_cpu(processor_name) or not self.check_igpu_compatibility(gpu_codename, macos_version) or not self.intel_igpu_properties.get(gpu_codename, True):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
igpu_properties = self.intel_igpu_properties[gpu_codename][platform]
|
||||||
|
|
||||||
|
if "Desktop" in platform:
|
||||||
|
if discrete_gpu:
|
||||||
|
if "Sandy Bridge" in gpu_codename:
|
||||||
|
return {
|
||||||
|
"AAPL,snb-platform-id": igpu_properties["AAPL,snb-platform-idEx"],
|
||||||
|
"device-id": "02010000",
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return {
|
||||||
|
"AAPL,ig-platform-id": igpu_properties["AAPL,ig-platform-idEx"]
|
||||||
|
}
|
||||||
|
del igpu_properties["AAPL,ig-platform-idEx"]
|
||||||
|
if "Haswell" in gpu_codename and not "440" in integrated_gpu_name:
|
||||||
|
igpu_properties["device-id"] = "12040000"
|
||||||
|
elif "Skylake" in gpu_codename and "P530" in integrated_gpu_name:
|
||||||
|
igpu_properties["device-id"] = "12040000"
|
||||||
|
else:
|
||||||
|
if "Haswell" in gpu_codename and "5" in integrated_gpu_name:
|
||||||
|
igpu_properties["AAPL,ig-platform-id"] = "0500260A"
|
||||||
|
del igpu_properties["device-id"]
|
||||||
|
elif "Broadwell" in gpu_codename and "56" in integrated_gpu_name:
|
||||||
|
igpu_properties["device-id"] = "26160000"
|
||||||
|
elif "Skylake" in gpu_codename:
|
||||||
|
if "NUC" in platform:
|
||||||
|
if "51" in integrated_gpu_name:
|
||||||
|
igpu_properties["AAPL,ig-platform-id"] = "00001E19"
|
||||||
|
elif "52" in integrated_gpu_name or "53" in integrated_gpu_name:
|
||||||
|
igpu_properties["AAPL,ig-platform-id"] = "02001619"
|
||||||
|
elif "54" in integrated_gpu_name or "55" in integrated_gpu_name:
|
||||||
|
igpu_properties["AAPL,ig-platform-id"] = "02002619"
|
||||||
|
|
||||||
|
if "510" in integrated_gpu_name:
|
||||||
|
igpu_properties["AAPL,ig-platform-id"] = "00001B19"
|
||||||
|
igpu_properties["device-id"] = "02190000"
|
||||||
|
elif "550" in integrated_gpu_name or "P530" in integrated_gpu_name:
|
||||||
|
igpu_properties["device-id"] = "16190000"
|
||||||
|
elif "Kaby Lake" in gpu_codename:
|
||||||
|
if "NUC" in platform:
|
||||||
|
if "15" in integrated_gpu_name:
|
||||||
|
igpu_properties["AAPL,ig-platform-id"] = "00001E59"
|
||||||
|
elif "63" in integrated_gpu_name:
|
||||||
|
igpu_properties["AAPL,ig-platform-id"] = "00001B59"
|
||||||
|
elif "40" in integrated_gpu_name or "65" in integrated_gpu_name:
|
||||||
|
igpu_properties["AAPL,ig-platform-id"] = "02002659"
|
||||||
|
else:
|
||||||
|
if "UHD" in integrated_gpu_name:
|
||||||
|
igpu_properties["AAPL,ig-platform-id"] = "0000C087"
|
||||||
|
igpu_properties["device-id"] = "16590000"
|
||||||
|
elif self.utils.contains_any(cpu_data.IntelCPUGenerations, gpu_codename, start=8, end=11):
|
||||||
|
if "NUC" in platform:
|
||||||
|
if "55" in integrated_gpu_name:
|
||||||
|
igpu_properties["AAPL,ig-platform-id"] = "0000A53E"
|
||||||
|
del igpu_properties["device-id"]
|
||||||
|
else:
|
||||||
|
if "3" in integrated_gpu_name:
|
||||||
|
igpu_properties["AAPL,ig-platform-id"] = "0900A53E"
|
||||||
|
|
||||||
|
igpu_properties["hda-gfx"] = "onboard-1"
|
||||||
|
igpu_properties["framebuffer-patch-enable"] = "01000000"
|
||||||
|
return igpu_properties
|
||||||
|
|
||||||
|
def system_product_info(self, platform, cpu_manufacturer, processor_name, cpu_codename, cpu_cores, discrete_gpu, igpu_props, macos_version):
|
||||||
|
product_name = "iMacPro1,1" if self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, start=12) else "MacPro7,1"
|
||||||
|
|
||||||
|
if "AMD" in cpu_manufacturer:
|
||||||
|
product_name = "MacBookPro16,3" if "Laptop" in platform else "iMacPro1,1"
|
||||||
|
|
||||||
|
if igpu_props:
|
||||||
|
if "Kaby Lake-R".lower() in cpu_codename.lower() and macos_version > 22:
|
||||||
|
cpu_codename = "Coffee Lake"
|
||||||
|
|
||||||
|
if "Sandy Bridge" in cpu_codename:
|
||||||
|
if "Desktop" in platform:
|
||||||
|
if macos_version < 18:
|
||||||
|
product_name = "iMac12,2"
|
||||||
|
else:
|
||||||
|
product_name = "MacPro6,1"
|
||||||
|
elif "NUC" in platform:
|
||||||
|
product_name = "Macmini5,1" if int(cpu_cores) < 4 else "Macmini5,3"
|
||||||
|
else:
|
||||||
|
product_name = "MacBookPro8,1" if int(cpu_cores) < 4 else "MacBookPro8,2"
|
||||||
|
elif "Ivy Bridge" in cpu_codename:
|
||||||
|
if macos_version == 20:
|
||||||
|
if "Desktop" in platform:
|
||||||
|
product_name = "iMac14,4" if not discrete_gpu else "iMac15,1"
|
||||||
|
elif "NUC" in platform:
|
||||||
|
product_name = "Macmini7,1"
|
||||||
|
else:
|
||||||
|
product_name = "MacBookPro11,1" if int(cpu_cores) < 4 else "MacBookPro11,5"
|
||||||
|
elif macos_version < 20:
|
||||||
|
if "Desktop" in platform:
|
||||||
|
product_name = "iMac13,1" if not discrete_gpu else "iMac13,2"
|
||||||
|
elif "NUC" in platform:
|
||||||
|
product_name = "Macmini6,1" if int(cpu_cores) < 4 else "Macmini6,2"
|
||||||
|
else:
|
||||||
|
product_name = "MacBookPro10,2" if int(cpu_cores) < 4 else "MacBookPro10,1"
|
||||||
|
else:
|
||||||
|
product_name = "MacPro6,1"
|
||||||
|
elif "Haswell" in cpu_codename:
|
||||||
|
if "Desktop" in platform:
|
||||||
|
product_name = "iMac14,4" if not discrete_gpu else "iMac15,1"
|
||||||
|
if macos_version == 21:
|
||||||
|
product_name = "iMac16,2" if not discrete_gpu else "iMac17,1"
|
||||||
|
elif "NUC" in platform:
|
||||||
|
product_name = "Macmini7,1"
|
||||||
|
else:
|
||||||
|
product_name = "MacBookPro11,1" if macos_version < 21 and int(cpu_cores) < 4 else "MacBookPro11,5"
|
||||||
|
elif "Broadwell" in cpu_codename:
|
||||||
|
if "Desktop" in platform:
|
||||||
|
product_name = "iMac16,2" if not discrete_gpu else "iMac17,1"
|
||||||
|
elif "NUC" in platform:
|
||||||
|
product_name = "iMac16,1"
|
||||||
|
else:
|
||||||
|
product_name = "MacBookPro12,1" if int(cpu_cores) < 4 else "MacBookPro11,5"
|
||||||
|
elif "Skylake" in cpu_codename:
|
||||||
|
product_name = "iMac17,1"
|
||||||
|
if "Laptop" in platform:
|
||||||
|
product_name = "MacBookPro13,1" if int(cpu_cores) < 4 else "MacBookPro13,3"
|
||||||
|
elif self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, start=8, end=11):
|
||||||
|
product_name = "Macmini8,1"
|
||||||
|
if "Desktop" in platform:
|
||||||
|
product_name = "iMac18,3" if macos_version == 17 else "iMac19,1"
|
||||||
|
if "Comet Lake" in cpu_codename:
|
||||||
|
product_name = "iMac20,1" if int(cpu_cores) < 10 else "iMac20,2"
|
||||||
|
elif "Laptop" in platform:
|
||||||
|
if "-8" in processor_name:
|
||||||
|
product_name = "MacBookPro15,2" if int(cpu_cores) < 6 else "MacBookPro15,3"
|
||||||
|
else:
|
||||||
|
product_name = "MacBookPro16,3" if int(cpu_cores) < 6 else "MacBookPro16,1"
|
||||||
|
elif "Kaby Lake" in cpu_codename:
|
||||||
|
product_name = "iMac18,1" if not discrete_gpu else "iMac18,3"
|
||||||
|
if "Laptop" in platform:
|
||||||
|
product_name = "MacBookPro14,1" if int(cpu_cores) < 4 else "MacBookPro14,3"
|
||||||
|
elif "Amber Lake" in cpu_codename:
|
||||||
|
product_name = "MacBookAir8,1"
|
||||||
|
elif "Ice Lake" in cpu_codename:
|
||||||
|
product_name = "MacBookAir9,1" if int(cpu_cores) < 4 else "MacBookPro16,2"
|
||||||
|
|
||||||
|
return product_name
|
||||||
|
|
||||||
|
def clean_up(self, config, efi_directory):
|
||||||
|
files_to_remove = []
|
||||||
|
|
||||||
|
drivers_directory = os.path.join(efi_directory, "EFI", "OC", "Drivers")
|
||||||
|
driver_list = self.utils.recursively_search(drivers_directory, ".efi")
|
||||||
|
driver_loaded = [kext.get("Path") for kext in config.get("UEFI").get("Drivers")]
|
||||||
|
for driver_path in driver_list:
|
||||||
|
if not driver_path in driver_loaded:
|
||||||
|
files_to_remove.append(os.path.join(drivers_directory, driver_path))
|
||||||
|
|
||||||
|
kexts_directory = os.path.join(efi_directory, "EFI", "OC", "Kexts")
|
||||||
|
kext_list = self.utils.recursively_search(kexts_directory, ".kext")
|
||||||
|
kext_loaded = [kext.get("BundlePath") for kext in config.get("Kernel").get("Add")]
|
||||||
|
for kext_path in kext_list:
|
||||||
|
if not kext_path in kext_loaded:
|
||||||
|
files_to_remove.append(os.path.join(kexts_directory, kext_path))
|
||||||
|
|
||||||
|
tools_directory = os.path.join(efi_directory, "EFI", "OC", "Tools")
|
||||||
|
tool_list = self.utils.recursively_search(tools_directory, ".efi")
|
||||||
|
tool_loaded = [tool.get("Path") for tool in config.get("Misc").get("Tools")]
|
||||||
|
for tool_path in tool_list:
|
||||||
|
if not tool_path in tool_loaded:
|
||||||
|
files_to_remove.append(os.path.join(tools_directory, tool_path))
|
||||||
|
|
||||||
|
for path in files_to_remove:
|
||||||
|
try:
|
||||||
|
if os.path.isdir(path):
|
||||||
|
shutil.rmtree(path)
|
||||||
|
else:
|
||||||
|
os.remove(path)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to remove file: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
def build_efi(self, hardware, macos_version):
|
||||||
|
efi_directory = os.path.join(os.getcwd(), "Results")
|
||||||
|
|
||||||
|
self.utils.mkdirs(efi_directory)
|
||||||
|
|
||||||
|
if not os.path.exists(self.ock_files_dir):
|
||||||
|
raise Exception(f"Directory '{self.ock_files_dir}' does not exist.")
|
||||||
|
|
||||||
|
source_efi_dir = os.path.join(self.ock_files_dir, "OpenCore")
|
||||||
|
shutil.copytree(source_efi_dir, efi_directory, dirs_exist_ok=True)
|
||||||
|
shutil.copytree(self.oc_binary_data_dir, os.path.join(efi_directory, "EFI", "OC"), dirs_exist_ok=True)
|
||||||
|
|
||||||
|
hardware_shorc = {}
|
||||||
|
hardware_shorc["Motherboard Name"] = hardware["Motherboard"].get("Motherboard Name").upper()
|
||||||
|
hardware_shorc["Motherboard Chipset"] = hardware["Motherboard"].get("Motherboard Chipset").upper()
|
||||||
|
hardware_shorc["Platform"] = hardware["Motherboard"].get("Platform")
|
||||||
|
hardware_shorc["CPU Configuration"] = hardware["Motherboard"].get("CPU Configuration")
|
||||||
|
hardware_shorc["CPU Manufacturer"] = hardware["CPU"].get("CPU Manufacturer")
|
||||||
|
hardware_shorc["Processor Name"] = hardware["CPU"].get("Processor Name")
|
||||||
|
hardware_shorc["CPU Cores"] = hardware["CPU"].get("CPU Cores")
|
||||||
|
hardware_shorc["CPU Codename"] = hardware["CPU"].get("CPU Codename")
|
||||||
|
hardware_shorc["Integrated GPU"] = list(hardware.get("GPU").items())[-1][1] if "Integrated GPU" in list(hardware.get("GPU").items())[-1][1]["Device Type"] else {}
|
||||||
|
hardware_shorc["Integrated GPU Manufacturer"] = hardware_shorc["Integrated GPU"]["Manufacturer"] if hardware_shorc["Integrated GPU"] else ""
|
||||||
|
hardware_shorc["Integrated GPU Name"] = list(hardware.get("GPU").keys())[-1] if hardware_shorc["Integrated GPU"] else ""
|
||||||
|
hardware_shorc["Integrated GPU Codename"] = hardware_shorc["Integrated GPU"]["GPU Codename"] if hardware_shorc["Integrated GPU"] else ""
|
||||||
|
hardware_shorc["Discrete GPU"] = list(hardware.get("GPU").items())[0][1] if "Discrete GPU" in list(hardware.get("GPU").items())[0][1]["Device Type"] else {}
|
||||||
|
hardware_shorc["Discrete GPU Manufacturer"] = hardware_shorc["Discrete GPU"]["Manufacturer"] if hardware_shorc["Discrete GPU"] else ""
|
||||||
|
hardware_shorc["Discrete GPU Codename"] = hardware_shorc["Discrete GPU"]["GPU Codename"] if hardware_shorc["Discrete GPU"] else ""
|
||||||
|
hardware_shorc["Ethernet (PCI)"] = []
|
||||||
|
for network_name, network_props in hardware["Network"].items():
|
||||||
|
connection_name = network_props["Connection Name"]
|
||||||
|
bus_type = network_props["Bus Type"]
|
||||||
|
|
||||||
|
if bus_type.startswith("PCI"):
|
||||||
|
if connection_name.startswith("WiFi"):
|
||||||
|
hardware_shorc["Wi-Fi (PCI)"] = network_props.get("Device ID")
|
||||||
|
elif connection_name.startswith("Ethernet"):
|
||||||
|
hardware_shorc["Ethernet (PCI)"].append(network_props.get("Device ID"))
|
||||||
|
hardware_shorc["Bluetooth"] = [device_props.get("Device ID") for device_name, device_props in hardware.get("Bluetooth", {}).items()]
|
||||||
|
hardware_shorc["Codec ID"] = next((device_props.get("Codec ID") for device_name, device_props in hardware.get("Audio").items()), None)
|
||||||
|
hardware_shorc["SD Controller"] = hardware.get("SD Controller")
|
||||||
|
hardware_shorc["Input"] = hardware.get("Input")
|
||||||
|
hardware_shorc["Storage Controllers"] = hardware.get("Storage").get("Storage Controllers")
|
||||||
|
hardware_shorc["USB Controllers"] = [controller_props.get("Device ID") for controller_name, controller_props in hardware.get("USB").get("USB Controllers").items()]
|
||||||
|
hardware_shorc["Intel MEI"] = hardware.get("Intel MEI")
|
||||||
|
hardware_shorc["Unsupported Devices"] = hardware.get("Compatibility").get("Unsupported Devices")
|
||||||
|
|
||||||
|
forbidden_chars = r'[<>:"/\\|?*]'
|
||||||
|
hardware_shorc["Motherboard Name"] = re.sub(forbidden_chars, '_', hardware_shorc["Motherboard Name"])
|
||||||
|
|
||||||
|
efi_option = {}
|
||||||
|
efi_option["macOS Version"] = macos_version
|
||||||
|
efi_option["Custom CPU Name"] = not (" Core" in hardware_shorc.get("Processor Name") and self.utils.contains_any(cpu_data.IntelCPUGenerations, hardware_shorc.get("CPU Codename"), end=12))
|
||||||
|
efi_option["Synchronize the TSC"] = "Laptop" in hardware_shorc["Platform"] and "ASUS" in hardware_shorc["Motherboard Name"] or "AMD" in hardware_shorc["Integrated GPU Manufacturer"]
|
||||||
|
efi_option["iGPU Properties"] = self.igpu_properties(
|
||||||
|
hardware_shorc["Platform"],
|
||||||
|
hardware_shorc.get("Processor Name"),
|
||||||
|
hardware_shorc.get("Integrated GPU Codename"),
|
||||||
|
hardware_shorc["Discrete GPU"],
|
||||||
|
hardware_shorc["Integrated GPU Manufacturer"],
|
||||||
|
hardware_shorc["Integrated GPU Name"],
|
||||||
|
efi_option.get("macOS Version"))
|
||||||
|
efi_option["SMBIOS"] = self.system_product_info(
|
||||||
|
hardware_shorc["Platform"],
|
||||||
|
hardware_shorc["CPU Manufacturer"],
|
||||||
|
hardware_shorc.get("Processor Name"),
|
||||||
|
hardware_shorc["CPU Codename"],
|
||||||
|
hardware_shorc["CPU Cores"],
|
||||||
|
hardware_shorc["Discrete GPU"],
|
||||||
|
efi_option["iGPU Properties"],
|
||||||
|
efi_option.get("macOS Version"))
|
||||||
|
|
||||||
|
input_devices = ", ".join(list(hardware_shorc.get("Input", {}).keys()))
|
||||||
|
hardware_shorc["Touchpad Communication"] = "None" if not "Laptop" in hardware_shorc.get("Platform") else "I2C" if "I2C" in input_devices else "PS2" if "PS2" in input_devices else "None"
|
||||||
|
efi_option["ACPI"] = self.acpi.initialize_patches(
|
||||||
|
hardware_shorc["Motherboard Name"],
|
||||||
|
hardware_shorc["Motherboard Chipset"],
|
||||||
|
hardware_shorc["Platform"],
|
||||||
|
hardware_shorc["CPU Manufacturer"],
|
||||||
|
hardware_shorc["CPU Codename"],
|
||||||
|
hardware_shorc["Integrated GPU"],
|
||||||
|
hardware_shorc["Ethernet (PCI)"],
|
||||||
|
hardware_shorc["Touchpad Communication"],
|
||||||
|
efi_option.get("SMBIOS"),
|
||||||
|
hardware_shorc.get("Intel MEI"),
|
||||||
|
hardware_shorc["Unsupported Devices"],
|
||||||
|
efi_option.get("macOS Version"),
|
||||||
|
os.path.join(efi_directory, "EFI", "OC", "ACPI")
|
||||||
|
)
|
||||||
|
|
||||||
|
kexts = self.kext.gathering_kexts(
|
||||||
|
hardware_shorc["Motherboard Name"],
|
||||||
|
hardware_shorc["Platform"],
|
||||||
|
hardware_shorc["CPU Configuration"],
|
||||||
|
hardware_shorc["CPU Manufacturer"],
|
||||||
|
hardware_shorc["CPU Codename"],
|
||||||
|
hardware_shorc["Discrete GPU Codename"],
|
||||||
|
hardware_shorc["Integrated GPU"],
|
||||||
|
hardware_shorc.get("Wi-Fi (PCI)"),
|
||||||
|
hardware_shorc["Ethernet (PCI)"],
|
||||||
|
hardware_shorc.get("Bluetooth"),
|
||||||
|
hardware_shorc.get("Codec ID"),
|
||||||
|
hardware_shorc["Input"],
|
||||||
|
hardware_shorc.get("SD Controller"),
|
||||||
|
hardware_shorc.get("Storage Controllers"),
|
||||||
|
hardware_shorc["USB Controllers"],
|
||||||
|
efi_option.get("SMBIOS"),
|
||||||
|
efi_option.get("Custom CPU Name"),
|
||||||
|
efi_option.get("Synchronize the TSC"),
|
||||||
|
efi_option.get("ACPI").get("Battery Status Patch Needed"),
|
||||||
|
efi_option.get("macOS Version")
|
||||||
|
)
|
||||||
|
|
||||||
|
kexts_directory = os.path.join(efi_directory, "EFI", "OC", "Kexts")
|
||||||
|
self.kext.install_kexts_to_efi(kexts, efi_option.get("macOS Version"), kexts_directory)
|
||||||
|
efi_option["Kernel_Add"] = self.kext.load_kexts(
|
||||||
|
kexts,
|
||||||
|
hardware_shorc["Motherboard Name"],
|
||||||
|
hardware_shorc["Platform"],
|
||||||
|
hardware_shorc["CPU Manufacturer"],
|
||||||
|
hardware_shorc["Discrete GPU Codename"],
|
||||||
|
efi_option["macOS Version"]
|
||||||
|
)
|
||||||
|
|
||||||
|
config_file = os.path.join(efi_directory, "EFI", "OC", "config.plist")
|
||||||
|
config_data = self.utils.read_file(config_file)
|
||||||
|
|
||||||
|
if not config_data:
|
||||||
|
raise Exception(f"Error: The file {config_file} does not exist.")
|
||||||
|
|
||||||
|
self.config.genarate(hardware_shorc, efi_option, config_data)
|
||||||
|
self.utils.write_file(config_file, config_data)
|
||||||
|
|
||||||
|
self.clean_up(config_data, efi_directory)
|
||||||
|
hardware_file = os.path.join(efi_directory, hardware_shorc.get("Motherboard Name") + ".json")
|
||||||
|
self.utils.write_file(hardware_file, hardware)
|
||||||
317
Scripts/gathering_files.py
Executable file
317
Scripts/gathering_files.py
Executable file
@@ -0,0 +1,317 @@
|
|||||||
|
from Scripts import github
|
||||||
|
from Scripts import resource_fetcher
|
||||||
|
from Scripts import utils
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
class gatheringFiles:
|
||||||
|
def __init__(self):
|
||||||
|
self.utils = utils.Utils()
|
||||||
|
self.github = github.Github()
|
||||||
|
self.fetcher = resource_fetcher.ResourceFetcher(self.github.headers)
|
||||||
|
self.dortania_builds_url = "https://raw.githubusercontent.com/dortania/build-repo/builds/latest.json"
|
||||||
|
self.amd_vanilla_patches_url = f"https://raw.githubusercontent.com/AMD-OSX/AMD_Vanilla/beta/patches.plist"
|
||||||
|
self.temporary_dir = tempfile.mkdtemp()
|
||||||
|
self.ock_files_dir = os.path.join(os.getcwd(), "OCK_Files")
|
||||||
|
self.download_history_file = os.path.join(self.ock_files_dir, "history.json")
|
||||||
|
self.builds = [
|
||||||
|
"AirportBrcmFixup",
|
||||||
|
"AppleALC",
|
||||||
|
"BrcmPatchRAM",
|
||||||
|
"BrightnessKeys",
|
||||||
|
"CryptexFixup",
|
||||||
|
"ECEnabler",
|
||||||
|
"HibernationFixup",
|
||||||
|
"IntelBluetoothFirmware",
|
||||||
|
"IntelMausi",
|
||||||
|
"Lilu",
|
||||||
|
"NVMeFix",
|
||||||
|
"RTCMemoryFixup",
|
||||||
|
"RealtekRTL8111",
|
||||||
|
"RestrictEvents",
|
||||||
|
"VirtualSMC",
|
||||||
|
"VoodooI2C",
|
||||||
|
"VoodooInput",
|
||||||
|
"VoodooPS2",
|
||||||
|
"VoodooSMBus",
|
||||||
|
"WhateverGreen"
|
||||||
|
]
|
||||||
|
self.releases = [
|
||||||
|
{
|
||||||
|
"owner": "blankmac",
|
||||||
|
"repo": "AlpsHID"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "SongXiaoXi",
|
||||||
|
"repo": "AppleIGC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "hieplpvip",
|
||||||
|
"repo": "AsusSMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "Xiashangning",
|
||||||
|
"repo": "BigSurface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "b00t0x",
|
||||||
|
"repo": "CpuTopologyRebuild"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "0xFireWolf",
|
||||||
|
"repo": "RealtekCardReader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "0xFireWolf",
|
||||||
|
"repo": "RealtekCardReaderFriend"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "VoodooSMBus",
|
||||||
|
"repo": "VoodooRMI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "OpenIntelWireless",
|
||||||
|
"repo": "itlwm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "ChefKissInc",
|
||||||
|
"repo": "NootRX"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "ChefKissInc",
|
||||||
|
"repo": "NootedRed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "ChefKissInc",
|
||||||
|
"repo": "ForgedInvariant"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "wjz304",
|
||||||
|
"repo": "OpenCore_Patch_Build"
|
||||||
|
}
|
||||||
|
][-5:]
|
||||||
|
self.actions = []
|
||||||
|
|
||||||
|
def get_bootloader_kexts_data(self):
|
||||||
|
results = [
|
||||||
|
{
|
||||||
|
"product_name": "AlpsHID",
|
||||||
|
"id": 69228327,
|
||||||
|
"url": "https://github.com/blankmac/AlpsHID/releases/download/v1.2/AlpsHID1.2_release.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "AMFIPass",
|
||||||
|
"id": 826491527,
|
||||||
|
"url": "https://github.com/dortania/OpenCore-Legacy-Patcher/raw/76516394fddb7ce4526ccbcc5b806795c30e9a89/payloads/Kexts/Acidanthera/AMFIPass-v1.4.1-RELEASE.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "AppleIGC",
|
||||||
|
"id": 138279923,
|
||||||
|
"url": "https://github.com/SongXiaoXi/AppleIGC/releases/download/v1.5/AppleIGC.kext.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "AppleMCEReporterDisabler",
|
||||||
|
"id": 738162736,
|
||||||
|
"url": "https://github.com/acidanthera/bugtracker/files/3703498/AppleMCEReporterDisabler.kext.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "AsusSMC",
|
||||||
|
"id": 41898282,
|
||||||
|
"url": "https://github.com/hieplpvip/AsusSMC/releases/download/1.4.1/AsusSMC-1.4.1-RELEASE.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "AtherosE2200Ethernet",
|
||||||
|
"id": 9746382,
|
||||||
|
"url": "https://github.com/Mieze/AtherosE2200Ethernet/releases/download/2.2.2/AtherosE2200Ethernet-V2.2.2.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "BigSurface",
|
||||||
|
"id": 18528518,
|
||||||
|
"url": "https://github.com/Xiashangning/BigSurface/releases/download/v6.5/BigSurface.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "CtlnaAHCIPort",
|
||||||
|
"id": 10460478,
|
||||||
|
"url": "https://github.com/lzhoang2801/lzhoang2801.github.io/raw/main/public/extra-files/CtlnaAHCIPort-v3.4.1.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "CpuTopologyRebuild",
|
||||||
|
"id": 13190749,
|
||||||
|
"url": "https://github.com/b00t0x/CpuTopologyRebuild/releases/download/1.1.0/CpuTopologyRebuild-1.1.0-RELEASE.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "IO80211FamilyLegacy",
|
||||||
|
"id": 817294638,
|
||||||
|
"url": "https://github.com/dortania/OpenCore-Legacy-Patcher/raw/main/payloads/Kexts/Wifi/IO80211FamilyLegacy-v1.0.0.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "IOSkywalkFamily",
|
||||||
|
"id": 926384761,
|
||||||
|
"url": "https://github.com/dortania/OpenCore-Legacy-Patcher/raw/main/payloads/Kexts/Wifi/IOSkywalkFamily-v1.1.0.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "LucyRTL8125Ethernet",
|
||||||
|
"id": 159470181,
|
||||||
|
"url": "https://github.com/Mieze/LucyRTL8125Ethernet/releases/download/v1.2.0d5/LucyRTL8125Ethernet-V1.2.0d5.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "NullEthernet",
|
||||||
|
"id": 182736492,
|
||||||
|
"url": "https://bitbucket.org/RehabMan/os-x-null-ethernet/downloads/RehabMan-NullEthernet-2016-1220.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "VoodooRMI",
|
||||||
|
"id": 13190749,
|
||||||
|
"url": "https://github.com/VoodooSMBus/VoodooRMI/releases/download/1.3.5/VoodooRMI-1.3.5-Release.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "RealtekRTL8100",
|
||||||
|
"id": 10460478,
|
||||||
|
"url": "https://github.com/lzhoang2801/lzhoang2801.github.io/raw/main/public/extra-files/RealtekRTL8100-v2.0.1.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "RealtekCardReader",
|
||||||
|
"id": 10460478,
|
||||||
|
"url": "https://github.com/0xFireWolf/RealtekCardReader/releases/download/v0.9.7/RealtekCardReader_0.9.7_006a845_RELEASE.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "RealtekCardReaderFriend",
|
||||||
|
"id": 10460478,
|
||||||
|
"url": "https://github.com/0xFireWolf/RealtekCardReaderFriend/releases/download/v1.0.4/RealtekCardReaderFriend_1.0.4_e1e3301_RELEASE.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "GenericUSBXHCI",
|
||||||
|
"id": 120325166,
|
||||||
|
"url": "https://github.com/RattletraPM/GUX-RyzenXHCIFix/releases/download/v1.3.0b1-ryzenxhcifix/GenericUSBXHCI.kext.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"product_name": "XHCI-unsupported",
|
||||||
|
"id": 185465401,
|
||||||
|
"url": "https://github.com/daliansky/OS-X-USB-Inject-All/releases/download/v0.8.0/XHCI-unsupported.kext.zip"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
dortania_builds_data = self.fetcher.fetch_and_parse_content(self.dortania_builds_url, "json")
|
||||||
|
|
||||||
|
for product_name, product_data in dortania_builds_data.items():
|
||||||
|
if product_name in self.builds:
|
||||||
|
results.append({
|
||||||
|
"product_name": product_name,
|
||||||
|
"id": product_data["versions"][0]["release"]["id"],
|
||||||
|
"url": product_data["versions"][0]["links"]["release"]
|
||||||
|
})
|
||||||
|
|
||||||
|
for product in self.releases:
|
||||||
|
results.extend(self.github.get_latest_release(product["owner"], product["repo"]))
|
||||||
|
# [self.github.get_latest_artifact_id(product["owner"], product["repo"]) for product in self.actions]
|
||||||
|
|
||||||
|
sorted_results = sorted(results, key=lambda x:x["product_name"])
|
||||||
|
|
||||||
|
return sorted_results
|
||||||
|
|
||||||
|
def product_index_in_history(self, product_name, versions):
|
||||||
|
for index, item in enumerate(versions):
|
||||||
|
if product_name in item["product_name"]:
|
||||||
|
return index
|
||||||
|
return None
|
||||||
|
|
||||||
|
def move_bootloader_kexts_to_product_directory(self, product_name):
|
||||||
|
product_directory = os.path.join(self.ock_files_dir, product_name)
|
||||||
|
|
||||||
|
if not os.path.exists(self.temporary_dir):
|
||||||
|
raise FileNotFoundError(f"The directory {self.temporary_dir} does not exist.")
|
||||||
|
|
||||||
|
if not "OpenCore" in product_name:
|
||||||
|
kext_paths = self.utils.recursively_search(self.temporary_dir, ".kext")
|
||||||
|
for kext_path in kext_paths:
|
||||||
|
source_kext_path = os.path.join(self.temporary_dir, kext_path)
|
||||||
|
destination_kext_path = os.path.join(product_directory, os.path.basename(kext_path))
|
||||||
|
|
||||||
|
if "Contents" in kext_path or "Debug".lower() in kext_path.lower():
|
||||||
|
continue
|
||||||
|
|
||||||
|
shutil.move(source_kext_path, destination_kext_path)
|
||||||
|
else:
|
||||||
|
source_bootloader_path = os.path.join(self.temporary_dir, product_name, "X64", "EFI")
|
||||||
|
if os.path.exists(source_bootloader_path):
|
||||||
|
destination_efi_path = os.path.join(product_directory, os.path.basename(source_bootloader_path))
|
||||||
|
shutil.move(source_bootloader_path, destination_efi_path)
|
||||||
|
source_config_path = os.path.join(os.path.dirname(os.path.dirname(source_bootloader_path)), "Docs", "Sample.plist")
|
||||||
|
destination_config_path = os.path.join(destination_efi_path, "OC", "config.plist")
|
||||||
|
shutil.move(source_config_path, destination_config_path)
|
||||||
|
macserial_paths = self.utils.recursively_search(self.temporary_dir, product_name, matching_file_name_pattern="macserial")
|
||||||
|
if macserial_paths:
|
||||||
|
for macserial_path in macserial_paths:
|
||||||
|
file_name = os.path.basename(macserial_path)
|
||||||
|
source_macserial_path = os.path.join(self.temporary_dir, macserial_path)
|
||||||
|
destination_macserial_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), file_name)
|
||||||
|
shutil.move(source_macserial_path, destination_macserial_path)
|
||||||
|
if os.name != "nt":
|
||||||
|
subprocess.run(["chmod", "+x", destination_macserial_path])
|
||||||
|
else:
|
||||||
|
raise FileNotFoundError("No bootloader or kexts files found in the product directory.")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def gathering_bootloader_kexts(self):
|
||||||
|
download_history = self.utils.read_file(self.download_history_file) or {
|
||||||
|
"versions": [],
|
||||||
|
"last_updated": "2024-07-25T12:00:00"
|
||||||
|
}
|
||||||
|
|
||||||
|
last_updated = datetime.fromisoformat(download_history["last_updated"])
|
||||||
|
|
||||||
|
current_time = datetime.now()
|
||||||
|
if current_time - last_updated < timedelta(minutes=10):
|
||||||
|
return
|
||||||
|
|
||||||
|
ock_data = self.get_bootloader_kexts_data()
|
||||||
|
|
||||||
|
self.utils.mkdirs(self.temporary_dir)
|
||||||
|
|
||||||
|
for product_data in ock_data:
|
||||||
|
|
||||||
|
product_index = self.product_index_in_history(product_data.get("product_name"), download_history.get("versions"))
|
||||||
|
if not product_index is None and product_data.get("id") == download_history.get("versions")[product_index].get("id"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
asset_dir = os.path.join(self.ock_files_dir, product_data.get("product_name"))
|
||||||
|
self.utils.mkdirs(asset_dir)
|
||||||
|
|
||||||
|
zip_path = os.path.join(self.temporary_dir, product_data.get("product_name")) + ".zip"
|
||||||
|
self.fetcher.download_and_save_file(product_data.get("url"), zip_path)
|
||||||
|
if self.move_bootloader_kexts_to_product_directory(product_data.get("product_name")):
|
||||||
|
if product_index is None:
|
||||||
|
download_history["versions"].append({
|
||||||
|
"product_name": product_data.get("product_name"),
|
||||||
|
"id": product_data.get("id")
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
download_history["versions"][product_index]["id"] = product_data.get("id")
|
||||||
|
|
||||||
|
current_time = datetime.now().isoformat()
|
||||||
|
download_history["last_updated"] = current_time
|
||||||
|
|
||||||
|
self.utils.write_file(self.download_history_file, download_history)
|
||||||
|
|
||||||
|
shutil.rmtree(self.temporary_dir, ignore_errors=True)
|
||||||
|
|
||||||
|
def get_amd_kernel_patches(self):
|
||||||
|
self.utils.head("Gathering Files")
|
||||||
|
print("")
|
||||||
|
print("Please wait for download AMD Vanilla Patches")
|
||||||
|
print(f"from {self.amd_vanilla_patches_url}")
|
||||||
|
print("")
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = self.fetcher.fetch_and_parse_content(self.amd_vanilla_patches_url, "plist")
|
||||||
|
|
||||||
|
return response["Kernel"]["Patch"]
|
||||||
|
except:
|
||||||
|
print(self.utils.message("Unable to download AMD Vanilla Patches at this time.\nPlease try again later or apply them manually if you are using an AMD CPU system", "warning"))
|
||||||
|
print("")
|
||||||
|
self.utils.request_input()
|
||||||
|
return {}
|
||||||
112
Scripts/github.py
Executable file
112
Scripts/github.py
Executable file
@@ -0,0 +1,112 @@
|
|||||||
|
from Scripts import resource_fetcher
|
||||||
|
from Scripts import utils
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
class Github:
|
||||||
|
def __init__(self):
|
||||||
|
self.utils = utils.Utils()
|
||||||
|
# Load the GitHub token from environment variables
|
||||||
|
self.github_token = os.getenv("GITHUB_TOKEN")
|
||||||
|
# Set the headers for GitHub API requests
|
||||||
|
self.headers = {
|
||||||
|
"Accept": "application/vnd.github+json",
|
||||||
|
"#Authorization": f"token {self.github_token}",
|
||||||
|
"X-GitHub-Api-Version": "2022-11-28",
|
||||||
|
}
|
||||||
|
self.fetcher = resource_fetcher.ResourceFetcher(self.headers)
|
||||||
|
|
||||||
|
def check_ratelimit(self):
|
||||||
|
url = "https://api.github.com/rate_limit"
|
||||||
|
|
||||||
|
response = self.fetcher.fetch_and_parse_content(url, "json")
|
||||||
|
if response.get("rate").get("remaining") == 0:
|
||||||
|
raise Exception("Please try again later, you have exhausted your GitHub REST API request quota")
|
||||||
|
|
||||||
|
def get_list_branches(self, owner, repo):
|
||||||
|
self.check_ratelimit()
|
||||||
|
|
||||||
|
url = f"https://api.github.com/repos/{owner}/{repo}/branches"
|
||||||
|
|
||||||
|
response = self.fetcher.fetch_and_parse_content(url, "json")
|
||||||
|
|
||||||
|
if not response:
|
||||||
|
return []
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def get_latest_artifact(self, owner, repo):
|
||||||
|
results = []
|
||||||
|
|
||||||
|
self.check_ratelimit()
|
||||||
|
|
||||||
|
url = f"https://api.github.com/repos/{owner}/{repo}/actions/artifacts?per_page=1"
|
||||||
|
|
||||||
|
response = self.fetcher.fetch_and_parse_content(url, "json")
|
||||||
|
|
||||||
|
latest_artifact_id = response.get("artifacts")[0].get("id")
|
||||||
|
|
||||||
|
results.append({
|
||||||
|
"product_name": repo,
|
||||||
|
"id": latest_artifact_id,
|
||||||
|
"url": "https://api.github.com/repos/{}/{}/actions/artifacts/{}/{}".format(owner, repo, latest_artifact_id, "zip")
|
||||||
|
})
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def get_latest_release(self, owner, repo):
|
||||||
|
result = []
|
||||||
|
|
||||||
|
self.check_ratelimit()
|
||||||
|
|
||||||
|
url = f"https://api.github.com/repos/{owner}/{repo}/releases?per_page=1"
|
||||||
|
|
||||||
|
response = self.fetcher.fetch_and_parse_content(url, "json")
|
||||||
|
|
||||||
|
# Iterate over the assets in the release
|
||||||
|
for asset in response[0].get("assets"):
|
||||||
|
asset_id = asset.get("id")
|
||||||
|
download_url = asset.get("browser_download_url")
|
||||||
|
asset_name = self.extract_asset_name(asset.get("name"))
|
||||||
|
|
||||||
|
if "apple" in download_url.lower() or ("app" not in download_url.lower() and "dsym" not in download_url.lower() and "adget" not in download_url):
|
||||||
|
if "lzhoang2601" in download_url or "tlwm" in download_url or ("tlwm" not in download_url and "DEBUG" not in download_url.upper()):
|
||||||
|
result.append({
|
||||||
|
"product_name": asset_name,
|
||||||
|
"id": asset_id,
|
||||||
|
"url": download_url
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def extract_asset_name(self, name):
|
||||||
|
# Extract the base name from the asset name
|
||||||
|
name_parts = name.split("-") if "-" in name else name.split("_")
|
||||||
|
|
||||||
|
asset_name = name_parts[0].split(".")[0]
|
||||||
|
if asset_name[-1].isdigit():
|
||||||
|
asset_name = asset_name[:-1]
|
||||||
|
|
||||||
|
if (len(name_parts) > 1):
|
||||||
|
if "uns" in name_parts[1]:
|
||||||
|
asset_name += "-" + name_parts[1]
|
||||||
|
elif "Sonoma14.4" in name:
|
||||||
|
asset_name += "23.4"
|
||||||
|
elif "Sonoma" in name:
|
||||||
|
asset_name += "23"
|
||||||
|
elif "Ventura" in name:
|
||||||
|
asset_name += "22"
|
||||||
|
elif "Monterey" in name:
|
||||||
|
asset_name += "21"
|
||||||
|
elif "Catalina" in name:
|
||||||
|
asset_name += "19"
|
||||||
|
elif "Mojave" in name:
|
||||||
|
asset_name += "18"
|
||||||
|
elif "HighSierra" in name:
|
||||||
|
asset_name += "17"
|
||||||
|
elif "BigSur" in name:
|
||||||
|
asset_name += "20"
|
||||||
|
|
||||||
|
return asset_name
|
||||||
774
Scripts/kext_maestro.py
Executable file
774
Scripts/kext_maestro.py
Executable file
@@ -0,0 +1,774 @@
|
|||||||
|
|
||||||
|
from Scripts.datasets import cpu_data
|
||||||
|
from Scripts.datasets import pci_data
|
||||||
|
from Scripts import utils
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
class KextMaestro:
|
||||||
|
def __init__(self):
|
||||||
|
self.utils = utils.Utils()
|
||||||
|
self.matching_keys = [
|
||||||
|
"IOPCIMatch",
|
||||||
|
"IONameMatch",
|
||||||
|
"IOPCIPrimaryMatch",
|
||||||
|
"idProduct",
|
||||||
|
"idVendor",
|
||||||
|
"HDAConfigDefault"
|
||||||
|
]
|
||||||
|
self.ock_files_dir = os.path.join(os.getcwd(), "OCK_Files")
|
||||||
|
self.kext_loading_sequence = [
|
||||||
|
{
|
||||||
|
"MainKext": "Lilu",
|
||||||
|
"BundlePath": "Lilu.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/Lilu",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VirtualSMC",
|
||||||
|
"BundlePath": "VirtualSMC.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VirtualSMC",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "ECEnabler",
|
||||||
|
"BundlePath": "ECEnabler.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/ECEnabler",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VirtualSMC",
|
||||||
|
"BundlePath": "SMCBatteryManager.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/SMCBatteryManager",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VirtualSMC",
|
||||||
|
"BundlePath": "SMCDellSensors.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/SMCDellSensors",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VirtualSMC",
|
||||||
|
"BundlePath": "SMCLightSensor.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/SMCLightSensor",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VirtualSMC",
|
||||||
|
"BundlePath": "SMCProcessor.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/SMCProcessor",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VirtualSMC",
|
||||||
|
"BundlePath": "SMCSuperIO.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/SMCSuperIO",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "WhateverGreen",
|
||||||
|
"BundlePath": "WhateverGreen.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/WhateverGreen",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "NootedRed",
|
||||||
|
"BundlePath": "NootedRed.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/NootedRed",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "NootRX",
|
||||||
|
"BundlePath": "NootRX.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/NootRX",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "AppleALC",
|
||||||
|
"BundlePath": "AppleALC.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/AppleALC",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "AirportItlwm",
|
||||||
|
"BundlePath": "AirportItlwm.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/AirportItlwm",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "itlwm",
|
||||||
|
"BundlePath": "itlwm.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/itlwm",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "IOSkywalkFamily",
|
||||||
|
"BundlePath": "IOSkywalkFamily.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/IOSkywalkFamily",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "IO80211FamilyLegacy",
|
||||||
|
"BundlePath": "IO80211FamilyLegacy.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/IO80211FamilyLegacy",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "IO80211FamilyLegacy",
|
||||||
|
"BundlePath": "IO80211FamilyLegacy.kext/Contents/PlugIns/AirPortBrcmNIC.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/AirPortBrcmNIC",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "AirportBrcmFixup",
|
||||||
|
"BundlePath": "AirportBrcmFixup.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/AirportBrcmFixup",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "AirportBrcmFixup",
|
||||||
|
"BundlePath": "AirportBrcmFixup.kext/Contents/PlugIns/AirPortBrcm4360_Injector.kext",
|
||||||
|
"ExecutablePath": "",
|
||||||
|
"MaxKernel": "19.99.99",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "AirportBrcmFixup",
|
||||||
|
"BundlePath": "AirportBrcmFixup.kext/Contents/PlugIns/AirPortBrcmNIC_Injector.kext",
|
||||||
|
"ExecutablePath": "",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "IntelBluetoothFirmware",
|
||||||
|
"BundlePath": "IntelBluetoothFirmware.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/IntelBluetoothFirmware",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "IntelBluetoothFirmware",
|
||||||
|
"BundlePath": "IntelBTPatcher.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/IntelBTPatcher",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "IntelBluetoothFirmware",
|
||||||
|
"BundlePath": "IntelBluetoothInjector.kext",
|
||||||
|
"ExecutablePath": "",
|
||||||
|
"MaxKernel": "20.99.99",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "BlueToolFixup",
|
||||||
|
"BundlePath": "BlueToolFixup.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/BlueToolFixup",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": "21.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "BrcmPatchRAM",
|
||||||
|
"BundlePath": "BrcmBluetoothInjector.kext",
|
||||||
|
"ExecutablePath": "",
|
||||||
|
"MaxKernel": "20.99.99",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "BrcmPatchRAM",
|
||||||
|
"BundlePath": "BrcmFirmwareData.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/BrcmFirmwareData",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "BrcmPatchRAM",
|
||||||
|
"BundlePath": "BrcmPatchRAM2.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/BrcmPatchRAM2",
|
||||||
|
"MaxKernel": "18.99.99",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "BrcmPatchRAM",
|
||||||
|
"BundlePath": "BrcmPatchRAM3.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/BrcmPatchRAM3",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": "19.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "AppleIGC",
|
||||||
|
"BundlePath": "AppleIGC.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/AppleIGC",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "AtherosE2200Ethernet",
|
||||||
|
"BundlePath": "AtherosE2200Ethernet.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/AtherosE2200Ethernet",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "IntelMausi",
|
||||||
|
"BundlePath": "IntelMausi.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/IntelMausi",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "LucyRTL8125Ethernet",
|
||||||
|
"BundlePath": "LucyRTL8125Ethernet.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/LucyRTL8125Ethernet",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "NullEthernet",
|
||||||
|
"BundlePath": "NullEthernet.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/NullEthernet",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "RealtekRTL8100",
|
||||||
|
"BundlePath": "RealtekRTL8100.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/RealtekRTL8100",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "RealtekRTL8111",
|
||||||
|
"BundlePath": "RealtekRTL8111.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/RealtekRTL8111",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "BrightnessKeys",
|
||||||
|
"BundlePath": "BrightnessKeys.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/BrightnessKeys",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "AsusSMC",
|
||||||
|
"BundlePath": "AsusSMC.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/AsusSMC",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooInput",
|
||||||
|
"BundlePath": "VoodooInput.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooInput",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooPS2",
|
||||||
|
"BundlePath": "VoodooPS2Controller.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooPS2Controller",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooPS2",
|
||||||
|
"BundlePath": "VoodooPS2Controller.kext/Contents/PlugIns/VoodooPS2Keyboard.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooPS2Keyboard",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooPS2",
|
||||||
|
"BundlePath": "VoodooPS2Controller.kext/Contents/PlugIns/VoodooPS2Mouse.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooPS2Mouse",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooPS2",
|
||||||
|
"BundlePath": "VoodooPS2Controller.kext/Contents/PlugIns/VoodooPS2Trackpad.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooPS2Trackpad",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooRMI",
|
||||||
|
"BundlePath": "VoodooRMI.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooRMI",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooRMI",
|
||||||
|
"BundlePath": "VoodooSMBus.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooSMBus",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooSMBus",
|
||||||
|
"BundlePath": "VoodooSMBus.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooSMBus",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooRMI",
|
||||||
|
"BundlePath": "VoodooRMI.kext/Contents/PlugIns/RMISMBus.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/RMISMBus",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooI2C",
|
||||||
|
"BundlePath": "VoodooI2C.kext/Contents/PlugIns/VoodooI2CServices.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooI2CServices",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooI2C",
|
||||||
|
"BundlePath": "VoodooI2C.kext/Contents/PlugIns/VoodooGPIO.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooGPIO",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooI2C",
|
||||||
|
"BundlePath": "VoodooI2C.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooI2C",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "BigSurface",
|
||||||
|
"BundlePath": "BigSurface.kext/Contents/PlugIns/VoodooInput.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooInput",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "BigSurface",
|
||||||
|
"BundlePath": "BigSurface.kext/Contents/PlugIns/VoodooGPIO.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooGPIO",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "BigSurface",
|
||||||
|
"BundlePath": "BigSurface.kext/Contents/PlugIns/VoodooSerial.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooSerial",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "BigSurface",
|
||||||
|
"BundlePath": "BigSurface.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/BigSurface",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "BigSurface",
|
||||||
|
"BundlePath": "BigSurface.kext/Contents/PlugIns/BigSurfaceHIDDriver.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/BigSurfaceHIDDriver",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooRMI",
|
||||||
|
"BundlePath": "VoodooRMI.kext/Contents/PlugIns/RMII2C.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/RMII2C",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "lzh",
|
||||||
|
"BundlePath": "VoodooI2CELAN.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooI2CELAN",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "VoodooI2C",
|
||||||
|
"BundlePath": "VoodooI2CHID.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooI2CHID",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "AlpsHID",
|
||||||
|
"BundlePath": "AlpsHID.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/AlpsHID",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "lzh",
|
||||||
|
"BundlePath": "VoodooI2CSynaptics.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/VoodooI2CSynaptics",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "AppleMCEReporterDisabler",
|
||||||
|
"BundlePath": "AppleMCEReporterDisabler.kext",
|
||||||
|
"ExecutablePath": "",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": "21.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "AMFIPass",
|
||||||
|
"BundlePath": "AMFIPass.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/AMFIPass",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "CpuTopologyRebuild",
|
||||||
|
"BundlePath": "CpuTopologyRebuild.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/CpuTopologyRebuild",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "CtlnaAHCIPort",
|
||||||
|
"BundlePath": "CtlnaAHCIPort.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/CtlnaAHCIPort",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "RealtekCardReader",
|
||||||
|
"BundlePath": "RealtekCardReader.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/RealtekCardReader",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "RealtekCardReaderFriend",
|
||||||
|
"BundlePath": "RealtekCardReaderFriend.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/RealtekCardReaderFriend",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "ForgedInvariant",
|
||||||
|
"BundlePath": "ForgedInvariant.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/ForgedInvariant",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "RestrictEvents",
|
||||||
|
"BundlePath": "RestrictEvents.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/RestrictEvents",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "HibernationFixup",
|
||||||
|
"BundlePath": "HibernationFixup.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/HibernationFixup",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "RTCMemoryFixup",
|
||||||
|
"BundlePath": "RTCMemoryFixup.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/RTCMemoryFixup",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "NVMeFix",
|
||||||
|
"BundlePath": "NVMeFix.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/NVMeFix",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": "18.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "CryptexFixup",
|
||||||
|
"BundlePath": "CryptexFixup.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/CryptexFixup",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "GenericUSBXHCI",
|
||||||
|
"BundlePath": "GenericUSBXHCI.kext",
|
||||||
|
"ExecutablePath": "Contents/MacOS/GenericUSBXHCI",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "XHCI-unsupported",
|
||||||
|
"BundlePath": "XHCI-unsupported.kext",
|
||||||
|
"ExecutablePath": "",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MainKext": "USBMap",
|
||||||
|
"BundlePath": "USBMap.kext",
|
||||||
|
"ExecutablePath": "",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
self.latest_macos_version = "24.99.99"
|
||||||
|
|
||||||
|
def extract_pci_id(self, kext_path):
|
||||||
|
if not os.path.exists(kext_path):
|
||||||
|
return []
|
||||||
|
|
||||||
|
plist_path = os.path.join(kext_path, "Contents", "Info.plist")
|
||||||
|
plist_data = self.utils.read_file(plist_path)
|
||||||
|
|
||||||
|
pci_ids = []
|
||||||
|
|
||||||
|
# Iterate through the personalities in the plist
|
||||||
|
for personality_name, properties in plist_data.get("IOKitPersonalities", {}).items():
|
||||||
|
matching_keys = [key for key in self.matching_keys if key in properties]
|
||||||
|
|
||||||
|
if not matching_keys:
|
||||||
|
continue
|
||||||
|
|
||||||
|
match_key = matching_keys[0]
|
||||||
|
|
||||||
|
if match_key in ["IOPCIMatch", "IOPCIPrimaryMatch"]:
|
||||||
|
# Split PCI IDs and format them
|
||||||
|
pci_list = properties[match_key].split(" ")
|
||||||
|
for pci_id in pci_list:
|
||||||
|
vendor_id = pci_id[-4:]
|
||||||
|
device_id = pci_id[2:6]
|
||||||
|
pci_ids.append(f"{vendor_id}-{device_id}".upper())
|
||||||
|
elif match_key == "IONameMatch":
|
||||||
|
# Process IONameMatch keys
|
||||||
|
for pci_id in properties[match_key]:
|
||||||
|
vendor_id = pci_id[3:7]
|
||||||
|
device_id = pci_id[-4:]
|
||||||
|
pci_ids.append(f"{vendor_id}-{device_id}".upper())
|
||||||
|
elif match_key == "idProduct":
|
||||||
|
# Process idProduct and idVendor
|
||||||
|
vendor_id = self.utils.int_to_hex(properties["idVendor"]).zfill(4)
|
||||||
|
device_id = self.utils.int_to_hex(properties["idProduct"]).zfill(4)
|
||||||
|
pci_ids.append(f"{vendor_id}-{device_id}".upper())
|
||||||
|
elif match_key == "HDAConfigDefault":
|
||||||
|
# Handle AppleALC configurations
|
||||||
|
for codec_layout in properties[match_key]:
|
||||||
|
codec_id = self.utils.int_to_hex(codec_layout.get("CodecID")).zfill(8)
|
||||||
|
pci_ids.append(f"{codec_id[:4]}-{codec_id[-4:]}")
|
||||||
|
pci_ids = sorted(list(set(pci_ids)))
|
||||||
|
|
||||||
|
return pci_ids
|
||||||
|
|
||||||
|
def gathering_kexts(self, motherboard_name, platform, cpu_configuration, cpu_manufacturer, cpu_codename, discrete_gpu_codename, integrated_gpu, wifi_pci, ethernet_pci, bluetooth, codec_id, input, sd_controller, storage_controllers, usb_controllers, smbios, custom_cpu_name, tsc_sync, battery_status_patch_needed, macos_version):
|
||||||
|
kexts = [
|
||||||
|
"Lilu",
|
||||||
|
"VirtualSMC",
|
||||||
|
"USBMap"
|
||||||
|
]
|
||||||
|
|
||||||
|
if macos_version > 22 or custom_cpu_name or "MacPro7,1" in smbios:
|
||||||
|
kexts.append("RestrictEvents")
|
||||||
|
|
||||||
|
if codec_id in pci_data.CodecIDs:
|
||||||
|
kexts.append("AppleALC")
|
||||||
|
|
||||||
|
if "AMD" in cpu_manufacturer and macos_version > 21 or int(cpu_configuration) > 1 and macos_version > 18:
|
||||||
|
kexts.append("AppleMCEReporterDisabler")
|
||||||
|
|
||||||
|
if macos_version > 21 and self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, end=2):
|
||||||
|
kexts.append("CryptexFixup")
|
||||||
|
|
||||||
|
if self.utils.contains_any(cpu_data.IntelCPUGenerations, cpu_codename, start=13):
|
||||||
|
kexts.append("CpuTopologyRebuild")
|
||||||
|
|
||||||
|
if tsc_sync:
|
||||||
|
kexts.append("ForgedInvariant")
|
||||||
|
|
||||||
|
if "AMD" in cpu_manufacturer and integrated_gpu and not discrete_gpu_codename:
|
||||||
|
kexts.append("NootedRed")
|
||||||
|
else:
|
||||||
|
kexts.append("NootRX" if "Navi 2" in discrete_gpu_codename else "WhateverGreen")
|
||||||
|
|
||||||
|
if wifi_pci and wifi_pci in pci_data.NetworkIDs:
|
||||||
|
if wifi_pci.startswith("14E4"):
|
||||||
|
if wifi_pci in ["14E4-43A0", "14E4-43A3", "14E4-43BA"]:
|
||||||
|
if macos_version > 22:
|
||||||
|
kexts.extend(["AirportBrcmFixup", "IOSkywalkFamily", "IO80211FamilyLegacy", "AMFIPass"])
|
||||||
|
elif wifi_pci in pci_data.NetworkIDs:
|
||||||
|
kexts.append("AirportBrcmFixup")
|
||||||
|
elif wifi_pci.startswith("8086"):
|
||||||
|
kexts.append("AirportItlwm" if macos_version < 23 else "itlwm")
|
||||||
|
|
||||||
|
if not ethernet_pci or not (ethernet_pci[0] in pci_data.NetworkIDs or ethernet_pci[-1] in pci_data.NetworkIDs):
|
||||||
|
kexts.append("NullEthernet")
|
||||||
|
else:
|
||||||
|
for pci_id in ethernet_pci:
|
||||||
|
idx = pci_data.NetworkIDs.index(pci_id)
|
||||||
|
|
||||||
|
if 108 <= idx <= 114:
|
||||||
|
kexts.append("AppleIGC")
|
||||||
|
elif 115 <= idx <= 121:
|
||||||
|
kexts.append("AtherosE2200Ethernet")
|
||||||
|
elif 122 <= idx <= 172:
|
||||||
|
kexts.append("IntelMausi")
|
||||||
|
elif 173 <= idx <= 175:
|
||||||
|
kexts.append("LucyRTL8125Ethernet")
|
||||||
|
elif idx == 176:
|
||||||
|
kexts.append("RealtekRTL8100")
|
||||||
|
elif 177 <= idx <= 180:
|
||||||
|
kexts.append("RealtekRTL8111")
|
||||||
|
|
||||||
|
if bluetooth and macos_version > 20 and not wifi_pci in ["14E4-43A0", "14E4-43A3", "14E4-43BA"]:
|
||||||
|
kexts.append("BlueToolFixup")
|
||||||
|
for usb_id in bluetooth:
|
||||||
|
if usb_id in pci_data.BluetoothIDs:
|
||||||
|
idx = pci_data.BluetoothIDs.index(usb_id)
|
||||||
|
|
||||||
|
if idx < 99:
|
||||||
|
kexts.append("BrcmPatchRAM")
|
||||||
|
else:
|
||||||
|
kexts.append("IntelBluetoothFirmware")
|
||||||
|
|
||||||
|
if "Laptop" in platform:
|
||||||
|
if "SURFACE" in motherboard_name:
|
||||||
|
kexts.append("BigSurface")
|
||||||
|
else:
|
||||||
|
if "ASUS" in motherboard_name:
|
||||||
|
kexts.append("AsusSMC")
|
||||||
|
kexts.append("BrightnessKeys")
|
||||||
|
|
||||||
|
for device_name, device_props in input.items():
|
||||||
|
if not device_props.get("Bus Type", "").startswith("ACPI"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if "PS/2" in device_name:
|
||||||
|
kexts.extend(["VoodooInput", "VoodooPS2"])
|
||||||
|
if "I2C" in device_name:
|
||||||
|
kexts.extend(["VoodooInput", "VoodooI2C"])
|
||||||
|
|
||||||
|
device_id = device_props.get("Device ID")
|
||||||
|
if device_id in pci_data.InputIDs:
|
||||||
|
idx = pci_data.InputIDs.index(device_id)
|
||||||
|
|
||||||
|
if idx < 77:
|
||||||
|
kexts.append("AlpsHID")
|
||||||
|
elif 76 < idx < 80:
|
||||||
|
kexts.append("VoodooSMBus")
|
||||||
|
else:
|
||||||
|
kexts.append("VoodooRMI")
|
||||||
|
|
||||||
|
if "Laptop" in platform and "SURFACE" not in motherboard_name and battery_status_patch_needed:
|
||||||
|
kexts.append("ECEnabler")
|
||||||
|
|
||||||
|
if sd_controller and sd_controller.get("Device ID") in pci_data.RealtekCardReaderIDs:
|
||||||
|
kexts.extend(["RealtekCardReader", "RealtekCardReaderFriend"])
|
||||||
|
|
||||||
|
for controller_name, controller_props in storage_controllers.items():
|
||||||
|
if "NVMe" in controller_name or "NVM Express" in controller_props.get("Device Description"):
|
||||||
|
kexts.append("NVMeFix")
|
||||||
|
else:
|
||||||
|
if controller_props.get("Device ID") in pci_data.UnsupportedSATAControllerIDs:
|
||||||
|
kexts.append("CtlnaAHCIPort")
|
||||||
|
|
||||||
|
for pci_id in usb_controllers:
|
||||||
|
if pci_id in pci_data.UnsupportedUSBControllerIDs:
|
||||||
|
idx = pci_data.UnsupportedUSBControllerIDs.index(pci_id)
|
||||||
|
if idx == 0:
|
||||||
|
kexts.append("GenericUSBXHCI")
|
||||||
|
else:
|
||||||
|
kexts.append("XHCI-unsupported")
|
||||||
|
|
||||||
|
return list(set(kexts))
|
||||||
|
|
||||||
|
def install_kexts_to_efi(self, kexts, macos_version, kexts_directory):
|
||||||
|
for kext_name in kexts:
|
||||||
|
if "AirportItlwm" in kext_name:
|
||||||
|
kext_name = f"{kext_name}{macos_version}"
|
||||||
|
elif "BlueToolFixup" in kext_name or "BrcmPatchRAM" in kext_name:
|
||||||
|
kext_name = "BrcmPatchRAM"
|
||||||
|
|
||||||
|
source_kext_dir = os.path.join(self.ock_files_dir, kext_name)
|
||||||
|
if os.path.exists(source_kext_dir):
|
||||||
|
shutil.copytree(source_kext_dir, kexts_directory, dirs_exist_ok=True)
|
||||||
|
|
||||||
|
def load_kexts(self, kexts, motherboard_name, platform, cpu_manufacturer, discrete_gpu_codename, macos_version):
|
||||||
|
kernel_add = []
|
||||||
|
unload_kext = []
|
||||||
|
|
||||||
|
if not "DELL" in motherboard_name:
|
||||||
|
unload_kext.append("SMCDellSensors")
|
||||||
|
if "Desktop" in platform:
|
||||||
|
unload_kext.extend([
|
||||||
|
"SMCBatteryManager",
|
||||||
|
"SMCLightSensor"
|
||||||
|
])
|
||||||
|
if "AMD" in cpu_manufacturer:
|
||||||
|
unload_kext.extend(["SMCProcessor", "SMCSuperIO"])
|
||||||
|
if "Navi 2" in discrete_gpu_codename:
|
||||||
|
unload_kext.append("SMCSuperIO")
|
||||||
|
elif "Laptop" in platform and not "SURFACE" in motherboard_name:
|
||||||
|
if "AMD" in cpu_manufacturer:
|
||||||
|
unload_kext.extend([
|
||||||
|
"SMCProcessor",
|
||||||
|
"SMCSuperIO"
|
||||||
|
])
|
||||||
|
|
||||||
|
if "VoodooSMBus" in kexts:
|
||||||
|
unload_kext.append("VoodooPS2Mouse")
|
||||||
|
elif "VoodooRMI" in kexts:
|
||||||
|
if not "VoodooI2C" in kexts:
|
||||||
|
unload_kext.append("RMII2C")
|
||||||
|
else:
|
||||||
|
unload_kext.extend([
|
||||||
|
"VoodooSMBus",
|
||||||
|
"RMISMBus",
|
||||||
|
"VoodooI2CServices",
|
||||||
|
"VoodooGPIO",
|
||||||
|
"VoodooI2CHID"
|
||||||
|
])
|
||||||
|
|
||||||
|
for kext in self.kext_loading_sequence:
|
||||||
|
if not kext.get("MainKext") in kexts or os.path.splitext(os.path.basename(kext.get("BundlePath")))[0] in unload_kext:
|
||||||
|
continue
|
||||||
|
max_supported_macos_version = kext.get("MaxKernel") or self.latest_macos_version
|
||||||
|
min_supported_macos_version = kext.get("MinKernel") or "17.0.0"
|
||||||
|
if not min_supported_macos_version[:2] <= str(macos_version) <= max_supported_macos_version[:2]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
kernel_add.append({
|
||||||
|
"Arch": "x86_64",
|
||||||
|
"BundlePath": kext.get("BundlePath"),
|
||||||
|
"Comment": "",
|
||||||
|
"Enabled": True,
|
||||||
|
"ExecutablePath": kext.get("ExecutablePath") or "",
|
||||||
|
"MaxKernel": "",
|
||||||
|
"MinKernel": "",
|
||||||
|
"PlistPath": "Contents/Info.plist"
|
||||||
|
})
|
||||||
|
|
||||||
|
return kernel_add
|
||||||
69
Scripts/resource_fetcher.py
Executable file
69
Scripts/resource_fetcher.py
Executable file
@@ -0,0 +1,69 @@
|
|||||||
|
import requests
|
||||||
|
import ssl
|
||||||
|
import os
|
||||||
|
import certifi
|
||||||
|
import zipfile
|
||||||
|
import plistlib
|
||||||
|
|
||||||
|
class ResourceFetcher:
|
||||||
|
def __init__(self, headers = None):
|
||||||
|
self.request_headers = headers
|
||||||
|
self.buffer_size = 16*1024
|
||||||
|
self.ssl_context = self.create_ssl_context()
|
||||||
|
|
||||||
|
def create_ssl_context(self):
|
||||||
|
try:
|
||||||
|
cafile = ssl.get_default_verify_paths().openssl_cafile
|
||||||
|
if not os.path.exists(cafile):
|
||||||
|
cafile = certifi.where()
|
||||||
|
ssl_context = ssl.create_default_context(cafile=cafile)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"SSL Context Creation Error: {e}")
|
||||||
|
ssl_context = ssl._create_unverified_context()
|
||||||
|
return ssl_context
|
||||||
|
|
||||||
|
def fetch_and_parse_content(self, resource_url, content_type=None):
|
||||||
|
response = requests.get(resource_url, headers=self.request_headers, verify=self.ssl_context.verify_mode != ssl.CERT_NONE)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
if content_type == 'json':
|
||||||
|
return response.json()
|
||||||
|
elif content_type == 'plist':
|
||||||
|
return plistlib.loads(response.content)
|
||||||
|
else:
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
def download_and_save_file(self, resource_url, destination_path, extract=True):
|
||||||
|
with requests.get(resource_url, headers=self.request_headers, stream=True, verify=self.ssl_context.verify_mode != ssl.CERT_NONE) as response:
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
try:
|
||||||
|
total_size = int(response.headers.get('Content-Length', -1))
|
||||||
|
except ValueError:
|
||||||
|
total_size = -1
|
||||||
|
|
||||||
|
bytes_downloaded = 0
|
||||||
|
|
||||||
|
print(f"Download from {resource_url}")
|
||||||
|
|
||||||
|
with open(destination_path, 'wb') as file_writer:
|
||||||
|
while True:
|
||||||
|
chunk = response.raw.read(self.buffer_size)
|
||||||
|
if not chunk:
|
||||||
|
break
|
||||||
|
file_writer.write(chunk)
|
||||||
|
bytes_downloaded += len(chunk)
|
||||||
|
if total_size != -1:
|
||||||
|
print(f"Downloaded {bytes_downloaded / (1024 * 1024):.2f} MB of {total_size / (1024 * 1024):.2f} MB", end='\r')
|
||||||
|
|
||||||
|
if extract and destination_path.lower().endswith('.zip'):
|
||||||
|
self.extract_zip_file(destination_path)
|
||||||
|
|
||||||
|
def extract_zip_file(self, zip_path, extraction_directory=None):
|
||||||
|
if extraction_directory is None:
|
||||||
|
extraction_directory = os.path.splitext(zip_path)[0]
|
||||||
|
|
||||||
|
os.makedirs(extraction_directory, exist_ok=True)
|
||||||
|
|
||||||
|
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
||||||
|
zip_ref.extractall(extraction_directory)
|
||||||
154
Scripts/run.py
Executable file
154
Scripts/run.py
Executable file
@@ -0,0 +1,154 @@
|
|||||||
|
# Original source:
|
||||||
|
# https://github.com/corpnewt/SSDTTime/blob/7b3fb78112bf320a1bc6a7e50dddb2b375cb70b0/Scripts/run.py
|
||||||
|
|
||||||
|
import sys, subprocess, time, threading, shlex
|
||||||
|
try:
|
||||||
|
from Queue import Queue, Empty
|
||||||
|
except:
|
||||||
|
from queue import Queue, Empty
|
||||||
|
|
||||||
|
ON_POSIX = 'posix' in sys.builtin_module_names
|
||||||
|
|
||||||
|
class Run:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
return
|
||||||
|
|
||||||
|
def _read_output(self, pipe, q):
|
||||||
|
try:
|
||||||
|
for line in iter(lambda: pipe.read(1), b''):
|
||||||
|
q.put(line)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
pipe.close()
|
||||||
|
|
||||||
|
def _create_thread(self, output):
|
||||||
|
# Creates a new queue and thread object to watch based on the output pipe sent
|
||||||
|
q = Queue()
|
||||||
|
t = threading.Thread(target=self._read_output, args=(output, q))
|
||||||
|
t.daemon = True
|
||||||
|
return (q,t)
|
||||||
|
|
||||||
|
def _stream_output(self, comm, shell = False):
|
||||||
|
output = error = ""
|
||||||
|
p = None
|
||||||
|
try:
|
||||||
|
if shell and type(comm) is list:
|
||||||
|
comm = " ".join(shlex.quote(x) for x in comm)
|
||||||
|
if not shell and type(comm) is str:
|
||||||
|
comm = shlex.split(comm)
|
||||||
|
p = subprocess.Popen(comm, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0, universal_newlines=True, close_fds=ON_POSIX)
|
||||||
|
# Setup the stdout thread/queue
|
||||||
|
q,t = self._create_thread(p.stdout)
|
||||||
|
qe,te = self._create_thread(p.stderr)
|
||||||
|
# Start both threads
|
||||||
|
t.start()
|
||||||
|
te.start()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
c = z = ""
|
||||||
|
try: c = q.get_nowait()
|
||||||
|
except Empty: pass
|
||||||
|
else:
|
||||||
|
sys.stdout.write(c)
|
||||||
|
output += c
|
||||||
|
sys.stdout.flush()
|
||||||
|
try: z = qe.get_nowait()
|
||||||
|
except Empty: pass
|
||||||
|
else:
|
||||||
|
sys.stderr.write(z)
|
||||||
|
error += z
|
||||||
|
sys.stderr.flush()
|
||||||
|
if not c==z=="": continue # Keep going until empty
|
||||||
|
# No output - see if still running
|
||||||
|
p.poll()
|
||||||
|
if p.returncode != None:
|
||||||
|
# Subprocess ended
|
||||||
|
break
|
||||||
|
# No output, but subprocess still running - stall for 20ms
|
||||||
|
time.sleep(0.02)
|
||||||
|
|
||||||
|
o, e = p.communicate()
|
||||||
|
return (output+o, error+e, p.returncode)
|
||||||
|
except:
|
||||||
|
if p:
|
||||||
|
try: o, e = p.communicate()
|
||||||
|
except: o = e = ""
|
||||||
|
return (output+o, error+e, p.returncode)
|
||||||
|
return ("", "Command not found!", 1)
|
||||||
|
|
||||||
|
def _decode(self, value, encoding="utf-8", errors="ignore"):
|
||||||
|
# Helper method to only decode if bytes type
|
||||||
|
if sys.version_info >= (3,0) and isinstance(value, bytes):
|
||||||
|
return value.decode(encoding,errors)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def _run_command(self, comm, shell = False):
|
||||||
|
c = None
|
||||||
|
try:
|
||||||
|
if shell and type(comm) is list:
|
||||||
|
comm = " ".join(shlex.quote(x) for x in comm)
|
||||||
|
if not shell and type(comm) is str:
|
||||||
|
comm = shlex.split(comm)
|
||||||
|
p = subprocess.Popen(comm, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
c = p.communicate()
|
||||||
|
except:
|
||||||
|
if c == None:
|
||||||
|
return ("", "Command not found!", 1)
|
||||||
|
return (self._decode(c[0]), self._decode(c[1]), p.returncode)
|
||||||
|
|
||||||
|
def run(self, command_list, leave_on_fail = False):
|
||||||
|
# Command list should be an array of dicts
|
||||||
|
if type(command_list) is dict:
|
||||||
|
# We only have one command
|
||||||
|
command_list = [command_list]
|
||||||
|
output_list = []
|
||||||
|
for comm in command_list:
|
||||||
|
args = comm.get("args", [])
|
||||||
|
shell = comm.get("shell", False)
|
||||||
|
stream = comm.get("stream", False)
|
||||||
|
sudo = comm.get("sudo", False)
|
||||||
|
stdout = comm.get("stdout", False)
|
||||||
|
stderr = comm.get("stderr", False)
|
||||||
|
mess = comm.get("message", None)
|
||||||
|
show = comm.get("show", False)
|
||||||
|
|
||||||
|
if not mess == None:
|
||||||
|
print(mess)
|
||||||
|
|
||||||
|
if not len(args):
|
||||||
|
# nothing to process
|
||||||
|
continue
|
||||||
|
if sudo:
|
||||||
|
# Check if we have sudo
|
||||||
|
out = self._run_command(["which", "sudo"])
|
||||||
|
if "sudo" in out[0]:
|
||||||
|
# Can sudo
|
||||||
|
if type(args) is list:
|
||||||
|
args.insert(0, out[0].replace("\n", "")) # add to start of list
|
||||||
|
elif type(args) is str:
|
||||||
|
args = out[0].replace("\n", "") + " " + args # add to start of string
|
||||||
|
|
||||||
|
if show:
|
||||||
|
print(" ".join(args))
|
||||||
|
|
||||||
|
if stream:
|
||||||
|
# Stream it!
|
||||||
|
out = self._stream_output(args, shell)
|
||||||
|
else:
|
||||||
|
# Just run and gather output
|
||||||
|
out = self._run_command(args, shell)
|
||||||
|
if stdout and len(out[0]):
|
||||||
|
print(out[0])
|
||||||
|
if stderr and len(out[1]):
|
||||||
|
print(out[1])
|
||||||
|
# Append output
|
||||||
|
output_list.append(out)
|
||||||
|
# Check for errors
|
||||||
|
if leave_on_fail and out[2] != 0:
|
||||||
|
# Got an error - leave
|
||||||
|
break
|
||||||
|
if len(output_list) == 1:
|
||||||
|
# We only ran one command - just return that output
|
||||||
|
return output_list[0]
|
||||||
|
return output_list
|
||||||
58
Scripts/smbios.py
Executable file
58
Scripts/smbios.py
Executable file
@@ -0,0 +1,58 @@
|
|||||||
|
from Scripts import gathering_files
|
||||||
|
from Scripts import utils
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import uuid
|
||||||
|
import random
|
||||||
|
|
||||||
|
class SMBIOS:
|
||||||
|
def __init__(self):
|
||||||
|
self.g = gathering_files.gatheringFiles()
|
||||||
|
self.utils = utils.Utils()
|
||||||
|
self.script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
self.macserial = self.check_macserial()
|
||||||
|
|
||||||
|
def check_macserial(self, quit=False):
|
||||||
|
macserial_name = "macserial.exe" if os.name == "nt" else "macserial"
|
||||||
|
macserial_path = os.path.join(self.script_dir, macserial_name)
|
||||||
|
|
||||||
|
if not os.path.exists(macserial_path):
|
||||||
|
download_history = self.utils.read_file(self.g.download_history_file)
|
||||||
|
|
||||||
|
if download_history:
|
||||||
|
product_index = self.g.product_index_in_history("OpenCore", download_history["versions"])
|
||||||
|
|
||||||
|
if product_index:
|
||||||
|
download_history["versions"].pop(product_index)
|
||||||
|
download_history["last_updated"] = "2024-07-25T12:00:00"
|
||||||
|
self.utils.write_file(self.g.download_history_file, download_history)
|
||||||
|
|
||||||
|
if quit:
|
||||||
|
raise Exception(f"{macserial_name} not found. Please reopen the program to download it")
|
||||||
|
else:
|
||||||
|
return macserial_path
|
||||||
|
|
||||||
|
def generate_random_mac(self):
|
||||||
|
random_mac = ''.join([format(random.randint(0, 255), '02X') for _ in range(6)])
|
||||||
|
return random_mac
|
||||||
|
|
||||||
|
def generate(self, product_name):
|
||||||
|
if not self.macserial:
|
||||||
|
self.check_macserial(True)
|
||||||
|
|
||||||
|
random_mac_address = self.generate_random_mac()
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
[self.macserial, "-g", "--model", product_name],
|
||||||
|
capture_output=True,
|
||||||
|
check=True, # Raises CalledProcessError for non-zero return code
|
||||||
|
)
|
||||||
|
first_serial = result.stdout.decode().splitlines()[0]
|
||||||
|
|
||||||
|
return {
|
||||||
|
"MLB": "A" + "0"*15 + "Z" if " | " in first_serial else first_serial.split(" | ")[-1],
|
||||||
|
"ROM": random_mac_address,
|
||||||
|
"SystemProductName": product_name,
|
||||||
|
"SystemSerialNumber": "A" + "0"*10 + "9" if " | " in first_serial else first_serial.split(" | ")[0],
|
||||||
|
"SystemUUID": str(uuid.uuid4()).upper(),
|
||||||
|
}
|
||||||
244
Scripts/utils.py
Executable file
244
Scripts/utils.py
Executable file
@@ -0,0 +1,244 @@
|
|||||||
|
from Scripts import resource_fetcher
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import plistlib
|
||||||
|
import shutil
|
||||||
|
import re
|
||||||
|
import binascii
|
||||||
|
import subprocess
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
class Utils:
|
||||||
|
def __init__(self, script_name = "OpCore Simplify"):
|
||||||
|
self.script_name = script_name
|
||||||
|
self.fetcher = resource_fetcher.ResourceFetcher({
|
||||||
|
"Accept": "application/vnd.github+json",
|
||||||
|
"X-GitHub-Api-Version": "2022-11-28",
|
||||||
|
})
|
||||||
|
self.repo_url = "https://raw.githubusercontent.com/lzhoang2801/OpCore-Simplify/main/version.json"
|
||||||
|
|
||||||
|
def write_file(self, file_path, data):
|
||||||
|
file_extension = os.path.splitext(file_path)[1]
|
||||||
|
|
||||||
|
with open(file_path, "w" if file_extension == ".json" else "wb") as file:
|
||||||
|
if file_extension == ".json":
|
||||||
|
json.dump(data, file, indent=4)
|
||||||
|
else:
|
||||||
|
if file_extension == ".plist":
|
||||||
|
data = plistlib.dumps(data)
|
||||||
|
|
||||||
|
file.write(data)
|
||||||
|
|
||||||
|
def read_file(self, file_path):
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
return None
|
||||||
|
|
||||||
|
file_extension = os.path.splitext(file_path)[1]
|
||||||
|
|
||||||
|
with open(file_path, "r" if file_extension == ".json" else "rb") as file_handle:
|
||||||
|
if file_extension == ".plist":
|
||||||
|
data = plistlib.load(file_handle)
|
||||||
|
elif file_extension == ".json":
|
||||||
|
data = json.load(file_handle)
|
||||||
|
else:
|
||||||
|
data = file_handle.read()
|
||||||
|
return data
|
||||||
|
|
||||||
|
def search_dict_iter(self, dictionary, search_term, equal=True, reverse=False):
|
||||||
|
dictionary_copy = dictionary.copy()
|
||||||
|
|
||||||
|
if reverse:
|
||||||
|
dictionary_copy = dict(list(dictionary_copy.items())[::-1])
|
||||||
|
|
||||||
|
stack = [(dictionary_copy, None)]
|
||||||
|
|
||||||
|
while stack:
|
||||||
|
current_dict, parent_dict = stack.pop()
|
||||||
|
for key, value in current_dict.items():
|
||||||
|
if equal and value == search_term or not equal and search_term in value:
|
||||||
|
return current_dict
|
||||||
|
if isinstance(value, dict):
|
||||||
|
stack.append((value, current_dict))
|
||||||
|
if equal and key == search_term or not equal and search_term in key:
|
||||||
|
return value
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def recursively_search(self, directory, matching_file_extension=None, matching_file_name_pattern=None, parent_directory=""):
|
||||||
|
matching_paths = []
|
||||||
|
|
||||||
|
if not os.path.exists(directory):
|
||||||
|
print(f"Error: The directory {directory} does not exist.")
|
||||||
|
return matching_paths
|
||||||
|
|
||||||
|
for child_directory in os.listdir(directory):
|
||||||
|
if "MACOSX" in child_directory or "dSYM" in child_directory:
|
||||||
|
continue
|
||||||
|
|
||||||
|
file_name = os.path.splitext(os.path.basename(child_directory))[0]
|
||||||
|
file_extension = os.path.splitext(os.path.basename(child_directory))[1]
|
||||||
|
|
||||||
|
if (matching_file_extension is not None and matching_file_extension == file_extension) or (matching_file_name_pattern is not None and matching_file_name_pattern in file_name):
|
||||||
|
path = os.path.join(parent_directory, child_directory)
|
||||||
|
full_path = os.path.join(directory, child_directory)
|
||||||
|
|
||||||
|
if not os.path.isdir(full_path) or not os.path.exists(os.path.join(full_path, file_name + file_extension)):
|
||||||
|
matching_paths.append(path)
|
||||||
|
|
||||||
|
child_directory = os.path.join(directory, child_directory)
|
||||||
|
if os.path.isdir(child_directory):
|
||||||
|
matching_paths.extend(self.recursively_search(child_directory, matching_file_extension, matching_file_name_pattern, os.path.join(parent_directory, os.path.basename(child_directory))))
|
||||||
|
|
||||||
|
return matching_paths
|
||||||
|
|
||||||
|
def sort_dict_by_key(self, input_dict, sort_key):
|
||||||
|
return dict(sorted(input_dict.items(), key=lambda item: item[1].get(sort_key, "")))
|
||||||
|
|
||||||
|
def mkdirs(self, *directories):
|
||||||
|
for directory in directories:
|
||||||
|
if not os.path.exists(os.path.dirname(directory)):
|
||||||
|
os.makedirs(os.path.dirname(directory))
|
||||||
|
if os.path.exists(directory):
|
||||||
|
shutil.rmtree(directory)
|
||||||
|
os.mkdir(directory)
|
||||||
|
|
||||||
|
def hex_to_bytes(self, string):
|
||||||
|
try:
|
||||||
|
# Remove non-hex characters (e.g., hyphens)
|
||||||
|
hex_string = re.sub(r'[^0-9a-fA-F]', '', string)
|
||||||
|
|
||||||
|
if len(re.sub(r"\s+", "", string)) != len(hex_string):
|
||||||
|
return string
|
||||||
|
|
||||||
|
# Convert hex string to bytes
|
||||||
|
bytes_data = binascii.unhexlify(hex_string)
|
||||||
|
|
||||||
|
return bytes_data
|
||||||
|
except binascii.Error:
|
||||||
|
# Handle invalid hex string
|
||||||
|
return string
|
||||||
|
|
||||||
|
def int_to_hex(self, number):
|
||||||
|
try:
|
||||||
|
return format(number, '02X')
|
||||||
|
except:
|
||||||
|
return number
|
||||||
|
|
||||||
|
def hex_to_int(self, hex_string):
|
||||||
|
return int(hex_string, 16)
|
||||||
|
|
||||||
|
def contains_any(self, data, search_item, start=0, end=None):
|
||||||
|
return next((item for item in data[start:end] if item.lower() in search_item.lower()), None)
|
||||||
|
|
||||||
|
def check_latest_version(self):
|
||||||
|
response = self.fetcher.fetch_and_parse_content(self.repo_url, "json")
|
||||||
|
|
||||||
|
latest_version = response.get('version')
|
||||||
|
|
||||||
|
if not latest_version:
|
||||||
|
print("Version information is missing in the JSON file.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return latest_version
|
||||||
|
|
||||||
|
def normalize_path(self, path):
|
||||||
|
# Remove all surrounding quotes if present
|
||||||
|
path = re.sub(r'^[\'"]+|[\'"]+$', '', path)
|
||||||
|
|
||||||
|
# Remove trailing spaces
|
||||||
|
path = path.strip()
|
||||||
|
|
||||||
|
# Expand ~ to the user's home directory
|
||||||
|
path = os.path.expanduser(path)
|
||||||
|
|
||||||
|
# Normalize path separators for the target operating system
|
||||||
|
if os.name == 'nt': # Windows
|
||||||
|
# Replace single backslashes with forward slashes
|
||||||
|
path = path.replace('\\', '/')
|
||||||
|
# Remove redundant slashes
|
||||||
|
path = re.sub(r'/+', '/', path)
|
||||||
|
else:
|
||||||
|
# Replace backslashes with forward slashes
|
||||||
|
path = path.replace('\\', '/')
|
||||||
|
|
||||||
|
# Normalize the path
|
||||||
|
path = os.path.normpath(path)
|
||||||
|
|
||||||
|
# Convert the path to an absolute path and normalize it according to the OS
|
||||||
|
return str(pathlib.Path(path).resolve())
|
||||||
|
|
||||||
|
def open_folder(self, folder_path):
|
||||||
|
if os.name == 'posix':
|
||||||
|
if 'darwin' in os.uname().sysname.lower():
|
||||||
|
subprocess.run(['open', folder_path])
|
||||||
|
else:
|
||||||
|
subprocess.run(['xdg-open', folder_path])
|
||||||
|
elif os.name == 'nt':
|
||||||
|
os.startfile(folder_path)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("This function is only supported on macOS, Windows, and Linux.")
|
||||||
|
|
||||||
|
def request_input(self, prompt="Press Enter to continue..."):
|
||||||
|
try:
|
||||||
|
user_response = input(prompt)
|
||||||
|
except NameError:
|
||||||
|
user_response = raw_input(prompt)
|
||||||
|
|
||||||
|
if not isinstance(user_response, str):
|
||||||
|
user_response = str(user_response)
|
||||||
|
|
||||||
|
return user_response
|
||||||
|
|
||||||
|
def clear_screen(self):
|
||||||
|
os.system('cls' if os.name=='nt' else 'clear')
|
||||||
|
|
||||||
|
def head(self, text = None, width = 68, resize=True):
|
||||||
|
if resize:
|
||||||
|
self.adjust_window_size()
|
||||||
|
self.clear_screen()
|
||||||
|
if text == None:
|
||||||
|
text = self.script_name
|
||||||
|
separator = "#" * width
|
||||||
|
title = f" {text} "
|
||||||
|
if len(title) > width - 2:
|
||||||
|
title = title[:width-4] + "..."
|
||||||
|
title = title.center(width - 2) # Center the title within the width minus 2 for the '#' characters
|
||||||
|
|
||||||
|
print(f"{separator}\n#{title}#\n{separator}")
|
||||||
|
|
||||||
|
def adjust_window_size(self, content=""):
|
||||||
|
lines = content.splitlines()
|
||||||
|
rows = len(lines)
|
||||||
|
cols = max(len(line) for line in lines) if lines else 0
|
||||||
|
print('\033[8;{};{}t'.format(max(rows+6, 30), max(cols+2, 100)))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def message(text, msg_type="attention"):
|
||||||
|
# ANSI escape codes for different colors and bold font
|
||||||
|
RED_BOLD = "\033[1;31m"
|
||||||
|
YELLOW_BOLD = "\033[1;33m"
|
||||||
|
CYAN_BOLD = "\033[1;36m"
|
||||||
|
RESET = "\033[0m"
|
||||||
|
|
||||||
|
if msg_type == "attention":
|
||||||
|
color_code = RED_BOLD
|
||||||
|
elif msg_type == "warning":
|
||||||
|
color_code = YELLOW_BOLD
|
||||||
|
elif msg_type == "reminder":
|
||||||
|
color_code = CYAN_BOLD
|
||||||
|
else:
|
||||||
|
color_code = RESET
|
||||||
|
|
||||||
|
return f"{color_code}{text}{RESET}"
|
||||||
|
|
||||||
|
def exit_program(self, custom_content=""):
|
||||||
|
self.head()
|
||||||
|
print(custom_content)
|
||||||
|
print("For more information, to report errors, or to contribute to the product:")
|
||||||
|
print("* Facebook: https://www.facebook.com/macforce2601")
|
||||||
|
print("* Telegram: https://t.me/lzhoang2601")
|
||||||
|
print("* GitHub: https://github.com/lzhoang2801/OpCore-Simplify")
|
||||||
|
print("")
|
||||||
|
|
||||||
|
print("Thank you for using our program!\n")
|
||||||
|
exit(0)
|
||||||
4
requirements.txt
Normal file
4
requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
bs4
|
||||||
|
requests
|
||||||
|
python-dotenv
|
||||||
|
pytz
|
||||||
3
version.json
Normal file
3
version.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"version": "0.0.1"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user