Index: sft/src/uartboot.c
===================================================================
--- Common/sft/src/uartboot.c	(revision 150)
+++ Common/sft/src/uartboot.c	(working copy)
@@ -293,11 +293,8 @@
       hNandReadBuf  = UTIL_allocMem(hNandInfo->dataBytesPerPage);
       
       // Clear buffers
-      for (i=0; i < hNandInfo->dataBytesPerPage; i++)
-      {
-        hNandWriteBuf[i] = 0xFF;
-        hNandReadBuf[i] = 0xFF;
-      }
+      UTIL_fillMem(hNandWriteBuf, (Uint32) 0xFFFFFFFF, hNandInfo->dataBytesPerPage);
+      UTIL_fillMem(hNandReadBuf, (Uint32) 0xFFFFFFFF, hNandInfo->dataBytesPerPage);
     
       // ------ Get UBL Data and Write it to Flash ------       
       // Get the UBL header and data
@@ -324,7 +321,7 @@
       DEBUG_printString("Writing UBL to NAND flash\r\n");
       if (LOCAL_NANDWriteHeaderAndData(hNandInfo, &nandBoot, ackHeader.imageBuff) != E_PASS)
       {
-        DEBUG_printString("Writing failed!");
+        DEBUG_printString("Writing failed!\r\n");
         goto UART_tryAgain;
       }
               
@@ -357,7 +354,7 @@
       DEBUG_printString("Writing APP to NAND flash\r\n");
       if (LOCAL_NANDWriteHeaderAndData(hNandInfo, &nandBoot, ackHeader.imageBuff) != E_PASS)
       {
-        DEBUG_printString("Writing failed!");
+        DEBUG_printString("Writing failed!\r\n");
         goto UART_tryAgain;
       }
 
@@ -537,6 +534,301 @@
 
 // Generic function to write a UBL or Application header and the associated data
 #if defined(UBL_NAND)
+
+static Uint32
+LOCAL_NANDWriteBlock(NAND_InfoHandle       hNandInfo,
+                     NANDBOOT_HeaderHandle hNandBoot,
+                     Uint32                blockNo,
+                     Uint32                pageCount,
+                     Uint8               **pDataPtr,
+                     Uint32               *pIsHeaderWritten)
+{
+   Uint32 *pPageBuf;
+   Uint32  pageNo;
+   Uint32  retCode;
+
+   pageNo = 0;
+
+   // Check block
+   retCode = E_PASS;
+
+   if(!(*pIsHeaderWritten))
+   {
+      // Write header page first
+      // Only set the flag if this entire block was written
+
+      pPageBuf = (Uint32 *) hNandWriteBuf;
+      UTIL_fillMem(pPageBuf, (Uint32) 0xFFFFFFFF, hNandInfo->dataBytesPerPage);
+
+      pPageBuf[0] = hNandBoot->magicNum;
+      pPageBuf[1] = hNandBoot->entryPoint;
+      pPageBuf[2] = hNandBoot->numPage;
+      pPageBuf[3] = blockNo;  // always start data in current block
+      pPageBuf[4] = 1;        // always start data in page 1 (this header goes in page 0)
+      pPageBuf[5] = hNandBoot->ldAddress;
+
+      retCode = NAND_writePage(hNandInfo, blockNo, 0, hNandWriteBuf);
+
+      if(retCode == E_PASS)
+      {
+         UTIL_waitLoop(600);
+         retCode = NAND_verifyPage(hNandInfo, blockNo, 0, hNandWriteBuf, hNandReadBuf);
+      }
+
+      if(retCode == E_PASS)
+      {
+         // Next page
+         ++pageNo;
+      }
+   }
+
+   while((retCode == E_PASS) && pageNo < pageCount)
+   {
+      UTIL_waitLoop(600);
+      retCode = NAND_writePage(hNandInfo, blockNo, pageNo, *pDataPtr);
+
+      if(retCode == E_PASS)
+      {
+         UTIL_waitLoop(600);
+         retCode = NAND_verifyPage(hNandInfo, blockNo, pageNo, *pDataPtr, hNandReadBuf);
+      }
+
+      ++pageNo;
+      *pDataPtr += hNandInfo->dataBytesPerPage;
+   }
+
+   if(retCode == E_PASS)
+   {
+      *pIsHeaderWritten = 1;
+   }
+   else
+   {
+      NAND_badBlockMark(hNandInfo, blockNo);
+      UTIL_waitLoop(600);
+   }
+
+   return retCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static Uint32
+LOCAL_NANDWriteHeaderAndData(NAND_InfoHandle       hNandInfo,
+                             NANDBOOT_HeaderHandle hNandBoot,
+                             Uint8                *pSrcBuf)
+{
+   Uint8  *pData;          // Used to iterate over data
+
+   Uint32 retCode;
+
+   Uint32 currentBlockNo;  // Which block we are operating on
+
+   Uint32 blockCount;      // How many blocks are in writing range
+
+   Uint32 writePageCount;  // How many pages to write
+   Uint32 dataBlockCount;  // How many blocks occupied by 1 copy
+
+   Uint32 goodBlockCount;  // How many blocks in our range are actually ok
+   Uint32 blocksRemaining; // Used as a down counter for tests
+
+   Uint32 pagesRemaining;  // Page down counter
+   Uint32 isHeaderWritten;
+   Uint32 dataCopyCount;
+
+   // Unprotect all needed blocks of the flash
+
+   blockCount = (hNandBoot->endBlock - hNandBoot->startBlock + 1);
+
+   retCode =
+      NAND_unProtectBlocks(hNandInfo,
+                             hNandBoot->startBlock,
+                               blockCount);
+
+   if( retCode != E_PASS)
+   {
+      DEBUG_printString("Unprotect failed\r\n");
+      return E_FAIL;
+   }
+
+   retCode = NAND_isWriteProtected(hNandInfo);
+
+   // Check if device is write protected
+   if(retCode != 0)
+   {
+      DEBUG_printString("NAND is write protected!\r\n");
+      return E_FAIL;
+   }
+
+   DEBUG_printString("Performing NAND erase on blocks ");
+   DEBUG_printHexInt(hNandBoot->startBlock);
+   DEBUG_printString(" to ");
+   DEBUG_printHexInt(hNandBoot->endBlock);
+   DEBUG_printString(" :\r\n");
+
+   goodBlockCount  = 0;
+   currentBlockNo  = hNandBoot->startBlock;
+   blocksRemaining = blockCount;
+   pData           = pSrcBuf;
+
+   while(blocksRemaining != 0)
+   {
+      // Check if block is marked bad
+      retCode = NAND_badBlockCheck(hNandInfo, currentBlockNo);
+
+      if(retCode == E_PASS)
+      {
+         // Block is not known to be bad, try erasure
+         retCode = NAND_eraseBlocks(hNandInfo, currentBlockNo, 1);
+
+         if(retCode != E_PASS)
+         {
+            DEBUG_printString("\tErase failed on block ");
+            DEBUG_printHexInt(currentBlockNo);
+            DEBUG_printString("\r\n");
+
+            NAND_badBlockMark(hNandInfo, currentBlockNo);
+         }
+      }
+      else
+      {
+         DEBUG_printString("\tSkipping bad block ");
+         DEBUG_printHexInt(currentBlockNo);
+         DEBUG_printString("\r\n");
+      }
+
+      if(retCode == E_PASS)
+      {
+         ++goodBlockCount;
+      }
+      else
+      if(currentBlockNo == hNandBoot->startBlock)
+      {
+         // Move the start position to a known good block
+         ++(hNandBoot->startBlock);
+      }
+
+      ++currentBlockNo;
+      --blocksRemaining;
+   }
+
+   // Post conditions:
+   // ** Any blocks that were not marked bad are erased
+   // ** Any blocks that did not erase correctly are marked bad
+   // ** goodBlockCount contains the number of blocks that passed
+
+   // Find out how many blocks 1 copy of the data will take
+
+   pagesRemaining  = hNandBoot->numPage + 1;
+   dataBlockCount  = UTIL_udiv32(pagesRemaining, hNandInfo->pagesPerBlock);
+
+   if(!dataBlockCount)
+   {
+      // Always write at least 1 block
+      dataBlockCount = 1;
+   }
+
+   if(dataBlockCount > goodBlockCount)
+   {
+      DEBUG_printString("\r\nNot enough good blocks for data!\r\n");
+      return E_FAIL;
+   }
+
+   // Set our counters and write out our data on a page basis
+
+   isHeaderWritten = 0;
+   currentBlockNo  = hNandBoot->startBlock;
+   dataCopyCount   = 0;
+
+   DEBUG_printString("\r\nBeginning NAND write at block ");
+   DEBUG_printHexInt(currentBlockNo);
+   DEBUG_printString("\r\n");
+
+   do
+   {
+      retCode = NAND_badBlockCheck(hNandInfo, currentBlockNo);
+
+      if(retCode == E_PASS)
+      {
+         // Consume block
+         --goodBlockCount;
+
+         if(pagesRemaining > hNandInfo->pagesPerBlock)
+         {
+            writePageCount = hNandInfo->pagesPerBlock;
+         }
+         else
+         {
+            writePageCount = pagesRemaining;
+         }
+
+         retCode =
+            LOCAL_NANDWriteBlock(hNandInfo,
+                                   hNandBoot,
+                                     currentBlockNo,
+                                       writePageCount,
+                                        &pData,
+                                         &isHeaderWritten);
+
+         if(retCode == E_PASS)
+         {
+            pagesRemaining -= writePageCount;
+
+            if(!pagesRemaining)
+            {
+               ++dataCopyCount;
+               DEBUG_printString("All pages written to NAND.\r\n");
+
+               if(dataBlockCount <= goodBlockCount)
+               {
+                  // Reset our page counter and header flag
+
+                  isHeaderWritten = 0;
+                  pagesRemaining  = hNandBoot->numPage + 1;
+                  pData           = pSrcBuf;
+
+                  DEBUG_printString("\r\nStarting next redundant copy at block ");
+                  DEBUG_printHexInt(currentBlockNo + 1);
+                  DEBUG_printString("\r\n");
+               }
+               else
+               {
+                  // Not enough blocks for another copy, so exit the main loop
+                  goodBlockCount = 0;
+               }
+            } // if(!pagesRemaining)
+         }// if(retCode == E_PASS)
+      } // if(retCode == E_PASS)
+      else
+      {
+         DEBUG_printString("\tSkipped bad block ");
+         DEBUG_printHexInt(currentBlockNo);
+         DEBUG_printString("\r\n");
+      }
+
+      ++currentBlockNo;
+
+   } while(goodBlockCount > 0);
+
+   // Final checks to see if we were successful in writing at least 1 image
+
+   DEBUG_printString("Finished NAND write: ");
+   DEBUG_printHexInt(dataCopyCount);
+   DEBUG_printString(" copies of data written.\r\n");
+
+   // Protect all blocks
+   NAND_protectBlocks(hNandInfo);
+
+   if(dataCopyCount > 0)
+   {
+      return E_PASS;
+   }
+   else
+   {
+      return E_FAIL;
+   }
+}
+
+#if 0 // Comment out old code
 static Uint32 LOCAL_NANDWriteHeaderAndData(NAND_InfoHandle hNandInfo, NANDBOOT_HeaderHandle hNandBoot, Uint8 *srcBuf)
 {
   Uint32    *ptr;
@@ -711,6 +1003,7 @@
   // We succeeded in writing all copies that would fit
   return E_PASS;
 }
+#endif // #if 0
 #endif
 
 
