/* * nandboot.c - NAND boot mode functions * * Copyright (C) 2008 Hugo Villeneuve * * Based on TI DaVinci Flash and Boot Utilities, original copyright follows: * Copyright 2008 Texas Instruments, Inc. * * 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; }