diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | core/nvram-format.c | 10 | ||||
-rw-r--r-- | core/test/run-nvram-format.c | 87 | ||||
-rw-r--r-- | include/nvram-format.h | 2 |
4 files changed, 96 insertions, 4 deletions
@@ -40,6 +40,7 @@ core/test/run-mem_region_init core/test/run-mem_region_release_unused core/test/run-mem_region_release_unused_noalloc core/test/run-msg +core/test/run-nvram-format core/test/run-pel core/test/run-pool core/test/run-trace diff --git a/core/nvram-format.c b/core/nvram-format.c index 3ec0db2..fc2ddef 100644 --- a/core/nvram-format.c +++ b/core/nvram-format.c @@ -60,7 +60,7 @@ static uint8_t chrp_nv_cksum(struct chrp_nvram_hdr *hdr) return c_sum; } -void nvram_format(void *nvram_image, uint32_t nvram_size) +int nvram_format(void *nvram_image, uint32_t nvram_size) { struct chrp_nvram_hdr *h; unsigned int offset = 0; @@ -69,6 +69,8 @@ void nvram_format(void *nvram_image, uint32_t nvram_size) memset(nvram_image, 0, nvram_size); /* Create private partition */ + if (nvram_size - offset < NVRAM_SIZE_FW_PRIV) + return -1; h = nvram_image + offset; h->sig = NVRAM_SIG_FW_PRIV; h->len = NVRAM_SIZE_FW_PRIV >> 4; @@ -77,6 +79,8 @@ void nvram_format(void *nvram_image, uint32_t nvram_size) offset += NVRAM_SIZE_FW_PRIV; /* Create common partition */ + if (nvram_size - offset < NVRAM_SIZE_COMMON) + return -1; h = nvram_image + offset; h->sig = NVRAM_SIG_SYSTEM; h->len = NVRAM_SIZE_COMMON >> 4; @@ -85,11 +89,15 @@ void nvram_format(void *nvram_image, uint32_t nvram_size) offset += NVRAM_SIZE_COMMON; /* Create free space partition */ + if (nvram_size - offset < sizeof(struct chrp_nvram_hdr)) + return -1; h = nvram_image + offset; h->sig = NVRAM_SIG_FREE; h->len = (nvram_size - offset) >> 4; strncpy(h->name, NVRAM_NAME_FREE, 12); h->cksum = chrp_nv_cksum(h); + + return 0; } /* diff --git a/core/test/run-nvram-format.c b/core/test/run-nvram-format.c index 7fb4217..77b759b 100644 --- a/core/test/run-nvram-format.c +++ b/core/test/run-nvram-format.c @@ -21,11 +21,94 @@ int main(void) { char *nvram_image = malloc(0x100000); + size_t sz; + struct chrp_nvram_hdr *h; - nvram_format(nvram_image, 0x100000); - + assert(nvram_format(nvram_image, 0x100000) == 0); assert(nvram_check(nvram_image, 0x100000) == 0); free(nvram_image); + + /* 1024 bytes is too small for our NVRAM */ + nvram_image = malloc(1024); + assert(nvram_format(nvram_image, 1024)!=0); + free(nvram_image); + + /* 4096 bytes is too small for our NVRAM */ + nvram_image = malloc(4096); + assert(nvram_format(nvram_image, 4096)!=0); + free(nvram_image); + + /* 64k is too small for our NVRAM */ + nvram_image = malloc(0x10000); + assert(nvram_format(nvram_image, 0x10000)!=0); + free(nvram_image); + + /* 68k is too small for our NVRAM */ + nvram_image = malloc(68*1024); + assert(nvram_format(nvram_image, 68*1024)!=0); + free(nvram_image); + + /* 68k+16 bytes (nvram header) should generate empty free space */ + sz = NVRAM_SIZE_COMMON + NVRAM_SIZE_FW_PRIV + + sizeof(struct chrp_nvram_hdr); + 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); + free(nvram_image); + + /* 128k NVRAM check */ + nvram_image = malloc(128*1024); + assert(nvram_format(nvram_image, 128*1024)==0); + assert(nvram_check(nvram_image,128*1024)==0); + + /* Now, we corrupt it */ + nvram_image[0] = 0; + assert(nvram_check(nvram_image,128*1024) != 0); + + assert(nvram_format(nvram_image, 128*1024)==0); + /* corrupt the length of the partition */ + nvram_image[2] = 0; + nvram_image[3] = 0; + assert(nvram_check(nvram_image,128*1024) != 0); + + assert(nvram_format(nvram_image, 128*1024)==0); + /* corrupt the length of the partition */ + nvram_image[2] = 0; + nvram_image[3] = 0; + /* but reset checksum! */ + h = (struct chrp_nvram_hdr*)nvram_image; + h->cksum = chrp_nv_cksum(h); + assert(nvram_check(nvram_image,128*1024) != 0); + + assert(nvram_format(nvram_image, 128*1024)==0); + /* make the length insanely beyond end of nvram */ + nvram_image[2] = 42; + nvram_image[3] = 32; + /* but reset checksum! */ + h = (struct chrp_nvram_hdr*)nvram_image; + h->cksum = chrp_nv_cksum(h); + assert(nvram_check(nvram_image,128*1024) != 0); + + assert(nvram_format(nvram_image, 128*1024)==0); + /* remove skiboot partition */ + nvram_image[12] = '\0'; + /* but reset checksum! */ + h = (struct chrp_nvram_hdr*)nvram_image; + h->cksum = chrp_nv_cksum(h); + assert(nvram_check(nvram_image,128*1024) != 0); + + assert(nvram_format(nvram_image, 128*1024)==0); + /* remove common partition */ + nvram_image[NVRAM_SIZE_FW_PRIV+5] = '\0'; + /* but reset checksum! */ + h = (struct chrp_nvram_hdr*)(&nvram_image[NVRAM_SIZE_FW_PRIV]); + h->cksum = chrp_nv_cksum(h); + assert(nvram_check(nvram_image,128*1024) != 0); + + free(nvram_image); + return 0; } diff --git a/include/nvram-format.h b/include/nvram-format.h index 693f0bd..d7432a7 100644 --- a/include/nvram-format.h +++ b/include/nvram-format.h @@ -17,7 +17,7 @@ #ifndef __NVRAM_FORMAT_H #define __NVRAM_FORMAT_H -void nvram_format(void *nvram_image, uint32_t nvram_size); +int nvram_format(void *nvram_image, uint32_t nvram_size); int nvram_check(void *nvram_image, uint32_t nvram_size); #endif /* __NVRAM_FORMAT_H */ |