first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -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.
|
||||
#
|
||||
|
||||
LIBSYSCFG_DIR := $(GET_LOCAL_DIR)
|
||||
LIBSYSCFG_BUILD := $(call TOLIBDIR,$(LIBSYSCFG_DIR)/LIBSYSCFG.a)
|
||||
COMMONLIBS += LIBSYSCFG
|
||||
|
||||
# Only process the remainder of the makefile if we are building libraries
|
||||
#
|
||||
ifeq ($(MAKEPHASE),libraries)
|
||||
|
||||
LIBSYSCFG_OBJS := $(LIBSYSCFG_DIR)/syscfg.o
|
||||
|
||||
LIBSYSCFG_OBJS := $(call TOLIBOBJDIR,$(LIBSYSCFG_OBJS))
|
||||
|
||||
ALL_DEPS += $(LIBSYSCFG_OBJS:%o=%d)
|
||||
|
||||
$(LIBSYSCFG_BUILD): $(LIBSYSCFG_OBJS)
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright (C) 2007, 2011, 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_SYSCFG=1
|
||||
LIBRARY_MODULES += lib/syscfg
|
||||
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2012, 2014 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, 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 Computer, Inc.
|
||||
*/
|
||||
/*
|
||||
* Support for detecting and reading the iPod-style SysCfg data
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <lib/syscfg.h>
|
||||
#include <lib/blockdev.h>
|
||||
#include <sys/menu.h>
|
||||
|
||||
static u_int32_t syscfgKeyCount;
|
||||
static uint8_t *syscfgData;
|
||||
static size_t syscfgDataLength;
|
||||
|
||||
struct syscfgHeader {
|
||||
u_int32_t shMagic;
|
||||
#define kSysCfgHeaderMagic 'SCfg'
|
||||
u_int32_t shSize;
|
||||
u_int32_t shMaxSize;
|
||||
u_int32_t shVersion;
|
||||
u_int32_t shBigEndian;
|
||||
u_int32_t shKeyCount;
|
||||
};
|
||||
|
||||
void syscfg_reinit(void)
|
||||
{
|
||||
free(syscfgData);
|
||||
syscfgDataLength = 0;
|
||||
syscfgData = NULL;
|
||||
syscfgKeyCount = 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_syscfg(int argc, struct cmd_arg *args)
|
||||
{
|
||||
struct syscfgHeader hdr;
|
||||
struct syscfgMemEntry entry;
|
||||
int index, curArg;
|
||||
size_t size, i, j;
|
||||
char *sfx;
|
||||
bool isExt;
|
||||
size_t lowExt;
|
||||
size_t highExt;
|
||||
size_t extSize = 0;
|
||||
uint8_t *buffer;
|
||||
bool showExt = false;
|
||||
|
||||
if (NULL == syscfgData) {
|
||||
printf("syscfg is not initialized!\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (syscfgDataLength < sizeof(struct syscfgHeader))
|
||||
return (0);
|
||||
|
||||
memcpy(&hdr, syscfgData, sizeof(struct syscfgHeader));
|
||||
printf("version 0x%08x with %d entries\n\n", hdr.shVersion, hdr.shKeyCount);
|
||||
|
||||
lowExt = hdr.shMaxSize;
|
||||
highExt = hdr.shSize;
|
||||
|
||||
for (index = 0; ; index++) {
|
||||
if (!syscfgFindByIndex(index, &entry))
|
||||
break;
|
||||
|
||||
if (argc > 1) {
|
||||
|
||||
/* When parameters are present, always show in extended mode */
|
||||
showExt = true;
|
||||
|
||||
/* If the first parameter is ext, assume match in all cases by skipping the match block */
|
||||
if(strcmp("ext", args[1].str) != 0) {
|
||||
|
||||
/* Scan the list of arguments looking for a match */
|
||||
for (curArg = 1; curArg < argc; curArg ++) {
|
||||
if (((entry.seTag >> 24) & 0xFF) == args[curArg].str[0] &&
|
||||
((entry.seTag >> 16) & 0xFF) == args[curArg].str[1] &&
|
||||
((entry.seTag >> 8) & 0xFF) == args[curArg].str[2] &&
|
||||
((entry.seTag >> 0) & 0xFF) == args[curArg].str[3])
|
||||
break;
|
||||
}
|
||||
if (curArg == argc) continue;
|
||||
}
|
||||
}
|
||||
|
||||
sfx = "";
|
||||
|
||||
/* Is this a standard entry or an Offset entry? */
|
||||
if (entry.seDataOffset != 0) {
|
||||
size = entry.seDataSize;
|
||||
if (size > sizeof(entry.seData)) {
|
||||
|
||||
/* The Size of the entry is too big for the structure
|
||||
* Should it be truncated? */
|
||||
if (!showExt) {
|
||||
size = sizeof(entry.seData);
|
||||
sfx = "...";
|
||||
}
|
||||
}
|
||||
if (entry.seDataOffset + entry.seDataSize > hdr.shMaxSize) {
|
||||
printf("entry->seDataOffset not within syscfgData");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Allocate the requested space aligned on 16 bytes to zero
|
||||
* pad the display. */
|
||||
buffer = calloc(1, (size + 15) & ~15);
|
||||
memcpy(buffer, syscfgData + entry.seDataOffset, size);
|
||||
|
||||
// Calculate the extents of the offset section
|
||||
if (entry.seDataOffset < lowExt) {
|
||||
lowExt = entry.seDataOffset;
|
||||
}
|
||||
if ((entry.seDataOffset + entry.seDataSize) > highExt) {
|
||||
highExt = entry.seDataOffset + entry.seDataSize;
|
||||
}
|
||||
isExt = true;
|
||||
} else {
|
||||
/* allocate enough space to mirror the entrys buffer */
|
||||
size = sizeof(entry.seData);
|
||||
|
||||
buffer = malloc(sizeof(entry.seData));
|
||||
memcpy(buffer, entry.seData, size);
|
||||
|
||||
isExt = false;
|
||||
}
|
||||
printf("0x%08x '%c%c%c%c' %4dB %c ",
|
||||
entry.seTag,
|
||||
(entry.seTag >> 24) & 0xff,
|
||||
(entry.seTag >> 16) & 0xff,
|
||||
(entry.seTag >> 8) & 0xff,
|
||||
entry.seTag & 0xff,
|
||||
entry.seDataSize,
|
||||
isExt ? '*' : ' ');
|
||||
|
||||
/* Format the data in nice columns */
|
||||
for (i = 0; i < size; i += 16 ) {
|
||||
printf("%*s", (i >= 16) ? 28 : 0, "");
|
||||
|
||||
/* Starting at the offset, display the data values up to 4 per line. */
|
||||
for (j = i; j < (i + 16); j += 4) {
|
||||
printf("0x%08x ", *((u_int32_t *)&buffer[j]));
|
||||
}
|
||||
|
||||
printf("%s\n", sfx);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("header @ 0-%zu", sizeof(struct syscfgHeader) - 1);
|
||||
printf("; entries @ %zu-%d", sizeof(struct syscfgHeader), hdr.shSize - 1);
|
||||
if (lowExt < highExt) {
|
||||
extSize = highExt - lowExt;
|
||||
printf("; extra data @ %zu-%zu", lowExt, highExt - 1);
|
||||
}
|
||||
printf("; using %zu of %d bytes\n", hdr.shSize + extSize, hdr.shMaxSize);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool
|
||||
syscfgInitWithBdev(const char *bdevName)
|
||||
{
|
||||
int result;
|
||||
struct blockdev *candidate;
|
||||
struct syscfgHeader hdr;
|
||||
|
||||
if (syscfgData != NULL)
|
||||
return(false);
|
||||
|
||||
/* look for the suggested bdev */
|
||||
if ((candidate = lookup_blockdev(bdevName)) == NULL) {
|
||||
dprintf(DEBUG_INFO, "syscfg: can't find bdev \"%s\"\n", bdevName);
|
||||
return(false);
|
||||
}
|
||||
|
||||
/* Make sure it's big enough */
|
||||
if (candidate->total_len <= kSysCfgBdevOffset + sizeof(hdr)) {
|
||||
dprintf(DEBUG_INFO, "syscfg: bdev size 0x%llx too small\n", candidate->total_len);
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* look for the header */
|
||||
if (blockdev_read(candidate, &hdr, kSysCfgBdevOffset, sizeof(hdr)) < (int)sizeof(hdr)) {
|
||||
dprintf(DEBUG_INFO, "syscfg: bdev read fail\n");
|
||||
return(false);
|
||||
}
|
||||
|
||||
if (hdr.shMagic != kSysCfgHeaderMagic) {
|
||||
dprintf(DEBUG_INFO, "syscfg: bad magic\n");
|
||||
return(false);
|
||||
}
|
||||
|
||||
dprintf(DEBUG_CRITICAL, "syscfg: version 0x%08x with %d entries using %d of %d bytes\n",
|
||||
hdr.shVersion, hdr.shKeyCount, hdr.shSize, hdr.shMaxSize);
|
||||
|
||||
/* If there is a syscfg there will also be diag info... protect them. */
|
||||
blockdev_set_protection(candidate, 0x2000, 0x6000);
|
||||
|
||||
syscfgDataLength = candidate->total_len - kSysCfgBdevOffset;
|
||||
if (hdr.shSize < syscfgDataLength)
|
||||
syscfgDataLength = hdr.shMaxSize;
|
||||
|
||||
syscfgData = malloc(syscfgDataLength);
|
||||
|
||||
result = blockdev_read(candidate, syscfgData, kSysCfgBdevOffset, syscfgDataLength);
|
||||
|
||||
if (result < 0 || (size_t)result < syscfgDataLength) {
|
||||
dprintf(DEBUG_INFO, "syscfg: bdev read fail (%d)\n", result);
|
||||
syscfg_reinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
syscfgKeyCount = hdr.shKeyCount;
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
void *
|
||||
syscfgGetData(struct syscfgMemEntry *entry)
|
||||
{
|
||||
/* Handle data stored externally from the entry */
|
||||
if (entry->seDataOffset != 0) {
|
||||
if (entry->seDataOffset > syscfgDataLength)
|
||||
return NULL;
|
||||
if (entry->seDataOffset + entry->seDataSize > syscfgDataLength)
|
||||
return NULL;
|
||||
|
||||
return syscfgData + entry->seDataOffset;
|
||||
} else {
|
||||
return entry->seData;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
syscfgGetSize(struct syscfgMemEntry *entry)
|
||||
{
|
||||
return entry->seDataSize;
|
||||
}
|
||||
|
||||
int
|
||||
syscfgCopyDataForTag(u_int32_t tag, u_int8_t *buffer, size_t size)
|
||||
{
|
||||
bool result;
|
||||
struct syscfgMemEntry entry;
|
||||
void *data;
|
||||
|
||||
result = syscfgFindByTag(tag, &entry);
|
||||
if (!result)
|
||||
return(-1);
|
||||
if (size > entry.seDataSize)
|
||||
size = entry.seDataSize;
|
||||
|
||||
data = syscfgGetData(&entry);
|
||||
if (data == NULL)
|
||||
return(-1);
|
||||
|
||||
memcpy(buffer, data, size);
|
||||
|
||||
// XXX check what to do with the assert that was removed from here
|
||||
return size;
|
||||
}
|
||||
|
||||
bool
|
||||
syscfgFindByTag(u_int32_t tag, struct syscfgMemEntry *entry)
|
||||
{
|
||||
static struct syscfgMemEntry temp;
|
||||
bool result;
|
||||
u_int32_t index;
|
||||
|
||||
for (index = 0; index < syscfgKeyCount; index++) {
|
||||
result = syscfgFindByIndex(index, &temp);
|
||||
if (result && (temp.seTag == tag)) {
|
||||
memcpy(entry, &temp, sizeof(*entry));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
syscfgFindByIndex(u_int32_t index, struct syscfgMemEntry *result)
|
||||
{
|
||||
struct syscfgEntry entry;
|
||||
struct syscfgEntryCNTB *entryCNTB;
|
||||
|
||||
if (index >= syscfgKeyCount)
|
||||
return false;
|
||||
|
||||
size_t offset = sizeof(struct syscfgHeader) + index * sizeof(struct syscfgEntry);
|
||||
if (offset >= syscfgDataLength || offset + sizeof(struct syscfgEntry) >= syscfgDataLength)
|
||||
return false;
|
||||
|
||||
memcpy(&entry, syscfgData + offset, sizeof(entry));
|
||||
|
||||
if (entry.seTag == 'CNTB') {
|
||||
entryCNTB = (struct syscfgEntryCNTB *)&entry;
|
||||
result->seTag = entryCNTB->seRealTag;
|
||||
memset(result->seData, 0, sizeof(result->seData));
|
||||
result->seDataSize = entryCNTB->seDataSize;
|
||||
result->seDataOffset = entryCNTB->seDataOffset;
|
||||
} else {
|
||||
result->seTag = entry.seTag;
|
||||
memcpy(result->seData, entry.seData, sizeof(result->seData));
|
||||
result->seDataSize = sizeof(result->seData);
|
||||
result->seDataOffset = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
syscfg_find_tag(uint32_t tag, void **data_out, uint32_t *size_out)
|
||||
{
|
||||
static struct syscfgMemEntry result;
|
||||
|
||||
if (syscfgFindByTag(tag, &result)) {
|
||||
if (data_out) {
|
||||
*data_out = syscfgGetData(&result);
|
||||
}
|
||||
if (size_out) {
|
||||
*size_out = syscfgGetSize(&result);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
#include <unittest.h>
|
||||
#include <lib/blockdev.h>
|
||||
#include <lib/syscfg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TEST_SYSCFG_BLOCKDEV_SIZE 0x8000
|
||||
|
||||
extern void syscfg_reinit(void);
|
||||
|
||||
const uint32_t test_syscfg_data1[] =
|
||||
{
|
||||
'SCfg', // magic
|
||||
0x1000, // size
|
||||
0x1000, // max size
|
||||
0x0, // version
|
||||
0x0, // big endian (NOT)
|
||||
9, // key count
|
||||
|
||||
'Ent0', // key
|
||||
0x0, 0x0, 0x0, 0x0, // data
|
||||
|
||||
'Ent1', // key
|
||||
0x1, 0x1, 0x1, 0x1, // data
|
||||
|
||||
'Ent2', // key
|
||||
0x200, 0x200, // data
|
||||
0x200, 0x200,
|
||||
|
||||
'Ent3', // key
|
||||
0x30000, 0x30000, // data
|
||||
0x30000, 0x30000,
|
||||
|
||||
'Ent4', // key
|
||||
0x4000000, 0x4000000, // data
|
||||
0x4000000, 0x4000000,
|
||||
|
||||
'CNTB', 'Ent5',
|
||||
4, 0x180, 0, // size 4 offset 0x100
|
||||
|
||||
'CNTB', 'Ent6',
|
||||
8, 0x184, 0, // size 4 offset 0x100
|
||||
|
||||
'CNTB', 'Ent7',
|
||||
1, 0x18c, 0, // size 1 offset 0x104
|
||||
|
||||
'CNTB', 'Ent8',
|
||||
32, 0x190, 0, // size 1 offset 0x104
|
||||
|
||||
// padding, delete an entry here whenever adding an entry above
|
||||
0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
// CNTB block data starts at 0x100
|
||||
0xabcd1234, // for 'Ent5'
|
||||
0x11111111, // for 'Ent6'
|
||||
0x22222222, // .
|
||||
0xDDDDDDAA, // for 'Ent7', only 'AA' part is actually valid
|
||||
0x12345678, // for 'Ent8'
|
||||
0x23456789, // .
|
||||
0x3456789a, // .
|
||||
0x456789ab, // .
|
||||
0x567891bc, // .
|
||||
0x6789abcd, // .
|
||||
0x789abcde, // .
|
||||
0x89abcdef, // .
|
||||
};
|
||||
|
||||
const uint32_t test_syscfg_data3[] =
|
||||
{
|
||||
'SCfg', // magic
|
||||
0x100, // size
|
||||
0x100, // max size
|
||||
0x0, // version
|
||||
0x0, // big endian (NOT)
|
||||
4, // key count
|
||||
|
||||
'CNTB', 'Ent1',
|
||||
8, 0xf8, 0, // pointer is right at end of advertised size, but ok
|
||||
|
||||
'CNTB', 'Ent2',
|
||||
4, 0x200, 0, // pointer is past advertised size
|
||||
|
||||
'CNTB', 'Ent3',
|
||||
2, 0xff, 0, // pointer plus size puts over the end
|
||||
|
||||
'CNTB', 'Ent4',
|
||||
32, 0x8000, 0, // pointer is past end of bdev
|
||||
|
||||
// actual CNTB block data is just padded out with zeroes
|
||||
};
|
||||
|
||||
// XXX add test with malformed data advertising way too big size
|
||||
|
||||
void test_setup_backing(void *backing, const void *data, size_t data_size)
|
||||
{
|
||||
TEST_ASSERT_NOT_NULL(backing);
|
||||
|
||||
memset(backing, 0, TEST_SYSCFG_BLOCKDEV_SIZE);
|
||||
|
||||
memcpy((uint8_t *)backing + 0x4000, data, data_size);
|
||||
}
|
||||
|
||||
|
||||
void test_syscfg1(uintptr_t param)
|
||||
{
|
||||
struct blockdev *bdev;
|
||||
|
||||
void *backing = malloc(TEST_SYSCFG_BLOCKDEV_SIZE);
|
||||
|
||||
bdev = create_mem_blockdev("syscfg_bdev1", backing, TEST_SYSCFG_BLOCKDEV_SIZE, 0x1000);
|
||||
TEST_ASSERT_NOT_NULL(bdev);
|
||||
|
||||
register_blockdev(bdev);
|
||||
|
||||
// Initializing with wrong name should result in failure
|
||||
TEST_ASSERT_EQ(syscfgInitWithBdev("wrong"), false);
|
||||
// and then a subsequent read should fail
|
||||
{
|
||||
uint8_t resultData[16];
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent0', resultData, sizeof(resultData)), -1);
|
||||
}
|
||||
|
||||
// Initializing with empty syscfg should result in failure
|
||||
memset(backing, 0, TEST_SYSCFG_BLOCKDEV_SIZE);
|
||||
TEST_ASSERT_EQ(syscfgInitWithBdev("syscfg_bdev1"), false);
|
||||
// and then a subsequent read should fail
|
||||
{
|
||||
uint8_t resultData[16];
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent0', resultData, sizeof(resultData)), -1);
|
||||
}
|
||||
|
||||
test_setup_backing(backing, test_syscfg_data1, sizeof(test_syscfg_data1));
|
||||
|
||||
// initializing with a valid syscfg should work
|
||||
TEST_ASSERT_EQ(syscfgInitWithBdev("syscfg_bdev1"), true);
|
||||
|
||||
{
|
||||
uint8_t resultData[16];
|
||||
|
||||
// looking for a non-existant tag should return failure
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('EntX', resultData, sizeof(resultData)), -1);
|
||||
|
||||
// looking for ones that exist should work
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent0', resultData, sizeof(resultData)), sizeof(resultData));
|
||||
TEST_ASSERT_MEM_EQ(resultData, TEST_ARRAY(uint32_t, 0, 0, 0, 0), sizeof(resultData));
|
||||
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent1', resultData, sizeof(resultData)), sizeof(resultData));
|
||||
TEST_ASSERT_MEM_EQ(resultData, TEST_ARRAY(uint32_t, 1, 1, 1, 1), sizeof(resultData));
|
||||
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent2', resultData, sizeof(resultData)), sizeof(resultData));
|
||||
TEST_ASSERT_MEM_EQ(resultData, TEST_ARRAY(uint32_t, 0x200, 0x200, 0x200, 0x200), sizeof(resultData));
|
||||
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent3', resultData, sizeof(resultData)), sizeof(resultData));
|
||||
TEST_ASSERT_MEM_EQ(resultData, TEST_ARRAY(uint32_t, 0x30000, 0x30000, 0x30000, 0x30000), sizeof(resultData));
|
||||
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent4', resultData, sizeof(resultData)), sizeof(resultData));
|
||||
TEST_ASSERT_MEM_EQ(resultData, TEST_ARRAY(uint32_t, 0x4000000, 0x4000000, 0x4000000, 0x4000000), sizeof(resultData));
|
||||
|
||||
// Requesting an amount smaller than the entry size results in just that amount
|
||||
memset(resultData, 0xff, sizeof(resultData));
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent1', resultData, 4), 4);
|
||||
TEST_ASSERT_MEM_EQ(resultData, TEST_ARRAY(uint32_t, 1, 0xffffffff, 0xffffffff, 0xffffffff), sizeof(resultData));
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t resultData[32];
|
||||
|
||||
// Requesting an amount bigger than the entry size results in a short read
|
||||
memset(resultData, 0xff, sizeof(resultData));
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent1', resultData, sizeof(resultData)), 16);
|
||||
TEST_ASSERT_MEM_EQ(resultData, TEST_ARRAY(uint32_t, 1, 1, 1, 1), 16);
|
||||
TEST_ASSERT_MEM_EQ(resultData + 16, TEST_ARRAY(uint32_t, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), 16);
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t resultData[4];
|
||||
|
||||
// Reading from a CNTB-style entry should work and return the size given in the entry
|
||||
memset(resultData, 0xff, sizeof(resultData));
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent5', resultData, sizeof(resultData)), sizeof(resultData));
|
||||
TEST_ASSERT_MEM_EQ(resultData, TEST_ARRAY(uint32_t, 0xabcd1234), sizeof(resultData));
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t resultData[8];
|
||||
|
||||
// Short reads from CNTB blocks should still result in the short size being returned
|
||||
memset(resultData, 0xff, sizeof(resultData));
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent6', resultData, 4), 4);
|
||||
TEST_ASSERT_MEM_EQ(resultData, TEST_ARRAY(uint32_t, 0x11111111, 0xffffffff), sizeof(resultData));
|
||||
}
|
||||
}
|
||||
|
||||
void test_syscfg2(uintptr_t param)
|
||||
{
|
||||
struct blockdev *bdev;
|
||||
void *backing = malloc(TEST_SYSCFG_BLOCKDEV_SIZE);
|
||||
test_setup_backing(backing, test_syscfg_data1, sizeof(test_syscfg_data1));
|
||||
|
||||
// bdev has the right data in it, but that data is past the end of its advertised length
|
||||
bdev = create_mem_blockdev("syscfg_bdev2", backing, 0x4000, 0x1000);
|
||||
|
||||
register_blockdev(bdev);
|
||||
|
||||
TEST_ASSERT_EQ(syscfgInitWithBdev("syscfg_bdev2"), false);
|
||||
}
|
||||
|
||||
void test_syscfg3(uintptr_t param)
|
||||
{
|
||||
struct blockdev *bdev;
|
||||
uint8_t resultData[8];
|
||||
void *backing = malloc(TEST_SYSCFG_BLOCKDEV_SIZE);
|
||||
|
||||
test_setup_backing(backing, test_syscfg_data3, sizeof(test_syscfg_data3));
|
||||
|
||||
bdev = create_mem_blockdev("syscfg_bdev3", backing, TEST_SYSCFG_BLOCKDEV_SIZE, 0x1000);
|
||||
|
||||
register_blockdev(bdev);
|
||||
|
||||
TEST_ASSERT_EQ(syscfgInitWithBdev("syscfg_bdev3"), true);
|
||||
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent1', resultData, 8), 8);
|
||||
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent2', resultData, 8), -1);
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent3', resultData, 8), -1);
|
||||
TEST_ASSERT_EQ(syscfgCopyDataForTag('Ent4', resultData, 8), -1);
|
||||
}
|
||||
|
||||
// XXX add a test for syscfg_find_tag
|
||||
|
||||
static struct test_suite syscfg_test_suite = {
|
||||
.name = "syscfg",
|
||||
.description = "tests the syscfg library",
|
||||
.setup_function = syscfg_reinit,
|
||||
.test_cases = {
|
||||
{ "syscfg", test_syscfg1, 0 },
|
||||
{ "syscfg", test_syscfg2, 0 },
|
||||
{ "syscfg", test_syscfg3, 0 },
|
||||
TEST_CASE_LAST
|
||||
}
|
||||
};
|
||||
|
||||
TEST_SUITE(syscfg_test_suite);
|
||||
@@ -0,0 +1,26 @@
|
||||
# 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 := syscfg
|
||||
|
||||
TEST_OBJS := \
|
||||
$(LOCAL_DIR)/syscfg.o \
|
||||
lib/blockdev/blockdev.o \
|
||||
lib/blockdev/mem_blockdev.o \
|
||||
lib/libc/log2.o
|
||||
|
||||
TEST_SUPPORT_OBJS := \
|
||||
tests/unittest-main.o \
|
||||
$(LOCAL_DIR)/tests.o
|
||||
|
||||
TEST_CFLAGS := \
|
||||
-DCPU_CACHELINE_SIZE=32
|
||||
Reference in new issue
Block a user