From 5893721859b73354a935135b4aee297bd41a5b1a Mon Sep 17 00:00:00 2001
From: Jean Delvare <jdelvare@suse.de>
Date: Wed, 1 Apr 2020 09:57:56 +0200
Subject: [PATCH 15/23] dmidecode: Add helper functions pr_list_start/item/end
Print lists through helper functions. pr_list_start() starts the
list, with an optional value. pr_list_item() prints a single item.
pr_list_end() is a no-op for plain text output, but is in place in
anticipation of supporting other output formats such as HTML.
Signed-off-by: Jean Delvare <jdelvare@suse.de>
---
dmidecode.c | 260 +++++++++++++++++++++++++++++-----------------------
dmioutput.c | 35 +++++++
dmioutput.h | 3 +
3 files changed, 184 insertions(+), 114 deletions(-)
diff --git a/dmidecode.c b/dmidecode.c
index 7ab058b61ef0..5a5299ed13ba 100644
--- a/dmidecode.c
+++ b/dmidecode.c
@@ -340,7 +340,7 @@ static void dmi_bios_rom_size(u8 code1, u16 code2)
pr_attr("ROM Size", "%u %s", code2 & 0x3FFF, unit[code2 >> 14]);
}
-static void dmi_bios_characteristics(u64 code, const char *prefix)
+static void dmi_bios_characteristics(u64 code)
{
/* 7.1.1 */
static const char *characteristics[] = {
@@ -381,18 +381,16 @@ static void dmi_bios_characteristics(u64 code, const char *prefix)
*/
if (code.l & (1 << 3))
{
- printf("%s%s\n",
- prefix, characteristics[0]);
+ pr_list_item("%s", characteristics[0]);
return;
}
for (i = 4; i <= 31; i++)
if (code.l & (1 << i))
- printf("%s%s\n",
- prefix, characteristics[i - 3]);
+ pr_list_item("%s", characteristics[i - 3]);
}
-static void dmi_bios_characteristics_x1(u8 code, const char *prefix)
+static void dmi_bios_characteristics_x1(u8 code)
{
/* 7.1.2.1 */
static const char *characteristics[] = {
@@ -409,11 +407,10 @@ static void dmi_bios_characteristics_x1(u8 code, const char *prefix)
for (i = 0; i <= 7; i++)
if (code & (1 << i))
- printf("%s%s\n",
- prefix, characteristics[i]);
+ pr_list_item("%s", characteristics[i]);
}
-static void dmi_bios_characteristics_x2(u8 code, const char *prefix)
+static void dmi_bios_characteristics_x2(u8 code)
{
/* 37.1.2.2 */
static const char *characteristics[] = {
@@ -427,8 +424,7 @@ static void dmi_bios_characteristics_x2(u8 code, const char *prefix)
for (i = 0; i <= 4; i++)
if (code & (1 << i))
- printf("%s%s\n",
- prefix, characteristics[i]);
+ pr_list_item("%s", characteristics[i]);
}
/*
@@ -521,7 +517,7 @@ static const char *dmi_system_wake_up_type(u8 code)
* 7.3 Base Board Information (Type 2)
*/
-static void dmi_base_board_features(u8 code, const char *prefix)
+static void dmi_base_board_features(u8 code)
{
/* 7.3.1 */
static const char *features[] = {
@@ -533,17 +529,17 @@ static void dmi_base_board_features(u8 code, const char *prefix)
};
if ((code & 0x1F) == 0)
- printf(" None\n");
+ pr_list_start("Features", "%s", "None");
else
{
int i;
- printf("\n");
+ pr_list_start("Features", NULL);
for (i = 0; i <= 4; i++)
if (code & (1 << i))
- printf("%s%s\n",
- prefix, features[i]);
+ pr_list_item("%s", features[i]);
}
+ pr_list_end();
}
static const char *dmi_base_board_type(u8 code)
@@ -570,15 +566,14 @@ static const char *dmi_base_board_type(u8 code)
return out_of_spec;
}
-static void dmi_base_board_handles(u8 count, const u8 *p, const char *prefix)
+static void dmi_base_board_handles(u8 count, const u8 *p)
{
int i;
- printf("%sContained Object Handles: %u\n",
- prefix, count);
+ pr_list_start("Contained Object Handles", "%u", count);
for (i = 0; i < count; i++)
- printf("%s\t0x%04X\n",
- prefix, WORD(p + sizeof(u16) * i));
+ pr_list_item("0x%04X", WORD(p + sizeof(u16) * i));
+ pr_list_end();
}
/*
@@ -693,27 +688,29 @@ static void dmi_chassis_power_cords(u8 code)
pr_attr("Number Of Power Cords", "%u", code);
}
-static void dmi_chassis_elements(u8 count, u8 len, const u8 *p, const char *prefix)
+static void dmi_chassis_elements(u8 count, u8 len, const u8 *p)
{
int i;
- printf("%sContained Elements: %u\n",
- prefix, count);
+ pr_list_start("Contained Elements", "%u", count);
for (i = 0; i < count; i++)
{
if (len >= 0x03)
{
- printf("%s\t%s (",
- prefix, p[i * len] & 0x80 ?
+ const char *type;
+
+ type = (p[i * len] & 0x80) ?
dmi_smbios_structure_type(p[i * len] & 0x7F) :
- dmi_base_board_type(p[i * len] & 0x7F));
+ dmi_base_board_type(p[i * len] & 0x7F);
+
if (p[1 + i * len] == p[2 + i * len])
- printf("%u", p[1 + i * len]);
+ pr_list_item("%s (%u)", type, p[1 + i * len]);
else
- printf("%u-%u", p[1 + i * len], p[2 + i * len]);
- printf(")\n");
+ pr_list_item("%s (%u-%u)", type, p[1 + i * len],
+ p[2 + i * len]);
}
}
+ pr_list_end();
}
/*
@@ -1033,7 +1030,7 @@ static const char *dmi_processor_family(const struct dmi_header *h, u16 ver)
}
}
-static void dmi_processor_id(const struct dmi_header *h, const char *prefix)
+static void dmi_processor_id(const struct dmi_header *h)
{
/* Intel AP-485 revision 36, table 2-4 */
static const char *flags[32] = {
@@ -1203,18 +1200,18 @@ static void dmi_processor_id(const struct dmi_header *h, const char *prefix)
}
edx = DWORD(p + 4);
- printf("%sFlags:", prefix);
if ((edx & 0xBFEFFBFF) == 0)
- printf(" None\n");
+ pr_list_start("Flags", "None");
else
{
int i;
- printf("\n");
+ pr_list_start("Flags", NULL);
for (i = 0; i <= 31; i++)
if (flags[i] != NULL && edx & (1 << i))
- printf("%s\t%s\n", prefix, flags[i]);
+ pr_list_item("%s", flags[i]);
}
+ pr_list_end();
}
static void dmi_processor_voltage(const char *attr, u8 code)
@@ -1373,7 +1370,7 @@ static void dmi_processor_cache(const char *attr, u16 code, const char *level,
pr_attr(attr, "0x%04X", code);
}
-static void dmi_processor_characteristics(u16 code, const char *prefix)
+static void dmi_processor_characteristics(const char *attr, u16 code)
{
/* 7.5.9 */
static const char *characteristics[] = {
@@ -1386,15 +1383,16 @@ static void dmi_processor_characteristics(u16 code, const char *prefix)
};
if ((code & 0x00FC) == 0)
- printf(" None\n");
+ pr_attr(attr, "None");
else
{
int i;
- printf("\n");
+ pr_list_start(attr, NULL);
for (i = 2; i <= 7; i++)
if (code & (1 << i))
- printf("%s%s\n", prefix, characteristics[i - 2]);
+ pr_list_item("%s", characteristics[i - 2]);
+ pr_list_end();
}
}
@@ -1421,7 +1419,7 @@ static const char *dmi_memory_controller_ed_method(u8 code)
return out_of_spec;
}
-static void dmi_memory_controller_ec_capabilities(u8 code, const char *prefix)
+static void dmi_memory_controller_ec_capabilities(const char *attr, u8 code)
{
/* 7.6.2 */
static const char *capabilities[] = {
@@ -1434,15 +1432,16 @@ static void dmi_memory_controller_ec_capabilities(u8 code, const char *prefix)
};
if ((code & 0x3F) == 0)
- printf(" None\n");
+ pr_attr(attr, "None");
else
{
int i;
- printf("\n");
+ pr_list_start(attr, NULL);
for (i = 0; i <= 5; i++)
if (code & (1 << i))
- printf("%s%s\n", prefix, capabilities[i]);
+ pr_list_item("%s", capabilities[i]);
+ pr_list_end();
}
}
@@ -1464,7 +1463,7 @@ static const char *dmi_memory_controller_interleave(u8 code)
return out_of_spec;
}
-static void dmi_memory_controller_speeds(u16 code, const char *prefix)
+static void dmi_memory_controller_speeds(const char *attr, u16 code)
{
/* 7.6.4 */
const char *speeds[] = {
@@ -1476,34 +1475,34 @@ static void dmi_memory_controller_speeds(u16 code, const char *prefix)
};
if ((code & 0x001F) == 0)
- printf(" None\n");
+ pr_attr(attr, "None");
else
{
int i;
- printf("\n");
+ pr_list_start(attr, NULL);
for (i = 0; i <= 4; i++)
if (code & (1 << i))
- printf("%s%s\n", prefix, speeds[i]);
+ pr_list_item("%s", speeds[i]);
+ pr_list_end();
}
}
-static void dmi_memory_controller_slots(u8 count, const u8 *p, const char *prefix)
+static void dmi_memory_controller_slots(u8 count, const u8 *p)
{
int i;
- printf("%sAssociated Memory Slots: %u\n",
- prefix, count);
+ pr_list_start("Associated Memory Slots", "%u", count);
for (i = 0; i < count; i++)
- printf("%s\t0x%04X\n",
- prefix, WORD(p + sizeof(u16) * i));
+ pr_list_item("0x%04X", WORD(p + sizeof(u16) * i));
+ pr_list_end();
}
/*
* 7.7 Memory Module Information (Type 6)
*/
-static void dmi_memory_module_types(u16 code, const char *sep)
+static void dmi_memory_module_types(const char *attr, u16 code, int flat)
{
/* 7.7.1 */
static const char *types[] = {
@@ -1521,14 +1520,34 @@ static void dmi_memory_module_types(u16 code, const char *sep)
};
if ((code & 0x07FF) == 0)
- printf(" None");
+ pr_attr(attr, "None");
+ else if (flat)
+ {
+ char type_str[68];
+ int i, off = 0;
+
+ for (i = 0; i <= 10; i++)
+ {
+ if (code & (1 << i))
+ {
+ /* Insert space if not the first value */
+ off += sprintf(type_str + off,
+ off ? " %s" :"%s",
+ types[i]);
+ }
+ }
+ if (off)
+ pr_attr(attr, type_str);
+ }
else
{
int i;
+ pr_list_start(attr, NULL);
for (i = 0; i <= 10; i++)
if (code & (1 << i))
- printf("%s%s", sep, types[i]);
+ pr_list_item("%s", types[i]);
+ pr_list_end();
}
}
@@ -1649,7 +1668,7 @@ static void dmi_cache_size(const char *attr, u16 code)
(((u32)code & 0x8000LU) << 16) | (code & 0x7FFFLU));
}
-static void dmi_cache_types(u16 code, const char *sep)
+static void dmi_cache_types(const char *attr, u16 code, int flat)
{
/* 7.8.2 */
static const char *types[] = {
@@ -1663,14 +1682,34 @@ static void dmi_cache_types(u16 code, const char *sep)
};
if ((code & 0x007F) == 0)
- printf(" None");
+ pr_attr(attr, "None");
+ else if (flat)
+ {
+ char type_str[70];
+ int i, off = 0;
+
+ for (i = 0; i <= 6; i++)
+ {
+ if (code & (1 << i))
+ {
+ /* Insert space if not the first value */
+ off += sprintf(type_str + off,
+ off ? " %s" :"%s",
+ types[i]);
+ }
+ }
+ if (off)
+ pr_attr(attr, type_str);
+ }
else
{
int i;
+ pr_list_start(attr, NULL);
for (i = 0; i <= 6; i++)
if (code & (1 << i))
- printf("%s%s", sep, types[i]);
+ pr_list_item("%s", types[i]);
+ pr_list_end();
}
}
@@ -2053,7 +2092,7 @@ static void dmi_slot_id(u8 code1, u8 code2, u8 type)
}
}
-static void dmi_slot_characteristics(u8 code1, u8 code2, const char *prefix)
+static void dmi_slot_characteristics(const char *attr, u8 code1, u8 code2)
{
/* 7.10.6 */
static const char *characteristics1[] = {
@@ -2074,20 +2113,21 @@ static void dmi_slot_characteristics(u8 code1, u8 code2, const char *prefix)
};
if (code1 & (1 << 0))
- printf(" Unknown\n");
+ pr_attr(attr, "Unknown");
else if ((code1 & 0xFE) == 0 && (code2 & 0x07) == 0)
- printf(" None\n");
+ pr_attr(attr, "None");
else
{
int i;
- printf("\n");
+ pr_list_start(attr, NULL);
for (i = 1; i <= 7; i++)
if (code1 & (1 << i))
- printf("%s%s\n", prefix, characteristics1[i - 1]);
+ pr_list_item("%s", characteristics1[i - 1]);
for (i = 0; i <= 3; i++)
if (code2 & (1 << i))
- printf("%s%s\n", prefix, characteristics2[i]);
+ pr_list_item("%s", characteristics2[i]);
+ pr_list_end();
}
}
@@ -2199,15 +2239,14 @@ static void dmi_system_configuration_options(const struct dmi_header *h)
* 7.14 BIOS Language Information (Type 13)
*/
-static void dmi_bios_languages(const struct dmi_header *h, const char *prefix)
+static void dmi_bios_languages(const struct dmi_header *h)
{
u8 *p = h->data + 4;
u8 count = p[0x00];
int i;
for (i = 1; i <= count; i++)
- printf("%s%s\n",
- prefix, dmi_string(h, i));
+ pr_list_item("%s", dmi_string(h, i));
}
static const char *dmi_bios_language_format(u8 code)
@@ -2222,14 +2261,14 @@ static const char *dmi_bios_language_format(u8 code)
* 7.15 Group Associations (Type 14)
*/
-static void dmi_group_associations_items(u8 count, const u8 *p, const char *prefix)
+static void dmi_group_associations_items(u8 count, const u8 *p)
{
int i;
for (i = 0; i < count; i++)
{
- printf("%s0x%04X (%s)\n",
- prefix, WORD(p + 3 * i + 1),
+ pr_list_item("0x%04X (%s)",
+ WORD(p + 3 * i + 1),
dmi_smbios_structure_type(p[3 * i]));
}
}
@@ -3936,7 +3975,7 @@ static void dmi_tpm_vendor_id(const u8 *p)
pr_attr("Vendor ID", "%s", vendor_id);
}
-static void dmi_tpm_characteristics(u64 code, const char *prefix)
+static void dmi_tpm_characteristics(u64 code)
{
/* 7.1.1 */
static const char *characteristics[] = {
@@ -3952,15 +3991,13 @@ static void dmi_tpm_characteristics(u64 code, const char *prefix)
*/
if (code.l & (1 << 2))
{
- printf("%s%s\n",
- prefix, characteristics[0]);
+ pr_list_item("%s", characteristics[0]);
return;
}
for (i = 3; i <= 5; i++)
if (code.l & (1 << i))
- printf("%s%s\n",
- prefix, characteristics[i - 2]);
+ pr_list_item("%s", characteristics[i - 2]);
}
/*
@@ -3997,12 +4034,13 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_bios_runtime_size((0x10000 - WORD(data + 0x06)) << 4);
}
dmi_bios_rom_size(data[0x09], h->length < 0x1A ? 16 : WORD(data + 0x18));
- printf("\tCharacteristics:\n");
- dmi_bios_characteristics(QWORD(data + 0x0A), "\t\t");
+ pr_list_start("Characteristics", NULL);
+ dmi_bios_characteristics(QWORD(data + 0x0A));
+ pr_list_end();
if (h->length < 0x13) break;
- dmi_bios_characteristics_x1(data[0x12], "\t\t");
+ dmi_bios_characteristics_x1(data[0x12]);
if (h->length < 0x14) break;
- dmi_bios_characteristics_x2(data[0x13], "\t\t");
+ dmi_bios_characteristics_x2(data[0x13]);
if (h->length < 0x18) break;
if (data[0x14] != 0xFF && data[0x15] != 0xFF)
pr_attr("BIOS Revision", "%u.%u",
@@ -4049,8 +4087,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
pr_attr("Asset Tag", "%s",
dmi_string(h, data[0x08]));
if (h->length < 0x0A) break;
- printf("\tFeatures:");
- dmi_base_board_features(data[0x09], "\t\t");
+ dmi_base_board_features(data[0x09]);
if (h->length < 0x0E) break;
pr_attr("Location In Chassis", "%s",
dmi_string(h, data[0x0A]));
@@ -4062,7 +4099,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
if (h->length < 0x0F) break;
if (h->length < 0x0F + data[0x0E] * sizeof(u16)) break;
if (!(opt.flags & FLAG_QUIET))
- dmi_base_board_handles(data[0x0E], data + 0x0F, "\t");
+ dmi_base_board_handles(data[0x0E], data + 0x0F);
break;
case 3: /* 7.4 Chassis Information */
@@ -4097,7 +4134,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_chassis_power_cords(data[0x12]);
if (h->length < 0x15) break;
if (h->length < 0x15 + data[0x13] * data[0x14]) break;
- dmi_chassis_elements(data[0x13], data[0x14], data + 0x15, "\t");
+ dmi_chassis_elements(data[0x13], data[0x14], data + 0x15);
if (h->length < 0x16 + data[0x13] * data[0x14]) break;
pr_attr("SKU Number", "%s",
dmi_string(h, data[0x15 + data[0x13] * data[0x14]]));
@@ -4114,7 +4151,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_processor_family(h, ver));
pr_attr("Manufacturer", "%s",
dmi_string(h, data[0x07]));
- dmi_processor_id(h, "\t");
+ dmi_processor_id(h);
pr_attr("Version", "%s",
dmi_string(h, data[0x10]));
dmi_processor_voltage("Voltage", data[0x11]);
@@ -4158,8 +4195,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
pr_attr("Thread Count", "%u",
h->length >= 0x30 && data[0x25] == 0xFF ?
WORD(data + 0x2E) : data[0x25]);
- printf("\tCharacteristics:");
- dmi_processor_characteristics(WORD(data + 0x26), "\t\t");
+ dmi_processor_characteristics("Characteristics",
+ WORD(data + 0x26));
break;
case 5: /* 7.6 Memory Controller Information */
@@ -4167,8 +4204,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
if (h->length < 0x0F) break;
pr_attr("Error Detecting Method", "%s",
dmi_memory_controller_ed_method(data[0x04]));
- printf("\tError Correcting Capabilities:");
- dmi_memory_controller_ec_capabilities(data[0x05], "\t\t");
+ dmi_memory_controller_ec_capabilities("Error Correcting Capabilities",
+ data[0x05]);
pr_attr("Supported Interleave", "%s",
dmi_memory_controller_interleave(data[0x06]));
pr_attr("Current Interleave", "%s",
@@ -4177,17 +4214,16 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
1 << data[0x08]);
pr_attr("Maximum Total Memory Size", "%u MB",
data[0x0E] * (1 << data[0x08]));
- printf("\tSupported Speeds:");
- dmi_memory_controller_speeds(WORD(data + 0x09), "\t\t");
- printf("\tSupported Memory Types:");
- dmi_memory_module_types(WORD(data + 0x0B), "\n\t\t");
- printf("\n");
+ dmi_memory_controller_speeds("Supported Speeds",
+ WORD(data + 0x09));
+ dmi_memory_module_types("Supported Memory Types",
+ WORD(data + 0x0B), 0);
dmi_processor_voltage("Memory Module Voltage", data[0x0D]);
if (h->length < 0x0F + data[0x0E] * sizeof(u16)) break;
- dmi_memory_controller_slots(data[0x0E], data + 0x0F, "\t");
+ dmi_memory_controller_slots(data[0x0E], data + 0x0F);
if (h->length < 0x10 + data[0x0E] * sizeof(u16)) break;
- printf("\tEnabled Error Correcting Capabilities:");
- dmi_memory_controller_ec_capabilities(data[0x0F + data[0x0E] * sizeof(u16)], "\t\t");
+ dmi_memory_controller_ec_capabilities("Enabled Error Correcting Capabilities",
+ data[0x0F + data[0x0E] * sizeof(u16)]);
break;
case 6: /* 7.7 Memory Module Information */
@@ -4197,9 +4233,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_string(h, data[0x04]));
dmi_memory_module_connections(data[0x05]);
dmi_memory_module_speed("Current Speed", data[0x06]);
- printf("\tType:");
- dmi_memory_module_types(WORD(data + 0x07), " ");
- printf("\n");
+ dmi_memory_module_types("Type", WORD(data + 0x07), 1);
dmi_memory_module_size("Installed Size", data[0x09]);
dmi_memory_module_size("Enabled Size", data[0x0A]);
dmi_memory_module_error(data[0x0B]);
@@ -4226,12 +4260,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
dmi_cache_size_2("Maximum Size", DWORD(data + 0x13));
else
dmi_cache_size("Maximum Size", WORD(data + 0x07));
- printf("\tSupported SRAM Types:");
- dmi_cache_types(WORD(data + 0x0B), "\n\t\t");
- printf("\n");
- printf("\tInstalled SRAM Type:");
- dmi_cache_types(WORD(data + 0x0D), " ");
- printf("\n");
+ dmi_cache_types("Supported SRAM Types", WORD(data + 0x0B), 0);
+ dmi_cache_types("Installed SRAM Type", WORD(data + 0x0D), 1);
if (h->length < 0x13) break;
dmi_memory_module_speed("Speed", data[0x0F]);
pr_attr("Error Correction Type", "%s",
@@ -4270,11 +4300,10 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
pr_attr("Length", "%s",
dmi_slot_length(data[0x08]));
dmi_slot_id(data[0x09], data[0x0A], data[0x05]);
- printf("\tCharacteristics:");
if (h->length < 0x0D)
- dmi_slot_characteristics(data[0x0B], 0x00, "\t\t");
+ dmi_slot_characteristics("Characteristics", data[0x0B], 0x00);
else
- dmi_slot_characteristics(data[0x0B], data[0x0C], "\t\t");
+ dmi_slot_characteristics("Characteristics", data[0x0B], data[0x0C]);
if (h->length < 0x11) break;
dmi_slot_segment_bus_func(WORD(data + 0x0D), data[0x0F], data[0x10]);
if (h->length < 0x13) break;
@@ -4308,8 +4337,9 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
pr_attr("Language Description Format", "%s",
dmi_bios_language_format(data[0x05]));
}
- printf("\tInstallable Languages: %u\n", data[0x04]);
- dmi_bios_languages(h, "\t\t");
+ pr_list_start("Installable Languages", "%u", data[0x04]);
+ dmi_bios_languages(h);
+ pr_list_end();
pr_attr("Currently Installed Language", "%s",
dmi_string(h, data[0x15]));
break;
@@ -4319,9 +4349,10 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
if (h->length < 0x05) break;
pr_attr("Name", "%s",
dmi_string(h, data[0x04]));
- printf("\tItems: %u\n",
+ pr_list_start("Items", "%u",
(h->length - 0x05) / 3);
- dmi_group_associations_items((h->length - 0x05) / 3, data + 0x05, "\t\t");
+ dmi_group_associations_items((h->length - 0x05) / 3, data + 0x05);
+ pr_list_end();
break;
case 15: /* 7.16 System Event Log */
@@ -5002,8 +5033,9 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
break;
}
pr_attr("Description", "%s", dmi_string(h, data[0x12]));
- printf("\tCharacteristics:\n");
- dmi_tpm_characteristics(QWORD(data + 0x13), "\t\t");
+ pr_list_start("Characteristics", NULL);
+ dmi_tpm_characteristics(QWORD(data + 0x13));
+ pr_list_end();
if (h->length < 0x1F) break;
pr_attr("OEM-specific Information", "0x%08X",
DWORD(data + 0x1B));
diff --git a/dmioutput.c b/dmioutput.c
index 2330b65755c9..4c8a32a3569a 100644
--- a/dmioutput.c
+++ b/dmioutput.c
@@ -71,3 +71,38 @@ void pr_attr(const char *name, const char *format, ...)
va_end(args);
printf("\n");
}
+
+void pr_list_start(const char *name, const char *format, ...)
+{
+ va_list args;
+
+ printf("\t%s:", name);
+
+ /* format is optional, skip value if not provided */
+ if (format)
+ {
+ printf(" ");
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ }
+ printf("\n");
+
+}
+
+void pr_list_item(const char *format, ...)
+{
+ va_list args;
+
+ printf("\t\t");
+
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ printf("\n");
+}
+
+void pr_list_end(void)
+{
+ /* a no-op for text output */
+}
diff --git a/dmioutput.h b/dmioutput.h
index 981dcb45f26a..33f09c4452bb 100644
--- a/dmioutput.h
+++ b/dmioutput.h
@@ -26,3 +26,6 @@ void pr_info(const char *format, ...);
void pr_handle(const struct dmi_header *h);
void pr_handle_name(const char *format, ...);
void pr_attr(const char *name, const char *format, ...);
+void pr_list_start(const char *name, const char *format, ...);
+void pr_list_item(const char *format, ...);
+void pr_list_end(void);
--
2.17.1