[PATCH 3/3] ntdll: Generate SMBIOS tables on Apple Silicon Macs.
Brendan Shanks
bshanks at codeweavers.com
Mon Sep 13 17:07:27 CDT 2021
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51557
Signed-off-by: Brendan Shanks <bshanks at codeweavers.com>
---
dlls/ntdll/unix/system.c | 105 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 104 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c
index 70636020489..960a737028f 100644
--- a/dlls/ntdll/unix/system.c
+++ b/dlls/ntdll/unix/system.c
@@ -1262,7 +1262,7 @@ static NTSTATUS create_cpuset_info(SYSTEM_CPU_SET_INFORMATION *info)
return STATUS_SUCCESS;
}
-#ifdef linux
+#if defined(linux) || defined(__APPLE__)
static void copy_smbios_string( char **buffer, const char *s, size_t len )
{
@@ -1458,6 +1458,10 @@ static NTSTATUS create_smbios_tables( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, U
return STATUS_SUCCESS;
}
+#endif
+
+#ifdef linux
+
static size_t get_smbios_string( const char *path, char *str, size_t size )
{
FILE *file;
@@ -1640,6 +1644,103 @@ static NTSTATUS get_smbios_from_iokit( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti,
return STATUS_SUCCESS;
}
+static size_t cf_to_string( CFTypeRef type_ref, char *buffer, size_t buffer_size )
+{
+ size_t length = 0;
+
+ if (!type_ref)
+ return 0;
+
+ if (CFGetTypeID(type_ref) == CFDataGetTypeID())
+ {
+ length = MIN(CFDataGetLength(type_ref), buffer_size);
+ CFDataGetBytes(type_ref, CFRangeMake(0, length), (UInt8*)buffer);
+ buffer[length] = 0;
+ length = strlen(buffer);
+ }
+ else if (CFGetTypeID(type_ref) == CFStringGetTypeID())
+ {
+ if (CFStringGetCString(type_ref, buffer, buffer_size, kCFStringEncodingASCII))
+ length = strlen(buffer);
+ }
+
+ CFRelease(type_ref);
+ return length;
+}
+
+static NTSTATUS generate_smbios( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULONG available_len,
+ ULONG *required_len )
+{
+ /* Apple Silicon Macs don't have SMBIOS, we need to generate it.
+ * Use strings and data from IOKit when available.
+ */
+ io_service_t platform_expert;
+ CFDataRef cf_manufacturer, cf_model;
+ CFStringRef cf_serial_number, cf_uuid_string;
+ char manufacturer[128], model[128], serial_number[128];
+ size_t manufacturer_len = 0, model_len = 0, serial_number_len = 0;
+ GUID system_uuid = {0};
+
+ platform_expert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
+ if (!platform_expert)
+ return STATUS_NO_MEMORY;
+
+ cf_manufacturer = IORegistryEntryCreateCFProperty(platform_expert, CFSTR("manufacturer"), kCFAllocatorDefault, 0);
+ cf_model = IORegistryEntryCreateCFProperty(platform_expert, CFSTR("model"), kCFAllocatorDefault, 0);
+ cf_serial_number = IORegistryEntryCreateCFProperty(platform_expert, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0);
+ cf_uuid_string = IORegistryEntryCreateCFProperty(platform_expert, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
+
+ manufacturer_len = cf_to_string(cf_manufacturer, manufacturer, sizeof(manufacturer));
+ model_len = cf_to_string(cf_model, model, sizeof(model));
+ serial_number_len = cf_to_string(cf_serial_number, serial_number, sizeof(serial_number));
+
+ if (cf_uuid_string)
+ {
+ CFUUIDRef cf_uuid;
+ CFUUIDBytes bytes;
+
+ cf_uuid = CFUUIDCreateFromString(kCFAllocatorDefault, cf_uuid_string);
+ bytes = CFUUIDGetUUIDBytes(cf_uuid);
+
+ system_uuid.Data1 = (bytes.byte0 << 24) | (bytes.byte1 << 16) | (bytes.byte2 << 8) | bytes.byte3;
+ system_uuid.Data2 = (bytes.byte4 << 8) | bytes.byte5;
+ system_uuid.Data3 = (bytes.byte6 << 8) | bytes.byte7;
+ memcpy(&system_uuid.Data4, &bytes.byte8, sizeof(system_uuid.Data4));
+
+ CFRelease(cf_uuid);
+ CFRelease(cf_uuid_string);
+ }
+
+ IOObjectRelease(platform_expert);
+
+#define S(s) s, s ## _len
+#define STR(s) s, sizeof(s)-1
+ return create_smbios_tables( sfti, available_len, required_len,
+ S(manufacturer), /* BIOS vendor */
+ STR("1.0"), /* BIOS version (required) */
+ STR("01/01/2021"), /* BIOS date (required) */
+ S(manufacturer), /* system vendor */
+ S(model), /* system product */
+ STR("1.0"), /* system version */
+ S(serial_number), /* system serial number */
+ &system_uuid, /* system UUID */
+ NULL, 0, /* system SKU */
+ S(model), /* system family */
+ S(manufacturer), /* board vendor */
+ S(model), /* board product */
+ S(model), /* board version */
+ S(serial_number), /* board serial number */
+ NULL, 0, /* board asset tag */
+ S(manufacturer), /* chassis vendor */
+ 2, /* chassis type: unknown */
+ NULL, 0, /* chassis version */
+ S(serial_number), /* chassis serial number */
+ NULL, 0 /* chassis asset tag */
+ );
+#undef STR
+#undef S
+}
+
static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULONG available_len,
ULONG *required_len )
{
@@ -1649,6 +1750,8 @@ static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULON
{
NTSTATUS ret;
ret = get_smbios_from_iokit(sfti, available_len, required_len);
+ if (ret == STATUS_NO_MEMORY)
+ ret = generate_smbios(sfti, available_len, required_len);
return ret;
}
default:
--
2.30.1 (Apple Git-130)
More information about the wine-devel
mailing list