OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
acdtinfo.c
Go to the documentation of this file.
1//
2// OpenCore project
3// Acidanthera version detection code
4// Copyright (c) 2021 vit9696
5// Public domain release
6//
7
8#include <stdio.h>
9#include <stdint.h>
10#include <stddef.h>
11#include <stdbool.h>
12#include <assert.h>
13
14#if defined(__APPLE__)
15
16#include <IOKit/graphics/IOGraphicsLib.h>
17#include <CoreFoundation/CoreFoundation.h>
18
19#define LILU_SERVICE_NAME "Lilu"
20#define ALC_SERVICE_NAME "AppleALC"
21#define ARPT_SERVICE_NAME "AirportBrcmFixup"
22#define BRKEYS_SERVICE_NAME "BrightnessKeys"
23#define CPUF_SERVICE_NAME "CPUFriend"
24#define CPUTSC_SERVICE_NAME "CpuTscSync"
25#define DBGEN_SERVICE_NAME "DebugEnhancer"
26#define HBFX_SERVICE_NAME "HibernationFixup"
27#define NVMEF_SERVICE_NAME "NVMeFix"
28#define RSTREV_SERVICE_NAME "RestrictEvents"
29#define RTCFX_SERVICE_NAME "RTCMemoryFixup"
30#define SMCBAT_SERVICE_NAME "SMCBatteryManager"
31#define SMCCPU_SERVICE_NAME "SMCProcessor"
32#define SMCDELL_SERVICE_NAME "SMCDellSensors"
33#define SMCLIGH_SERVICE_NAME "SMCLightSensor"
34#define SMCSSIO_SERVICE_NAME "SMCSuperIO"
35#define VSMC_SERVICE_NAME "VirtualSMC"
36#define WEG_SERVICE_NAME "WhateverGreen"
37
38#define ACDT_VERSION_NAME "VersionInfo"
39#define ACDT_VERSION_LENGTH 32
40
41typedef struct {
42 char build_type[3];
43 char delim1;
44 char version_major;
45 char version_minor;
46 char version_patch;
47 char delim2;
48 char year[4];
49 char delim3;
50 char month[2];
51 char delim4;
52 char day[2];
53} acdt_version_t;
54
55static CFStringRef acdt_kext_list[] = {
56 CFSTR(LILU_SERVICE_NAME),
57 CFSTR(ALC_SERVICE_NAME),
58 CFSTR(ARPT_SERVICE_NAME),
59 CFSTR(BRKEYS_SERVICE_NAME),
60 CFSTR(CPUF_SERVICE_NAME),
61 CFSTR(CPUTSC_SERVICE_NAME),
62 CFSTR(DBGEN_SERVICE_NAME),
63 CFSTR(HBFX_SERVICE_NAME),
64 CFSTR(NVMEF_SERVICE_NAME),
65 CFSTR(RSTREV_SERVICE_NAME),
66 CFSTR(RTCFX_SERVICE_NAME),
67 CFSTR(SMCBAT_SERVICE_NAME),
68 CFSTR(SMCCPU_SERVICE_NAME),
69 CFSTR(SMCDELL_SERVICE_NAME),
70 CFSTR(SMCLIGH_SERVICE_NAME),
71 CFSTR(SMCSSIO_SERVICE_NAME),
72 CFSTR(VSMC_SERVICE_NAME),
73 CFSTR(WEG_SERVICE_NAME),
74};
75
76#define ACDT_KEXT_NUM (sizeof(acdt_kext_list)/sizeof(acdt_kext_list[0]))
77
78io_object_t acdt_get_service_worker(CFStringRef service_name, io_iterator_t device_iterator) {
79 io_object_t object;
80 while ((object = IOIteratorNext(device_iterator))) {
81 CFTypeRef class_name = IORegistryEntryCreateCFProperty(object, CFSTR("IOClass"), kCFAllocatorDefault, 0);
82 if (class_name != NULL
83 && CFGetTypeID(class_name) == CFStringGetTypeID()
84 && CFEqual(class_name, service_name)) {
85 break;
86 }
87
88 IOObjectRelease(object);
89
90 kern_return_t result = IORegistryIteratorEnterEntry(device_iterator);
91 if (result == kIOReturnSuccess) {
92 object = acdt_get_service_worker(service_name, device_iterator);
93 IORegistryIteratorExitEntry(device_iterator);
94 if (object != 0) {
95 break;
96 }
97 }
98 }
99
100 return object;
101}
102
103io_object_t acdt_get_service(CFStringRef service_name) {
104 io_iterator_t device_iterator;
105 kern_return_t result = IORegistryCreateIterator(kIOMasterPortDefault,
106 kIOServicePlane, 0, &device_iterator);
107 if (result != kIOReturnSuccess) {
108 fprintf(stderr, "ERROR: Unable to connect to access IOService - %d\n", result);
109 return 0;
110 }
111
112 io_object_t object = acdt_get_service_worker(service_name, device_iterator);
113 IOObjectRelease(device_iterator);
114 return object;
115}
116
117bool acdt_detect_kext(CFStringRef service, char *version) {
118 assert(service != NULL);
119 assert(version != NULL);
120
121 version[0] = '\0';
122
123 io_object_t object = acdt_get_service(service);
124 if (object == 0) {
125 return false;
126 }
127
128 // Not every plugin is published as a service, thus do recursive property iteration.
129 CFTypeRef version_name = IORegistryEntryCreateCFProperty(object,
130 CFSTR(ACDT_VERSION_NAME), kCFAllocatorDefault, 0);
131 if (version_name != NULL && CFGetTypeID(version_name) == CFStringGetTypeID()) {
132 if (!CFStringGetCString(version_name, version, ACDT_VERSION_LENGTH, kCFStringEncodingUTF8)) {
133 fprintf(stderr, "ERROR: Unable to decode version string\n");
134 }
135 } else {
136 // This is non-fatal for older plugins that may not publish versions.
137 fprintf(stderr, "ERROR: Kext has no version info, make sure you have the latest version.\n");
138 }
139
140 IOObjectRelease(object);
141
142 return true;
143}
144
145const char *acdt_get_build_type(acdt_version_t *version) {
146 if (strncmp(version->build_type, "DBG", 3) == 0) {
147 return "DEBUG";
148 }
149 if (strncmp(version->build_type, "REL", 3) == 0) {
150 return "RELEASE";
151 }
152 if (strncmp(version->build_type, "NPT", 3) == 0) {
153 return "NOOPT";
154 }
155 return "Unknown";
156}
157
158int main() {
159 char tmp_version[ACDT_VERSION_LENGTH];
160 acdt_version_t acdt_version;
161 printf("Installed kexts:\n");
162 for (size_t i = 0; i < ACDT_KEXT_NUM; ++i) {
163 bool has_kext = acdt_detect_kext(acdt_kext_list[i], tmp_version);
164 printf("- %-32s: ", CFStringGetCStringPtr(acdt_kext_list[i], kCFStringEncodingUTF8));
165 if (has_kext && tmp_version[0] != '\0') {
166 memcpy(&acdt_version, tmp_version, sizeof(acdt_version));
167 printf("Yes (%c.%c.%c, published %.2s.%.2s.%.4s, %s)\n", acdt_version.version_major,
168 acdt_version.version_minor, acdt_version.version_patch,
169 acdt_version.day, acdt_version.month, acdt_version.year,
170 acdt_get_build_type(&acdt_version));
171 } else if (has_kext) {
172 printf("Yes\n");
173 } else {
174 puts("No");
175 }
176 }
177}
178
179#else
180
181int main() {
182 fprintf(stderr, "This utility requires macOS\n");
183 return -1;
184}
185
186#endif
UINT8 version
Definition BmfFile.h:126
int main()
Definition acdtinfo.c:181
#define assert
#define memcpy(Dst, Src, Size)
Definition lzvn.h:57