iBoot/lib/effaceable/iokit/AppleEffaceableNAND.cpp

233 lines
6.3 KiB
C++

/*
* Copyright (c) 2010-11 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 <stdint.h>
#include <IOKit/IOLib.h>
#include "AppleEffaceableNAND.h"
#include "effaceable_contract.h"
#include "effaceable_debug.h"
// =============================================================================
#define debug(...) dlogf((void*)0, __VA_ARGS__ )
// =============================================================================
#ifdef super
#undef super
#endif
#define super AppleEffaceableStorage
OSDefineMetaClassAndStructors(AppleEffaceableNAND, AppleEffaceableStorage);
// =============================================================================
bool
AppleEffaceableNAND::start(IOService *provider)
{
bool ok = false;
debug(INFO, "starting");
setupNandContract();
if (0 == (_partition = OSDynamicCast(IOFlashStoragePartition, provider))) {
debug(ERR, "provider is not an IOFlashStoragePartition");
} else if (!super::start(provider)) {
debug(ERR, "superclass unable to start");
} else {
debug(INIT, "started");
ok = true;
}
return ok;
}
// =============================================================================
effaceable_nand_hal_t *
AppleEffaceableNAND::nand(void)
{
return &_nand_hal;
}
void
AppleEffaceableNAND::setupDeviceContract(void)
{
startEffaceableNAND(device(), system(), nand(), storage());
}
// =============================================================================
AppleEffaceableNAND * context(effaceable_nand_hal_t * nand)
{
AppleEffaceableNAND * context;
// XXX assert instead?
if (0 == (context = (AppleEffaceableNAND *)nand->opaque))
panic("null context");
return context;
}
uint32_t getPageSizeHook(effaceable_nand_hal_t * nand)
{
return context(nand)->getPageSizeNand();
}
uint32_t getPageCountHook(effaceable_nand_hal_t * nand)
{
return context(nand)->getPageCountNand();
}
uint32_t getBlockCountHook(effaceable_nand_hal_t * nand)
{
return context(nand)->getBlockCountNand();
}
uint32_t getBankCountHook(effaceable_nand_hal_t * nand)
{
return context(nand)->getBankCountNand();
}
bool isBlockBadHook(effaceable_nand_hal_t * nand, uint32_t bank, uint32_t block)
{
return context(nand)->isBlockBadNand(bank, block);
}
EffaceableReturn eraseBlockHook(effaceable_nand_hal_t * nand, uint32_t bank, uint32_t block)
{
return context(nand)->eraseBlockNand(bank, block);
}
EffaceableReturn writePageHook(effaceable_nand_hal_t * nand, uint32_t bank, uint32_t block, uint32_t page, const void * buf, uint32_t length)
{
return context(nand)->writePageNand(bank, block, page, buf, length);
}
EffaceableReturn readPageHook(effaceable_nand_hal_t * nand, uint32_t bank, uint32_t block, uint32_t page, void * buf, uint32_t length)
{
return context(nand)->readPageNand(bank, block, page, buf, length);
}
bool requestPartitionTableDiffHook(effaceable_nand_hal_t * nand, void * buf, uint32_t length)
{
return context(nand)->requestPartitionTableDiffNand(buf, length);
}
bool providePartitionTableDiffHook(effaceable_nand_hal_t * nand, void * buf, uint32_t length)
{
return context(nand)->providePartitionTableDiffNand(buf, length);
}
// =============================================================================
void
AppleEffaceableNAND::setupNandContract(void)
{
nand()->opaque = this;
nand()->getPageSize = getPageSizeHook;
nand()->getPageCount = getPageCountHook;
nand()->getBlockCount = getBlockCountHook;
nand()->getBankCount = getBankCountHook;
nand()->isBlockBad = isBlockBadHook;
nand()->eraseBlock = eraseBlockHook;
nand()->writePage = writePageHook;
nand()->readPage = readPageHook;
nand()->requestPartitionTableDiff = requestPartitionTableDiffHook;
nand()->providePartitionTableDiff = providePartitionTableDiffHook;
}
uint32_t AppleEffaceableNAND::getPageSizeNand(void)
{
return (IOByteCount)_partition->getPageSize();
}
uint32_t AppleEffaceableNAND::getPageCountNand(void)
{
return _partition->getPagesPerBlock();
}
uint32_t AppleEffaceableNAND::getBlockCountNand(void)
{
return _partition->getBlockCount();
}
uint32_t AppleEffaceableNAND::getBankCountNand(void)
{
return _partition->getBankCount();
}
bool AppleEffaceableNAND::isBlockBadNand(uint32_t bank, uint32_t block)
{
return _partition->isBlockBad(bank, block);
}
EffaceableReturn AppleEffaceableNAND::eraseBlockNand(uint32_t bank, uint32_t block)
{
return efReturn(_partition->eraseBlock(bank, block));
}
EffaceableReturn AppleEffaceableNAND::writePageNand(uint32_t bank, uint32_t block, uint32_t page, const void * buf, uint32_t length)
{
IOReturn ok;
IOBufferMemoryDescriptor * bmd;
// XXX It's unfortunate that the IOBMD is necessary; think about how/where to clean it up.
bmd = IOBufferMemoryDescriptor::withBytes(buf, length, kIODirectionInOut, true);
if (0 == bmd)
panic("no memory");
ok = _partition->writePage(bank, block, page, bmd);
bmd->release();
return efReturn(ok);
}
EffaceableReturn AppleEffaceableNAND::readPageNand(uint32_t bank, uint32_t block, uint32_t page, void * buf, uint32_t length)
{
IOReturn ok;
IOBufferMemoryDescriptor * bmd;
// XXX It's unfortunate that the IOBMD is necessary; think about how/where to clean it up.
bmd = IOBufferMemoryDescriptor::withCapacity(length, kIODirectionInOut, true);
if (0 == bmd)
panic("no memory");
ok = _partition->readPage(bank, block, page, bmd);
if (kIOReturnSuccess == ok)
bmd->readBytes(0, buf, length);
bmd->release();
return efReturn(ok);
}
bool AppleEffaceableNAND::requestPartitionTableDiffNand(void * buf, uint32_t length)
{
return _partition->requestPartitionTableDiff(buf, length);
}
bool AppleEffaceableNAND::providePartitionTableDiffNand(void * buf, uint32_t length)
{
return _partition->providePartitionTableDiff(buf, length);
}
// =============================================================================