/** @file

  Copyright (c) 2008-2009, Apple Inc. All rights reserved.
  
  All rights reserved. This program and the accompanying materials
  are licensed and made available under the terms and conditions of the BSD License
  which accompanies this distribution.  The full text of the license may be found at
  http://opensource.org/licenses/bsd-license.php

  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/

#include "Flash.h"

NAND_PART_INFO_TABLE gNandPartInfoTable[1] = {
  { 0x2C, 0xBA, 17, 11 }
};

NAND_FLASH_INFO *gNandFlashInfo = NULL;
UINT8           *gEccCode;
UINTN           gNum512BytesChunks = 0;

//

// Device path for SemiHosting. It contains our autogened Caller ID GUID.

//

typedef struct {

  VENDOR_DEVICE_PATH        Guid;

  EFI_DEVICE_PATH_PROTOCOL  End;

} FLASH_DEVICE_PATH;



FLASH_DEVICE_PATH gDevicePath = {

  {

    { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0 },

    EFI_CALLER_ID_GUID

  },

  { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}

};



//Actual page address = Column address + Page address + Block address.
UINTN
GetActualPageAddressInBytes (
  UINTN BlockIndex,
  UINTN PageIndex
)
{
  //BlockAddressStart = Start of the Block address in actual NAND
  //PageAddressStart = Start of the Page address in actual NAND
  return ((BlockIndex << gNandFlashInfo->BlockAddressStart) + (PageIndex << gNandFlashInfo->PageAddressStart));
}

VOID
NandSendCommand (
  UINT8 Command
)
{
  MmioWrite16(GPMC_NAND_COMMAND_0, Command);
}

VOID
NandSendAddress (
  UINT8 Address
)
{
  MmioWrite16(GPMC_NAND_ADDRESS_0, Address);
}

UINT16
NandReadStatus (
  VOID
  )
{
  //Send READ STATUS command
  NandSendCommand(READ_STATUS_CMD);

  //Read status.
  return MmioRead16(GPMC_NAND_DATA_0);
}

VOID
NandSendAddressCycles (
  UINTN Address
)
{
  //Column address
  NandSendAddress(Address & 0xff);
  Address >>= 8;

  //Column address
  NandSendAddress(Address & 0x07);
  Address >>= 3;

  //Page and Block address
  NandSendAddress(Address & 0xff);
  Address >>= 8;

  //Block address
  NandSendAddress(Address & 0xff);
  Address >>= 8;

  //Block address
  NandSendAddress(Address & 0x01);
}

VOID
GpmcInit (
  VOID
  )
{
  //Enable Smart-idle mode.
  MmioWrite32 (GPMC_SYSCONFIG, SMARTIDLEMODE);

  //Set IRQSTATUS and IRQENABLE to the reset value
  MmioWrite32 (GPMC_IRQSTATUS, 0x0);
  MmioWrite32 (GPMC_IRQENABLE, 0x0);

  //Disable GPMC timeout control.
  MmioWrite32 (GPMC_TIMEOUT_CONTROL, TIMEOUTDISABLE);

  //Set WRITEPROTECT bit to enable write access.
  MmioWrite32 (GPMC_CONFIG, WRITEPROTECT_HIGH);

  //NOTE: Following GPMC_CONFIGi_0 register settings are taken from u-boot memory dump.
  MmioWrite32 (GPMC_CONFIG1_0, DEVICETYPE_NAND | DEVICESIZE_X16);
  MmioWrite32 (GPMC_CONFIG2_0, CSRDOFFTIME | CSWROFFTIME);
  MmioWrite32 (GPMC_CONFIG3_0, ADVRDOFFTIME | ADVWROFFTIME);
  MmioWrite32 (GPMC_CONFIG4_0, OEONTIME | OEOFFTIME | WEONTIME | WEOFFTIME);
  MmioWrite32 (GPMC_CONFIG5_0, RDCYCLETIME | WRCYCLETIME | RDACCESSTIME | PAGEBURSTACCESSTIME);
  MmioWrite32 (GPMC_CONFIG6_0, WRACCESSTIME | WRDATAONADMUXBUS | CYCLE2CYCLEDELAY | CYCLE2CYCLESAMECSEN);
  MmioWrite32 (GPMC_CONFIG7_0, MASKADDRESS_128MB | CSVALID | BASEADDRESS);
}

EFI_STATUS
NandDetectPart (
  VOID
)
{
  UINT8      NandInfo = 0;
  UINT8      PartInfo[5];
  UINTN      Index;
  BOOLEAN    Found = FALSE;

  //Send READ ID command
  NandSendCommand(READ_ID_CMD);

  //Send one address cycle.
  NandSendAddress(0);

  //Read 5-bytes to idenfity code programmed into the NAND flash devices.
  //BYTE 0 = Manufacture ID
  //Byte 1 = Device ID
  //Byte 2, 3, 4 = Nand part specific information (Page size, Block size etc)
  for (Index = 0; Index < sizeof(PartInfo); Index++) {
    PartInfo[Index] = MmioRead16(GPMC_NAND_DATA_0);
  }

  //Check if the ManufactureId and DeviceId are part of the currently supported nand parts.
  for (Index = 0; Index < sizeof(gNandPartInfoTable)/sizeof(NAND_PART_INFO_TABLE); Index++) {
    if (gNandPartInfoTable[Index].ManufactureId == PartInfo[0] && gNandPartInfoTable[Index].DeviceId == PartInfo[1]) {
      gNandFlashInfo->BlockAddressStart = gNandPartInfoTable[Index].BlockAddressStart;
      gNandFlashInfo->PageAddressStart = gNandPartInfoTable[Index].PageAddressStart;
      Found = TRUE;
      break;
    }
  }

  if (Found == FALSE) {
    DEBUG ((EFI_D_ERROR, "Nand part is not currently supported. Manufacture id: %x, Device id: %x\n", PartInfo[0], PartInfo[1]));
    return EFI_NOT_FOUND;
  }

  //Populate NAND_FLASH_INFO based on the result of READ ID command.
  gNandFlashInfo->ManufactureId = PartInfo[0];
  gNandFlashInfo->DeviceId = PartInfo[1];
  NandInfo = PartInfo[3];

  if (PAGE_SIZE(NandInfo) == PAGE_SIZE_2K_VAL) {
    gNandFlashInfo->PageSize = PAGE_SIZE_2K;
  } else {
    DEBUG ((EFI_D_ERROR, "Unknown Page size.\n"));
    return EFI_DEVICE_ERROR;
  }

  if (SPARE_AREA_SIZE(NandInfo) == SPARE_AREA_SIZE_64B_VAL) {
    gNandFlashInfo->SparePageSize = SPARE_AREA_SIZE_64B;
  } else {
    DEBUG ((EFI_D_ERROR, "Unknown Spare area size.\n"));
    return EFI_DEVICE_ERROR;
  }

  if (BLOCK_SIZE(NandInfo) == BLOCK_SIZE_128K_VAL) {
    gNandFlashInfo->BlockSize = BLOCK_SIZE_128K;
  } else {
    DEBUG ((EFI_D_ERROR, "Unknown Block size.\n"));
    return EFI_DEVICE_ERROR;
  }

  if (ORGANIZATION(NandInfo) == ORGANIZATION_X8) {
    gNandFlashInfo->Organization = 0;
  } else if (ORGANIZATION(NandInfo) == ORGANIZATION_X16) {
    gNandFlashInfo->Organization = 1;
  }

  //Calculate total number of blocks.
  gNandFlashInfo->NumPagesPerBlock = DivU64x32(gNandFlashInfo->BlockSize, gNandFlashInfo->PageSize);

  return EFI_SUCCESS;
}

VOID
NandConfigureEcc (
  VOID
  )
{
  //Define ECC size 0 and size 1 to 512 bytes
  MmioWrite32 (GPMC_ECC_SIZE_CONFIG, (ECCSIZE0_512BYTES | ECCSIZE1_512BYTES));
}

VOID 
NandEnableEcc (
  VOID
  )
{
  //Clear all the ECC result registers and select ECC result register 1
  MmioWrite32 (GPMC_ECC_CONTROL, (ECCCLEAR | ECCPOINTER_REG1));

  //Enable ECC engine on CS0
  MmioWrite32 (GPMC_ECC_CONFIG, (ECCENABLE | ECCCS_0 | ECC16B));
}

VOID
NandDisableEcc (
  VOID
  )
{
  //Turn off ECC engine.
  MmioWrite32 (GPMC_ECC_CONFIG, ECCDISABLE);
}

VOID
NandCalculateEcc (
  VOID
  )
{
  UINTN Index;
  UINTN EccResultRegister;
  UINTN EccResult;

  //Capture 32-bit ECC result for each 512-bytes chunk.
  //In our case PageSize is 2K so read ECC1-ECC4 result registers and
  //generate total of 12-bytes of ECC code for the particular page.

  EccResultRegister = GPMC_ECC1_RESULT;

  for (Index = 0; Index < gNum512BytesChunks; Index++) {

    EccResult = MmioRead32(EccResultRegister);

    //Calculate ECC code from 32-bit ECC result value.
    //NOTE: Following calculation is not part of TRM. We got this information 
    //from Beagleboard mailing list.
    gEccCode[Index * 3] = EccResult & 0xFF;
    gEccCode[(Index * 3) + 1] = (EccResult >> 16) & 0xFF;
    gEccCode[(Index * 3) + 2] = (((EccResult >> 20) & 0xF0) | ((EccResult >> 8) & 0x0F));

    //Point to next ECC result register.
    EccResultRegister += 4;
  }
}

EFI_STATUS
NandReadPage (
  IN  UINTN                         BlockIndex,
  IN  UINTN                         PageIndex,
  OUT VOID                          *Buffer,
  OUT UINT8                         *SpareBuffer
)
{
  UINTN      Address;
  UINTN      Index;
  UINTN      NumMainAreaWords = (gNandFlashInfo->PageSize/2);
  UINTN      NumSpareAreaWords = (gNandFlashInfo->SparePageSize/2);
  UINT16     *MainAreaWordBuffer = Buffer;
  UINT16     *SpareAreaWordBuffer = (UINT16 *)SpareBuffer;
  UINTN      Timeout = MAX_RETRY_COUNT;

  //Generate device address in bytes to access specific block and page index
  Address = GetActualPageAddressInBytes(BlockIndex, PageIndex);

  //Send READ command
  NandSendCommand(PAGE_READ_CMD);

  //Send 5 Address cycles to access specific device address
  NandSendAddressCycles(Address);

  //Send READ CONFIRM command
  NandSendCommand(PAGE_READ_CONFIRM_CMD);

  //Poll till device is busy.
  while (Timeout) {
    if ((NandReadStatus() & NAND_READY) == NAND_READY) {
      break;
    }
    Timeout--;
  }

  if (Timeout == 0) {
    DEBUG ((EFI_D_ERROR, "Read page timed out.\n"));
    return EFI_TIMEOUT;
  }

  //Reissue READ command
  NandSendCommand(PAGE_READ_CMD);

  //Enable ECC engine.
  NandEnableEcc();

  //Read data into the buffer.
  for (Index = 0; Index < NumMainAreaWords; Index++) {
    *MainAreaWordBuffer++ = MmioRead16(GPMC_NAND_DATA_0);
  }

  //Read spare area into the buffer.
  for (Index = 0; Index < NumSpareAreaWords; Index++) {
    *SpareAreaWordBuffer++ = MmioRead16(GPMC_NAND_DATA_0);
  }

  //Calculate ECC.
  NandCalculateEcc();

  //Turn off ECC engine.
  NandDisableEcc();

  //Perform ECC correction.
  //Need to implement..

  return EFI_SUCCESS;
}

EFI_STATUS
NandWritePage (
  IN  UINTN                         BlockIndex,
  IN  UINTN                         PageIndex,
  OUT VOID                          *Buffer,
  IN  UINT8                         *SpareBuffer
)
{
  UINTN      Address;
  UINT16     *MainAreaWordBuffer = Buffer;
  UINT16     *SpareAreaWordBuffer = (UINT16 *)SpareBuffer;
  UINTN      Index;
  UINTN      NandStatus;
  UINTN      Timeout = MAX_RETRY_COUNT;

  //Generate device address in bytes to access specific block and page index
  Address = GetActualPageAddressInBytes(BlockIndex, PageIndex);

  //Send SERIAL DATA INPUT command
  NandSendCommand(PROGRAM_PAGE_CMD);

  //Send 5 Address cycles to access specific device address
  NandSendAddressCycles(Address);

  //Enable ECC engine.
  NandEnableEcc();

  //Data input from Buffer
  for (Index = 0; Index < (gNandFlashInfo->PageSize/2); Index++) {
    MmioWrite16(GPMC_NAND_DATA_0, *MainAreaWordBuffer++);

    //After each write access, device has to wait to accept data.
    //Currently we may not be programming proper timing parameters to 
    //the GPMC_CONFIGi_0 registers and we would need to figure that out.
    //Without following delay, page programming fails.
    gBS->Stall(1);
  }

  //Calculate ECC.
  NandCalculateEcc();

  //Turn off ECC engine.
  NandDisableEcc();

  //Prepare Spare area buffer with ECC codes.
  SetMem(SpareBuffer, gNandFlashInfo->SparePageSize, 0xFF);
  CopyMem(&SpareBuffer[ECC_POSITION], gEccCode, gNum512BytesChunks * 3);

  //Program spare area with calculated ECC.
  for (Index = 0; Index < (gNandFlashInfo->SparePageSize/2); Index++) {
    MmioWrite16(GPMC_NAND_DATA_0, *SpareAreaWordBuffer++);
  }

  //Send PROGRAM command
  NandSendCommand(PROGRAM_PAGE_CONFIRM_CMD);

  //Poll till device is busy.
  while (Timeout) {
    NandStatus = NandReadStatus();
    if ((NandStatus & NAND_READY) == NAND_READY) {
      break;
    }
    Timeout--;
  }

  if (Timeout == 0) {
    DEBUG ((EFI_D_ERROR, "Program page timed out.\n"));
    return EFI_TIMEOUT;
  }

  //Bit0 indicates Pass/Fail status
  if (NandStatus & NAND_FAILURE) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
NandEraseBlock (
  IN UINTN BlockIndex
)
{
  UINTN      Address;
  UINTN      NandStatus;
  UINTN      Timeout = MAX_RETRY_COUNT;

  //Generate device address in bytes to access specific block and page index
  Address = GetActualPageAddressInBytes(BlockIndex, 0);

  //Send ERASE SETUP command
  NandSendCommand(BLOCK_ERASE_CMD);

  //Send 3 address cycles to device to access Page address and Block address
  Address >>= 11; //Ignore column addresses

  NandSendAddress(Address & 0xff);
  Address >>= 8;

  NandSendAddress(Address & 0xff);
  Address >>= 8;

  NandSendAddress(Address & 0xff);

  //Send ERASE CONFIRM command
  NandSendCommand(BLOCK_ERASE_CONFIRM_CMD);

  //Poll till device is busy.
  while (Timeout) {
    NandStatus = NandReadStatus();
    if ((NandStatus & NAND_READY) == NAND_READY) {
      break;
    }
    Timeout--;
    gBS->Stall(1);
  }

  if (Timeout == 0) {
    DEBUG ((EFI_D_ERROR, "Erase block timed out for Block: %d.\n", BlockIndex));
    return EFI_TIMEOUT;
  }

  //Bit0 indicates Pass/Fail status
  if (NandStatus & NAND_FAILURE) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
NandReadBlock (
  IN UINTN                          StartBlockIndex,
  IN UINTN                          EndBlockIndex,
  OUT VOID                          *Buffer,
  OUT VOID                          *SpareBuffer
)
{
  UINTN      BlockIndex;
  UINTN      PageIndex;
  EFI_STATUS Status = EFI_SUCCESS;

  for (BlockIndex = StartBlockIndex; BlockIndex <= EndBlockIndex; BlockIndex++) {
    //For each block read number of pages
    for (PageIndex = 0; PageIndex < gNandFlashInfo->NumPagesPerBlock; PageIndex++) {
      Status = NandReadPage(BlockIndex, PageIndex, Buffer, SpareBuffer);
      if (EFI_ERROR(Status)) {
        return Status;
      }
      Buffer = ((UINT8 *)Buffer + gNandFlashInfo->PageSize);
    }
  }

  return Status;
}

EFI_STATUS
NandWriteBlock (
  IN UINTN                          StartBlockIndex,
  IN UINTN                          EndBlockIndex,
  OUT VOID                          *Buffer,
  OUT VOID                          *SpareBuffer
  )
{
  UINTN      BlockIndex;
  UINTN      PageIndex;
  EFI_STATUS Status = EFI_SUCCESS;

  for (BlockIndex = StartBlockIndex; BlockIndex <= EndBlockIndex; BlockIndex++) {
    //Page programming.
    for (PageIndex = 0; PageIndex < gNandFlashInfo->NumPagesPerBlock; PageIndex++) {
      Status = NandWritePage(BlockIndex, PageIndex, Buffer, SpareBuffer);
      if (EFI_ERROR(Status)) {
        return Status;
      }
      Buffer = ((UINT8 *)Buffer + gNandFlashInfo->PageSize);
    }
  }

  return Status;
}

EFI_STATUS
EFIAPI
NandFlashReset (
  IN EFI_BLOCK_IO_PROTOCOL          *This,
  IN BOOLEAN                        ExtendedVerification
  )
{
  UINTN BusyStall = 50;                            // microSeconds
  UINTN ResetBusyTimeout = (1000000 / BusyStall);  // 1 Second

  //Send RESET command to device.
  NandSendCommand(RESET_CMD);
  
  //Wait for 1ms before we check status register.
  gBS->Stall(1000);

  //Check BIT#5 & BIT#6 in Status register to make sure RESET is done.
  while ((NandReadStatus() & NAND_RESET_STATUS) != NAND_RESET_STATUS) {

    //In case of extended verification, wait for extended amount of time
    //to make sure device is reset.
    if (ExtendedVerification) {
      if (ResetBusyTimeout == 0) {
        return EFI_DEVICE_ERROR;
      }

      gBS->Stall(BusyStall);
      ResetBusyTimeout--;
    }
  }
  
  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
NandFlashReadBlocks (
  IN EFI_BLOCK_IO_PROTOCOL          *This,
  IN UINT32                         MediaId,
  IN EFI_LBA                        Lba,
  IN UINTN                          BufferSize,
  OUT VOID                          *Buffer
  )
{
  UINTN      NumBlocks;
  UINTN      EndBlockIndex;
  EFI_STATUS Status;
  UINT8      *SpareBuffer = NULL;

  if (Buffer == NULL) {
    Status = EFI_INVALID_PARAMETER;
    goto exit;
  }
  
  if (Lba > LAST_BLOCK) {
    Status = EFI_INVALID_PARAMETER;
    goto exit;
  }
  
  if ((BufferSize % gNandFlashInfo->BlockSize) != 0) {
    Status = EFI_BAD_BUFFER_SIZE;
    goto exit;
  }

  NumBlocks = DivU64x32(BufferSize, gNandFlashInfo->BlockSize);
  EndBlockIndex = ((UINTN)Lba + NumBlocks) - 1;

  SpareBuffer = (UINT8 *)AllocatePool(gNandFlashInfo->SparePageSize);
  if (SpareBuffer == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto exit;
  }

  //Read block
  Status = NandReadBlock((UINTN)Lba, EndBlockIndex, Buffer, SpareBuffer);
  if (EFI_ERROR(Status)) {
    DEBUG((EFI_D_ERROR, "Read block fails: %x\n", Status));
    goto exit;
  }

exit:
  if (SpareBuffer != NULL) {
    FreePool (SpareBuffer);
  }

  return Status;
}

EFI_STATUS
EFIAPI
NandFlashWriteBlocks (
  IN EFI_BLOCK_IO_PROTOCOL          *This,
  IN UINT32                         MediaId,
  IN EFI_LBA                        Lba,
  IN UINTN                          BufferSize,
  IN VOID                           *Buffer
  )
{
  UINTN      BlockIndex;
  UINTN      NumBlocks;
  UINTN      EndBlockIndex;
  EFI_STATUS Status;
  UINT8      *SpareBuffer = NULL;

  if (Buffer == NULL) {
    Status = EFI_INVALID_PARAMETER;
    goto exit;
  }
  
  if (Lba > LAST_BLOCK) {
    Status = EFI_INVALID_PARAMETER;
    goto exit;
  }
  
  if ((BufferSize % gNandFlashInfo->BlockSize) != 0) {
    Status = EFI_BAD_BUFFER_SIZE;
    goto exit;
  }

  NumBlocks = DivU64x32(BufferSize, gNandFlashInfo->BlockSize);
  EndBlockIndex = ((UINTN)Lba + NumBlocks) - 1;

  SpareBuffer = (UINT8 *)AllocatePool(gNandFlashInfo->SparePageSize);
  if (SpareBuffer == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto exit;
  }

  // Erase block
  for (BlockIndex = (UINTN)Lba; BlockIndex <= EndBlockIndex; BlockIndex++) {
    Status = NandEraseBlock(BlockIndex);
    if (EFI_ERROR(Status)) {
      DEBUG((EFI_D_ERROR, "Erase block failed. Status: %x\n", Status));
      goto exit;
    }
  }
  
  // Program data
  Status = NandWriteBlock((UINTN)Lba, EndBlockIndex, Buffer, SpareBuffer);
  if (EFI_ERROR(Status)) {
    DEBUG((EFI_D_ERROR, "Block write fails: %x\n", Status));
    goto exit;
  }

exit:
  if (SpareBuffer != NULL) {
    FreePool (SpareBuffer);
  }

  return Status;
}

EFI_STATUS
EFIAPI
NandFlashFlushBlocks (
  IN EFI_BLOCK_IO_PROTOCOL  *This
  )
{
  return EFI_SUCCESS;
}



EFI_BLOCK_IO_MEDIA gNandFlashMedia = {
  SIGNATURE_32('n','a','n','d'),            // MediaId
  FALSE,                                    // RemovableMedia
  TRUE,                                     // MediaPresent
  FALSE,                                    // LogicalPartition
  FALSE,                                    // ReadOnly
  FALSE,                                    // WriteCaching
  0,                                        // BlockSize
  2,                                        // IoAlign
  0,                                        // Pad
  0                                         // LastBlock
};

EFI_BLOCK_IO_PROTOCOL BlockIo = 
{
  EFI_BLOCK_IO_INTERFACE_REVISION,  // Revision
  &gNandFlashMedia,                  // *Media
  NandFlashReset,                   // Reset
  NandFlashReadBlocks,              // ReadBlocks
  NandFlashWriteBlocks,             // WriteBlocks
  NandFlashFlushBlocks              // FlushBlocks
};

EFI_STATUS
NandFlashInitialize (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
{
  EFI_STATUS  Status;
  
  gNandFlashInfo = (NAND_FLASH_INFO *)AllocateZeroPool (sizeof(NAND_FLASH_INFO));

  //Initialize GPMC module.
  GpmcInit();

  //Reset NAND part
  NandFlashReset(&BlockIo, FALSE);

  //Detect NAND part and populate gNandFlashInfo structure
  Status = NandDetectPart ();
  if (EFI_ERROR(Status)) {
    DEBUG((EFI_D_ERROR, "Nand part id detection failure: Status: %x\n", Status));
    return Status;
  }

  //Count total number of 512Bytes chunk based on the page size.
  if (gNandFlashInfo->PageSize == PAGE_SIZE_512B) {
    gNum512BytesChunks = 1;
  } else if (gNandFlashInfo->PageSize == PAGE_SIZE_2K) {
    gNum512BytesChunks = 4;
  } else if (gNandFlashInfo->PageSize == PAGE_SIZE_4K) {
    gNum512BytesChunks = 8;
  }

  gEccCode = (UINT8 *)AllocatePool(gNum512BytesChunks * 3);
  if (gEccCode == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  //Configure ECC
  NandConfigureEcc ();

  //Patch EFI_BLOCK_IO_MEDIA structure.
  gNandFlashMedia.BlockSize = gNandFlashInfo->BlockSize;
  gNandFlashMedia.LastBlock = LAST_BLOCK;

  //Publish BlockIO.
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &ImageHandle, 
                  &gEfiBlockIoProtocolGuid, &BlockIo,
                  &gEfiDevicePathProtocolGuid, &gDevicePath, 
                  NULL
                  );
  return Status;
}

