first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,41 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <lib/blockdev.h>
|
||||
#include <lib/env.h>
|
||||
#include <lib/nvram.h>
|
||||
|
||||
struct blockdev *create_mock_blockdev(const char *name, const char *filename, uint32_t block_size);
|
||||
|
||||
int do_printenv(int argc, void *args);
|
||||
|
||||
int fuzz_main(const char *filename)
|
||||
{
|
||||
struct blockdev *bdev;
|
||||
int result;
|
||||
|
||||
bdev = create_mock_blockdev("nvram", filename, 1);
|
||||
if (bdev != NULL)
|
||||
register_blockdev(bdev);
|
||||
|
||||
result = nvram_load();
|
||||
if (result != 0) {
|
||||
do_printenv(0, NULL);
|
||||
nvram_save();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Mock for lib/env
|
||||
bool
|
||||
env_blacklist(const char *name, bool write)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
env_blacklist_nvram(const char *name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
# Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
|
||||
LIBNVRAM_DIR := $(GET_LOCAL_DIR)
|
||||
LIBNVRAM_BUILD := $(call TOLIBDIR,$(LIBNVRAM_DIR)/LIBNVRAM.a)
|
||||
COMMONLIBS += LIBNVRAM
|
||||
|
||||
# Only process the remainder of the makefile if we are building libraries
|
||||
#
|
||||
ifeq ($(MAKEPHASE),libraries)
|
||||
|
||||
LIBNVRAM_OBJS := $(LIBNVRAM_DIR)/nvram.o
|
||||
|
||||
LIBNVRAM_OBJS := $(call TOLIBOBJDIR,$(LIBNVRAM_OBJS))
|
||||
|
||||
ALL_DEPS += $(LIBNVRAM_OBJS:%o=%d)
|
||||
|
||||
$(LIBNVRAM_BUILD): $(LIBNVRAM_OBJS)
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,555 @@
|
||||
/*
|
||||
* Copyright (c) 2007-2012 Apple Inc. All rights reserved.
|
||||
* Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <stdlib.h>
|
||||
#include <list.h>
|
||||
#include <lib/blockdev.h>
|
||||
#include <lib/cksum.h>
|
||||
#include <lib/env.h>
|
||||
#include <lib/libiboot.h>
|
||||
#include <lib/nvram.h>
|
||||
#include <string.h>
|
||||
#include <sys/menu.h>
|
||||
|
||||
/*
|
||||
* Regardless of whether it is NOR or NAND providing the backing
|
||||
* store, NVRAM_BANK_SIZE controls default size of each nvram bank.
|
||||
*/
|
||||
#define NVRAM_BANK_SIZE 0x2000
|
||||
|
||||
/*
|
||||
* Support for CHRP NVRAM hosting our environment.
|
||||
*/
|
||||
|
||||
/* this is a somewhat arbitrary and historical value */
|
||||
#define NVRAM_MAX_ENV_PARTITION 0x7f0
|
||||
|
||||
/* Panic info partition */
|
||||
#define NVRAM_PANIC_NAME "APL,OSXPanic"
|
||||
#define NVRAM_PANIC_NAME_TRUNCATED "APL,OSXPani"
|
||||
#define NVRAM_PANIC_SIZE 0x800
|
||||
#define NVRAM_PANIC_SIG 0xa1
|
||||
|
||||
struct chrp_nvram_header {
|
||||
uint8_t sig;
|
||||
uint8_t cksum;
|
||||
uint16_t len;
|
||||
char name[12];
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
struct apple_nvram_header {
|
||||
struct chrp_nvram_header chrp;
|
||||
uint32_t adler;
|
||||
uint32_t generation;
|
||||
uint8_t padding[8];
|
||||
};
|
||||
|
||||
/* in memory representation of a nvram partition */
|
||||
struct nvram_partition {
|
||||
struct list_node node;
|
||||
|
||||
uint8_t chrp_sig;
|
||||
size_t len;
|
||||
uint8_t *data;
|
||||
|
||||
char name[16];
|
||||
};
|
||||
|
||||
/* in memory representation of a nvram bank (may be multiple ones) */
|
||||
struct nvram_bank {
|
||||
struct list_node node;
|
||||
|
||||
struct list_node part_list;
|
||||
struct blockdev *dev;
|
||||
off_t offset;
|
||||
size_t len;
|
||||
|
||||
uint32_t generation;
|
||||
};
|
||||
|
||||
static struct list_node nvram_bank_list = LIST_INITIAL_VALUE(nvram_bank_list);
|
||||
static struct nvram_bank *newest_bank;
|
||||
static struct nvram_bank *oldest_bank;
|
||||
|
||||
static uint8_t chrp_checksum(const struct chrp_nvram_header *hdr)
|
||||
{
|
||||
uint16_t sum;
|
||||
const uint8_t *p;
|
||||
|
||||
/* checksum the header (minus the checksum itself) */
|
||||
sum = hdr->sig;
|
||||
for (p = (const uint8_t *)&hdr->len; p < hdr->data; p++)
|
||||
sum += *p;
|
||||
while (sum > 0xff)
|
||||
sum = (sum & 0xff) + (sum >> 8);
|
||||
return sum;
|
||||
}
|
||||
|
||||
static struct nvram_partition *find_part_in_bank(const struct nvram_bank *bank, const char *name)
|
||||
{
|
||||
struct nvram_partition *part;
|
||||
|
||||
list_for_every_entry(&bank->part_list, part, struct nvram_partition, node) {
|
||||
if (!strcmp(name, part->name))
|
||||
return part;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* find the oldest and newest banks */
|
||||
static void sort_bank_age(void)
|
||||
{
|
||||
struct nvram_bank *bank;
|
||||
|
||||
list_for_every_entry(&nvram_bank_list, bank, struct nvram_bank, node) {
|
||||
if (!oldest_bank || bank->generation < oldest_bank->generation)
|
||||
oldest_bank = bank;
|
||||
if (!newest_bank || bank->generation > newest_bank->generation)
|
||||
newest_bank = bank;
|
||||
}
|
||||
}
|
||||
|
||||
static int load_bank_partitions(struct nvram_bank *bank, uint8_t *buf)
|
||||
{
|
||||
struct chrp_nvram_header *hdr;
|
||||
struct nvram_partition *part = NULL;
|
||||
size_t offset;
|
||||
|
||||
offset = 0x20;
|
||||
while ((offset + sizeof(struct chrp_nvram_header)) <= bank->len) {
|
||||
hdr = (struct chrp_nvram_header *)(buf + offset);
|
||||
|
||||
#if 0
|
||||
dprintf(DEBUG_SPEW, "nvram: load_bank_partitions: looking at header at offset %u\n", offset);
|
||||
dhexdump(DEBUG_SPEW, hdr, sizeof(*hdr));
|
||||
#endif
|
||||
|
||||
/* verify the checksum */
|
||||
if (hdr->cksum != chrp_checksum(hdr)) {
|
||||
#if !NVRAM_NOCHECKSUM
|
||||
printf("load_bank_partitions: checksum failure\n");
|
||||
goto error_exit;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* is it free space? if so, we're done */
|
||||
if (hdr->sig == 0x7f)
|
||||
break;
|
||||
|
||||
/* see if the length makes sense */
|
||||
if (((hdr->len * 0x10) + offset > bank->len) || (hdr->len < 1)) {
|
||||
printf("load_bank_partitions: partition len out of range\n");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* skip it if it's a known corrupted partition name */
|
||||
if (!memcmp(hdr->name, NVRAM_PANIC_NAME_TRUNCATED, 12)) {
|
||||
/* The last byte shouldn't have been terminated */
|
||||
offset += hdr->len * 0x10;
|
||||
/* This partition should disappear when written back */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* it's good, create a partition */
|
||||
part = malloc(sizeof(struct nvram_partition));
|
||||
|
||||
/* note that 0x10 == sizeof(struct chrp_nvram_header) */
|
||||
part->chrp_sig = hdr->sig;
|
||||
part->len = (hdr->len * 0x10) - 0x10;
|
||||
ASSERT(sizeof(part->name) >= sizeof(hdr->name) + 1);
|
||||
memcpy(part->name, hdr->name, sizeof(hdr->name));
|
||||
part->name[sizeof(hdr->name)] = '\0';
|
||||
part->data = malloc(part->len);
|
||||
memcpy(part->data, buf + offset + 0x10, part->len);
|
||||
|
||||
dprintf(DEBUG_SPEW, "found partition '%s' at offset %zu, len %zu\n", part->name, offset, part->len);
|
||||
|
||||
/* add it to the bank list */
|
||||
list_add_tail(&bank->part_list, &part->node);
|
||||
|
||||
offset += hdr->len * 0x10;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_exit:
|
||||
if (part != NULL) {
|
||||
if (part->data != NULL)
|
||||
free(part->data);
|
||||
|
||||
free(part);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void process_loaded_bank(struct nvram_bank *bank)
|
||||
{
|
||||
struct nvram_partition *part;
|
||||
|
||||
/* look for the environment variable partition */
|
||||
part = find_part_in_bank(bank, "common");
|
||||
if (part) {
|
||||
|
||||
env_unserialize(part->data, part->len);
|
||||
}
|
||||
}
|
||||
|
||||
static int nvram_save_env(struct nvram_bank *bank)
|
||||
{
|
||||
struct nvram_partition *part;
|
||||
size_t env_length;
|
||||
|
||||
/* see if there's already a common partition */
|
||||
part = find_part_in_bank(bank, "common");
|
||||
if (part == NULL) {
|
||||
/* create a new one */
|
||||
part = calloc(1, sizeof(struct nvram_partition));
|
||||
part->chrp_sig = 0x70;
|
||||
strlcpy(part->name, "common", sizeof(part->name));
|
||||
part->len = 0;
|
||||
part->data = NULL;
|
||||
|
||||
list_add_head(&bank->part_list, &part->node);
|
||||
}
|
||||
|
||||
/* throw away the old data, we're going to overwrite it */
|
||||
if (part->data)
|
||||
free(part->data);
|
||||
|
||||
/* allocate a new buffer for this data */
|
||||
part->len = NVRAM_MAX_ENV_PARTITION;
|
||||
part->data = malloc(part->len);
|
||||
|
||||
/* serialise environment and adjust buffer size to suit */
|
||||
env_length = env_serialize(part->data, part->len);
|
||||
memset(part->data + env_length, 0, part->len - env_length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvram_prepare_bank(struct nvram_bank *bank, uint8_t *buf)
|
||||
{
|
||||
int err = 0;
|
||||
struct nvram_partition *part;
|
||||
struct apple_nvram_header *apple_hdr;
|
||||
struct chrp_nvram_header *hdr;
|
||||
size_t offset;
|
||||
|
||||
/* lay down an apple nvram header */
|
||||
apple_hdr = (struct apple_nvram_header *)buf;
|
||||
apple_hdr->chrp.sig = 0x5a;
|
||||
apple_hdr->chrp.len = 0x2; // 0x20 bytes
|
||||
memcpy(apple_hdr->chrp.name, "nvram", sizeof("nvram"));
|
||||
apple_hdr->chrp.cksum = chrp_checksum(&apple_hdr->chrp);
|
||||
apple_hdr->generation = bank->generation;
|
||||
|
||||
/* iterate through each of the sections in the nvram, laying them out in the buffer */
|
||||
offset = 0x20;
|
||||
list_for_every_entry(&bank->part_list, part, struct nvram_partition, node) {
|
||||
|
||||
/* partition must have data */
|
||||
if (0 == part->len)
|
||||
goto fail;
|
||||
|
||||
/* make sure there is room to establish a header in the buffer */
|
||||
if ((offset + sizeof(struct chrp_nvram_header)) > bank->len)
|
||||
goto fail;
|
||||
|
||||
hdr = (struct chrp_nvram_header *)&buf[offset];
|
||||
hdr->sig = part->chrp_sig;
|
||||
hdr->len = ROUNDUP(part->len + 0x10, 0x10) / 0x10;
|
||||
memcpy(hdr->name, part->name, sizeof(hdr->name));
|
||||
hdr->cksum = chrp_checksum(hdr);
|
||||
|
||||
/* make sure there is room to copy data into the buffer */
|
||||
if ((offset + sizeof(struct chrp_nvram_header) + part->len) > bank->len)
|
||||
goto fail;
|
||||
|
||||
memcpy(hdr->data, part->data, part->len);
|
||||
|
||||
offset += hdr->len * 0x10;
|
||||
}
|
||||
|
||||
/* write out a free space partition to cover the rest of the buffer, if there's free space */
|
||||
if ((offset + sizeof(struct chrp_nvram_header)) <= bank->len) {
|
||||
hdr = (struct chrp_nvram_header *)&buf[offset];
|
||||
hdr->sig = 0x7f;
|
||||
hdr->len = (bank->len - offset) / 0x10;
|
||||
memset(hdr->name, 0x77, sizeof(hdr->name));
|
||||
hdr->cksum = chrp_checksum(hdr);
|
||||
}
|
||||
|
||||
/* fill in the adler32 checksum on the apple header */
|
||||
apple_hdr->adler = adler32(buf + 0x14, bank->len - 0x14);
|
||||
|
||||
out:
|
||||
return err;
|
||||
fail:
|
||||
err = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int nvram_write_bank(struct nvram_bank *bank)
|
||||
{
|
||||
int err;
|
||||
uint8_t *buf;
|
||||
|
||||
/* allocate a buffer to stage this in */
|
||||
buf = calloc(1, bank->len);
|
||||
|
||||
/* prepare buf with bank data */
|
||||
err = nvram_prepare_bank(bank, buf);
|
||||
if (err) {
|
||||
dprintf(DEBUG_CRITICAL, "unable to prepare buffer with nvram bank data\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* write it out */
|
||||
if (bank->dev) {
|
||||
dprintf(DEBUG_INFO, "saving nvram contents at bdev '%s', offset 0x%llx, len 0x%zx, gen %d\n",
|
||||
bank->dev->name, bank->offset, bank->len, bank->generation);
|
||||
err = blockdev_write(bank->dev, buf, bank->offset, bank->len);
|
||||
} else {
|
||||
err = 0;
|
||||
dprintf(DEBUG_CRITICAL, "nowhere to save environment\n");
|
||||
}
|
||||
#if 0
|
||||
printf("would have written this to offset 0x%llx, len %d:\n", bank->offset, bank->len);
|
||||
hexdump(buf, bank->len);
|
||||
#endif
|
||||
out:
|
||||
free(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
int nvram_save(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* overwrite the 'oldest' bank (lowest generation count) */
|
||||
if (!oldest_bank) {
|
||||
printf("nvram_save: no oldest bank previously saved, dropping request\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find the next generation number to assign this bank */
|
||||
if (newest_bank)
|
||||
oldest_bank->generation = newest_bank->generation + 1;
|
||||
else
|
||||
oldest_bank->generation = 1;
|
||||
|
||||
/* write out our environment */
|
||||
nvram_save_env(oldest_bank);
|
||||
|
||||
/* write out the bank */
|
||||
err = nvram_write_bank(oldest_bank);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* we have a new oldest bank, reevaluate */
|
||||
sort_bank_age();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nvram_set_panic(const void *panic_data, size_t length)
|
||||
{
|
||||
struct nvram_partition *part;
|
||||
|
||||
/* overwrite the 'oldest' bank (lowest generation count) */
|
||||
if (!oldest_bank) {
|
||||
printf("nvram_set_panic: no oldest bank previously saved, dropping request\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find a panic info partition */
|
||||
part = find_part_in_bank(oldest_bank, NVRAM_PANIC_NAME);
|
||||
if (part == NULL) {
|
||||
/* create a new one */
|
||||
part = calloc(1, sizeof(struct nvram_partition));
|
||||
part->chrp_sig = NVRAM_PANIC_SIG;
|
||||
strlcpy(part->name, NVRAM_PANIC_NAME, sizeof(part->name));
|
||||
part->len = NVRAM_PANIC_SIZE;
|
||||
part->data = malloc(NVRAM_PANIC_SIZE);
|
||||
|
||||
list_add_head(&oldest_bank->part_list, &part->node);
|
||||
}
|
||||
if (part->len < 5) {
|
||||
/* partition not big enough to store anything */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* the first 4 bytes are the panic length. adjust length to fit. */
|
||||
if (length + 4 > part->len) length = part->len - 4;
|
||||
*(uint32_t *) part->data = length;
|
||||
|
||||
/* copy panic data into the partition. */
|
||||
memcpy(part->data + 4, panic_data, length);
|
||||
|
||||
/* zero the remainder of the partition. */
|
||||
memset(part->data + 4 + length, 0, part->len - length - 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvram_load_dev(struct blockdev *dev, off_t offset, size_t banklen, int count)
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
uint8_t *buf;
|
||||
int banks_found = 0;
|
||||
|
||||
if (offset < 0) {
|
||||
offset = dev->total_len + offset;
|
||||
}
|
||||
|
||||
buf = malloc(banklen);
|
||||
|
||||
for (i=0; i < count; i++, offset += banklen) {
|
||||
struct nvram_bank *bank;
|
||||
struct apple_nvram_header *hdr;
|
||||
|
||||
/* read in potential nvram bank */
|
||||
if (dev == NULL) {
|
||||
dprintf(DEBUG_INFO, "nowhere to load environment from; using transient buffer-only solution\n");
|
||||
goto bank_fail;
|
||||
}
|
||||
|
||||
err = blockdev_read(dev, buf, offset, banklen);
|
||||
if (err <= 0) {
|
||||
dprintf(DEBUG_INFO, "nvram_load: failed to read potential nvram bank at offset 0x%llx\n", offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("potential nvram bank: \n");
|
||||
hexdump(buf, banklen);
|
||||
#endif
|
||||
|
||||
/* see if it starts with a valid header */
|
||||
hdr = (struct apple_nvram_header *)buf;
|
||||
if (hdr->chrp.cksum != chrp_checksum(&hdr->chrp)) {
|
||||
#if !NVRAM_NOCHECKSUM
|
||||
dprintf(DEBUG_INFO, "nvram_load: nvram partition at offset 0x%llx failed checksum\n", offset);
|
||||
goto bank_fail;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* do an adler32 of the entire buffer */
|
||||
uint32_t adler = adler32(buf + 0x14, banklen - 0x14);
|
||||
if (adler != hdr->adler) {
|
||||
#if !NVRAM_NOCHECKSUM
|
||||
dprintf(DEBUG_INFO, "nvram_load: nvram bank fails adler32\n");
|
||||
goto bank_fail;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* valid header, lets start building a bank structure */
|
||||
bank = malloc(sizeof(struct nvram_bank));
|
||||
|
||||
list_initialize(&bank->part_list);
|
||||
bank->dev = dev;
|
||||
bank->offset = offset;
|
||||
bank->len = banklen;
|
||||
bank->generation = hdr->generation;
|
||||
|
||||
/* read in the partitions within the bank */
|
||||
err = load_bank_partitions(bank, buf);
|
||||
if (err < 0) {
|
||||
// error parsing partitions, free this bank and continue
|
||||
free(bank);
|
||||
goto bank_fail;
|
||||
}
|
||||
|
||||
/* add the bank to the list */
|
||||
list_add_tail(&nvram_bank_list, &bank->node);
|
||||
|
||||
banks_found++;
|
||||
continue;
|
||||
|
||||
bank_fail:
|
||||
/* we failed to load a bank at a nvram slot, allocate a blank bank */
|
||||
bank = malloc(sizeof(struct nvram_bank));
|
||||
list_initialize(&bank->part_list);
|
||||
bank->dev = dev;
|
||||
bank->offset = offset;
|
||||
bank->len = banklen;
|
||||
bank->generation = 0;
|
||||
|
||||
dprintf(DEBUG_INFO, "nvram_load: found invalid or empty bank at 0x%llx, creating blank bank\n", offset);
|
||||
|
||||
/* add the bank to the list */
|
||||
banks_found++;
|
||||
list_add_tail(&nvram_bank_list, &bank->node);
|
||||
}
|
||||
|
||||
dprintf(DEBUG_INFO, "nvram_load: found %d banks of nvram\n", banks_found);
|
||||
|
||||
if (banks_found) {
|
||||
/* search through the bank list, sorting by age */
|
||||
sort_bank_age();
|
||||
|
||||
/* do any bank processing on the current (newest) bank */
|
||||
process_loaded_bank(newest_bank);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return banks_found;
|
||||
}
|
||||
|
||||
int nvram_load(void)
|
||||
{
|
||||
int result;
|
||||
struct blockdev *bdev;
|
||||
|
||||
dprintf(DEBUG_INFO, "loading nvram\n");
|
||||
|
||||
// Look for a real NVRAM block device
|
||||
bdev = lookup_blockdev("nvram");
|
||||
if (bdev) {
|
||||
result = nvram_load_dev(bdev, 0, NVRAM_BANK_SIZE, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Fall back to just creating a temporary nvram not backed by any block device */
|
||||
return (nvram_load_dev(NULL, 0, NVRAM_BANK_SIZE, 1) ? 0 : -1);
|
||||
}
|
||||
|
||||
int nvram_update_devicetree(dt_node_t *node, const char *propname)
|
||||
{
|
||||
uint8_t *buf;
|
||||
int err = -1;
|
||||
|
||||
if (!oldest_bank) {
|
||||
panic("nvram_update_devicetree: no bank previously saved\n");
|
||||
} else if (!newest_bank) {
|
||||
dprintf(DEBUG_CRITICAL, "nvram_update_devicetree: no content available\n");
|
||||
} else {
|
||||
buf = malloc(newest_bank->len);
|
||||
/* prepare device tree proper buffer with bank data */
|
||||
err = nvram_prepare_bank(newest_bank, buf);
|
||||
|
||||
if (err) {
|
||||
dprintf(DEBUG_CRITICAL, "nvram_update_devicetree: unable to update devicetree with nvram content\n");
|
||||
} else {
|
||||
dt_set_prop(node, propname, buf, newest_bank->len);
|
||||
dprintf(DEBUG_INFO, "nvram_update_devicetree: updated devicetree with nvram generation %d\n",
|
||||
newest_bank->generation);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
|
||||
# Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
|
||||
OPTIONS += WITH_NVRAM=1
|
||||
|
||||
MODULES += \
|
||||
lib/cksum \
|
||||
lib/env \
|
||||
lib/heap
|
||||
|
||||
LIBRARY_MODULES += lib/nvram
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
|
||||
TEST_OBJS := \
|
||||
lib/blockdev/blockdev.o \
|
||||
lib/cksum/adler32.o \
|
||||
lib/env/env.o \
|
||||
lib/libc/log2.o \
|
||||
lib/nvram/nvram.o
|
||||
|
||||
TEST_SUPPORT_OBJS := \
|
||||
tests/mocks/sys/security.o \
|
||||
tests/mocks/syscfg.o \
|
||||
lib/devicetree/devicetree.o
|
||||
|
||||
TEST_CFLAGS := \
|
||||
-DCPU_CACHELINE_SIZE=32
|
||||
@@ -0,0 +1,24 @@
|
||||
# Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
TEST_NAME := nvram-fuzz
|
||||
|
||||
include $(LOCAL_DIR)/tests-common.mk
|
||||
|
||||
TEST_SUPPORT_OBJS += \
|
||||
tests/fuzz-main.o \
|
||||
tests/mocks/blockdev.o \
|
||||
$(LOCAL_DIR)/fuzz.o
|
||||
|
||||
TEST_CFLAGS += \
|
||||
-DNVRAM_NOCHECKSUM=1
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#include <stdint.h>
|
||||
#include <unittest.h>
|
||||
#include <lib/blockdev.h>
|
||||
#include <lib/env.h>
|
||||
#include <lib/nvram.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// There aren't any useful test cases here yet, as the nvram
|
||||
// testing infrastructure was mainly added to allow fuzzing.
|
||||
// For unit testing, we need a sample NVRAM and then some
|
||||
// getenv calls
|
||||
|
||||
// For now, this just exercises the the "empty NVRAM" case
|
||||
static void test_nvram_load(uintptr_t ctx)
|
||||
{
|
||||
struct blockdev *bdev;
|
||||
int result;
|
||||
void *backing;
|
||||
|
||||
backing = calloc(8192, 1);
|
||||
|
||||
bdev = create_mem_blockdev("nvram", backing, 8192, 4096);
|
||||
if (bdev != NULL)
|
||||
register_blockdev(bdev);
|
||||
|
||||
result = nvram_load();
|
||||
}
|
||||
|
||||
struct test_suite nvram_suite = {
|
||||
.name = "nvram",
|
||||
.test_cases = {
|
||||
{ "nvram_load", test_nvram_load, 0, "" },
|
||||
TEST_CASE_LAST
|
||||
}
|
||||
};
|
||||
|
||||
TEST_SUITE(nvram_suite);
|
||||
|
||||
// Mock for lib/env
|
||||
bool
|
||||
env_blacklist(const char *name, bool write)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
env_blacklist_nvram(const char *name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
# Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
TEST_NAME := nvram
|
||||
|
||||
include $(LOCAL_DIR)/tests-common.mk
|
||||
|
||||
TEST_OBJS += \
|
||||
lib/blockdev/mem_blockdev.o
|
||||
|
||||
TEST_SUPPORT_OBJS += \
|
||||
tests/unittest-main.o \
|
||||
$(LOCAL_DIR)/tests.o
|
||||
Reference in new issue
Block a user