Blame SOURCES/0014-dmidecode-Add-helper-function-pr_attr.patch

f877e3
From 07968a8a578d34137eb6db0c26b860c567f60903 Mon Sep 17 00:00:00 2001
f877e3
From: Jean Delvare <jdelvare@suse.de>
f877e3
Date: Wed, 1 Apr 2020 09:52:04 +0200
f877e3
Subject: [PATCH 14/23] dmidecode: Add helper function pr_attr
f877e3
f877e3
Print all first-level attributes through a helper function pr_attr.
f877e3
f877e3
Signed-off-by: Jean Delvare <jdelvare@suse.de>
f877e3
---
f877e3
 dmidecode.c | 1357 ++++++++++++++++++++++++---------------------------
f877e3
 dmioem.c    |   66 +--
f877e3
 dmioutput.c |   12 +
f877e3
 dmioutput.h |    1 +
f877e3
 4 files changed, 691 insertions(+), 745 deletions(-)
f877e3
f877e3
diff --git a/dmidecode.c b/dmidecode.c
f877e3
index c226bad06638..7ab058b61ef0 100644
f877e3
--- a/dmidecode.c
f877e3
+++ b/dmidecode.c
f877e3
@@ -261,7 +261,7 @@ static void dmi_dump(const struct dmi_header *h, const char *prefix)
f877e3
 }
f877e3
 
f877e3
 /* shift is 0 if the value is in bytes, 1 if it is in kilobytes */
f877e3
-static void dmi_print_memory_size(u64 code, int shift)
f877e3
+static void dmi_print_memory_size(const char *attr, u64 code, int shift)
f877e3
 {
f877e3
 	unsigned long capacity;
f877e3
 	u16 split[7];
f877e3
@@ -301,7 +301,7 @@ static void dmi_print_memory_size(u64 code, int shift)
f877e3
 	else
f877e3
 		capacity = split[i];
f877e3
 
f877e3
-	printf(" %lu %s", capacity, unit[i + shift]);
f877e3
+	pr_attr(attr, "%lu %s", capacity, unit[i + shift]);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -310,10 +310,19 @@ static void dmi_print_memory_size(u64 code, int shift)
f877e3
 
f877e3
 static void dmi_bios_runtime_size(u32 code)
f877e3
 {
f877e3
+	const char *format;
f877e3
+
f877e3
 	if (code & 0x000003FF)
f877e3
-		printf(" %u bytes", code);
f877e3
+	{
f877e3
+		format = "%u bytes";
f877e3
+	}
f877e3
 	else
f877e3
-		printf(" %u kB", code >> 10);
f877e3
+	{
f877e3
+		format = "%u kB";
f877e3
+		code >>= 10;
f877e3
+	}
f877e3
+
f877e3
+	pr_attr("Runtime Size", format, code);
f877e3
 }
f877e3
 
f877e3
 static void dmi_bios_rom_size(u8 code1, u16 code2)
f877e3
@@ -325,10 +334,10 @@ static void dmi_bios_rom_size(u8 code1, u16 code2)
f877e3
 	if (code1 != 0xFF)
f877e3
 	{
f877e3
 		u64 s = { .l = (code1 + 1) << 6 };
f877e3
-		dmi_print_memory_size(s, 1);
f877e3
+		dmi_print_memory_size("ROM Size", s, 1);
f877e3
 	}
f877e3
 	else
f877e3
-		printf(" %u %s", code2 & 0x3FFF, unit[code2 >> 14]);
f877e3
+		pr_attr("ROM Size", "%u %s", code2 & 0x3FFF, unit[code2 >> 14]);
f877e3
 }
f877e3
 
f877e3
 static void dmi_bios_characteristics(u64 code, const char *prefix)
f877e3
@@ -426,7 +435,7 @@ static void dmi_bios_characteristics_x2(u8 code, const char *prefix)
f877e3
  * 7.2 System Information (Type 1)
f877e3
  */
f877e3
 
f877e3
-static void dmi_system_uuid(const u8 *p, u16 ver)
f877e3
+static void dmi_system_uuid(const char *attr, const u8 *p, u16 ver)
f877e3
 {
f877e3
 	int only0xFF = 1, only0x00 = 1;
f877e3
 	int i;
f877e3
@@ -439,12 +448,18 @@ static void dmi_system_uuid(const u8 *p, u16 ver)
f877e3
 
f877e3
 	if (only0xFF)
f877e3
 	{
f877e3
-		printf("Not Present");
f877e3
+		if (attr)
f877e3
+			pr_attr(attr, "Not Present");
f877e3
+		else
f877e3
+			printf("Not Present\n");
f877e3
 		return;
f877e3
 	}
f877e3
 	if (only0x00)
f877e3
 	{
f877e3
-		printf("Not Settable");
f877e3
+		if (attr)
f877e3
+			pr_attr(attr, "Not Settable");
f877e3
+		else
f877e3
+			printf("Not Settable\n");
f877e3
 		return;
f877e3
 	}
f877e3
 
f877e3
@@ -457,13 +472,29 @@ static void dmi_system_uuid(const u8 *p, u16 ver)
f877e3
 	 * for older versions.
f877e3
 	 */
f877e3
 	if (ver >= 0x0206)
f877e3
-		printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
f877e3
-			p[3], p[2], p[1], p[0], p[5], p[4], p[7], p[6],
f877e3
-			p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
f877e3
+	{
f877e3
+		if (attr)
f877e3
+			pr_attr(attr,
f877e3
+				"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
f877e3
+				p[3], p[2], p[1], p[0], p[5], p[4], p[7], p[6],
f877e3
+				p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
f877e3
+		else
f877e3
+			printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
f877e3
+				p[3], p[2], p[1], p[0], p[5], p[4], p[7], p[6],
f877e3
+				p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
f877e3
+	}
f877e3
 	else
f877e3
-		printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
f877e3
-			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
f877e3
-			p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
f877e3
+	{
f877e3
+		if (attr)
f877e3
+			pr_attr(attr,
f877e3
+				"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
f877e3
+				p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
f877e3
+				p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
f877e3
+		else
f877e3
+			printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
f877e3
+				p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
f877e3
+				p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
f877e3
+	}
f877e3
 }
f877e3
 
f877e3
 static const char *dmi_system_wake_up_type(u8 code)
f877e3
@@ -649,17 +680,17 @@ static const char *dmi_chassis_security_status(u8 code)
f877e3
 static void dmi_chassis_height(u8 code)
f877e3
 {
f877e3
 	if (code == 0x00)
f877e3
-		printf(" Unspecified");
f877e3
+		pr_attr("Height", "Unspecified");
f877e3
 	else
f877e3
-		printf(" %u U", code);
f877e3
+		pr_attr("Height", "%u U", code);
f877e3
 }
f877e3
 
f877e3
 static void dmi_chassis_power_cords(u8 code)
f877e3
 {
f877e3
 	if (code == 0x00)
f877e3
-		printf(" Unspecified");
f877e3
+		pr_attr("Number Of Power Cords", "Unspecified");
f877e3
 	else
f877e3
-		printf(" %u", code);
f877e3
+		pr_attr("Number Of Power Cords", "%u", code);
f877e3
 }
f877e3
 
f877e3
 static void dmi_chassis_elements(u8 count, u8 len, const u8 *p, const char *prefix)
f877e3
@@ -1052,8 +1083,8 @@ static void dmi_processor_id(const struct dmi_header *h, const char *prefix)
f877e3
 	 * This might help learn about new processors supporting the
f877e3
 	 * CPUID instruction or another form of identification.
f877e3
 	 */
f877e3
-	printf("%sID: %02X %02X %02X %02X %02X %02X %02X %02X\n",
f877e3
-		prefix, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
f877e3
+	pr_attr("ID", "%02X %02X %02X %02X %02X %02X %02X %02X",
f877e3
+		p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
f877e3
 
f877e3
 	if (type == 0x05) /* 80386 */
f877e3
 	{
f877e3
@@ -1061,8 +1092,9 @@ static void dmi_processor_id(const struct dmi_header *h, const char *prefix)
f877e3
 		/*
f877e3
 		 * 80386 have a different signature.
f877e3
 		 */
f877e3
-		printf("%sSignature: Type %u, Family %u, Major Stepping %u, Minor Stepping %u\n",
f877e3
-			prefix, dx >> 12, (dx >> 8) & 0xF,
f877e3
+		pr_attr("Signature",
f877e3
+			"Type %u, Family %u, Major Stepping %u, Minor Stepping %u",
f877e3
+			dx >> 12, (dx >> 8) & 0xF,
f877e3
 			(dx >> 4) & 0xF, dx & 0xF);
f877e3
 		return;
f877e3
 	}
f877e3
@@ -1080,8 +1112,9 @@ static void dmi_processor_id(const struct dmi_header *h, const char *prefix)
f877e3
 			sig = 1;
f877e3
 		else
f877e3
 		{
f877e3
-			printf("%sSignature: Type %u, Family %u, Model %u, Stepping %u\n",
f877e3
-				prefix, (dx >> 12) & 0x3, (dx >> 8) & 0xF,
f877e3
+			pr_attr("Signature",
f877e3
+				"Type %u, Family %u, Model %u, Stepping %u",
f877e3
+				(dx >> 12) & 0x3, (dx >> 8) & 0xF,
f877e3
 				(dx >> 4) & 0xF, dx & 0xF);
f877e3
 			return;
f877e3
 		}
f877e3
@@ -1097,8 +1130,9 @@ static void dmi_processor_id(const struct dmi_header *h, const char *prefix)
f877e3
 		 */
f877e3
 		if (midr == 0)
f877e3
 			return;
f877e3
-		printf("%sSignature: Implementor 0x%02x, Variant 0x%x, Architecture %u, Part 0x%03x, Revision %u\n",
f877e3
-			prefix, midr >> 24, (midr >> 20) & 0xF,
f877e3
+		pr_attr("Signature",
f877e3
+			"Implementor 0x%02x, Variant 0x%x, Architecture %u, Part 0x%03x, Revision %u",
f877e3
+			midr >> 24, (midr >> 20) & 0xF,
f877e3
 			(midr >> 16) & 0xF, (midr >> 4) & 0xFFF, midr & 0xF);
f877e3
 		return;
f877e3
 	}
f877e3
@@ -1153,15 +1187,15 @@ static void dmi_processor_id(const struct dmi_header *h, const char *prefix)
f877e3
 	switch (sig)
f877e3
 	{
f877e3
 		case 1: /* Intel */
f877e3
-			printf("%sSignature: Type %u, Family %u, Model %u, Stepping %u\n",
f877e3
-				prefix, (eax >> 12) & 0x3,
f877e3
+			pr_attr("Signature",
f877e3
+				"Type %u, Family %u, Model %u, Stepping %u",
f877e3
+				(eax >> 12) & 0x3,
f877e3
 				((eax >> 20) & 0xFF) + ((eax >> 8) & 0x0F),
f877e3
 				((eax >> 12) & 0xF0) + ((eax >> 4) & 0x0F),
f877e3
 				eax & 0xF);
f877e3
 			break;
f877e3
 		case 2: /* AMD, publication #25481 revision 2.28 */
f877e3
-			printf("%sSignature: Family %u, Model %u, Stepping %u\n",
f877e3
-				prefix,
f877e3
+			pr_attr("Signature", "Family %u, Model %u, Stepping %u",
f877e3
 				((eax >> 8) & 0xF) + (((eax >> 8) & 0xF) == 0xF ? (eax >> 20) & 0xFF : 0),
f877e3
 				((eax >> 4) & 0xF) | (((eax >> 8) & 0xF) == 0xF ? (eax >> 12) & 0xF0 : 0),
f877e3
 				eax & 0xF);
f877e3
@@ -1183,7 +1217,7 @@ static void dmi_processor_id(const struct dmi_header *h, const char *prefix)
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
-static void dmi_processor_voltage(u8 code)
f877e3
+static void dmi_processor_voltage(const char *attr, u8 code)
f877e3
 {
f877e3
 	/* 7.5.4 */
f877e3
 	static const char *voltage[] = {
f877e3
@@ -1194,25 +1228,47 @@ static void dmi_processor_voltage(u8 code)
f877e3
 	int i;
f877e3
 
f877e3
 	if (code & 0x80)
f877e3
-		printf(" %.1f V", (float)(code & 0x7f) / 10);
f877e3
+		pr_attr(attr, "%.1f V", (float)(code & 0x7f) / 10);
f877e3
 	else if ((code & 0x07) == 0x00)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
 	{
f877e3
+		char voltage_str[18];
f877e3
+		int off = 0;
f877e3
+
f877e3
 		for (i = 0; i <= 2; i++)
f877e3
+		{
f877e3
 			if (code & (1 << i))
f877e3
-				printf(" %s", voltage[i]);
f877e3
+			{
f877e3
+				/* Insert space if not the first value */
f877e3
+				off += sprintf(voltage_str + off,
f877e3
+					       off ? " %s" :"%s",
f877e3
+					       voltage[i]);
f877e3
+			}
f877e3
+		}
f877e3
+		if (off)
f877e3
+			pr_attr(attr, voltage_str);
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
-static void dmi_processor_frequency(const u8 *p)
f877e3
+static void dmi_processor_frequency(const char *attr, const u8 *p)
f877e3
 {
f877e3
 	u16 code = WORD(p);
f877e3
 
f877e3
 	if (code)
f877e3
-		printf("%u MHz", code);
f877e3
+	{
f877e3
+		if (attr)
f877e3
+			pr_attr(attr, "%u MHz", code);
f877e3
+		else
f877e3
+			printf("%u MHz\n", code);
f877e3
+	}
f877e3
 	else
f877e3
-		printf("Unknown");
f877e3
+	{
f877e3
+		if (attr)
f877e3
+			pr_attr(attr, "Unknown");
f877e3
+		else
f877e3
+			printf("Unknown\n");
f877e3
+	}
f877e3
 }
f877e3
 
f877e3
 /* code is assumed to be a 3-bit value */
f877e3
@@ -1303,17 +1359,18 @@ static const char *dmi_processor_upgrade(u8 code)
f877e3
 	return out_of_spec;
f877e3
 }
f877e3
 
f877e3
-static void dmi_processor_cache(u16 code, const char *level, u16 ver)
f877e3
+static void dmi_processor_cache(const char *attr, u16 code, const char *level,
f877e3
+				u16 ver)
f877e3
 {
f877e3
 	if (code == 0xFFFF)
f877e3
 	{
f877e3
 		if (ver >= 0x0203)
f877e3
-			printf(" Not Provided");
f877e3
+			pr_attr(attr, "Not Provided");
f877e3
 		else
f877e3
-			printf(" No %s Cache", level);
f877e3
+			pr_attr(attr, "No %s Cache", level);
f877e3
 	}
f877e3
 	else
f877e3
-		printf(" 0x%04X", code);
f877e3
+		pr_attr(attr, "0x%04X", code);
f877e3
 }
f877e3
 
f877e3
 static void dmi_processor_characteristics(u16 code, const char *prefix)
f877e3
@@ -1478,46 +1535,48 @@ static void dmi_memory_module_types(u16 code, const char *sep)
f877e3
 static void dmi_memory_module_connections(u8 code)
f877e3
 {
f877e3
 	if (code == 0xFF)
f877e3
-		printf(" None");
f877e3
+		pr_attr("Bank Connections", "None");
f877e3
+	else if ((code & 0xF0) == 0xF0)
f877e3
+		pr_attr("Bank Connections", "%u", code & 0x0F);
f877e3
+	else if ((code & 0x0F) == 0x0F)
f877e3
+		pr_attr("Bank Connections", "%u", code >> 4);
f877e3
 	else
f877e3
-	{
f877e3
-		if ((code & 0xF0) != 0xF0)
f877e3
-			printf(" %u", code >> 4);
f877e3
-		if ((code & 0x0F) != 0x0F)
f877e3
-			printf(" %u", code & 0x0F);
f877e3
-	}
f877e3
+		pr_attr("Bank Connections", "%u %u", code >> 4, code & 0x0F);
f877e3
 }
f877e3
 
f877e3
-static void dmi_memory_module_speed(u8 code)
f877e3
+static void dmi_memory_module_speed(const char *attr, u8 code)
f877e3
 {
f877e3
 	if (code == 0)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" %u ns", code);
f877e3
+		pr_attr(attr, "%u ns", code);
f877e3
 }
f877e3
 
f877e3
-static void dmi_memory_module_size(u8 code)
f877e3
+static void dmi_memory_module_size(const char *attr, u8 code)
f877e3
 {
f877e3
+	const char *connection;
f877e3
+
f877e3
 	/* 7.7.2 */
f877e3
+	if (code & 0x80)
f877e3
+		connection = " (Double-bank Connection)";
f877e3
+	else
f877e3
+		connection = " (Single-bank Connection)";
f877e3
+
f877e3
 	switch (code & 0x7F)
f877e3
 	{
f877e3
 		case 0x7D:
f877e3
-			printf(" Not Determinable");
f877e3
+			pr_attr(attr, "Not Determinable%s", connection);
f877e3
 			break;
f877e3
 		case 0x7E:
f877e3
-			printf(" Disabled");
f877e3
+			pr_attr(attr, "Disabled%s", connection);
f877e3
 			break;
f877e3
 		case 0x7F:
f877e3
-			printf(" Not Installed");
f877e3
+			pr_attr(attr, "Not Installed");
f877e3
 			return;
f877e3
 		default:
f877e3
-			printf(" %u MB", 1 << (code & 0x7F));
f877e3
+			pr_attr(attr, "%u MB%s", 1 << (code & 0x7F),
f877e3
+				connection);
f877e3
 	}
f877e3
-
f877e3
-	if (code & 0x80)
f877e3
-		printf(" (Double-bank Connection)");
f877e3
-	else
f877e3
-		printf(" (Single-bank Connection)");
f877e3
 }
f877e3
 
f877e3
 static void dmi_memory_module_error(u8 code)
f877e3
@@ -1530,9 +1589,9 @@ static void dmi_memory_module_error(u8 code)
f877e3
 	};
f877e3
 
f877e3
 	if (code & (1 << 2))
f877e3
-		printf(" See Event Log\n");
f877e3
+		pr_attr("Error Status", "See Event Log");
f877e3
 	else
f877e3
-		printf(" %s\n", status[code & 0x03]);
f877e3
+		pr_attr("Error Status", "%s", status[code & 0x03]);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -1564,7 +1623,7 @@ static const char *dmi_cache_location(u8 code)
f877e3
 	return location[code];
f877e3
 }
f877e3
 
f877e3
-static void dmi_cache_size_2(u32 code)
f877e3
+static void dmi_cache_size_2(const char *attr, u32 code)
f877e3
 {
f877e3
 	u64 size;
f877e3
 
f877e3
@@ -1581,12 +1640,13 @@ static void dmi_cache_size_2(u32 code)
f877e3
 	}
f877e3
 
f877e3
 	/* Use a more convenient unit for large cache size */
f877e3
-	dmi_print_memory_size(size, 1);
f877e3
+	dmi_print_memory_size(attr, size, 1);
f877e3
 }
f877e3
 
f877e3
-static void dmi_cache_size(u16 code)
f877e3
+static void dmi_cache_size(const char *attr, u16 code)
f877e3
 {
f877e3
-	dmi_cache_size_2((((u32)code & 0x8000LU) << 16) | (code & 0x7FFFLU));
f877e3
+	dmi_cache_size_2(attr,
f877e3
+			 (((u32)code & 0x8000LU) << 16) | (code & 0x7FFFLU));
f877e3
 }
f877e3
 
f877e3
 static void dmi_cache_types(u16 code, const char *sep)
f877e3
@@ -1938,16 +1998,16 @@ static const char *dmi_slot_length(u8 code)
f877e3
 	return out_of_spec;
f877e3
 }
f877e3
 
f877e3
-static void dmi_slot_id(u8 code1, u8 code2, u8 type, const char *prefix)
f877e3
+static void dmi_slot_id(u8 code1, u8 code2, u8 type)
f877e3
 {
f877e3
 	/* 7.10.5 */
f877e3
 	switch (type)
f877e3
 	{
f877e3
 		case 0x04: /* MCA */
f877e3
-			printf("%sID: %u\n", prefix, code1);
f877e3
+			pr_attr("ID", "%u", code1);
f877e3
 			break;
f877e3
 		case 0x05: /* EISA */
f877e3
-			printf("%sID: %u\n", prefix, code1);
f877e3
+			pr_attr("ID", "%u", code1);
f877e3
 			break;
f877e3
 		case 0x06: /* PCI */
f877e3
 		case 0x0E: /* PCI */
f877e3
@@ -1985,10 +2045,10 @@ static void dmi_slot_id(u8 code1, u8 code2, u8 type, const char *prefix)
f877e3
 		case 0xBB: /* PCI Express 4 */
f877e3
 		case 0xBC: /* PCI Express 4 */
f877e3
 		case 0xBD: /* PCI Express 4 */
f877e3
-			printf("%sID: %u\n", prefix, code1);
f877e3
+			pr_attr("ID", "%u", code1);
f877e3
 			break;
f877e3
 		case 0x07: /* PCMCIA */
f877e3
-			printf("%sID: Adapter %u, Socket %u\n", prefix, code1, code2);
f877e3
+			pr_attr("ID", "Adapter %u, Socket %u", code1, code2);
f877e3
 			break;
f877e3
 	}
f877e3
 }
f877e3
@@ -2031,22 +2091,26 @@ static void dmi_slot_characteristics(u8 code1, u8 code2, const char *prefix)
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
-static void dmi_slot_segment_bus_func(u16 code1, u8 code2, u8 code3, const char *prefix)
f877e3
+static void dmi_slot_segment_bus_func(u16 code1, u8 code2, u8 code3)
f877e3
 {
f877e3
 	/* 7.10.8 */
f877e3
 	if (!(code1 == 0xFFFF && code2 == 0xFF && code3 == 0xFF))
f877e3
-		printf("%sBus Address: %04x:%02x:%02x.%x\n",
f877e3
-		       prefix, code1, code2, code3 >> 3, code3 & 0x7);
f877e3
+		pr_attr("Bus Address", "%04x:%02x:%02x.%x",
f877e3
+			code1, code2, code3 >> 3, code3 & 0x7);
f877e3
 }
f877e3
 
f877e3
-static void dmi_slot_peers(u8 n, const u8 *data, const char *prefix)
f877e3
+static void dmi_slot_peers(u8 n, const u8 *data)
f877e3
 {
f877e3
+	char attr[16];
f877e3
 	int i;
f877e3
 
f877e3
 	for (i = 1; i <= n; i++, data += 5)
f877e3
-		printf("%sPeer Device %d: %04x:%02x:%02x.%x (Width %u)\n",
f877e3
-		       prefix, i, WORD(data), data[2], data[3] >> 3,
f877e3
-		       data[3] & 0x07, data[4]);
f877e3
+	{
f877e3
+		sprintf(attr, "Peer Device %hu", i);
f877e3
+		pr_attr(attr, "%04x:%02x:%02x.%x (Width %u)",
f877e3
+			WORD(data), data[2], data[3] >> 3, data[3] & 0x07,
f877e3
+			data[4]);
f877e3
+	}
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -2074,7 +2138,7 @@ static const char *dmi_on_board_devices_type(u8 code)
f877e3
 	return out_of_spec;
f877e3
 }
f877e3
 
f877e3
-static void dmi_on_board_devices(const struct dmi_header *h, const char *prefix)
f877e3
+static void dmi_on_board_devices(const struct dmi_header *h)
f877e3
 {
f877e3
 	u8 *p = h->data + 4;
f877e3
 	u8 count = (h->length - 0x04) / 2;
f877e3
@@ -2087,12 +2151,11 @@ static void dmi_on_board_devices(const struct dmi_header *h, const char *prefix)
f877e3
 		else
f877e3
 			pr_handle_name("On Board Device %d Information",
f877e3
 				       i + 1);
f877e3
-		printf("%s\tType: %s\n",
f877e3
-			prefix, dmi_on_board_devices_type(p[2 * i] & 0x7F));
f877e3
-		printf("%s\tStatus: %s\n",
f877e3
-			prefix, p[2 * i] & 0x80 ? "Enabled" : "Disabled");
f877e3
-		printf("%s\tDescription: %s\n",
f877e3
-			prefix, dmi_string(h, p[2 * i + 1]));
f877e3
+		pr_attr("Type", "%s",
f877e3
+			dmi_on_board_devices_type(p[2 * i] & 0x7F));
f877e3
+		pr_attr("Status", "%s",
f877e3
+			p[2 * i] & 0x80 ? "Enabled" : "Disabled");
f877e3
+		pr_attr("Description", "%s", dmi_string(h, p[2 * i + 1]));
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
@@ -2100,30 +2163,36 @@ static void dmi_on_board_devices(const struct dmi_header *h, const char *prefix)
f877e3
  * 7.12 OEM Strings (Type 11)
f877e3
  */
f877e3
 
f877e3
-static void dmi_oem_strings(const struct dmi_header *h, const char *prefix)
f877e3
+static void dmi_oem_strings(const struct dmi_header *h)
f877e3
 {
f877e3
+	char attr[11];
f877e3
 	u8 *p = h->data + 4;
f877e3
 	u8 count = p[0x00];
f877e3
 	int i;
f877e3
 
f877e3
 	for (i = 1; i <= count; i++)
f877e3
-		printf("%sString %d: %s\n",
f877e3
-			prefix, i, dmi_string(h, i));
f877e3
+	{
f877e3
+		sprintf(attr, "String %hu", i);
f877e3
+		pr_attr(attr, "%s",dmi_string(h, i));
f877e3
+	}
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
  * 7.13 System Configuration Options (Type 12)
f877e3
  */
f877e3
 
f877e3
-static void dmi_system_configuration_options(const struct dmi_header *h, const char *prefix)
f877e3
+static void dmi_system_configuration_options(const struct dmi_header *h)
f877e3
 {
f877e3
+	char attr[11];
f877e3
 	u8 *p = h->data + 4;
f877e3
 	u8 count = p[0x00];
f877e3
 	int i;
f877e3
 
f877e3
 	for (i = 1; i <= count; i++)
f877e3
-		printf("%sOption %d: %s\n",
f877e3
-			prefix, i, dmi_string(h, i));
f877e3
+	{
f877e3
+		sprintf(attr, "Option %hu", i);
f877e3
+		pr_attr(attr, "%s",dmi_string(h, i));
f877e3
+	}
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -2197,7 +2266,7 @@ static void dmi_event_log_status(u8 code)
f877e3
 		"Full" /* 1 */
f877e3
 	};
f877e3
 
f877e3
-	printf(" %s, %s",
f877e3
+	pr_attr("Status", "%s, %s",
f877e3
 		valid[(code >> 0) & 1], full[(code >> 1) & 1]);
f877e3
 }
f877e3
 
f877e3
@@ -2209,16 +2278,17 @@ static void dmi_event_log_address(u8 method, const u8 *p)
f877e3
 		case 0x00:
f877e3
 		case 0x01:
f877e3
 		case 0x02:
f877e3
-			printf(" Index 0x%04X, Data 0x%04X", WORD(p), WORD(p + 2));
f877e3
+			pr_attr("Access Address", "Index 0x%04X, Data 0x%04X",
f877e3
+				WORD(p), WORD(p + 2));
f877e3
 			break;
f877e3
 		case 0x03:
f877e3
-			printf(" 0x%08X", DWORD(p));
f877e3
+			pr_attr("Access Address", "0x%08X", DWORD(p));
f877e3
 			break;
f877e3
 		case 0x04:
f877e3
-			printf(" 0x%04X", WORD(p));
f877e3
+			pr_attr("Access Address", "0x%04X", WORD(p));
f877e3
 			break;
f877e3
 		default:
f877e3
-			printf(" Unknown");
f877e3
+			pr_attr("Access Address", "Unknown");
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
@@ -2295,19 +2365,22 @@ static const char *dmi_event_log_descriptor_format(u8 code)
f877e3
 	return out_of_spec;
f877e3
 }
f877e3
 
f877e3
-static void dmi_event_log_descriptors(u8 count, u8 len, const u8 *p, const char *prefix)
f877e3
+static void dmi_event_log_descriptors(u8 count, u8 len, const u8 *p)
f877e3
 {
f877e3
 	/* 7.16.1 */
f877e3
+	char attr[16];
f877e3
 	int i;
f877e3
 
f877e3
 	for (i = 0; i < count; i++)
f877e3
 	{
f877e3
 		if (len >= 0x02)
f877e3
 		{
f877e3
-			printf("%sDescriptor %u: %s\n",
f877e3
-				prefix, i + 1, dmi_event_log_descriptor_type(p[i * len]));
f877e3
-			printf("%sData Format %u: %s\n",
f877e3
-				prefix, i + 1, dmi_event_log_descriptor_format(p[i * len + 1]));
f877e3
+			sprintf(attr, "Descriptor %hu", i + 1);
f877e3
+			pr_attr(attr, "%s",
f877e3
+				dmi_event_log_descriptor_type(p[i * len]));
f877e3
+			sprintf(attr, "Data Format %hu", i + 1);
f877e3
+			pr_attr(attr, "%s",
f877e3
+				dmi_event_log_descriptor_format(p[i * len + 1]));
f877e3
 		}
f877e3
 	}
f877e3
 }
f877e3
@@ -2385,40 +2458,40 @@ static const char *dmi_memory_array_ec_type(u8 code)
f877e3
 static void dmi_memory_array_error_handle(u16 code)
f877e3
 {
f877e3
 	if (code == 0xFFFE)
f877e3
-		printf(" Not Provided");
f877e3
+		pr_attr("Error Information Handle", "Not Provided");
f877e3
 	else if (code == 0xFFFF)
f877e3
-		printf(" No Error");
f877e3
+		pr_attr("Error Information Handle", "No Error");
f877e3
 	else
f877e3
-		printf(" 0x%04X", code);
f877e3
+		pr_attr("Error Information Handle", "0x%04X", code);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
  * 7.18 Memory Device (Type 17)
f877e3
  */
f877e3
 
f877e3
-static void dmi_memory_device_width(u16 code)
f877e3
+static void dmi_memory_device_width(const char *attr, u16 code)
f877e3
 {
f877e3
 	/*
f877e3
 	 * If no memory module is present, width may be 0
f877e3
 	 */
f877e3
 	if (code == 0xFFFF || code == 0)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" %u bits", code);
f877e3
+		pr_attr(attr, "%u bits", code);
f877e3
 }
f877e3
 
f877e3
 static void dmi_memory_device_size(u16 code)
f877e3
 {
f877e3
 	if (code == 0)
f877e3
-		printf(" No Module Installed");
f877e3
+		pr_attr("Size", "No Module Installed");
f877e3
 	else if (code == 0xFFFF)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Size", "Unknown");
f877e3
 	else
f877e3
 	{
f877e3
 		u64 s = { .l = code & 0x7FFF };
f877e3
 		if (!(code & 0x8000))
f877e3
 			s.l <<= 10;
f877e3
-		dmi_print_memory_size(s, 1);
f877e3
+		dmi_print_memory_size("Size", s, 1);
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
@@ -2431,19 +2504,20 @@ static void dmi_memory_device_extended_size(u32 code)
f877e3
 	 * as an integer without rounding
f877e3
 	 */
f877e3
 	if (code & 0x3FFUL)
f877e3
-		printf(" %lu MB", (unsigned long)code);
f877e3
+		pr_attr("Size", "%lu MB", (unsigned long)code);
f877e3
 	else if (code & 0xFFC00UL)
f877e3
-		printf(" %lu GB", (unsigned long)code >> 10);
f877e3
+		pr_attr("Size", "%lu GB", (unsigned long)code >> 10);
f877e3
 	else
f877e3
-		printf(" %lu TB", (unsigned long)code >> 20);
f877e3
+		pr_attr("Size", "%lu TB", (unsigned long)code >> 20);
f877e3
 }
f877e3
 
f877e3
-static void dmi_memory_voltage_value(u16 code)
f877e3
+static void dmi_memory_voltage_value(const char *attr, u16 code)
f877e3
 {
f877e3
 	if (code == 0)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(code % 100 ? " %g V" : " %.1f V", (float)code / 1000);
f877e3
+		pr_attr(attr, code % 100 ? "%g V" : "%.1f V",
f877e3
+			(float)code / 1000);
f877e3
 }
f877e3
 
f877e3
 static const char *dmi_memory_device_form_factor(u8 code)
f877e3
@@ -2476,11 +2550,11 @@ static const char *dmi_memory_device_form_factor(u8 code)
f877e3
 static void dmi_memory_device_set(u8 code)
f877e3
 {
f877e3
 	if (code == 0)
f877e3
-		printf(" None");
f877e3
+		pr_attr("Set", "None");
f877e3
 	else if (code == 0xFF)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Set", "Unknown");
f877e3
 	else
f877e3
-		printf(" %u", code);
f877e3
+		pr_attr("Set", "%u", code);
f877e3
 }
f877e3
 
f877e3
 static const char *dmi_memory_device_type(u8 code)
f877e3
@@ -2547,25 +2621,29 @@ static void dmi_memory_device_type_detail(u16 code)
f877e3
 		"Unbuffered (Unregistered)",
f877e3
 		"LRDIMM"  /* 15 */
f877e3
 	};
f877e3
+	char list[172];		/* Update length if you touch the array above */
f877e3
 
f877e3
 	if ((code & 0xFFFE) == 0)
f877e3
-		printf(" None");
f877e3
+		pr_attr("Type Detail", "None");
f877e3
 	else
f877e3
 	{
f877e3
-		int i;
f877e3
+		int i, off = 0;
f877e3
 
f877e3
+		list[0] = '\0';
f877e3
 		for (i = 1; i <= 15; i++)
f877e3
 			if (code & (1 << i))
f877e3
-				printf(" %s", detail[i - 1]);
f877e3
+				off += sprintf(list + off, off ? " %s" : "%s",
f877e3
+					       detail[i - 1]);
f877e3
+		pr_attr("Type Detail", list);
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
-static void dmi_memory_device_speed(u16 code)
f877e3
+static void dmi_memory_device_speed(const char *attr, u16 code)
f877e3
 {
f877e3
 	if (code == 0)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" %u MT/s", code);
f877e3
+		pr_attr(attr, "%u MT/s", code);
f877e3
 }
f877e3
 
f877e3
 static void dmi_memory_technology(u8 code)
f877e3
@@ -2581,9 +2659,9 @@ static void dmi_memory_technology(u8 code)
f877e3
 		"Intel Optane DC persistent memory" /* 0x07 */
f877e3
 	};
f877e3
 	if (code >= 0x01 && code <= 0x07)
f877e3
-		printf(" %s", technology[code - 0x01]);
f877e3
+		pr_attr("Memory Technology", "%s", technology[code - 0x01]);
f877e3
 	else
f877e3
-		printf(" %s", out_of_spec);
f877e3
+		pr_attr("Memory Technology", "%s", out_of_spec);
f877e3
 }
f877e3
 
f877e3
 static void dmi_memory_operating_mode_capability(u16 code)
f877e3
@@ -2596,49 +2674,54 @@ static void dmi_memory_operating_mode_capability(u16 code)
f877e3
 		"Byte-accessible persistent memory",
f877e3
 		"Block-accessible persistent memory" /* 5 */
f877e3
 	};
f877e3
+	char list[99];		/* Update length if you touch the array above */
f877e3
 
f877e3
 	if ((code & 0xFFFE) == 0)
f877e3
-		printf(" None");
f877e3
+		pr_attr("Memory Operating Mode Capability", "None");
f877e3
 	else {
f877e3
-		int i;
f877e3
+		int i, off = 0;
f877e3
 
f877e3
+		list[0] = '\0';
f877e3
 		for (i = 1; i <= 5; i++)
f877e3
 			if (code & (1 << i))
f877e3
-				printf(" %s", mode[i - 1]);
f877e3
+				off += sprintf(list + off, off ? " %s" : "%s",
f877e3
+					       mode[i - 1]);
f877e3
+		pr_attr("Memory Operating Mode Capability", list);
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
-static void dmi_memory_manufacturer_id(u16 code)
f877e3
+static void dmi_memory_manufacturer_id(const char *attr, u16 code)
f877e3
 {
f877e3
 	/* 7.18.8 */
f877e3
 	/* 7.18.10 */
f877e3
 	/* LSB is 7-bit Odd Parity number of continuation codes */
f877e3
 	if (code == 0)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" Bank %d, Hex 0x%02X", (code & 0x7F) + 1, code >> 8);
f877e3
+		pr_attr(attr, "Bank %d, Hex 0x%02X",
f877e3
+			(code & 0x7F) + 1, code >> 8);
f877e3
 }
f877e3
 
f877e3
-static void dmi_memory_product_id(u16 code)
f877e3
+static void dmi_memory_product_id(const char *attr, u16 code)
f877e3
 {
f877e3
 	/* 7.18.9 */
f877e3
 	/* 7.18.11 */
f877e3
 	if (code == 0)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" 0x%04X", code);
f877e3
+		pr_attr(attr, "0x%04X", code);
f877e3
 }
f877e3
 
f877e3
-static void dmi_memory_size(u64 code)
f877e3
+static void dmi_memory_size(const char *attr, u64 code)
f877e3
 {
f877e3
 	/* 7.18.12 */
f877e3
 	/* 7.18.13 */
f877e3
 	if (code.h == 0xFFFFFFFF && code.l == 0xFFFFFFFF)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else if (code.h == 0x0 && code.l == 0x0)
f877e3
-		printf(" None");
f877e3
+		pr_attr(attr, "None");
f877e3
 	else
f877e3
-		dmi_print_memory_size(code, 0);
f877e3
+		dmi_print_memory_size(attr, code, 0);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -2704,17 +2787,17 @@ static const char *dmi_memory_error_operation(u8 code)
f877e3
 static void dmi_memory_error_syndrome(u32 code)
f877e3
 {
f877e3
 	if (code == 0x00000000)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Vendor Syndrome", "Unknown");
f877e3
 	else
f877e3
-		printf(" 0x%08X", code);
f877e3
+		pr_attr("Vendor Syndrome", "0x%08X", code);
f877e3
 }
f877e3
 
f877e3
-static void dmi_32bit_memory_error_address(u32 code)
f877e3
+static void dmi_32bit_memory_error_address(const char *attr, u32 code)
f877e3
 {
f877e3
 	if (code == 0x80000000)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" 0x%08X", code);
f877e3
+		pr_attr(attr, "0x%08X", code);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -2724,23 +2807,23 @@ static void dmi_32bit_memory_error_address(u32 code)
f877e3
 static void dmi_mapped_address_size(u32 code)
f877e3
 {
f877e3
 	if (code == 0)
f877e3
-		printf(" Invalid");
f877e3
+		pr_attr("Range Size", "Invalid");
f877e3
 	else
f877e3
 	{
f877e3
 		u64 size;
f877e3
 
f877e3
 		size.h = 0;
f877e3
 		size.l = code;
f877e3
-		dmi_print_memory_size(size, 1);
f877e3
+		dmi_print_memory_size("Range Size", size, 1);
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
 static void dmi_mapped_address_extended_size(u64 start, u64 end)
f877e3
 {
f877e3
 	if (start.h == end.h && start.l == end.l)
f877e3
-		printf(" Invalid");
f877e3
+		pr_attr("Range Size", "Invalid");
f877e3
 	else
f877e3
-		dmi_print_memory_size(u64_range(start, end), 0);
f877e3
+		dmi_print_memory_size("Range Size", u64_range(start, end), 0);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -2750,36 +2833,32 @@ static void dmi_mapped_address_extended_size(u64 start, u64 end)
f877e3
 static void dmi_mapped_address_row_position(u8 code)
f877e3
 {
f877e3
 	if (code == 0)
f877e3
-		printf(" %s", out_of_spec);
f877e3
+		pr_attr("Partition Row Position", "%s", out_of_spec);
f877e3
 	else if (code == 0xFF)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Partition Row Position", "Unknown");
f877e3
 	else
f877e3
-		printf(" %u", code);
f877e3
+		pr_attr("Partition Row Position", "%u", code);
f877e3
 }
f877e3
 
f877e3
-static void dmi_mapped_address_interleave_position(u8 code, const char *prefix)
f877e3
+static void dmi_mapped_address_interleave_position(u8 code)
f877e3
 {
f877e3
 	if (code != 0)
f877e3
 	{
f877e3
-		printf("%sInterleave Position:", prefix);
f877e3
 		if (code == 0xFF)
f877e3
-			printf(" Unknown");
f877e3
+			pr_attr("Interleave Position", "Unknown");
f877e3
 		else
f877e3
-			printf(" %u", code);
f877e3
-		printf("\n");
f877e3
+			pr_attr("Interleave Position", "%u", code);
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
-static void dmi_mapped_address_interleaved_data_depth(u8 code, const char *prefix)
f877e3
+static void dmi_mapped_address_interleaved_data_depth(u8 code)
f877e3
 {
f877e3
 	if (code != 0)
f877e3
 	{
f877e3
-		printf("%sInterleaved Data Depth:", prefix);
f877e3
 		if (code == 0xFF)
f877e3
-			printf(" Unknown");
f877e3
+			pr_attr("Interleaved Data Depth", "Unknown");
f877e3
 		else
f877e3
-			printf(" %u", code);
f877e3
-		printf("\n");
f877e3
+			pr_attr("Interleaved Data Depth", "%u", code);
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
@@ -2859,25 +2938,25 @@ static const char *dmi_battery_chemistry(u8 code)
f877e3
 static void dmi_battery_capacity(u16 code, u8 multiplier)
f877e3
 {
f877e3
 	if (code == 0)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Design Capacity", "Unknown");
f877e3
 	else
f877e3
-		printf(" %u mWh", code * multiplier);
f877e3
+		pr_attr("Design Capacity", "%u mWh", code * multiplier);
f877e3
 }
f877e3
 
f877e3
 static void dmi_battery_voltage(u16 code)
f877e3
 {
f877e3
 	if (code == 0)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Design Voltage", "Unknown");
f877e3
 	else
f877e3
-		printf(" %u mV", code);
f877e3
+		pr_attr("Design Voltage", "%u mV", code);
f877e3
 }
f877e3
 
f877e3
 static void dmi_battery_maximum_error(u8 code)
f877e3
 {
f877e3
 	if (code == 0xFF)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Maximum Error", "Unknown");
f877e3
 	else
f877e3
-		printf(" %u%%", code);
f877e3
+		pr_attr("Maximum Error", "%u%%", code);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -2897,20 +2976,20 @@ static const char *dmi_system_reset_boot_option(u8 code)
f877e3
 	return option[code];
f877e3
 }
f877e3
 
f877e3
-static void dmi_system_reset_count(u16 code)
f877e3
+static void dmi_system_reset_count(const char *attr, u16 code)
f877e3
 {
f877e3
 	if (code == 0xFFFF)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" %u", code);
f877e3
+		pr_attr(attr, "%u", code);
f877e3
 }
f877e3
 
f877e3
-static void dmi_system_reset_timer(u16 code)
f877e3
+static void dmi_system_reset_timer(const char *attr, u16 code)
f877e3
 {
f877e3
 	if (code == 0xFFFF)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" %u min", code);
f877e3
+		pr_attr(attr, "%u min", code);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -2935,27 +3014,32 @@ static const char *dmi_hardware_security_status(u8 code)
f877e3
 
f877e3
 static void dmi_power_controls_power_on(const u8 *p)
f877e3
 {
f877e3
+	char time[15];
f877e3
+	int off = 0;
f877e3
+
f877e3
 	/* 7.26.1 */
f877e3
 	if (dmi_bcd_range(p[0], 0x01, 0x12))
f877e3
-		printf(" %02X", p[0]);
f877e3
+		off += sprintf(time + off, "%02X", p[0]);
f877e3
 	else
f877e3
-		printf(" *");
f877e3
+		off += sprintf(time + off, "*");
f877e3
 	if (dmi_bcd_range(p[1], 0x01, 0x31))
f877e3
-		printf("-%02X", p[1]);
f877e3
+		off += sprintf(time + off, "-%02X", p[1]);
f877e3
 	else
f877e3
-		printf("-*");
f877e3
+		off += sprintf(time + off, "-*");
f877e3
 	if (dmi_bcd_range(p[2], 0x00, 0x23))
f877e3
-		printf(" %02X", p[2]);
f877e3
+		off += sprintf(time + off, " %02X", p[2]);
f877e3
 	else
f877e3
-		printf(" *");
f877e3
+		off += sprintf(time + off, " *");
f877e3
 	if (dmi_bcd_range(p[3], 0x00, 0x59))
f877e3
-		printf(":%02X", p[3]);
f877e3
+		off += sprintf(time + off, ":%02X", p[3]);
f877e3
 	else
f877e3
-		printf(":*");
f877e3
+		off += sprintf(time + off, ":*");
f877e3
 	if (dmi_bcd_range(p[4], 0x00, 0x59))
f877e3
-		printf(":%02X", p[4]);
f877e3
+		off += sprintf(time + off, ":%02X", p[4]);
f877e3
 	else
f877e3
-		printf(":*");
f877e3
+		off += sprintf(time + off, ":*");
f877e3
+
f877e3
+	pr_attr("Next Scheduled Power-on", time);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -3001,28 +3085,28 @@ static const char *dmi_probe_status(u8 code)
f877e3
 	return out_of_spec;
f877e3
 }
f877e3
 
f877e3
-static void dmi_voltage_probe_value(u16 code)
f877e3
+static void dmi_voltage_probe_value(const char *attr, u16 code)
f877e3
 {
f877e3
 	if (code == 0x8000)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" %.3f V", (float)(i16)code / 1000);
f877e3
+		pr_attr(attr, "%.3f V", (float)(i16)code / 1000);
f877e3
 }
f877e3
 
f877e3
 static void dmi_voltage_probe_resolution(u16 code)
f877e3
 {
f877e3
 	if (code == 0x8000)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Resolution", "Unknown");
f877e3
 	else
f877e3
-		printf(" %.1f mV", (float)code / 10);
f877e3
+		pr_attr("Resolution", "%.1f mV", (float)code / 10);
f877e3
 }
f877e3
 
f877e3
 static void dmi_probe_accuracy(u16 code)
f877e3
 {
f877e3
 	if (code == 0x8000)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Accuracy", "Unknown");
f877e3
 	else
f877e3
-		printf(" %.2f%%", (float)code / 100);
f877e3
+		pr_attr("Accuracy", "%.2f%%", (float)code / 100);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -3058,9 +3142,9 @@ static const char *dmi_cooling_device_type(u8 code)
f877e3
 static void dmi_cooling_device_speed(u16 code)
f877e3
 {
f877e3
 	if (code == 0x8000)
f877e3
-		printf(" Unknown Or Non-rotating");
f877e3
+		pr_attr("Nominal Speed", "Unknown Or Non-rotating");
f877e3
 	else
f877e3
-		printf(" %u rpm", code);
f877e3
+		pr_attr("Nominal Speed", "%u rpm", code);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -3093,40 +3177,40 @@ static const char *dmi_temperature_probe_location(u8 code)
f877e3
 	return out_of_spec;
f877e3
 }
f877e3
 
f877e3
-static void dmi_temperature_probe_value(u16 code)
f877e3
+static void dmi_temperature_probe_value(const char *attr, u16 code)
f877e3
 {
f877e3
 	if (code == 0x8000)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" %.1f deg C", (float)(i16)code / 10);
f877e3
+		pr_attr(attr, "%.1f deg C", (float)(i16)code / 10);
f877e3
 }
f877e3
 
f877e3
 static void dmi_temperature_probe_resolution(u16 code)
f877e3
 {
f877e3
 	if (code == 0x8000)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Resolution", "Unknown");
f877e3
 	else
f877e3
-		printf(" %.3f deg C", (float)code / 1000);
f877e3
+		pr_attr("Resolution", "%.3f deg C", (float)code / 1000);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
  * 7.30 Electrical Current Probe (Type 29)
f877e3
  */
f877e3
 
f877e3
-static void dmi_current_probe_value(u16 code)
f877e3
+static void dmi_current_probe_value(const char *attr, u16 code)
f877e3
 {
f877e3
 	if (code == 0x8000)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" %.3f A", (float)(i16)code / 1000);
f877e3
+		pr_attr(attr, "%.3f A", (float)(i16)code / 1000);
f877e3
 }
f877e3
 
f877e3
 static void dmi_current_probe_resolution(u16 code)
f877e3
 {
f877e3
 	if (code == 0x8000)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Resolution", "Unknown");
f877e3
 	else
f877e3
-		printf(" %.1f mA", (float)code / 10);
f877e3
+		pr_attr("Resolution", "%.1f mA", (float)code / 10);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -3160,12 +3244,12 @@ static const char *dmi_system_boot_status(u8 code)
f877e3
  * 7.34 64-bit Memory Error Information (Type 33)
f877e3
  */
f877e3
 
f877e3
-static void dmi_64bit_memory_error_address(u64 code)
f877e3
+static void dmi_64bit_memory_error_address(const char *attr, u64 code)
f877e3
 {
f877e3
 	if (code.h == 0x80000000 && code.l == 0x00000000)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr(attr, "Unknown");
f877e3
 	else
f877e3
-		printf(" 0x%08X%08X", code.h, code.l);
f877e3
+		pr_attr(attr, "0x%08X%08X", code.h, code.l);
f877e3
 }
f877e3
 
f877e3
 /*
f877e3
@@ -3253,17 +3337,20 @@ static const char *dmi_memory_channel_type(u8 code)
f877e3
 	return out_of_spec;
f877e3
 }
f877e3
 
f877e3
-static void dmi_memory_channel_devices(u8 count, const u8 *p, const char *prefix)
f877e3
+static void dmi_memory_channel_devices(u8 count, const u8 *p)
f877e3
 {
f877e3
+	char attr[18];
f877e3
 	int i;
f877e3
 
f877e3
 	for (i = 1; i <= count; i++)
f877e3
 	{
f877e3
-		printf("%sDevice %u Load: %u\n",
f877e3
-			prefix, i, p[3 * i]);
f877e3
+		sprintf(attr, "Device %hu Load", i);
f877e3
+		pr_attr(attr, "%u", p[3 * i]);
f877e3
 		if (!(opt.flags & FLAG_QUIET))
f877e3
-			printf("%sDevice %u Handle: 0x%04X\n",
f877e3
-				prefix, i, WORD(p + 3 * i + 1));
f877e3
+		{
f877e3
+			sprintf(attr, "Device %hu Handle", i);
f877e3
+			pr_attr(attr, "0x%04X", WORD(p + 3 * i + 1));
f877e3
+		}
f877e3
 	}
f877e3
 }
f877e3
 
f877e3
@@ -3291,12 +3378,13 @@ static void dmi_ipmi_base_address(u8 type, const u8 *p, u8 lsb)
f877e3
 {
f877e3
 	if (type == 0x04) /* SSIF */
f877e3
 	{
f877e3
-		printf("0x%02X (SMBus)", (*p) >> 1);
f877e3
+		pr_attr("Base Address", "0x%02X (SMBus)", (*p) >> 1);
f877e3
 	}
f877e3
 	else
f877e3
 	{
f877e3
 		u64 address = QWORD(p);
f877e3
-		printf("0x%08X%08X (%s)", address.h, (address.l & ~1) | lsb,
f877e3
+		pr_attr("Base Address", "0x%08X%08X (%s)",
f877e3
+			address.h, (address.l & ~1) | lsb,
f877e3
 			address.l & 1 ? "I/O" : "Memory-mapped");
f877e3
 	}
f877e3
 }
f877e3
@@ -3322,9 +3410,9 @@ static const char *dmi_ipmi_register_spacing(u8 code)
f877e3
 static void dmi_power_supply_power(u16 code)
f877e3
 {
f877e3
 	if (code == 0x8000)
f877e3
-		printf(" Unknown");
f877e3
+		pr_attr("Max Power Capacity", "Unknown");
f877e3
 	else
f877e3
-		printf(" %u W", (unsigned int)code);
f877e3
+		pr_attr("Max Power Capacity", "%u W", (unsigned int)code);
f877e3
 }
f877e3
 
f877e3
 static const char *dmi_power_supply_type(u8 code)
f877e3
@@ -3387,7 +3475,7 @@ static const char *dmi_power_supply_range_switching(u8 code)
f877e3
  * whether it's worth the effort.
f877e3
  */
f877e3
 
f877e3
-static void dmi_additional_info(const struct dmi_header *h, const char *prefix)
f877e3
+static void dmi_additional_info(const struct dmi_header *h)
f877e3
 {
f877e3
 	u8 *p = h->data + 4;
f877e3
 	u8 count = *p++;
f877e3
@@ -3403,30 +3491,28 @@ static void dmi_additional_info(const struct dmi_header *h, const char *prefix)
f877e3
 		length = p[0x00];
f877e3
 		if (length < 0x05 || h->length < offset + length) break;
f877e3
 
f877e3
-		printf("%s\tReferenced Handle: 0x%04x\n",
f877e3
-			prefix, WORD(p + 0x01));
f877e3
-		printf("%s\tReferenced Offset: 0x%02x\n",
f877e3
-			prefix, p[0x03]);
f877e3
-		printf("%s\tString: %s\n",
f877e3
-			prefix, dmi_string(h, p[0x04]));
f877e3
+		pr_attr("Referenced Handle", "0x%04x",
f877e3
+			WORD(p + 0x01));
f877e3
+		pr_attr("Referenced Offset", "0x%02x",
f877e3
+			p[0x03]);
f877e3
+		pr_attr("String", "%s",
f877e3
+			dmi_string(h, p[0x04]));
f877e3
 
f877e3
-		printf("%s\tValue: ", prefix);
f877e3
 		switch (length - 0x05)
f877e3
 		{
f877e3
 			case 1:
f877e3
-				printf("0x%02x", p[0x05]);
f877e3
+				pr_attr("Value", "0x%02x", p[0x05]);
f877e3
 				break;
f877e3
 			case 2:
f877e3
-				printf("0x%04x", WORD(p + 0x05));
f877e3
+				pr_attr("Value", "0x%04x", WORD(p + 0x05));
f877e3
 				break;
f877e3
 			case 4:
f877e3
-				printf("0x%08x", DWORD(p + 0x05));
f877e3
+				pr_attr("Value", "0x%08x", DWORD(p + 0x05));
f877e3
 				break;
f877e3
 			default:
f877e3
-				printf("Unexpected size");
f877e3
+				pr_attr("Value", "Unexpected size");
f877e3
 				break;
f877e3
 		}
f877e3
-		printf("\n");
f877e3
 
f877e3
 		p += length;
f877e3
 		offset += length;
f877e3
@@ -3580,8 +3666,7 @@ static void dmi_parse_protocol_record(const char *prefix, u8 *rec)
f877e3
 	 * we can just pick a sufficiently recent version here.
f877e3
 	 */
f877e3
 	printf("%s\tService UUID: ", prefix);
f877e3
-	dmi_system_uuid(&rdata[0], 0x311);
f877e3
-	printf("\n");
f877e3
+	dmi_system_uuid(NULL, &rdata[0], 0x311);	/* FIXME */
f877e3
 
f877e3
 	/*
f877e3
 	 * DSP0270: 8.6: Redfish Over IP Host IP Assignment Type
f877e3
@@ -3710,7 +3795,7 @@ static void dmi_parse_controller_structure(const struct dmi_header *h,
f877e3
 		return;
f877e3
 
f877e3
 	type = data[0x4];
f877e3
-	printf("%sHost Interface Type: %s\n", prefix,
f877e3
+	pr_attr("Host Interface Type", "%s",
f877e3
 		dmi_management_controller_host_type(type));
f877e3
 
f877e3
 	/*
f877e3
@@ -3725,17 +3810,17 @@ static void dmi_parse_controller_structure(const struct dmi_header *h,
f877e3
 		/* DSP0270: 8.3 Table 2: Device Type */
f877e3
 		type = data[0x6];
f877e3
 
f877e3
-		printf("%sDevice Type: %s\n", prefix,
f877e3
+		pr_attr("Device Type", "%s",
f877e3
 			dmi_parse_device_type(type));
f877e3
 		if (type == 0x2 && len >= 5)
f877e3
 		{
f877e3
 			/* USB Device Type - need at least 6 bytes */
f877e3
 			u8 *usbdata = &data[0x7];
f877e3
 			/* USB Device Descriptor: idVendor */
f877e3
-			printf("%sidVendor: 0x%04x\n", prefix,
f877e3
+			pr_attr("idVendor", "0x%04x",
f877e3
 				WORD(&usbdata[0x0]));
f877e3
 			/* USB Device Descriptor: idProduct */
f877e3
-			printf("%sidProduct: 0x%04x\n", prefix,
f877e3
+			pr_attr("idProduct", "0x%04x",
f877e3
 				WORD(&usbdata[0x2]));
f877e3
 			/*
f877e3
 			 * USB Serial number is here, but its useless, don't
f877e3
@@ -3747,16 +3832,16 @@ static void dmi_parse_controller_structure(const struct dmi_header *h,
f877e3
 			/* PCI Device Type - Need at least 8 bytes */
f877e3
 			u8 *pcidata = &data[0x7];
f877e3
 			/* PCI Device Descriptor: VendorID */
f877e3
-			printf("%sVendorID: 0x%04x\n", prefix,
f877e3
+			pr_attr("VendorID", "0x%04x",
f877e3
 				WORD(&pcidata[0x0]));
f877e3
 			/* PCI Device Descriptor: DeviceID */
f877e3
-			printf("%sDeviceID: 0x%04x\n", prefix,
f877e3
+			pr_attr("DeviceID", "0x%04x",
f877e3
 				WORD(&pcidata[0x2]));
f877e3
 			/* PCI Device Descriptor: PCI SubvendorID */
f877e3
-			printf("%sSubVendorID: 0x%04x\n", prefix,
f877e3
+			pr_attr("SubVendorID", "0x%04x",
f877e3
 				WORD(&pcidata[0x4]));
f877e3
 			/* PCI Device Descriptor: PCI SubdeviceID */
f877e3
-			printf("%sSubDeviceID: 0x%04x\n", prefix,
f877e3
+			pr_attr("SubDeviceID", "0x%04x",
f877e3
 				WORD(&pcidata[0x6]));
f877e3
 		}
f877e3
 		else if (type == 0x4 && len >= 5)
f877e3
@@ -3764,8 +3849,8 @@ static void dmi_parse_controller_structure(const struct dmi_header *h,
f877e3
 			/* OEM Device Type - Need at least 4 bytes */
f877e3
 			u8 *oemdata = &data[0x7];
f877e3
 			/* OEM Device Descriptor: IANA */
f877e3
-			printf("%sVendor ID: 0x%02x:0x%02x:0x%02x:0x%02x\n",
f877e3
-				prefix, oemdata[0x0], oemdata[0x1],
f877e3
+			pr_attr("Vendor ID", "0x%02x:0x%02x:0x%02x:0x%02x",
f877e3
+				oemdata[0x0], oemdata[0x1],
f877e3
 				oemdata[0x2], oemdata[0x3]);
f877e3
 		}
f877e3
 		/* Don't mess with unknown types for now */
f877e3
@@ -3848,7 +3933,7 @@ static void dmi_tpm_vendor_id(const u8 *p)
f877e3
 	/* Terminate the string */
f877e3
 	vendor_id[i] = '\0';
f877e3
 
f877e3
-	printf(" %s", vendor_id);
f877e3
+	pr_attr("Vendor ID", "%s", vendor_id);
f877e3
 }
f877e3
 
f877e3
 static void dmi_tpm_characteristics(u64 code, const char *prefix)
f877e3
@@ -3894,11 +3979,11 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 		case 0: /* 7.1 BIOS Information */
f877e3
 			pr_handle_name("BIOS Information");
f877e3
 			if (h->length < 0x12) break;
f877e3
-			printf("\tVendor: %s\n",
f877e3
+			pr_attr("Vendor", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tVersion: %s\n",
f877e3
+			pr_attr("Version", "%s",
f877e3
 				dmi_string(h, data[0x05]));
f877e3
-			printf("\tRelease Date: %s\n",
f877e3
+			pr_attr("Release Date", "%s",
f877e3
 				dmi_string(h, data[0x08]));
f877e3
 			/*
f877e3
 			 * On IA-64, the BIOS base address will read 0 because
f877e3
@@ -3907,15 +3992,11 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 			 */
f877e3
 			if (WORD(data + 0x06) != 0)
f877e3
 			{
f877e3
-				printf("\tAddress: 0x%04X0\n",
f877e3
+				pr_attr("Address", "0x%04X0",
f877e3
 					WORD(data + 0x06));
f877e3
-				printf("\tRuntime Size:");
f877e3
 				dmi_bios_runtime_size((0x10000 - WORD(data + 0x06)) << 4);
f877e3
-				printf("\n");
f877e3
 			}
f877e3
-			printf("\tROM Size:");
f877e3
 			dmi_bios_rom_size(data[0x09], h->length < 0x1A ? 16 : WORD(data + 0x18));
f877e3
-			printf("\n");
f877e3
 			printf("\tCharacteristics:\n");
f877e3
 			dmi_bios_characteristics(QWORD(data + 0x0A), "\t\t");
f877e3
 			if (h->length < 0x13) break;
f877e3
@@ -3924,61 +4005,59 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 			dmi_bios_characteristics_x2(data[0x13], "\t\t");
f877e3
 			if (h->length < 0x18) break;
f877e3
 			if (data[0x14] != 0xFF && data[0x15] != 0xFF)
f877e3
-				printf("\tBIOS Revision: %u.%u\n",
f877e3
+				pr_attr("BIOS Revision", "%u.%u",
f877e3
 					data[0x14], data[0x15]);
f877e3
 			if (data[0x16] != 0xFF && data[0x17] != 0xFF)
f877e3
-				printf("\tFirmware Revision: %u.%u\n",
f877e3
+				pr_attr("Firmware Revision", "%u.%u",
f877e3
 					data[0x16], data[0x17]);
f877e3
 			break;
f877e3
 
f877e3
 		case 1: /* 7.2 System Information */
f877e3
 			pr_handle_name("System Information");
f877e3
 			if (h->length < 0x08) break;
f877e3
-			printf("\tManufacturer: %s\n",
f877e3
+			pr_attr("Manufacturer", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tProduct Name: %s\n",
f877e3
+			pr_attr("Product Name", "%s",
f877e3
 				dmi_string(h, data[0x05]));
f877e3
-			printf("\tVersion: %s\n",
f877e3
+			pr_attr("Version", "%s",
f877e3
 				dmi_string(h, data[0x06]));
f877e3
-			printf("\tSerial Number: %s\n",
f877e3
+			pr_attr("Serial Number", "%s",
f877e3
 				dmi_string(h, data[0x07]));
f877e3
 			if (h->length < 0x19) break;
f877e3
-			printf("\tUUID: ");
f877e3
-			dmi_system_uuid(data + 0x08, ver);
f877e3
-			printf("\n");
f877e3
-			printf("\tWake-up Type: %s\n",
f877e3
+			dmi_system_uuid("UUID", data + 0x08, ver);
f877e3
+			pr_attr("Wake-up Type", "%s",
f877e3
 				dmi_system_wake_up_type(data[0x18]));
f877e3
 			if (h->length < 0x1B) break;
f877e3
-			printf("\tSKU Number: %s\n",
f877e3
+			pr_attr("SKU Number", "%s",
f877e3
 				dmi_string(h, data[0x19]));
f877e3
-			printf("\tFamily: %s\n",
f877e3
+			pr_attr("Family", "%s",
f877e3
 				dmi_string(h, data[0x1A]));
f877e3
 			break;
f877e3
 
f877e3
 		case 2: /* 7.3 Base Board Information */
f877e3
 			pr_handle_name("Base Board Information");
f877e3
 			if (h->length < 0x08) break;
f877e3
-			printf("\tManufacturer: %s\n",
f877e3
+			pr_attr("Manufacturer", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tProduct Name: %s\n",
f877e3
+			pr_attr("Product Name", "%s",
f877e3
 				dmi_string(h, data[0x05]));
f877e3
-			printf("\tVersion: %s\n",
f877e3
+			pr_attr("Version", "%s",
f877e3
 				dmi_string(h, data[0x06]));
f877e3
-			printf("\tSerial Number: %s\n",
f877e3
+			pr_attr("Serial Number", "%s",
f877e3
 				dmi_string(h, data[0x07]));
f877e3
 			if (h->length < 0x09) break;
f877e3
-			printf("\tAsset Tag: %s\n",
f877e3
+			pr_attr("Asset Tag", "%s",
f877e3
 				dmi_string(h, data[0x08]));
f877e3
 			if (h->length < 0x0A) break;
f877e3
 			printf("\tFeatures:");
f877e3
 			dmi_base_board_features(data[0x09], "\t\t");
f877e3
 			if (h->length < 0x0E) break;
f877e3
-			printf("\tLocation In Chassis: %s\n",
f877e3
+			pr_attr("Location In Chassis", "%s",
f877e3
 				dmi_string(h, data[0x0A]));
f877e3
 			if (!(opt.flags & FLAG_QUIET))
f877e3
-				printf("\tChassis Handle: 0x%04X\n",
f877e3
+				pr_attr("Chassis Handle", "0x%04X",
f877e3
 					WORD(data + 0x0B));
f877e3
-			printf("\tType: %s\n",
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_base_board_type(data[0x0D]));
f877e3
 			if (h->length < 0x0F) break;
f877e3
 			if (h->length < 0x0F + data[0x0E] * sizeof(u16)) break;
f877e3
@@ -3989,109 +4068,94 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 		case 3: /* 7.4 Chassis Information */
f877e3
 			pr_handle_name("Chassis Information");
f877e3
 			if (h->length < 0x09) break;
f877e3
-			printf("\tManufacturer: %s\n",
f877e3
+			pr_attr("Manufacturer", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tType: %s\n",
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_chassis_type(data[0x05]));
f877e3
-			printf("\tLock: %s\n",
f877e3
+			pr_attr("Lock", "%s",
f877e3
 				dmi_chassis_lock(data[0x05] >> 7));
f877e3
-			printf("\tVersion: %s\n",
f877e3
+			pr_attr("Version", "%s",
f877e3
 				dmi_string(h, data[0x06]));
f877e3
-			printf("\tSerial Number: %s\n",
f877e3
+			pr_attr("Serial Number", "%s",
f877e3
 				dmi_string(h, data[0x07]));
f877e3
-			printf("\tAsset Tag: %s\n",
f877e3
+			pr_attr("Asset Tag", "%s",
f877e3
 				dmi_string(h, data[0x08]));
f877e3
 			if (h->length < 0x0D) break;
f877e3
-			printf("\tBoot-up State: %s\n",
f877e3
+			pr_attr("Boot-up State", "%s",
f877e3
 				dmi_chassis_state(data[0x09]));
f877e3
-			printf("\tPower Supply State: %s\n",
f877e3
+			pr_attr("Power Supply State", "%s",
f877e3
 				dmi_chassis_state(data[0x0A]));
f877e3
-			printf("\tThermal State: %s\n",
f877e3
+			pr_attr("Thermal State", "%s",
f877e3
 				dmi_chassis_state(data[0x0B]));
f877e3
-			printf("\tSecurity Status: %s\n",
f877e3
+			pr_attr("Security Status", "%s",
f877e3
 				dmi_chassis_security_status(data[0x0C]));
f877e3
 			if (h->length < 0x11) break;
f877e3
-			printf("\tOEM Information: 0x%08X\n",
f877e3
+			pr_attr("OEM Information", "0x%08X",
f877e3
 				DWORD(data + 0x0D));
f877e3
 			if (h->length < 0x13) break;
f877e3
-			printf("\tHeight:");
f877e3
 			dmi_chassis_height(data[0x11]);
f877e3
-			printf("\n");
f877e3
-			printf("\tNumber Of Power Cords:");
f877e3
 			dmi_chassis_power_cords(data[0x12]);
f877e3
-			printf("\n");
f877e3
 			if (h->length < 0x15) break;
f877e3
 			if (h->length < 0x15 + data[0x13] * data[0x14]) break;
f877e3
 			dmi_chassis_elements(data[0x13], data[0x14], data + 0x15, "\t");
f877e3
 			if (h->length < 0x16 + data[0x13] * data[0x14]) break;
f877e3
-			printf("\tSKU Number: %s\n",
f877e3
+			pr_attr("SKU Number", "%s",
f877e3
 				dmi_string(h, data[0x15 + data[0x13] * data[0x14]]));
f877e3
 			break;
f877e3
 
f877e3
 		case 4: /* 7.5 Processor Information */
f877e3
 			pr_handle_name("Processor Information");
f877e3
 			if (h->length < 0x1A) break;
f877e3
-			printf("\tSocket Designation: %s\n",
f877e3
+			pr_attr("Socket Designation", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tType: %s\n",
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_processor_type(data[0x05]));
f877e3
-			printf("\tFamily: %s\n",
f877e3
+			pr_attr("Family", "%s",
f877e3
 				dmi_processor_family(h, ver));
f877e3
-			printf("\tManufacturer: %s\n",
f877e3
+			pr_attr("Manufacturer", "%s",
f877e3
 				dmi_string(h, data[0x07]));
f877e3
 			dmi_processor_id(h, "\t");
f877e3
-			printf("\tVersion: %s\n",
f877e3
+			pr_attr("Version", "%s",
f877e3
 				dmi_string(h, data[0x10]));
f877e3
-			printf("\tVoltage:");
f877e3
-			dmi_processor_voltage(data[0x11]);
f877e3
-			printf("\n");
f877e3
-			printf("\tExternal Clock: ");
f877e3
-			dmi_processor_frequency(data + 0x12);
f877e3
-			printf("\n");
f877e3
-			printf("\tMax Speed: ");
f877e3
-			dmi_processor_frequency(data + 0x14);
f877e3
-			printf("\n");
f877e3
-			printf("\tCurrent Speed: ");
f877e3
-			dmi_processor_frequency(data + 0x16);
f877e3
-			printf("\n");
f877e3
+			dmi_processor_voltage("Voltage", data[0x11]);
f877e3
+			dmi_processor_frequency("External Clock", data + 0x12);
f877e3
+			dmi_processor_frequency("Max Speed", data + 0x14);
f877e3
+			dmi_processor_frequency("Current Speed", data + 0x16);
f877e3
 			if (data[0x18] & (1 << 6))
f877e3
-				printf("\tStatus: Populated, %s\n",
f877e3
+				pr_attr("Status", "Populated, %s",
f877e3
 					dmi_processor_status(data[0x18] & 0x07));
f877e3
 			else
f877e3
-				printf("\tStatus: Unpopulated\n");
f877e3
-			printf("\tUpgrade: %s\n",
f877e3
+				pr_attr("Status", "Unpopulated");
f877e3
+			pr_attr("Upgrade", "%s",
f877e3
 				dmi_processor_upgrade(data[0x19]));
f877e3
 			if (h->length < 0x20) break;
f877e3
 			if (!(opt.flags & FLAG_QUIET))
f877e3
 			{
f877e3
-				printf("\tL1 Cache Handle:");
f877e3
-				dmi_processor_cache(WORD(data + 0x1A), "L1", ver);
f877e3
-				printf("\n");
f877e3
-				printf("\tL2 Cache Handle:");
f877e3
-				dmi_processor_cache(WORD(data + 0x1C), "L2", ver);
f877e3
-				printf("\n");
f877e3
-				printf("\tL3 Cache Handle:");
f877e3
-				dmi_processor_cache(WORD(data + 0x1E), "L3", ver);
f877e3
-				printf("\n");
f877e3
+				dmi_processor_cache("L1 Cache Handle",
f877e3
+						    WORD(data + 0x1A), "L1", ver);
f877e3
+				dmi_processor_cache("L2 Cache Handle",
f877e3
+						    WORD(data + 0x1C), "L2", ver);
f877e3
+				dmi_processor_cache("L3 Cache Handle",
f877e3
+						    WORD(data + 0x1E), "L3", ver);
f877e3
 			}
f877e3
 			if (h->length < 0x23) break;
f877e3
-			printf("\tSerial Number: %s\n",
f877e3
+			pr_attr("Serial Number", "%s",
f877e3
 				dmi_string(h, data[0x20]));
f877e3
-			printf("\tAsset Tag: %s\n",
f877e3
+			pr_attr("Asset Tag", "%s",
f877e3
 				dmi_string(h, data[0x21]));
f877e3
-			printf("\tPart Number: %s\n",
f877e3
+			pr_attr("Part Number", "%s",
f877e3
 				dmi_string(h, data[0x22]));
f877e3
 			if (h->length < 0x28) break;
f877e3
 			if (data[0x23] != 0)
f877e3
-				printf("\tCore Count: %u\n",
f877e3
+				pr_attr("Core Count", "%u",
f877e3
 					h->length >= 0x2C && data[0x23] == 0xFF ?
f877e3
 					WORD(data + 0x2A) : data[0x23]);
f877e3
 			if (data[0x24] != 0)
f877e3
-				printf("\tCore Enabled: %u\n",
f877e3
+				pr_attr("Core Enabled", "%u",
f877e3
 					h->length >= 0x2E && data[0x24] == 0xFF ?
f877e3
 					WORD(data + 0x2C) : data[0x24]);
f877e3
 			if (data[0x25] != 0)
f877e3
-				printf("\tThread Count: %u\n",
f877e3
+				pr_attr("Thread Count", "%u",
f877e3
 					h->length >= 0x30 && data[0x25] == 0xFF ?
f877e3
 					WORD(data + 0x2E) : data[0x25]);
f877e3
 			printf("\tCharacteristics:");
f877e3
@@ -4101,26 +4165,24 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 		case 5: /* 7.6 Memory Controller Information */
f877e3
 			pr_handle_name("Memory Controller Information");
f877e3
 			if (h->length < 0x0F) break;
f877e3
-			printf("\tError Detecting Method: %s\n",
f877e3
+			pr_attr("Error Detecting Method", "%s",
f877e3
 				dmi_memory_controller_ed_method(data[0x04]));
f877e3
 			printf("\tError Correcting Capabilities:");
f877e3
 			dmi_memory_controller_ec_capabilities(data[0x05], "\t\t");
f877e3
-			printf("\tSupported Interleave: %s\n",
f877e3
+			pr_attr("Supported Interleave", "%s",
f877e3
 				dmi_memory_controller_interleave(data[0x06]));
f877e3
-			printf("\tCurrent Interleave: %s\n",
f877e3
+			pr_attr("Current Interleave", "%s",
f877e3
 				dmi_memory_controller_interleave(data[0x07]));
f877e3
-			printf("\tMaximum Memory Module Size: %u MB\n",
f877e3
+			pr_attr("Maximum Memory Module Size", "%u MB",
f877e3
 				1 << data[0x08]);
f877e3
-			printf("\tMaximum Total Memory Size: %u MB\n",
f877e3
+			pr_attr("Maximum Total Memory Size", "%u MB",
f877e3
 				data[0x0E] * (1 << data[0x08]));
f877e3
 			printf("\tSupported Speeds:");
f877e3
 			dmi_memory_controller_speeds(WORD(data + 0x09), "\t\t");
f877e3
 			printf("\tSupported Memory Types:");
f877e3
 			dmi_memory_module_types(WORD(data + 0x0B), "\n\t\t");
f877e3
 			printf("\n");
f877e3
-			printf("\tMemory Module Voltage:");
f877e3
-			dmi_processor_voltage(data[0x0D]);
f877e3
-			printf("\n");
f877e3
+			dmi_processor_voltage("Memory Module Voltage", data[0x0D]);
f877e3
 			if (h->length < 0x0F + data[0x0E] * sizeof(u16)) break;
f877e3
 			dmi_memory_controller_slots(data[0x0E], data + 0x0F, "\t");
f877e3
 			if (h->length < 0x10 + data[0x0E] * sizeof(u16)) break;
f877e3
@@ -4131,52 +4193,39 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 		case 6: /* 7.7 Memory Module Information */
f877e3
 			pr_handle_name("Memory Module Information");
f877e3
 			if (h->length < 0x0C) break;
f877e3
-			printf("\tSocket Designation: %s\n",
f877e3
+			pr_attr("Socket Designation", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tBank Connections:");
f877e3
 			dmi_memory_module_connections(data[0x05]);
f877e3
-			printf("\n");
f877e3
-			printf("\tCurrent Speed:");
f877e3
-			dmi_memory_module_speed(data[0x06]);
f877e3
-			printf("\n");
f877e3
+			dmi_memory_module_speed("Current Speed", data[0x06]);
f877e3
 			printf("\tType:");
f877e3
 			dmi_memory_module_types(WORD(data + 0x07), " ");
f877e3
 			printf("\n");
f877e3
-			printf("\tInstalled Size:");
f877e3
-			dmi_memory_module_size(data[0x09]);
f877e3
-			printf("\n");
f877e3
-			printf("\tEnabled Size:");
f877e3
-			dmi_memory_module_size(data[0x0A]);
f877e3
-			printf("\n");
f877e3
-			printf("\tError Status:");
f877e3
+			dmi_memory_module_size("Installed Size", data[0x09]);
f877e3
+			dmi_memory_module_size("Enabled Size", data[0x0A]);
f877e3
 			dmi_memory_module_error(data[0x0B]);
f877e3
 			break;
f877e3
 
f877e3
 		case 7: /* 7.8 Cache Information */
f877e3
 			pr_handle_name("Cache Information");
f877e3
 			if (h->length < 0x0F) break;
f877e3
-			printf("\tSocket Designation: %s\n",
f877e3
+			pr_attr("Socket Designation", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tConfiguration: %s, %s, Level %u\n",
f877e3
+			pr_attr("Configuration", "%s, %s, Level %u",
f877e3
 				WORD(data + 0x05) & 0x0080 ? "Enabled" : "Disabled",
f877e3
 				WORD(data + 0x05) & 0x0008 ? "Socketed" : "Not Socketed",
f877e3
 				(WORD(data + 0x05) & 0x0007) + 1);
f877e3
-			printf("\tOperational Mode: %s\n",
f877e3
+			pr_attr("Operational Mode", "%s",
f877e3
 				dmi_cache_mode((WORD(data + 0x05) >> 8) & 0x0003));
f877e3
-			printf("\tLocation: %s\n",
f877e3
+			pr_attr("Location", "%s",
f877e3
 				dmi_cache_location((WORD(data + 0x05) >> 5) & 0x0003));
f877e3
-			printf("\tInstalled Size:");
f877e3
 			if (h->length >= 0x1B)
f877e3
-				dmi_cache_size_2(DWORD(data + 0x17));
f877e3
+				dmi_cache_size_2("Installed Size", DWORD(data + 0x17));
f877e3
 			else
f877e3
-				dmi_cache_size(WORD(data + 0x09));
f877e3
-			printf("\n");
f877e3
-			printf("\tMaximum Size:");
f877e3
+				dmi_cache_size("Installed Size", WORD(data + 0x09));
f877e3
 			if (h->length >= 0x17)
f877e3
-				dmi_cache_size_2(DWORD(data + 0x13));
f877e3
+				dmi_cache_size_2("Maximum Size", DWORD(data + 0x13));
f877e3
 			else
f877e3
-				dmi_cache_size(WORD(data + 0x07));
f877e3
-			printf("\n");
f877e3
+				dmi_cache_size("Maximum Size", WORD(data + 0x07));
f877e3
 			printf("\tSupported SRAM Types:");
f877e3
 			dmi_cache_types(WORD(data + 0x0B), "\n\t\t");
f877e3
 			printf("\n");
f877e3
@@ -4184,73 +4233,71 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 			dmi_cache_types(WORD(data + 0x0D), " ");
f877e3
 			printf("\n");
f877e3
 			if (h->length < 0x13) break;
f877e3
-			printf("\tSpeed:");
f877e3
-			dmi_memory_module_speed(data[0x0F]);
f877e3
-			printf("\n");
f877e3
-			printf("\tError Correction Type: %s\n",
f877e3
+			dmi_memory_module_speed("Speed", data[0x0F]);
f877e3
+			pr_attr("Error Correction Type", "%s",
f877e3
 				dmi_cache_ec_type(data[0x10]));
f877e3
-			printf("\tSystem Type: %s\n",
f877e3
+			pr_attr("System Type", "%s",
f877e3
 				dmi_cache_type(data[0x11]));
f877e3
-			printf("\tAssociativity: %s\n",
f877e3
+			pr_attr("Associativity", "%s",
f877e3
 				dmi_cache_associativity(data[0x12]));
f877e3
 			break;
f877e3
 
f877e3
 		case 8: /* 7.9 Port Connector Information */
f877e3
 			pr_handle_name("Port Connector Information");
f877e3
 			if (h->length < 0x09) break;
f877e3
-			printf("\tInternal Reference Designator: %s\n",
f877e3
+			pr_attr("Internal Reference Designator", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tInternal Connector Type: %s\n",
f877e3
+			pr_attr("Internal Connector Type", "%s",
f877e3
 				dmi_port_connector_type(data[0x05]));
f877e3
-			printf("\tExternal Reference Designator: %s\n",
f877e3
+			pr_attr("External Reference Designator", "%s",
f877e3
 				dmi_string(h, data[0x06]));
f877e3
-			printf("\tExternal Connector Type: %s\n",
f877e3
+			pr_attr("External Connector Type", "%s",
f877e3
 				dmi_port_connector_type(data[0x07]));
f877e3
-			printf("\tPort Type: %s\n",
f877e3
+			pr_attr("Port Type", "%s",
f877e3
 				dmi_port_type(data[0x08]));
f877e3
 			break;
f877e3
 
f877e3
 		case 9: /* 7.10 System Slots */
f877e3
 			pr_handle_name("System Slot Information");
f877e3
 			if (h->length < 0x0C) break;
f877e3
-			printf("\tDesignation: %s\n",
f877e3
+			pr_attr("Designation", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tType: %s%s\n",
f877e3
+			pr_attr("Type", "%s%s",
f877e3
 				dmi_slot_bus_width(data[0x06]),
f877e3
 				dmi_slot_type(data[0x05]));
f877e3
-			printf("\tCurrent Usage: %s\n",
f877e3
+			pr_attr("Current Usage", "%s",
f877e3
 				dmi_slot_current_usage(data[0x07]));
f877e3
-			printf("\tLength: %s\n",
f877e3
+			pr_attr("Length", "%s",
f877e3
 				dmi_slot_length(data[0x08]));
f877e3
-			dmi_slot_id(data[0x09], data[0x0A], data[0x05], "\t");
f877e3
+			dmi_slot_id(data[0x09], data[0x0A], data[0x05]);
f877e3
 			printf("\tCharacteristics:");
f877e3
 			if (h->length < 0x0D)
f877e3
 				dmi_slot_characteristics(data[0x0B], 0x00, "\t\t");
f877e3
 			else
f877e3
 				dmi_slot_characteristics(data[0x0B], data[0x0C], "\t\t");
f877e3
 			if (h->length < 0x11) break;
f877e3
-			dmi_slot_segment_bus_func(WORD(data + 0x0D), data[0x0F], data[0x10], "\t");
f877e3
+			dmi_slot_segment_bus_func(WORD(data + 0x0D), data[0x0F], data[0x10]);
f877e3
 			if (h->length < 0x13) break;
f877e3
-			printf("\tData Bus Width: %u\n", data[0x11]);
f877e3
-			printf("\tPeer Devices: %u\n", data[0x12]);
f877e3
+			pr_attr("Data Bus Width", "%u", data[0x11]);
f877e3
+			pr_attr("Peer Devices", "%u", data[0x12]);
f877e3
 			if (h->length - 0x13 >= data[0x12] * 5)
f877e3
-				dmi_slot_peers(data[0x12], data + 0x13, "\t");
f877e3
+				dmi_slot_peers(data[0x12], data + 0x13);
f877e3
 			break;
f877e3
 
f877e3
 		case 10: /* 7.11 On Board Devices Information */
f877e3
-			dmi_on_board_devices(h, "");
f877e3
+			dmi_on_board_devices(h);
f877e3
 			break;
f877e3
 
f877e3
 		case 11: /* 7.12 OEM Strings */
f877e3
 			pr_handle_name("OEM Strings");
f877e3
 			if (h->length < 0x05) break;
f877e3
-			dmi_oem_strings(h, "\t");
f877e3
+			dmi_oem_strings(h);
f877e3
 			break;
f877e3
 
f877e3
 		case 12: /* 7.13 System Configuration Options */
f877e3
 			pr_handle_name("System Configuration Options");
f877e3
 			if (h->length < 0x05) break;
f877e3
-			dmi_system_configuration_options(h, "\t");
f877e3
+			dmi_system_configuration_options(h);
f877e3
 			break;
f877e3
 
f877e3
 		case 13: /* 7.14 BIOS Language Information */
f877e3
@@ -4258,19 +4305,19 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 			if (h->length < 0x16) break;
f877e3
 			if (ver >= 0x0201)
f877e3
 			{
f877e3
-				printf("\tLanguage Description Format: %s\n",
f877e3
+				pr_attr("Language Description Format", "%s",
f877e3
 					dmi_bios_language_format(data[0x05]));
f877e3
 			}
f877e3
 			printf("\tInstallable Languages: %u\n", data[0x04]);
f877e3
 			dmi_bios_languages(h, "\t\t");
f877e3
-			printf("\tCurrently Installed Language: %s\n",
f877e3
+			pr_attr("Currently Installed Language", "%s",
f877e3
 				dmi_string(h, data[0x15]));
f877e3
 			break;
f877e3
 
f877e3
 		case 14: /* 7.15 Group Associations */
f877e3
 			pr_handle_name("Group Associations");
f877e3
 			if (h->length < 0x05) break;
f877e3
-			printf("\tName: %s\n",
f877e3
+			pr_attr("Name", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
 			printf("\tItems: %u\n",
f877e3
 				(h->length - 0x05) / 3);
f877e3
@@ -4280,51 +4327,47 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 		case 15: /* 7.16 System Event Log */
f877e3
 			pr_handle_name("System Event Log");
f877e3
 			if (h->length < 0x14) break;
f877e3
-			printf("\tArea Length: %u bytes\n",
f877e3
+			pr_attr("Area Length", "%u bytes",
f877e3
 				WORD(data + 0x04));
f877e3
-			printf("\tHeader Start Offset: 0x%04X\n",
f877e3
+			pr_attr("Header Start Offset", "0x%04X",
f877e3
 				WORD(data + 0x06));
f877e3
 			if (WORD(data + 0x08) - WORD(data + 0x06))
f877e3
-				printf("\tHeader Length: %u byte%s\n",
f877e3
+				pr_attr("Header Length", "%u byte%s",
f877e3
 					WORD(data + 0x08) - WORD(data + 0x06),
f877e3
 					WORD(data + 0x08) - WORD(data + 0x06) > 1 ? "s" : "");
f877e3
-			printf("\tData Start Offset: 0x%04X\n",
f877e3
+			pr_attr("Data Start Offset", "0x%04X",
f877e3
 				WORD(data + 0x08));
f877e3
-			printf("\tAccess Method: %s\n",
f877e3
+			pr_attr("Access Method", "%s",
f877e3
 				dmi_event_log_method(data[0x0A]));
f877e3
-			printf("\tAccess Address:");
f877e3
 			dmi_event_log_address(data[0x0A], data + 0x10);
f877e3
-			printf("\n");
f877e3
-			printf("\tStatus:");
f877e3
 			dmi_event_log_status(data[0x0B]);
f877e3
-			printf("\n");
f877e3
-			printf("\tChange Token: 0x%08X\n",
f877e3
+			pr_attr("Change Token", "0x%08X",
f877e3
 				DWORD(data + 0x0C));
f877e3
 			if (h->length < 0x17) break;
f877e3
-			printf("\tHeader Format: %s\n",
f877e3
+			pr_attr("Header Format", "%s",
f877e3
 				dmi_event_log_header_type(data[0x14]));
f877e3
-			printf("\tSupported Log Type Descriptors: %u\n",
f877e3
+			pr_attr("Supported Log Type Descriptors", "%u",
f877e3
 				data[0x15]);
f877e3
 			if (h->length < 0x17 + data[0x15] * data[0x16]) break;
f877e3
-			dmi_event_log_descriptors(data[0x15], data[0x16], data + 0x17, "\t");
f877e3
+			dmi_event_log_descriptors(data[0x15], data[0x16], data + 0x17);
f877e3
 			break;
f877e3
 
f877e3
 		case 16: /* 7.17 Physical Memory Array */
f877e3
 			pr_handle_name("Physical Memory Array");
f877e3
 			if (h->length < 0x0F) break;
f877e3
-			printf("\tLocation: %s\n",
f877e3
+			pr_attr("Location", "%s",
f877e3
 				dmi_memory_array_location(data[0x04]));
f877e3
-			printf("\tUse: %s\n",
f877e3
+			pr_attr("Use", "%s",
f877e3
 				dmi_memory_array_use(data[0x05]));
f877e3
-			printf("\tError Correction Type: %s\n",
f877e3
+			pr_attr("Error Correction Type", "%s",
f877e3
 				dmi_memory_array_ec_type(data[0x06]));
f877e3
-			printf("\tMaximum Capacity:");
f877e3
 			if (DWORD(data + 0x07) == 0x80000000)
f877e3
 			{
f877e3
 				if (h->length < 0x17)
f877e3
-					printf(" Unknown");
f877e3
+					pr_attr("Maximum Capacity", "Unknown");
f877e3
 				else
f877e3
-					dmi_print_memory_size(QWORD(data + 0x0F), 0);
f877e3
+					dmi_print_memory_size("Maximum Capacity",
f877e3
+							      QWORD(data + 0x0F), 0);
f877e3
 			}
f877e3
 			else
f877e3
 			{
f877e3
@@ -4332,16 +4375,12 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 
f877e3
 				capacity.h = 0;
f877e3
 				capacity.l = DWORD(data + 0x07);
f877e3
-				dmi_print_memory_size(capacity, 1);
f877e3
+				dmi_print_memory_size("Maximum Capacity",
f877e3
+						      capacity, 1);
f877e3
 			}
f877e3
-			printf("\n");
f877e3
 			if (!(opt.flags & FLAG_QUIET))
f877e3
-			{
f877e3
-				printf("\tError Information Handle:");
f877e3
 				dmi_memory_array_error_handle(WORD(data + 0x0B));
f877e3
-				printf("\n");
f877e3
-			}
f877e3
-			printf("\tNumber Of Devices: %u\n",
f877e3
+			pr_attr("Number Of Devices", "%u",
f877e3
 				WORD(data + 0x0D));
f877e3
 			break;
f877e3
 
f877e3
@@ -4350,132 +4389,91 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 			if (h->length < 0x15) break;
f877e3
 			if (!(opt.flags & FLAG_QUIET))
f877e3
 			{
f877e3
-				printf("\tArray Handle: 0x%04X\n",
f877e3
+				pr_attr("Array Handle", "0x%04X",
f877e3
 					WORD(data + 0x04));
f877e3
-				printf("\tError Information Handle:");
f877e3
 				dmi_memory_array_error_handle(WORD(data + 0x06));
f877e3
-				printf("\n");
f877e3
 			}
f877e3
-			printf("\tTotal Width:");
f877e3
-			dmi_memory_device_width(WORD(data + 0x08));
f877e3
-			printf("\n");
f877e3
-			printf("\tData Width:");
f877e3
-			dmi_memory_device_width(WORD(data + 0x0A));
f877e3
-			printf("\n");
f877e3
-			printf("\tSize:");
f877e3
+			dmi_memory_device_width("Total Width", WORD(data + 0x08));
f877e3
+			dmi_memory_device_width("Data Width", WORD(data + 0x0A));
f877e3
 			if (h->length >= 0x20 && WORD(data + 0x0C) == 0x7FFF)
f877e3
 				dmi_memory_device_extended_size(DWORD(data + 0x1C));
f877e3
 			else
f877e3
 				dmi_memory_device_size(WORD(data + 0x0C));
f877e3
-			printf("\n");
f877e3
-			printf("\tForm Factor: %s\n",
f877e3
+			pr_attr("Form Factor", "%s",
f877e3
 				dmi_memory_device_form_factor(data[0x0E]));
f877e3
-			printf("\tSet:");
f877e3
 			dmi_memory_device_set(data[0x0F]);
f877e3
-			printf("\n");
f877e3
-			printf("\tLocator: %s\n",
f877e3
+			pr_attr("Locator", "%s",
f877e3
 				dmi_string(h, data[0x10]));
f877e3
-			printf("\tBank Locator: %s\n",
f877e3
+			pr_attr("Bank Locator", "%s",
f877e3
 				dmi_string(h, data[0x11]));
f877e3
-			printf("\tType: %s\n",
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_memory_device_type(data[0x12]));
f877e3
-			printf("\tType Detail:");
f877e3
 			dmi_memory_device_type_detail(WORD(data + 0x13));
f877e3
-			printf("\n");
f877e3
 			if (h->length < 0x17) break;
f877e3
-			printf("\tSpeed:");
f877e3
-			dmi_memory_device_speed(WORD(data + 0x15));
f877e3
-			printf("\n");
f877e3
+			dmi_memory_device_speed("Speed", WORD(data + 0x15));
f877e3
 			if (h->length < 0x1B) break;
f877e3
-			printf("\tManufacturer: %s\n",
f877e3
+			pr_attr("Manufacturer", "%s",
f877e3
 				dmi_string(h, data[0x17]));
f877e3
-			printf("\tSerial Number: %s\n",
f877e3
+			pr_attr("Serial Number", "%s",
f877e3
 				dmi_string(h, data[0x18]));
f877e3
-			printf("\tAsset Tag: %s\n",
f877e3
+			pr_attr("Asset Tag", "%s",
f877e3
 				dmi_string(h, data[0x19]));
f877e3
-			printf("\tPart Number: %s\n",
f877e3
+			pr_attr("Part Number", "%s",
f877e3
 				dmi_string(h, data[0x1A]));
f877e3
 			if (h->length < 0x1C) break;
f877e3
-			printf("\tRank: ");
f877e3
 			if ((data[0x1B] & 0x0F) == 0)
f877e3
-				printf("Unknown");
f877e3
+				pr_attr("Rank", "Unknown");
f877e3
 			else
f877e3
-				printf("%u", data[0x1B] & 0x0F);
f877e3
-			printf("\n");
f877e3
+				pr_attr("Rank", "%u", data[0x1B] & 0x0F);
f877e3
 			if (h->length < 0x22) break;
f877e3
-			printf("\tConfigured Memory Speed:");
f877e3
-			dmi_memory_device_speed(WORD(data + 0x20));
f877e3
-			printf("\n");
f877e3
+			dmi_memory_device_speed("Configured Memory Speed",
f877e3
+						WORD(data + 0x20));
f877e3
 			if (h->length < 0x28) break;
f877e3
-			printf("\tMinimum Voltage:");
f877e3
-			dmi_memory_voltage_value(WORD(data + 0x22));
f877e3
-			printf("\n");
f877e3
-			printf("\tMaximum Voltage:");
f877e3
-			dmi_memory_voltage_value(WORD(data + 0x24));
f877e3
-			printf("\n");
f877e3
-			printf("\tConfigured Voltage:");
f877e3
-			dmi_memory_voltage_value(WORD(data + 0x26));
f877e3
-			printf("\n");
f877e3
+			dmi_memory_voltage_value("Minimum Voltage",
f877e3
+						 WORD(data + 0x22));
f877e3
+			dmi_memory_voltage_value("Maximum Voltage",
f877e3
+						 WORD(data + 0x24));
f877e3
+			dmi_memory_voltage_value("Configured Voltage",
f877e3
+						 WORD(data + 0x26));
f877e3
 			if (h->length < 0x34) break;
f877e3
-			printf("\tMemory Technology:");
f877e3
 			dmi_memory_technology(data[0x28]);
f877e3
-			printf("\n");
f877e3
-			printf("\tMemory Operating Mode Capability:");
f877e3
 			dmi_memory_operating_mode_capability(WORD(data + 0x29));
f877e3
-			printf("\n");
f877e3
-			printf("\tFirmware Version: %s\n",
f877e3
+			pr_attr("Firmware Version", "%s",
f877e3
 				dmi_string(h, data[0x2B]));
f877e3
-			printf("\tModule Manufacturer ID:");
f877e3
-			dmi_memory_manufacturer_id(WORD(data + 0x2C));
f877e3
-			printf("\n");
f877e3
-			printf("\tModule Product ID:");
f877e3
-			dmi_memory_product_id(WORD(data + 0x2E));
f877e3
-			printf("\n");
f877e3
-			printf("\tMemory Subsystem Controller Manufacturer ID:");
f877e3
-			dmi_memory_manufacturer_id(WORD(data + 0x30));
f877e3
-			printf("\n");
f877e3
-			printf("\tMemory Subsystem Controller Product ID:");
f877e3
-			dmi_memory_product_id(WORD(data + 0x32));
f877e3
-			printf("\n");
f877e3
+			dmi_memory_manufacturer_id("Module Manufacturer ID",
f877e3
+						   WORD(data + 0x2C));
f877e3
+			dmi_memory_product_id("Module Product ID",
f877e3
+					      WORD(data + 0x2E));
f877e3
+			dmi_memory_manufacturer_id("Memory Subsystem Controller Manufacturer ID",
f877e3
+						   WORD(data + 0x30));
f877e3
+			dmi_memory_product_id("Memory Subsystem Controller Product ID",
f877e3
+					      WORD(data + 0x32));
f877e3
 			if (h->length < 0x3C) break;
f877e3
-			printf("\tNon-Volatile Size:");
f877e3
-			dmi_memory_size(QWORD(data + 0x34));
f877e3
-			printf("\n");
f877e3
+			dmi_memory_size("Non-Volatile Size", QWORD(data + 0x34));
f877e3
 			if (h->length < 0x44) break;
f877e3
-			printf("\tVolatile Size:");
f877e3
-			dmi_memory_size(QWORD(data + 0x3C));
f877e3
-			printf("\n");
f877e3
+			dmi_memory_size("Volatile Size", QWORD(data + 0x3C));
f877e3
 			if (h->length < 0x4C) break;
f877e3
-			printf("\tCache Size:");
f877e3
-			dmi_memory_size(QWORD(data + 0x44));
f877e3
-			printf("\n");
f877e3
+			dmi_memory_size("Cache Size", QWORD(data + 0x44));
f877e3
 			if (h->length < 0x54) break;
f877e3
-			printf("\tLogical Size:");
f877e3
-			dmi_memory_size(QWORD(data + 0x4C));
f877e3
-			printf("\n");
f877e3
+			dmi_memory_size("Logical Size", QWORD(data + 0x4C));
f877e3
 			break;
f877e3
 
f877e3
 		case 18: /* 7.19 32-bit Memory Error Information */
f877e3
 			pr_handle_name("32-bit Memory Error Information");
f877e3
 			if (h->length < 0x17) break;
f877e3
-			printf("\tType: %s\n",
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_memory_error_type(data[0x04]));
f877e3
-			printf("\tGranularity: %s\n",
f877e3
+			pr_attr("Granularity", "%s",
f877e3
 				dmi_memory_error_granularity(data[0x05]));
f877e3
-			printf("\tOperation: %s\n",
f877e3
+			pr_attr("Operation", "%s",
f877e3
 				dmi_memory_error_operation(data[0x06]));
f877e3
-			printf("\tVendor Syndrome:");
f877e3
 			dmi_memory_error_syndrome(DWORD(data + 0x07));
f877e3
-			printf("\n");
f877e3
-			printf("\tMemory Array Address:");
f877e3
-			dmi_32bit_memory_error_address(DWORD(data + 0x0B));
f877e3
-			printf("\n");
f877e3
-			printf("\tDevice Address:");
f877e3
-			dmi_32bit_memory_error_address(DWORD(data + 0x0F));
f877e3
-			printf("\n");
f877e3
-			printf("\tResolution:");
f877e3
-			dmi_32bit_memory_error_address(DWORD(data + 0x13));
f877e3
-			printf("\n");
f877e3
+			dmi_32bit_memory_error_address("Memory Array Address",
f877e3
+						       DWORD(data + 0x0B));
f877e3
+			dmi_32bit_memory_error_address("Device Address",
f877e3
+						       DWORD(data + 0x0F));
f877e3
+			dmi_32bit_memory_error_address("Resolution",
f877e3
+						       DWORD(data + 0x13));
f877e3
 			break;
f877e3
 
f877e3
 		case 19: /* 7.20 Memory Array Mapped Address */
f877e3
@@ -4488,29 +4486,26 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 				start = QWORD(data + 0x0F);
f877e3
 				end = QWORD(data + 0x17);
f877e3
 
f877e3
-				printf("\tStarting Address: 0x%08X%08Xk\n",
f877e3
+				pr_attr("Starting Address", "0x%08X%08Xk",
f877e3
 					start.h, start.l);
f877e3
-				printf("\tEnding Address: 0x%08X%08Xk\n",
f877e3
+				pr_attr("Ending Address", "0x%08X%08Xk",
f877e3
 					end.h, end.l);
f877e3
-				printf("\tRange Size:");
f877e3
 				dmi_mapped_address_extended_size(start, end);
f877e3
 			}
f877e3
 			else
f877e3
 			{
f877e3
-				printf("\tStarting Address: 0x%08X%03X\n",
f877e3
+				pr_attr("Starting Address", "0x%08X%03X",
f877e3
 					DWORD(data + 0x04) >> 2,
f877e3
 					(DWORD(data + 0x04) & 0x3) << 10);
f877e3
-				printf("\tEnding Address: 0x%08X%03X\n",
f877e3
+				pr_attr("Ending Address", "0x%08X%03X",
f877e3
 					DWORD(data + 0x08) >> 2,
f877e3
 					((DWORD(data + 0x08) & 0x3) << 10) + 0x3FF);
f877e3
-				printf("\tRange Size:");
f877e3
 				dmi_mapped_address_size(DWORD(data + 0x08) - DWORD(data + 0x04) + 1);
f877e3
 			}
f877e3
-			printf("\n");
f877e3
 			if (!(opt.flags & FLAG_QUIET))
f877e3
-				printf("\tPhysical Array Handle: 0x%04X\n",
f877e3
+				pr_attr("Physical Array Handle", "0x%04X",
f877e3
 					WORD(data + 0x0C));
f877e3
-			printf("\tPartition Width: %u\n",
f877e3
+			pr_attr("Partition Width", "%u",
f877e3
 				data[0x0E]);
f877e3
 			break;
f877e3
 
f877e3
@@ -4524,344 +4519,288 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 				start = QWORD(data + 0x13);
f877e3
 				end = QWORD(data + 0x1B);
f877e3
 
f877e3
-				printf("\tStarting Address: 0x%08X%08Xk\n",
f877e3
+				pr_attr("Starting Address", "0x%08X%08Xk",
f877e3
 					start.h, start.l);
f877e3
-				printf("\tEnding Address: 0x%08X%08Xk\n",
f877e3
+				pr_attr("Ending Address", "0x%08X%08Xk",
f877e3
 					end.h, end.l);
f877e3
-				printf("\tRange Size:");
f877e3
 				dmi_mapped_address_extended_size(start, end);
f877e3
 			}
f877e3
 			else
f877e3
 			{
f877e3
-				printf("\tStarting Address: 0x%08X%03X\n",
f877e3
+				pr_attr("Starting Address", "0x%08X%03X",
f877e3
 					DWORD(data + 0x04) >> 2,
f877e3
 					(DWORD(data + 0x04) & 0x3) << 10);
f877e3
-				printf("\tEnding Address: 0x%08X%03X\n",
f877e3
+				pr_attr("Ending Address", "0x%08X%03X",
f877e3
 					DWORD(data + 0x08) >> 2,
f877e3
 					((DWORD(data + 0x08) & 0x3) << 10) + 0x3FF);
f877e3
-				printf("\tRange Size:");
f877e3
 				dmi_mapped_address_size(DWORD(data + 0x08) - DWORD(data + 0x04) + 1);
f877e3
 			}
f877e3
-			printf("\n");
f877e3
 			if (!(opt.flags & FLAG_QUIET))
f877e3
 			{
f877e3
-				printf("\tPhysical Device Handle: 0x%04X\n",
f877e3
+				pr_attr("Physical Device Handle", "0x%04X",
f877e3
 					WORD(data + 0x0C));
f877e3
-				printf("\tMemory Array Mapped Address Handle: 0x%04X\n",
f877e3
+				pr_attr("Memory Array Mapped Address Handle", "0x%04X",
f877e3
 					WORD(data + 0x0E));
f877e3
 			}
f877e3
-			printf("\tPartition Row Position:");
f877e3
 			dmi_mapped_address_row_position(data[0x10]);
f877e3
-			printf("\n");
f877e3
-			dmi_mapped_address_interleave_position(data[0x11], "\t");
f877e3
-			dmi_mapped_address_interleaved_data_depth(data[0x12], "\t");
f877e3
+			dmi_mapped_address_interleave_position(data[0x11]);
f877e3
+			dmi_mapped_address_interleaved_data_depth(data[0x12]);
f877e3
 			break;
f877e3
 
f877e3
 		case 21: /* 7.22 Built-in Pointing Device */
f877e3
 			pr_handle_name("Built-in Pointing Device");
f877e3
 			if (h->length < 0x07) break;
f877e3
-			printf("\tType: %s\n",
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_pointing_device_type(data[0x04]));
f877e3
-			printf("\tInterface: %s\n",
f877e3
+			pr_attr("Interface", "%s",
f877e3
 				dmi_pointing_device_interface(data[0x05]));
f877e3
-			printf("\tButtons: %u\n",
f877e3
+			pr_attr("Buttons", "%u",
f877e3
 				data[0x06]);
f877e3
 			break;
f877e3
 
f877e3
 		case 22: /* 7.23 Portable Battery */
f877e3
 			pr_handle_name("Portable Battery");
f877e3
 			if (h->length < 0x10) break;
f877e3
-			printf("\tLocation: %s\n",
f877e3
+			pr_attr("Location", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tManufacturer: %s\n",
f877e3
+			pr_attr("Manufacturer", "%s",
f877e3
 				dmi_string(h, data[0x05]));
f877e3
 			if (data[0x06] || h->length < 0x1A)
f877e3
-				printf("\tManufacture Date: %s\n",
f877e3
+				pr_attr("Manufacture Date", "%s",
f877e3
 					dmi_string(h, data[0x06]));
f877e3
 			if (data[0x07] || h->length < 0x1A)
f877e3
-				printf("\tSerial Number: %s\n",
f877e3
+				pr_attr("Serial Number", "%s",
f877e3
 					dmi_string(h, data[0x07]));
f877e3
-			printf("\tName: %s\n",
f877e3
+			pr_attr("Name", "%s",
f877e3
 				dmi_string(h, data[0x08]));
f877e3
 			if (data[0x09] != 0x02 || h->length < 0x1A)
f877e3
-				printf("\tChemistry: %s\n",
f877e3
+				pr_attr("Chemistry", "%s",
f877e3
 					dmi_battery_chemistry(data[0x09]));
f877e3
-			printf("\tDesign Capacity:");
f877e3
 			if (h->length < 0x16)
f877e3
 				dmi_battery_capacity(WORD(data + 0x0A), 1);
f877e3
 			else
f877e3
 				dmi_battery_capacity(WORD(data + 0x0A), data[0x15]);
f877e3
-			printf("\n");
f877e3
-			printf("\tDesign Voltage:");
f877e3
 			dmi_battery_voltage(WORD(data + 0x0C));
f877e3
-			printf("\n");
f877e3
-			printf("\tSBDS Version: %s\n",
f877e3
+			pr_attr("SBDS Version", "%s",
f877e3
 				dmi_string(h, data[0x0E]));
f877e3
-			printf("\tMaximum Error:");
f877e3
 			dmi_battery_maximum_error(data[0x0F]);
f877e3
-			printf("\n");
f877e3
 			if (h->length < 0x1A) break;
f877e3
 			if (data[0x07] == 0)
f877e3
-				printf("\tSBDS Serial Number: %04X\n",
f877e3
+				pr_attr("SBDS Serial Number", "%04X",
f877e3
 					WORD(data + 0x10));
f877e3
 			if (data[0x06] == 0)
f877e3
-				printf("\tSBDS Manufacture Date: %u-%02u-%02u\n",
f877e3
+				pr_attr("SBDS Manufacture Date", "%u-%02u-%02u",
f877e3
 					1980 + (WORD(data + 0x12) >> 9),
f877e3
 					(WORD(data + 0x12) >> 5) & 0x0F,
f877e3
 					WORD(data + 0x12) & 0x1F);
f877e3
 			if (data[0x09] == 0x02)
f877e3
-				printf("\tSBDS Chemistry: %s\n",
f877e3
+				pr_attr("SBDS Chemistry", "%s",
f877e3
 					dmi_string(h, data[0x14]));
f877e3
-			printf("\tOEM-specific Information: 0x%08X\n",
f877e3
+			pr_attr("OEM-specific Information", "0x%08X",
f877e3
 				DWORD(data + 0x16));
f877e3
 			break;
f877e3
 
f877e3
 		case 23: /* 7.24 System Reset */
f877e3
 			pr_handle_name("System Reset");
f877e3
 			if (h->length < 0x0D) break;
f877e3
-			printf("\tStatus: %s\n",
f877e3
+			pr_attr("Status", "%s",
f877e3
 				data[0x04] & (1 << 0) ? "Enabled" : "Disabled");
f877e3
-			printf("\tWatchdog Timer: %s\n",
f877e3
+			pr_attr("Watchdog Timer", "%s",
f877e3
 				data[0x04] & (1 << 5) ? "Present" : "Not Present");
f877e3
 			if (!(data[0x04] & (1 << 5)))
f877e3
 				break;
f877e3
-			printf("\tBoot Option: %s\n",
f877e3
+			pr_attr("Boot Option", "%s",
f877e3
 				dmi_system_reset_boot_option((data[0x04] >> 1) & 0x3));
f877e3
-			printf("\tBoot Option On Limit: %s\n",
f877e3
+			pr_attr("Boot Option On Limit", "%s",
f877e3
 				dmi_system_reset_boot_option((data[0x04] >> 3) & 0x3));
f877e3
-			printf("\tReset Count:");
f877e3
-			dmi_system_reset_count(WORD(data + 0x05));
f877e3
-			printf("\n");
f877e3
-			printf("\tReset Limit:");
f877e3
-			dmi_system_reset_count(WORD(data + 0x07));
f877e3
-			printf("\n");
f877e3
-			printf("\tTimer Interval:");
f877e3
-			dmi_system_reset_timer(WORD(data + 0x09));
f877e3
-			printf("\n");
f877e3
-			printf("\tTimeout:");
f877e3
-			dmi_system_reset_timer(WORD(data + 0x0B));
f877e3
-			printf("\n");
f877e3
+			dmi_system_reset_count("Reset Count", WORD(data + 0x05));
f877e3
+			dmi_system_reset_count("Reset Limit", WORD(data + 0x07));
f877e3
+			dmi_system_reset_timer("Timer Interval", WORD(data + 0x09));
f877e3
+			dmi_system_reset_timer("Timeout", WORD(data + 0x0B));
f877e3
 			break;
f877e3
 
f877e3
 		case 24: /* 7.25 Hardware Security */
f877e3
 			pr_handle_name("Hardware Security");
f877e3
 			if (h->length < 0x05) break;
f877e3
-			printf("\tPower-On Password Status: %s\n",
f877e3
+			pr_attr("Power-On Password Status", "%s",
f877e3
 				dmi_hardware_security_status(data[0x04] >> 6));
f877e3
-			printf("\tKeyboard Password Status: %s\n",
f877e3
+			pr_attr("Keyboard Password Status", "%s",
f877e3
 				dmi_hardware_security_status((data[0x04] >> 4) & 0x3));
f877e3
-			printf("\tAdministrator Password Status: %s\n",
f877e3
+			pr_attr("Administrator Password Status", "%s",
f877e3
 				dmi_hardware_security_status((data[0x04] >> 2) & 0x3));
f877e3
-			printf("\tFront Panel Reset Status: %s\n",
f877e3
+			pr_attr("Front Panel Reset Status", "%s",
f877e3
 				dmi_hardware_security_status(data[0x04] & 0x3));
f877e3
 			break;
f877e3
 
f877e3
 		case 25: /* 7.26 System Power Controls */
f877e3
 			pr_handle_name("System Power Controls");
f877e3
 			if (h->length < 0x09) break;
f877e3
-			printf("\tNext Scheduled Power-on:");
f877e3
 			dmi_power_controls_power_on(data + 0x04);
f877e3
-			printf("\n");
f877e3
 			break;
f877e3
 
f877e3
 		case 26: /* 7.27 Voltage Probe */
f877e3
 			pr_handle_name("Voltage Probe");
f877e3
 			if (h->length < 0x14) break;
f877e3
-			printf("\tDescription: %s\n",
f877e3
+			pr_attr("Description", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tLocation: %s\n",
f877e3
+			pr_attr("Location", "%s",
f877e3
 				dmi_voltage_probe_location(data[0x05] & 0x1f));
f877e3
-			printf("\tStatus: %s\n",
f877e3
+			pr_attr("Status", "%s",
f877e3
 				dmi_probe_status(data[0x05] >> 5));
f877e3
-			printf("\tMaximum Value:");
f877e3
-			dmi_voltage_probe_value(WORD(data + 0x06));
f877e3
-			printf("\n");
f877e3
-			printf("\tMinimum Value:");
f877e3
-			dmi_voltage_probe_value(WORD(data + 0x08));
f877e3
-			printf("\n");
f877e3
-			printf("\tResolution:");
f877e3
+			dmi_voltage_probe_value("Maximum Value", WORD(data + 0x06));
f877e3
+			dmi_voltage_probe_value("Minimum Value", WORD(data + 0x08));
f877e3
 			dmi_voltage_probe_resolution(WORD(data + 0x0A));
f877e3
-			printf("\n");
f877e3
-			printf("\tTolerance:");
f877e3
-			dmi_voltage_probe_value(WORD(data + 0x0C));
f877e3
-			printf("\n");
f877e3
-			printf("\tAccuracy:");
f877e3
+			dmi_voltage_probe_value("Tolerance", WORD(data + 0x0C));
f877e3
 			dmi_probe_accuracy(WORD(data + 0x0E));
f877e3
-			printf("\n");
f877e3
-			printf("\tOEM-specific Information: 0x%08X\n",
f877e3
+			pr_attr("OEM-specific Information", "0x%08X",
f877e3
 				DWORD(data + 0x10));
f877e3
 			if (h->length < 0x16) break;
f877e3
-			printf("\tNominal Value:");
f877e3
-			dmi_voltage_probe_value(WORD(data + 0x14));
f877e3
-			printf("\n");
f877e3
+			dmi_voltage_probe_value("Nominal Value", WORD(data + 0x14));
f877e3
 			break;
f877e3
 
f877e3
 		case 27: /* 7.28 Cooling Device */
f877e3
 			pr_handle_name("Cooling Device");
f877e3
 			if (h->length < 0x0C) break;
f877e3
 			if (!(opt.flags & FLAG_QUIET) && WORD(data + 0x04) != 0xFFFF)
f877e3
-				printf("\tTemperature Probe Handle: 0x%04X\n",
f877e3
+				pr_attr("Temperature Probe Handle", "0x%04X",
f877e3
 					WORD(data + 0x04));
f877e3
-			printf("\tType: %s\n",
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_cooling_device_type(data[0x06] & 0x1f));
f877e3
-			printf("\tStatus: %s\n",
f877e3
+			pr_attr("Status", "%s",
f877e3
 				dmi_probe_status(data[0x06] >> 5));
f877e3
 			if (data[0x07] != 0x00)
f877e3
-				printf("\tCooling Unit Group: %u\n",
f877e3
+				pr_attr("Cooling Unit Group", "%u",
f877e3
 					data[0x07]);
f877e3
-			printf("\tOEM-specific Information: 0x%08X\n",
f877e3
+			pr_attr("OEM-specific Information", "0x%08X",
f877e3
 				DWORD(data + 0x08));
f877e3
 			if (h->length < 0x0E) break;
f877e3
-			printf("\tNominal Speed:");
f877e3
 			dmi_cooling_device_speed(WORD(data + 0x0C));
f877e3
-			printf("\n");
f877e3
 			if (h->length < 0x0F) break;
f877e3
-			printf("\tDescription: %s\n", dmi_string(h, data[0x0E]));
f877e3
+			pr_attr("Description", "%s", dmi_string(h, data[0x0E]));
f877e3
 			break;
f877e3
 
f877e3
 		case 28: /* 7.29 Temperature Probe */
f877e3
 			pr_handle_name("Temperature Probe");
f877e3
 			if (h->length < 0x14) break;
f877e3
-			printf("\tDescription: %s\n",
f877e3
+			pr_attr("Description", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tLocation: %s\n",
f877e3
+			pr_attr("Location", "%s",
f877e3
 				dmi_temperature_probe_location(data[0x05] & 0x1F));
f877e3
-			printf("\tStatus: %s\n",
f877e3
+			pr_attr("Status", "%s",
f877e3
 				dmi_probe_status(data[0x05] >> 5));
f877e3
-			printf("\tMaximum Value:");
f877e3
-			dmi_temperature_probe_value(WORD(data + 0x06));
f877e3
-			printf("\n");
f877e3
-			printf("\tMinimum Value:");
f877e3
-			dmi_temperature_probe_value(WORD(data + 0x08));
f877e3
-			printf("\n");
f877e3
-			printf("\tResolution:");
f877e3
+			dmi_temperature_probe_value("Maximum Value",
f877e3
+						    WORD(data + 0x06));
f877e3
+			dmi_temperature_probe_value("Minimum Value",
f877e3
+						    WORD(data + 0x08));
f877e3
 			dmi_temperature_probe_resolution(WORD(data + 0x0A));
f877e3
-			printf("\n");
f877e3
-			printf("\tTolerance:");
f877e3
-			dmi_temperature_probe_value(WORD(data + 0x0C));
f877e3
-			printf("\n");
f877e3
-			printf("\tAccuracy:");
f877e3
+			dmi_temperature_probe_value("Tolerance",
f877e3
+						    WORD(data + 0x0C));
f877e3
 			dmi_probe_accuracy(WORD(data + 0x0E));
f877e3
-			printf("\n");
f877e3
-			printf("\tOEM-specific Information: 0x%08X\n",
f877e3
+			pr_attr("OEM-specific Information", "0x%08X",
f877e3
 				DWORD(data + 0x10));
f877e3
 			if (h->length < 0x16) break;
f877e3
-			printf("\tNominal Value:");
f877e3
-			dmi_temperature_probe_value(WORD(data + 0x14));
f877e3
-			printf("\n");
f877e3
+			dmi_temperature_probe_value("Nominal Value",
f877e3
+						    WORD(data + 0x14));
f877e3
 			break;
f877e3
 
f877e3
 		case 29: /* 7.30 Electrical Current Probe */
f877e3
 			pr_handle_name("Electrical Current Probe");
f877e3
 			if (h->length < 0x14) break;
f877e3
-			printf("\tDescription: %s\n",
f877e3
+			pr_attr("Description", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tLocation: %s\n",
f877e3
+			pr_attr("Location", "%s",
f877e3
 				dmi_voltage_probe_location(data[5] & 0x1F));
f877e3
-			printf("\tStatus: %s\n",
f877e3
+			pr_attr("Status", "%s",
f877e3
 				dmi_probe_status(data[0x05] >> 5));
f877e3
-			printf("\tMaximum Value:");
f877e3
-			dmi_current_probe_value(WORD(data + 0x06));
f877e3
-			printf("\n");
f877e3
-			printf("\tMinimum Value:");
f877e3
-			dmi_current_probe_value(WORD(data + 0x08));
f877e3
-			printf("\n");
f877e3
-			printf("\tResolution:");
f877e3
+			dmi_current_probe_value("Maximum Value",
f877e3
+						WORD(data + 0x06));
f877e3
+			dmi_current_probe_value("Minimum Value",
f877e3
+						WORD(data + 0x08));
f877e3
 			dmi_current_probe_resolution(WORD(data + 0x0A));
f877e3
-			printf("\n");
f877e3
-			printf("\tTolerance:");
f877e3
-			dmi_current_probe_value(WORD(data + 0x0C));
f877e3
-			printf("\n");
f877e3
-			printf("\tAccuracy:");
f877e3
+			dmi_current_probe_value("Tolerance",
f877e3
+						WORD(data + 0x0C));
f877e3
 			dmi_probe_accuracy(WORD(data + 0x0E));
f877e3
-			printf("\n");
f877e3
-			printf("\tOEM-specific Information: 0x%08X\n",
f877e3
+			pr_attr("OEM-specific Information", "0x%08X",
f877e3
 				DWORD(data + 0x10));
f877e3
 			if (h->length < 0x16) break;
f877e3
-			printf("\tNominal Value:");
f877e3
-			dmi_current_probe_value(WORD(data + 0x14));
f877e3
-			printf("\n");
f877e3
+			dmi_current_probe_value("Nominal Value",
f877e3
+						WORD(data + 0x14));
f877e3
 			break;
f877e3
 
f877e3
 		case 30: /* 7.31 Out-of-band Remote Access */
f877e3
 			pr_handle_name("Out-of-band Remote Access");
f877e3
 			if (h->length < 0x06) break;
f877e3
-			printf("\tManufacturer Name: %s\n",
f877e3
+			pr_attr("Manufacturer Name", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tInbound Connection: %s\n",
f877e3
+			pr_attr("Inbound Connection", "%s",
f877e3
 				data[0x05] & (1 << 0) ? "Enabled" : "Disabled");
f877e3
-			printf("\tOutbound Connection: %s\n",
f877e3
+			pr_attr("Outbound Connection", "%s",
f877e3
 				data[0x05] & (1 << 1) ? "Enabled" : "Disabled");
f877e3
 			break;
f877e3
 
f877e3
 		case 31: /* 7.32 Boot Integrity Services Entry Point */
f877e3
 			pr_handle_name("Boot Integrity Services Entry Point");
f877e3
 			if (h->length < 0x1C) break;
f877e3
-			printf("\tChecksum: %s\n",
f877e3
+			pr_attr("Checksum", "%s",
f877e3
 				checksum(data, h->length) ? "OK" : "Invalid");
f877e3
-			printf("\t16-bit Entry Point Address: %04X:%04X\n",
f877e3
+			pr_attr("16-bit Entry Point Address", "%04X:%04X",
f877e3
 				DWORD(data + 0x08) >> 16,
f877e3
 				DWORD(data + 0x08) & 0xFFFF);
f877e3
-			printf("\t32-bit Entry Point Address: 0x%08X\n",
f877e3
+			pr_attr("32-bit Entry Point Address", "0x%08X",
f877e3
 				DWORD(data + 0x0C));
f877e3
 			break;
f877e3
 
f877e3
 		case 32: /* 7.33 System Boot Information */
f877e3
 			pr_handle_name("System Boot Information");
f877e3
 			if (h->length < 0x0B) break;
f877e3
-			printf("\tStatus: %s\n",
f877e3
+			pr_attr("Status", "%s",
f877e3
 				dmi_system_boot_status(data[0x0A]));
f877e3
 			break;
f877e3
 
f877e3
 		case 33: /* 7.34 64-bit Memory Error Information */
f877e3
 			pr_handle_name("64-bit Memory Error Information");
f877e3
 			if (h->length < 0x1F) break;
f877e3
-			printf("\tType: %s\n",
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_memory_error_type(data[0x04]));
f877e3
-			printf("\tGranularity: %s\n",
f877e3
+			pr_attr("Granularity", "%s",
f877e3
 				dmi_memory_error_granularity(data[0x05]));
f877e3
-			printf("\tOperation: %s\n",
f877e3
+			pr_attr("Operation", "%s",
f877e3
 				dmi_memory_error_operation(data[0x06]));
f877e3
-			printf("\tVendor Syndrome:");
f877e3
 			dmi_memory_error_syndrome(DWORD(data + 0x07));
f877e3
-			printf("\n");
f877e3
-			printf("\tMemory Array Address:");
f877e3
-			dmi_64bit_memory_error_address(QWORD(data + 0x0B));
f877e3
-			printf("\n");
f877e3
-			printf("\tDevice Address:");
f877e3
-			dmi_64bit_memory_error_address(QWORD(data + 0x13));
f877e3
-			printf("\n");
f877e3
-			printf("\tResolution:");
f877e3
-			dmi_32bit_memory_error_address(DWORD(data + 0x1B));
f877e3
-			printf("\n");
f877e3
+			dmi_64bit_memory_error_address("Memory Array Address",
f877e3
+						       QWORD(data + 0x0B));
f877e3
+			dmi_64bit_memory_error_address("Device Address",
f877e3
+						       QWORD(data + 0x13));
f877e3
+			dmi_32bit_memory_error_address("Resolution",
f877e3
+						       DWORD(data + 0x1B));
f877e3
 			break;
f877e3
 
f877e3
 		case 34: /* 7.35 Management Device */
f877e3
 			pr_handle_name("Management Device");
f877e3
 			if (h->length < 0x0B) break;
f877e3
-			printf("\tDescription: %s\n",
f877e3
+			pr_attr("Description", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
-			printf("\tType: %s\n",
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_management_device_type(data[0x05]));
f877e3
-			printf("\tAddress: 0x%08X\n",
f877e3
+			pr_attr("Address", "0x%08X",
f877e3
 				DWORD(data + 0x06));
f877e3
-			printf("\tAddress Type: %s\n",
f877e3
+			pr_attr("Address Type", "%s",
f877e3
 				dmi_management_device_address_type(data[0x0A]));
f877e3
 			break;
f877e3
 
f877e3
 		case 35: /* 7.36 Management Device Component */
f877e3
 			pr_handle_name("Management Device Component");
f877e3
 			if (h->length < 0x0B) break;
f877e3
-			printf("\tDescription: %s\n",
f877e3
+			pr_attr("Description", "%s",
f877e3
 				dmi_string(h, data[0x04]));
f877e3
 			if (!(opt.flags & FLAG_QUIET))
f877e3
 			{
f877e3
-				printf("\tManagement Device Handle: 0x%04X\n",
f877e3
+				pr_attr("Management Device Handle", "0x%04X",
f877e3
 					WORD(data + 0x05));
f877e3
-				printf("\tComponent Handle: 0x%04X\n",
f877e3
+				pr_attr("Component Handle", "0x%04X",
f877e3
 					WORD(data + 0x07));
f877e3
 				if (WORD(data + 0x09) != 0xFFFF)
f877e3
-					printf("\tThreshold Handle: 0x%04X\n",
f877e3
+					pr_attr("Threshold Handle", "0x%04X",
f877e3
 						WORD(data + 0x09));
f877e3
 			}
f877e3
 			break;
f877e3
@@ -4870,36 +4809,36 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 			pr_handle_name("Management Device Threshold Data");
f877e3
 			if (h->length < 0x10) break;
f877e3
 			if (WORD(data + 0x04) != 0x8000)
f877e3
-				printf("\tLower Non-critical Threshold: %d\n",
f877e3
+				pr_attr("Lower Non-critical Threshold", "%d",
f877e3
 					(i16)WORD(data + 0x04));
f877e3
 			if (WORD(data + 0x06) != 0x8000)
f877e3
-				printf("\tUpper Non-critical Threshold: %d\n",
f877e3
+				pr_attr("Upper Non-critical Threshold", "%d",
f877e3
 					(i16)WORD(data + 0x06));
f877e3
 			if (WORD(data + 0x08) != 0x8000)
f877e3
-				printf("\tLower Critical Threshold: %d\n",
f877e3
+				pr_attr("Lower Critical Threshold", "%d",
f877e3
 					(i16)WORD(data + 0x08));
f877e3
 			if (WORD(data + 0x0A) != 0x8000)
f877e3
-				printf("\tUpper Critical Threshold: %d\n",
f877e3
+				pr_attr("Upper Critical Threshold", "%d",
f877e3
 					(i16)WORD(data + 0x0A));
f877e3
 			if (WORD(data + 0x0C) != 0x8000)
f877e3
-				printf("\tLower Non-recoverable Threshold: %d\n",
f877e3
+				pr_attr("Lower Non-recoverable Threshold", "%d",
f877e3
 					(i16)WORD(data + 0x0C));
f877e3
 			if (WORD(data + 0x0E) != 0x8000)
f877e3
-				printf("\tUpper Non-recoverable Threshold: %d\n",
f877e3
+				pr_attr("Upper Non-recoverable Threshold", "%d",
f877e3
 					(i16)WORD(data + 0x0E));
f877e3
 			break;
f877e3
 
f877e3
 		case 37: /* 7.38 Memory Channel */
f877e3
 			pr_handle_name("Memory Channel");
f877e3
 			if (h->length < 0x07) break;
f877e3
-			printf("\tType: %s\n",
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_memory_channel_type(data[0x04]));
f877e3
-			printf("\tMaximal Load: %u\n",
f877e3
+			pr_attr("Maximal Load", "%u",
f877e3
 				data[0x05]);
f877e3
-			printf("\tDevices: %u\n",
f877e3
+			pr_attr("Devices", "%u",
f877e3
 				data[0x06]);
f877e3
 			if (h->length < 0x07 + 3 * data[0x06]) break;
f877e3
-			dmi_memory_channel_devices(data[0x06], data + 0x07, "\t");
f877e3
+			dmi_memory_channel_devices(data[0x06], data + 0x07);
f877e3
 			break;
f877e3
 
f877e3
 		case 38: /* 7.39 IPMI Device Information */
f877e3
@@ -4909,37 +4848,35 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 			 */
f877e3
 			pr_handle_name("IPMI Device Information");
f877e3
 			if (h->length < 0x10) break;
f877e3
-			printf("\tInterface Type: %s\n",
f877e3
+			pr_attr("Interface Type", "%s",
f877e3
 				dmi_ipmi_interface_type(data[0x04]));
f877e3
-			printf("\tSpecification Version: %u.%u\n",
f877e3
+			pr_attr("Specification Version", "%u.%u",
f877e3
 				data[0x05] >> 4, data[0x05] & 0x0F);
f877e3
-			printf("\tI2C Slave Address: 0x%02x\n",
f877e3
+			pr_attr("I2C Slave Address", "0x%02x",
f877e3
 				data[0x06] >> 1);
f877e3
 			if (data[0x07] != 0xFF)
f877e3
-				printf("\tNV Storage Device Address: %u\n",
f877e3
+				pr_attr("NV Storage Device Address", "%u",
f877e3
 					data[0x07]);
f877e3
 			else
f877e3
-				printf("\tNV Storage Device: Not Present\n");
f877e3
-			printf("\tBase Address: ");
f877e3
+				pr_attr("NV Storage Device", "Not Present");
f877e3
 			dmi_ipmi_base_address(data[0x04], data + 0x08,
f877e3
 				h->length < 0x11 ? 0 : (data[0x10] >> 4) & 1);
f877e3
-			printf("\n");
f877e3
 			if (h->length < 0x12) break;
f877e3
 			if (data[0x04] != 0x04)
f877e3
 			{
f877e3
-				printf("\tRegister Spacing: %s\n",
f877e3
+				pr_attr("Register Spacing", "%s",
f877e3
 					dmi_ipmi_register_spacing(data[0x10] >> 6));
f877e3
 				if (data[0x10] & (1 << 3))
f877e3
 				{
f877e3
-					printf("\tInterrupt Polarity: %s\n",
f877e3
+					pr_attr("Interrupt Polarity", "%s",
f877e3
 						data[0x10] & (1 << 1) ? "Active High" : "Active Low");
f877e3
-					printf("\tInterrupt Trigger Mode: %s\n",
f877e3
+					pr_attr("Interrupt Trigger Mode", "%s",
f877e3
 						data[0x10] & (1 << 0) ? "Level" : "Edge");
f877e3
 				}
f877e3
 			}
f877e3
 			if (data[0x11] != 0x00)
f877e3
 			{
f877e3
-				printf("\tInterrupt Number: %u\n",
f877e3
+				pr_attr("Interrupt Number", "%u",
f877e3
 					data[0x11]);
f877e3
 			}
f877e3
 			break;
f877e3
@@ -4948,51 +4885,47 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 			pr_handle_name("System Power Supply");
f877e3
 			if (h->length < 0x10) break;
f877e3
 			if (data[0x04] != 0x00)
f877e3
-				printf("\tPower Unit Group: %u\n",
f877e3
+				pr_attr("Power Unit Group", "%u",
f877e3
 					data[0x04]);
f877e3
-			printf("\tLocation: %s\n",
f877e3
+			pr_attr("Location", "%s",
f877e3
 				dmi_string(h, data[0x05]));
f877e3
-			printf("\tName: %s\n",
f877e3
+			pr_attr("Name", "%s",
f877e3
 				dmi_string(h, data[0x06]));
f877e3
-			printf("\tManufacturer: %s\n",
f877e3
+			pr_attr("Manufacturer", "%s",
f877e3
 				dmi_string(h, data[0x07]));
f877e3
-			printf("\tSerial Number: %s\n",
f877e3
+			pr_attr("Serial Number", "%s",
f877e3
 				dmi_string(h, data[0x08]));
f877e3
-			printf("\tAsset Tag: %s\n",
f877e3
+			pr_attr("Asset Tag", "%s",
f877e3
 				dmi_string(h, data[0x09]));
f877e3
-			printf("\tModel Part Number: %s\n",
f877e3
+			pr_attr("Model Part Number", "%s",
f877e3
 				dmi_string(h, data[0x0A]));
f877e3
-			printf("\tRevision: %s\n",
f877e3
+			pr_attr("Revision", "%s",
f877e3
 				dmi_string(h, data[0x0B]));
f877e3
-			printf("\tMax Power Capacity:");
f877e3
 			dmi_power_supply_power(WORD(data + 0x0C));
f877e3
-			printf("\n");
f877e3
-			printf("\tStatus:");
f877e3
 			if (WORD(data + 0x0E) & (1 << 1))
f877e3
-				printf(" Present, %s",
f877e3
+				pr_attr("Status", "Present, %s",
f877e3
 					dmi_power_supply_status((WORD(data + 0x0E) >> 7) & 0x07));
f877e3
 			else
f877e3
-				printf(" Not Present");
f877e3
-			printf("\n");
f877e3
-			printf("\tType: %s\n",
f877e3
+				pr_attr("Status", "Not Present");
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_power_supply_type((WORD(data + 0x0E) >> 10) & 0x0F));
f877e3
-			printf("\tInput Voltage Range Switching: %s\n",
f877e3
+			pr_attr("Input Voltage Range Switching", "%s",
f877e3
 				dmi_power_supply_range_switching((WORD(data + 0x0E) >> 3) & 0x0F));
f877e3
-			printf("\tPlugged: %s\n",
f877e3
+			pr_attr("Plugged", "%s",
f877e3
 				WORD(data + 0x0E) & (1 << 2) ? "No" : "Yes");
f877e3
-			printf("\tHot Replaceable: %s\n",
f877e3
+			pr_attr("Hot Replaceable", "%s",
f877e3
 				WORD(data + 0x0E) & (1 << 0) ? "Yes" : "No");
f877e3
 			if (h->length < 0x16) break;
f877e3
 			if (!(opt.flags & FLAG_QUIET))
f877e3
 			{
f877e3
 				if (WORD(data + 0x10) != 0xFFFF)
f877e3
-					printf("\tInput Voltage Probe Handle: 0x%04X\n",
f877e3
+					pr_attr("Input Voltage Probe Handle", "0x%04X",
f877e3
 						WORD(data + 0x10));
f877e3
 				if (WORD(data + 0x12) != 0xFFFF)
f877e3
-					printf("\tCooling Device Handle: 0x%04X\n",
f877e3
+					pr_attr("Cooling Device Handle", "0x%04X",
f877e3
 						WORD(data + 0x12));
f877e3
 				if (WORD(data + 0x14) != 0xFFFF)
f877e3
-					printf("\tInput Current Probe Handle: 0x%04X\n",
f877e3
+					pr_attr("Input Current Probe Handle", "0x%04X",
f877e3
 						WORD(data + 0x14));
f877e3
 			}
f877e3
 			break;
f877e3
@@ -5001,19 +4934,19 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 			if (h->length < 0x0B) break;
f877e3
 			if (opt.flags & FLAG_QUIET)
f877e3
 				return;
f877e3
-			dmi_additional_info(h, "");
f877e3
+			dmi_additional_info(h);
f877e3
 			break;
f877e3
 
f877e3
 		case 41: /* 7.42 Onboard Device Extended Information */
f877e3
 			pr_handle_name("Onboard Device");
f877e3
 			if (h->length < 0x0B) break;
f877e3
-			printf("\tReference Designation: %s\n", dmi_string(h, data[0x04]));
f877e3
-			printf("\tType: %s\n",
f877e3
+			pr_attr("Reference Designation", "%s", dmi_string(h, data[0x04]));
f877e3
+			pr_attr("Type", "%s",
f877e3
 				dmi_on_board_devices_type(data[0x05] & 0x7F));
f877e3
-			printf("\tStatus: %s\n",
f877e3
+			pr_attr("Status", "%s",
f877e3
 				data[0x05] & 0x80 ? "Enabled" : "Disabled");
f877e3
-			printf("\tType Instance: %u\n", data[0x06]);
f877e3
-			dmi_slot_segment_bus_func(WORD(data + 0x07), data[0x09], data[0x0A], "\t");
f877e3
+			pr_attr("Type Instance", "%u", data[0x06]);
f877e3
+			dmi_slot_segment_bus_func(WORD(data + 0x07), data[0x09], data[0x0A]);
f877e3
 			break;
f877e3
 
f877e3
 		case 42: /* 7.43 Management Controller Host Interface */
f877e3
@@ -5021,7 +4954,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 			if (ver < 0x0302)
f877e3
 			{
f877e3
 				if (h->length < 0x05) break;
f877e3
-				printf("\tInterface Type: %s\n",
f877e3
+				pr_attr("Interface Type", "%s",
f877e3
 					dmi_management_controller_host_type(data[0x04]));
f877e3
 				/*
f877e3
 				 * There you have a type-dependent, variable-length
f877e3
@@ -5032,7 +4965,7 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 				if (h->length < 0x09) break;
f877e3
 				if (data[0x04] == 0xF0)		/* OEM */
f877e3
 				{
f877e3
-					printf("\tVendor ID: 0x%02X%02X%02X%02X\n",
f877e3
+					pr_attr("Vendor ID", "0x%02X%02X%02X%02X",
f877e3
 						data[0x05], data[0x06], data[0x07],
f877e3
 						data[0x08]);
f877e3
 				}
f877e3
@@ -5044,10 +4977,8 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 		case 43: /* 7.44 TPM Device */
f877e3
 			pr_handle_name("TPM Device");
f877e3
 			if (h->length < 0x1B) break;
f877e3
-			printf("\tVendor ID:");
f877e3
 			dmi_tpm_vendor_id(data + 0x04);
f877e3
-			printf("\n");
f877e3
-			printf("\tSpecification Version: %d.%d\n", data[0x08], data[0x09]);
f877e3
+			pr_attr("Specification Version", "%d.%d", data[0x08], data[0x09]);
f877e3
 			switch (data[0x08])
f877e3
 			{
f877e3
 				case 0x01:
f877e3
@@ -5056,11 +4987,11 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 					 * redundant with the above, and uncoded
f877e3
 					 * in a silly way.
f877e3
 					 */
f877e3
-					printf("\tFirmware Revision: %u.%u\n",
f877e3
+					pr_attr("Firmware Revision", "%u.%u",
f877e3
 						data[0x0C], data[0x0D]);
f877e3
 					break;
f877e3
 				case 0x02:
f877e3
-					printf("\tFirmware Revision: %u.%u\n",
f877e3
+					pr_attr("Firmware Revision", "%u.%u",
f877e3
 						DWORD(data + 0x0A) >> 16,
f877e3
 						DWORD(data + 0x0A) & 0xFFFF);
f877e3
 					/*
f877e3
@@ -5070,11 +5001,11 @@ static void dmi_decode(const struct dmi_header *h, u16 ver)
f877e3
 					 */
f877e3
 					break;
f877e3
 			}
f877e3
-			printf("\tDescription: %s\n", dmi_string(h, data[0x12]));
f877e3
+			pr_attr("Description", "%s", dmi_string(h, data[0x12]));
f877e3
 			printf("\tCharacteristics:\n");
f877e3
 			dmi_tpm_characteristics(QWORD(data + 0x13), "\t\t");
f877e3
 			if (h->length < 0x1F) break;
f877e3
-			printf("\tOEM-specific Information: 0x%08X\n",
f877e3
+			pr_attr("OEM-specific Information", "0x%08X",
f877e3
 				DWORD(data + 0x1B));
f877e3
 			break;
f877e3
 
f877e3
@@ -5141,8 +5072,7 @@ static void dmi_table_string(const struct dmi_header *h, const u8 *data, u16 ver
f877e3
 				printf("%u.%u\n", data[key - 1], data[key]);
f877e3
 			break;
f877e3
 		case 0x108:
f877e3
-			dmi_system_uuid(data + offset, ver);
f877e3
-			printf("\n");
f877e3
+			dmi_system_uuid(NULL, data + offset, ver);
f877e3
 			break;
f877e3
 		case 0x305:
f877e3
 			printf("%s\n", dmi_chassis_type(data[offset]));
f877e3
@@ -5151,8 +5081,7 @@ static void dmi_table_string(const struct dmi_header *h, const u8 *data, u16 ver
f877e3
 			printf("%s\n", dmi_processor_family(h, ver));
f877e3
 			break;
f877e3
 		case 0x416:
f877e3
-			dmi_processor_frequency(data + offset);
f877e3
-			printf("\n");
f877e3
+			dmi_processor_frequency(NULL, data + offset);
f877e3
 			break;
f877e3
 		default:
f877e3
 			printf("%s\n", dmi_string(h, data[offset]));
f877e3
diff --git a/dmioem.c b/dmioem.c
f877e3
index c999c08c4475..873ec1068c16 100644
f877e3
--- a/dmioem.c
f877e3
+++ b/dmioem.c
f877e3
@@ -96,16 +96,16 @@ static int dmi_decode_acer(const struct dmi_header *h)
f877e3
 			pr_handle_name("Acer Hotkey Function");
f877e3
 			if (h->length < 0x0F) break;
f877e3
 			cap = WORD(data + 0x04);
f877e3
-			printf("\tFunction bitmap for Communication Button: 0x%04hx\n", cap);
f877e3
+			pr_attr("Function bitmap for Communication Button", "0x%04hx", cap);
f877e3
 			printf("\t\tWiFi: %s\n", cap & 0x0001 ? "Yes" : "No");
f877e3
 			printf("\t\t3G: %s\n", cap & 0x0040 ? "Yes" : "No");
f877e3
 			printf("\t\tWiMAX: %s\n", cap & 0x0080 ? "Yes" : "No");
f877e3
 			printf("\t\tBluetooth: %s\n", cap & 0x0800 ? "Yes" : "No");
f877e3
-			printf("\tFunction bitmap for Application Button: 0x%04hx\n", WORD(data + 0x06));
f877e3
-			printf("\tFunction bitmap for Media Button: 0x%04hx\n", WORD(data + 0x08));
f877e3
-			printf("\tFunction bitmap for Display Button: 0x%04hx\n", WORD(data + 0x0A));
f877e3
-			printf("\tFunction bitmap for Others Button: 0x%04hx\n", WORD(data + 0x0C));
f877e3
-			printf("\tCommunication Function Key Number: %d\n", data[0x0E]);
f877e3
+			pr_attr("Function bitmap for Application Button", "0x%04hx", WORD(data + 0x06));
f877e3
+			pr_attr("Function bitmap for Media Button", "0x%04hx", WORD(data + 0x08));
f877e3
+			pr_attr("Function bitmap for Display Button", "0x%04hx", WORD(data + 0x0A));
f877e3
+			pr_attr("Function bitmap for Others Button", "0x%04hx", WORD(data + 0x0C));
f877e3
+			pr_attr("Communication Function Key Number", "%d", data[0x0E]);
f877e3
 			break;
f877e3
 
f877e3
 		default:
f877e3
@@ -128,19 +128,21 @@ static void dmi_print_hp_net_iface_rec(u8 id, u8 bus, u8 dev, const u8 *mac)
f877e3
 	 * 640K ought to be enough for anybody(said no one, ever).
f877e3
 	 * */
f877e3
 	static u8 nic_ctr;
f877e3
+	char attr[8];
f877e3
 
f877e3
 	if (id == 0xFF)
f877e3
 		id = ++nic_ctr;
f877e3
 
f877e3
+	sprintf(attr, "NIC %hu", id);
f877e3
 	if (dev == 0x00 && bus == 0x00)
f877e3
-		printf("\tNIC %d: Disabled\n", id);
f877e3
+		pr_attr(attr, "Disabled");
f877e3
 	else if (dev == 0xFF && bus == 0xFF)
f877e3
-		printf("\tNIC %d: Not Installed\n", id);
f877e3
+		pr_attr(attr, "Not Installed");
f877e3
 	else
f877e3
 	{
f877e3
-		printf("\tNIC %d: PCI device %02x:%02x.%x, "
f877e3
-			"MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
f877e3
-			id, bus, dev >> 3, dev & 7,
f877e3
+		pr_attr(attr, "PCI device %02x:%02x.%x, "
f877e3
+			"MAC address %02X:%02X:%02X:%02X:%02X:%02X",
f877e3
+			bus, dev >> 3, dev & 7,
f877e3
 			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
f877e3
 	}
f877e3
 }
f877e3
@@ -160,13 +162,13 @@ static int dmi_decode_hp(const struct dmi_header *h)
f877e3
 			 */
f877e3
 			pr_handle_name("%s ProLiant System/Rack Locator", company);
f877e3
 			if (h->length < 0x0B) break;
f877e3
-			printf("\tRack Name: %s\n", dmi_string(h, data[0x04]));
f877e3
-			printf("\tEnclosure Name: %s\n", dmi_string(h, data[0x05]));
f877e3
-			printf("\tEnclosure Model: %s\n", dmi_string(h, data[0x06]));
f877e3
-			printf("\tEnclosure Serial: %s\n", dmi_string(h, data[0x0A]));
f877e3
-			printf("\tEnclosure Bays: %d\n", data[0x08]);
f877e3
-			printf("\tServer Bay: %s\n", dmi_string(h, data[0x07]));
f877e3
-			printf("\tBays Filled: %d\n", data[0x09]);
f877e3
+			pr_attr("Rack Name", "%s", dmi_string(h, data[0x04]));
f877e3
+			pr_attr("Enclosure Name", "%s", dmi_string(h, data[0x05]));
f877e3
+			pr_attr("Enclosure Model", "%s", dmi_string(h, data[0x06]));
f877e3
+			pr_attr("Enclosure Serial", "%s", dmi_string(h, data[0x0A]));
f877e3
+			pr_attr("Enclosure Bays", "%d", data[0x08]);
f877e3
+			pr_attr("Server Bay", "%s", dmi_string(h, data[0x07]));
f877e3
+			pr_attr("Bays Filled", "%d", data[0x09]);
f877e3
 			break;
f877e3
 
f877e3
 		case 209:
f877e3
@@ -243,20 +245,22 @@ static int dmi_decode_hp(const struct dmi_header *h)
f877e3
 			 */
f877e3
 			pr_handle_name("%s 64-bit CRU Information", company);
f877e3
 			if (h->length < 0x18) break;
f877e3
-			printf("\tSignature: 0x%08x", DWORD(data + 0x04));
f877e3
 			if (is_printable(data + 0x04, 4))
f877e3
-				printf(" (%c%c%c%c)", data[0x04], data[0x05],
f877e3
+				pr_attr("Signature", "0x%08x (%c%c%c%c)",
f877e3
+					DWORD(data + 0x04),
f877e3
+					data[0x04], data[0x05],
f877e3
 					data[0x06], data[0x07]);
f877e3
-			printf("\n");
f877e3
+			else
f877e3
+				pr_attr("Signature", "0x%08x", DWORD(data + 0x04));
f877e3
 			if (DWORD(data + 0x04) == 0x55524324)
f877e3
 			{
f877e3
 				u64 paddr = QWORD(data + 0x08);
f877e3
 				paddr.l += DWORD(data + 0x14);
f877e3
 				if (paddr.l < DWORD(data + 0x14))
f877e3
 					paddr.h++;
f877e3
-				printf("\tPhysical Address: 0x%08x%08x\n",
f877e3
+				pr_attr("Physical Address", "0x%08x%08x",
f877e3
 					paddr.h, paddr.l);
f877e3
-				printf("\tLength: 0x%08x\n", DWORD(data + 0x10));
f877e3
+				pr_attr("Length", "0x%08x", DWORD(data + 0x10));
f877e3
 			}
f877e3
 			break;
f877e3
 
f877e3
@@ -268,12 +272,12 @@ static int dmi_decode_hp(const struct dmi_header *h)
f877e3
 			 */
f877e3
 			pr_handle_name("%s ProLiant Information", company);
f877e3
 			if (h->length < 0x08) break;
f877e3
-			printf("\tPower Features: 0x%08x\n", DWORD(data + 0x04));
f877e3
+			pr_attr("Power Features", "0x%08x", DWORD(data + 0x04));
f877e3
 			if (h->length < 0x0C) break;
f877e3
-			printf("\tOmega Features: 0x%08x\n", DWORD(data + 0x08));
f877e3
+			pr_attr("Omega Features", "0x%08x", DWORD(data + 0x08));
f877e3
 			if (h->length < 0x14) break;
f877e3
 			feat = DWORD(data + 0x10);
f877e3
-			printf("\tMisc. Features: 0x%08x\n", feat);
f877e3
+			pr_attr("Misc. Features", "0x%08x", feat);
f877e3
 			printf("\t\tiCRU: %s\n", feat & 0x0001 ? "Yes" : "No");
f877e3
 			printf("\t\tUEFI: %s\n", feat & 0x1400 ? "Yes" : "No");
f877e3
 			break;
f877e3
@@ -320,8 +324,8 @@ static int dmi_decode_ibm_lenovo(const struct dmi_header *h)
f877e3
 				return 0;
f877e3
 
f877e3
 			pr_handle_name("ThinkVantage Technologies");
f877e3
-			printf("\tVersion: %u\n", data[0x04]);
f877e3
-			printf("\tDiagnostics: %s\n",
f877e3
+			pr_attr("Version", "%u", data[0x04]);
f877e3
+			pr_attr("Diagnostics", "%s",
f877e3
 				data[0x14] & 0x80 ? "Available" : "No");
f877e3
 			break;
f877e3
 
f877e3
@@ -359,7 +363,7 @@ static int dmi_decode_ibm_lenovo(const struct dmi_header *h)
f877e3
 				return 0;
f877e3
 
f877e3
 			pr_handle_name("ThinkPad Device Presence Detection");
f877e3
-			printf("\tFingerprint Reader: %s\n",
f877e3
+			pr_attr("Fingerprint Reader", "%s",
f877e3
 				data[0x09] & 0x01 ? "Present" : "No");
f877e3
 			break;
f877e3
 
f877e3
@@ -392,8 +396,8 @@ static int dmi_decode_ibm_lenovo(const struct dmi_header *h)
f877e3
 				return 0;
f877e3
 
f877e3
 			pr_handle_name("ThinkPad Embedded Controller Program");
f877e3
-			printf("\tVersion ID: %s\n", dmi_string(h, 1));
f877e3
-			printf("\tRelease Date: %s\n", dmi_string(h, 2));
f877e3
+			pr_attr("Version ID", "%s", dmi_string(h, 1));
f877e3
+			pr_attr("Release Date", "%s", dmi_string(h, 2));
f877e3
 			break;
f877e3
 
f877e3
 		default:
f877e3
diff --git a/dmioutput.c b/dmioutput.c
f877e3
index ca7edab5cc69..2330b65755c9 100644
f877e3
--- a/dmioutput.c
f877e3
+++ b/dmioutput.c
f877e3
@@ -59,3 +59,15 @@ void pr_handle_name(const char *format, ...)
f877e3
 	va_end(args);
f877e3
 	printf("\n");
f877e3
 }
f877e3
+
f877e3
+void pr_attr(const char *name, const char *format, ...)
f877e3
+{
f877e3
+	va_list args;
f877e3
+
f877e3
+	printf("\t%s: ", name);
f877e3
+
f877e3
+	va_start(args, format);
f877e3
+	vprintf(format, args);
f877e3
+	va_end(args);
f877e3
+	printf("\n");
f877e3
+}
f877e3
diff --git a/dmioutput.h b/dmioutput.h
f877e3
index 0acdce7658c9..981dcb45f26a 100644
f877e3
--- a/dmioutput.h
f877e3
+++ b/dmioutput.h
f877e3
@@ -25,3 +25,4 @@ void pr_comment(const char *format, ...);
f877e3
 void pr_info(const char *format, ...);
f877e3
 void pr_handle(const struct dmi_header *h);
f877e3
 void pr_handle_name(const char *format, ...);
f877e3
+void pr_attr(const char *name, const char *format, ...);
f877e3
-- 
f877e3
2.17.1
f877e3