WIP device probe refactor part 2

This commit is contained in:
Dhinak G
2021-06-06 23:03:25 -04:00
parent 4747c2619f
commit fecf9502d0
3 changed files with 750 additions and 758 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -83,8 +83,8 @@ def patching_status():
return sip_enabled, sbm_enabled, amfi_enabled, fv_enabled
def cls():
if check_recovery() == False:
os.system('cls' if os.name == 'nt' else 'clear')
if not check_recovery():
os.system("cls" if os.name == "nt" else "clear")
else:
print("\u001Bc")

View File

@@ -1,35 +1,11 @@
import binascii
import enum
import itertools
from dataclasses import dataclass, field
import plistlib
import subprocess
from dataclasses import dataclass, field
from typing import Any, ClassVar, Optional, Type
from Resources import Utilities, ioreg, PCIIDArray
@dataclass
class GPU:
arch: enum.Enum = field(init=False) # The architecture, see subclasses.
def __post_init__(self):
self.detect_arch()
def detect_arch(self):
raise NotImplementedError
@dataclass
class WirelessCard:
CLASS_CODE: ClassVar[int] = 0x028000 # 00800200 hexswapped
model: enum.Enum = field(init=False)
def __post_init__(self):
self.detect_model()
def detect_model(self):
raise NotImplementedError
from Resources import PCIIDArray, Utilities, ioreg
@dataclass
@@ -41,7 +17,8 @@ class PCIDevice:
class_code: int # The class code of this PCI device
# ioregistryentry: Optional[ioreg.IORegistryEntry] = None
name: Optional[str] = None
name: Optional[str] = None # Name of IORegistryEntry
model: Optional[str] = None # model property
pci_path: Optional[str] = None
# def __getstate__(self):
@@ -50,14 +27,15 @@ class PCIDevice:
# return state
@classmethod
def from_ioregistry(cls, entry: ioreg.IORegistryEntry):
device = cls(
int.from_bytes(entry.properties["vendor-id"][:4], byteorder="little"),
int.from_bytes(entry.properties["device-id"][:4], byteorder="little"),
int.from_bytes(entry.properties["class-code"][:6], byteorder="little"),
)
def from_ioregistry(cls, entry: ioreg.IORegistryEntry, anti_spoof=False):
if anti_spoof and "IOName" in entry.properties:
vendor_id, device_id = (int(i, 16) for i in entry.properties["IOName"][3:].split(","))
else:
vendor_id, device_id = [int.from_bytes(entry.properties[i][:4], byteorder="little") for i in ["vendor-id", "device-id"]]
device = cls(vendor_id, device_id, int.from_bytes(entry.properties["class-code"][:6], byteorder="little"), name=entry.name)
if "model" in entry.properties:
device.name = entry.properties["model"].strip(b"\0").decode()
device.model = entry.properties["model"].strip(b"\0").decode()
device.populate_pci_path(entry)
return device
@@ -69,7 +47,7 @@ class PCIDevice:
# return None
def vendor_detect(self, *, inherits: ClassVar[Any] = None, classes: list = None):
for i in classes or PCIDevice.__subclasses__():
for i in classes or itertools.chain.from_iterable([subclass.__subclasses__() for subclass in PCIDevice.__subclasses__()]):
if issubclass(i, inherits or object) and i.detect(self):
return i
return None
@@ -83,8 +61,7 @@ class PCIDevice:
# raise NotImplementedError
def populate_pci_path(self, entry: ioreg.IORegistryEntry):
# Eventually
# Trash, but who really cares?
# Based off gfxutil logic, seems to work.
paths = []
while entry:
if entry.entry_class == "IOPCIDevice":
@@ -98,7 +75,30 @@ class PCIDevice:
@dataclass
class NVIDIA(GPU, PCIDevice):
class GPU(PCIDevice):
arch: enum.Enum = field(init=False) # The architecture, see subclasses.
def __post_init__(self):
self.detect_arch()
def detect_arch(self):
raise NotImplementedError
@dataclass
class WirelessCard(PCIDevice):
CLASS_CODE: ClassVar[int] = 0x028000 # 00800200 hexswapped
chipset: enum.Enum = field(init=False)
def __post_init__(self):
self.detect_chipset()
def detect_chipset(self):
raise NotImplementedError
@dataclass
class NVIDIA(GPU):
VENDOR_ID: ClassVar[int] = 0x10DE
class Archs(enum.Enum):
@@ -123,7 +123,7 @@ class NVIDIA(GPU, PCIDevice):
@dataclass
class AMD(GPU, PCIDevice):
class AMD(GPU):
VENDOR_ID: ClassVar[int] = 0x1002
class Archs(enum.Enum):
@@ -156,7 +156,7 @@ class AMD(GPU, PCIDevice):
@dataclass
class Intel(GPU, PCIDevice):
class Intel(GPU):
VENDOR_ID: ClassVar[int] = 0x8086
class Archs(enum.Enum):
@@ -180,10 +180,10 @@ class Intel(GPU, PCIDevice):
@dataclass
class Broadcom(WirelessCard, PCIDevice):
class Broadcom(WirelessCard):
VENDOR_ID: ClassVar[int] = 0x14E4
class Models(enum.Enum):
class Chipsets(enum.Enum):
# pylint: disable=invalid-name
AirportBrcmNIC = "AirportBrcmNIC supported"
AirPortBrcm4360 = "AirPortBrcm4360 supported"
@@ -191,38 +191,38 @@ class Broadcom(WirelessCard, PCIDevice):
AirPortBrcm43224 = "AppleAirPortBrcm43224 supported"
Unknown = "Unknown"
model: Models = field(init=False)
chipset: Chipsets = field(init=False)
def detect_model(self):
def detect_chipset(self):
if self.device_id in PCIIDArray.broadcom_ids.AirPortBrcmNIC:
self.model = Broadcom.Models.AirportBrcmNIC
self.chipset = Broadcom.Chipsets.AirportBrcmNIC
elif self.device_id in PCIIDArray.broadcom_ids.AirPortBrcm4360:
self.model = Broadcom.Models.AirPortBrcm4360
self.chipset = Broadcom.Chipsets.AirPortBrcm4360
elif self.device_id in PCIIDArray.broadcom_ids.AirPortBrcm4331:
self.model = Broadcom.Models.AirPortBrcm4331
self.chipset = Broadcom.Chipsets.AirPortBrcm4331
elif self.device_id in PCIIDArray.broadcom_ids.AppleAirPortBrcm43224:
self.model = Broadcom.Models.AirPortBrcm43224
self.chipset = Broadcom.Chipsets.AirPortBrcm43224
else:
self.model = Broadcom.Models.Unknown
self.chipset = Broadcom.Chipsets.Unknown
@dataclass
class Atheros(WirelessCard, PCIDevice):
class Atheros(WirelessCard):
VENDOR_ID: ClassVar[int] = 0x168C
class Models(enum.Enum):
class Chipsets(enum.Enum):
# pylint: disable=invalid-name
# Well there's only one model but
AirPortAtheros40 = "AirPortAtheros40 supported"
Unknown = "Unknown"
model: Models = field(init=False)
chipset: Chipsets = field(init=False)
def detect_model(self):
def detect_chipset(self):
if self.device_id in PCIIDArray.atheros_ids.AtherosWifi:
self.model = Atheros.Models.AirPortAtheros40
self.chipset = Atheros.Chipsets.AirPortAtheros40
else:
self.model = Atheros.Models.Unknown
self.chipset = Atheros.Chipsets.Unknown
@dataclass
@@ -233,16 +233,16 @@ class CPU:
@dataclass
class Computer:
opencore_model: Optional[str] = None
opencore_board_id: Optional[str] = None
real_model: Optional[str] = None
real_board_id: Optional[str] = None
reported_model: Optional[str] = None
reported_board_id: Optional[str] = None
gpus: list[GPU] = field(default_factory=list)
igpu: Optional[GPU] = None
dgpu: Optional[GPU] = None
wifi: Optional[PCIDevice] = None
igpu: Optional[GPU] = None # Shortcut for IGPU
dgpu: Optional[GPU] = None # Shortcut for GFX0
wifi: Optional[WirelessCard] = None
cpu: Optional[CPU] = None
oclp: Optional[str] = None
oclp_version: Optional[str] = None
ioregistry: Optional[ioreg.IOReg] = None
@staticmethod
@@ -258,6 +258,7 @@ class Computer:
return computer
def gpu_probe(self):
# Chain together two iterators: one for class code 00000300, the other for class code 00800300
devices = itertools.chain(self.ioregistry.find(property=("class-code", binascii.a2b_hex("00000300"))), self.ioregistry.find(property=("class-code", binascii.a2b_hex("00800300"))))
for device in devices:
@@ -266,28 +267,21 @@ class Computer:
self.gpus.append(vendor.from_ioregistry(device)) # type: ignore
def dgpu_probe(self):
# result = subprocess.run("ioreg -r -n GFX0 -a".split(), stdout=subprocess.PIPE).stdout.strip()
result = list(self.ioregistry.find(name="GFX0"))
if not result:
device = next(self.ioregistry.find(name="GFX0"), None)
if not device:
# No devices
return
# device = plistlib.loads(result)[0]
device = result[0]
vendor: Type[GPU] = PCIDevice.from_ioregistry(device).vendor_detect(inherits=GPU) # type: ignore
if vendor:
self.dgpu = vendor.from_ioregistry(device) # type: ignore
def igpu_probe(self):
# result = subprocess.run("ioreg -r -n IGPU -a".split(), stdout=subprocess.PIPE).stdout.strip()
result = list(self.ioregistry.find(name="IGPU"))
if not result:
device = next(self.ioregistry.find(name="IGPU"), None)
if not device:
# No devices
return
# device = plistlib.loads(result)[0]
device = result[0]
vendor: Type[GPU] = PCIDevice.from_ioregistry(device).vendor_detect(inherits=GPU) # type: ignore
if vendor:
self.igpu = vendor.from_ioregistry(device) # type: ignore
@@ -311,24 +305,22 @@ class Computer:
for device in devices:
vendor: Type[WirelessCard] = PCIDevice.from_ioregistry(device).vendor_detect(inherits=WirelessCard) # type: ignore
if vendor:
self.wifi = vendor.from_ioregistry(device) # type: ignore
self.wifi = vendor.from_ioregistry(device, anti_spoof=True) # type: ignore
break
def smbios_probe(self):
opencore_model = subprocess.run("nvram -x 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-product".split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.strip()
if opencore_model:
self.opencore_model = plistlib.loads(opencore_model)["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-product"].decode()
self.reported_model = next(self.ioregistry.find(entry_class="IOPlatformExpertDevice")).properties["model"].strip(b"\0").decode()
opencore_board = subprocess.run("nvram -x 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-board".split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.strip()
if opencore_board:
self.opencore_board_id = plistlib.loads(opencore_board)["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-board"].decode()
# Reported model
entry = next(self.ioregistry.find(entry_class="IOPlatformExpertDevice"))
self.reported_model = entry.properties["model"].strip(b"\0").decode()
self.reported_board_id = entry.properties.get("board-id", entry.properties.get("target-type", b"")).strip(b"\0").decode()
oclp_version = subprocess.run("nvram -x 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:OCLP-Version".split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.strip()
if oclp_version:
self.oclp = plistlib.loads(oclp_version)["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:OCLP-Version"].strip(b"\0").decode()
# Real model
# TODO: We previously had logic for OC users using iMacPro1,1 with incorrect ExposeSensitiveData. Add logic?
self.real_model = Utilities.get_nvram("oem-product", "4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102", decode=True) or self.reported_model
self.real_board_id = Utilities.get_nvram("oem-board", "4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102", decode=True) or self.reported_board_id
# OCLP version
self.oclp_version = Utilities.get_nvram("OCLP-Version", "4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102", decode=True)
def cpu_probe(self):
self.cpu = CPU(