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
+672 -672
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -83,8 +83,8 @@ def patching_status():
return sip_enabled, sbm_enabled, amfi_enabled, fv_enabled return sip_enabled, sbm_enabled, amfi_enabled, fv_enabled
def cls(): def cls():
if check_recovery() == False: if not check_recovery():
os.system('cls' if os.name == 'nt' else 'clear') os.system("cls" if os.name == "nt" else "clear")
else: else:
print("\u001Bc") print("\u001Bc")
+76 -84
View File
@@ -1,35 +1,11 @@
import binascii import binascii
import enum import enum
import itertools import itertools
from dataclasses import dataclass, field
import plistlib
import subprocess import subprocess
from dataclasses import dataclass, field
from typing import Any, ClassVar, Optional, Type from typing import Any, ClassVar, Optional, Type
from Resources import Utilities, ioreg, PCIIDArray from Resources import PCIIDArray, Utilities, ioreg
@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
@dataclass @dataclass
@@ -41,7 +17,8 @@ class PCIDevice:
class_code: int # The class code of this PCI device class_code: int # The class code of this PCI device
# ioregistryentry: Optional[ioreg.IORegistryEntry] = None # 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 pci_path: Optional[str] = None
# def __getstate__(self): # def __getstate__(self):
@@ -50,14 +27,15 @@ class PCIDevice:
# return state # return state
@classmethod @classmethod
def from_ioregistry(cls, entry: ioreg.IORegistryEntry): def from_ioregistry(cls, entry: ioreg.IORegistryEntry, anti_spoof=False):
device = cls( if anti_spoof and "IOName" in entry.properties:
int.from_bytes(entry.properties["vendor-id"][:4], byteorder="little"), vendor_id, device_id = (int(i, 16) for i in entry.properties["IOName"][3:].split(","))
int.from_bytes(entry.properties["device-id"][:4], byteorder="little"), else:
int.from_bytes(entry.properties["class-code"][:6], byteorder="little"), 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: 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) device.populate_pci_path(entry)
return device return device
@@ -69,7 +47,7 @@ class PCIDevice:
# return None # return None
def vendor_detect(self, *, inherits: ClassVar[Any] = None, classes: list = 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): if issubclass(i, inherits or object) and i.detect(self):
return i return i
return None return None
@@ -83,8 +61,7 @@ class PCIDevice:
# raise NotImplementedError # raise NotImplementedError
def populate_pci_path(self, entry: ioreg.IORegistryEntry): def populate_pci_path(self, entry: ioreg.IORegistryEntry):
# Eventually # Based off gfxutil logic, seems to work.
# Trash, but who really cares?
paths = [] paths = []
while entry: while entry:
if entry.entry_class == "IOPCIDevice": if entry.entry_class == "IOPCIDevice":
@@ -98,7 +75,30 @@ class PCIDevice:
@dataclass @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 VENDOR_ID: ClassVar[int] = 0x10DE
class Archs(enum.Enum): class Archs(enum.Enum):
@@ -123,7 +123,7 @@ class NVIDIA(GPU, PCIDevice):
@dataclass @dataclass
class AMD(GPU, PCIDevice): class AMD(GPU):
VENDOR_ID: ClassVar[int] = 0x1002 VENDOR_ID: ClassVar[int] = 0x1002
class Archs(enum.Enum): class Archs(enum.Enum):
@@ -156,7 +156,7 @@ class AMD(GPU, PCIDevice):
@dataclass @dataclass
class Intel(GPU, PCIDevice): class Intel(GPU):
VENDOR_ID: ClassVar[int] = 0x8086 VENDOR_ID: ClassVar[int] = 0x8086
class Archs(enum.Enum): class Archs(enum.Enum):
@@ -180,10 +180,10 @@ class Intel(GPU, PCIDevice):
@dataclass @dataclass
class Broadcom(WirelessCard, PCIDevice): class Broadcom(WirelessCard):
VENDOR_ID: ClassVar[int] = 0x14E4 VENDOR_ID: ClassVar[int] = 0x14E4
class Models(enum.Enum): class Chipsets(enum.Enum):
# pylint: disable=invalid-name # pylint: disable=invalid-name
AirportBrcmNIC = "AirportBrcmNIC supported" AirportBrcmNIC = "AirportBrcmNIC supported"
AirPortBrcm4360 = "AirPortBrcm4360 supported" AirPortBrcm4360 = "AirPortBrcm4360 supported"
@@ -191,38 +191,38 @@ class Broadcom(WirelessCard, PCIDevice):
AirPortBrcm43224 = "AppleAirPortBrcm43224 supported" AirPortBrcm43224 = "AppleAirPortBrcm43224 supported"
Unknown = "Unknown" 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: 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: 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: 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: elif self.device_id in PCIIDArray.broadcom_ids.AppleAirPortBrcm43224:
self.model = Broadcom.Models.AirPortBrcm43224 self.chipset = Broadcom.Chipsets.AirPortBrcm43224
else: else:
self.model = Broadcom.Models.Unknown self.chipset = Broadcom.Chipsets.Unknown
@dataclass @dataclass
class Atheros(WirelessCard, PCIDevice): class Atheros(WirelessCard):
VENDOR_ID: ClassVar[int] = 0x168C VENDOR_ID: ClassVar[int] = 0x168C
class Models(enum.Enum): class Chipsets(enum.Enum):
# pylint: disable=invalid-name # pylint: disable=invalid-name
# Well there's only one model but # Well there's only one model but
AirPortAtheros40 = "AirPortAtheros40 supported" AirPortAtheros40 = "AirPortAtheros40 supported"
Unknown = "Unknown" 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: if self.device_id in PCIIDArray.atheros_ids.AtherosWifi:
self.model = Atheros.Models.AirPortAtheros40 self.chipset = Atheros.Chipsets.AirPortAtheros40
else: else:
self.model = Atheros.Models.Unknown self.chipset = Atheros.Chipsets.Unknown
@dataclass @dataclass
@@ -233,16 +233,16 @@ class CPU:
@dataclass @dataclass
class Computer: class Computer:
opencore_model: Optional[str] = None real_model: Optional[str] = None
opencore_board_id: Optional[str] = None real_board_id: Optional[str] = None
reported_model: Optional[str] = None reported_model: Optional[str] = None
reported_board_id: Optional[str] = None reported_board_id: Optional[str] = None
gpus: list[GPU] = field(default_factory=list) gpus: list[GPU] = field(default_factory=list)
igpu: Optional[GPU] = None igpu: Optional[GPU] = None # Shortcut for IGPU
dgpu: Optional[GPU] = None dgpu: Optional[GPU] = None # Shortcut for GFX0
wifi: Optional[PCIDevice] = None wifi: Optional[WirelessCard] = None
cpu: Optional[CPU] = None cpu: Optional[CPU] = None
oclp: Optional[str] = None oclp_version: Optional[str] = None
ioregistry: Optional[ioreg.IOReg] = None ioregistry: Optional[ioreg.IOReg] = None
@staticmethod @staticmethod
@@ -258,6 +258,7 @@ class Computer:
return computer return computer
def gpu_probe(self): 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")))) 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: for device in devices:
@@ -266,28 +267,21 @@ class Computer:
self.gpus.append(vendor.from_ioregistry(device)) # type: ignore self.gpus.append(vendor.from_ioregistry(device)) # type: ignore
def dgpu_probe(self): def dgpu_probe(self):
# result = subprocess.run("ioreg -r -n GFX0 -a".split(), stdout=subprocess.PIPE).stdout.strip() device = next(self.ioregistry.find(name="GFX0"), None)
result = list(self.ioregistry.find(name="GFX0")) if not device:
if not result:
# No devices # No devices
return return
# device = plistlib.loads(result)[0]
device = result[0]
vendor: Type[GPU] = PCIDevice.from_ioregistry(device).vendor_detect(inherits=GPU) # type: ignore vendor: Type[GPU] = PCIDevice.from_ioregistry(device).vendor_detect(inherits=GPU) # type: ignore
if vendor: if vendor:
self.dgpu = vendor.from_ioregistry(device) # type: ignore self.dgpu = vendor.from_ioregistry(device) # type: ignore
def igpu_probe(self): def igpu_probe(self):
# result = subprocess.run("ioreg -r -n IGPU -a".split(), stdout=subprocess.PIPE).stdout.strip() device = next(self.ioregistry.find(name="IGPU"), None)
result = list(self.ioregistry.find(name="IGPU")) if not device:
if not result:
# No devices # No devices
return return
# device = plistlib.loads(result)[0]
device = result[0]
vendor: Type[GPU] = PCIDevice.from_ioregistry(device).vendor_detect(inherits=GPU) # type: ignore vendor: Type[GPU] = PCIDevice.from_ioregistry(device).vendor_detect(inherits=GPU) # type: ignore
if vendor: if vendor:
self.igpu = vendor.from_ioregistry(device) # type: ignore self.igpu = vendor.from_ioregistry(device) # type: ignore
@@ -311,24 +305,22 @@ class Computer:
for device in devices: for device in devices:
vendor: Type[WirelessCard] = PCIDevice.from_ioregistry(device).vendor_detect(inherits=WirelessCard) # type: ignore vendor: Type[WirelessCard] = PCIDevice.from_ioregistry(device).vendor_detect(inherits=WirelessCard) # type: ignore
if vendor: if vendor:
self.wifi = vendor.from_ioregistry(device) # type: ignore self.wifi = vendor.from_ioregistry(device, anti_spoof=True) # type: ignore
break break
def smbios_probe(self): 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() # Reported model
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()
entry = next(self.ioregistry.find(entry_class="IOPlatformExpertDevice")) 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() 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() # Real model
if oclp_version: # TODO: We previously had logic for OC users using iMacPro1,1 with incorrect ExposeSensitiveData. Add logic?
self.oclp = plistlib.loads(oclp_version)["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:OCLP-Version"].strip(b"\0").decode() 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): def cpu_probe(self):
self.cpu = CPU( self.cpu = CPU(