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.
129 lines
3.6 KiB
129 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; |
|
}
|
|
|