mirror of
https://github.com/outbackdingo/OpCore-Simplify.git
synced 2026-08-25 07:10:18 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
+163
@@ -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
|
||||
@@ -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.
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+397
@@ -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
|
||||
Executable
+302
@@ -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
|
||||
Executable
+232
@@ -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)))
|
||||
@@ -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
|
||||
Executable
+2842
File diff suppressed because it is too large
Load Diff
Executable
+606
@@ -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
|
||||
Executable
+951
@@ -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
|
||||
]
|
||||
}
|
||||
Executable
+212
@@ -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
|
||||
Executable
+364
@@ -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
|
||||
Executable
+161
@@ -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"
|
||||
]
|
||||
|
||||
Executable
+43
@@ -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"
|
||||
]
|
||||
Executable
+1157
File diff suppressed because it is too large
Load Diff
Executable
+728
@@ -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
|
||||
Executable
+505
@@ -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)
|
||||
Executable
+317
@@ -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 {}
|
||||
Executable
+112
@@ -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
|
||||
Executable
+774
@@ -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
|
||||
Executable
+69
@@ -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)
|
||||
Executable
+154
@@ -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
|
||||
Executable
+58
@@ -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(),
|
||||
}
|
||||
Executable
+244
@@ -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)
|
||||
@@ -0,0 +1,4 @@
|
||||
bs4
|
||||
requests
|
||||
python-dotenv
|
||||
pytz
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "0.0.1"
|
||||
}
|
||||
Reference in New Issue
Block a user