Files
OpCore-Simplify/Scripts/acpi_guru.py
2025-05-06 13:53:38 +07:00

3353 lines
125 KiB
Python

# Original source: https://github.com/corpnewt/SSDTTime/blob/44aadf01b7fe75cb4a3eab5590e7b6c458265c6f/SSDTTime.py
from Scripts.datasets import acpi_patch_data
from Scripts.datasets import chipset_data
from Scripts.datasets import cpu_data
from Scripts.datasets import pci_data
from Scripts import smbios
from Scripts import dsdt
from Scripts import run
from Scripts import utils
import os
import binascii
import re
import tempfile
import shutil
import sys
import plistlib
class ACPIGuru:
def __init__(self):
self.acpi = dsdt.DSDT()
self.smbios = smbios.SMBIOS()
self.run = run.Run().run
self.utils = utils.Utils()
self.patches = acpi_patch_data.patches
self.hardware_report = None
self.disabled_devices = None
self.acpi_directory = None
self.smbios_model = None
self.dsdt = None
self.lpc_bus_device = None
self.osi_strings = {
"Windows 2000": "Windows 2000",
"Windows XP": "Windows 2001",
"Windows XP SP1": "Windows 2001 SP1",
"Windows Server 2003": "Windows 2001.1",
"Windows XP SP2": "Windows 2001 SP2",
"Windows Server 2003 SP1": "Windows 2001.1 SP1",
"Windows Vista": "Windows 2006",
"Windows Vista SP1": "Windows 2006 SP1",
"Windows Server 2008": "Windows 2006.1",
"Windows 7, Win Server 2008 R2": "Windows 2009",
"Windows 8, Win Server 2012": "Windows 2012",
"Windows 8.1": "Windows 2013",
"Windows 10": "Windows 2015",
"Windows 10, version 1607": "Windows 2016",
"Windows 10, version 1703": "Windows 2017",
"Windows 10, version 1709": "Windows 2017.2",
"Windows 10, version 1803": "Windows 2018",
"Windows 10, version 1809": "Windows 2018.2",
"Windows 10, version 1903": "Windows 2019",
"Windows 10, version 2004": "Windows 2020",
"Windows 11": "Windows 2021",
"Windows 11, version 22H2": "Windows 2022"
}
self.pre_patches = (
{
"PrePatch":"GPP7 duplicate _PRW methods",
"Comment" :"GPP7._PRW to XPRW to fix Gigabyte's Mistake",
"Find" :"3708584847500A021406535245470214065350525701085F505257",
"Replace" :"3708584847500A0214065352454702140653505257010858505257"
},
{
"PrePatch":"GPP7 duplicate UP00 devices",
"Comment" :"GPP7.UP00 to UPXX to fix Gigabyte's Mistake",
"Find" :"1047052F035F53425F50434930475050375B82450455503030",
"Replace" :"1047052F035F53425F50434930475050375B82450455505858"
},
{
"PrePatch":"GPP6 duplicate _PRW methods",
"Comment" :"GPP6._PRW to XPRW to fix ASRock's Mistake",
"Find" :"47505036085F4144520C04000200140F5F505257",
"Replace" :"47505036085F4144520C04000200140F58505257"
},
{
"PrePatch":"GPP1 duplicate PTXH devices",
"Comment" :"GPP1.PTXH to XTXH to fix MSI's Mistake",
"Find" :"50545848085F41445200140F",
"Replace" :"58545848085F41445200140F"
}
)
self.target_irqs = [0, 2, 8, 11]
self.illegal_names = ("XHC1", "EHC1", "EHC2", "PXSX")
self.dsdt_patches = []
def get_unique_name(self,name,target_folder,name_append="-Patched"):
# Get a new file name in the Results folder so we don't override the original
name = os.path.basename(name)
ext = "" if not "." in name else name.split(".")[-1]
if ext: name = name[:-len(ext)-1]
if name_append: name = name+str(name_append)
check_name = ".".join((name,ext)) if ext else name
if not os.path.exists(os.path.join(target_folder,check_name)):
return check_name
# We need a unique name
num = 1
while True:
check_name = "{}-{}".format(name,num)
if ext: check_name += "."+ext
if not os.path.exists(os.path.join(target_folder,check_name)):
return check_name
num += 1 # Increment our counter
def get_unique_device(self, path, base_name, starting_number=0, used_names = []):
# Appends a hex number until a unique device is found
while True:
hex_num = hex(starting_number).replace("0x","").upper()
name = base_name[:-1*len(hex_num)]+hex_num
if not len(self.acpi.get_device_paths("."+name)) and not name in used_names:
return (name,starting_number)
starting_number += 1
def sorted_nicely(self, l):
convert = lambda text: int(text) if text.isdigit() else text
alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key.lower()) ]
return sorted(l, key = alphanum_key)
def read_acpi_tables(self, path):
if not path:
return
self.utils.head("Loading ACPI Table(s)")
print("by CorpNewt")
print("")
tables = []
trouble_dsdt = None
fixed = False
temp = None
prior_tables = self.acpi.acpi_tables # Retain in case of failure
# Clear any existing tables so we load anew
self.acpi.acpi_tables = {}
if os.path.isdir(path):
print("Gathering valid tables from {}...\n".format(os.path.basename(path)))
for t in self.sorted_nicely(os.listdir(path)):
if not "Patched" in t and self.acpi.table_is_valid(path,t):
print(" - {}".format(t))
tables.append(t)
if not tables:
# Check if there's an ACPI directory within the passed
# directory - this may indicate SysReport was dropped
if os.path.isdir(os.path.join(path,"ACPI")):
# Rerun this function with that updated path
return self.read_acpi_tables(os.path.join(path,"ACPI"))
print(" - No valid .aml files were found!")
print("")
#self.u.grab("Press [enter] to return...")
self.utils.request_input()
# Restore any prior tables
self.acpi.acpi_tables = prior_tables
return
print("")
# We got at least one file - let's look for the DSDT specifically
# and try to load that as-is. If it doesn't load, we'll have to
# manage everything with temp folders
dsdt_list = [x for x in tables if self.acpi._table_signature(path,x) == "DSDT"]
if len(dsdt_list) > 1:
print("Multiple files with DSDT signature passed:")
for d in self.sorted_nicely(dsdt_list):
print(" - {}".format(d))
print("\nOnly one is allowed at a time. Please remove one of the above and try again.")
print("")
#self.u.grab("Press [enter] to return...")
self.utils.request_input()
# Restore any prior tables
self.acpi.acpi_tables = prior_tables
return
# Get the DSDT, if any
dsdt = dsdt_list[0] if len(dsdt_list) else None
if dsdt: # Try to load it and see if it causes problems
print("Disassembling {} to verify if pre-patches are needed...".format(dsdt))
if not self.acpi.load(os.path.join(path,dsdt))[0]:
trouble_dsdt = dsdt
else:
print("\nDisassembled successfully!\n")
elif not "Patched" in path and os.path.isfile(path):
print("Loading {}...".format(os.path.basename(path)))
if self.acpi.load(path)[0]:
print("\nDone.")
# If it loads fine - just return the path
# to the parent directory
return os.path.dirname(path)
if not self.acpi._table_signature(path) == "DSDT":
# Not a DSDT, we aren't applying pre-patches
print("\n{} could not be disassembled!".format(os.path.basename(path)))
print("")
#self.u.grab("Press [enter] to return...")
self.utils.request_input()
# Restore any prior tables
self.acpi.acpi_tables = prior_tables
return
# It didn't load - set it as the trouble file
trouble_dsdt = os.path.basename(path)
# Put the table in the tables list, and adjust
# the path to represent the parent dir
tables.append(os.path.basename(path))
path = os.path.dirname(path)
else:
print("Passed file/folder does not exist!")
print("")
#self.u.grab("Press [enter] to return...")
self.utils.request_input()
# Restore any prior tables
self.acpi.acpi_tables = prior_tables
return
# If we got here - check if we have a trouble_dsdt.
if trouble_dsdt:
# We need to move our ACPI files to a temp folder
# then try patching the DSDT there
temp = tempfile.mkdtemp()
for table in tables:
shutil.copy(
os.path.join(path,table),
temp
)
# Get a reference to the new trouble file
trouble_path = os.path.join(temp,trouble_dsdt)
# Now we try patching it
print("Checking available pre-patches...")
print("Loading {} into memory...".format(trouble_dsdt))
with open(trouble_path,"rb") as f:
d = f.read()
res = self.acpi.check_output(path)
target_name = self.get_unique_name(trouble_dsdt,res,name_append="-Patched")
self.dsdt_patches = []
print("Iterating patches...\n")
for p in self.pre_patches:
if not all(x in p for x in ("PrePatch","Comment","Find","Replace")): continue
print(" - {}".format(p["PrePatch"]))
find = binascii.unhexlify(p["Find"])
if d.count(find) == 1:
self.dsdt_patches.append(p) # Retain the patch
repl = binascii.unhexlify(p["Replace"])
print(" --> Located - applying...")
d = d.replace(find,repl) # Replace it in memory
with open(trouble_path,"wb") as f:
f.write(d) # Write the updated file
# Attempt to load again
if self.acpi.load(trouble_path)[0]:
fixed = True
# We got it to load - let's write the patches
print("\nDisassembled successfully!\n")
#self.make_plist(None, None, patches)
# Save to the local file
#with open(os.path.join(res,target_name),"wb") as f:
# f.write(d)
#print("\n!! Patches applied to modified file in Results folder:\n {}".format(target_name))
#self.patch_warn()
break
if not fixed:
print("\n{} could not be disassembled!".format(trouble_dsdt))
print("")
#self.u.grab("Press [enter] to return...")
self.utils.request_input()
if temp:
shutil.rmtree(temp,ignore_errors=True)
# Restore any prior tables
self.acpi.acpi_tables = prior_tables
return
# Let's load the rest of the tables
if len(tables) > 1:
print("Loading valid tables in {}...".format(path))
loaded_tables,failed = self.acpi.load(temp or path)
if not loaded_tables or failed:
print("\nFailed to load tables in {}{}\n".format(
os.path.dirname(path) if os.path.isfile(path) else path,
":" if failed else ""
))
for t in self.sorted_nicely(failed):
print(" - {}".format(t))
# Restore any prior tables
if not loaded_tables:
self.acpi.acpi_tables = prior_tables
else:
if len(tables) > 1:
print("") # Newline for readability
print("Done.")
# If we had to patch the DSDT, or if not all tables loaded,
# make sure we get interaction from the user to continue
if trouble_dsdt or not loaded_tables or failed:
print("")
#self.u.grab("Press [enter] to return...")
#self.utils.request_input()
if temp:
shutil.rmtree(temp,ignore_errors=True)
self.dsdt = self.acpi.get_dsdt_or_only()
return path
def _ensure_dsdt(self, allow_any=False):
# Helper to check conditions for when we have valid tables
return self.dsdt and ((allow_any and self.acpi.acpi_tables) or (not allow_any and self.acpi.get_dsdt_or_only()))
def ensure_dsdt(self, allow_any=False):
if self._ensure_dsdt(allow_any=allow_any):
# Got it already
return True
# Need to prompt
self.select_acpi_tables()
self.dsdt = self.acpi.get_dsdt_or_only()
if self._ensure_dsdt(allow_any=allow_any):
return True
return False
def get_sta_var(self,var="STAS",device=None,dev_hid="ACPI000E",dev_name="AWAC",log_locate=False,table=None):
# Helper to check for a device, check for (and qualify) an _STA method,
# and look for a specific variable in the _STA scope
#
# Returns a dict with device info - only "valid" parameter is
# guaranteed.
has_var = False
patches = []
root = None
if device:
dev_list = self.acpi.get_device_paths(device,table=table)
if not len(dev_list):
if log_locate: print(" - Could not locate {}".format(device))
return {"value":False}
else:
if log_locate: print("Locating {} ({}) devices...".format(dev_hid,dev_name))
dev_list = self.acpi.get_device_paths_with_hid(dev_hid,table=table)
if not len(dev_list):
if log_locate: print(" - Could not locate any {} devices".format(dev_hid))
return {"valid":False}
dev = dev_list[0]
if log_locate: print(" - Found {}".format(dev[0]))
root = dev[0].split(".")[0]
#print(" --> Verifying _STA...")
# Check Method first - then Name
sta_type = "MethodObj"
sta = self.acpi.get_method_paths(dev[0]+"._STA",table=table)
xsta = self.acpi.get_method_paths(dev[0]+".XSTA",table=table)
if not sta and not xsta:
# Check for names
sta_type = "IntObj"
sta = self.acpi.get_name_paths(dev[0]+"._STA",table=table)
xsta = self.acpi.get_name_paths(dev[0]+".XSTA",table=table)
if xsta and not sta:
#print(" --> _STA already renamed to XSTA! Skipping other checks...")
#print(" Please disable _STA to XSTA renames for this device, reboot, and try again.")
#print("")
return {"valid":False,"break":True,"device":dev,"dev_name":dev_name,"dev_hid":dev_hid,"sta_type":sta_type}
if sta:
if var:
scope = "\n".join(self.acpi.get_scope(sta[0][1],strip_comments=True,table=table))
has_var = var in scope
#print(" --> {} {} variable".format("Has" if has_var else "Does NOT have",var))
#else:
#print(" --> No _STA method/name found")
# Let's find out of we need a unique patch for _STA -> XSTA
if sta and not has_var:
#print(" --> Generating _STA to XSTA rename")
sta_index = self.acpi.find_next_hex(sta[0][1],table=table)[1]
#print(" ----> Found at index {}".format(sta_index))
sta_hex = "5F535441" # _STA
xsta_hex = "58535441" # XSTA
padl,padr = self.acpi.get_shortest_unique_pad(sta_hex,sta_index,table=table)
patches.append({"Comment":"{} _STA to XSTA Rename".format(dev_name),"Find":padl+sta_hex+padr,"Replace":padl+xsta_hex+padr})
return {"valid":True,"has_var":has_var,"sta":sta,"patches":patches,"device":dev,"dev_name":dev_name,"dev_hid":dev_hid,"root":root,"sta_type":sta_type}
def get_lpc_name(self,log=False,skip_ec=False,skip_common_names=False):
# Intel devices appear to use _ADR, 0x001F0000
# AMD devices appear to use _ADR, 0x00140003
if log: print("Locating LPC(B)/SBRG...")
for table_name in self.sorted_nicely(list(self.acpi.acpi_tables)):
table = self.acpi.acpi_tables[table_name]
# The LPCB device will always be the parent of the PNP0C09 device
# if found
if not skip_ec:
ec_list = self.acpi.get_device_paths_with_hid("PNP0C09",table=table)
if len(ec_list):
lpc_name = ".".join(ec_list[0][0].split(".")[:-1])
if log: print(" - Found {} in {}".format(lpc_name,table_name))
return lpc_name
# Maybe try common names if we haven't found it yet
if not skip_common_names:
for x in ("LPCB", "LPC0", "LPC", "SBRG", "PX40"):
try:
lpc_name = self.acpi.get_device_paths(x,table=table)[0][0]
if log: print(" - Found {} in {}".format(lpc_name,table_name))
return lpc_name
except: pass
# Finally check by address - some Intel tables have devices at
# 0x00140003
paths = self.acpi.get_path_of_type(obj_type="Name",obj="_ADR",table=table)
for path in paths:
adr = self.get_address_from_line(path[1],table=table)
if adr in (0x001F0000, 0x00140003):
# Get the path minus ._ADR
lpc_name = path[0][:-5]
# Make sure the LPCB device does not have an _HID
lpc_hid = lpc_name+"._HID"
if any(x[0]==lpc_hid for x in table.get("paths",[])):
continue
if log: print(" - Found {} in {}".format(lpc_name,table_name))
return lpc_name
if log:
print(" - Could not locate LPC(B)! Aborting!")
print("")
return None # Didn't find it
def get_address_from_line(self, line, split_by="_ADR, ", table=None):
if table is None:
table = self.acpi.get_dsdt_or_only()
try:
return int(table["lines"][line].split(split_by)[1].split(")")[0].replace("Zero","0x0").replace("One","0x1"),16)
except:
return None
def enable_cpu_power_management(self):
#if not self.ensure_dsdt(allow_any=True):
# return
#self.u.head("Plugin Type")
#print("")
#print("Determining CPU name scheme...")
for table_name in self.sorted_nicely(list(self.acpi.acpi_tables)):
ssdt_name = "SSDT-PLUG"
table = self.acpi.acpi_tables[table_name]
if not table.get("signature") in (b"DSDT",b"SSDT"):
continue # We're not checking data tables
#print(" Checking {}...".format(table_name))
try: cpu_name = self.acpi.get_processor_paths(table=table)[0][0]
except: cpu_name = None
if cpu_name:
#print(" - Found Processor: {}".format(cpu_name))
#oc = {"Comment":"Sets plugin-type to 1 on first Processor object","Enabled":True,"Path":ssdt_name+".aml"}
#print("Creating SSDT-PLUG...")
ssdt = """//
// Based on the sample found at https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/SSDT-PLUG.dsl
//
DefinitionBlock ("", "SSDT", 2, "ZPSS", "CpuPlug", 0x00003000)
{
External ([[CPUName]], ProcessorObj)
Scope ([[CPUName]])
{
If (_OSI ("Darwin")) {
Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method
{
If (LNot (Arg2))
{
Return (Buffer (One)
{
0x03
})
}
Return (Package (0x02)
{
"plugin-type",
One
})
}
}
}
}""".replace("[[CPUName]]",cpu_name)
else:
ssdt_name += "-ALT"
#print(" - No Processor objects found...")
procs = self.acpi.get_device_paths_with_hid(hid="ACPI0007",table=table)
if not procs:
#print(" - No ACPI0007 devices found...")
continue
#print(" - Located {:,} ACPI0007 device{}".format(
# len(procs), "" if len(procs)==1 else "s"
#))
parent = procs[0][0].split(".")[0]
#print(" - Got parent at {}, iterating...".format(parent))
proc_list = []
for proc in procs:
#print(" - Checking {}...".format(proc[0].split(".")[-1]))
uid = self.acpi.get_path_of_type(obj_type="Name",obj=proc[0]+"._UID",table=table)
if not uid:
#print(" --> Not found! Skipping...")
continue
# Let's get the actual _UID value
try:
_uid = table["lines"][uid[0][1]].split("_UID, ")[1].split(")")[0]
#print(" --> _UID: {}".format(_uid))
proc_list.append((proc[0],_uid))
except:
pass
#print(" --> Not found! Skipping...")
if not proc_list:
continue
#print("Iterating {:,} valid processor device{}...".format(len(proc_list),"" if len(proc_list)==1 else "s"))
ssdt = """//
// Based on the sample found at https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/Source/SSDT-PLUG-ALT.dsl
//
DefinitionBlock ("", "SSDT", 2, "ZPSS", "CpuPlugA", 0x00003000)
{
External ([[parent]], DeviceObj)
Scope ([[parent]])
{""".replace("[[parent]]",parent)
# Ensure our name scheme won't conflict
schemes = ("C000","CP00","P000","PR00","CX00","PX00")
# Walk the processor objects, and add them to the SSDT
for i,proc_uid in enumerate(proc_list):
proc,uid = proc_uid
adr = hex(i)[2:].upper()
name = None
for s in schemes:
name_check = s[:-len(adr)]+adr
check_path = "{}.{}".format(parent,name_check)
if self.acpi.get_path_of_type(obj_type="Device",obj=check_path,table=table):
continue # Already defined - skip
# If we got here - we found an unused name
name = name_check
break
if not name:
#print(" - Could not find an available name scheme! Aborting.")
#print("")
#self.u.grab("Press [enter] to return to main menu...")
return
ssdt+="""
Processor ([[name]], [[uid]], 0x00000510, 0x06)
{
// [[proc]]
Name (_HID, "ACPI0007" /* Processor Device */) // _HID: Hardware ID
Name (_UID, [[uid]])
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}""".replace("[[name]]",name).replace("[[uid]]",uid).replace("[[proc]]",proc)
if i == 0: # Got the first, add plugin-type as well
ssdt += """
Method (_DSM, 4, NotSerialized)
{
If (LNot (Arg2)) {
Return (Buffer (One) { 0x03 })
}
Return (Package (0x02)
{
"plugin-type",
One
})
}"""
# Close up the SSDT
ssdt += """
}"""
ssdt += """
}
}"""
# oc = {"Comment":"Redefines modern CPU Devices as legacy Processor objects and sets plugin-type to 1 on the first","Enabled":True,"Path":ssdt_name+".aml"}
#self.make_plist(oc, ssdt_name+".aml", ())
#self.write_ssdt(ssdt_name,ssdt)
#print("")
#print("Done.")
#self.patch_warn()
#self.u.grab("Press [enter] to return...")
#return
# If we got here - we reached the end
#print("No valid processor devices found!")
#print("")
#self.u.grab("Press [enter] to return...")
#return
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt),
"Path": ssdt_name + ".aml"
}
]
}
def list_irqs(self):
# Walks the DSDT keeping track of the current device and
# saving the IRQNoFlags if found
devices = {}
current_device = None
current_hid = None
irq = False
last_irq = False
irq_index = 0
for index,line in enumerate(self.dsdt["lines"]):
if self.acpi.is_hex(line):
# Skip all hex lines
continue
if irq:
# Get the values
num = line.split("{")[1].split("}")[0].replace(" ","")
num = "#" if not len(num) else num
if current_device in devices:
if last_irq: # In a row
devices[current_device]["irq"] += ":"+num
else: # Skipped at least one line
irq_index = self.acpi.find_next_hex(index)[1]
devices[current_device]["irq"] += "-"+str(irq_index)+"|"+num
else:
irq_index = self.acpi.find_next_hex(index)[1]
devices[current_device] = {"irq":str(irq_index)+"|"+num}
irq = False
last_irq = True
elif "Device (" in line:
# Check if we retain the _HID here
if current_device and current_device in devices and current_hid:
# Save it
devices[current_device]["hid"] = current_hid
last_irq = False
current_hid = None
try: current_device = line.split("(")[1].split(")")[0]
except:
current_device = None
continue
elif "_HID, " in line and current_device:
try: current_hid = line.split('"')[1]
except: pass
elif "IRQNoFlags" in line and current_device:
# Next line has our interrupts
irq = True
# Check if just a filler line
elif len(line.replace("{","").replace("}","").replace("(","").replace(")","").replace(" ","").split("//")[0]):
# Reset last IRQ as it's not in a row
last_irq = False
# Retain the final _HID if needed
if current_device and current_device in devices and current_hid:
devices[current_device]["hid"] = current_hid
return devices
def get_irq_choice(self, irqs):
names_and_hids = [
"PIC",
"IPIC",
"TMR",
"TIMR",
"RTC",
"RTC0",
"RTC1",
"PNPC0000",
"PNP0100",
"PNP0B00"
]
defaults = [x for x in irqs if x.upper() in names_and_hids or irqs[x].get("hid","").upper() in names_and_hids]
d = {}
for x in defaults:
d[x] = self.target_irqs
return d
def get_hex_from_irqs(self, irq, rem_irq = None):
# We need to search for a few different types:
#
# 22 XX XX 22 XX XX 22 XX XX (multiples on different lines)
# 22 XX XX (summed multiples in the same bracket - {0,8,11})
# 22 XX XX (single IRQNoFlags entry)
#
# Can end with 79 [00] (end of method), 86 09 (middle of method) or 47 01 (unknown)
lines = []
remd = []
for a in irq.split("-"):
index,i = a.split("|") # Get the index
index = int(index)
find = self.get_int_for_line(i)
repl = [0]*len(find)
# Now we need to verify if we're patching *all* IRQs, or just some specifics
if rem_irq:
repl = [x for x in find]
matched = []
for x in rem_irq:
# Get the int
rem = self.convert_irq_to_int(x)
repl1 = [y&(rem^0xFFFF) if y >= rem else y for y in repl]
if repl1 != repl:
# Changes were made
remd.append(x)
repl = [y for y in repl1]
# Get the hex
d = {
"irq":i,
"find": "".join(["22"+self.acpi.get_hex_from_int(x) for x in find]),
"repl": "".join(["22"+self.acpi.get_hex_from_int(x) for x in repl]),
"remd": remd,
"index": index
}
d["changed"] = not (d["find"]==d["repl"])
lines.append(d)
return lines
def get_int_for_line(self, irq):
irq_list = []
for i in irq.split(":"):
irq_list.append(self.same_line_irq(i))
return irq_list
def convert_irq_to_int(self, irq):
b = "0"*(16-irq)+"1"+"0"*(irq)
return int(b,2)
def same_line_irq(self, irq):
# We sum the IRQ values and return the int
total = 0
for i in irq.split(","):
if i == "#":
continue # Null value
try: i=int(i)
except: continue # Not an int
if i > 15 or i < 0:
continue # Out of range
total = total | self.convert_irq_to_int(i)
return total
def fix_irq_conflicts(self):
hpets = self.acpi.get_device_paths_with_hid("PNP0103")
hpet_fake = not hpets
hpet_sta = False
sta = None
patches = []
if hpets:
name = hpets[0][0]
sta = self.get_sta_var(var=None,dev_hid="PNP0103",dev_name="HPET",log_locate=False)
if sta.get("patches"):
hpet_sta = True
patches.extend(sta.get("patches",[]))
hpet = self.acpi.get_method_paths(name+"._CRS") or self.acpi.get_name_paths(name+"._CRS")
if not hpet:
return
crs_index = self.acpi.find_next_hex(hpet[0][1])[1]
mem_base = mem_length = primed = None
for line in self.acpi.get_scope(hpets[0][1],strip_comments=True):
if "Memory32Fixed (" in line:
primed = True
continue
if not primed:
continue
elif ")" in line: # Reached the end of the scope
break
# We're primed, and not at the end - let's try to get the base and length
try:
val = line.strip().split(",")[0].replace("Zero","0x0").replace("One","0x1")
check = int(val,16)
except:
break
# Set them in order
if mem_base is None:
mem_base = val
else:
mem_length = val
break # Leave after we get both values
# Check if we found the values
got_mem = mem_base and mem_length
if not got_mem:
mem_base = "0xFED00000"
mem_length = "0x00000400"
crs = "5F435253"
xcrs = "58435253"
padl,padr = self.acpi.get_shortest_unique_pad(crs, crs_index)
patches.append({"Comment":"{} _CRS to XCRS Rename".format(name.split(".")[-1].lstrip("\\")),"Find":padl+crs+padr,"Replace":padl+xcrs+padr})
else:
ec_list = self.acpi.get_device_paths_with_hid("PNP0C09")
name = None
if len(ec_list):
name = ".".join(ec_list[0][0].split(".")[:-1])
if name == None:
for x in ("LPCB", "LPC0", "LPC", "SBRG", "PX40"):
try:
name = self.acpi.get_device_paths(x)[0][0]
break
except: pass
if not name:
return
devs = self.list_irqs()
target_irqs = self.get_irq_choice(devs)
if target_irqs is None: return # Bailed, going to the main menu
# Let's apply patches as we go
saved_dsdt = self.dsdt.get("raw")
unique_patches = {}
generic_patches = []
for dev in devs:
if not dev in target_irqs:
continue
irq_patches = self.get_hex_from_irqs(devs[dev]["irq"],target_irqs[dev])
i = [x for x in irq_patches if x["changed"]]
for a,t in enumerate(i):
if not t["changed"]:
# Nothing patched - skip
continue
# Try our endings here - 7900, 8609, and 4701 - also allow for up to 8 chars of pad (thanks MSI)
matches = re.findall("("+t["find"]+"(.{0,8})(7900|4701|8609))",self.acpi.get_hex_starting_at(t["index"])[0])
if not len(matches):
continue
if len(matches) > 1:
# Found too many matches!
# Add them all as find/replace entries
for x in matches:
generic_patches.append({
"remd":",".join([str(y) for y in set(t["remd"])]),
"orig":t["find"],
"find":t["find"]+"".join(x[1:]),
"repl":t["repl"]+"".join(x[1:])
})
continue
ending = "".join(matches[0][1:])
padl,padr = self.acpi.get_shortest_unique_pad(t["find"]+ending, t["index"])
t_patch = padl+t["find"]+ending+padr
r_patch = padl+t["repl"]+ending+padr
if not dev in unique_patches:
unique_patches[dev] = []
unique_patches[dev].append({
"dev":dev,
"remd":",".join([str(y) for y in set(t["remd"])]),
"orig":t["find"],
"find":t_patch,
"repl":r_patch
})
# Walk the unique patches if any
if len(unique_patches):
for x in unique_patches:
for i,p in enumerate(unique_patches[x]):
patch_name = "{} IRQ {} Patch".format(x, p["remd"])
if len(unique_patches[x]) > 1:
patch_name += " - {} of {}".format(i+1, len(unique_patches[x]))
patches.append({
"Comment": patch_name,
"Find": p["find"],
"Replace": p["repl"]
})
# Walk the generic patches if any
if len(generic_patches):
generic_set = [] # Make sure we don't repeat find values
for x in generic_patches:
if x in generic_set:
continue
generic_set.append(x)
for i,x in enumerate(generic_set):
patch_name = "Generic IRQ Patch {} of {} - {} - {}".format(i+1,len(generic_set),x["remd"],x["orig"])
patches.append({
"Comment": patch_name,
"Find": x["find"],
"Replace": x["repl"],
"Enabled": False
})
# Restore the original DSDT in memory
self.dsdt["raw"] = saved_dsdt
ssdt_name = "SSDT-HPET"
if hpet_fake:
ssdt_content = """// Fake HPET device
//
DefinitionBlock ("", "SSDT", 2, "ZPSS", "HPET", 0x00000000)
{
External ([[name]], DeviceObj)
Scope ([[name]])
{
Device (HPET)
{
Name (_HID, EisaId ("PNP0103") /* HPET System Timer */) // _HID: Hardware ID
Name (_CID, EisaId ("PNP0C01") /* System Board */) // _CID: Compatible ID
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
{
IRQNoFlags ()
{0,8,11}
Memory32Fixed (ReadWrite,
0xFED00000, // Address Base
0x00000400, // Address Length
)
})
}
}
}""".replace("[[name]]",name)
else:
ssdt_content = """//
// Supplementary HPET _CRS from Goldfish64
// Requires the HPET's _CRS to XCRS rename
//
DefinitionBlock ("", "SSDT", 2, "ZPSS", "HPET", 0x00000000)
{
External ([[name]], DeviceObj)
External ([[name]].XCRS, [[type]])
Scope ([[name]])
{
Name (BUFX, ResourceTemplate ()
{
IRQNoFlags ()
{0,8,11}
Memory32Fixed (ReadWrite,
// [[mem]]
[[mem_base]], // Address Base
[[mem_length]], // Address Length
)
})
Method (_CRS, 0, Serialized) // _CRS: Current Resource Settings
{
// Return our buffer if booting macOS or the XCRS method
// no longer exists for some reason
If (LOr (_OSI ("Darwin"), LNot(CondRefOf ([[name]].XCRS))))
{
Return (BUFX)
}
// Not macOS and XCRS exists - return its result
Return ([[name]].XCRS[[method]])
}""" \
.replace("[[name]]",name) \
.replace("[[type]]","MethodObj" if hpet[0][-1] == "Method" else "BuffObj") \
.replace("[[mem]]","Base/Length pulled from DSDT" if got_mem else "Default Base/Length - verify with your DSDT!") \
.replace("[[mem_base]]",mem_base) \
.replace("[[mem_length]]",mem_length) \
.replace("[[method]]"," ()" if hpet[0][-1]=="Method" else "")
if hpet_sta:
# Inject our external reference to the renamed XSTA method
ssdt_parts = []
external = False
for line in ssdt_content.split("\n"):
if "External (" in line: external = True
elif external:
ssdt_parts.append(" External ({}.XSTA, {})".format(name,sta["sta_type"]))
external = False
ssdt_parts.append(line)
ssdt_content = "\n".join(ssdt_parts)
# Add our method
ssdt_content += """
Method (_STA, 0, NotSerialized) // _STA: Status
{
// Return 0x0F if booting macOS or the XSTA method
// no longer exists for some reason
If (LOr (_OSI ("Darwin"), LNot (CondRefOf ([[name]].XSTA))))
{
Return (0x0F)
}
// Not macOS and XSTA exists - return its result
Return ([[name]].XSTA[[called]])
}""".replace("[[name]]",name).replace("[[called]]"," ()" if sta["sta_type"]=="MethodObj" else "")
ssdt_content += """
}
}"""
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
],
"Patch": patches
}
def fix_system_clock_awac(self):
#if not self.ensure_dsdt():
# return
#self.u.head("SSDT RTCAWAC")
#print("")
rtc_range_needed = False
rtc_crs_type = None
crs_lines = []
lpc_name = None
awac_dict = self.get_sta_var(var="STAS",dev_hid="ACPI000E",dev_name="AWAC")
rtc_dict = self.get_sta_var(var="STAS",dev_hid="PNP0B00",dev_name="RTC")
# At this point - we should have any info about our AWAC and RTC devices
# we need. Let's see if we need an RTC fake - then build the SSDT.
if not rtc_dict.get("valid"):
#print(" - Fake needed!")
lpc_name = self.get_lpc_name()
if lpc_name is None:
#self.u.grab("Press [enter] to return to main menu...")
return
else:
# Let's check if our RTC device has a _CRS variable - and if so, let's look for any skipped ranges
#print(" --> Checking for _CRS...")
rtc_crs = self.acpi.get_method_paths(rtc_dict["device"][0]+"._CRS") or self.acpi.get_name_paths(rtc_dict["device"][0]+"._CRS")
if rtc_crs:
#print(" ----> {}".format(rtc_crs[0][0]))
rtc_crs_type = "MethodObj" if rtc_crs[0][-1] == "Method" else "BuffObj"
# Only check for the range if it's a buffobj
if rtc_crs_type.lower() == "buffobj":
#print(" --> _CRS is a Buffer - checking RTC range...")
last_adr = last_len = last_ind = None
crs_scope = self.acpi.get_scope(rtc_crs[0][1])
# Let's try and clean up the scope - it's often a jumbled mess
pad_len = len(crs_scope[0])-len(crs_scope[0].lstrip())
pad = crs_scope[0][:pad_len]
fixed_scope = []
for line in crs_scope:
if line.startswith(pad): # Got a full line - strip the pad, and save it
fixed_scope.append(line[pad_len:])
else: # Likely a part of the prior line
fixed_scope[-1] = fixed_scope[-1]+line
for i,line in enumerate(fixed_scope):
if "Name (_CRS, " in line:
# Rename _CRS to BUFX for later - and strip any comments to avoid confusion
line = line.replace("Name (_CRS, ","Name (BUFX, ").split(" //")[0]
if "IO (Decode16," in line:
# We have our start - get the the next line, and 4th line
try:
curr_adr = int(fixed_scope[i+1].strip().split(",")[0],16)
curr_len = int(fixed_scope[i+4].strip().split(",")[0],16)
curr_ind = i+4 # Save the value we may pad
except: # Bad values? Bail...
#print(" ----> Failed to gather values - could not verify RTC range.")
rtc_range_needed = False
break
if last_adr is not None: # Compare our range values
adjust = curr_adr - (last_adr + last_len)
if adjust: # We need to increment the previous length by our adjust value
rtc_range_needed = True
#print(" ----> Adjusting IO range {} length to {}".format(self.hexy(last_adr,pad_to=4),self.hexy(last_len+adjust,pad_to=2)))
try:
hex_find,hex_repl = self.hexy(last_len,pad_to=2),self.hexy(last_len+adjust,pad_to=2)
crs_lines[last_ind] = crs_lines[last_ind].replace(hex_find,hex_repl)
except:
#print(" ----> Failed to adjust values - could not verify RTC range.")
rtc_range_needed = False
break
# Save our last values
last_adr,last_len,last_ind = curr_adr,curr_len,curr_ind
crs_lines.append(line)
if rtc_range_needed: # We need to generate a rename for _CRS -> XCRS
#print(" --> Generating _CRS to XCRS rename...")
crs_index = self.acpi.find_next_hex(rtc_crs[0][1])[1]
#print(" ----> Found at index {}".format(crs_index))
crs_hex = "5F435253" # _CRS
xcrs_hex = "58435253" # XCRS
padl,padr = self.acpi.get_shortest_unique_pad(crs_hex, crs_index)
patches = rtc_dict.get("patches",[])
patches.append({"Comment":"{} _CRS to XCRS Rename".format(rtc_dict["dev_name"]),"Find":padl+crs_hex+padr,"Replace":padl+xcrs_hex+padr})
rtc_dict["patches"] = patches
rtc_dict["crs"] = True
#else:
# print(" ----> Not found")
# Let's see if we even need an SSDT
# Not required if AWAC is not present; RTC is present, doesn't have an STAS var, and doesn't have an _STA method, and no range fixes are needed
if not awac_dict.get("valid") and rtc_dict.get("valid") and not rtc_dict.get("has_var") and not rtc_dict.get("sta") and not rtc_range_needed:
#print("")
#print("Valid PNP0B00 (RTC) device located and qualified, and no ACPI000E (AWAC) devices found.")
#print("No patching or SSDT needed.")
#print("")
#self.u.grab("Press [enter] to return to main menu...")
return
suffix = []
for x in (awac_dict,rtc_dict):
if not x.get("valid"): continue
val = ""
if x.get("sta") and not x.get("has_var"):
val = "{} _STA to XSTA".format(x["dev_name"])
if x.get("crs"):
val += "{} _CRS to XCRS".format(" and " if val else x["dev_name"])
if val: suffix.append(val)
#if suffix:
# comment += " - Requires {} Rename".format(", ".join(suffix))
# At this point - we need to do the following:
# 1. Change STAS if needed
# 2. Setup _STA with _OSI and call XSTA if needed
# 3. Fake RTC if needed
#oc = {"Comment":comment,"Enabled":True,"Path":"SSDT-RTCAWAC.aml"}
#self.make_plist(oc, "SSDT-RTCAWAC.aml", awac_dict.get("patches",[])+rtc_dict.get("patches",[]), replace=True)
#print("Creating SSDT-RTCAWAC...")
ssdt_name = "SSDT-RTCAWAC"
ssdt = """//
// Original sources from Acidanthera:
// - https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/SSDT-AWAC.dsl
// - https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/SSDT-RTC0.dsl
//
// Uses the ZPSS name to denote where this was created for troubleshooting purposes.
//
DefinitionBlock ("", "SSDT", 2, "ZPSS", "RTCAWAC", 0x00000000)
{
"""
if any(x.get("has_var") for x in (awac_dict,rtc_dict)):
ssdt += """ External (STAS, IntObj)
Scope (\\)
{
Method (_INI, 0, NotSerialized) // _INI: Initialize
{
If (_OSI ("Darwin"))
{
Store (One, STAS)
}
}
}
"""
for x in (awac_dict,rtc_dict):
if not x.get("valid") or x.get("has_var") or not x.get("device"): continue
# Device was found, and it doesn't have the STAS var - check if we
# have an _STA (which would be renamed)
macos,original = ("Zero","0x0F") if x.get("dev_hid") == "ACPI000E" else ("0x0F","Zero")
if x.get("sta"):
ssdt += """ External ([[DevPath]], DeviceObj)
External ([[DevPath]].XSTA, [[sta_type]])
Scope ([[DevPath]])
{
Name (ZSTA, [[Original]])
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return ([[macOS]])
}
// Default to [[Original]] - but return the result of the renamed XSTA if possible
If (CondRefOf ([[DevPath]].XSTA))
{
Store ([[DevPath]].XSTA[[called]], ZSTA)
}
Return (ZSTA)
}
}
""".replace("[[DevPath]]",x["device"][0]).replace("[[Original]]",original).replace("[[macOS]]",macos).replace("[[sta_type]]",x["sta_type"]).replace("[[called]]"," ()" if x["sta_type"]=="MethodObj" else "")
elif x.get("dev_hid") == "ACPI000E":
# AWAC device with no STAS, and no _STA - let's just add one
ssdt += """ External ([[DevPath]], DeviceObj)
Scope ([[DevPath]])
{
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (Zero)
}
Else
{
Return (0x0F)
}
}
}
""".replace("[[DevPath]]",x["device"][0])
# Check if we need to setup an RTC range correction
if rtc_range_needed and rtc_crs_type.lower() == "buffobj" and crs_lines and rtc_dict.get("valid"):
ssdt += """ External ([[DevPath]], DeviceObj)
External ([[DevPath]].XCRS, [[type]])
Scope ([[DevPath]])
{
// Adjusted and renamed _CRS buffer ripped from DSDT with corrected range
[[NewCRS]]
// End of adjusted _CRS and renamed buffer
// Create a new _CRS method that returns the result of the renamed XCRS
Method (_CRS, 0, Serialized) // _CRS: Current Resource Settings
{
If (LOr (_OSI ("Darwin"), LNot (CondRefOf ([[DevPath]].XCRS))))
{
// Return our buffer if booting macOS or the XCRS method
// no longer exists for some reason
Return (BUFX)
}
// Not macOS and XCRS exists - return its result
Return ([[DevPath]].XCRS[[method]])
}
}
""".replace("[[DevPath]]",rtc_dict["device"][0]) \
.replace("[[type]]",rtc_crs_type) \
.replace("[[method]]"," ()" if rtc_crs_type == "Method" else "") \
.replace("[[NewCRS]]","\n".join([(" "*8)+x for x in crs_lines]))
# Check if we do not have an RTC device at all
if not rtc_dict.get("valid") and lpc_name:
ssdt += """ External ([[LPCName]], DeviceObj) // (from opcode)
Scope ([[LPCName]])
{
Device (RTC0)
{
Name (_HID, EisaId ("PNP0B00")) // _HID: Hardware ID
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
{
IO (Decode16,
0x0070, // Range Minimum
0x0070, // Range Maximum
0x01, // Alignment
0x08, // Length
)
IRQNoFlags ()
{8}
})
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (0)
}
}
}
}
""".replace("[[LPCName]]",lpc_name)
ssdt += "}"
#self.write_ssdt("SSDT-RTCAWAC",ssdt)
#print("")
#print("Done.")
# See if we just generated a failsafe - and encourage manual checking
# Would require only an RTC device (no AWAC) that has an _STA with no STAS var
#if rtc_dict.get("valid") and not awac_dict.get("valid") and rtc_dict.get("sta") and not rtc_dict.get("has_var") and not rtc_range_needed:
# print("\n {}!! NOTE !!{} Only RTC (no AWAC) detected with an _STA method and no STAS".format(self.yel,self.rst))
# print(" variable! Patch(es) and SSDT-RTCAWAC created as a failsafe,")
# print(" but verify you need them by checking the RTC._STA conditions!")
#self.patch_warn()
#self.u.grab("Press [enter] to return...")
if self.write_ssdt(ssdt_name, ssdt):
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt),
"Path": ssdt_name + ".aml"
}
],
"Patch": awac_dict.get("patches",[])+rtc_dict.get("patches",[])
}
def fake_embedded_controller(self):
ssdt_name = "SSDT-EC"
laptop = "Laptop" in self.hardware_report.get("Motherboard").get("Platform")
#if not self.ensure_dsdt():
# return
#self.u.head("Fake EC")
#print("")
#print("Locating PNP0C09 (EC) devices...")
# Set up a helper method to determine
# if an _STA needs patching based on
# the type and returns.
def sta_needs_patching(sta):
if not isinstance(sta,dict) or not sta.get("sta"):
return False
# Check if we have an IntObj or MethodObj
# _STA, and scrape for values if possible.
if sta.get("sta_type") == "IntObj":
# We got an int - see if it's force-enabled
try:
sta_scope = table["lines"][sta["sta"][0][1]]
if not "Name (_STA, 0x0F)" in sta_scope:
return True
except Exception as e:
#print(e)
return True
elif sta.get("sta_type") == "MethodObj":
# We got a method - if we have more than one
# "Return (", or not a single "Return (0x0F)",
# then we need to patch this out and replace
try:
sta_scope = "\n".join(self.acpi.get_scope(sta["sta"][0][1],strip_comments=True,table=table))
if sta_scope.count("Return (") > 1 or not "Return (0x0F)" in sta_scope:
# More than one return, or our return isn't force-enabled
return True
except Exception as e:
return True
# If we got here - it's not a recognized type, or
# it was fullly qualified and doesn't need patching
return False
rename = False
named_ec = False
ec_to_patch = []
ec_to_enable = []
ec_sta = {}
ec_enable_sta = {}
patches = []
lpc_name = None
ec_located = False
for table_name in self.sorted_nicely(list(self.acpi.acpi_tables)):
table = self.acpi.acpi_tables[table_name]
ec_list = self.acpi.get_device_paths_with_hid("PNP0C09",table=table)
if len(ec_list):
lpc_name = ".".join(ec_list[0][0].split(".")[:-1])
#print(" - Got {:,} in {}".format(len(ec_list),table_name))
#print(" - Validating...")
for x in ec_list:
device = orig_device = x[0]
#print(" --> {}".format(device))
if device.split(".")[-1] == "EC":
named_ec = True
if not laptop:
# Only rename if we're trying to replace it
#print(" ----> PNP0C09 (EC) called EC. Renaming")
device = ".".join(device.split(".")[:-1]+["EC0"])
rename = True
scope = "\n".join(self.acpi.get_scope(x[1],strip_comments=True,table=table))
# We need to check for _HID, _CRS, and _GPE
if all(y in scope for y in ["_HID","_CRS","_GPE"]):
#print(" ----> Valid PNP0C09 (EC) Device")
ec_located = True
sta = self.get_sta_var(
var=None,
device=orig_device,
dev_hid="PNP0C09",
dev_name=orig_device.split(".")[-1],
log_locate=False,
table=table
)
if not laptop:
ec_to_patch.append(device)
# Only unconditionally override _STA methods
# if not building for a laptop
if sta.get("patches"):
patches.extend(sta.get("patches",[]))
ec_sta[device] = sta
elif sta.get("patches"):
if sta_needs_patching(sta):
# Retain the info as we need to override it
ec_to_enable.append(device)
ec_enable_sta[device] = sta
# Disable the patches by default and add to the list
for patch in sta.get("patches",[]):
patch["Enabled"] = False
patch["Disabled"] = True
patches.append(patch)
#else:
# print(" --> _STA properly enabled - skipping rename")
#else:
# print(" ----> NOT Valid PNP0C09 (EC) Device")
#if not ec_located:
#print(" - No valid PNP0C09 (EC) devices found - only needs a Fake EC device")
if laptop and named_ec and not patches:
#print(" ----> Named EC device located - no fake needed.")
#print("")
#self.u.grab("Press [enter] to return to main menu...")
return
if lpc_name is None:
lpc_name = self.get_lpc_name(skip_ec=True,skip_common_names=True)
if lpc_name is None:
#self.u.grab("Press [enter] to return to main menu...")
return
#comment = "Faked Embedded Controller"
if rename == True:
patches.insert(0,{
"Comment":"EC to EC0{}".format("" if not ec_sta else " - must come before any EC _STA to XSTA renames!"),
"Find":"45435f5f",
"Replace":"4543305f"
})
# comment += " - Needs EC to EC0 {}".format(
# "and EC _STA to XSTA renames" if ec_sta else "rename"
# )
#elif ec_sta:
# comment += " - Needs EC _STA to XSTA renames"
#oc = {"Comment":comment,"Enabled":True,"Path":"SSDT-EC.aml"}
#self.make_plist(oc, "SSDT-EC.aml", patches, replace=True)
#print("Creating SSDT-EC...")
ssdt = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "EC", 0x00001000)
{
External ([[LPCName]], DeviceObj)
""".replace("[[LPCName]]",lpc_name)
for x in ec_to_patch:
ssdt += " External ({}, DeviceObj)\n".format(x)
if x in ec_sta:
ssdt += " External ({}.XSTA, {})\n".format(x,ec_sta[x].get("sta_type","MethodObj"))
# Walk the ECs to enable
for x in ec_to_enable:
ssdt += " External ({}, DeviceObj)\n".format(x)
if x in ec_enable_sta:
# Add the _STA and XSTA refs as the patch may not be enabled
ssdt += " External ({0}._STA, {1})\n External ({0}.XSTA, {1})\n".format(x,ec_enable_sta[x].get("sta_type","MethodObj"))
# Walk them again and add the _STAs
for x in ec_to_patch:
ssdt += """
Scope ([[ECName]])
{
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0)
}
Else
{
Return ([[XSTA]])
}
}
}
""".replace("[[LPCName]]",lpc_name).replace("[[ECName]]",x) \
.replace("[[XSTA]]","{}.XSTA{}".format(x," ()" if ec_sta[x].get("sta_type","MethodObj")=="MethodObj" else "") if x in ec_sta else "0x0F")
# Walk them yet again - and force enable as needed
for x in ec_to_enable:
ssdt += """
If (LAnd (CondRefOf ([[ECName]].XSTA), LNot (CondRefOf ([[ECName]]._STA))))
{
Scope ([[ECName]])
{
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return ([[XSTA]])
}
}
}
}
""".replace("[[LPCName]]",lpc_name).replace("[[ECName]]",x) \
.replace("[[XSTA]]","{}.XSTA{}".format(x," ()" if ec_enable_sta[x].get("sta_type","MethodObj")=="MethodObj" else "") if x in ec_enable_sta else "Zero")
# Create the faked EC
if not laptop or not named_ec:
ssdt += """
Scope ([[LPCName]])
{
Device (EC)
{
Name (_HID, "ACID0001") // _HID: Hardware ID
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
}
}""".replace("[[LPCName]]",lpc_name)
# Close the SSDT scope
ssdt += """
}"""
#self.write_ssdt("SSDT-EC",ssdt)
#print("")
#print("Done.")
#self.patch_warn()
#self.u.grab("Press [enter] to return...")
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt),
"Path": ssdt_name + ".aml"
}
],
"Patch": patches
}
def get_data(self, data, pad_to=0):
if sys.version_info >= (3, 0):
if not isinstance(data,bytes):
data = data.encode()
return data+b"\x00"*(max(pad_to-len(data),0))
else:
return plistlib.Data(data+b"\x00"*(max(pad_to-len(data),0)))
def write_ssdt(self, ssdt_name, ssdt_content, compile=True):
dsl_path = os.path.join(self.acpi_directory, ssdt_name + ".dsl")
aml_path = os.path.join(self.acpi_directory, ssdt_name + ".aml")
with open(dsl_path,"w") as f:
f.write(ssdt_content)
if not compile:
return False
output = self.run({
"args":[self.acpi.iasl, dsl_path]
})
if output[-1] != 0:
return False
else:
os.remove(dsl_path)
return os.path.exists(aml_path)
def apply_acpi_patches(self, acpi_patches):
acpi_patches = [
{
"Base": acpi_patch.get("Base", ""),
"BaseSkip": acpi_patch.get("BaseSkip", 0),
"Comment": acpi_patch.get("Comment", ""),
"Count": acpi_patch.get("Count", 0),
"Enabled": True,
"Find": self.utils.hex_to_bytes(acpi_patch["Find"]),
"Limit": acpi_patch.get("Limit", 0),
"Mask": self.utils.hex_to_bytes(acpi_patch.get("Mask", "")),
"OemTableId": self.utils.hex_to_bytes(acpi_patch.get("OemTableId", "")),
"Replace": self.utils.hex_to_bytes(acpi_patch["Replace"]),
"ReplaceMask": self.utils.hex_to_bytes(acpi_patch.get("ReplaceMask", "")),
"Skip": acpi_patch.get("Skip", 0),
"TableLength": acpi_patch.get("TableLength", 0),
"TableSignature": self.utils.hex_to_bytes(acpi_patch.get("TableSignature", "")),
}
for acpi_patch in acpi_patches
]
return sorted(acpi_patches, key=lambda x: x["Comment"])
def add_intel_management_engine(self):
ssdt_name = "SSDT-IMEI"
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "IMEI", 0x00000000)
{
External (_SB_.PCI0, DeviceObj)
Scope (_SB.PCI0)
{
Device (IMEI)
{
Name (_ADR, 0x00160000) // _ADR: Address
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
}
}
}"""
imei_device = self.acpi.get_device_paths_with_hid("0x00160000", self.dsdt)
if not imei_device:
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
]
}
def add_memory_controller_device(self):
if not self.lpc_bus_device:
return
ssdt_name = "SSDT-MCHC"
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "MCHC", 0)
{
External ([[PCIName]], DeviceObj)
Scope ([[PCIName]])
{
Device (MCHC)
{
Name (_ADR, Zero)
Method (_STA, 0, NotSerialized)
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
}
}
}"""
mchc_device = self.acpi.get_device_paths("MCHC", self.dsdt)
if mchc_device:
return
pci_bus_device = ".".join(self.lpc_bus_device.split(".")[:2])
ssdt_content = ssdt_content.replace("[[PCIName]]", pci_bus_device)
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
]
}
def add_system_management_bus_device(self):
if not self.lpc_bus_device:
return
try:
smbus_device_name = self.acpi.get_device_paths_with_hid("0x001F0003" if self.hardware_report.get("CPU").get("Codename") in cpu_data.IntelCPUGenerations[50:] else "0x001F0004", self.dsdt)[0][0].split(".")[-1]
except:
smbus_device_name = "SBUS"
pci_bus_device = ".".join(self.lpc_bus_device.split(".")[:2])
smbus_device_path = "{}.{}".format(pci_bus_device, smbus_device_name)
ssdt_name = "SSDT-{}".format(smbus_device_name)
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "[[SMBUSName]]", 0)
{
External ([[SMBUSDevice]], DeviceObj)
Scope ([[SMBUSDevice]])
{
Device (BUS0)
{
Name (_CID, "smbus")
Name (_ADR, Zero)
Method (_STA, 0, NotSerialized)
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
}
}
}""".replace("[[SMBUSName]]", smbus_device_name).replace("[[SMBUSDevice]]", smbus_device_path)
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
]
}
def add_usb_power_properties(self):
ssdt_name = "SSDT-USBX"
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "USBX", 0x00001000)
{
Scope (\\_SB)
{
Device (USBX)
{
Name (_ADR, Zero) // _ADR: Address
Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method
{
If (LNot (Arg2))
{
Return (Buffer ()
{
0x03
})
}
Return (Package ()
{[[USBX_PROPS]]
})
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
}
}
}"""
usb_power_properties = None
if self.utils.contains_any(["MacPro7,1", "iMacPro1,1", "iMac20,", "iMac19,", "iMac18,", "iMac17,", "iMac16,"], self.smbios_model):
usb_power_properties = {
"kUSBSleepPowerSupply":"0x13EC",
"kUSBSleepPortCurrentLimit":"0x0834",
"kUSBWakePowerSupply":"0x13EC",
"kUSBWakePortCurrentLimit":"0x0834"
}
elif "MacMini8,1" in self.smbios_model:
usb_power_properties = {
"kUSBSleepPowerSupply":"0x0C80",
"kUSBSleepPortCurrentLimit":"0x0834",
"kUSBWakePowerSupply":"0x0C80",
"kUSBWakePortCurrentLimit":"0x0834"
}
elif self.utils.contains_any(["MacBookPro16,", "MacBookPro15,", "MacBookPro14,", "MacBookPro13,", "MacBookAir9,1"], self.smbios_model):
usb_power_properties = {
"kUSBSleepPortCurrentLimit":"0x0BB8",
"kUSBWakePortCurrentLimit":"0x0BB8"
}
elif "MacBook9,1" in self.smbios_model:
usb_power_properties = {
"kUSBSleepPowerSupply":"0x05DC",
"kUSBSleepPortCurrentLimit":"0x05DC",
"kUSBWakePowerSupply":"0x05DC",
"kUSBWakePortCurrentLimit":"0x05DC"
}
if usb_power_properties:
ssdt_content = ssdt_content.replace("[[USBX_PROPS]]", ",".join("\n \"{}\",\n {}".format(key, usb_power_properties[key]) for key in usb_power_properties))
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
]
}
def ambient_light_sensor(self):
ssdt_name = "SSDT-ALS0"
ssdt_content = """
// Resource: https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/Source/SSDT-ALS0.dsl
/*
* Starting with macOS 10.15 Ambient Light Sensor presence is required for backlight functioning.
* Here we create an Ambient Light Sensor ACPI Device, which can be used by SMCLightSensor kext
* to report either dummy (when no device is present) or valid values through SMC interface.
*/
DefinitionBlock ("", "SSDT", 2, "ZPSS", "ALS0", 0x00000000)
{
Scope (_SB)
{
Device (ALS0)
{
Name (_HID, "ACPI0008" /* Ambient Light Sensor Device */) // _HID: Hardware ID
Name (_CID, "smc-als") // _CID: Compatible ID
Name (_ALI, 0x012C) // _ALI: Ambient Light Illuminance
Name (_ALR, Package (0x01) // _ALR: Ambient Light Response
{
Package (0x02)
{
0x64,
0x012C
}
})
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
}
}
}"""
try:
als_device = self.acpi.get_device_paths_with_hid("ACPI0008", self.dsdt)[0][0]
except:
als_device = None
patches = []
if als_device:
als_device_name = als_device.split(".")[-1]
if "." not in als_device:
als_device_name = als_device_name[1:]
sta = self.get_sta_var(var=None, device=None, dev_hid="ACPI0008", dev_name=als_device_name, table=self.dsdt)
patches.extend(sta.get("patches", []))
ssdt_name = "SSDT-{}".format(als_device_name)
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "[[ALSName]]", 0x00000000)
{
External ([[ALSDevice]], DeviceObj)
External ([[ALSDevice]].XSTA, [[STAType]])
Scope ([[ALSDevice]])
{
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return ([[XSTA]])
}
}
}
}""".replace("[[ALSName]]", als_device_name) \
.replace("[[ALSDevice]]", als_device) \
.replace("[[STAType]]", sta.get("sta_type","MethodObj")) \
.replace("[[XSTA]]", "{}.XSTA{}".format(als_device," ()" if sta.get("sta_type","MethodObj") == "MethodObj" else "") if sta else "0x0F")
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
],
"Patch": patches
}
def findall_power_resource_blocks(self, table_lines):
power_resource_blocks = []
i = 0
while i < len(table_lines):
line = table_lines[i].strip()
if line.startswith("PowerResource"):
start_index = i
open_brackets = 1
i += 1
while i < len(table_lines) and open_brackets > 0:
if '{' in table_lines[i]:
open_brackets += table_lines[i].count('{')
if '}' in table_lines[i]:
open_brackets -= table_lines[i].count('}')
i += 1
end_index = i - 1
power_resource_blocks.append((start_index, end_index))
else:
i += 1
return power_resource_blocks
def is_method_in_power_resource(self, method, table_lines):
power_resource_blocks = self.findall_power_resource_blocks(table_lines)
for start, end in power_resource_blocks:
if start <= method[1] <= end:
return True
return False
def disable_unsupported_device(self):
results = {
"Add": []
}
for device_name, device_props in self.disabled_devices.items():
if not device_props.get("Bus Type", "PCI") == "PCI" or not device_props.get("ACPI Path"):
continue
ssdt_name = None
if "GPU" in device_name:
ssdt_name = "SSDT-Disable_GPU_{}".format(device_props.get("ACPI Path").split(".")[2])
target_device = device_props.get("ACPI Path")
off_method_found = ps3_method_found = False
for table_name, table_data in self.acpi.acpi_tables.items():
off_methods = self.acpi.get_method_paths("_OFF", table_data)
ps3_methods = self.acpi.get_method_paths("_PS3", table_data)
off_method_found = off_method_found or any(method[0].startswith(target_device) and not self.is_method_in_power_resource(method, table_data.get("lines")) for method in off_methods)
ps3_method_found = ps3_method_found or any(method[0].startswith(target_device) for method in ps3_methods)
if not off_method_found and not ps3_method_found:
continue
if off_method_found:
ps3_method_found = False
device_props["Disabled"] = True
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "DGPU", 0x00000000)
{"""
if off_method_found:
ssdt_content += """
External ([[DevicePath]]._OFF, MethodObj)
External ([[DevicePath]]._ON_, MethodObj)"""
if ps3_method_found:
ssdt_content += """
External ([[DevicePath]]._PS0, MethodObj)
External ([[DevicePath]]._PS3, MethodObj)
External ([[DevicePath]]._DSM, MethodObj)
"""
ssdt_content += """
Device (DGPU)
{
Name (_HID, "DGPU1000")
Method (_INI, 0, NotSerialized)
{
_OFF ()
}
Method (_STA, 0, NotSerialized)
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
Method (_ON, 0, NotSerialized)
{
"""
if off_method_found:
ssdt_content += """
[[DevicePath]]._ON ()
"""
if ps3_method_found:
ssdt_content += """
[[DevicePath]]._PS0 ()
"""
ssdt_content += """
}
Method (_OFF, 0, NotSerialized)
{
"""
if off_method_found:
ssdt_content += """
[[DevicePath]]._OFF ()
"""
if ps3_method_found:
ssdt_content += """
[[DevicePath]]._DSM (ToUUID ("a486d8f8-0bda-471b-a72b-6042a6b5bee0") /* Unknown UUID */, 0x0100, 0x1A, Buffer (0x04)
{
0x01, 0x00, 0x00, 0x03 // ....
})
[[DevicePath]]._PS3 ()
"""
ssdt_content += """\n }\n }\n}"""
elif "Network" in device_name and device_props.get("Bus Type") == "PCI":
ssdt_name = "SSDT-Disable_Network_{}".format(device_props.get("ACPI Path").split(".")[2])
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "DNET", 0x00000000)
{
External ([[DevicePath]], DeviceObj)
Method ([[DevicePath]]._DSM, 4, NotSerialized) // _DSM: Device-Specific Method
{
If ((!Arg2 || (_OSI ("Darwin") == Zero)))
{
Return (Buffer (One)
{
0x03 // .
})
}
Return (Package (0x0A)
{
"name",
Buffer (0x09)
{
"#network"
},
"IOName",
"#display",
"class-code",
Buffer (0x04)
{
0xFF, 0xFF, 0xFF, 0xFF // ....
},
"vendor-id",
Buffer (0x04)
{
0xFF, 0xFF, 0x00, 0x00 // ....
},
"device-id",
Buffer (0x04)
{
0xFF, 0xFF, 0x00, 0x00 // ....
}
})
}
}
"""
elif "Storage" in device_name:
ssdt_name = "SSDT-Disable_NVMe_{}".format(device_props.get("ACPI Path").split(".")[-2])
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "DNVMe", 0x00000000)
{
External ([[DevicePath]], DeviceObj)
Method ([[DevicePath]]._DSM, 4, NotSerialized) // _DSM: Device-Specific Method
{
If (_OSI ("Darwin"))
{
If (!Arg2)
{
Return (Buffer (One)
{
0x03 // .
})
}
Return (Package (0x02)
{
"class-code",
Buffer (0x04)
{
0xFF, 0x08, 0x01, 0x00 // ....
}
})
}
}
}
"""
if ssdt_name:
ssdt_content = ssdt_content.replace("[[DevicePath]]", device_props.get("ACPI Path"))
results["Add"].append(
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
)
return results
def enable_backlight_controls(self):
patches = []
integrated_gpu = list(self.hardware_report.get("GPU").items())[-1][-1]
uid_value = 19
if integrated_gpu.get("Codename") in ("Iron Lake", "Sandy Bridge", "Ivy Bridge"):
uid_value = 14
elif integrated_gpu.get("Codename") in ("Haswell", "Broadwell"):
uid_value = 15
elif integrated_gpu.get("Codename") in ("Skylake", "Kaby Lake"):
uid_value = 16
if "PNLF" in self.dsdt.get("table"):
patches.append({
"Comment": "PNLF to XNLF Rename",
"Find": "504E4C46",
"Replace": "584E4C46"
})
for table_name in self.sorted_nicely(list(self.acpi.acpi_tables)):
table = self.acpi.acpi_tables[table_name]
if binascii.unhexlify("084E4243460A00") in table.get("raw"):
patches.append({
"Comment": "NBCF 0x00 to 0x01",
"Find": "084E4243460A00",
"Replace": "084E4243460A01"
})
break
elif binascii.unhexlify("084E42434600") in table.get("raw"):
patches.append({
"Comment": "NBCF Zero to One",
"Find": "084E42434600",
"Replace": "084E42434601"
})
break
ssdt_name = "SSDT-PNLF"
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "PNLF", 0x00000000)
{"""
if integrated_gpu.get("ACPI Path"):
ssdt_content += """\n External ([[DevicePath]], DeviceObj)\n Device ([[DevicePath]].PNLF)"""
else:
ssdt_content += """\n Device (PNLF)"""
ssdt_content += """
{
Name (_HID, EisaId ("APP0002")) // _HID: Hardware ID
Name (_CID, "backlight") // _CID: Compatible ID
Name (_UID, [[uid_value]]) // _UID: Unique ID
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0B)
}
Else
{
Return (Zero)
}
}"""
if integrated_gpu.get("ACPI Path") and uid_value == 14:
ssdt_content += """
Method (_INI, 0, Serialized)
{
If (_OSI ("Darwin"))
{
OperationRegion ([[DevicePath]].RMP3, PCI_Config, Zero, 0x14)
Field ([[DevicePath]].RMP3, AnyAcc, NoLock, Preserve)
{
Offset (0x02), GDID,16,
Offset (0x10), BAR1,32,
}
// IGPU PWM backlight register descriptions:
// LEV2 not currently used
// LEVL level of backlight in Sandy/Ivy
// P0BL counter, when zero is vertical blank
// GRAN see description below in INI1 method
// LEVW should be initialized to 0xC0000000
// LEVX PWMMax except FBTYPE_HSWPLUS combo of max/level (Sandy/Ivy stored in MSW)
// LEVD level of backlight for Coffeelake
// PCHL not currently used
OperationRegion (RMB1, SystemMemory, BAR1 & ~0xF, 0xe1184)
Field(RMB1, AnyAcc, Lock, Preserve)
{
Offset (0x48250),
LEV2, 32,
LEVL, 32,
Offset (0x70040),
P0BL, 32,
Offset (0xc2000),
GRAN, 32,
Offset (0xc8250),
LEVW, 32,
LEVX, 32,
LEVD, 32,
Offset (0xe1180),
PCHL, 32,
}
// Now fixup the backlight PWM depending on the framebuffer type
// At this point:
// Local4 is RMCF.BLKT value (unused here), if specified (default is 1)
// Local0 is device-id for IGPU
// Local2 is LMAX, if specified (Ones means based on device-id)
// Local3 is framebuffer type
// Adjustment required when using WhateverGreen.kext
Local0 = GDID
Local2 = Ones
Local3 = 0
// check Sandy/Ivy
// #define FBTYPE_SANDYIVY 1
If (LOr (LEqual (1, Local3), LNotEqual (Match (Package()
{
// Sandy HD3000
0x010b, 0x0102,
0x0106, 0x1106, 0x1601, 0x0116, 0x0126,
0x0112, 0x0122,
// Ivy
0x0152, 0x0156, 0x0162, 0x0166,
0x016a,
// Arrandale
0x0046, 0x0042,
}, MEQ, Local0, MTR, 0, 0), Ones)))
{
if (LEqual (Local2, Ones))
{
// #define SANDYIVY_PWMMAX 0x710
Store (0x710, Local2)
}
// change/scale only if different than current...
Store (LEVX >> 16, Local1)
If (LNot (Local1))
{
Store (Local2, Local1)
}
If (LNotEqual (Local2, Local1))
{
// set new backlight PWMMax but retain current backlight level by scaling
Store ((LEVL * Local2) / Local1, Local0)
Store (Local2 << 16, Local3)
If (LGreater (Local2, Local1))
{
// PWMMax is getting larger... store new PWMMax first
Store (Local3, LEVX)
Store (Local0, LEVL)
}
Else
{
// otherwise, store new brightness level, followed by new PWMMax
Store (Local0, LEVL)
Store (Local3, LEVX)
}
}
}
}
}"""
ssdt_content += """
}
}"""
ssdt_content = ssdt_content.replace("[[uid_value]]", str(uid_value))
if integrated_gpu.get("ACPI Path"):
ssdt_content = ssdt_content.replace("[[DevicePath]]", integrated_gpu.get("ACPI Path"))
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
],
"Patch": patches
}
def enable_gpio_device(self):
try:
gpio_device = self.acpi.get_device_paths("GPI0", self.dsdt)[0][0] or self.acpi.get_device_paths("GPIO", self.dsdt)[0][0]
except:
return
sta = self.get_sta_var(var=None, device=gpio_device, dev_hid=None, dev_name=gpio_device.split(".")[-1], table=self.dsdt)
ssdt_name = "SSDT-GPI0"
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "GPI0", 0x00000000)
{
External ([[GPI0Path]], DeviceObj)
External ([[GPI0Path]].XSTA, [[STAType]])
Scope ([[GPI0Path]])
{
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return ([[XSTA]])
}
}
}
}""".replace("[[GPI0Path]]", gpio_device) \
.replace("[[STAType]]", sta.get("sta_type","MethodObj")) \
.replace("[[XSTA]]", "{}.XSTA{}".format(gpio_device," ()" if sta.get("sta_type","MethodObj") == "MethodObj" else "") if sta else "0x0F")
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
],
"Patch": sta.get("patches", [])
}
def enable_nvram_support(self):
if not self.lpc_bus_device:
return
ssdt_name = "SSDT-PMC"
ssdt_content = """
// Resource: https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/Source/SSDT-PMC.dsl
/*
* Intel 300-series PMC support for macOS
*
* Starting from Z390 chipsets PMC (D31:F2) is only available through MMIO.
* Since there is no standard device for PMC in ACPI, Apple introduced its
* own naming "APP9876" to access this device from AppleIntelPCHPMC driver.
* To avoid confusion we disable this device for all other operating systems,
* as they normally use another non-standard device with "PNP0C02" HID and
* "PCHRESV" UID.
*
* On certain implementations, including APTIO V, PMC initialisation is
* required for NVRAM access. Otherwise it will freeze in SMM mode.
* The reason for this is rather unclear. Note, that PMC and SPI are
* located in separate memory regions and PCHRESV maps both, yet only
* PMC region is used by AppleIntelPCHPMC:
* 0xFE000000~0xFE00FFFF - PMC MBAR
* 0xFE010000~0xFE010FFF - SPI BAR0
* 0xFE020000~0xFE035FFF - SerialIo BAR in ACPI mode
*
* PMC device has nothing to do to LPC bus, but is added to its scope for
* faster initialisation. If we add it to PCI0, where it normally exists,
* it will start in the end of PCI configuration, which is too late for
* NVRAM support.
*/
DefinitionBlock ("", "SSDT", 2, "ACDT", "PMCR", 0x00001000)
{
External ([[LPCPath]], DeviceObj)
Scope ([[LPCPath]])
{
Device (PMCR)
{
Name (_HID, EisaId ("APP9876")) // _HID: Hardware ID
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0B)
}
Else
{
Return (Zero)
}
}
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
{
Memory32Fixed (ReadWrite,
0xFE000000, // Address Base
0x00010000, // Address Length
)
})
}
}
}""".replace("[[LPCPath]]", self.lpc_bus_device)
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
],
}
def remove_conditional_scope(self):
return {
"Patch": [
{
"Comment": "Remove conditional ACPI scope declaration",
"Find": "A000000092935043484100",
"Replace": "A3A3A3A3A3A3A3A3A3A3A3",
"Mask": "FF000000FFFFFFFFFFFFFF",
"Count": 1,
"TableSignature": "44534454"
}
]
}
def fix_hp_005_post_error(self):
if binascii.unhexlify("4701700070000108") in self.dsdt.get("raw"):
return {
"Patch": [
{
"Comment": "Fix HP Real-Time Clock Power Loss (005) Post Error",
"Find": "4701700070000108",
"Replace": "4701700070000102"
}
]
}
def add_null_ethernet_device(self):
random_mac_address = self.smbios.generate_random_mac()
mac_address_byte = ", ".join([f'0x{random_mac_address[i:i+2]}' for i in range(0, len(random_mac_address), 2)])
ssdt_name = "SSDT-RMNE"
ssdt_content = """
// Resource: https://github.com/RehabMan/OS-X-Null-Ethernet/blob/master/SSDT-RMNE.dsl
/* ssdt.dsl -- SSDT injector for NullEthernet
*
* Copyright (c) 2014 RehabMan <racerrehabman@gmail.com>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
// Use this SSDT as an alternative to patching your DSDT...
DefinitionBlock("", "SSDT", 2, "ZPSS", "RMNE", 0x00001000)
{
Device (RMNE)
{
Name (_ADR, Zero)
// The NullEthernet kext matches on this HID
Name (_HID, "NULE0000")
// This is the MAC address returned by the kext. Modify if necessary.
Name (MAC, Buffer() { [[MACAddress]] })
Method (_DSM, 4, NotSerialized)
{
If (LEqual (Arg2, Zero)) { Return (Buffer() { 0x03 } ) }
Return (Package()
{
"built-in", Buffer() { 0x00 },
"IOName", "ethernet",
"name", Buffer() { "ethernet" },
"model", Buffer() { "RM-NullEthernet-1001" },
"device_type", Buffer() { "ethernet" },
})
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
}
}""".replace("[[MACAddress]]", mac_address_byte)
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
]
}
def is_intel_hedt_cpu(self, processor_name, cpu_codename):
if cpu_codename in cpu_data.IntelCPUGenerations[45:66]:
return cpu_codename.endswith(("-X", "-P", "-W", "-E", "-EP", "-EX"))
if cpu_codename in cpu_data.IntelCPUGenerations[66:]:
return "Xeon" in processor_name
return False
def fix_system_clock_hedt(self):
awac_device = self.acpi.get_device_paths_with_hid("ACPI000E", self.dsdt)
try:
rtc_device = self.acpi.get_device_paths_with_hid("PNP0B00", self.dsdt)[0][0]
if rtc_device.endswith("RTC"):
rtc_device += "_"
except:
if not self.lpc_bus_device:
return
rtc_device = self.lpc_bus_device + ".RTC0"
new_rtc_device = ".".join(rtc_device.split(".")[:-1] + [self.get_unique_device(rtc_device, rtc_device.split(".")[-1])[0]])
patches = []
ssdt_name = "SSDT-RTC0-RANGE"
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "RtcRange", 0x00000000)
{"""
if not awac_device:
sta = self.get_sta_var(var=None, device=rtc_device, dev_hid=None, dev_name=rtc_device.split(".")[-1], table=self.dsdt)
patches.extend(sta.get("patches", []))
ssdt_content += """
External ([[device_path]], DeviceObj)
Scope ([[device_path]])
{
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (Zero)
}
Else
{
Return (0x0F)
}
}
}""".replace("[[device_path]]", rtc_device)
ssdt_content += """
External ([[parent_path]], DeviceObj)
Device ([[device_path]])
{
Name (_HID, EisaId ("PNP0B00") /* AT Real-Time Clock */) // _HID: Hardware ID
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
{
IO (Decode16,
0x0070, // Range Minimum
0x0070, // Range Maximum
0x01, // Alignment
0x04, // Length
)
IO (Decode16,
0x0074, // Range Minimum
0x0074, // Range Maximum
0x01, // Alignment
0x04, // Length
)
IRQNoFlags ()
{8}
})
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (0x0F)
}
Else
{
Return (Zero)
}
}
}
}""".replace("[[parent_path]]", ".".join(rtc_device.split(".")[:-1])).replace("[[device_path]]", new_rtc_device)
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
],
"Patch": patches
}
def instant_wake_fix(self):
ssdt_name = "SSDT-PRW"
uswe_object = "9355535745"
wole_object = "93574F4C45"
gprw_method = "4750525702"
uprw_method = "5550525702"
xprw_method = "5850525702"
patches = []
if binascii.unhexlify(gprw_method) in self.dsdt.get("raw"):
patches.append({
"Comment": "GPRW to XPRW Rename",
"Find": gprw_method,
"Replace": xprw_method
})
else:
gprw_method = None
if binascii.unhexlify(uprw_method) in self.dsdt.get("raw"):
patches.append({
"Comment": "UPRW to XPRW Rename",
"Find": uprw_method,
"Replace": xprw_method
})
else:
uprw_method = None
if not binascii.unhexlify(uswe_object) in self.dsdt.get("raw"):
uswe_object = None
if not binascii.unhexlify(wole_object) in self.dsdt.get("raw"):
wole_object = None
ssdt_content = """
// Resource: https://github.com/5T33Z0/OC-Little-Translated/blob/main/04_Fixing_Sleep_and_Wake_Issues/060D_Instant_Wake_Fix/README.md
DefinitionBlock ("", "SSDT", 2, "ZPSS", "_PRW", 0x00000000)
{"""
if gprw_method or uprw_method:
ssdt_content += """\n External(XPRW, MethodObj)"""
if uswe_object:
ssdt_content += "\n External (USWE, FieldUnitObj)"
if wole_object:
ssdt_content += "\n External (WOLE, FieldUnitObj)"
if uswe_object or wole_object:
ssdt_content += """\n
Scope (\\)
{
If (_OSI ("Darwin"))
{"""
if uswe_object:
ssdt_content += "\n USWE = Zero"
if wole_object:
ssdt_content += "\n WOLE = Zero"
ssdt_content += """ }
}"""
if gprw_method:
ssdt_content += """
Method (GPRW, 2, NotSerialized)
{
If (_OSI ("Darwin"))
{
If ((0x6D == Arg0))
{
Return (Package ()
{
0x6D,
Zero
})
}
If ((0x0D == Arg0))
{
Return (Package ()
{
0x0D,
Zero
})
}
}
Return (XPRW (Arg0, Arg1))
}"""
if uprw_method:
ssdt_content += """
Method (UPRW, 2, NotSerialized)
{
If (_OSI ("Darwin"))
{
If ((0x6D == Arg0))
{
Return (Package ()
{
0x6D,
Zero
})
}
If ((0x0D == Arg0))
{
Return (Package ()
{
0x0D,
Zero
})
}
}
Return (XPRW (Arg0, Arg1))
}"""
ssdt_content += "\n}"
if gprw_method or uprw_method or uswe_object or wole_object:
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
],
"Patch": patches
}
def fix_uncore_bridge(self):
unc0_device = self.acpi.get_device_paths("UNC0", self.dsdt)
if not unc0_device:
return
ssdt_name = "SSDT-UNC"
ssdt_content = """
// Resource: https://github.com/acidanthera/OpenCorePkg/blob/master/Docs/AcpiSamples/Source/SSDT-UNC.dsl
/*
* Discovered on X99-series.
* These platforms have uncore PCI bridges for 4 CPU sockets
* present in ACPI despite having none physically.
*
* Under normal conditions these are disabled depending on
* CPU presence in the socket via Processor Bit Mask (PRBM),
* but on X99 this code is unused or broken as such bridges
* simply do not exist. We fix that by writing 0 to PRBM.
*
* Doing so is important as starting with macOS 11 IOPCIFamily
* will crash as soon as it sees non-existent PCI bridges.
*/
DefinitionBlock ("", "SSDT", 2, "ZPSS", "UNC", 0x00000000)
{
External (_SB.UNC0, DeviceObj)
External (PRBM, IntObj)
Scope (_SB.UNC0)
{
Method (_INI, 0, NotSerialized)
{
// In most cases this patch does benefit all operating systems,
// yet on select pre-Windows 10 it may cause issues.
// Remove If (_OSI ("Darwin")) in case you have none.
If (_OSI ("Darwin")) {
PRBM = 0
}
}
}
}"""
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
]
}
def operating_system_patch(self):
ssdt_name = "SSDT-XOSI"
ssdt_content = """
// Resource: https://github.com/dortania/Getting-Started-With-ACPI/blob/master/extra-files/decompiled/SSDT-XOSI.dsl
DefinitionBlock ("", "SSDT", 2, "ZPSS", "XOSI", 0x00001000)
{
Method (XOSI, 1, NotSerialized)
{
// Based off of:
// https://docs.microsoft.com/en-us/windows-hardware/drivers/acpi/winacpi-osi#_osi-strings-for-windows-operating-systems
// Add OSes from the below list as needed, most only check up to Windows 2015
// but check what your DSDT looks for
Store (Package ()
{
[[OSIStrings]]
}, Local0)
If (_OSI ("Darwin"))
{
Return (LNotEqual (Match (Local0, MEQ, Arg0, MTR, Zero, Zero), Ones))
}
Else
{
Return (_OSI (Arg0))
}
}
}""".replace("[[OSIStrings]]", "\n,".join([" \"{}\"".format(osi_string) for target_os, osi_string in self.osi_strings.items() if osi_string in self.dsdt.get("table")]))
patches = []
osid = self.acpi.get_method_paths("OSID", self.dsdt)
if osid:
patches.append({
"Comment": "OSID to XSID rename - must come before _OSI to XOSI rename!",
"Find": "4F534944",
"Replace": "58534944"
})
osif = self.acpi.get_method_paths("OSIF", self.dsdt)
if osif:
patches.append({
"Comment": "OSIF to XSIF rename - must come before _OSI to XOSI rename!",
"Find": "4F534946",
"Replace": "58534946"
})
patches.append({
"Comment": "_OSI to XOSI rename - requires SSDT-XOSI.aml",
"Find": "5F4F5349",
"Replace": "584F5349"
})
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
],
"Patch": patches
}
def surface_laptop_special_patch(self):
ssdt_name = "SSDT-SURFACE"
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "SURFACE", 0x00001000)
{
External (_SB_.PCI0, DeviceObj)
External (GPRW, MethodObj) // 2 Arguments
If (_OSI ("Darwin"))
{
Scope (_SB)
{
Device (ALS0)
{
Name (_HID, "ACPI0008" /* Ambient Light Sensor Device */) // _HID: Hardware ID
Name (_CID, "smc-als") // _CID: Compatible ID
Name (_ALI, 0x012C) // _ALI: Ambient Light Illuminance
Name (_ALR, Package (0x05) // _ALR: Ambient Light Response
{
Package (0x02)
{
0x46,
Zero
},
Package (0x02)
{
0x49,
0x0A
},
Package (0x02)
{
0x55,
0x50
},
Package (0x02)
{
0x64,
0x012C
},
Package (0x02)
{
0x96,
0x03E8
}
})
Method (XALI, 1, Serialized)
{
_ALI = Arg0
}
}
Device (ADP0)
{
Name (_HID, "ACPI0003" /* Power Source Device */) // _HID: Hardware ID
Name (SPSR, Zero)
Method (_PRW, 0, NotSerialized) // _PRW: Power Resources for Wake
{
Return (GPRW (0x6D, 0x04))
}
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
Method (XPSR, 1, Serialized)
{
If ((Arg0 == Zero))
{
SPSR = Zero
}
ElseIf ((Arg0 == One))
{
SPSR = One
}
Notify (ADP0, 0x80) // Status Change
}
Method (_PSR, 0, Serialized) // _PSR: Power Source
{
Return (SPSR) /* \\_SB_.ADP0.SPSR */
}
Method (_PCL, 0, NotSerialized) // _PCL: Power Consumer List
{
Return (\\_SB)
}
}
Device (BAT0)
{
Name (_HID, EisaId ("PNP0C0A") /* Control Method Battery */) // _HID: Hardware ID
Name (_UID, Zero) // _UID: Unique ID
Name (_PCL, Package (0x01) // _PCL: Power Consumer List
{
_SB
})
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x1F)
}
}
}
Scope (_SB.PCI0)
{
Device (IPTS)
{
Name (_ADR, 0x00160004) // _ADR: Address
}
}
}
}
"""
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
]
}
def find_line_start(self, text, index):
current_idx = index
while current_idx > 0:
if text[current_idx] == '\n':
return current_idx + 1
current_idx -= 1
return 0
def extract_line(self, text, index):
start_idx = self.find_line_start(text, index)
end_idx = text.index("\n", start_idx) + 1 if "\n" in text[start_idx:] else len(text)
return text[start_idx:end_idx].strip(), start_idx, end_idx
def extract_block_content(self, text, start_idx):
try:
block_start = text.index("{", start_idx)
brace_count = 1
pos = block_start + 1
while brace_count > 0 and pos < len(text):
if text[pos] == '{':
brace_count += 1
elif text[pos] == '}':
brace_count -= 1
pos += 1
if brace_count == 0:
return text[block_start:pos]
except ValueError as e:
pass
return ""
def parse_field_line(self, line):
try:
if "//" in line:
line = line.split("//")[0].strip()
parts = line.split(",")
if len(parts) >= 2:
field_name = parts[0].strip()
size_part = parts[1].strip()
try:
field_size = int(size_part)
except ValueError:
return None, None
return field_name, field_size
except (ValueError, IndexError) as e:
pass
return None, None
def process_embedded_control_region(self, table, start_idx):
try:
embed_control_idx = table.index("EmbeddedControl", start_idx)
line, start_line_idx, end_line_idx = self.extract_line(table, embed_control_idx)
region_name = line.split("(")[1].split(",")[0].strip()
return region_name, end_line_idx
except (ValueError, IndexError) as e:
return None, start_idx + 1
def process_field_definition(self, table, region_name, start_idx):
fields = []
try:
field_pattern = f"Field ({region_name}"
if field_pattern not in table[start_idx:]:
return fields, len(table)
field_start_idx = table.index(field_pattern, start_idx)
field_line, field_start_line_idx, field_end_line_idx = self.extract_line(table, field_start_idx)
field_block = self.extract_block_content(table, field_end_line_idx)
for line in field_block.splitlines():
line = line.strip()
if not line or line in ["{", "}"]:
continue
field_name, field_size = self.parse_field_line(line)
if field_name and field_size is not None:
field_info = {
"name": field_name,
"size": field_size,
}
fields.append(field_info)
return fields, field_end_line_idx
except (ValueError, IndexError) as e:
return fields, start_idx + 1
def battery_status_patch(self):
if not self.dsdt:
return False
search_start_idx = 0
all_fields = []
while "EmbeddedControl" in self.dsdt.get("table")[search_start_idx:]:
region_name, search_start_idx = self.process_embedded_control_region(self.dsdt.get("table"), search_start_idx)
if not region_name:
continue
current_idx = search_start_idx
region_fields = []
while True:
fields, next_idx = self.process_field_definition(self.dsdt.get("table"), region_name, current_idx)
if not fields or next_idx <= current_idx:
break
region_fields.extend(fields)
current_idx = next_idx
if f"Field ({region_name}" not in self.dsdt.get("table")[current_idx:]:
break
all_fields.extend(region_fields)
return any(f["size"] > 8 for f in all_fields)
def dropping_the_table(self, signature=None, oemtableid=None):
table_data = self.acpi.get_table_with_signature(signature) or self.acpi.get_table_with_id(oemtableid)
if not table_data:
return
return {
"All": True,
"Comment": "Delete {}".format((signature or oemtableid).rstrip(b"\x00").decode()),
"Enabled": True,
"OemTableId": self.utils.hex_to_bytes(binascii.hexlify(table_data.get("id")).decode()),
"TableLength": table_data.get("length"),
"TableSignature": self.utils.hex_to_bytes(binascii.hexlify(table_data.get("signature")).decode())
}
def fix_apic_processor_id(self):
self.apic = self.acpi.get_table_with_signature("APIC")
new_apic = ""
if not self.apic:
return
for table_name in self.sorted_nicely(list(self.acpi.acpi_tables)):
table = self.acpi.acpi_tables[table_name]
processors = self.acpi.get_processor_paths(table=table)
if not processors:
continue
processor_index = -1
apic_length = len(self.apic.get("lines"))
skip_unknown_subtable = False
for index in range(apic_length):
line = self.apic.get("lines")[index]
if "Unknown" in line:
skip_unknown_subtable = not skip_unknown_subtable
continue
if skip_unknown_subtable:
continue
if "Subtable Type" in line and "[Processor Local APIC]" in line:
processor_index += 1
apic_processor_id = self.apic["lines"][index + 2][-2:]
try:
processor_id = table.get("lines")[processors[processor_index][1]].split(", ")[1][2:]
except:
return
if processor_index == 0 and apic_processor_id == processor_id:
return
self.apic["lines"][index + 2] = self.apic["lines"][index + 2][:-2] + processor_id
new_apic += line + "\n"
if processor_index != -1:
return {
"Add": [
{
"Comment": "APIC.aml",
"Enabled": self.write_ssdt("APIC", new_apic),
"Path": "APIC.aml"
}
],
"Delete": [
self.dropping_the_table("APIC")
]
}
def disable_usb_hub_devices(self):
ssdt_name = "SSDT-USB-Reset"
patches = []
ssdt_content = """
DefinitionBlock ("", "SSDT", 2, "ZPSS", "UsbReset", 0x00001000)
{"""
rhub_devices = self.acpi.get_device_paths("RHUB")
rhub_devices.extend(self.acpi.get_device_paths("HUBN"))
rhub_devices.extend(self.acpi.get_device_paths("URTH"))
if not rhub_devices:
return
for device in rhub_devices:
device_path = device[0]
sta = self.get_sta_var(var=None, device=device_path, dev_hid=None, dev_name=device_path.split(".")[-1], table=self.dsdt)
patches.extend(sta.get("patches", []))
ssdt_content += """
External ([[device_path]], DeviceObj)
Scope ([[device_path]])
{
Method (_STA, 0, NotSerialized) // _STA: Status
{
If (_OSI ("Darwin"))
{
Return (Zero)
}
Else
{
Return (0x0F)
}
}
}
""".replace("[[device_path]]", device_path)
ssdt_content += "\n}"
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
],
"Patch": patches
}
def return_thermal_zone(self):
ssdt_name = "SSDT-WMIS"
ssdt_content = """
// Resource: https://github.com/zhen-zen/YogaSMC/blob/master/YogaSMC/SSDTSample/SSDT-WMIS.dsl
/*
* Sample SSDT to fix sensor return
*
* Certain models forget to return result from ThermalZone:
*
* Method (WQBI, 1, NotSerialized)
* {
* \_TZ.WQBI (Arg0)
* }
*
* So we have to patch it for correct reporting.
* Rename Method (WQBI, 1, N) to XQBI
* (ThermalZone one usually has Serialized type)
*
* Find: 57514249 01 // WQBI
* Repl: 58514249 01 // XQBI
*
* MethodFlags :=
* bit 0-2: ArgCount (0-7)
* bit 3: SerializeFlag
* 0 NotSerialized
* 1 Serialized
*/
DefinitionBlock ("", "SSDT", 2, "ZPSS", "WMIS", 0x00000000)
{
External (_TZ.WQBI, MethodObj) // Method in ThermalZone
Method (_SB.WMIS.WQBI, 1, NotSerialized)
{
Return (\_TZ.WQBI (Arg0))
}
}
"""
for table_name in self.sorted_nicely(list(self.acpi.acpi_tables)):
table = self.acpi.acpi_tables[table_name]
wqbi_method = self.acpi.get_method_paths("WQBI", table=table)
if not wqbi_method:
continue
return {
"Add": [
{
"Comment": ssdt_name + ".aml",
"Enabled": self.write_ssdt(ssdt_name, ssdt_content),
"Path": ssdt_name + ".aml"
}
],
"Patch": [
{
"Comment": "WQBI to XQBI Rename",
"Find": "5751424901",
"Replace": "5851424901"
}
]
}
def drop_cpu_tables(self):
cpu_tables = ["CpuPm", "Cpu0Ist"]
deletes = []
for table_name in cpu_tables:
padded_table_id = self.get_data(table_name, pad_to=8)
table_entry = self.dropping_the_table(oemtableid=padded_table_id)
if table_entry:
deletes.append(table_entry)
return {
"Delete": deletes
}
def select_acpi_tables(self):
while True:
self.utils.head("Select ACPI Tables")
print("")
print("Q. Quit")
print(" ")
menu = self.utils.request_input("Please drag and drop ACPI Tables folder here: ")
if menu.lower() == "q":
self.utils.exit_program()
path = self.utils.normalize_path(menu)
if not path:
continue
return self.read_acpi_tables(path)
def get_patch_index(self, name):
for index, patch in enumerate(self.patches):
if patch.name == name:
return index
return None
def select_acpi_patches(self, hardware_report, disabled_devices):
selected_patches = []
if "Laptop" in hardware_report.get("Motherboard").get("Platform") and \
"Integrated GPU" in list(hardware_report.get("GPU").items())[-1][-1].get("Device Type") and \
not "SURFACE" in hardware_report.get("Motherboard").get("Name"):
selected_patches.append("ALS")
selected_patches.append("PNLF")
if self.is_intel_hedt_cpu(hardware_report.get("CPU").get("Processor Name"), hardware_report.get("CPU").get("Codename")):
selected_patches.append("APIC")
if "Intel" in hardware_report.get("CPU").get("Manufacturer"):
selected_patches.append("BUS0")
for device_name, device_info in disabled_devices.items():
if "PCI" in device_info.get("Bus Type", "PCI"):
selected_patches.append("Disable Devices")
selected_patches.append("FakeEC")
if "HP " in hardware_report.get("Motherboard").get("Name"):
selected_patches.append("CMOS")
if hardware_report.get("Motherboard").get("Chipset") in chipset_data.IntelChipsets[-7:]:
selected_patches.append("RCSP")
if "Laptop" in hardware_report.get("Motherboard").get("Platform") and hardware_report.get("CPU").get("Codename") in cpu_data.IntelCPUGenerations[50:]:
selected_patches.append("FixHPET")
for device_name, device_info in hardware_report.get("System Devices", {}).items():
device_id = device_info.get("Device ID")
if not device_id in ("8086-1C3A", "8086-1E3A"):
continue
if "Sandy Bridge" in hardware_report.get("CPU").get("Codename") and device_id in "8086-1E3A" or \
"Ivy Bridge" in hardware_report.get("CPU").get("Codename") and device_id in "8086-1C3A":
selected_patches.append("IMEI")
if hardware_report.get("Motherboard").get("Chipset") in chipset_data.IntelChipsets[100:112]:
selected_patches.append("PMC")
if "Sandy Bridge" in hardware_report.get("CPU").get("Codename") or "Ivy Bridge" in hardware_report.get("CPU").get("Codename"):
selected_patches.append("PM (Legacy)")
else:
selected_patches.append("PLUG")
if not hardware_report.get("Network"):
selected_patches.append("RMNE")
if hardware_report.get("Motherboard").get("Chipset") in ("C610/X99", "Wellsburg", "X299"):
selected_patches.append("RTC0")
if "AMD" in hardware_report.get("CPU").get("Manufacturer") or hardware_report.get("CPU").get("Codename") in cpu_data.IntelCPUGenerations[:40]:
selected_patches.append("RTCAWAC")
if "SURFACE" in hardware_report.get("Motherboard").get("Name"):
selected_patches.append("Surface Patch")
else:
if "Intel" in hardware_report.get("CPU").get("Manufacturer"):
for device_name, device_info in hardware_report.get("Input", {}).items():
if "I2C" in device_info.get("Device Type", "None"):
selected_patches.append("GPI0")
if hardware_report.get("Motherboard").get("Chipset") in ("C600/X79", "C610/X99", "Wellsburg"):
selected_patches.append("UNC")
if "AMD" in hardware_report.get("CPU").get("Manufacturer") or hardware_report.get("Motherboard").get("Chipset") in chipset_data.IntelChipsets[112:]:
selected_patches.append("USB Reset")
selected_patches.append("USBX")
if "Laptop" in hardware_report.get("Motherboard").get("Platform"):
selected_patches.append("BATP")
selected_patches.append("XOSI")
for device_name, device_info in hardware_report.get("System Devices", {}).items():
if device_info.get("Bus Type") == "ACPI" and device_info.get("Device") in pci_data.YogaHIDs:
selected_patches.append("WMIS")
for patch in self.patches:
patch.checked = patch.name in selected_patches
def customize_patch_selection(self):
while True:
contents = []
contents.append("")
contents.append("List of available patches:")
contents.append("")
for index, kext in enumerate(self.patches, start=1):
checkbox = "[*]" if kext.checked else "[ ]"
line = "{} {:2}. {:15} - {:60}".format(checkbox, index, kext.name, kext.description)
if kext.checked:
line = "\033[1;32m{}\033[0m".format(line)
contents.append(line)
contents.append("\033[1;36m")
contents.append("Note: You can select multiple kexts by entering their indices separated by commas (e.g., '1, 2, 3').")
contents.append("\033[0m")
contents.append("B. Back")
contents.append("Q. Quit")
contents.append("")
content = "\n".join(contents)
self.utils.adjust_window_size(content)
self.utils.head("Customize ACPI Patch Selections", resize=False)
print(content)
option = self.utils.request_input("Select your option: ")
if option.lower() == "q":
self.utils.exit_program()
if option.lower() == "b":
return
indices = [int(i.strip()) -1 for i in option.split(",") if i.strip().isdigit()]
for index in indices:
if index >= 0 and index < len(self.patches):
patch = self.patches[index]
patch.checked = not patch.checked