ubl/nandboot.c

126 lines
3.5 KiB
C

/*
* nandboot.c - NAND boot mode functions
*
* Copyright (C) 2008 Hugo Villeneuve <hugo@hugovil.com>
*
* Based on TI DaVinci Flash and Boot Utilities, original copyright follows:
* Copyright 2008 Texas Instruments, Inc. <www.ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "common.h"
#include "nand.h"
#include "util.h"
#include "uart.h"
static uint8_t nand_header[MAX_PAGE_SIZE] __attribute__((section(".ddrram")));
/*
* Find out where the application is and copy to RAM
* jump_entry_point: Entry point for application we are decoding out of
* flash
*/
int
nand_copy(uint32_t *jump_entry_point)
{
uint32_t count, start_block;
uint32_t i;
uint32_t magicNum;
uint32_t block, page;
uint32_t readError = E_FAIL;
int failedOnceAlready = false;
uint8_t *rxBuf; /* Temporary buffer to load header in NAND */
struct nand_image_descriptor_t im_desc;
int last_header_block;
start_block = START_APP_BLOCK_NUM;
last_header_block = start_block + 10;
NAND_startAgain:
/* Read header about application starting at START_APP_BLOCK_NUM, Page 0
* and try 10 blocks. */
for (count = start_block; count <= last_header_block; count++) {
if (nand_read_page(count, 0, nand_header) != E_PASS)
continue;
magicNum = *((uint32_t *) nand_header);
/* Valid magic number found */
if ((magicNum & MAGIC_NUMBER_MASK) == MAGIC_NUMBER_VALID) {
start_block = count;
break;
}
}
/* Never found valid header. */
if (count > last_header_block)
return E_FAIL;
memcpy((void *) &im_desc, nand_header, sizeof(im_desc));
uart_send_str("Image infos: Magic = ");
uart_send_hexnum(im_desc.magic, 8);
uart_send_str(", Entry = ");
uart_send_hexnum(im_desc.entry_point, 8);
uart_send_str(", Pages = ");
uart_send_hexnum(im_desc.size_in_pages, 8);
uart_send_str(", Load = ");
uart_send_hexnum(im_desc.load_address, 8);
uart_send_lf();
rxBuf = (uint8_t *) im_desc.load_address;
NAND_retry:
/* initialize block and page number to be used for read */
block = im_desc.block_num;
page = im_desc.page_num;
/* Perform the actual copying of the application from NAND to RAM */
for (i = 0; i < im_desc.size_in_pages; i++) {
/* if page goes beyond max number of pages increment block
* number and reset page number */
if (page >= nand_get_pages_per_block()) {
page = 0;
block++;
}
/* Copy the data */
readError =
nand_read_page(block, page++,
&rxBuf[i * nand_get_bytes_per_page()]);
/*
* We attempt to read the app data twice. If we fail twice then
* we go look for a new application header in the NAND flash at
* the next block.
*/
if (readError != E_PASS) {
if (failedOnceAlready) {
start_block++;
goto NAND_startAgain;
} else {
failedOnceAlready = true;
goto NAND_retry;
}
}
}
/* Application was read correctly, so set entrypoint */
*jump_entry_point = im_desc.entry_point;
return E_PASS;
}