[coreboot-gerrit] Change in coreboot[master]: include/memory_info.h: Change serial number field from 5 bytes to 4

Raul Rangel (Code Review) gerrit at coreboot.org
Fri Mar 23 21:38:25 CET 2018


Raul Rangel has uploaded this change for review. ( https://review.coreboot.org/25343


Change subject: include/memory_info.h: Change serial number field from 5 bytes to 4
......................................................................

include/memory_info.h: Change serial number field from 5 bytes to 4

dimm_info.serial had a strange contract. The SPD spec defines a 4 byte
serial number. dimm_info.serial required a 4 character ascii string with
a null terminator.

This change makes the serial field so it matches the SPD spec.
smbios.c will then translate the byte array into hex and set it on the
smbios table.

There were only two callers that set the serial number:
* haswell/raminit.c: already does a memcpy(serial, spd->serial, 4), so
  it already matches the new contract.
* amd_late_init.c: Previously copied the last 4 characters. Requires
  decoding the serial number into a byte array.

google/cyan/spd/spd.c: This could be updated to pass the serial number,
but it uses a hard coded spd.bin.

Testing this on grunt, dmidecode now shows the full serial number:
        Serial Number: 00000000

BUG=b:65403853
TEST=tested on grunt

Change-Id: Ifc58ad9ea4cdd2abe06a170a39b1f32680e7b299
Signed-off-by: Raul E Rangel <rrangel at chromium.org>
---
M src/arch/x86/smbios.c
A src/include/hexutil.h
M src/include/memory_info.h
M src/lib/Makefile.inc
A src/lib/hexutil.c
M src/soc/amd/common/block/pi/amd_late_init.c
6 files changed, 154 insertions(+), 33 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/43/25343/1

diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c
index 7079374..21125c4 100644
--- a/src/arch/x86/smbios.c
+++ b/src/arch/x86/smbios.c
@@ -29,6 +29,7 @@
 #include <memory_info.h>
 #include <spd.h>
 #include <cbmem.h>
+#include <hexutil.h>
 #if IS_ENABLED(CONFIG_CHROMEOS)
 #include <vendorcode/google/chromeos/gnvs.h>
 #endif
@@ -251,6 +252,16 @@
 	}
 }
 
+/* Encodes the SPD serial number into hex */
+static void smbios_fill_dimm_serial_number(const struct dimm_info *dimm,
+					   struct smbios_type17 *t)
+{
+	char serial[sizeof(dimm->serial) * 2 + 1];
+	encode_as_hex_string(dimm->serial, sizeof(dimm->serial), serial,
+			     sizeof(serial));
+	t->serial_number = smbios_add_string(t->eos, serial);
+}
+
 static int create_smbios_type17_for_dimm(struct dimm_info *dimm,
 					 unsigned long *current, int *handle)
 {
@@ -290,13 +301,7 @@
 	}
 
 	smbios_fill_dimm_manufacturer_from_id(dimm->mod_id, t);
-	/* put '\0' in the end of data */
-	dimm->serial[DIMM_INFO_SERIAL_SIZE - 1] = '\0';
-	if (dimm->serial[0] == 0)
-		t->serial_number = smbios_add_string(t->eos, "None");
-	else
-		t->serial_number = smbios_add_string(t->eos,
-						   (const char *)dimm->serial);
+	smbios_fill_dimm_serial_number(dimm, t);
 
 	snprintf(locator, sizeof(locator), "Channel-%d-DIMM-%d",
 		dimm->channel_num, dimm->dimm_num);
diff --git a/src/include/hexutil.h b/src/include/hexutil.h
new file mode 100644
index 0000000..e57cd34
--- /dev/null
+++ b/src/include/hexutil.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef HEXUTIL_H
+#define HEXUTIL_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * Decodes a hex character [0-9A-Za-z] into a byte.
+ *
+ * Invalid characters are mapped to 0.
+ * */
+uint8_t decode_hex_character(char hex);
+
+/**
+ * Decodes a hex string into a byte array.
+ *
+ * Examples:
+ *  * "01AF" => {0x01, 0xAF}
+ *  * "1AF" => {0x01, 0xAF}
+ *  * "1AF" => {0x00, 0x00, 0x01, 0xAF} w/ 4 byte dest buffer.
+ *
+ * @param src_size size of the src buffer
+ * @param dest_size must be at least (strlen(src) + 1) / 2 in size. If the
+ * buffer is bigger than required the most significant bytes are cleared.
+ */
+void decode_hex_string(const char *src, size_t src_size, uint8_t *dest,
+		       size_t dest_size);
+
+/**
+ * Encodes a byte array into a hex string.
+ *
+ * e.g., {0x01, 0x02} => "0102"
+ *
+ * @param dest_size must be at least (src_size * 2 + 1).
+ */
+void encode_as_hex_string(const uint8_t *src, size_t src_size, char *dest,
+			  size_t dest_size);
+#endif
diff --git a/src/include/memory_info.h b/src/include/memory_info.h
index 4613015..d26d789 100644
--- a/src/include/memory_info.h
+++ b/src/include/memory_info.h
@@ -19,7 +19,7 @@
 #include <stdint.h>
 #include <compiler.h>
 
-#define DIMM_INFO_SERIAL_SIZE		5
+#define DIMM_INFO_SERIAL_SIZE		4
 #define DIMM_INFO_PART_NUMBER_SIZE	19
 #define DIMM_INFO_TOTAL			8	/* Maximum num of dimm is 8 */
 
@@ -46,11 +46,7 @@
 	uint8_t dimm_num;
 	uint8_t bank_locator;
 	/*
-	 * The last byte is '\0' for the end of string.
-	 *
-	 * Even though the SPD spec defines this field as a byte array the value
-	 * is passed directly to SMBIOS as a string, and thus must be printable
-	 * ASCII.
+	 * SPD serial number.
 	 */
 	uint8_t serial[DIMM_INFO_SERIAL_SIZE];
 	/*
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index 960b5cb..3ae77a6 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -133,6 +133,7 @@
 ramstage-$(CONFIG_GENERIC_GPIO_LIB) += gpio.c
 ramstage-$(CONFIG_GENERIC_UDELAY) += timer.c
 ramstage-y += b64_decode.c
+ramstage-y += hexutil.c
 ramstage-$(CONFIG_ACPI_NHLT) += nhlt.c
 
 romstage-y += cbmem_common.c
diff --git a/src/lib/hexutil.c b/src/lib/hexutil.c
new file mode 100644
index 0000000..7c335a1
--- /dev/null
+++ b/src/lib/hexutil.c
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <hexutil.h>
+#include <string.h>
+
+uint8_t decode_hex_character(char hex)
+{
+	if (isdigit(hex))
+		return hex - '0';
+	else if (isxdigit(hex) && isupper(hex))
+		return hex - 'A' + 10;
+	else if (isxdigit(hex) && islower(hex))
+		return hex - 'a' + 10;
+	else
+		return 0;
+}
+
+void decode_hex_string(const char *src, size_t src_size, uint8_t *dest,
+		       size_t dest_size)
+{
+	const size_t src_len = strnlen(src, src_size - 1);
+
+	for (size_t i = 0; i < dest_size; ++i) {
+		int offset = (src_len - 1) - i * 2;
+
+		uint8_t byte = 0;
+
+		if (offset >= 0) {
+			char low = src[offset];
+			byte |= decode_hex_character(low);
+		}
+
+		if (offset >= 1) {
+			char high = src[offset - 1];
+			byte |= decode_hex_character(high) << 4;
+		}
+
+		dest[dest_size - i - 1] = byte;
+	}
+}
+
+void encode_as_hex_string(const uint8_t *src, size_t src_size, char *dest,
+			  size_t dest_size)
+{
+	for (size_t i = 0; i < src_size; ++i) {
+		size_t dest_offset = i * 2;
+
+		if (dest_offset < dest_size) {
+			if (dest_offset + 3 <= dest_size) {
+				snprintf(dest + dest_offset, 3, "%02hhx",
+					 src[i]);
+			} else if (dest_offset + 2 <= dest_size) {
+				snprintf(dest + dest_offset, 2, "%01hhx",
+					 src[i] >> 4);
+			} else {
+				dest[dest_offset] = '\0';
+			}
+		}
+	}
+}
diff --git a/src/soc/amd/common/block/pi/amd_late_init.c b/src/soc/amd/common/block/pi/amd_late_init.c
index 48c1718..6b09987 100644
--- a/src/soc/amd/common/block/pi/amd_late_init.c
+++ b/src/soc/amd/common/block/pi/amd_late_init.c
@@ -15,11 +15,12 @@
 
 #include <arch/acpi.h>
 #include <bootstate.h>
+#include <cbmem.h>
 #include <console/console.h>
 #include <device/device.h>
 #include <device/pci_def.h>
 #include <device/pci_ops.h>
-#include <cbmem.h>
+#include <hexutil.h>
 #include <memory_info.h>
 
 #include <amdblocks/agesawrapper.h>
@@ -27,20 +28,9 @@
 
 static void transfer_memory_info(TYPE17_DMI_INFO *dmi17, struct dimm_info *dimm)
 {
-	size_t len, destlen;
-	uint32_t offset;
+	decode_hex_string(dmi17->SerialNumber, sizeof(dmi17->SerialNumber),
+			  dimm->serial, sizeof(dimm->serial));
 
-
-	len = strnlen(dmi17->SerialNumber, sizeof(dmi17->SerialNumber)) + 1;
-	destlen = sizeof(dimm->serial);
-
-	if (len > destlen) {
-		offset = len - destlen;
-		len = destlen;
-	} else
-		offset = 0;
-
-	strncpy((char *)dimm->serial, &dmi17->SerialNumber[offset], len);
 	dimm->dimm_size = dmi17->ExtSize;
 	dimm->ddr_type = dmi17->MemoryType;
 	dimm->ddr_frequency = dmi17->Speed;
@@ -55,6 +45,10 @@
 
 static void print_dimm_info(const struct dimm_info *dimm)
 {
+	char serial[sizeof(dimm->serial) * 2 + 1];
+	encode_as_hex_string(dimm->serial, sizeof(dimm->serial), serial,
+			     sizeof(serial));
+
 	printk(RAM_SPEW,
 	       "CBMEM_ID_MEMINFO:\n"
 	       "  dimm_size: %u\n"
@@ -67,8 +61,8 @@
 	       "  mod_id: %hu\n"
 	       "  mod_type: 0x%hhx\n"
 	       "  bus_width: %hhu\n"
-	       "  serial(%zu): %s\n"
-	       "  module_part_number(%zu): %s\n",
+	       "  serial: 0x%s\n"
+	       "  module_part_number(%zu): '%s'\n",
 	       dimm->dimm_size,
 	       dimm->ddr_type,
 	       dimm->ddr_frequency,
@@ -79,8 +73,7 @@
 	       dimm->mod_id,
 	       dimm->mod_type,
 	       dimm->bus_width,
-	       strlen((char *) dimm->serial),
-	       (char *) dimm->serial,
+	       serial,
 	       strlen((char *) dimm->module_part_number),
 	       (char *) dimm->module_part_number
 	);
@@ -104,8 +97,8 @@
 	       "  FormFactor: 0x%x\n"
 	       "  DeviceLocator: %8s\n"
 	       "  BankLocator: %10s\n"
-	       "  SerialNumber(%zu): %9s\n"
-	       "  PartNumber(%zu): %19s\n",
+	       "  SerialNumber(%zu): '%9s'\n"
+	       "  PartNumber(%zu): '%19s'\n",
 	       dmi17->Handle,
 	       dmi17->TotalWidth,
 	       dmi17->DataWidth,

-- 
To view, visit https://review.coreboot.org/25343
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifc58ad9ea4cdd2abe06a170a39b1f32680e7b299
Gerrit-Change-Number: 25343
Gerrit-PatchSet: 1
Gerrit-Owner: Raul Rangel <rrangel at chromium.org>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180323/c62f2e33/attachment-0001.html>


More information about the coreboot-gerrit mailing list