[PATCH v3 1/4] kernel32: Return BIOS info from GetSystemFirmwareTable on Linux

Alex Henrie alexhenrie24 at gmail.com
Wed Jun 13 09:30:28 CDT 2018


Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
 dlls/kernel32/cpu.c     | 135 ++++++++++++++++++++++++++++++++++++++++
 dlls/kernel32/process.c |  10 ---
 2 files changed, 135 insertions(+), 10 deletions(-)

diff --git a/dlls/kernel32/cpu.c b/dlls/kernel32/cpu.c
index ec1fd0f90d..4dd9bb628a 100644
--- a/dlls/kernel32/cpu.c
+++ b/dlls/kernel32/cpu.c
@@ -46,8 +46,37 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(reg);
 
+#include "pshpack1.h"
+
+struct smbios_prologue {
+    BYTE calling_method;
+    BYTE major_version;
+    BYTE minor_version;
+    BYTE revision;
+    DWORD length;
+};
+
+struct smbios_bios {
+    BYTE type;
+    BYTE length;
+    WORD handle;
+    BYTE manufacturer;
+    BYTE version;
+    WORD start;
+    BYTE date;
+    BYTE size;
+    UINT64 characteristics;
+};
+
+#include "poppack.h"
+
 #define SHARED_DATA     ((KSHARED_USER_DATA*)0x7ffe0000)
 
+/* Firmware table providers */
+#define ACPI 0x41435049
+#define FIRM 0x4649524D
+#define RSMB 0x52534D42
+
 /****************************************************************************
  *		QueryPerformanceCounter (KERNEL32.@)
  *
@@ -336,3 +365,109 @@ DWORD64 WINAPI GetEnabledXStateFeatures(void)
     FIXME("\n");
     return 0;
 }
+
+static inline void copy_smbios_string(void **buffer, char *string, size_t string_size)
+{
+    if (!string) return;
+    strcpy(*buffer, string);
+    *buffer = (char*)(*buffer) + string_size;
+}
+
+#ifdef linux
+static char* get_smbios_string(const char *path, size_t *string_size)
+{
+    FILE *file = fopen(path, "r");
+    char *ret = NULL;
+    *string_size = 0;
+    if (file)
+    {
+        *string_size = getline(&ret, string_size, file) + 1;
+        fclose(file);
+        if (*string_size >= 2 && ret[*string_size - 2] == '\n')
+        {
+            ret[*string_size - 2] = 0;
+            (*string_size)--;
+        }
+        if (*string_size == 1)
+        {
+            free(ret);
+            ret = NULL;
+            *string_size = 0;
+        }
+    }
+    return ret;
+}
+#endif
+
+/***********************************************************************
+ *           GetSystemFirmwareTable (KERNEL32.@)
+ */
+UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, void *buffer, DWORD size)
+{
+    FIXME("(%08x %08x %p %d): semi-stub\n", provider, id, buffer, size);
+    switch (provider)
+    {
+        case RSMB:
+        {
+#ifdef linux
+            char *bios_manufacturer, *bios_version, *bios_date;
+            size_t bios_manufacturer_size, bios_version_size, bios_date_size;
+            size_t required_size = sizeof(struct smbios_prologue);
+            BYTE string_count;
+            struct smbios_prologue *prologue;
+            struct smbios_bios *bios;
+
+            bios_manufacturer = get_smbios_string("/sys/class/dmi/id/bios_vendor", &bios_manufacturer_size);
+            bios_version = get_smbios_string("/sys/class/dmi/id/bios_version", &bios_version_size);
+            bios_date = get_smbios_string("/sys/class/dmi/id/bios_date", &bios_date_size);
+
+            required_size += sizeof(struct smbios_bios);
+            required_size += max(bios_manufacturer_size + bios_version_size + bios_date_size + 1, 2);
+
+            if (required_size > size)
+                return required_size;
+
+            prologue = (struct smbios_prologue*)buffer;
+            prologue->calling_method = 0;
+            prologue->major_version = 2;
+            prologue->minor_version = 0;
+            prologue->revision = 0;
+            prologue->length = required_size - sizeof(struct smbios_prologue);
+            buffer = (char*)buffer + sizeof(struct smbios_prologue);
+
+            string_count = 0;
+            bios = (struct smbios_bios*)buffer;
+            bios->type = 0;
+            bios->length = sizeof(struct smbios_bios);
+            bios->handle = 0;
+            bios->manufacturer = bios_manufacturer ? ++string_count : 0;
+            bios->version = bios_version ? ++string_count : 0;
+            bios->start = 0;
+            bios->date = bios_date ? ++string_count : 0;
+            bios->size = 0;
+            bios->characteristics = 0x4; /* not supported */
+            buffer = (char*)buffer + sizeof(struct smbios_bios);
+
+            if (string_count)
+            {
+                copy_smbios_string(&buffer, bios_manufacturer, bios_manufacturer_size);
+                copy_smbios_string(&buffer, bios_version, bios_version_size);
+                copy_smbios_string(&buffer, bios_date, bios_date_size);
+                memset(buffer, 0, 1);
+            }
+            else
+            {
+                memset(buffer, 0, 2);
+            }
+
+            free(bios_manufacturer);
+            free(bios_version);
+            free(bios_date);
+
+            return required_size;
+#endif
+        }
+    }
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 0;
+}
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index ff56e9a692..6adf08d257 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -4126,16 +4126,6 @@ HRESULT WINAPI UnregisterApplicationRestart(void)
     return S_OK;
 }
 
-/***********************************************************************
- *           GetSystemFirmwareTable       (KERNEL32.@)
- */
-UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD size)
-{
-    FIXME("(%d %d %p %d):stub\n", provider, id, buffer, size);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return 0;
-}
-
 struct proc_thread_attr
 {
     DWORD_PTR attr;
-- 
2.17.1




More information about the wine-devel mailing list