diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/board_r.c | 10 | ||||
-rw-r--r-- | common/cmd_bootm.c | 23 | ||||
-rw-r--r-- | common/cmd_fastboot.c | 1888 | ||||
-rw-r--r-- | common/image-android.c | 19 | ||||
-rw-r--r-- | common/image-fdt.c | 29 |
6 files changed, 100 insertions, 1870 deletions
diff --git a/common/Makefile b/common/Makefile index 436ca39..f97a385 100644 --- a/common/Makefile +++ b/common/Makefile @@ -182,6 +182,7 @@ obj-y += usb.o usb_hub.o obj-$(CONFIG_USB_STORAGE) += usb_storage.o endif obj-$(CONFIG_CMD_FASTBOOT) += cmd_fastboot.o +obj-$(CONFIG_FSL_FASTBOOT) += aboot.o obj-$(CONFIG_CMD_FS_UUID) += cmd_fs_uuid.o obj-$(CONFIG_CMD_USB_MASS_STORAGE) += cmd_usb_mass_storage.o diff --git a/common/board_r.c b/common/board_r.c index ceccb80..b1ad605 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -58,8 +58,8 @@ #ifdef CONFIG_AVR32 #include <asm/arch/mmu.h> #endif -#ifdef CONFIG_FASTBOOT -#include <fastboot.h> +#ifdef CONFIG_FSL_FASTBOOT +#include <fsl_fastboot.h> #endif DECLARE_GLOBAL_DATA_PTR; @@ -676,7 +676,7 @@ static int initr_kbd(void) } #endif -#ifdef CONFIG_FASTBOOT +#ifdef CONFIG_FSL_FASTBOOT static int initr_fastboot_setup(void) { fastboot_setup(); @@ -865,7 +865,7 @@ init_fnc_t init_sequence_r[] = { #ifdef CONFIG_BOARD_LATE_INIT board_late_init, #endif -#ifdef CONFIG_FASTBOOT +#ifdef CONFIG_FSL_FASTBOOT initr_fastboot_setup, #endif #ifdef CONFIG_CMD_SCSI @@ -911,7 +911,7 @@ init_fnc_t init_sequence_r[] = { #ifdef CONFIG_PS2KBD initr_kbd, #endif -#ifdef CONFIG_FASTBOOT +#ifdef CONFIG_FSL_FASTBOOT initr_check_fastboot, #endif run_main_loop, diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index c4e8d58..b64eddc 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -130,9 +130,24 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #ifdef CONFIG_SECURE_BOOT extern uint32_t authenticate_image( uint32_t ddr_start, uint32_t image_size); - if (authenticate_image(load_addr, - image_get_image_size((image_header_t *)load_addr)) == 0) { - printf("Authenticate uImage Fail, Please check\n"); + + switch (genimg_get_format(load_addr)) { +#if defined(CONFIG_IMAGE_FORMAT_LEGACY) + case IMAGE_FORMAT_LEGACY: + if (authenticate_image(load_addr, + image_get_image_size((image_header_t *)load_addr)) == 0) { + printf("Authenticate uImage Fail, Please check\n"); + return 1; + } + break; +#endif +#ifdef CONFIG_ANDROID_BOOT_IMAGE + case IMAGE_FORMAT_ANDROID: + /* Do this authentication in boota command */ + break; +#endif + default: + printf("Not valid image format for Authentication, Please check\n"); return 1; } #endif @@ -651,7 +666,6 @@ U_BOOT_CMD( ); #endif /* CONFIG_CMD_BOOTZ */ -#if 0 #ifdef CONFIG_CMD_BOOTI /* See Documentation/arm64/booting.txt in the Linux kernel */ struct Image_header { @@ -800,4 +814,3 @@ U_BOOT_CMD( "boot arm64 Linux Image image from memory", booti_help_text ); #endif /* CONFIG_CMD_BOOTI */ -#endif diff --git a/common/cmd_fastboot.c b/common/cmd_fastboot.c index b41b8ee..7956a5b 100644 --- a/common/cmd_fastboot.c +++ b/common/cmd_fastboot.c @@ -1,1879 +1,49 @@ /* - * Copyright 2008 - 2009 (C) Wind River Systems, Inc. - * Tom Rix <Tom.Rix@windriver.com> + * Copyright 2008 - 2009 Windriver, <www.windriver.com> + * Author: Tom Rix <Tom.Rix@windriver.com> * - * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. + * (C) Copyright 2014 Linaro, Ltd. + * Rob Herring <robh@kernel.org> * - * 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., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * Part of the rx_handler were copied from the Android project. - * Specifically rx command parsing in the usb_rx_data_complete - * function of the file bootable/bootloader/legacy/usbloader/usbloader.c - * - * The logical naming of flash comes from the Android project - * Thse structures and functions that look like fastboot_flash_* - * They come from bootable/bootloader/legacy/libboot/flash.c - * - * This is their Copyright: - * - * Copyright (C) 2008 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * SPDX-License-Identifier: GPL-2.0+ */ -#include <asm/byteorder.h> #include <common.h> #include <command.h> -#include <nand.h> -#include <fastboot.h> -#include <environment.h> -#include <mmc.h> - -#if defined(CONFIG_OF_LIBFDT) -#include <libfdt.h> -#include <fdt_support.h> -#endif -#include <asm/bootm.h> - -#ifdef CONFIG_FASTBOOT - -int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); -extern int do_bootm_linux(int flag, int argc, - char *argv[], bootm_headers_t *images); - -/* Forward decl */ -static int tx_handler(void); -static int rx_handler(const unsigned char *buffer, unsigned int buffer_size); -static void reset_handler(void); - -static struct cmd_fastboot_interface interface = { - .rx_handler = rx_handler, - .reset_handler = reset_handler, - .product_name = NULL, - .serial_no = NULL, - .nand_block_size = 0, - .transfer_buffer = (unsigned char *)0xffffffff, - .transfer_buffer_size = 0, -}; - -static unsigned int download_size; -static unsigned int download_bytes; -static unsigned int download_bytes_unpadded; -static unsigned int download_error; -static unsigned int continue_booting; -static unsigned int upload_size; -static unsigned int upload_bytes; -static unsigned int upload_error; - -#define MMC_SATA_BLOCK_SIZE 512 - -#ifdef CONFIG_FASTBOOT_STORAGE_NAND -static void save_env(struct fastboot_ptentry *ptn, - char *var, char *val) -{ -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - char lock[128], unlock[128]; -#endif - - setenv(var, val); - -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - sprintf(lock, "nand lock 0x%x 0x%x", ptn->start, ptn->length); - sprintf(unlock, "nand unlock 0x%x 0x%x", ptn->start, ptn->length); - - /* This could be a problem is there is an outstanding lock */ - run_command(unlock, 0); -#endif - saveenv(); - -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - run_command(lock, 0); -#endif -} - -void save_parts_values(struct fastboot_ptentry *ptn, - unsigned int offset, - unsigned int size) -{ - char var[64], val[32]; -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - char lock[128], unlock[128]; - struct fastboot_ptentry *env_ptn; -#endif - - printf("saving it..\n"); - - - sprintf(var, "%s_nand_offset", ptn->name); - sprintf(val, "0x%x", offset); - - printf("setenv %s %s\n", var, val); - - setenv(var, val); - - sprintf(var, "%s_nand_size", ptn->name); - sprintf(val, "0x%x", size); - - printf("setenv %s %s\n", var, val); - - setenv(var, val); - -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - /* Warning : - The environment is assumed to be in a partition named 'enviroment'. - It is very possible that your board stores the enviroment - someplace else. */ - env_ptn = fastboot_flash_find_ptn("environment"); - - if (env_ptn) { - sprintf(lock, "nand lock 0x%x 0x%x", - env_ptn->start, env_ptn->length); - sprintf(unlock, "nand unlock 0x%x 0x%x", - env_ptn->start, env_ptn->length); - - run_command(unlock, 0); - } -#endif - saveenv(); - -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - if (env_ptn) - run_command(lock, 0); -#endif -} - -int check_parts_values(struct fastboot_ptentry *ptn) -{ - char var[64]; - - sprintf(var, "%s_nand_offset", ptn->name); - if (!getenv(var)) - return 1; - - sprintf(var, "%s_nand_size", ptn->name); - if (!getenv(var)) - return 1; - - return 0; -} +#include <g_dnl.h> -static int write_to_ptn(struct fastboot_ptentry *ptn) +static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { - int ret = 1; - char length[32]; - char write_type[32]; - int repeat, repeat_max; - -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - char lock[128]; - char unlock[128]; -#endif - char write[128]; - char erase[128]; - - printf("flashing '%s'\n", ptn->name); + int ret; - /* Which flavor of write to use */ - if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_I) - sprintf(write_type, "write.i"); -#ifdef CONFIG_CMD_NAND_TRIMFFS - else if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_TRIMFFS) - sprintf(write_type, "write.trimffs"); -#endif - else - sprintf(write_type, "write"); + g_dnl_clear_detach(); + ret = g_dnl_register("usb_dnl_fastboot"); + if (ret) + return ret; - /* Some flashing requires writing the same data in multiple, - consecutive flash partitions */ - repeat_max = 1; - if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_REPEAT_MASK) { - if (ptn->flags & - FASTBOOT_PTENTRY_FLAGS_WRITE_CONTIGUOUS_BLOCK) { - printf("Warning can not do both 'contiguous block' " - "and 'repeat' writes for for partition '%s'\n", ptn->name); - printf("Ignoring repeat flag\n"); - } else { - repeat_max = ptn->flags & - FASTBOOT_PTENTRY_FLAGS_REPEAT_MASK; - } + if (!g_dnl_board_usb_cable_connected()) { + puts("\rUSB cable not detected.\n" \ + "Command exit.\n"); + g_dnl_unregister(); + g_dnl_clear_detach(); + return CMD_RET_FAILURE; } - /* Unlock the whole partition instead of trying to - manage special cases */ - sprintf(length, "0x%x", ptn->length * repeat_max); - - for (repeat = 0; repeat < repeat_max; repeat++) { -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - sprintf(lock, "nand lock 0x%x %s", - ptn->start + (repeat * ptn->length), length); - sprintf(unlock, "nand unlock 0x%x %s", - ptn->start + (repeat * ptn->length), length); -#endif - sprintf(erase, "nand erase 0x%x %s", - ptn->start + (repeat * ptn->length), length); - -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - run_command(unlock, 0); -#endif - run_command(erase, 0); - - if ((ptn->flags & - FASTBOOT_PTENTRY_FLAGS_WRITE_NEXT_GOOD_BLOCK) && - (ptn->flags & - FASTBOOT_PTENTRY_FLAGS_WRITE_CONTIGUOUS_BLOCK)) { - /* Both can not be true */ - printf("Warning can not do 'next good block' and \ - 'contiguous block' for partition '%s'\n", - ptn->name); - printf("Ignoring these flags\n"); - } else if (ptn->flags & - FASTBOOT_PTENTRY_FLAGS_WRITE_NEXT_GOOD_BLOCK) { - /* Keep writing until you get a good block - transfer_buffer should already be aligned */ - if (interface.nand_block_size) { - unsigned int blocks = download_bytes / - interface.nand_block_size; - unsigned int i = 0; - unsigned int offset = 0; - - while (i < blocks) { - /* Check for overflow */ - if (offset >= ptn->length) - break; - - /* download's address only advance - if last write was successful */ - - /* nand's address always advances */ - sprintf(write, "nand %s 0x%p 0x%x 0x%x", write_type, - interface.transfer_buffer + - (i * interface.nand_block_size), - ptn->start + (repeat * ptn->length) + offset, - interface.nand_block_size); - - ret = run_command(write, 0); - if (ret) - break; - else - i++; - - /* Go to next nand block */ - offset += interface.nand_block_size; - } - } else { - printf("Warning nand block size can not be 0 \ - when using 'next good block' for \ - partition '%s'\n", ptn->name); - printf("Ignoring write request\n"); - } - } else if (ptn->flags & - FASTBOOT_PTENTRY_FLAGS_WRITE_CONTIGUOUS_BLOCK) { - /* Keep writing until you get a good block - transfer_buffer should already be aligned */ - if (interface.nand_block_size) { - if (0 == nand_curr_device) { - nand_info_t *nand; - unsigned long off; - unsigned int ok_start; - - nand = &nand_info[nand_curr_device]; - - printf("\nDevice %d bad blocks:\n", - nand_curr_device); - - /* Initialize the ok_start to the - start of the partition - Then try to find a block large - enough for the download */ - ok_start = ptn->start; - - /* It is assumed that the start and - length are multiples of block size */ - for (off = ptn->start; - off < ptn->start + ptn->length; - off += nand->erasesize) { - if (nand_block_isbad(nand, off)) { - /* Reset the ok_start - to the next block */ - ok_start = off + - nand->erasesize; - } - - /* Check if we have enough - blocks */ - if ((ok_start - off) >= - download_bytes) - break; - } - - /* Check if there is enough space */ - if (ok_start + download_bytes <= - ptn->start + ptn->length) { - - sprintf(write, "nand %s 0x%p 0x%x 0x%x", write_type, - interface.transfer_buffer, - ok_start, - download_bytes); - - ret = run_command(write, 0); - - /* Save the results into an - environment variable on the - format - ptn_name + 'offset' - ptn_name + 'size' */ - if (ret) { - /* failed */ - save_parts_values(ptn, ptn->start, 0); - } else { - /* success */ - save_parts_values(ptn, ok_start, download_bytes); - } - } else { - printf("Error could not find enough contiguous space " - "in partition '%s'\n", ptn->name); - printf("Ignoring write request\n"); - } - } else { - /* TBD : Generalize flash handling */ - printf("Error only handling 1 NAND per board"); - printf("Ignoring write request\n"); - } - } else { - printf("Warning nand block size can not be 0 \ - when using 'continuous block' for \ - partition '%s'\n", ptn->name); - printf("Ignoring write request\n"); - } - } else { - /* Normal case */ - sprintf(write, "nand %s 0x%p 0x%x 0x%x", write_type, - interface.transfer_buffer, - ptn->start + (repeat * ptn->length), - download_bytes); -#ifdef CONFIG_CMD_NAND_TRIMFFS - if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_TRIMFFS) { - sprintf(write, "nand %s 0x%p 0x%x 0x%x", write_type, - interface.transfer_buffer, - ptn->start + (repeat * ptn->length), - download_bytes_unpadded); - } -#endif - - ret = run_command(write, 0); - - if (0 == repeat) { - if (ret) /* failed */ - save_parts_values(ptn, ptn->start, 0); - else /* success */ - save_parts_values(ptn, ptn->start, - download_bytes); - } - } - -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - run_command(lock, 0); -#endif - - if (ret) + while (1) { + if (g_dnl_detach()) break; - } - - return ret; -} -#else -static void save_env(struct fastboot_ptentry *ptn, - char *var, char *val) -{ - setenv(var, val); - saveenv(); -} -#endif - -/* When save = 0, just parse. The input is unchanged - When save = 1, parse and do the save. The input is changed */ -static int parse_env(void *ptn, char *err_string, int save, int debug) -{ - int ret = 1; - unsigned int sets = 0; - unsigned int comment_start = 0; - char *var = NULL; - char *var_end = NULL; - char *val = NULL; - char *val_end = NULL; - unsigned int i; - - char *buff = (char *)interface.transfer_buffer; - unsigned int size = download_bytes_unpadded; - - /* The input does not have to be null terminated. - This will cause a problem in the corner case - where the last line does not have a new line. - Put a null after the end of the input. - - WARNING : Input buffer is assumed to be bigger - than the size of the input */ - if (save) - buff[size] = 0; - - for (i = 0; i < size; i++) { - - if (NULL == var) { - - /* - * Check for comments, comment ok only on - * mostly empty lines - */ - if (buff[i] == '#') - comment_start = 1; - - if (comment_start) { - if ((buff[i] == '\r') || - (buff[i] == '\n')) { - comment_start = 0; - } - } else { - if (!((buff[i] == ' ') || - (buff[i] == '\t') || - (buff[i] == '\r') || - (buff[i] == '\n'))) { - /* - * Normal whitespace before the - * variable - */ - var = &buff[i]; - } - } - - } else if (((NULL == var_end) || (NULL == val)) && - ((buff[i] == '\r') || (buff[i] == '\n'))) { - - /* This is the case when a variable - is unset. */ - - if (save) { - /* Set the var end to null so the - normal string routines will work - - WARNING : This changes the input */ - buff[i] = '\0'; - - save_env(ptn, var, val); - - if (debug) - printf("Unsetting %s\n", var); - } - - /* Clear the variable so state is parse is back - to initial. */ - var = NULL; - var_end = NULL; - sets++; - } else if (NULL == var_end) { - if ((buff[i] == ' ') || - (buff[i] == '\t')) - var_end = &buff[i]; - } else if (NULL == val) { - if (!((buff[i] == ' ') || - (buff[i] == '\t'))) - val = &buff[i]; - } else if (NULL == val_end) { - if ((buff[i] == '\r') || - (buff[i] == '\n')) { - /* look for escaped cr or ln */ - if ('\\' == buff[i - 1]) { - /* check for dos */ - if ((buff[i] == '\r') && - (buff[i+1] == '\n')) - buff[i + 1] = ' '; - buff[i - 1] = buff[i] = ' '; - } else { - val_end = &buff[i]; - } - } - } else { - sprintf(err_string, "Internal Error"); - - if (debug) - printf("Internal error at %s %d\n", - __FILE__, __LINE__); - return 1; - } - /* Check if a var / val pair is ready */ - if (NULL != val_end) { - if (save) { - /* Set the end's with nulls so - normal string routines will - work. - - WARNING : This changes the input */ - *var_end = '\0'; - *val_end = '\0'; - - save_env(ptn, var, val); - - if (debug) - printf("Setting %s %s\n", var, val); - } - - /* Clear the variable so state is parse is back - to initial. */ - var = NULL; - var_end = NULL; - val = NULL; - val_end = NULL; - - sets++; - } - } - - /* Corner case - Check for the case that no newline at end of the input */ - if ((NULL != var) && - (NULL == val_end)) { - if (save) { - /* case of val / val pair */ - if (var_end) - *var_end = '\0'; - /* else case handled by setting 0 past - the end of buffer. - Similar for val_end being null */ - save_env(ptn, var, val); - - if (debug) { - if (var_end) - printf("Trailing Setting %s %s\n", var, val); - else - printf("Trailing Unsetting %s\n", var); - } - } - sets++; - } - /* Did we set anything ? */ - if (0 == sets) - sprintf(err_string, "No variables set"); - else - ret = 0; - - return ret; -} - -static int saveenv_to_ptn(struct fastboot_ptentry *ptn, char *err_string) -{ - int ret = 1; - int save = 0; - int debug = 0; - - /* err_string is only 32 bytes - Initialize with a generic error message. */ - sprintf(err_string, "%s", "Unknown Error"); - - /* Parse the input twice. - Only save to the enviroment if the entire input if correct */ - save = 0; - if (0 == parse_env(ptn, err_string, save, debug)) { - save = 1; - ret = parse_env(ptn, err_string, save, debug); - } - return ret; -} - - -#if defined(CONFIG_FASTBOOT_STORAGE_NAND) - -static void process_flash_nand(const char *cmdbuf, char *response) -{ - if (download_bytes) { - struct fastboot_ptentry *ptn; - - ptn = fastboot_flash_find_ptn(cmdbuf + 6); - if (ptn == 0) { - sprintf(response, "FAILpartition does not exist"); - } else if ((download_bytes > ptn->length) && - !(ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_ENV)) { - sprintf(response, "FAILimage too large for partition"); - /* TODO : Improve check for yaffs write */ - } else { - /* Check if this is not really a flash write - but rather a saveenv */ - if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_ENV) { - /* Since the response can only be 64 bytes, - there is no point in having a large error message. */ - char err_string[32]; - if (saveenv_to_ptn(ptn, &err_string[0])) { - printf("savenv '%s' failed : %s\n", - ptn->name, err_string); - sprintf(response, "FAIL%s", err_string); - } else { - printf("partition '%s' saveenv-ed\n", ptn->name); - sprintf(response, "OKAY"); - } - } else { - /* Normal case */ - if (write_to_ptn(ptn)) { - printf("flashing '%s' failed\n", ptn->name); - sprintf(response, "FAILfailed to flash partition"); - } else { - printf("partition '%s' flashed\n", ptn->name); - sprintf(response, "OKAY"); - } - } - } - } else { - sprintf(response, "FAILno image downloaded"); - } - -} -#endif - -#if defined(CONFIG_FASTBOOT_STORAGE_SATA) -static void process_flash_sata(const char *cmdbuf, char *response) -{ - if (download_bytes) { - struct fastboot_ptentry *ptn; - - /* Next is the partition name */ - ptn = fastboot_flash_find_ptn(cmdbuf + 6); - if (ptn == 0) { - printf("Partition:'%s' does not exist\n", ptn->name); - sprintf(response, "FAILpartition does not exist"); - } else if ((download_bytes > - ptn->length * MMC_SATA_BLOCK_SIZE) && - !(ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_ENV)) { - printf("Image too large for the partition\n"); - sprintf(response, "FAILimage too large for partition"); - } else if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_ENV) { - /* Since the response can only be 64 bytes, - there is no point in having a large error message. */ - char err_string[32]; - if (saveenv_to_ptn(ptn, &err_string[0])) { - printf("savenv '%s' failed : %s\n", ptn->name, err_string); - sprintf(response, "FAIL%s", err_string); - } else { - printf("partition '%s' saveenv-ed\n", ptn->name); - sprintf(response, "OKAY"); - } - } else { - unsigned int temp; - char sata_write[128]; - - /* block count */ - temp = (download_bytes + - MMC_SATA_BLOCK_SIZE - 1) / - MMC_SATA_BLOCK_SIZE; - - sprintf(sata_write, "sata write 0x%x 0x%x 0x%x", - (unsigned int)interface.transfer_buffer, - ptn->start, - temp) - - if (run_command(sata_write, 0)) { - printf("Writing '%s' FAILED!\n", - ptn->name); - sprintf(response, - "FAIL: Write partition"); - } else { - printf("Writing '%s' DONE!\n", - ptn->name); - sprintf(response, "OKAY"); - } - } - } else { - sprintf(response, "FAILno image downloaded"); - } - -} -#endif - -#if defined(CONFIG_FASTBOOT_STORAGE_MMC) -static void process_flash_mmc(const char *cmdbuf, char *response) -{ - if (download_bytes) { - struct fastboot_ptentry *ptn; - - /* Next is the partition name */ - ptn = fastboot_flash_find_ptn(cmdbuf + 6); - if (ptn == 0) { - printf("Partition:'%s' does not exist\n", ptn->name); - sprintf(response, "FAILpartition does not exist"); - } else if ((download_bytes > - ptn->length * MMC_SATA_BLOCK_SIZE) && - !(ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_ENV)) { - printf("Image too large for the partition\n"); - sprintf(response, "FAILimage too large for partition"); - } else if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_WRITE_ENV) { - /* Since the response can only be 64 bytes, - there is no point in having a large error message. */ - char err_string[32]; - if (saveenv_to_ptn(ptn, &err_string[0])) { - printf("savenv '%s' failed : %s\n", ptn->name, err_string); - sprintf(response, "FAIL%s", err_string); - } else { - printf("partition '%s' saveenv-ed\n", ptn->name); - sprintf(response, "OKAY"); - } - } else { - unsigned int temp; - - char mmc_dev[128]; - char mmc_write[128]; - int mmcret; - - printf("writing to partition '%s'\n", ptn->name); - - if (ptn->partition_id != FASTBOOT_MMC_NONE_PARTITION_ID) - sprintf(mmc_dev, "mmc dev %x %x", - fastboot_devinfo.dev_id, /*slot no*/ - ptn->partition_id /*part no*/); - else - sprintf(mmc_dev, "mmc dev %x", - fastboot_devinfo.dev_id /*slot no*/); - - /* block count */ - temp = (download_bytes + - MMC_SATA_BLOCK_SIZE - 1) / - MMC_SATA_BLOCK_SIZE; - - sprintf(mmc_write, "mmc write 0x%x 0x%x 0x%x", - (unsigned int)interface.transfer_buffer, /*source*/ - ptn->start, /*dest*/ - temp /*length*/); - - printf("Initializing '%s'\n", ptn->name); - - mmcret = run_command(mmc_dev, 0); - if (mmcret) - sprintf(response, "FAIL:Init of MMC card"); - else - sprintf(response, "OKAY"); - - printf("Writing '%s'\n", ptn->name); - if (run_command(mmc_write, 0)) { - printf("Writing '%s' FAILED!\n", ptn->name); - sprintf(response, "FAIL: Write partition"); - } else { - printf("Writing '%s' DONE!\n", ptn->name); - sprintf(response, "OKAY"); - } - } - } else { - sprintf(response, "FAILno image downloaded"); - } -} - -#endif - -static void reset_handler () -{ - /* If there was a download going on, bail */ - download_size = 0; - download_bytes = 0; - download_bytes_unpadded = 0; - download_error = 0; - continue_booting = 0; - upload_size = 0; - upload_bytes = 0; - upload_error = 0; -} - -static void rx_process_getvar(const char *cmdbuf, char *response) -{ - int temp_len = 0; - - strcpy(response, "OKAY"); - - temp_len = strlen("getvar:"); - if (!strcmp(cmdbuf + temp_len, "version")) { - strcpy(response + 4, FASTBOOT_VERSION); - } else if (!strcmp(cmdbuf + temp_len, - "product")) { - if (interface.product_name) - strcpy(response + 4, interface.product_name); - - } else if (!strcmp(cmdbuf + temp_len, - "serialno")) { - if (interface.serial_no) - strcpy(response + 4, interface.serial_no); - - } else if (!strcmp(cmdbuf + temp_len, - "downloadsize")) { - if (interface.transfer_buffer_size) - sprintf(response + 4, "0x%x", - interface.transfer_buffer_size); - } else { - fastboot_getvar(cmdbuf + 7, response + 4); - } -} - -static void rx_process_reboot(const char *cmdbuf, char *response) -{ - sprintf(response, "OKAY"); - fastboot_tx_status(response, strlen(response)); - udelay(1000000); /* 1 sec */ - - do_reset(NULL, 0, 0, NULL); -} - -static int rx_process_erase(const char *cmdbuf, char *response) -{ -#if defined(CONFIG_FASTBOOT_STORAGE_NAND) - struct fastboot_ptentry *ptn; - - ptn = fastboot_flash_find_ptn(cmdbuf + 6); - if (ptn == 0) { - sprintf(response, "FAILpartition does not exist"); - } else { - int status, repeat, repeat_max; - - printf("erasing '%s'\n", ptn->name); - -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - char lock[128]; - char unlock[128]; -#endif - char erase[128]; - - repeat_max = 1; - if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_REPEAT_MASK) - repeat_max = ptn->flags & FASTBOOT_PTENTRY_FLAGS_REPEAT_MASK; - - for (repeat = 0; repeat < repeat_max; - repeat++) { -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - sprintf(lock, "nand lock 0x%x 0x%x", - ptn->start + (repeat * ptn->length), - ptn->length); - sprintf(unlock, "nand unlock 0x%x 0x%x", - ptn->start + (repeat * ptn->length), - ptn->length); -#endif - sprintf(erase, "nand erase 0x%x 0x%x", - ptn->start + (repeat * ptn->length), - ptn->length); - -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - run_command(unlock, 0); -#endif - status = run_command(erase, 0); -#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK - run_command(lock, 0); -#endif - - if (status) - break; - } - - if (status) { - sprintf(response, - "FAILfailed to erase partition"); - } else { - printf("partition '%s' erased\n", ptn->name); - sprintf(response, "OKAY"); - } - } - return 0; -#else - printf("Not support erase command for EMMC\n"); - return -1; -#endif - -} - -static void rx_process_flash(const char *cmdbuf, char *response) -{ - switch (fastboot_devinfo.type) { -#if defined(CONFIG_FASTBOOT_STORAGE_SATA) - case DEV_SATA: - process_flash_sata(cmdbuf, response); - break; -#endif -#if defined(CONFIG_FASTBOOT_STORAGE_MMC) - case DEV_MMC: - process_flash_mmc(cmdbuf, response); - break; -#endif -#if defined(CONFIG_FASTBOOT_STORAGE_NAND) - case DEV_NAND: - process_flash_nand(cmdbuf, response); - break; -#endif - default: - printf("Not support flash command for current device %d\n", - fastboot_devinfo.type); - sprintf(response, - "FAILfailed to flash device"); - break; - } -} - -static void rx_process_boot(const char *cmdbuf, char *response) -{ - if ((download_bytes) && - (CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE < - download_bytes)) { - char start[32]; - char *booti_args[4] = {"booti", NULL, "boot", NULL}; - - /* - * Use this later to determine if a command line was passed - * for the kernel. - */ - /* struct fastboot_boot_img_hdr *fb_hdr = */ - /* (struct fastboot_boot_img_hdr *) interface.transfer_buffer; */ - - /* Skip the mkbootimage header */ - /* image_header_t *hdr = */ - /* (image_header_t *) */ - /* &interface.transfer_buffer[CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE]; */ - - booti_args[1] = start; - sprintf(start, "0x%x", (unsigned int)interface.transfer_buffer); - - /* Execution should jump to kernel so send the response - now and wait a bit. */ - sprintf(response, "OKAY"); - fastboot_tx_status(response, strlen(response)); - - printf("Booting kernel...\n"); - - - /* Reserve for further use, this can - * be more convient for developer. */ - /* if (strlen ((char *) &fb_hdr->cmdline[0])) */ - /* set_env("bootargs", (char *) &fb_hdr->cmdline[0]); */ - - /* boot the boot.img */ - do_booti(NULL, 0, 3, booti_args); - - - } - sprintf(response, "FAILinvalid boot image"); -} - -static void rx_process_upload(const char *cmdbuf, char *response) -{ -#if defined(CONFIG_FASTBOOT_STORAGE_NAND) - unsigned int adv, delim_index, len; - struct fastboot_ptentry *ptn; - unsigned int is_raw = 0; - - /* Is this a raw read ? */ - if (memcmp(cmdbuf, "uploadraw:", 10) == 0) { - is_raw = 1; - adv = 10; - } else { - adv = 7; - } - - /* Scan to the next ':' to find when the size starts */ - len = strlen(cmdbuf); - for (delim_index = adv; - delim_index < len; delim_index++) { - if (cmdbuf[delim_index] == ':') { - /* WARNING, cmdbuf is being modified. */ - *((char *) &cmdbuf[delim_index]) = 0; + if (ctrlc()) break; - } - } - - ptn = fastboot_flash_find_ptn(cmdbuf + adv); - if (ptn == 0) { - sprintf(response, - "FAILpartition does not exist"); - } else { - /* This is how much the user is expecting */ - unsigned int user_size; - /* - * This is the maximum size needed for - * this partition - */ - unsigned int size; - /* This is the length of the data */ - unsigned int length; - /* - * Used to check previous write of - * the parition - */ - char env_ptn_length_var[128]; - char *env_ptn_length_val; - - user_size = 0; - if (delim_index < len) - user_size = - simple_strtoul(cmdbuf + delim_index + 1, - NULL, 16); - - /* Make sure output is padded to block size */ - length = ptn->length; - sprintf(env_ptn_length_var, - "%s_nand_size", ptn->name); - env_ptn_length_val = getenv(env_ptn_length_var); - if (env_ptn_length_val) { - length = - simple_strtoul(env_ptn_length_val, - NULL, 16); - /* Catch possible problems */ - if (!length) - length = ptn->length; - } - - size = length / interface.nand_block_size; - size *= interface.nand_block_size; - if (length % interface.nand_block_size) - size += interface.nand_block_size; - - if (is_raw) - size += (size / - interface.nand_block_size) * - interface.nand_oob_size; - - if (size > interface.transfer_buffer_size) { - - sprintf(response, "FAILdata too large"); - - } else if (user_size == 0) { - - /* Send the data response */ - sprintf(response, "DATA%08x", size); - - } else if (user_size != size) { - /* This is the wrong size */ - sprintf(response, "FAIL"); - } else { - /* - * This is where the transfer - * buffer is populated - */ - unsigned char *buf = - interface.transfer_buffer; - char read[128]; - - /* - * Setting upload_size causes - * transfer to happen in main loop - */ - upload_size = size; - upload_bytes = 0; - upload_error = 0; - - /* - * Poison the transfer buffer, 0xff - * is erase value of nand - */ - memset(buf, 0xff, upload_size); - - /* Which flavor of read to use */ - if (is_raw) - sprintf(read, "nand read.raw 0x%x 0x%x 0x%x", - (unsigned int)(interface.transfer_buffer), - ptn->start, - upload_size); - else - sprintf(read, "nand read.i 0x%x 0x%x 0x%x", - (unsigned int)(interface.transfer_buffer), - ptn->start, - upload_size); - - run_command(read, 0); - - /* Send the data response */ - sprintf(response, "DATA%08x", size); - } - } -#endif - -} - -static int tx_handler(void) -{ - if (upload_size) { - - int bytes_written; - bytes_written = fastboot_tx(interface.transfer_buffer + - upload_bytes, upload_size - - upload_bytes); - if (bytes_written > 0) { - - upload_bytes += bytes_written; - /* Check if this is the last */ - if (upload_bytes == upload_size) { - - /* Reset upload */ - upload_size = 0; - upload_bytes = 0; - upload_error = 0; - } - } - } - return upload_error; -} - -static int rx_handler (const unsigned char *buffer, unsigned int buffer_size) -{ - int ret = 1; - - /*response buffer, Use 65 instead of 64 - null gets dropped. strcpy's need the extra byte */ - char response[FASTBOOT_RESPONSE_SIZE]; - - if (download_size) { - /* Something to download */ - - if (buffer_size) { - /* Handle possible overflow */ - unsigned int transfer_size = - download_size - download_bytes; - - if (buffer_size < transfer_size) - transfer_size = buffer_size; - - /* Save the data to the transfer buffer */ - memcpy(interface.transfer_buffer + download_bytes, - buffer, transfer_size); - - download_bytes += transfer_size; - - /* Check if transfer is done */ - if (download_bytes >= download_size) { - /* Reset global transfer variable, - Keep download_bytes because it will be - used in the next possible flashing command */ - download_size = 0; - - if (download_error) { - /* There was an earlier error */ - sprintf(response, "ERROR"); - } else { - /* Everything has transferred, - send the OK response */ - sprintf(response, "OKAY"); - } - fastboot_tx_status(response, strlen(response)); - - printf("\ndownloading of %d bytes finished\n", - download_bytes); - -#if defined(CONFIG_FASTBOOT_STORAGE_NAND) - /* Pad to block length - In most cases, padding the download to be - block aligned is correct. The exception is - when the following flash writes to the oob - area. This happens when the image is a - YAFFS image. Since we do not know what - the download is until it is flashed, - go ahead and pad it, but save the true - size in case if should have - been unpadded */ - download_bytes_unpadded = download_bytes; - if (interface.nand_block_size) { - if (download_bytes % - interface.nand_block_size) { - unsigned int pad = - interface.nand_block_size - - (download_bytes % interface.nand_block_size); - unsigned int i; - - for (i = 0; i < pad; i++) { - if (download_bytes >= - interface.transfer_buffer_size) - break; - - interface.transfer_buffer[download_bytes] = 0; - download_bytes++; - } - } - } -#endif - } - - /* Provide some feedback */ - if (download_bytes && - 0 == (download_bytes % - (16 * interface.nand_block_size))) { - /* Some feeback that the - download is happening */ - if (download_error) - printf("X"); - else - printf("."); - if (0 == (download_bytes % - (80 * 16 * - interface.nand_block_size))) - printf("\n"); - - } - } else { - /* Ignore empty buffers */ - printf("Warning empty download buffer\n"); - printf("Ignoring\n"); - } - ret = 0; - } else { - /* A command */ - - /* Cast to make compiler happy with string functions */ - const char *cmdbuf = (char *) buffer; - printf("cmdbuf: %s\n", cmdbuf); - - /* Generic failed response */ - sprintf(response, "FAIL"); - - /* reboot - Reboot the board. */ - if (memcmp(cmdbuf, "reboot", 6) == 0) { - rx_process_reboot(cmdbuf, response); - /* This code is unreachable, - leave it to make the compiler happy */ - return 0; - } - - /* getvar - Get common fastboot variables - Board has a chance to handle other variables */ - if (memcmp(cmdbuf, "getvar:", 7) == 0) { - rx_process_getvar(cmdbuf, response); - ret = 0; - } - - /* erase - Erase a register flash partition - Board has to set up flash partitions */ - if (memcmp(cmdbuf, "erase:", 6) == 0) - ret = rx_process_erase(cmdbuf, response); - - /* download - download something .. - What happens to it depends on the next command after data */ - - if (memcmp(cmdbuf, "download:", 9) == 0) { - - /* save the size */ - download_size = simple_strtoul(cmdbuf + 9, NULL, 16); - /* Reset the bytes count, now it is safe */ - download_bytes = 0; - /* Reset error */ - download_error = 0; - - printf("Starting download of %d bytes\n", - download_size); - - if (0 == download_size) { - /* bad user input */ - sprintf(response, "FAILdata invalid size"); - } else if (download_size > - interface.transfer_buffer_size) { - /* set download_size to 0 because this is an error */ - download_size = 0; - sprintf(response, "FAILdata too large"); - } else { - /* The default case, the transfer fits - completely in the interface buffer */ - sprintf(response, "DATA%08x", download_size); - } - ret = 0; - } - - /* boot - boot what was downloaded - - WARNING WARNING WARNING - - This is not what you expect. - The fastboot client does its own packaging of the - kernel. The layout is defined in the android header - file bootimage.h. This layeout is copiedlooks like this, - - ** - ** +-----------------+ - ** | boot header | 1 page - ** +-----------------+ - ** | kernel | n pages - ** +-----------------+ - ** | ramdisk | m pages - ** +-----------------+ - ** | second stage | o pages - ** +-----------------+ - ** - - We only care about the kernel. - So we have to jump past a page. - - What is a page size ? - The fastboot client uses 2048 - - The is the default value of - - CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE - - */ - - if (memcmp(cmdbuf, "boot", 4) == 0) { - rx_process_boot(cmdbuf, response); - ret = 0; - } - - /* flash - Flash what was downloaded */ - if (memcmp(cmdbuf, "flash:", 6) == 0) { - rx_process_flash(cmdbuf, response); - ret = 0; - } - - /* continue - Stop doing fastboot */ - if (memcmp(cmdbuf, "continue", 8) == 0) { - sprintf(response, "OKAY"); - continue_booting = 1; - ret = 0; - } - - /* upload - Upload just the data in a partition */ - if ((memcmp(cmdbuf, "upload:", 7) == 0) || - (memcmp(cmdbuf, "uploadraw:", 10) == 0)) { - rx_process_upload(cmdbuf, response); - ret = 0; - } - - fastboot_tx_status(response, strlen(response)); - - } /* End of command */ - - return ret; -} - -int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int ret = 1; - int check_timeout = 0; - uint64_t timeout_endtime = 0; - uint64_t timeout_ticks = 1000; - int continue_from_disconnect = 0; - - do { - continue_from_disconnect = 0; - - /* Initialize the board specific support */ - if (0 == fastboot_init(&interface)) { - - int poll_status; - - /* If we got this far, we are a success */ - ret = 0; - printf("fastboot initialized\n"); - - timeout_endtime = get_timer(0); - timeout_endtime += timeout_ticks; - - while (1) { - uint64_t current_time = 0; - poll_status = fastboot_poll(); - - if (1 == check_timeout) - current_time = get_timer(0); - - if (FASTBOOT_ERROR == poll_status) { - /* Error */ - break; - } else if (FASTBOOT_DISCONNECT == poll_status) { - /* beak, cleanup and re-init */ - printf("Fastboot disconnect detected\n"); - continue_from_disconnect = 1; - break; - } else if ((1 == check_timeout) && - (FASTBOOT_INACTIVE == poll_status)) { - - /* No activity */ - if (current_time >= timeout_endtime) { - printf("Fastboot inactivity detected\n"); - break; - } - } else { - /* Something happened */ - if (1 == check_timeout) { - /* Update the timeout endtime */ - timeout_endtime = current_time; - timeout_endtime += timeout_ticks; - } - } - - /* Check if the user wanted to terminate with ^C */ - if ((FASTBOOT_INACTIVE == poll_status) && - (ctrlc())) { - printf("Fastboot ended by user\n"); - break; - } - - /* - * Check if the fastboot client wanted to - * continue booting - */ - if (continue_booting) { - printf("Fastboot ended by client\n"); - break; - } - - /* Check if there is something to upload */ - tx_handler(); - } - } - - /* Reset the board specific support */ - fastboot_shutdown(); - - /* restart the loop if a disconnect was detected */ - } while (continue_from_disconnect); - - return ret; -} - -U_BOOT_CMD( - fastboot, 2, 1, do_fastboot, - "fastboot- use USB Fastboot protocol\n", - "[inactive timeout]\n" - " - Run as a fastboot usb device.\n" - " - The optional inactive timeout is the decimal seconds before\n" - " - the normal console resumes\n" -); - - -#ifdef CONFIG_CMD_BOOTI - /* Section for Android bootimage format support - * Refer: - * http://android.git.kernel.org/?p=platform/system/core.git;a=blob; - * f=mkbootimg/bootimg.h - */ - -void -bootimg_print_image_hdr(struct fastboot_boot_img_hdr *hdr) -{ -#ifdef DEBUG - int i; - printf(" Image magic: %s\n", hdr->magic); - - printf(" kernel_size: 0x%x\n", hdr->kernel_size); - printf(" kernel_addr: 0x%x\n", hdr->kernel_addr); - - printf(" rdisk_size: 0x%x\n", hdr->ramdisk_size); - printf(" rdisk_addr: 0x%x\n", hdr->ramdisk_addr); - - printf(" second_size: 0x%x\n", hdr->second_size); - printf(" second_addr: 0x%x\n", hdr->second_addr); - - printf(" tags_addr: 0x%x\n", hdr->tags_addr); - printf(" page_size: 0x%x\n", hdr->page_size); - - printf(" name: %s\n", hdr->name); - printf(" cmdline: %s%x\n", hdr->cmdline); - - for (i = 0; i < 8; i++) - printf(" id[%d]: 0x%x\n", i, hdr->id[i]); -#endif -} - -static struct fastboot_boot_img_hdr boothdr __aligned(ARCH_DMA_MINALIGN); - -#define ALIGN_SECTOR(n, pagesz) ((n + (pagesz - 1)) & (~(pagesz - 1))) - -#ifdef CONFIG_LMB -static void boot_start_lmb(bootm_headers_t *images) -{ - ulong mem_start; - phys_size_t mem_size; - - lmb_init(&images->lmb); - - mem_start = getenv_bootm_low(); - mem_size = getenv_bootm_size(); - - lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size); - - arch_lmb_reserve(&images->lmb); - board_lmb_reserve(&images->lmb); -} -#else -#define lmb_reserve(lmb, base, size) -static inline void boot_start_lmb(bootm_headers_t *images) { } -#endif - -/* Allow for arch specific config before we boot */ -static void __arch_preboot_os(void) -{ - /* please define platform specific arch_preboot_os() */ -} -void arch_preboot_os(void) __attribute__((weak, alias("__arch_preboot_os"))); - -/* booti <addr> [ mmc0 | mmc1 [ <partition> ] ] */ -int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unsigned addr = 0; - char *ptn = "boot"; - int mmcc = -1; - struct fastboot_boot_img_hdr *hdr = &boothdr; - uint32_t image_size; - unsigned bootimg_addr; -#ifdef CONFIG_SECURE_BOOT -#define IVT_SIZE 0x20 -#define CSF_PAD_SIZE 0x2000 -/* Max of bootimage size to be 16MB */ -#define MAX_ANDROID_BOOT_AUTH_SIZE 0x1000000 -/* Size appended to boot.img with boot_signer */ -#define BOOTIMAGE_SIGNATURE_SIZE 0x100 -#endif - int i = 0; - bootm_headers_t images; - - for (i = 0; i < argc; i++) - printf("%s ", argv[i]); - printf("\n"); - - if (argc < 2) - return -1; - - if (!strncmp(argv[1], "mmc", 3)) - mmcc = simple_strtoul(argv[1]+3, NULL, 10); - else - addr = simple_strtoul(argv[1], NULL, 16); - - if (argc > 2) - ptn = argv[2]; - - if (mmcc != -1) { -#ifdef CONFIG_MMC - struct fastboot_ptentry *pte; - struct mmc *mmc; - disk_partition_t info; - block_dev_desc_t *dev_desc = NULL; - unsigned sector; - unsigned bootimg_sectors; - - memset((void *)&info, 0 , sizeof(disk_partition_t)); - /* i.MX use MBR as partition table, so this will have - to find the start block and length for the - partition name and register the fastboot pte we - define the partition number of each partition in - config file - */ - mmc = find_mmc_device(mmcc); - if (!mmc) { - printf("booti: cannot find '%d' mmc device\n", mmcc); - goto fail; - } - dev_desc = get_dev("mmc", mmcc); - if (NULL == dev_desc) { - printf("** Block device MMC %d not supported\n", mmcc); - goto fail; - } - - /* below was i.MX mmc operation code */ - if (mmc_init(mmc)) { - printf("mmc%d init failed\n", mmcc); - goto fail; - } - - pte = fastboot_flash_find_ptn(ptn); - if (!pte) { - printf("booti: cannot find '%s' partition\n", ptn); - goto fail; - } - - if (mmc->block_dev.block_read(mmcc, pte->start, - 1, (void *)hdr) < 0) { - printf("booti: mmc failed to read bootimg header\n"); - goto fail; - } - - if (memcmp(hdr->magic, FASTBOOT_BOOT_MAGIC, 8)) { - printf("booti: bad boot image magic\n"); - goto fail; - } - - image_size = hdr->page_size + - ALIGN_SECTOR(hdr->kernel_size, hdr->page_size) + - ALIGN_SECTOR(hdr->ramdisk_size, hdr->page_size) + - ALIGN_SECTOR(hdr->second_size, hdr->page_size); - bootimg_sectors = image_size/512; - bootimg_addr = hdr->kernel_addr - hdr->page_size; - -#ifdef CONFIG_SECURE_BOOT - /* Default boot.img should be padded to 0x1000 - before appended with IVT&CSF data. Set the threshold of - boot image for athendication as 16MB - */ - image_size += BOOTIMAGE_SIGNATURE_SIZE; - image_size = ALIGN_SECTOR(image_size, 0x1000); - if (image_size > MAX_ANDROID_BOOT_AUTH_SIZE) { - printf("The image size is too large for athenticated boot!\n"); - return 1; - } - /* Make sure all data boot.img + IVT + CSF been read to memory */ - bootimg_sectors = image_size/512 + - ALIGN_SECTOR(IVT_SIZE + CSF_PAD_SIZE, 512)/512; -#endif - - if (mmc->block_dev.block_read(mmcc, pte->start, - bootimg_sectors, - (void *)bootimg_addr) < 0) { - printf("booti: mmc failed to read kernel\n"); - goto fail; - } - /* flush cache after read */ - flush_cache((ulong)bootimg_addr, bootimg_sectors * 512); /* FIXME */ - -#ifdef CONFIG_SECURE_BOOT - extern uint32_t authenticate_image(uint32_t ddr_start, - uint32_t image_size); - - if (authenticate_image(bootimg_addr, image_size)) { - printf("Authenticate OK\n"); - } else { - printf("Authenticate image Fail, Please check\n\n"); - return 1; - } -#endif /*CONFIG_SECURE_BOOT*/ - - sector = pte->start + (hdr->page_size / 512); - sector += ALIGN_SECTOR(hdr->kernel_size, hdr->page_size) / 512; - if (mmc->block_dev.block_read(mmcc, sector, - (hdr->ramdisk_size / 512) + 1, - (void *)hdr->ramdisk_addr) < 0) { - printf("booti: mmc failed to read ramdisk\n"); - goto fail; - } - /* flush cache after read */ - flush_cache((ulong)hdr->ramdisk_addr, hdr->ramdisk_size); /* FIXME */ - -#ifdef CONFIG_OF_LIBFDT - /* load the dtb file */ - if (hdr->second_size && hdr->second_addr) { - sector += ALIGN_SECTOR(hdr->ramdisk_size, hdr->page_size) / 512; - if (mmc->block_dev.block_read(mmcc, sector, - (hdr->second_size / 512) + 1, - (void *)hdr->second_addr) < 0) { - printf("booti: mmc failed to dtb\n"); - goto fail; - } - /* flush cache after read */ - flush_cache((ulong)hdr->second_addr, hdr->second_size); /* FIXME */ - } -#endif /*CONFIG_OF_LIBFDT*/ - -#else /*! CONFIG_MMC*/ - return -1; -#endif /*! CONFIG_MMC*/ - } else { - unsigned kaddr, raddr, end; -#ifdef CONFIG_OF_LIBFDT - unsigned fdtaddr = 0; -#endif - - /* set this aside somewhere safe */ - memcpy(hdr, (void *) addr, sizeof(*hdr)); - - if (memcmp(hdr->magic, FASTBOOT_BOOT_MAGIC, 8)) { - printf("booti: bad boot image magic\n"); - return 1; - } - - bootimg_print_image_hdr(hdr); - - kaddr = addr + hdr->page_size; - raddr = kaddr + ALIGN_SECTOR(hdr->kernel_size, hdr->page_size); - end = raddr + hdr->ramdisk_size; -#ifdef CONFIG_OF_LIBFDT - if (hdr->second_size) { - fdtaddr = raddr + ALIGN_SECTOR(hdr->ramdisk_size, hdr->page_size); - end = fdtaddr + hdr->second_size; - } -#endif /*CONFIG_OF_LIBFDT*/ - -#ifdef CONFIG_SECURE_BOOT - image_size = hdr->page_size + - ALIGN_SECTOR(hdr->kernel_size, hdr->page_size) + - ALIGN_SECTOR(hdr->ramdisk_size, hdr->page_size) + - ALIGN_SECTOR(hdr->second_size, hdr->page_size) + BOOTIMAGE_SIGNATURE_SIZE; - if (image_size > MAX_ANDROID_BOOT_AUTH_SIZE) { - printf("The image size is too large for athenticated boot!\n"); - return 1; - } - bootimg_addr = addr; - extern uint32_t authenticate_image(uint32_t ddr_start, - uint32_t image_size); - - if (authenticate_image(bootimg_addr, image_size)) { - printf("Authenticate OK\n"); - } else { - printf("Authenticate image Fail, Please check\n\n"); - return 1; - } -#endif /*CONFIG_SECURE_BOOT*/ - - if (kaddr != hdr->kernel_addr) { - /*check overlap*/ - if (((hdr->kernel_addr >= addr) && - (hdr->kernel_addr <= end)) || - ((addr >= hdr->kernel_addr) && - (addr <= hdr->kernel_addr + hdr->kernel_size))) { - printf("Fail: booti address overlap with kernel address\n"); - return 1; - } - memmove((void *) hdr->kernel_addr, - (void *)kaddr, hdr->kernel_size); - } - if (raddr != hdr->ramdisk_addr) { - /*check overlap*/ - if (((hdr->ramdisk_addr >= addr) && - (hdr->ramdisk_addr <= end)) || - ((addr >= hdr->ramdisk_addr) && - (addr <= hdr->ramdisk_addr + hdr->ramdisk_size))) { - printf("Fail: booti address overlap with ramdisk address\n"); - return 1; - } - memmove((void *) hdr->ramdisk_addr, - (void *)raddr, hdr->ramdisk_size); - } - -#ifdef CONFIG_OF_LIBFDT - if (hdr->second_size && fdtaddr != hdr->second_addr) { - /*check overlap*/ - if (((hdr->second_addr >= addr) && - (hdr->second_addr <= end)) || - ((addr >= hdr->second_addr) && - (addr <= hdr->second_addr + hdr->second_size))) { - printf("Fail: booti address overlap with FDT address\n"); - return 1; - } - memmove((void *) hdr->second_addr, - (void *)fdtaddr, hdr->second_size); - } -#endif /*CONFIG_OF_LIBFDT*/ - } - - printf("kernel @ %08x (%d)\n", hdr->kernel_addr, hdr->kernel_size); - printf("ramdisk @ %08x (%d)\n", hdr->ramdisk_addr, hdr->ramdisk_size); -#ifdef CONFIG_OF_LIBFDT - if (hdr->second_size) - printf("fdt @ %08x (%d)\n", hdr->second_addr, hdr->second_size); -#endif /*CONFIG_OF_LIBFDT*/ - -#ifdef CONFIG_CMDLINE_TAG -#ifndef CONFIG_SECURE_BOOT - /* not allow to change bootargs in cmd line */ - char *commandline = getenv("bootargs"); -#else - char *commandline = NULL; -#endif - - /* If no bootargs env, just use hdr command line */ - if (!commandline) { - commandline = (char *)hdr->cmdline; -#ifdef CONFIG_SERIAL_TAG - char appended_cmd_line[FASTBOOT_BOOT_ARGS_SIZE]; - struct tag_serialnr serialnr; - get_board_serial(&serialnr); - if (strlen((char *)hdr->cmdline) + - strlen("androidboot.serialno") + 17 < FASTBOOT_BOOT_ARGS_SIZE) { - sprintf(appended_cmd_line, - "%s androidboot.serialno=%08x%08x", - (char *)hdr->cmdline, - serialnr.high, - serialnr.low); - commandline = appended_cmd_line; - } else { - printf("Cannot append androidboot.serialno\n"); - } - - setenv("bootargs", commandline); -#endif + usb_gadget_handle_interrupts(); } - /* XXX: in production, you should always use boot.img 's cmdline !!! */ - printf("kernel cmdline:\n"); - printf("\tuse boot.img "); - printf("command line:\n\t%s\n", commandline); -#endif /*CONFIG_CMDLINE_TAG*/ - - memset(&images, 0, sizeof(images)); - - /*Setup lmb for memory reserve*/ - boot_start_lmb(&images); - - images.ep = hdr->kernel_addr; - images.rd_start = hdr->ramdisk_addr; - images.rd_end = hdr->ramdisk_addr + hdr->ramdisk_size; - - /*Reserve memory for kernel image*/ - lmb_reserve(&images.lmb, images.ep, hdr->kernel_size); - -#ifdef CONFIG_OF_LIBFDT - /*use secondary fields for fdt, second_size= fdt size, second_addr= fdt addr*/ - images.ft_addr = (char *)(hdr->second_addr); - images.ft_len = (ulong)(hdr->second_size); - set_working_fdt_addr((ulong)(images.ft_addr)); -#endif /*CONFIG_OF_LIBFDT*/ - - arch_preboot_os(); - - do_bootm_linux(0, 0, NULL, &images); - - puts("booti: Control returned to monitor - resetting...\n"); - do_reset(cmdtp, flag, argc, argv); - return 1; - -fail: -#ifdef CONFIG_FASTBOOT - return do_fastboot(NULL, 0, 0, NULL); -#else /*! CONFIG_FASTBOOT*/ - return -1; -#endif /*! CONFIG_FASTBOOT*/ + g_dnl_unregister(); + g_dnl_clear_detach(); + return CMD_RET_SUCCESS; } U_BOOT_CMD( - booti, 3, 1, do_booti, - "booti - boot android bootimg from memory\n", - "[<addr> | mmc0 | mmc1 | mmc2 | mmcX] [<partition>]\n " - "- boot application image stored in memory or mmc\n" - "\t'addr' should be the address of boot image " - "which is zImage+ramdisk.img\n" - "\t'mmcX' is the mmc device you store your boot.img, " - "which will read the boot.img from 1M offset('/boot' partition)\n" - "\t 'partition' (optional) is the partition id of your device, " - "if no partition give, will going to 'boot' partition\n" + fastboot, 1, 0, do_fastboot, + "use USB Fastboot protocol", + "\n" + " - run as a fastboot usb device" ); -#endif /* CONFIG_CMD_BOOTI */ - -#endif /* CONFIG_FASTBOOT */ diff --git a/common/image-android.c b/common/image-android.c index 59079fc..eb1582b 100644 --- a/common/image-android.c +++ b/common/image-android.c @@ -120,3 +120,22 @@ int android_image_get_ramdisk(const struct andr_img_hdr *hdr, *rd_len = hdr->ramdisk_size; return 0; } + +int android_image_get_fdt(const struct andr_img_hdr *hdr, + ulong *fdt_data, ulong *fdt_len) +{ + if (!hdr->second_size) + return -1; + + printf("FDT load addr 0x%08x size %u KiB\n", + hdr->second_addr, DIV_ROUND_UP(hdr->second_size, 1024)); + + *fdt_data = (unsigned long)hdr; + *fdt_data += hdr->page_size; + *fdt_data += ALIGN(hdr->kernel_size, hdr->page_size); + *fdt_data += ALIGN(hdr->ramdisk_size, hdr->page_size); + + *fdt_len = hdr->second_size; + return 0; +} + diff --git a/common/image-fdt.c b/common/image-fdt.c index d9e4728..a52f7a8 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -416,7 +416,34 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, debug("## No Flattened Device Tree\n"); goto no_fdt; } - } else { + } +#ifdef CONFIG_ANDROID_BOOT_IMAGE + else if (genimg_get_format((void *)images->os.start) == + IMAGE_FORMAT_ANDROID) { + ulong fdt_data, fdt_len; + android_image_get_fdt((void *)images->os.start, + &fdt_data, &fdt_len); + + if (fdt_len) { + fdt_blob = (char *)fdt_data; + printf(" Booting using the fdt at 0x%p\n", fdt_blob); + + if (fdt_check_header(fdt_blob) != 0) { + fdt_error("image is not a fdt"); + goto error; + } + + if (fdt_totalsize(fdt_blob) != fdt_len) { + fdt_error("fdt size != image size"); + goto error; + } + } else { + debug("## No Flattened Device Tree\n"); + goto no_fdt; + } + } +#endif + else { debug("## No Flattened Device Tree\n"); goto no_fdt; } |