#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <uuid/uuid.h>
#include "lib/checksum.h"
#include "lib/lib_smbios.h"
#include "lib/vpd.h"
#include "lib/vpd_tables.h"
int vpd_sizeof_strings(void *table)
{
uint8_t *p;
struct vpd_header *header = table;
size_t size = 0, offset = 0;
unsigned char cmp[2] = { '\0', '\0' };
uint8_t found = 0;
for (p = table + header->length - 1; p; p++, offset++) {
if (!memcmp(p, cmp, 2)) {
found = 1;
break;
}
}
if (found)
size = offset;
return size;
}
struct vpd_entry *vpd_create_eps(uint16_t structure_table_len,
uint16_t num_structures,
uint32_t eps_base) {
struct vpd_entry *eps = NULL;
eps = malloc(sizeof(struct vpd_entry));
if (!eps)
return NULL;
memset(eps, 0, sizeof(*eps));
memcpy(eps->anchor_string, VPD_ENTRY_MAGIC, 4);
eps->entry_length = sizeof(struct vpd_entry);
eps->major_ver = CONFIG_EPS_VPD_MAJOR_VERSION;
eps->minor_ver = CONFIG_EPS_VPD_MINOR_VERSION;
eps->entry_rev = 0;
memcpy(eps->inter_anchor_string, "_DMI_", 5);
eps->table_length = structure_table_len;
eps->table_address = eps_base + eps->entry_length;
#ifdef CONFIG_EPS_NUM_STRUCTURES
eps->table_entry_count = CONFIG_EPS_NUM_STRUCTURES;
#else
eps->table_entry_count = num_structures;
#endif
eps->bcd_revision = (CONFIG_EPS_VPD_MAJOR_VERSION << 4) |
CONFIG_EPS_VPD_MINOR_VERSION;
eps->inter_anchor_cksum = zero8_csum(&eps->inter_anchor_string[0], 0xf);
eps->entry_cksum = zero8_csum((uint8_t *)eps, eps->entry_length);
return eps;
}
int vpd_append_type127(uint16_t handle, uint8_t **buf, size_t len)
{
struct vpd_table_eot *data;
size_t total_len, struct_len;
struct_len = sizeof(struct vpd_table_eot) + 2;
total_len = len + struct_len;
*buf = realloc(*buf, total_len);
data = (struct vpd_table_eot *)(*buf + len);
data->header.type = 127;
data->header.length = sizeof(*data);
data->header.handle = handle;
memset(*buf + len + sizeof(*data), 0, 2);
return total_len;
}
int vpd_append_type241(uint16_t handle, uint8_t **buf,
size_t len, const char *uuid, uint32_t offset,
uint32_t size, const char *vendor,
const char *desc, const char *variant)
{
struct vpd_header *header;
struct vpd_table_binary_blob_pointer *data;
char *string_ptr;
size_t struct_len, total_len;
int string_index = 1;
struct_len = sizeof(struct vpd_header) +
sizeof(struct vpd_table_binary_blob_pointer);
if (vendor)
struct_len += strlen(vendor) + 1;
if (desc)
struct_len += strlen(desc) + 1;
if (variant)
struct_len += strlen(variant) + 1;
struct_len += 1;
total_len = len + struct_len;
*buf = realloc(*buf, total_len);
memset(*buf + len, 0, struct_len);
header = (struct vpd_header *)(*buf + len);
data = (struct vpd_table_binary_blob_pointer *)
((uint8_t *)header + sizeof(*header));
string_ptr = (char *)data + sizeof(*data);
header->type = VPD_TYPE_BINARY_BLOB_POINTER;
header->length = sizeof(*header) + sizeof(*data);
header->handle = handle;
data->struct_major_version = 1;
data->struct_minor_version = 0;
if (vendor) {
data->vendor = string_index;
string_index++;
sprintf(string_ptr, "%s%c", vendor, '\0');
string_ptr += strlen(vendor) + 1;
}
if (desc) {
data->description = string_index;
string_index++;
sprintf(string_ptr, "%s%c", desc, '\0');
string_ptr += strlen(desc) + 1;
}
data->major_version = 2;
data->minor_version = 0;
if (variant) {
data->variant = string_index;
string_index++;
sprintf(string_ptr, "%s%c", variant, '\0');
string_ptr += strlen(variant) + 1;
}
memset(&data->reserved[0], 0, 5);
if (uuid_parse(uuid, &data->uuid[0]) < 0) {
fprintf(stderr, "invalid UUID \"%s\" specified\n", uuid);
goto vpd_create_type241_fail;
}
data->offset = offset;
data->size = size;
return total_len;
vpd_create_type241_fail:
return -1;
}
int vpd_type241_size(struct vpd_header *header) {
uint8_t *ptr = (uint8_t*)header;
char *str = (char*)ptr + header->length;
int length = sizeof(struct vpd_header) +
sizeof(struct vpd_table_binary_blob_pointer);
int i;
if (header->type != VPD_TYPE_BINARY_BLOB_POINTER) return -1;
for (i = 0; i < 3; ++i) {
int len = strlen(str) + 1;
length += len;
str += len;
}
if (ptr[length] == 0) length++;
return length;
}
void vpd_free_table(void *data)
{
uint8_t *foo = data;
free(foo);
}