iBoot/drivers/flash_nand/boot/nvram/nand_nvram_dump.c

174 lines
7.2 KiB
C

/*
* 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);
}
/* ========================================================================== */