Example #1
0
static Uint32 LOCAL_recvHeaderAndData(UARTBOOT_HeaderHandle ackHeader)
{
  Uint32 error = E_FAIL, recvLen;

  // Recv ACK command
  error = UART_checkSequence("    ACK", TRUE);
  if(error != E_PASS)
  {
    return E_FAIL;
  }

  // Get the ACK header elements
  error =  UART_recvHexData( 4, (Uint32 *) &(ackHeader->magicNum)     );
  error |= UART_recvHexData( 4, (Uint32 *) &(ackHeader->startAddr) );
  error |= UART_recvHexData( 4, (Uint32 *) &(ackHeader->byteCnt)  );
  error |= UART_checkSequence("0000", FALSE);
  if(error != E_PASS)
  {
    return E_FAIL;
  }

  // Verify that the data size is appropriate
  if((ackHeader->byteCnt == 0) || (ackHeader->byteCnt > APP_IMAGE_SIZE))
  {
    LOCAL_sendSequence(" BADCNT");  // trailing /0 will come along
      return E_FAIL;
  }

  // Verify application start address is in RAM (lower 16bit of appStartAddr also used 
  // to hold UBL entry point if this header describes a UBL)
  if( (ackHeader->startAddr < DEVICE_DDR2_START_ADDR) || (ackHeader->startAddr > DEVICE_DDR2_END_ADDR) )
  {
    LOCAL_sendSequence("BADADDR");  // trailing /0 will come along
    return E_FAIL;
  }

  // Send BEGIN command
  if (LOCAL_sendSequence("  BEGIN") != E_PASS)
    return E_FAIL;

  // Receive the data over UART
  recvLen = ackHeader->byteCnt;
  error = UART_recvStringN((String)(ackHeader->loadAddr), &recvLen, FALSE );
  if ( (error != E_PASS) || (recvLen != ackHeader->byteCnt) )
  {
    DEBUG_printString("\r\nUART Receive Error\r\n");
    return E_FAIL;
  }

  // Return DONE when all data arrives
  if ( LOCAL_sendSequence("   DONE") != E_PASS )
    return E_FAIL;

  return E_PASS;
}
Example #2
0
Uint32 UARTBOOT_copy(void)
{
  UARTBOOT_HeaderObj  ackHeader;
  Uint32              bootCmd;

UART_tryAgain:
  DEBUG_printString("Starting UART Boot...\r\n");

  // UBL Sends 'BOOTUBL/0'
  if (LOCAL_sendSequence("BOOTUBL") != E_PASS)
    goto UART_tryAgain;

  // Receive the BOOT command
  if(LOCAL_recvCommand(&bootCmd) != E_PASS)
    goto UART_tryAgain;

  switch(bootCmd)
  {
    // Only used for doing simple boot of UART
    case UBL_MAGIC_SAFE:
    {
      if (LOCAL_sendSequence("SENDAPP") != E_PASS)
        goto UART_tryAgain;
      if (LOCAL_recvHeaderAndData(&ackHeader) != E_PASS)
        goto UART_tryAgain;
      gEntryPoint = ackHeader.startAddr;
      break;
    }
    default:
    {
      DEBUG_printString("Boot command not supported!");
      return E_FAIL;
    }
  }

  return E_PASS;
}
Example #3
0
Uint32 UARTBOOT_copy(void)
{

#if defined(UBL_NAND)
    NANDBOOT_HeaderObj  nandBoot;
    NAND_InfoHandle     hNandInfo;
#elif defined(UBL_NOR)
    NOR_InfoHandle      hNorInfo;
#endif
    UARTBOOT_HeaderObj  ackHeader;
    Uint32              bootCmd;

UART_tryAgain:
    DEBUG_printString("Starting UART Boot...\r\n");

    // UBL Sends 'BOOTUBL/0'
    if (LOCAL_sendSequence("BOOTUBL") != E_PASS)
        goto UART_tryAgain;

    // Receive the BOOT command
    if(LOCAL_recvCommand(&bootCmd) != E_PASS)
        goto UART_tryAgain;

    // Send ^^^DONE\0 to indicate command was accepted
    if ( LOCAL_sendSequence("   DONE") != E_PASS )
        goto UART_tryAgain;

    switch(bootCmd)
    {
#if defined(UBL_NOR)
    case UBL_MAGIC_NOR_BIN_BURN:
    {
        // Initialize the NOR Flash
        hNorInfo = NOR_open((Uint32)&EMIFStart, (Uint8)DEVICE_emifBusWidth()) ;
        if (hNorInfo == NULL)
        {
            DEBUG_printString("NOR_open() failed!");
            goto UART_tryAgain;
        }

        // Get the APP (should be u-boot) into binary form
        if ( LOCAL_recvHeaderAndData(&ackHeader) != E_PASS )
            goto UART_tryAgain;

        // Erasing the Flash
        if ( NOR_erase(hNorInfo,hNorInfo->flashBase, ackHeader.byteCnt) != E_PASS )
            goto UART_tryAgain;

        // Write the actual application to the flash
        if ( NOR_writeBytes(hNorInfo,hNorInfo->flashBase, ackHeader.byteCnt, (Uint32)ackHeader.imageBuff) != E_PASS )
            goto UART_tryAgain;

        // Return DONE when UBL flash operation has been completed
        if ( LOCAL_sendSequence("   DONE") != E_PASS )
            return E_FAIL;

        // Set the entry point for code execution
        gEntryPoint = hNorInfo->flashBase;
        break;
    }
    case UBL_MAGIC_NOR_GLOBAL_ERASE:
    {
        // Initialize the NOR Flash
        hNorInfo = NOR_open((Uint32)&EMIFStart, (Uint8)DEVICE_emifBusWidth()) ;
        if (hNorInfo == NULL)
        {
            DEBUG_printString("NOR_open() failed!");
            goto UART_tryAgain;
        }

        // Erasing the Flash
        if (NOR_globalErase(hNorInfo) != E_PASS)
        {
            DEBUG_printString("\r\nErase failed.\r\n");
        }
        else
        {
            DEBUG_printString("\r\nErase completed successfully.\r\n");
        }

        // Return DONE when erase operation has been completed
        if ( LOCAL_sendSequence("   DONE") != E_PASS )
            return E_FAIL;

        // Set the entry point for code execution
        // Go to reset in this case since no code was downloaded
        gEntryPoint = 0x0;

        break;
    }
#elif defined(UBL_NAND)
    case UBL_MAGIC_NAND_BIN_BURN:
    {
        // Initialize the NAND Flash
        hNandInfo = NAND_open((Uint32)&EMIFStart);
        if ( hNandInfo ==  NULL )
        {
            DEBUG_printString("NAND_open() failed!");
            goto UART_tryAgain;
        }

        // ------ Get UBL Data and Write it to Flash ------
        // Get the UBL header and data
        if (LOCAL_recvHeaderAndData(&ackHeader) != E_PASS)
            goto UART_tryAgain;

        // Setup the NANDBOOT header that will be stored in flash
        nandBoot.magicNum = ackHeader.magicNum;
        nandBoot.entryPoint = ackHeader.startAddr;
        nandBoot.page = 1;                          // The page is always page 0 for the UBL header, so we use page 1 for data
        nandBoot.block = DEVICE_NAND_RBL_SEARCH_START_BLOCK;       // Set starting block to begin the write attempts
        nandBoot.ldAddress = ackHeader.loadAddr;    // This field doesn't matter for the UBL header

        // Calculate the number of NAND pages needed to store the UBL image
        nandBoot.numPage = 0;
        while ( (nandBoot.numPage * hNandInfo->dataBytesPerPage) < (ackHeader.byteCnt))
        {
            nandBoot.numPage++;
        }

        // Write header to page 0 of block 1(or up to block 5)
        // Write the UBL to the same block, starting at page 1
        DEBUG_printString("Writing UBL to NAND flash\r\n");
        if (LOCAL_NANDWriteHeaderAndData(hNandInfo, &nandBoot, ackHeader.imageBuff) != E_PASS)
            goto UART_tryAgain;

        // Return DONE when UBL flash operation has been completed
        if ( LOCAL_sendSequence("   DONE") != E_PASS )
            return E_FAIL;

        // ------ Get Application Data and Write it to Flash ------
        // Get the application header and data
        if (LOCAL_recvHeaderAndData(&ackHeader) != E_PASS)
            goto UART_tryAgain;

        // Setup the NANDBOOT header that will be stored in flash
        nandBoot.magicNum = ackHeader.magicNum;         // Rely on the host applciation to send over the right magic number (safe or bin)
        nandBoot.entryPoint = ackHeader.startAddr;      // Use the entrypoint received in ACK header
        nandBoot.page = 1;                              // The page is always page 0 for the header, so we use page 1 for data
        nandBoot.block = DEVICE_NAND_UBL_SEARCH_START_BLOCK;           // Set the starting block for application
        nandBoot.ldAddress = ackHeader.loadAddr;        // The load address is only important if this is a binary image

        // Calculate the number of NAND pages needed to store the APP image
        nandBoot.numPage = 0;
        while ( (nandBoot.numPage * hNandInfo->dataBytesPerPage) < ackHeader.byteCnt )
        {
            nandBoot.numPage++;
        }

        // Write header to page 0 of block 1(or up to block 5)
        // Write the UBL to the same block, starting at page 1
        DEBUG_printString("Writing APP to NAND flash\r\n");
        if (LOCAL_NANDWriteHeaderAndData(hNandInfo,&nandBoot, ackHeader.imageBuff) != E_PASS)
            goto UART_tryAgain;

        // Return DONE when UBL flash operation has been completed
        if ( LOCAL_sendSequence("   DONE") != E_PASS )
            return E_FAIL;

        // Set the entry point to nowhere, since there isn't an appropriate binary image to run */
        gEntryPoint = 0x0;
        break;
    }  // end case UBL_MAGIC_NAND_BIN_BURN
    case UBL_MAGIC_NAND_GLOBAL_ERASE:
    {
        // Initialize the NAND Flash
        hNandInfo = NAND_open((Uint32)&EMIFStart);
        if ( hNandInfo ==  NULL )
        {
            DEBUG_printString("NAND_open() failed!");
            goto UART_tryAgain;
        }

        // Unprotect the NAND Flash
        NAND_unProtectBlocks(hNandInfo, DEVICE_NAND_RBL_SEARCH_START_BLOCK, DEVICE_NAND_UBL_SEARCH_END_BLOCK-1);

        // Erase all the pages of the device
        if (NAND_eraseBlocks(hNandInfo, DEVICE_NAND_RBL_SEARCH_START_BLOCK, DEVICE_NAND_UBL_SEARCH_END_BLOCK-1) != E_PASS)
        {
            DEBUG_printString("Erase failed.\r\n");
            goto UART_tryAgain;
        }
        else
        {
            DEBUG_printString("Erase completed successfully.\r\n");
        }

        // Protect the device
        NAND_protectBlocks(hNandInfo);

        // Return DONE when erase operation has been completed
        if ( LOCAL_sendSequence("   DONE") != E_PASS )
            return E_FAIL;

        // Set the entry point for code execution
        // Go to reset in this case since no code was downloaded
        gEntryPoint = 0x0;
        break;
    }
#endif
    default:
    {
        DEBUG_printString("Boot command not supported!");
        return E_FAIL;
    }
    }

    LOCAL_sendSequence("   DONE");

    return E_PASS;
}
Example #4
0
static Uint32 LOCAL_recvHeaderAndData(UARTBOOT_HeaderHandle ackHeader)
{
    Uint32  error = E_PASS, recvLen;
    Bool    imageIsUBL;
    Uint32  maxImageSize,minStartAddr,maxStartAddr;

    // Issue command to host to send image
    if ( LOCAL_sendSequence("SENDIMG") != E_PASS)
    {
        return E_FAIL;
    }

    // Recv ACK command
    if(UART_checkSequence("    ACK", TRUE) != E_PASS)
    {
        return E_FAIL;
    }

    // Get the ACK header elements
    error =  UART_recvHexData( 4, (Uint32 *) &(ackHeader->magicNum)  );
    error |= UART_recvHexData( 4, (Uint32 *) &(ackHeader->startAddr) );
    error |= UART_recvHexData( 4, (Uint32 *) &(ackHeader->byteCnt)   );
    error |= UART_recvHexData( 4, (Uint32 *) &(ackHeader->loadAddr)  );
    error |= UART_checkSequence("0000", FALSE);
    if(error != E_PASS)
    {
        return E_FAIL;
    }

    // Check if this is a UBL or APP image
    if (ackHeader->loadAddr == 0x00000020)
    {
        imageIsUBL = TRUE;
        maxImageSize = UBL_IMAGE_SIZE;
        minStartAddr = 0x0100;
        maxStartAddr = UBL_IMAGE_SIZE;
    }
    else
    {
        imageIsUBL = FALSE;
        maxImageSize = APP_IMAGE_SIZE;
        minStartAddr = DEVICE_DDR2_START_ADDR;
        maxStartAddr = DEVICE_DDR2_END_ADDR;
    }


    // Verify that the data size is appropriate
    if((ackHeader->byteCnt == 0) || (ackHeader->byteCnt > maxImageSize))
    {
        LOCAL_sendSequence(" BADCNT");  // trailing /0 will come along
        return E_FAIL;
    }

    // Verify application start address is in RAM (lower 16bit of appStartAddr also used
    // to hold UBL entry point if this header describes a UBL)
    if( (ackHeader->startAddr < minStartAddr) || (ackHeader->startAddr > maxStartAddr) )
    {
        LOCAL_sendSequence("BADADDR");  // trailing /0 will come along
        return E_FAIL;
    }

    // Allocate space in DDR to store image
    ackHeader->imageBuff = (Uint8 *) UTIL_allocMem(ackHeader->byteCnt);

    // Send BEGIN command
    if (LOCAL_sendSequence("  BEGIN") != E_PASS)
        return E_FAIL;

    // Receive the data over UART
    recvLen = ackHeader->byteCnt;
    error = UART_recvStringN((String)ackHeader->imageBuff, &recvLen, FALSE );
    if ( (error != E_PASS) || (recvLen != ackHeader->byteCnt) )
    {
        DEBUG_printString("\r\nUART Receive Error\r\n");
        return E_FAIL;
    }

    // Return DONE when all data arrives
    if ( LOCAL_sendSequence("   DONE") != E_PASS )
        return E_FAIL;

    return E_PASS;
}
Uint32 UARTBOOT_copy(void)
{

#if defined(UBL_NAND)
  NANDBOOT_HeaderObj  nandBoot;
  NAND_InfoHandle     hNandInfo;
#elif defined(UBL_NOR)
  NORBOOT_HeaderObj   norBoot;
  NOR_InfoHandle      hNorInfo;
#endif  
  UARTBOOT_HeaderObj  ackHeader;
  Uint32              bootCmd;

UART_tryAgain:
  DEBUG_printString("Starting UART Boot...\r\n");

  // UBL Sends 'BOOTUBL/0'
  if (LOCAL_sendSequence("BOOTUBL") != E_PASS)
    goto UART_tryAgain;

  // Receive the BOOT command
  if(LOCAL_recvCommand(&bootCmd) != E_PASS)
    goto UART_tryAgain;
    
  // Send ^^^DONE\0 to indicate command was accepted
  if ( LOCAL_sendSequence("   DONE") != E_PASS )
    goto UART_tryAgain;

  switch(bootCmd)
  {
#if defined(UBL_NOR)
    case UBL_MAGIC_NOR_FLASH_NO_UBL:
    {
      // Initialize the NOR Flash
      hNorInfo = NOR_open((Uint32)&EMIFStart, (Uint8)DEVICE_emifBusWidth());
      if (hNorInfo == NULL)
      {
        DEBUG_printString("NOR_open() failed!");
        goto UART_tryAgain;    
      }
    
      // Get the APP (should be u-boot) into binary form
      if ( LOCAL_recvHeaderAndData(&ackHeader) != E_PASS )
        goto UART_tryAgain;
      
      // Erasing the Flash
      if ( NOR_erase(hNorInfo,hNorInfo->flashBase, ackHeader.byteCnt) != E_PASS )
        goto UART_tryAgain;

      // Write the actual application to the flash
      if ( NOR_writeBytes(hNorInfo,hNorInfo->flashBase, ackHeader.byteCnt, (Uint32)ackHeader.imageBuff) != E_PASS )
        goto UART_tryAgain;
          
      // Return DONE when UBL flash operation has been completed
      if ( LOCAL_sendSequence("   DONE") != E_PASS )
        return E_FAIL;

      // Set the entry point for code execution
      gEntryPoint = hNorInfo->flashBase;
      break;
    }
    case UBL_MAGIC_NOR_FLASH:
    {
      Uint32 blockSize, blockAddr;
    
      // Initialize the NAND Flash
      hNorInfo = NOR_open((Uint32)&EMIFStart, (Uint8)DEVICE_emifBusWidth());
      if ( hNorInfo ==  NULL )
      {
        DEBUG_printString("NOR_open() failed!");
        goto UART_tryAgain;
      }
    
      // ------ Get UBL Data and Write it to Flash ------       
      // Get the UBL header and data
      if (LOCAL_recvHeaderAndData(&ackHeader) != E_PASS)
        goto UART_tryAgain;

      // Erasing the Flash
      if ( NOR_erase(hNorInfo,hNorInfo->flashBase, ackHeader.byteCnt) != E_PASS )
        goto UART_tryAgain;
	        
      // Write the UBL data to the start of the NOR flash
      DEBUG_printString("Writing UBL to NOR flash\r\n");
      if (NOR_writeBytes(hNorInfo,hNorInfo->flashBase, ackHeader.byteCnt, (Uint32)ackHeader.imageBuff) != E_PASS )
        goto UART_tryAgain;
          
      // Return DONE when UBL flash operation has been completed
      if ( LOCAL_sendSequence("   DONE") != E_PASS )
        return E_FAIL;
        
      // Get block size and base of block where UBL was written
      NOR_getBlockInfo(hNorInfo,hNorInfo->flashBase+ackHeader.byteCnt,&blockSize,&blockAddr);

      // Get the application header and data
      if (LOCAL_recvHeaderAndData(&ackHeader) != E_PASS)
        goto UART_tryAgain;
        
      // Setup the NORBOOT header that will be stored in flash
      norBoot.magicNum = ackHeader.magicNum;
      norBoot.entryPoint = ackHeader.startAddr;
      norBoot.appSize = ackHeader.byteCnt;
      norBoot.ldAddress = ackHeader.loadAddr;

      // Erasing the Flash
      if ( NOR_erase(hNorInfo,(blockAddr + blockSize), (ackHeader.byteCnt + sizeof(NORBOOT_HeaderObj))) != E_PASS )
        goto UART_tryAgain;
	        
      // Write the NORBOOT header to the flash
      DEBUG_printString("Writing APP to NOR flash\r\n");
      if (NOR_writeBytes(hNorInfo,(blockAddr + blockSize), sizeof(NORBOOT_HeaderObj), (Uint32)&norBoot) != E_PASS )
        goto UART_tryAgain;
      
      // Write the application data to the flash
      if ( NOR_writeBytes(hNorInfo,(blockAddr + blockSize + sizeof(NORBOOT_HeaderObj)), norBoot.appSize, (Uint32)ackHeader.imageBuff) != E_PASS )
        goto UART_tryAgain;
          
      // Return DONE when UBL flash operation has been completed
      if ( LOCAL_sendSequence("   DONE") != E_PASS )
        return E_FAIL;

      // Set the entry point to nowhere, since there isn't an appropriate binary image to run */
      gEntryPoint = 0x0;
      break;
    }  
    case UBL_MAGIC_NOR_ERASE:
    {
      // Initialize the NOR Flash
      hNorInfo = NOR_open((Uint32)&EMIFStart, (Uint8)DEVICE_emifBusWidth()) ;
      if (hNorInfo == NULL)
      {
        DEBUG_printString("NOR_open() failed!");
        goto UART_tryAgain;    
      }

      // Erasing the Flash
      if (NOR_globalErase(hNorInfo) != E_PASS)
      {
        DEBUG_printString("\r\nErase failed.\r\n");
      }
      else
      {
        DEBUG_printString("\r\nErase completed successfully.\r\n");
      }
      
      // Return DONE when erase operation has been completed
      if ( LOCAL_sendSequence("   DONE") != E_PASS )
        return E_FAIL;

      // Set the entry point for code execution
      // Go to reset in this case since no code was downloaded
      gEntryPoint = 0x0; 

      break;
    }
#elif defined(UBL_NAND)
    case UBL_MAGIC_NAND_FLASH:
    {
      Uint32 i;
    
      // Initialize the NAND Flash
      hNandInfo = NAND_open((Uint32)&EMIFStart, (Uint8) DEVICE_emifBusWidth() );
      if ( hNandInfo ==  NULL )
      {
        DEBUG_printString("NAND_open() failed!");
        goto UART_tryAgain;
      }
      
      // Allocate mem for write and read buffers (only once)
      hNandWriteBuf = UTIL_allocMem(hNandInfo->dataBytesPerPage);
      hNandReadBuf  = UTIL_allocMem(hNandInfo->dataBytesPerPage);
     	trvx(hNandWriteBuf); 
     	trvx(hNandReadBuf); 
      // Clear buffers
      for (i=0; i < hNandInfo->dataBytesPerPage; i++)
      {
        hNandWriteBuf[i] = 0xFF;
        hNandReadBuf[i] = 0xFF;
      }
    
      // ------ Get UBL Data and Write it to Flash ------       
      // Get the UBL header and data
      if (LOCAL_recvHeaderAndData(&ackHeader) != E_PASS)
        goto UART_tryAgain;
       
      // Setup fixed elements of the NANDBOOT header that will be stored in flash for UBL
      nandBoot.magicNum = ackHeader.magicNum;
      nandBoot.entryPoint = ackHeader.startAddr;
      nandBoot.page = 1;                          // The page is always page 0 for the UBL header, so we use page 1 for data        
      nandBoot.ldAddress = ackHeader.loadAddr;    // This field doesn't matter for the UBL header      
      nandBoot.forceContigImage = TRUE;
      nandBoot.startBlock = DEVICE_NAND_RBL_SEARCH_START_BLOCK;
      nandBoot.endBlock = DEVICE_NAND_RBL_SEARCH_END_BLOCK;
        
      // Calculate the number of NAND pages needed to store the UBL image
      nandBoot.numPage = 0;
      while ( (nandBoot.numPage * hNandInfo->dataBytesPerPage) < (ackHeader.byteCnt))
      {
        nandBoot.numPage++;
      }     
        
      // Write multiple copies of the UBL to the appropriate RBL search blocks
      DEBUG_printString("Writing UBL to NAND flash\r\n");
      if (LOCAL_NANDWriteHeaderAndData(hNandInfo, &nandBoot, ackHeader.imageBuff) != E_PASS)
      {
        DEBUG_printString("Writing failed!");
        goto UART_tryAgain;
      }
              
      // Return DONE when UBL flash operation has been completed
      if ( LOCAL_sendSequence("   DONE") != E_PASS )
        return E_FAIL;

      // ------ Get Application Data and Write it to Flash ------       
      // Get the application header and data
      if (LOCAL_recvHeaderAndData(&ackHeader) != E_PASS)
        goto UART_tryAgain;
      
      // Setup fixed elements of the NANDBOOT header that will be stored in flash for APP
      nandBoot.magicNum         = ackHeader.magicNum;         // Rely on the host applciation to send over the right magic number (safe or bin)
      nandBoot.entryPoint       = ackHeader.startAddr;      // Use the entrypoint received in ACK header
      nandBoot.page             = 1;                              // The page is always page 0 for the header, so we use page 1 for data
      nandBoot.ldAddress        = ackHeader.loadAddr;        // The load address is only important if this is a binary image
      nandBoot.forceContigImage = FALSE;
      nandBoot.startBlock       = DEVICE_NAND_UBL_SEARCH_START_BLOCK;
      nandBoot.endBlock         = DEVICE_NAND_UBL_SEARCH_END_BLOCK;      
      
      // Calculate the number of NAND pages needed to store the APP image
      nandBoot.numPage = 0;
      while ( (nandBoot.numPage * hNandInfo->dataBytesPerPage) < ackHeader.byteCnt )
      {
        nandBoot.numPage++;
      }

      // Write multiple copies of the APP to the appropriate UBL search blocks
      DEBUG_printString("Writing APP to NAND flash\r\n");
      if (LOCAL_NANDWriteHeaderAndData(hNandInfo, &nandBoot, ackHeader.imageBuff) != E_PASS)
      {
        DEBUG_printString("Writing failed!");
        goto UART_tryAgain;
      }

      // Return DONE when UBL flash operation has been completed
      if ( LOCAL_sendSequence("   DONE") != E_PASS )
        return E_FAIL;

      // Set the entry point to nowhere, since there isn't an appropriate binary image to run */
      gEntryPoint = 0x0;
      break;
    }  
    case UBL_MAGIC_NAND_ERASE:
    {
      // Initialize the NAND Flash
      hNandInfo = NAND_open((Uint32)&EMIFStart, (Uint8) DEVICE_emifBusWidth() );
      if ( hNandInfo ==  NULL )
      {
        DEBUG_printString("NAND_open() failed!");
        goto UART_tryAgain;
      }   

      // Unprotect the NAND Flash
      NAND_unProtectBlocks(hNandInfo, DEVICE_NAND_RBL_SEARCH_START_BLOCK, DEVICE_NAND_UBL_SEARCH_END_BLOCK-1);

      // Erase all the pages of the device
      if (NAND_eraseBlocks(hNandInfo, DEVICE_NAND_RBL_SEARCH_START_BLOCK, DEVICE_NAND_UBL_SEARCH_END_BLOCK-1) != E_PASS)
      {
        DEBUG_printString("Erase failed.\r\n");
        goto UART_tryAgain;
      }
      else
      {
        DEBUG_printString("Erase completed successfully.\r\n");
      }
                  
      // Protect the device
      NAND_protectBlocks(hNandInfo);
      
      // Return DONE when erase operation has been completed
      if ( LOCAL_sendSequence("   DONE") != E_PASS )
        return E_FAIL;

      // Set the entry point for code execution
      // Go to reset in this case since no code was downloaded 
      gEntryPoint = 0x0; 
      break;
    }
#elif defined(UBL_SDMMC)
    case UBL_MAGIC_SDMMC_FLASH:
    {
      break;
    }
    case UBL_MAGIC_SDMMC_ERASE:
    {
      break;
    }
#endif
    default:
    {
      DEBUG_printString("Boot command not supported!");
      return E_FAIL;
    }
  }
  
  LOCAL_sendSequence("   DONE");

  return E_PASS;
}