smbios: add module to match SMBios vendor and product
Change-Id: Ib7848da1c22c42a1a9030891159f4e852c6c1ecd Reviewed-on: https://review.haiku-os.org/c/haiku/+/2503 Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
parent
bd3b700484
commit
97f2b91169
23
headers/private/drivers/smbios.h
Normal file
23
headers/private/drivers/smbios.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2020, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _SMBIOS_MODULE_H_
|
||||
#define _SMBIOS_MODULE_H_
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
#include <module.h>
|
||||
|
||||
|
||||
typedef struct smbios_module_info {
|
||||
module_info info;
|
||||
|
||||
bool (*match_vendor_product)(const char* vendor, const char* product);
|
||||
} smbios_module_info;
|
||||
|
||||
|
||||
#define SMBIOS_MODULE_NAME "generic/smbios/driver_v1"
|
||||
|
||||
|
||||
#endif // _SMBIOS_MODULE_H_
|
@ -6,4 +6,5 @@ SubInclude HAIKU_TOP src add-ons kernel generic dpc ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic locked_pool ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic mpu401 ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic scsi_periph ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic smbios ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic tty ;
|
||||
|
8
src/add-ons/kernel/generic/smbios/Jamfile
Normal file
8
src/add-ons/kernel/generic/smbios/Jamfile
Normal file
@ -0,0 +1,8 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel generic smbios ;
|
||||
|
||||
UsePrivateHeaders drivers ;
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
KernelAddon smbios :
|
||||
smbios.cpp
|
||||
;
|
257
src/add-ons/kernel/generic/smbios/smbios.cpp
Normal file
257
src/add-ons/kernel/generic/smbios/smbios.cpp
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright 2020, Jérôme Duval, jerome.duval@gmail.com.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
|
||||
#include "smbios.h"
|
||||
|
||||
#include <device_manager.h>
|
||||
#include <KernelExport.h>
|
||||
#include <module.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
|
||||
#define TRACE_SMBIOS
|
||||
#ifdef TRACE_SMBIOS
|
||||
# define TRACE(x...) dprintf (x)
|
||||
#else
|
||||
# define TRACE(x...) ;
|
||||
#endif
|
||||
|
||||
|
||||
static device_manager_info* gDeviceManager;
|
||||
static char* sHardwareVendor = NULL;
|
||||
static char* sHardwareProduct = NULL;
|
||||
|
||||
struct smbios {
|
||||
uint32 anchor_string;
|
||||
uint8 entry_point_checksum;
|
||||
uint8 entry_point_length;
|
||||
struct {
|
||||
uint8 major;
|
||||
uint8 minor;
|
||||
} version;
|
||||
uint16 maximum_size;
|
||||
uint8 entry_point_revision;
|
||||
uint8 formatted_area[5];
|
||||
|
||||
uint8 dmi_anchor_string[5];
|
||||
uint8 intermediate_checksum;
|
||||
uint16 structure_table_size;
|
||||
uint32 structure_table;
|
||||
uint16 num_structures;
|
||||
uint8 bcd_revision;
|
||||
} _PACKED;
|
||||
|
||||
|
||||
struct smbios3 {
|
||||
uint8 anchor_string[5];
|
||||
uint8 entry_point_checksum;
|
||||
uint8 entry_point_length;
|
||||
struct {
|
||||
uint8 major;
|
||||
uint8 minor;
|
||||
uint8 doc;
|
||||
} version;
|
||||
uint8 entry_point_revision;
|
||||
uint8 reserved;
|
||||
uint32 structure_table_size;
|
||||
uint64 structure_table;
|
||||
} _PACKED;
|
||||
|
||||
|
||||
struct smbios_structure_header {
|
||||
uint8 type;
|
||||
uint8 length;
|
||||
uint16 handle;
|
||||
} _PACKED;
|
||||
|
||||
|
||||
#define SMBIOS "_SM_"
|
||||
#define SMBIOS3 "_SM3_"
|
||||
|
||||
enum {
|
||||
SMBIOS_TYPE_BIOS = 0,
|
||||
SMBIOS_TYPE_SYSTEM,
|
||||
};
|
||||
|
||||
|
||||
struct smbios_system {
|
||||
struct smbios_structure_header header;
|
||||
uint8 manufacturer;
|
||||
uint8 product_name;
|
||||
uint8 version;
|
||||
uint8 serial_number;
|
||||
uint8 uuid[16];
|
||||
uint8 wakeup_type;
|
||||
uint8 sku_number;
|
||||
uint8 family;
|
||||
} _PACKED;
|
||||
|
||||
|
||||
static bool
|
||||
smbios_match_vendor_product(const char* vendor, const char* product)
|
||||
{
|
||||
if (vendor == NULL && product == NULL)
|
||||
return false;
|
||||
|
||||
bool match = true;
|
||||
if (vendor != NULL && sHardwareVendor != NULL)
|
||||
match = strcmp(vendor, sHardwareVendor) == 0;
|
||||
if (match && product != NULL && sHardwareProduct != NULL)
|
||||
match = strcmp(product, sHardwareProduct) == 0;
|
||||
return match;
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
smbios_get_string(struct smbios_structure_header* table, uint8* tableEnd,
|
||||
uint8 index)
|
||||
{
|
||||
uint8* addr = (uint8*)table + table->length;
|
||||
uint8 i = 1;
|
||||
for (; addr < tableEnd && i < index && *addr != 0; i++) {
|
||||
while (*addr != 0 && addr < tableEnd)
|
||||
addr++;
|
||||
addr++;
|
||||
}
|
||||
if (i == index)
|
||||
return (const char*)addr;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
smbios_scan()
|
||||
{
|
||||
TRACE("smbios_scan\n");
|
||||
static bool scanDone = false;
|
||||
if (scanDone)
|
||||
return;
|
||||
|
||||
// map SMBIOS area 0xf0000 - 0xfffff
|
||||
addr_t smBiosBase;
|
||||
area_id smbiosArea = map_physical_memory("pc bios", 0xf0000, 0x10000,
|
||||
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&smBiosBase);
|
||||
if (smbiosArea < 0)
|
||||
return;
|
||||
|
||||
struct smbios *smbios = NULL;
|
||||
struct smbios3 *smbios3 = NULL;
|
||||
for (addr_t offset = 0; offset <= 0xffe0; offset += 0x10) {
|
||||
void* p = (void*)(smBiosBase + offset);
|
||||
if (memcmp(p, SMBIOS3, 5) == 0) {
|
||||
smbios3 = (struct smbios3 *)p;
|
||||
break;
|
||||
} else if (memcmp(p, SMBIOS, 4) == 0) {
|
||||
smbios = (struct smbios *)p;
|
||||
}
|
||||
}
|
||||
|
||||
phys_addr_t tablePhysAddr = 0;
|
||||
size_t tablePhysLength = 0;
|
||||
void* table;
|
||||
status_t status;
|
||||
uint8* tableEnd;
|
||||
|
||||
if (smbios != NULL) {
|
||||
tablePhysAddr = smbios->structure_table;
|
||||
tablePhysLength = smbios->structure_table_size;
|
||||
} else if (smbios3 != NULL) {
|
||||
tablePhysAddr = smbios3->structure_table;
|
||||
tablePhysLength = smbios3->structure_table_size;
|
||||
}
|
||||
|
||||
if (tablePhysAddr == 0)
|
||||
goto err;
|
||||
|
||||
table = malloc(tablePhysLength);
|
||||
if (table == NULL)
|
||||
goto err;
|
||||
status = vm_memcpy_from_physical(table, tablePhysAddr,
|
||||
tablePhysLength, false);
|
||||
if (status != B_OK)
|
||||
goto err;
|
||||
|
||||
tableEnd = (uint8*)table + tablePhysLength;
|
||||
for (uint8* addr = (uint8*)table;
|
||||
(addr + sizeof(struct smbios_structure_header)) < tableEnd;) {
|
||||
struct smbios_structure_header* table
|
||||
= (struct smbios_structure_header*)addr;
|
||||
|
||||
if (table->type == SMBIOS_TYPE_SYSTEM) {
|
||||
struct smbios_system *system = (struct smbios_system*)table;
|
||||
TRACE("found System Information at %p\n", table);
|
||||
TRACE("found vendor %u product %u\n", system->manufacturer,
|
||||
system->product_name);
|
||||
const char* vendor = smbios_get_string(table, tableEnd,
|
||||
system->manufacturer);
|
||||
const char* product = smbios_get_string(table, tableEnd,
|
||||
system->product_name);
|
||||
if (vendor != NULL)
|
||||
sHardwareVendor = strdup(vendor);
|
||||
if (product != NULL)
|
||||
sHardwareProduct = strdup(product);
|
||||
break;
|
||||
}
|
||||
addr += table->length;
|
||||
for (; addr + 1 < tableEnd; addr++) {
|
||||
if (*addr == 0 && *(addr + 1) == 0)
|
||||
break;
|
||||
}
|
||||
addr += 2;
|
||||
}
|
||||
|
||||
scanDone = true;
|
||||
TRACE("smbios_scan found vendor %s product %s\n", sHardwareVendor,
|
||||
sHardwareProduct);
|
||||
err:
|
||||
delete_area(smbiosArea);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
smbios_scan();
|
||||
return B_OK;
|
||||
case B_MODULE_UNINIT:
|
||||
free(sHardwareVendor);
|
||||
free(sHardwareProduct);
|
||||
return B_OK;
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
{B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager},
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
static smbios_module_info sSMBIOSModule = {
|
||||
{
|
||||
SMBIOS_MODULE_NAME,
|
||||
B_KEEP_LOADED,
|
||||
std_ops
|
||||
},
|
||||
|
||||
smbios_match_vendor_product,
|
||||
};
|
||||
|
||||
|
||||
module_info *modules[] = {
|
||||
(module_info*)&sSMBIOSModule,
|
||||
NULL
|
||||
};
|
Loading…
Reference in New Issue
Block a user