From f9c7273106d749c65be283fa8a5c9fd3aaf92e79 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Thu, 9 Feb 2023 12:44:26 -0700 Subject: [PATCH] os_probe.py: Rework to be Object-oriented Minimize repetitive calls to platform.uname() --- resources/main.py | 9 +++-- resources/os_probe.py | 88 ++++++++++++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 25 deletions(-) diff --git a/resources/main.py b/resources/main.py index de1649fda..4dd962c82 100644 --- a/resources/main.py +++ b/resources/main.py @@ -44,10 +44,11 @@ class OpenCoreLegacyPatcher: def generate_base_data(self): - self.constants.detected_os = os_probe.detect_kernel_major() - self.constants.detected_os_minor = os_probe.detect_kernel_minor() - self.constants.detected_os_build = os_probe.detect_os_build() - self.constants.detected_os_version = os_probe.detect_os_version() + os_data = os_probe.OSProbe() + self.constants.detected_os = os_data.detect_kernel_major() + self.constants.detected_os_minor = os_data.detect_kernel_minor() + self.constants.detected_os_build = os_data.detect_os_build() + self.constants.detected_os_version = os_data.detect_os_version() self.constants.computer = device_probe.Computer.probe() self.constants.recovery_status = utilities.check_recovery() self.computer = self.constants.computer diff --git a/resources/os_probe.py b/resources/os_probe.py index 657ed662f..a88f32883 100644 --- a/resources/os_probe.py +++ b/resources/os_probe.py @@ -5,31 +5,77 @@ import subprocess import plistlib -def detect_kernel_major(): - # Return Major Kernel Version - # Example Output: 21 (integer) - return int(platform.uname().release.partition(".")[0]) +class OSProbe: + """ + Library for querying OS information specific to macOS + """ + + def __init__(self): + self.uname_data = platform.uname() -def detect_kernel_minor(): - # Return Minor Kernel Version - # Example Output: 1 (integer) - return int(platform.uname().release.partition(".")[2].partition(".")[0]) + def detect_kernel_major(self): + """ + Detect the booted major kernel version + + Returns: + int: Major kernel version (ex. 21, from 21.1.0) + """ + + return int(self.uname_data.release.partition(".")[0]) -def detect_os_version(): - # Return OS version - # Example Output: 12.0 (string) - return subprocess.run("sw_vers -productVersion".split(), stdout=subprocess.PIPE).stdout.decode().strip() + def detect_kernel_minor(self): + """ + Detect the booted minor kernel version + + Returns: + int: Minor kernel version (ex. 1, from 21.1.0) + """ + + return int(self.uname_data.release.partition(".")[2].partition(".")[0]) -def detect_os_build(): - # Return OS build - # Example Output: 21A5522h (string) + def detect_os_version(self): + """ + Detect the booted OS version - # With macOS 13.2, Apple implemented the Rapid Security Response system which - # will change the reported build to the RSR version and not the original host - # To get the proper versions: - # - Host: /System/Library/CoreServices/SystemVersion.plist - # - RSR: /System/Volumes/Preboot/Cryptexes/OS/System/Library/CoreServices/SystemVersion.plist - return plistlib.load(open("/System/Library/CoreServices/SystemVersion.plist", "rb"))["ProductBuildVersion"] + Returns: + str: OS version (ex. 12.0) + """ + + result = subprocess.run(["sw_vers", "-productVersion"], stdout=subprocess.PIPE) + if result.returncode != 0: + raise RuntimeError("Failed to detect OS version") + + return result.stdout.decode().strip() + + + def detect_os_build(self, rsr: bool = False): + """ + Detect the booted OS build + + Implementation note: + With macOS 13.2, Apple implemented the Rapid Security Response system which + will change the reported build to the RSR version and not the original host + + To get the proper versions: + - Host: /System/Library/CoreServices/SystemVersion.plist + - RSR: /System/Volumes/Preboot/Cryptexes/OS/System/Library/CoreServices/SystemVersion.plist + + + Parameters: + rsr (bool): Whether to use the RSR version of the build + + Returns: + str: OS build (ex. 21A5522h) + """ + + file_path = "/System/Library/CoreServices/SystemVersion.plist" + if rsr is True: + file_path = f"/System/Volumes/Preboot/Cryptexes/OS{file_path}" + + try: + return plistlib.load(open(file_path, "rb"))["ProductBuildVersion"] + except Exception as e: + raise RuntimeError(f"Failed to detect OS build: {e}")