You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.6 KiB
130 lines
3.6 KiB
/*
|
|
* 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_UBOOT_BLOCK_NUM;
|
|
last_header_block = END_UBOOT_BLOCK_NUM;
|
|
|
|
NAND_startAgain:
|
|
failedOnceAlready = false;
|
|
|
|
/* Read header about application starting at START_UBOOT_BLOCK_NUM, Page 0
|
|
* and try 50 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_str(", Block = ");
|
|
uart_send_hexnum(im_desc.block_num, 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;
|
|
}
|