aboutsummaryrefslogtreecommitdiff
path: root/lib/smbios-parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/smbios-parser.c')
-rw-r--r--lib/smbios-parser.c152
1 files changed, 142 insertions, 10 deletions
diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
index 34203f952c..2b9392936b 100644
--- a/lib/smbios-parser.c
+++ b/lib/smbios-parser.c
@@ -39,10 +39,8 @@ const struct smbios_entry *smbios_entry(u64 address, u32 size)
return entry;
}
-static const struct smbios_header *next_header(const struct smbios_header *curr)
+static u8 *find_next_header(u8 *pos)
{
- u8 *pos = ((u8 *)curr) + curr->length;
-
/* search for _double_ NULL bytes */
while (!((*pos == 0) && (*(pos + 1) == 0)))
pos++;
@@ -50,13 +48,27 @@ static const struct smbios_header *next_header(const struct smbios_header *curr)
/* step behind the double NULL bytes */
pos += 2;
- return (struct smbios_header *)pos;
+ return pos;
+}
+
+static struct smbios_header *get_next_header(struct smbios_header *curr)
+{
+ u8 *pos = ((u8 *)curr) + curr->length;
+
+ return (struct smbios_header *)find_next_header(pos);
+}
+
+static const struct smbios_header *next_header(const struct smbios_header *curr)
+{
+ u8 *pos = ((u8 *)curr) + curr->length;
+
+ return (struct smbios_header *)find_next_header(pos);
}
const struct smbios_header *smbios_header(const struct smbios_entry *entry, int type)
{
const unsigned int num_header = entry->struct_count;
- const struct smbios_header *header = (struct smbios_header *)entry->struct_table_address;
+ const struct smbios_header *header = (struct smbios_header *)((uintptr_t)entry->struct_table_address);
for (unsigned int i = 0; i < num_header; i++) {
if (header->type == type)
@@ -68,8 +80,8 @@ const struct smbios_header *smbios_header(const struct smbios_entry *entry, int
return NULL;
}
-static const char *string_from_smbios_table(const struct smbios_header *header,
- int idx)
+static char *string_from_smbios_table(const struct smbios_header *header,
+ int idx)
{
unsigned int i = 1;
u8 *pos;
@@ -86,10 +98,10 @@ static const char *string_from_smbios_table(const struct smbios_header *header,
pos++;
}
- return (const char *)pos;
+ return (char *)pos;
}
-const char *smbios_string(const struct smbios_header *header, int index)
+char *smbios_string(const struct smbios_header *header, int index)
{
if (!header)
return NULL;
@@ -109,7 +121,7 @@ int smbios_update_version_full(void *smbios_tab, const char *version)
if (!hdr)
return log_msg_ret("tab", -ENOENT);
bios = (struct smbios_type0 *)hdr;
- ptr = (char *)smbios_string(hdr, bios->bios_ver);
+ ptr = smbios_string(hdr, bios->bios_ver);
if (!ptr)
return log_msg_ret("str", -ENOMEDIUM);
@@ -132,3 +144,123 @@ int smbios_update_version_full(void *smbios_tab, const char *version)
return 0;
}
+
+struct smbios_filter_param {
+ u32 offset;
+ u32 size;
+ bool is_string;
+};
+
+struct smbios_filter_table {
+ int type;
+ struct smbios_filter_param *params;
+ u32 count;
+};
+
+struct smbios_filter_param smbios_type1_filter_params[] = {
+ {offsetof(struct smbios_type1, serial_number),
+ FIELD_SIZEOF(struct smbios_type1, serial_number), true},
+ {offsetof(struct smbios_type1, uuid),
+ FIELD_SIZEOF(struct smbios_type1, uuid), false},
+ {offsetof(struct smbios_type1, wakeup_type),
+ FIELD_SIZEOF(struct smbios_type1, wakeup_type), false},
+};
+
+struct smbios_filter_param smbios_type2_filter_params[] = {
+ {offsetof(struct smbios_type2, serial_number),
+ FIELD_SIZEOF(struct smbios_type2, serial_number), true},
+ {offsetof(struct smbios_type2, chassis_location),
+ FIELD_SIZEOF(struct smbios_type2, chassis_location), false},
+};
+
+struct smbios_filter_param smbios_type3_filter_params[] = {
+ {offsetof(struct smbios_type3, serial_number),
+ FIELD_SIZEOF(struct smbios_type3, serial_number), true},
+ {offsetof(struct smbios_type3, asset_tag_number),
+ FIELD_SIZEOF(struct smbios_type3, asset_tag_number), true},
+};
+
+struct smbios_filter_param smbios_type4_filter_params[] = {
+ {offsetof(struct smbios_type4, serial_number),
+ FIELD_SIZEOF(struct smbios_type4, serial_number), true},
+ {offsetof(struct smbios_type4, asset_tag),
+ FIELD_SIZEOF(struct smbios_type4, asset_tag), true},
+ {offsetof(struct smbios_type4, part_number),
+ FIELD_SIZEOF(struct smbios_type4, part_number), true},
+ {offsetof(struct smbios_type4, core_count),
+ FIELD_SIZEOF(struct smbios_type4, core_count), false},
+ {offsetof(struct smbios_type4, core_enabled),
+ FIELD_SIZEOF(struct smbios_type4, core_enabled), false},
+ {offsetof(struct smbios_type4, thread_count),
+ FIELD_SIZEOF(struct smbios_type4, thread_count), false},
+ {offsetof(struct smbios_type4, core_count2),
+ FIELD_SIZEOF(struct smbios_type4, core_count2), false},
+ {offsetof(struct smbios_type4, core_enabled2),
+ FIELD_SIZEOF(struct smbios_type4, core_enabled2), false},
+ {offsetof(struct smbios_type4, thread_count2),
+ FIELD_SIZEOF(struct smbios_type4, thread_count2), false},
+ {offsetof(struct smbios_type4, voltage),
+ FIELD_SIZEOF(struct smbios_type4, voltage), false},
+};
+
+struct smbios_filter_table smbios_filter_tables[] = {
+ {SMBIOS_SYSTEM_INFORMATION, smbios_type1_filter_params,
+ ARRAY_SIZE(smbios_type1_filter_params)},
+ {SMBIOS_BOARD_INFORMATION, smbios_type2_filter_params,
+ ARRAY_SIZE(smbios_type2_filter_params)},
+ {SMBIOS_SYSTEM_ENCLOSURE, smbios_type3_filter_params,
+ ARRAY_SIZE(smbios_type3_filter_params)},
+ {SMBIOS_PROCESSOR_INFORMATION, smbios_type4_filter_params,
+ ARRAY_SIZE(smbios_type4_filter_params)},
+};
+
+static void clear_smbios_table(struct smbios_header *header,
+ struct smbios_filter_param *filter,
+ u32 count)
+{
+ u32 i;
+ char *str;
+ u8 string_id;
+
+ for (i = 0; i < count; i++) {
+ if (filter[i].is_string) {
+ string_id = *((u8 *)header + filter[i].offset);
+ if (string_id == 0) /* string is empty */
+ continue;
+
+ str = smbios_string(header, string_id);
+ if (!str)
+ continue;
+
+ /* string is cleared to space, keep '\0' terminator */
+ memset(str, ' ', strlen(str));
+
+ } else {
+ memset((void *)((u8 *)header + filter[i].offset),
+ 0, filter[i].size);
+ }
+ }
+}
+
+void smbios_prepare_measurement(const struct smbios_entry *entry,
+ struct smbios_header *smbios_copy)
+{
+ u32 i, j;
+ struct smbios_header *header;
+
+ for (i = 0; i < ARRAY_SIZE(smbios_filter_tables); i++) {
+ header = smbios_copy;
+ for (j = 0; j < entry->struct_count; j++) {
+ if (header->type == smbios_filter_tables[i].type)
+ break;
+
+ header = get_next_header(header);
+ }
+ if (j >= entry->struct_count)
+ continue;
+
+ clear_smbios_table(header,
+ smbios_filter_tables[i].params,
+ smbios_filter_tables[i].count);
+ }
+}