[Skiboot] [PATCH] nvram-format: Fix endian issues

Stewart Smith stewart at linux.vnet.ibm.com
Tue Jan 10 13:01:46 AEDT 2017


NVRAM formats are always BE, so let's use the sparse annotation to catch
any issues (and correct said issues).

On LE platforms, the test was erroneously passing as with building the
nvram-format code on LE we were produces an incorrect NVRAM image.

Signed-off-by: Stewart Smith <stewart at linux.vnet.ibm.com>
---
 core/nvram-format.c          | 35 ++++++++++++++++++++---------------
 core/test/run-nvram-format.c |  6 +++---
 2 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/core/nvram-format.c b/core/nvram-format.c
index 5c7c9fe35b06..84407fc1af71 100644
--- a/core/nvram-format.c
+++ b/core/nvram-format.c
@@ -1,4 +1,4 @@
-/* Copyright 2013-2014 IBM Corp.
+/* Copyright 2013-2017 IBM Corp.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
 struct chrp_nvram_hdr {
 	uint8_t		sig;
 	uint8_t		cksum;
-	uint16_t	len;
+	be16		len;
 	char		name[12];
 };
 
@@ -75,11 +75,13 @@ int nvram_format(void *nvram_image, uint32_t nvram_size)
 		return -1;
 	h = nvram_image + offset;
 	h->sig = NVRAM_SIG_FW_PRIV;
-	h->len = NVRAM_SIZE_FW_PRIV >> 4;
+	h->len = cpu_to_be16(NVRAM_SIZE_FW_PRIV >> 4);
 	strcpy(h->name, NVRAM_NAME_FW_PRIV);
 	h->cksum = chrp_nv_cksum(h);
-	prlog(PR_DEBUG, "NVRAM: Created '%s' partition at 0x%08x for size 0x%08x"
-			" with cksum 0x%02x\n", NVRAM_NAME_FW_PRIV, offset, h->len, h->cksum);
+	prlog(PR_DEBUG, "NVRAM: Created '%s' partition at 0x%08x"
+	      " for size 0x%08x with cksum 0x%02x\n",
+	      NVRAM_NAME_FW_PRIV, offset,
+	      be16_to_cpu(h->len), h->cksum);
 	offset += NVRAM_SIZE_FW_PRIV;
 
 	/* Create common partition */
@@ -87,11 +89,13 @@ int nvram_format(void *nvram_image, uint32_t nvram_size)
 		return -1;
 	h = nvram_image + offset;
 	h->sig = NVRAM_SIG_SYSTEM;
-	h->len = NVRAM_SIZE_COMMON >> 4;
+	h->len = cpu_to_be16(NVRAM_SIZE_COMMON >> 4);
 	strcpy(h->name, NVRAM_NAME_COMMON);
 	h->cksum = chrp_nv_cksum(h);
-	prlog(PR_DEBUG, "NVRAM: Created '%s' partition at 0x%08x for size 0x%08x"
-			" with cksum 0x%02x\n", NVRAM_NAME_COMMON, offset, h->len, h->cksum);
+	prlog(PR_DEBUG, "NVRAM: Created '%s' partition at 0x%08x"
+	      " for size 0x%08x with cksum 0x%02x\n",
+	      NVRAM_NAME_COMMON, offset,
+	      be16_to_cpu(h->len), h->cksum);
 	offset += NVRAM_SIZE_COMMON;
 
 	/* Create free space partition */
@@ -99,12 +103,13 @@ int nvram_format(void *nvram_image, uint32_t nvram_size)
 		return -1;
 	h = nvram_image + offset;
 	h->sig = NVRAM_SIG_FREE;
-	h->len = (nvram_size - offset) >> 4;
+	h->len = cpu_to_be16((nvram_size - offset) >> 4);
 	/* We have the full 12 bytes here */
 	memcpy(h->name, NVRAM_NAME_FREE, 12);
 	h->cksum = chrp_nv_cksum(h);
-	prlog(PR_DEBUG, "NVRAM: Created '%s' partition at 0x%08x for size 0x%08x"
-			" with cksum 0x%02x\n", NVRAM_NAME_FREE, offset, h->len, h->cksum);
+	prlog(PR_DEBUG, "NVRAM: Created '%s' partition at 0x%08x"
+	      " for size 0x%08x with cksum 0x%02x\n",
+	      NVRAM_NAME_FREE, offset, be16_to_cpu(h->len), h->cksum);
 	return 0;
 }
 
@@ -129,7 +134,7 @@ int nvram_check(void *nvram_image, const uint32_t nvram_size)
 				offset, h->cksum, chrp_nv_cksum(h));
 			goto failed;
 		}
-		if (h->len < 1) {
+		if (be16_to_cpu(h->len) < 1) {
 			prerror("NVRAM: Partition at offset 0x%x"
 				" has incorrect 0 length\n", offset);
 			goto failed;
@@ -143,7 +148,7 @@ int nvram_check(void *nvram_image, const uint32_t nvram_size)
 		    strcmp(h->name, NVRAM_NAME_FW_PRIV) == 0)
 			skiboot_part_hdr = h;
 
-		offset += h->len << 4;
+		offset += be16_to_cpu(h->len) << 4;
 		if (offset > nvram_size) {
 			prerror("NVRAM: Partition at offset 0x%x"
 				" extends beyond end of nvram !\n", offset);
@@ -166,7 +171,7 @@ int nvram_check(void *nvram_image, const uint32_t nvram_size)
 		 * always check.
 		 */
 		const char *last_byte = (const char *) skiboot_part_hdr +
-			skiboot_part_hdr->len * 16 - 1;
+			be16_to_cpu(skiboot_part_hdr->len) * 16 - 1;
 
 		if (*last_byte != 0) {
 			prerror("NVRAM: Skiboot private partition is not NUL terminated");
@@ -224,7 +229,7 @@ const char *nvram_query(const char *key)
 	}
 
 	part_end = (const char *) skiboot_part_hdr
-		+ skiboot_part_hdr->len * 16 - 1;
+		+ be16_to_cpu(skiboot_part_hdr->len) * 16 - 1;
 
 	start = (const char *) skiboot_part_hdr
 		+ sizeof(*skiboot_part_hdr);
diff --git a/core/test/run-nvram-format.c b/core/test/run-nvram-format.c
index 4ca2cded2a60..5bd8ea2ae6ec 100644
--- a/core/test/run-nvram-format.c
+++ b/core/test/run-nvram-format.c
@@ -69,8 +69,8 @@ int main(void)
 	nvram_image = malloc(sz);
 	assert(nvram_format(nvram_image, sz)==0);
 	assert(nvram_check(nvram_image, sz)==0);
-	assert(nvram_image[sz-13]==0);
-	assert(nvram_image[sz-14]==1);
+	assert(nvram_image[sz-14]==0);
+	assert(nvram_image[sz-13]==1);
 	h = (struct chrp_nvram_hdr*)(&nvram_image[NVRAM_SIZE_COMMON + NVRAM_SIZE_FW_PRIV]);
 	assert(memcmp(h->name, "wwwwwwwwwwww", 12)==0);
 	free(nvram_image);
@@ -87,7 +87,7 @@ int main(void)
 	/* Does our NUL checking work? */
 	assert(nvram_format(nvram_image, 128 * 1024) == 0);
 	h = (struct chrp_nvram_hdr *) nvram_image;
-	memset((char *) h + sizeof(*h), 0xFF, h->len * 16 - sizeof(*h));
+	memset((char *) h + sizeof(*h), 0xFF, be16_to_cpu(h->len) * 16 - sizeof(*h));
 	assert(nvram_check(nvram_image, 128 * 1024) != 0);
 
 	assert(nvram_format(nvram_image, 128*1024)==0);
-- 
2.1.4



More information about the Skiboot mailing list