[PATCH v2 1/4] kernel32: Return BIOS info from GetSystemFirmwareTable on Linux
Alex Henrie
alexhenrie24 at gmail.com
Mon May 28 23:05:26 CDT 2018
Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
dlls/kernel32/process.c | 130 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 129 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index ff56e9a692..6797475438 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -81,6 +81,30 @@ typedef struct
DWORD dwReserved;
} LOADPARMS32;
+#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"
+
static DWORD shutdown_flags = 0;
static DWORD shutdown_priority = 0x280;
static BOOL is_wow64;
@@ -102,6 +126,11 @@ const WCHAR *DIR_SysWow64 = NULL;
#define PDB32_FILE_APIS_OEM 0x0040 /* File APIs are OEM */
#define PDB32_WIN32S_PROC 0x8000 /* Win32s process */
+/* Firmware table providers */
+#define ACPI 0x41435049
+#define FIRM 0x4649524D
+#define RSMB 0x52534D42
+
static const WCHAR exeW[] = {'.','e','x','e',0};
static const WCHAR comW[] = {'.','c','o','m',0};
static const WCHAR batW[] = {'.','b','a','t',0};
@@ -4126,12 +4155,111 @@ HRESULT WINAPI UnregisterApplicationRestart(void)
return S_OK;
}
+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, PVOID buffer, DWORD size)
{
- FIXME("(%d %d %p %d):stub\n", provider, id, buffer, 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);
+ if (bios_manufacturer_size || bios_version_size || bios_date_size)
+ required_size += bios_manufacturer_size + bios_version_size + bios_date_size + 1;
+ else
+ required_size += 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;
}
--
2.17.0
More information about the wine-devel
mailing list