Commit 2868881c authored by Brendan Shanks's avatar Brendan Shanks Committed by Alexandre Julliard

ntdll: Factor out SMBIOS table creation.

parent 7c4941d0
......@@ -166,6 +166,60 @@ struct smbios_boot_info
#include "poppack.h"
struct smbios_bios_args
{
const char *vendor;
size_t vendor_len;
const char *version;
size_t version_len;
const char *date;
size_t date_len;
};
struct smbios_system_args
{
const char *vendor;
size_t vendor_len;
const char *product;
size_t product_len;
const char *version;
size_t version_len;
const char *serial;
size_t serial_len;
GUID uuid;
const char *sku;
size_t sku_len;
const char *family;
size_t family_len;
};
struct smbios_board_args
{
const char *vendor;
size_t vendor_len;
const char *product;
size_t product_len;
const char *version;
size_t version_len;
const char *serial;
size_t serial_len;
const char *asset_tag;
size_t asset_tag_len;
};
struct smbios_chassis_args
{
const char *vendor;
size_t vendor_len;
BYTE type;
const char *version;
size_t version_len;
const char *serial;
size_t serial_len;
const char *asset_tag;
size_t asset_tag_len;
};
/* Firmware table providers */
#define ACPI 0x41435049
#define FIRM 0x4649524D
......@@ -1264,85 +1318,20 @@ static NTSTATUS create_cpuset_info(SYSTEM_CPU_SET_INFORMATION *info)
#ifdef linux
static void copy_smbios_string( char **buffer, char *s, size_t len )
static void copy_smbios_string( char **buffer, const char *s, size_t len )
{
if (!len) return;
memcpy(*buffer, s, len + 1);
*buffer += len + 1;
}
static size_t get_smbios_string( const char *path, char *str, size_t size )
static NTSTATUS create_smbios_tables( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULONG available_len,
ULONG *required_len,
const struct smbios_bios_args *bios_args,
const struct smbios_system_args *system_args,
const struct smbios_board_args *board_args,
const struct smbios_chassis_args *chassis_args )
{
FILE *file;
size_t len;
if (!(file = fopen(path, "r"))) return 0;
len = fread( str, 1, size - 1, file );
fclose( file );
if (len >= 1 && str[len - 1] == '\n') len--;
str[len] = 0;
return len;
}
static void get_system_uuid( GUID *uuid )
{
static const unsigned char hex[] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
0,10,11,12,13,14,15 /* 0x60 */
};
int fd;
memset( uuid, 0xff, sizeof(*uuid) );
if ((fd = open( "/var/lib/dbus/machine-id", O_RDONLY )) != -1)
{
unsigned char buf[32], *p = buf;
if (read( fd, buf, sizeof(buf) ) == sizeof(buf))
{
uuid->Data1 = hex[p[6]] << 28 | hex[p[7]] << 24 | hex[p[4]] << 20 | hex[p[5]] << 16 |
hex[p[2]] << 12 | hex[p[3]] << 8 | hex[p[0]] << 4 | hex[p[1]];
uuid->Data2 = hex[p[10]] << 12 | hex[p[11]] << 8 | hex[p[8]] << 4 | hex[p[9]];
uuid->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[12]] << 4 | hex[p[13]];
uuid->Data4[0] = hex[p[16]] << 4 | hex[p[17]];
uuid->Data4[1] = hex[p[18]] << 4 | hex[p[19]];
uuid->Data4[2] = hex[p[20]] << 4 | hex[p[21]];
uuid->Data4[3] = hex[p[22]] << 4 | hex[p[23]];
uuid->Data4[4] = hex[p[24]] << 4 | hex[p[25]];
uuid->Data4[5] = hex[p[26]] << 4 | hex[p[27]];
uuid->Data4[6] = hex[p[28]] << 4 | hex[p[29]];
uuid->Data4[7] = hex[p[30]] << 4 | hex[p[31]];
}
close( fd );
}
}
static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULONG available_len,
ULONG *required_len )
{
switch (sfti->ProviderSignature)
{
case RSMB:
{
char bios_vendor[128], bios_version[128], bios_date[128];
size_t bios_vendor_len, bios_version_len, bios_date_len;
char system_vendor[128], system_product[128], system_version[128], system_serial[128];
size_t system_vendor_len, system_product_len, system_version_len, system_serial_len;
char system_sku[128], system_family[128];
size_t system_sku_len, system_family_len;
char board_vendor[128], board_product[128], board_version[128], board_serial[128], board_asset_tag[128];
size_t board_vendor_len, board_product_len, board_version_len, board_serial_len, board_asset_tag_len;
char chassis_vendor[128], chassis_version[128], chassis_serial[128], chassis_asset_tag[128];
char chassis_type[11] = "2"; /* unknown */
size_t chassis_vendor_len, chassis_version_len, chassis_serial_len, chassis_asset_tag_len;
char *buffer = (char*)sfti->TableBuffer;
BYTE string_count;
BYTE handle_count = 0;
......@@ -1354,45 +1343,23 @@ static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULON
struct smbios_boot_info *boot_info;
struct smbios_header *end_of_table;
#define S(s) s, sizeof(s)
bios_vendor_len = get_smbios_string("/sys/class/dmi/id/bios_vendor", S(bios_vendor));
bios_version_len = get_smbios_string("/sys/class/dmi/id/bios_version", S(bios_version));
bios_date_len = get_smbios_string("/sys/class/dmi/id/bios_date", S(bios_date));
system_vendor_len = get_smbios_string("/sys/class/dmi/id/sys_vendor", S(system_vendor));
system_product_len = get_smbios_string("/sys/class/dmi/id/product_name", S(system_product));
system_version_len = get_smbios_string("/sys/class/dmi/id/product_version", S(system_version));
system_serial_len = get_smbios_string("/sys/class/dmi/id/product_serial", S(system_serial));
system_sku_len = get_smbios_string("/sys/class/dmi/id/product_sku", S(system_sku));
system_family_len = get_smbios_string("/sys/class/dmi/id/product_family", S(system_family));
board_vendor_len = get_smbios_string("/sys/class/dmi/id/board_vendor", S(board_vendor));
board_product_len = get_smbios_string("/sys/class/dmi/id/board_name", S(board_product));
board_version_len = get_smbios_string("/sys/class/dmi/id/board_version", S(board_version));
board_serial_len = get_smbios_string("/sys/class/dmi/id/board_serial", S(board_serial));
board_asset_tag_len = get_smbios_string("/sys/class/dmi/id/board_asset_tag", S(board_asset_tag));
chassis_vendor_len = get_smbios_string("/sys/class/dmi/id/chassis_vendor", S(chassis_vendor));
chassis_version_len = get_smbios_string("/sys/class/dmi/id/chassis_version", S(chassis_version));
chassis_serial_len = get_smbios_string("/sys/class/dmi/id/chassis_serial", S(chassis_serial));
chassis_asset_tag_len = get_smbios_string("/sys/class/dmi/id/chassis_tag", S(chassis_asset_tag));
get_smbios_string("/sys/class/dmi/id/chassis_type", S(chassis_type));
#undef S
*required_len = sizeof(struct smbios_prologue);
#define L(l) (l + (l ? 1 : 0))
*required_len += sizeof(struct smbios_bios);
*required_len += max(L(bios_vendor_len) + L(bios_version_len) + L(bios_date_len) + 1, 2);
*required_len += max(L(bios_args->vendor_len) + L(bios_args->version_len) + L(bios_args->date_len) + 1, 2);
*required_len += sizeof(struct smbios_system);
*required_len += max(L(system_vendor_len) + L(system_product_len) + L(system_version_len) +
L(system_serial_len) + L(system_sku_len) + L(system_family_len) + 1, 2);
*required_len += max(L(system_args->vendor_len) + L(system_args->product_len) + L(system_args->version_len) +
L(system_args->serial_len) + L(system_args->sku_len) + L(system_args->family_len) + 1, 2);
*required_len += sizeof(struct smbios_board);
*required_len += max(L(board_vendor_len) + L(board_product_len) + L(board_version_len) +
L(board_serial_len) + L(board_asset_tag_len) + 1, 2);
*required_len += max(L(board_args->vendor_len) + L(board_args->product_len) + L(board_args->version_len) +
L(board_args->serial_len) + L(board_args->asset_tag_len) + 1, 2);
*required_len += sizeof(struct smbios_chassis);
*required_len += max(L(chassis_vendor_len) + L(chassis_version_len) + L(chassis_serial_len) +
L(chassis_asset_tag_len) + 1, 2);
*required_len += max(L(chassis_args->vendor_len) + L(chassis_args->version_len) + L(chassis_args->serial_len) +
L(chassis_args->asset_tag_len) + 1, 2);
*required_len += sizeof(struct smbios_boot_info);
*required_len += 2;
......@@ -1421,10 +1388,10 @@ static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULON
bios->hdr.type = 0;
bios->hdr.length = sizeof(struct smbios_bios);
bios->hdr.handle = handle_count++;
bios->vendor = bios_vendor_len ? ++string_count : 0;
bios->version = bios_version_len ? ++string_count : 0;
bios->vendor = bios_args->vendor_len ? ++string_count : 0;
bios->version = bios_args->version_len ? ++string_count : 0;
bios->start = 0;
bios->date = bios_date_len ? ++string_count : 0;
bios->date = bios_args->date_len ? ++string_count : 0;
bios->size = 0;
bios->characteristics = 0x4; /* not supported */
bios->characteristics_ext[0] = 0;
......@@ -1435,9 +1402,9 @@ static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULON
bios->ec_firmware_minor_release = 0xFF; /* not supported */
buffer += sizeof(struct smbios_bios);
copy_smbios_string(&buffer, bios_vendor, bios_vendor_len);
copy_smbios_string(&buffer, bios_version, bios_version_len);
copy_smbios_string(&buffer, bios_date, bios_date_len);
copy_smbios_string(&buffer, bios_args->vendor, bios_args->vendor_len);
copy_smbios_string(&buffer, bios_args->version, bios_args->version_len);
copy_smbios_string(&buffer, bios_args->date, bios_args->date_len);
if (!string_count) *buffer++ = 0;
*buffer++ = 0;
......@@ -1446,22 +1413,22 @@ static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULON
system->hdr.type = 1;
system->hdr.length = sizeof(struct smbios_system);
system->hdr.handle = handle_count++;
system->vendor = system_vendor_len ? ++string_count : 0;
system->product = system_product_len ? ++string_count : 0;
system->version = system_version_len ? ++string_count : 0;
system->serial = system_serial_len ? ++string_count : 0;
get_system_uuid( (GUID *)system->uuid );
system->vendor = system_args->vendor_len ? ++string_count : 0;
system->product = system_args->product_len ? ++string_count : 0;
system->version = system_args->version_len ? ++string_count : 0;
system->serial = system_args->serial_len ? ++string_count : 0;
memcpy( system->uuid, &system_args->uuid, sizeof(GUID) );
system->wake_up_type = 0x02; /* unknown */
system->sku_number = system_sku_len ? ++string_count : 0;
system->family = system_family_len ? ++string_count : 0;
system->sku_number = system_args->sku_len ? ++string_count : 0;
system->family = system_args->family_len ? ++string_count : 0;
buffer += sizeof(struct smbios_system);
copy_smbios_string(&buffer, system_vendor, system_vendor_len);
copy_smbios_string(&buffer, system_product, system_product_len);
copy_smbios_string(&buffer, system_version, system_version_len);
copy_smbios_string(&buffer, system_serial, system_serial_len);
copy_smbios_string(&buffer, system_sku, system_sku_len);
copy_smbios_string(&buffer, system_family, system_family_len);
copy_smbios_string(&buffer, system_args->vendor, system_args->vendor_len);
copy_smbios_string(&buffer, system_args->product, system_args->product_len);
copy_smbios_string(&buffer, system_args->version, system_args->version_len);
copy_smbios_string(&buffer, system_args->serial, system_args->serial_len);
copy_smbios_string(&buffer, system_args->sku, system_args->sku_len);
copy_smbios_string(&buffer, system_args->family, system_args->family_len);
if (!string_count) *buffer++ = 0;
*buffer++ = 0;
......@@ -1470,11 +1437,11 @@ static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULON
chassis->hdr.type = 3;
chassis->hdr.length = sizeof(struct smbios_chassis);
chassis->hdr.handle = handle_count++;
chassis->vendor = chassis_vendor_len ? ++string_count : 0;
chassis->type = atoi(chassis_type);
chassis->version = chassis_version_len ? ++string_count : 0;
chassis->serial = chassis_serial_len ? ++string_count : 0;
chassis->asset_tag = chassis_asset_tag_len ? ++string_count : 0;
chassis->vendor = chassis_args->vendor_len ? ++string_count : 0;
chassis->type = chassis_args->type;
chassis->version = chassis_args->version_len ? ++string_count : 0;
chassis->serial = chassis_args->serial_len ? ++string_count : 0;
chassis->asset_tag = chassis_args->asset_tag_len ? ++string_count : 0;
chassis->boot_state = 0x02; /* unknown */
chassis->power_supply_state = 0x02; /* unknown */
chassis->thermal_state = 0x02; /* unknown */
......@@ -1486,10 +1453,10 @@ static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULON
chassis->contained_element_rec_length = 3;
buffer += sizeof(struct smbios_chassis);
copy_smbios_string(&buffer, chassis_vendor, chassis_vendor_len);
copy_smbios_string(&buffer, chassis_version, chassis_version_len);
copy_smbios_string(&buffer, chassis_serial, chassis_serial_len);
copy_smbios_string(&buffer, chassis_asset_tag, chassis_asset_tag_len);
copy_smbios_string(&buffer, chassis_args->vendor, chassis_args->vendor_len);
copy_smbios_string(&buffer, chassis_args->version, chassis_args->version_len);
copy_smbios_string(&buffer, chassis_args->serial, chassis_args->serial_len);
copy_smbios_string(&buffer, chassis_args->asset_tag, chassis_args->asset_tag_len);
if (!string_count) *buffer++ = 0;
*buffer++ = 0;
......@@ -1498,11 +1465,11 @@ static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULON
board->hdr.type = 2;
board->hdr.length = sizeof(struct smbios_board);
board->hdr.handle = handle_count++;
board->vendor = board_vendor_len ? ++string_count : 0;
board->product = board_product_len ? ++string_count : 0;
board->version = board_version_len ? ++string_count : 0;
board->serial = board_serial_len ? ++string_count : 0;
board->asset_tag = board_asset_tag_len ? ++string_count : 0;
board->vendor = board_args->vendor_len ? ++string_count : 0;
board->product = board_args->product_len ? ++string_count : 0;
board->version = board_args->version_len ? ++string_count : 0;
board->serial = board_args->serial_len ? ++string_count : 0;
board->asset_tag = board_args->asset_tag_len ? ++string_count : 0;
board->feature_flags = 0x5; /* hosting board, removable */
board->location = 0;
board->chassis_handle = chassis->hdr.handle;
......@@ -1510,11 +1477,11 @@ static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULON
board->num_contained_handles = 0;
buffer += sizeof(struct smbios_board);
copy_smbios_string(&buffer, board_vendor, board_vendor_len);
copy_smbios_string(&buffer, board_product, board_product_len);
copy_smbios_string(&buffer, board_version, board_version_len);
copy_smbios_string(&buffer, board_serial, board_serial_len);
copy_smbios_string(&buffer, board_asset_tag, board_asset_tag_len);
copy_smbios_string(&buffer, board_args->vendor, board_args->vendor_len);
copy_smbios_string(&buffer, board_args->product, board_args->product_len);
copy_smbios_string(&buffer, board_args->version, board_args->version_len);
copy_smbios_string(&buffer, board_args->serial, board_args->serial_len);
copy_smbios_string(&buffer, board_args->asset_tag, board_args->asset_tag_len);
if (!string_count) *buffer++ = 0;
*buffer++ = 0;
......@@ -1537,6 +1504,127 @@ static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULON
*buffer++ = 0;
return STATUS_SUCCESS;
}
static size_t get_smbios_string( const char *path, char *str, size_t size )
{
FILE *file;
size_t len;
if (!(file = fopen(path, "r"))) return 0;
len = fread( str, 1, size - 1, file );
fclose( file );
if (len >= 1 && str[len - 1] == '\n') len--;
str[len] = 0;
return len;
}
static void get_system_uuid( GUID *uuid )
{
static const unsigned char hex[] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
0,10,11,12,13,14,15 /* 0x60 */
};
int fd;
memset( uuid, 0xff, sizeof(*uuid) );
if ((fd = open( "/var/lib/dbus/machine-id", O_RDONLY )) != -1)
{
unsigned char buf[32], *p = buf;
if (read( fd, buf, sizeof(buf) ) == sizeof(buf))
{
uuid->Data1 = hex[p[6]] << 28 | hex[p[7]] << 24 | hex[p[4]] << 20 | hex[p[5]] << 16 |
hex[p[2]] << 12 | hex[p[3]] << 8 | hex[p[0]] << 4 | hex[p[1]];
uuid->Data2 = hex[p[10]] << 12 | hex[p[11]] << 8 | hex[p[8]] << 4 | hex[p[9]];
uuid->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[12]] << 4 | hex[p[13]];
uuid->Data4[0] = hex[p[16]] << 4 | hex[p[17]];
uuid->Data4[1] = hex[p[18]] << 4 | hex[p[19]];
uuid->Data4[2] = hex[p[20]] << 4 | hex[p[21]];
uuid->Data4[3] = hex[p[22]] << 4 | hex[p[23]];
uuid->Data4[4] = hex[p[24]] << 4 | hex[p[25]];
uuid->Data4[5] = hex[p[26]] << 4 | hex[p[27]];
uuid->Data4[6] = hex[p[28]] << 4 | hex[p[29]];
uuid->Data4[7] = hex[p[30]] << 4 | hex[p[31]];
}
close( fd );
}
}
static NTSTATUS get_firmware_info( SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, ULONG available_len,
ULONG *required_len )
{
switch (sfti->ProviderSignature)
{
case RSMB:
{
char bios_vendor[128], bios_version[128], bios_date[128];
struct smbios_bios_args bios_args;
char system_vendor[128], system_product[128], system_version[128], system_serial[128];
char system_sku[128], system_family[128];
struct smbios_system_args system_args;
char board_vendor[128], board_product[128], board_version[128], board_serial[128], board_asset_tag[128];
struct smbios_board_args board_args;
char chassis_vendor[128], chassis_version[128], chassis_serial[128], chassis_asset_tag[128];
char chassis_type[11] = "2"; /* unknown */
struct smbios_chassis_args chassis_args;
#define S(s) s, sizeof(s)
bios_args.vendor_len = get_smbios_string("/sys/class/dmi/id/bios_vendor", S(bios_vendor));
bios_args.vendor = bios_vendor;
bios_args.version_len = get_smbios_string("/sys/class/dmi/id/bios_version", S(bios_version));
bios_args.version = bios_version;
bios_args.date_len = get_smbios_string("/sys/class/dmi/id/bios_date", S(bios_date));
bios_args.date = bios_date;
system_args.vendor_len = get_smbios_string("/sys/class/dmi/id/sys_vendor", S(system_vendor));
system_args.vendor = system_vendor;
system_args.product_len = get_smbios_string("/sys/class/dmi/id/product_name", S(system_product));
system_args.product = system_product;
system_args.version_len = get_smbios_string("/sys/class/dmi/id/product_version", S(system_version));
system_args.version = system_version;
system_args.serial_len = get_smbios_string("/sys/class/dmi/id/product_serial", S(system_serial));
system_args.serial = system_serial;
get_system_uuid(&system_args.uuid);
system_args.sku_len = get_smbios_string("/sys/class/dmi/id/product_sku", S(system_sku));
system_args.sku = system_sku;
system_args.family_len = get_smbios_string("/sys/class/dmi/id/product_family", S(system_family));
system_args.family = system_family;
board_args.vendor_len = get_smbios_string("/sys/class/dmi/id/board_vendor", S(board_vendor));
board_args.vendor = board_vendor;
board_args.product_len = get_smbios_string("/sys/class/dmi/id/board_name", S(board_product));
board_args.product = board_product;
board_args.version_len = get_smbios_string("/sys/class/dmi/id/board_version", S(board_version));
board_args.version = board_version;
board_args.serial_len = get_smbios_string("/sys/class/dmi/id/board_serial", S(board_serial));
board_args.serial = board_serial;
board_args.asset_tag_len = get_smbios_string("/sys/class/dmi/id/board_asset_tag", S(board_asset_tag));
board_args.asset_tag = board_asset_tag;
chassis_args.vendor_len = get_smbios_string("/sys/class/dmi/id/chassis_vendor", S(chassis_vendor));
chassis_args.vendor = chassis_vendor;
get_smbios_string("/sys/class/dmi/id/chassis_type", S(chassis_type));
chassis_args.type = atoi(chassis_type);
chassis_args.version_len = get_smbios_string("/sys/class/dmi/id/chassis_version", S(chassis_version));
chassis_args.version = chassis_version;
chassis_args.serial_len = get_smbios_string("/sys/class/dmi/id/chassis_serial", S(chassis_serial));
chassis_args.serial = chassis_serial;
chassis_args.asset_tag_len = get_smbios_string("/sys/class/dmi/id/chassis_tag", S(chassis_asset_tag));
chassis_args.asset_tag = chassis_asset_tag;
#undef S
return create_smbios_tables( sfti, available_len, required_len,
&bios_args, &system_args, &board_args, &chassis_args );
}
default:
FIXME("info_class SYSTEM_FIRMWARE_TABLE_INFORMATION provider %08x\n", sfti->ProviderSignature);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment