first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012 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.
|
||||
*/
|
||||
|
||||
#if WITH_NVRAM
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
#include <platform.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <lib/blockdev.h>
|
||||
#include <lib/nvram.h>
|
||||
#include <lib/env.h>
|
||||
#include <lib/libc.h>
|
||||
|
||||
#include <sys/menu.h>
|
||||
#include <sys/task.h>
|
||||
|
||||
#include <platform/soc/hwclocks.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "nand_part.h"
|
||||
#include "nand_part_interface.h"
|
||||
#include "nand_export.h"
|
||||
#include "nand_nvram_impl.h"
|
||||
#include "nand_nvram_core.h"
|
||||
#include "nand_nvram_dump.h"
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
#define DEBUG_NONDESTRUCTIVE 0
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
#define TRACE_ENABLE 0
|
||||
#if TRACE_ENABLE
|
||||
|
||||
// FWiW: tracing is relying on single-threaded behavior for correctness
|
||||
|
||||
static utime_t trace_time = 0;
|
||||
static unsigned int trace_line = 0;
|
||||
|
||||
#define TRACE_BEFORE() \
|
||||
do { \
|
||||
trace_line = __LINE__; \
|
||||
trace_time = system_time(); \
|
||||
} while (0)
|
||||
|
||||
#define TRACE_AFTER() \
|
||||
do { \
|
||||
utime_t elapsed = system_time() - trace_time; \
|
||||
dprintf(DEBUG_CRITICAL, \
|
||||
"\nTRACE - %s@%u-%u: %u.%03u ms\n", \
|
||||
__func__, \
|
||||
trace_line, \
|
||||
__LINE__, \
|
||||
elapsed / 1000, \
|
||||
elapsed % 1000); \
|
||||
} while (0)
|
||||
|
||||
#else /* !TRACE_ENABLE */
|
||||
|
||||
#define TRACE_BEFORE() /* do nothing */
|
||||
#define TRACE_AFTER() /* do nothing */
|
||||
|
||||
#endif
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
typedef struct {
|
||||
|
||||
NandPartInterface * npi;
|
||||
uint32_t part;
|
||||
bool is_initialized;
|
||||
nand_nvram_t * nvram;
|
||||
struct blockdev nvram_bdev;
|
||||
|
||||
} _context_t;
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
static _context_t _context = { .part = ~0 };
|
||||
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
static int flash_nand_nvram_read(struct blockdev *bdev, void *buffer, off_t offset, uint64_t length);
|
||||
static int flash_nand_nvram_read_block(struct blockdev *bdev, void *buffer, block_addr block, uint32_t count);
|
||||
static int flash_nand_nvram_write(struct blockdev *bdev, const void *buffer, off_t offset, uint64_t length);
|
||||
static int flash_nand_nvram_write_block(struct blockdev *bdev, const void *buffer, block_addr block, uint32_t count);
|
||||
|
||||
extern bool
|
||||
flash_nand_nvram_init(NandPartInterface *npi, uint32_t part, bool isNewborn)
|
||||
{
|
||||
nand_nvram_geometry_t geometry;
|
||||
uint32_t page_size = 0;
|
||||
|
||||
if (_context.is_initialized)
|
||||
goto done;
|
||||
|
||||
dprintf(DEBUG_SPEW, "initializing nand nvram...\n");
|
||||
|
||||
TRACE_BEFORE();
|
||||
if (isNewborn || (NULL == npi)) {
|
||||
|
||||
dprintf(DEBUG_SPEW, "nand partition table unavailable; returning failure\n");
|
||||
goto done;
|
||||
|
||||
} else {
|
||||
|
||||
_context.npi = npi;
|
||||
_context.part = part;
|
||||
|
||||
page_size = npi_get_bytes_per_page(npi, part);
|
||||
|
||||
/* specify nand geometry information */
|
||||
geometry.bytes_per_meta_buffer = kNAND_NVRAM_META_SIZE;
|
||||
geometry.bytes_per_meta_actual = kNAND_NVRAM_META_SIZE;
|
||||
geometry.number_of_banks = npi_get_bank_width(npi, part);
|
||||
geometry.blocks_per_bank = npi_get_block_depth(npi, part);
|
||||
geometry.pages_per_block = npi_get_pages_per_block(npi, part);
|
||||
geometry.data_pages_per_block = geometry.pages_per_block - kNAND_NVRAM_PAGE_RESERVED_IN_BLOCK;
|
||||
geometry.bytes_per_page = page_size - geometry.bytes_per_meta_buffer;
|
||||
|
||||
if (!nand_nvram_open(&_context.nvram, &_context, &geometry, kNAND_NVRAM_SIZE)) {
|
||||
dprintf(DEBUG_CRITICAL, "couldn't open nand nvram device\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
dprintf(DEBUG_SPEW, "nand nvram initialized\n");
|
||||
}
|
||||
|
||||
construct_blockdev(&_context.nvram_bdev, "nvram", kNAND_NVRAM_SIZE, 1);
|
||||
_context.nvram_bdev.read_hook = &flash_nand_nvram_read;
|
||||
_context.nvram_bdev.read_block_hook = &flash_nand_nvram_read_block;
|
||||
_context.nvram_bdev.write_hook = &flash_nand_nvram_write;
|
||||
_context.nvram_bdev.write_block_hook = &flash_nand_nvram_write_block;
|
||||
register_blockdev(&_context.nvram_bdev);
|
||||
|
||||
_context.is_initialized = true;
|
||||
|
||||
done:
|
||||
TRACE_AFTER();
|
||||
return (_context.is_initialized);
|
||||
}
|
||||
|
||||
static int
|
||||
flash_nand_nvram_read(struct blockdev *bdev, void *buffer, off_t offset, uint64_t length)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
TRACE_BEFORE();
|
||||
if (!_context.is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ok = nand_nvram_read(_context.nvram, offset, buffer, length);
|
||||
TRACE_AFTER();
|
||||
|
||||
return (ok ? length : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
flash_nand_nvram_read_block(struct blockdev *bdev, void *buffer, block_addr block, uint32_t count)
|
||||
{
|
||||
return flash_nand_nvram_read(bdev, buffer, block, count);
|
||||
}
|
||||
|
||||
static int
|
||||
flash_nand_nvram_write(struct blockdev *bdev, const void *buffer, off_t offset, uint64_t length)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
TRACE_BEFORE();
|
||||
if (!_context.is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ok = nand_nvram_write(_context.nvram, offset, buffer, length);
|
||||
if (ok)
|
||||
ok = nand_nvram_sync(_context.nvram);
|
||||
TRACE_AFTER();
|
||||
|
||||
return (ok ? length : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
flash_nand_nvram_write_block(struct blockdev *bdev, const void *buffer, block_addr block, uint32_t count)
|
||||
{
|
||||
return flash_nand_nvram_write(bdev, buffer, block, count);
|
||||
}
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
bool
|
||||
flash_nand_nvram_is_block_bad(void * context, uint32_t bank, uint32_t block)
|
||||
{
|
||||
const _context_t * ctxt = (_context_t*)context;
|
||||
bool bad;
|
||||
|
||||
TRACE_BEFORE();
|
||||
bad = npi_is_block_bad(ctxt->npi, ctxt->part, bank, block);
|
||||
TRACE_AFTER();
|
||||
|
||||
return (bad);
|
||||
}
|
||||
|
||||
bool
|
||||
flash_nand_nvram_read_page(void * context, uint32_t bank, uint32_t page, void * data, void * meta, bool * is_clean)
|
||||
{
|
||||
const _context_t * ctxt = (_context_t*)context;
|
||||
const nand_nvram_geometry_t * geo = nand_nvram_get_geometry(ctxt->nvram);
|
||||
const uint32_t block = page / geo->pages_per_block;
|
||||
const uint32_t page_in_block = page % geo->pages_per_block;
|
||||
const uint32_t nand_page_size = npi_get_bytes_per_page(ctxt->npi, ctxt->part);
|
||||
UInt8 * buf = NULL;
|
||||
bool ok = false;
|
||||
|
||||
TRACE_BEFORE();
|
||||
buf = (UInt8*)memalign(nand_page_size, CPU_CACHELINE_SIZE);
|
||||
|
||||
if (npi_read_page(ctxt->npi, ctxt->part, bank, block, page_in_block, buf, is_clean)) {
|
||||
|
||||
memcpy(meta, buf, geo->bytes_per_meta_actual);
|
||||
memcpy(data, buf + geo->bytes_per_meta_buffer, geo->bytes_per_page);
|
||||
|
||||
ok = true;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
TRACE_AFTER();
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
bool
|
||||
flash_nand_nvram_write_page(void * context, uint32_t bank, uint32_t page, void * data, void * meta)
|
||||
{
|
||||
const _context_t * ctxt = (_context_t*)context;
|
||||
const nand_nvram_geometry_t * geo = nand_nvram_get_geometry(ctxt->nvram);
|
||||
const uint32_t block = page / geo->pages_per_block;
|
||||
const uint32_t page_in_block = page % geo->pages_per_block;
|
||||
const uint32_t nand_page_size = npi_get_bytes_per_page(ctxt->npi, ctxt->part);
|
||||
UInt8 * buf = NULL;
|
||||
bool ok = false;
|
||||
|
||||
TRACE_BEFORE();
|
||||
buf = (UInt8*)memalign(nand_page_size, CPU_CACHELINE_SIZE);
|
||||
|
||||
memcpy(buf, meta, geo->bytes_per_meta_actual);
|
||||
memcpy(buf + geo->bytes_per_meta_buffer, data, geo->bytes_per_page);
|
||||
|
||||
ok = npi_write_page(ctxt->npi, ctxt->part, bank, block, page_in_block, buf);
|
||||
|
||||
free(buf);
|
||||
TRACE_AFTER();
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
bool
|
||||
flash_nand_nvram_request_ptab_diff(void * context, void * data, uint32_t size)
|
||||
{
|
||||
const _context_t * ctxt = (_context_t*)context;
|
||||
bool ok;
|
||||
|
||||
TRACE_BEFORE();
|
||||
ok = npi_request_ptab_diff(ctxt->npi, ctxt->part, data, size);
|
||||
TRACE_AFTER();
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
bool
|
||||
flash_nand_nvram_provide_ptab_diff(void * context, void * data, uint32_t size)
|
||||
{
|
||||
const _context_t * ctxt = (_context_t*)context;
|
||||
bool ok;
|
||||
|
||||
TRACE_BEFORE();
|
||||
ok = npi_provide_ptab_diff(ctxt->npi, ctxt->part, data, size);
|
||||
TRACE_AFTER();
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
bool
|
||||
flash_nand_nvram_erase_block(void * context, uint32_t bank, uint32_t block)
|
||||
{
|
||||
const _context_t * ctxt = (_context_t*)context;
|
||||
bool ok;
|
||||
|
||||
TRACE_BEFORE();
|
||||
ok = npi_erase_block(ctxt->npi, ctxt->part, bank, block);
|
||||
TRACE_AFTER();
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
bool flash_nand_nvram_copy_ptab(void * context, void * buf)
|
||||
{
|
||||
const _context_t * ctxt = (_context_t*)context;
|
||||
bool ok = false;
|
||||
|
||||
TRACE_BEFORE();
|
||||
if (NULL != buf) {
|
||||
ok = npi_get_ptab_bytes(ctxt->npi, buf, npi_get_bytes_per_page(ctxt->npi, ctxt->part));
|
||||
}
|
||||
TRACE_AFTER();
|
||||
|
||||
return(ok);
|
||||
}
|
||||
|
||||
bool flash_nand_nvram_read_ptab(void * context, uint32_t bank, uint32_t page, void * buf)
|
||||
{
|
||||
const _context_t * ctxt = (_context_t*)context;
|
||||
const nand_nvram_geometry_t * geo = nand_nvram_get_geometry(ctxt->nvram);
|
||||
const uint32_t block = page / geo->pages_per_block;
|
||||
const uint32_t page_in_block = page % geo->pages_per_block;
|
||||
bool is_clean;
|
||||
bool ok = false;
|
||||
|
||||
TRACE_BEFORE();
|
||||
if (NULL != buf) {
|
||||
ok = npi_read_page(ctxt->npi, ctxt->part, bank, block, page_in_block, buf, &is_clean);
|
||||
}
|
||||
TRACE_AFTER();
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
bool flash_nand_nvram_write_ptab(void * context, uint32_t bank, uint32_t page, void * buf)
|
||||
{
|
||||
const _context_t * ctxt = (_context_t*)context;
|
||||
const nand_nvram_geometry_t * geo = nand_nvram_get_geometry(ctxt->nvram);
|
||||
const uint32_t block = page / geo->pages_per_block;
|
||||
const uint32_t page_in_block = page % geo->pages_per_block;
|
||||
bool ok = false;
|
||||
|
||||
TRACE_BEFORE();
|
||||
if (NULL != buf) {
|
||||
ok = npi_write_page(ctxt->npi, ctxt->part, bank, block, page_in_block, buf);
|
||||
}
|
||||
TRACE_AFTER();
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
static int do_nvram_dump(int argc, struct cmd_arg *args)
|
||||
{
|
||||
return (nand_nvram_dump(_context.nvram) ? 0 : -1);
|
||||
}
|
||||
|
||||
MENU_COMMAND_DEVELOPMENT(nvramdump, do_nvram_dump, "dump nand-based nvram pages", NULL);
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
#endif // WITH_NVRAM
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 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.
|
||||
*/
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
/*!
|
||||
@header nand_nvram_core
|
||||
|
||||
@abstract portable core of a nand-based NVRAM device implementation
|
||||
|
||||
@discussion In order to boot from nand, the NVRAM device must have an
|
||||
implementation with a backing store on the nand flash device since
|
||||
the traditional nor-based backing store will no longer be available.
|
||||
This class implements such a device over a slice of the nand array,
|
||||
using a journalled commit approach with multiple redundant copies.
|
||||
|
||||
@copyright Apple Inc.
|
||||
|
||||
@updated 2011-05-18
|
||||
*/
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
#ifndef _NAND_NVRAM_CORE_H
|
||||
#define _NAND_NVRAM_CORE_H
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
/*!
|
||||
@group public platform-independent interface function declarations
|
||||
*/
|
||||
|
||||
/*!
|
||||
@function nand_nvram_open
|
||||
|
||||
@abstract Open platform-independent ram-shadowed nand nvram device.
|
||||
|
||||
@param _geometry Geometry of nand device array slice for backing store.
|
||||
|
||||
@result Returns bool indicating whether function succeeded.
|
||||
*/
|
||||
bool nand_nvram_open(nand_nvram_t ** _nvram, void * context, nand_nvram_geometry_t * _geometry, uint32_t _size);
|
||||
|
||||
/*!
|
||||
@function nand_nvram_read
|
||||
|
||||
@abstract Read data from the nvram device shadow.
|
||||
|
||||
@param _offset Byte offset into nvram data blob.
|
||||
|
||||
@param _buffer Pointer to memory buffer to read data from.
|
||||
|
||||
@param _length Amount of data in bytes to read from blob.
|
||||
|
||||
@result Returns bool indicating whether function succeeded.
|
||||
*/
|
||||
bool nand_nvram_read(nand_nvram_t * _nvram, uint32_t _offset, uint8_t * _buffer, uint32_t _length);
|
||||
|
||||
/*!
|
||||
@function nand_nvram_write
|
||||
|
||||
@abstract Write data to the nvram device shadow.
|
||||
|
||||
@param _offset Byte offset into nvram data blob.
|
||||
|
||||
@param _buffer Pointer to memory buffer to write data into.
|
||||
|
||||
@param _length Amount of data in bytes to write to blob.
|
||||
|
||||
@result Returns bool indicating whether function succeeded.
|
||||
*/
|
||||
bool nand_nvram_write(nand_nvram_t * _nvram, uint32_t _offset, const uint8_t * _buffer, uint32_t _length);
|
||||
|
||||
/*!
|
||||
@function nand_nvram_sync
|
||||
|
||||
@abstract Synchronize nvram device data to backing store.
|
||||
|
||||
@result Returns bool indicating whether function succeeded.
|
||||
*/
|
||||
bool nand_nvram_sync(nand_nvram_t * _nvram);
|
||||
|
||||
/*!
|
||||
@function nand_nvram_get_geometry
|
||||
|
||||
@abstract Provide access to nand nvram driver's geometry information.
|
||||
|
||||
@result Returns pointer to struct defining nand nvram geometry.
|
||||
*/
|
||||
const nand_nvram_geometry_t * nand_nvram_get_geometry(nand_nvram_t * _nvram);
|
||||
|
||||
/*!
|
||||
@function nand_nvram_close
|
||||
|
||||
@abstract Close platform-independent ram-shadowed nand nvram device.
|
||||
*/
|
||||
void nand_nvram_close(nand_nvram_t ** _nvram);
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* ! _NAND_NVRAM_CORE_H */
|
||||
|
||||
/* ========================================================================== */
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "nand_part.h"
|
||||
#include "nand_nvram_platform.h"
|
||||
#include "nand_nvram_impl.h"
|
||||
#include "nand_nvram_dump.h"
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
static void
|
||||
dumpData(nand_nvram_t * nv, uint8_t * data)
|
||||
{
|
||||
const uint32_t bytes_per_row = 16;
|
||||
char alpha[bytes_per_row + 1];
|
||||
uint32_t col = 0;
|
||||
uint32_t idx;
|
||||
|
||||
nand_nvram_printf(nv->context, " <data>");
|
||||
nand_nvram_set_mem(nv->context, alpha, 0x00, bytes_per_row + 1);
|
||||
for (idx = 0; idx < nv->geo.bytes_per_page; idx++) {
|
||||
uint8_t byte = data[idx];
|
||||
col = (idx % bytes_per_row);
|
||||
if (0 == col) {
|
||||
if (0 != alpha[0]) {
|
||||
nand_nvram_printf(nv->context, " <!-- %s -->", alpha);
|
||||
nand_nvram_set_mem(nv->context, alpha, 0x00, bytes_per_row + 1);
|
||||
}
|
||||
nand_nvram_printf(nv->context, "\n ");
|
||||
}
|
||||
alpha[col] = ((0x20 <= byte) && (byte <= 0x7e)) ? (char) byte : '.';
|
||||
nand_nvram_printf(nv->context, "%02X ", byte);
|
||||
}
|
||||
if (0 != alpha[0]) {
|
||||
for (idx = 0; idx < (bytes_per_row - (col + 1)); idx++) {
|
||||
nand_nvram_printf(nv->context, " ");
|
||||
}
|
||||
nand_nvram_printf(nv->context, " <!-- %s -->", alpha);
|
||||
nand_nvram_set_mem(nv->context, alpha, 0x00, bytes_per_row + 1);
|
||||
}
|
||||
nand_nvram_printf(nv->context, "\n </data>\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dumpMeta(nand_nvram_t * nv, meta_t * meta)
|
||||
{
|
||||
nand_nvram_printf(nv->context, " <meta_t>\n");
|
||||
nand_nvram_printf(nv->context, " <generation>0x%08X</generation>\n", meta->generation);
|
||||
nand_nvram_printf(nv->context, " <page_max>0x%02X</page_max>\n", meta->page_max);
|
||||
nand_nvram_printf(nv->context, " <page_idx>0x%02X</page_idx>\n", meta->page_idx);
|
||||
nand_nvram_printf(nv->context, " <version_major>0x%02X</version_major>\n", meta->version_major);
|
||||
nand_nvram_printf(nv->context, " <version_minor>0x%02X</version_minor>\n", meta->version_minor);
|
||||
nand_nvram_printf(nv->context, " <signature>0x%04X</signature>\n", meta->signature);
|
||||
nand_nvram_printf(nv->context, " </meta_t>\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dumpPage(nand_nvram_t * nv, uint32_t bank, uint32_t block, uint32_t page, meta_t * meta, uint8_t * data)
|
||||
{
|
||||
uint32_t abs_page = page + (block * nv->geo.pages_per_block);
|
||||
|
||||
nand_nvram_printf(nv->context, " <page>\n");
|
||||
nand_nvram_printf(nv->context, " <bank_num>%d</bank_num>\n", bank);
|
||||
nand_nvram_printf(nv->context, " <block_num>%d</block_num>\n", block);
|
||||
nand_nvram_printf(nv->context, " <page_num>%d</page_num>\n", page);
|
||||
if (nand_nvram_read_page(nv->context, bank, abs_page, data, meta, NULL)) {
|
||||
NandPartTable *closing = (NandPartTable*)meta;
|
||||
if (kNAND_NVRAM_SIGNATURE == meta->signature) {
|
||||
nand_nvram_printf(nv->context, " <type>content</type>\n");
|
||||
dumpMeta(nv, meta);
|
||||
} else if (kNandPartHeaderMagic == closing->header.magic) {
|
||||
nand_nvram_printf(nv->context, " <type>closing</type>\n");
|
||||
} else {
|
||||
nand_nvram_printf(nv->context, " <type>unrecognized</type>\n");
|
||||
}
|
||||
dumpData(nv, data);
|
||||
} else {
|
||||
nand_nvram_printf(nv->context, " <type>unreadable</type>\n");
|
||||
}
|
||||
nand_nvram_printf(nv->context, " </page>\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dumpBlock(nand_nvram_t * nv, uint32_t bank, uint32_t block, meta_t * meta, uint8_t * data)
|
||||
{
|
||||
uint32_t page;
|
||||
|
||||
nand_nvram_printf(nv->context, " <block>\n");
|
||||
nand_nvram_printf(nv->context, " <bank_num>%d</bank_num>\n", bank);
|
||||
nand_nvram_printf(nv->context, " <block_num>%d</block_num>\n", block);
|
||||
if (nand_nvram_is_block_bad(nv->context, bank, block)) {
|
||||
nand_nvram_printf(nv->context, " <bad/>\n");
|
||||
} else {
|
||||
for (page = 0; page < nv->geo.pages_per_block; page++)
|
||||
{
|
||||
dumpPage(nv, bank, block, page, meta, data);
|
||||
}
|
||||
}
|
||||
nand_nvram_printf(nv->context, " </block>\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dumpBank(nand_nvram_t * nv, uint32_t bank, meta_t * meta, uint8_t * data)
|
||||
{
|
||||
uint32_t block;
|
||||
|
||||
nand_nvram_printf(nv->context, " <bank>\n");
|
||||
nand_nvram_printf(nv->context, " <bank_num>%d</bank_num>\n", bank);
|
||||
for (block = 0; block < nv->geo.blocks_per_bank; block++)
|
||||
{
|
||||
dumpBlock(nv, bank, block, meta, data);
|
||||
}
|
||||
nand_nvram_printf(nv->context, " </bank>\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dumpGeometry(nand_nvram_t * nv)
|
||||
{
|
||||
nand_nvram_printf(nv->context, " <nand_nvram_geometry_t>\n");
|
||||
nand_nvram_printf(nv->context, " <number_of_banks>%d</number_of_banks>\n", nv->geo.number_of_banks);
|
||||
nand_nvram_printf(nv->context, " <blocks_per_bank>%d</blocks_per_bank>\n", nv->geo.blocks_per_bank);
|
||||
nand_nvram_printf(nv->context, " <pages_per_block>%d</pages_per_block>\n", nv->geo.pages_per_block);
|
||||
nand_nvram_printf(nv->context, " <data_pages_per_block>%d</data_pages_per_block>\n", nv->geo.data_pages_per_block);
|
||||
nand_nvram_printf(nv->context, " <bytes_per_page>%d</bytes_per_page>\n", nv->geo.bytes_per_page);
|
||||
nand_nvram_printf(nv->context, " <bytes_per_meta_buffer>%d</bytes_per_meta_buffer>\n", nv->geo.bytes_per_meta_buffer);
|
||||
nand_nvram_printf(nv->context, " <bytes_per_meta_actual>%d</bytes_per_meta_actual>\n", nv->geo.bytes_per_meta_actual);
|
||||
nand_nvram_printf(nv->context, " </nand_nvram_geometry_t>\n");
|
||||
}
|
||||
|
||||
bool
|
||||
nand_nvram_dump(nand_nvram_t * nv)
|
||||
{
|
||||
bool ok = false;
|
||||
uint32_t bank;
|
||||
meta_t * meta = NULL;
|
||||
uint8_t * data = NULL;
|
||||
|
||||
if ((NULL != nv) &&
|
||||
(NULL != nv->context) &&
|
||||
(NULL != (meta = nand_nvram_alloc_mem(nv->context, nv->geo.bytes_per_meta_buffer))) &&
|
||||
(NULL != (data = nand_nvram_alloc_mem(nv->context, nv->geo.bytes_per_page)))) {
|
||||
|
||||
nand_nvram_printf(nv->context, "<nvram>\n");
|
||||
dumpGeometry(nv);
|
||||
for (bank = 0; bank < nv->geo.number_of_banks; bank++)
|
||||
{
|
||||
dumpBank(nv, bank, meta, data);
|
||||
}
|
||||
nand_nvram_printf(nv->context, "</nvram>\n");
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (NULL != meta) {
|
||||
nand_nvram_free_mem(nv->context, meta, nv->geo.bytes_per_meta_buffer);
|
||||
}
|
||||
if (NULL != data) {
|
||||
nand_nvram_free_mem(nv->context, data, nv->geo.bytes_per_page);
|
||||
}
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
/* ========================================================================== */
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011 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.
|
||||
*/
|
||||
|
||||
#ifndef _NAND_NVRAM_DUMP_H_
|
||||
#define _NAND_NVRAM_DUMP_H_
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
bool nand_nvram_dump(nand_nvram_t * nv);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _NAND_NVRAM_DUMP_H_
|
||||
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2012 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.
|
||||
*/
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
/*!
|
||||
@header nand_nvram_impl
|
||||
|
||||
@abstract portable header info for nand nvram implementation use only
|
||||
|
||||
@discussion These declarations have been pulled out into an
|
||||
independent file so that diagnostic utilities and white box unit
|
||||
tests might take advantage of knowing implementation-specific
|
||||
details. Nevertheless, no client of the nand nvram driver nor its
|
||||
system-specific wrapper should ever need to reference this header.
|
||||
Any declarations that need that level of visibility are intended to
|
||||
be placed in "nand_nvram_core.h".
|
||||
|
||||
@copyright Apple Inc.
|
||||
|
||||
@updated 2012-02-21
|
||||
*/
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
#ifndef _NAND_NVRAM_IMPL_H
|
||||
#define _NAND_NVRAM_IMPL_H
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
/*!
|
||||
@group public platform-independent type declarations
|
||||
*/
|
||||
|
||||
/*!
|
||||
@typedef nand_nvram_t
|
||||
|
||||
@abstract Opaque reference to structure needed by nand nvram implementation.
|
||||
*/
|
||||
typedef struct nand_nvram nand_nvram_t;
|
||||
|
||||
/*!
|
||||
@typedef nand_nvram_geometry_t
|
||||
|
||||
@abstract
|
||||
*/
|
||||
typedef struct nand_nvram_geometry nand_nvram_geometry_t;
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
/*!
|
||||
@group private platform-independent type declarations
|
||||
*/
|
||||
|
||||
typedef struct _meta meta_t;
|
||||
typedef struct _blob blob_t;
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
/*!
|
||||
@group public platform-independent constant definitions
|
||||
*/
|
||||
|
||||
/*!
|
||||
@const kNAND_NVRAM_SIZE
|
||||
|
||||
@abstract Standard size of nvram presented by the driver. Note
|
||||
that, if this ends up changing in the future, this value should
|
||||
start being defined on a platform/product specific basis.
|
||||
*/
|
||||
#define kNAND_NVRAM_SIZE 8192
|
||||
|
||||
/*!
|
||||
@const kNAND_NVRAM_META_SIZE
|
||||
|
||||
@abstract Amount of bytes required by meta data for each nvram
|
||||
backing store page.
|
||||
*/
|
||||
#define kNAND_NVRAM_META_SIZE 10
|
||||
|
||||
/*!
|
||||
@const kNAND_NVRAM_PAGE_RESERVED_IN_BLOCK
|
||||
|
||||
@abstract Number of pages reserved for partition table in each
|
||||
NAND block.
|
||||
*/
|
||||
#define kNAND_NVRAM_PAGE_RESERVED_IN_BLOCK 2
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
/*!
|
||||
@group private platform-independent constant definitions
|
||||
*/
|
||||
|
||||
/*!
|
||||
@const NULL
|
||||
|
||||
@abstract It really sucks that some of our systems don't define NULL.
|
||||
*/
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
/*!
|
||||
@const kNAND_NVRAM_MAX_SIZE
|
||||
|
||||
@abstract Maximum amount of storage; should fit into a standard 2K page.
|
||||
*/
|
||||
#define kNAND_NVRAM_MAX_SIZE (128 * 2048)
|
||||
|
||||
/*!
|
||||
@const kNAND_NVRAM_SIGNATURE
|
||||
|
||||
@abstract Constant value used to identify nand nvram meta data.
|
||||
*/
|
||||
#define kNAND_NVRAM_SIGNATURE ((uint16_t) 0xBEAD)
|
||||
|
||||
/*!
|
||||
@const kNAND_NVRAM_VERSION_MAJOR
|
||||
|
||||
@abstract Major version of the driver that wrote the nvram content.
|
||||
Major version differences are considered to be incompatible. Even
|
||||
major version numbers are reserved for development purposes; odd
|
||||
version numbers should be used for when development is frozen,
|
||||
stabilized, and therefore only accepting minor revision level changes.
|
||||
*/
|
||||
#define kNAND_NVRAM_FEATURE_EXTRA_AREA_VERSION_MAJOR ((uint8_t) 0x0)
|
||||
#define kNAND_NVRAM_VERSION_MAJOR kNAND_NVRAM_FEATURE_EXTRA_AREA_VERSION_MAJOR
|
||||
|
||||
/*!
|
||||
@const kNAND_NVRAM_VERSION_MINOR
|
||||
|
||||
@abstract Minor version of the driver that wrote the nvram content.
|
||||
Minor versions should be fully compatible within a major version and
|
||||
are intended to be incremented when the driver has changed between
|
||||
public releases.
|
||||
*/
|
||||
#define kNAND_NVRAM_FEATURE_EXTRA_AREA_VERSION_MINOR ((uint8_t) 0x3)
|
||||
#define kNAND_NVRAM_VERSION_MINOR kNAND_NVRAM_FEATURE_EXTRA_AREA_VERSION_MINOR
|
||||
|
||||
/*!
|
||||
@const kNAND_NVRAM_GENERATION_ERASED
|
||||
|
||||
@abstract A generation number of all ones is reserved since it also
|
||||
corresponds to the erased state of nand bits.
|
||||
*/
|
||||
#define kNAND_NVRAM_GENERATION_ERASED ((uint32_t) 0xFFFFFFFF)
|
||||
|
||||
/*!
|
||||
@const kNAND_NVRAM_GENERATION_UNKNOWN
|
||||
|
||||
@abstract A generation number of all zeros is reserved since it
|
||||
corresponds to the state of an uninitialized meta struct.
|
||||
*/
|
||||
#define kNAND_NVRAM_GENERATION_UNKNOWN ((uint32_t) 0x00000000)
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
/*!
|
||||
@group public platform-independent structure declarations
|
||||
*/
|
||||
|
||||
/*!
|
||||
@struct nand_nvram_geometry
|
||||
|
||||
@abstract Geometry of nand device array slice.
|
||||
|
||||
@field number_of_banks Number of logical banks.
|
||||
|
||||
@field blocks_per_bank Number of blocks in each bank.
|
||||
|
||||
@field pages_per_block Number of pages per block.
|
||||
|
||||
@field data_pages_per_block Number of pages per block available for data storage.
|
||||
|
||||
@field bytes_per_page Size in bytes of page.
|
||||
|
||||
@field bytes_per_meta_buffer Size in bytes of buffer for in-memory per-page meta info.
|
||||
|
||||
@field bytes_per_meta_actual Size in bytes of in-storage per-page meta info (i.e. actual size).
|
||||
*/
|
||||
struct nand_nvram_geometry {
|
||||
|
||||
uint32_t number_of_banks;
|
||||
uint32_t blocks_per_bank;
|
||||
uint32_t pages_per_block;
|
||||
uint32_t data_pages_per_block;
|
||||
uint32_t bytes_per_page;
|
||||
uint32_t bytes_per_meta_buffer;
|
||||
uint32_t bytes_per_meta_actual;
|
||||
};
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
/*!
|
||||
@group private platform-independent structure declarations
|
||||
*/
|
||||
|
||||
/*!
|
||||
@struct _meta
|
||||
|
||||
@abstract Structure defining per-page meta layout.
|
||||
|
||||
@field generation Monotonically increasing generation of blob;
|
||||
kNAND_NVRAM_GENERATION_UNKNOWN and kNAND_NVRAM_GENERATION_ERASED are
|
||||
reserved values that should never appear on a nand device.
|
||||
|
||||
@field page_max Maximum page index for blob (i.e. page count - 1).
|
||||
|
||||
@field page_idx Page index of this meta within blob.
|
||||
|
||||
@field version_major Major version number of nand nvram driver.
|
||||
|
||||
@field version_minor Minor version number of nand nvram driver.
|
||||
|
||||
@field signature Constant value of kNAND_NVRAM_SIGNATURE marks valid
|
||||
nvram meta.
|
||||
*/
|
||||
struct _meta {
|
||||
|
||||
uint32_t generation;
|
||||
uint8_t page_max;
|
||||
uint8_t page_idx;
|
||||
uint8_t version_major;
|
||||
uint8_t version_minor;
|
||||
uint16_t signature;
|
||||
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/*!
|
||||
@struct _blob
|
||||
|
||||
@abstract Container for N pages of data and meta information
|
||||
for convenience of writing to/from nand devices.
|
||||
|
||||
@field pageCount Number of pages currently allocated to
|
||||
shadow the blob.
|
||||
|
||||
@field metaBufs Buffer containing pages' meta structs.
|
||||
|
||||
@field dataBufs Buffer containing pages' data.
|
||||
*/
|
||||
struct _blob {
|
||||
|
||||
void * meta_bufs;
|
||||
void * data_bufs;
|
||||
};
|
||||
|
||||
/*!
|
||||
@struct nand_nvram
|
||||
|
||||
@abstract NAND-based nvram driver context information.
|
||||
|
||||
@field geometry Geometry of nand device array slice used for
|
||||
backing store.
|
||||
|
||||
@field is_dirty Flag indicating whether shadow has been
|
||||
modified since last restore or sync.
|
||||
|
||||
@field shadow Blob used as container for pages of data and meta
|
||||
information being shadowed from nand.
|
||||
|
||||
@field cursors Array of page numbers of next page in each
|
||||
bank available for commit.
|
||||
*/
|
||||
struct nand_nvram {
|
||||
|
||||
nand_nvram_geometry_t geo;
|
||||
void * context;
|
||||
uint32_t size;
|
||||
bool is_born;
|
||||
bool is_dirty;
|
||||
uint32_t * watermarks;
|
||||
uint32_t * cursors;
|
||||
bool * copies;
|
||||
blob_t * shadow;
|
||||
};
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* ! _NAND_NVRAM_IMPL_H */
|
||||
|
||||
/* ========================================================================== */
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 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.
|
||||
*/
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
/*!
|
||||
@header nand_nvram_platform
|
||||
|
||||
@abstract iBoot platform-specific macros needed by nand nvram
|
||||
|
||||
@copyright Apple Inc.
|
||||
|
||||
@updated 2011-05-18
|
||||
*/
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
#ifndef _NAND_NVRAM_PLATFORM_H
|
||||
#define _NAND_NVRAM_PLATFORM_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <lib/heap.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
#define nand_nvram_alloc_mem(context, size) memalign((size), CPU_CACHELINE_SIZE)
|
||||
|
||||
#define nand_nvram_compare_mem(context, left, right, size) memcmp((left), (right), (size))
|
||||
|
||||
#define nand_nvram_copy_mem(context, dest, src, size) memcpy((dest), (src), (size))
|
||||
|
||||
#define nand_nvram_set_mem(context, mem, value, size) memset((mem), (value), (size))
|
||||
|
||||
#define nand_nvram_free_mem(context, mem, size) free((mem))
|
||||
|
||||
#define nand_nvram_printf(context, ...) dprintf(DEBUG_CRITICAL, __VA_ARGS__)
|
||||
|
||||
#define nand_nvram_is_block_bad(context, bank, block) flash_nand_nvram_is_block_bad((context), (bank), (block))
|
||||
|
||||
#define nand_nvram_read_page(context, bank, page, data, meta, is_clean) flash_nand_nvram_read_page((context), (bank), (page), (data), (meta), (is_clean))
|
||||
|
||||
#define nand_nvram_write_page(context, bank, page, data, meta) flash_nand_nvram_write_page((context), (bank), (page), (data), (meta))
|
||||
|
||||
#define nand_nvram_erase_block(context, bank, block) flash_nand_nvram_erase_block((context), (bank), (block))
|
||||
|
||||
#define nand_nvram_request_ptab_diff(context, data, size) flash_nand_nvram_request_ptab_diff((context), (data), (size))
|
||||
|
||||
#define nand_nvram_provide_ptab_diff(context, data, size) flash_nand_nvram_provide_ptab_diff((context), (data), (size))
|
||||
|
||||
#define nand_nvram_copy_ptab(context, buf) flash_nand_nvram_copy_ptab((context), (buf))
|
||||
|
||||
#define nand_nvram_read_ptab(context, bank, page, buf) flash_nand_nvram_read_ptab((context), (bank), (page), (buf))
|
||||
|
||||
#define nand_nvram_write_ptab(context, bank, page, buf) flash_nand_nvram_write_ptab((context), (bank), (page), (buf))
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
bool flash_nand_nvram_is_block_bad(void * context, uint32_t bank, uint32_t block);
|
||||
bool flash_nand_nvram_read_page(void * context, uint32_t bank, uint32_t page, void * data, void * meta, bool * is_clean);
|
||||
bool flash_nand_nvram_write_page(void * context, uint32_t bank, uint32_t page, void * data, void * meta);
|
||||
bool flash_nand_nvram_erase_block(void * context, uint32_t bank, uint32_t block);
|
||||
bool flash_nand_nvram_request_ptab_diff(void * context, void * data, uint32_t size);
|
||||
bool flash_nand_nvram_provide_ptab_diff(void * context, void * data, uint32_t size);
|
||||
bool flash_nand_nvram_copy_ptab(void * context, void * buf);
|
||||
bool flash_nand_nvram_read_ptab(void * context, uint32_t bank, uint32_t page, void * buf);
|
||||
bool flash_nand_nvram_write_ptab(void * context, uint32_t bank, uint32_t page, void * buf);
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _NAND_NVRAM_PLATFORM_H */
|
||||
|
||||
/* ========================================================================== */
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2011 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)
|
||||
|
||||
OPTIONS += \
|
||||
WITH_NAND_NVRAM=1
|
||||
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/nand_nvram.o \
|
||||
$(LOCAL_DIR)/nand_nvram_core.o \
|
||||
$(LOCAL_DIR)/nand_nvram_dump.o
|
||||
Reference in new issue
Block a user