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