diff options
Diffstat (limited to 'drivers/usb/gadget/f_fastboot.c')
-rw-r--r-- | drivers/usb/gadget/f_fastboot.c | 308 |
1 files changed, 276 insertions, 32 deletions
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 912fa50..2f19e50 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -100,6 +100,10 @@ static inline struct f_fastboot *func_to_fastboot(struct usb_function *f) static struct f_fastboot *fastboot_func; static unsigned int download_size; static unsigned int download_bytes; +#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT +static bool is_recovery_mode; +#endif + static int strcmp_l1(const char *s1, const char *s2); static struct usb_endpoint_descriptor fs_ep_in = { @@ -1051,6 +1055,12 @@ static void process_flash_mmc(const char *cmdbuf) printf("Writing '%s' DONE!\n", ptn->name); fastboot_okay(""); } + if (strncmp(ptn->name, "gpt", 3) == 0) { + /* will force scan the device, + so dev_desc can be re-inited + with the latest data */ + run_command(mmc_dev, 0); + } } } } else { @@ -1060,14 +1070,87 @@ static void process_flash_mmc(const char *cmdbuf) #endif +#if defined(CONFIG_FASTBOOT_STORAGE_MMC) +static void process_erase_mmc(const char *cmdbuf, char *response) +{ + int mmc_no = 0; + lbaint_t blks, blks_start, blks_size, grp_size; + struct mmc *mmc; + struct blk_desc *dev_desc; + struct fastboot_ptentry *ptn; + disk_partition_t info; + + ptn = fastboot_flash_find_ptn(cmdbuf); + if ((ptn == NULL) || (ptn->flags & FASTBOOT_PTENTRY_FLAGS_UNERASEABLE)) { + sprintf(response, "FAILpartition does not exist or uneraseable"); + return; + } + + mmc_no = fastboot_devinfo.dev_id; + printf("erase target is MMC:%d\n", mmc_no); + + mmc = find_mmc_device(mmc_no); + if ((mmc == NULL) || mmc_init(mmc)) { + printf("MMC card init failed!\n"); + return; + } + + dev_desc = blk_get_dev("mmc", mmc_no); + if (NULL == dev_desc) { + printf("Block device MMC %d not supported\n", + mmc_no); + sprintf(response, "FAILnot valid MMC card"); + return; + } + + if (part_get_info(dev_desc, + ptn->partition_index, &info)) { + printf("Bad partition index:%d for partition:%s\n", + ptn->partition_index, ptn->name); + sprintf(response, "FAILerasing of MMC card"); + return; + } + + /* Align blocks to erase group size to avoid erasing other partitions */ + grp_size = mmc->erase_grp_size; + blks_start = (info.start + grp_size - 1) & ~(grp_size - 1); + if (info.size >= grp_size) + blks_size = (info.size - (blks_start - info.start)) & + (~(grp_size - 1)); + else + blks_size = 0; + + printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n", + blks_start, blks_start + blks_size); + + blks = dev_desc->block_erase(dev_desc, blks_start, blks_size); + if (blks != blks_size) { + printf("failed erasing from device %d", dev_desc->devnum); + sprintf(response, "FAILerasing of MMC card"); + return; + } + + printf("........ erased " LBAFU " bytes from '%s'\n", + blks_size * info.blksz, cmdbuf); + sprintf(response, "OKAY"); + + return; +} +#endif -static int rx_process_erase(const char *cmdbuf) +#if defined(CONFIG_FASTBOOT_STORAGE_SATA) +static void process_erase_sata(const char *cmdbuf, char *response) { + return; +} +#endif #if defined(CONFIG_FASTBOOT_STORAGE_NAND) +static int process_erase_nand(const char *cmdbuf, char *response) +{ struct fastboot_ptentry *ptn; ptn = fastboot_flash_find_ptn(cmdbuf); - if (ptn == 0) { + if (ptn == NULL || (ptn->flags & FASTBOOT_PTENTRY_FLAGS_UNERASEABLE)) { fastboot_fail("partition does not exist"); } else { int status, repeat, repeat_max; @@ -1117,12 +1200,35 @@ static int rx_process_erase(const char *cmdbuf) fastboot_okay(""); } } - return 0; -#else - printf("Not support erase command for EMMC\n"); - return -1; + return; +} #endif +static void rx_process_erase(const char *cmdbuf, char *response) +{ + switch (fastboot_devinfo.type) { +#if defined(CONFIG_FASTBOOT_STORAGE_SATA) + case DEV_SATA: + process_erase_sata(cmdbuf, response); + break; +#endif +#if defined(CONFIG_FASTBOOT_STORAGE_MMC) + case DEV_MMC: + process_erase_mmc(cmdbuf, response); + break; +#endif +#if defined(CONFIG_FASTBOOT_STORAGE_NAND) + case DEV_NAND: + process_erase_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_flash(const char *cmdbuf) @@ -1206,6 +1312,7 @@ static int _fastboot_parts_add_ptable_entry(int ptable_index, int mmc_dos_partition_index, int mmc_partition_index, const char *name, + const char *fstype, struct blk_desc *dev_desc, struct fastboot_ptentry *ptable) { @@ -1221,11 +1328,8 @@ static int _fastboot_parts_add_ptable_entry(int ptable_index, ptable[ptable_index].length = info.size; ptable[ptable_index].partition_id = mmc_partition_index; ptable[ptable_index].partition_index = mmc_dos_partition_index; -#ifdef CONFIG_EFI_PARTITION strcpy(ptable[ptable_index].name, (const char *)info.name); -#else - strcpy(ptable[ptable_index].name, name); -#endif + strcpy(ptable[ptable_index].fstype, (const char *)info.type); #ifdef CONFIG_PARTITION_UUIDS strcpy(ptable[ptable_index].uuid, (const char *)info.uuid); @@ -1300,6 +1404,7 @@ static int _fastboot_parts_load_from_ptable(void) ptable[PTN_GPT_INDEX].start = ANDROID_GPT_OFFSET / dev_desc->blksz; ptable[PTN_GPT_INDEX].length = ANDROID_GPT_SIZE / dev_desc->blksz; ptable[PTN_GPT_INDEX].partition_id = user_partition; + ptable[PTN_GPT_INDEX].flags = FASTBOOT_PTENTRY_FLAGS_UNERASEABLE; /* Bootloader */ strcpy(ptable[PTN_BOOTLOADER_INDEX].name, FASTBOOT_PARTITION_BOOTLOADER); ptable[PTN_BOOTLOADER_INDEX].start = @@ -1307,6 +1412,7 @@ static int _fastboot_parts_load_from_ptable(void) ptable[PTN_BOOTLOADER_INDEX].length = ANDROID_BOOTLOADER_SIZE / dev_desc->blksz; ptable[PTN_BOOTLOADER_INDEX].partition_id = boot_partition; + ptable[PTN_BOOTLOADER_INDEX].flags = FASTBOOT_PTENTRY_FLAGS_UNERASEABLE; int tbl_idx; int part_idx = 1; @@ -1316,6 +1422,7 @@ static int _fastboot_parts_load_from_ptable(void) part_idx++, user_partition, NULL, + NULL, dev_desc, ptable); if (ret) break; @@ -1674,7 +1781,7 @@ void fastboot_setup(void) char serial[17]; get_board_serial(&serialnr); - sprintf(serial, "%u%u", serialnr.high, serialnr.low); + sprintf(serial, "%08x%08x", serialnr.high, serialnr.low); g_dnl_set_serialnumber(serial); /*execute board relevant initilizations for preparing fastboot */ @@ -1733,6 +1840,33 @@ static FbBootMode fastboot_get_bootmode(void) return boot_mode; } +#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT +/* Setup booargs for taking the system parition as ramdisk */ +static void fastboot_setup_system_boot_args(const char *slot) +{ + const char *system_part_name = NULL; + if(slot == NULL) + return; + if(!strncmp(slot, "_a", strlen("_a")) || !strncmp(slot, "boot_a", strlen("boot_a"))) { + system_part_name = FASTBOOT_PARTITION_SYSTEM_A; + } + else if(!strncmp(slot, "_b", strlen("_b")) || !strncmp(slot, "boot_b", strlen("boot_b"))) { + system_part_name = FASTBOOT_PARTITION_SYSTEM_B; + } + struct fastboot_ptentry *ptentry = fastboot_flash_find_ptn(system_part_name); + if(ptentry != NULL) { + char bootargs_3rd[ANDR_BOOT_ARGS_SIZE]; +#if defined(CONFIG_FASTBOOT_STORAGE_MMC) + u32 dev_no = mmc_map_to_kernel_blk(mmc_get_env_dev()); + sprintf(bootargs_3rd, "skip_initramfs root=/dev/mmcblk%dp%d", + dev_no, + ptentry->partition_index); + setenv("bootargs_3rd", bootargs_3rd); +#endif + //TBD to support NAND ubifs system parition boot directly + } +} +#endif /* export to lib_arm/board.c */ void fastboot_run_bootmode(void) { @@ -2012,6 +2146,11 @@ slot_select: printf("no valid slot found, enter to recovery\n"); ptn = "recovery"; } +#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT + else { + fastboot_setup_system_boot_args(ptn); + } +#endif use_given_ptn: printf("use slot %s\n", ptn); } @@ -2587,6 +2726,40 @@ bool is_slotvar(char *cmd) return false; } +static char *get_serial(void) +{ +#ifdef CONFIG_SERIAL_TAG + struct tag_serialnr serialnr; + static char serial[32]; + get_board_serial(&serialnr); + sprintf(serial, "%08x%08x", serialnr.high, serialnr.low); + return serial; +#else + return NULL; +#endif +} + +#if !defined(PRODUCT_NAME) +#define PRODUCT_NAME "NXP i.MX" +#endif + +#if !defined(VARIANT_NAME) +#define VARIANT_NAME "NXP i.MX" +#endif + +static int get_block_size(void) { + int mmc_no = 0; + struct blk_desc *dev_desc; + mmc_no = fastboot_devinfo.dev_id; + dev_desc = blk_get_dev("mmc", mmc_no); + if (NULL == dev_desc) { + printf("** Block device MMC %d not supported\n", + mmc_no); + return 0; + } + return dev_desc->blksz; +} + static void cb_getvar(struct usb_ep *ep, struct usb_request *req) { char *cmd = req->buf; @@ -2616,10 +2789,47 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req) strncat(response, FASTBOOT_VAR_NO, chars_left); #endif } - if (!strcmp_l1("version", cmd)) { - strncat(response, FASTBOOT_VERSION, chars_left); - } else if (!strcmp_l1("bootloader-version", cmd)) { + + char *str = cmd; + if ((str = strstr(cmd, "partition-size:"))) { + str +=strlen("partition-size:"); + struct fastboot_ptentry* fb_part; + fb_part = fastboot_flash_find_ptn(str); + if (!fb_part) { + strncat(response, "Wrong partition name.", chars_left); + goto fail; + } else { + char str_num[20]; + sprintf(str_num, "0x%016x", fb_part->length * get_block_size()); + strncat(response, str_num, chars_left); + } + } else if ((str = strstr(cmd, "partition-type:"))) { + str +=strlen("partition-type:"); + struct fastboot_ptentry* fb_part; + fb_part = fastboot_flash_find_ptn(str); + if (!fb_part) { + strncat(response, "Wrong partition name.", chars_left); + goto fail; + } else { + strncat(response, fb_part->fstype, chars_left); + } + } else if (!strcmp_l1("all", cmd)) { + /* FIXME need to return all vars here */ + } else if (!strcmp_l1("version-baseband", cmd)) { + strncat(response, "N/A", chars_left); + } else if (!strcmp_l1("version-bootloader", cmd) || + !strcmp_l1("bootloader-version", cmd)) { strncat(response, U_BOOT_VERSION, chars_left); + } else if (!strcmp_l1("version", cmd)) { + strncat(response, FASTBOOT_VERSION, chars_left); + } else if (!strcmp_l1("battery-voltage", cmd)) { + strncat(response, "0mV", chars_left); + } else if (!strcmp_l1("battery-soc-ok", cmd)) { + strncat(response, "yes", chars_left); + } else if (!strcmp_l1("variant", cmd)) { + strncat(response, VARIANT_NAME, chars_left); + } else if (!strcmp_l1("off-mode-charge", cmd)) { + strncat(response, "1", chars_left); } else if (!strcmp_l1("downloadsize", cmd) || !strcmp_l1("max-download-size", cmd)) { char str_num[12]; @@ -2627,13 +2837,15 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req) sprintf(str_num, "0x%08x", CONFIG_FASTBOOT_BUF_SIZE); strncat(response, str_num, chars_left); } else if (!strcmp_l1("serialno", cmd)) { - s = getenv("serial#"); + s = get_serial(); if (s) strncat(response, s, chars_left); - else - strcpy(response, "FAILValue not set"); + else { + strncat(response, "FAILValue not set", chars_left); + goto fail; + } } else if (!strcmp_l1("product", cmd)) { - strncat(response, "Freescale i.MX", chars_left); + strncat(response, PRODUCT_NAME, chars_left); } #ifdef CONFIG_FASTBOOT_LOCK else if (!strcmp_l1("secure", cmd)) { @@ -2948,6 +3160,17 @@ static void cb_flashing(struct usb_ep *ep, struct usb_request *req) #endif +static int partition_table_valid(void) +{ + int status, mmc_no; + struct blk_desc *dev_desc; + disk_partition_t info; + mmc_no = fastboot_devinfo.dev_id; + dev_desc = blk_get_dev("mmc", mmc_no); + status = part_get_info(dev_desc, 1, &info); + return (status == 0); +} + #ifdef CONFIG_FASTBOOT_FLASH static void cb_flash(struct usb_ep *ep, struct usb_request *req) { @@ -2985,11 +3208,26 @@ static void cb_flash(struct usb_ep *ep, struct usb_request *req) fastboot_fail("no flash device defined"); #ifdef CONFIG_FSL_FASTBOOT +#ifdef CONFIG_FASTBOOT_LOCK + int gpt_valid_pre = 0; + int gpt_valid_pst = 0; + if (strncmp(cmd, "gpt", 3) == 0) + gpt_valid_pre = partition_table_valid(); +#endif rx_process_flash(cmd); -#else -#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV - fb_mmc_flash_write(cmd, (void *)CONFIG_FASTBOOT_BUF_ADDR, - download_bytes); +#ifdef CONFIG_FASTBOOT_LOCK + if (strncmp(cmd, "gpt", 3) == 0) { + gpt_valid_pst = partition_table_valid(); + /* If gpt is valid, load partitons table into memory. + So if the next command is "fastboot reboot bootloader", + it can find the "misc" partition to r/w. */ + if(gpt_valid_pst) + _fastboot_load_partitions(); + /* If gpt invalid -> valid, write unlock status, also wipe data. */ + if ((gpt_valid_pre == 0) && (gpt_valid_pst == 1)) + do_fastboot_unlock(true); + } + #endif #ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV fb_nand_flash_write(cmd, @@ -3017,17 +3255,23 @@ static void cb_erase(struct usb_ep *ep, struct usb_request *req) /* initialize the response buffer */ fb_response_str = response; - fastboot_fail("no flash device defined"); -#ifdef CONFIG_FSL_FASTBOOT - rx_process_erase(cmd); -#else -#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV - fb_mmc_erase(cmd); -#endif -#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV - fb_nand_erase(cmd); -#endif +#ifdef CONFIG_FASTBOOT_LOCK + FbLockState status; + status = fastboot_get_lock_stat(); + if (status == FASTBOOT_LOCK) { + error("device is LOCKed!\n"); + strcpy(response, "FAIL device is locked."); + fastboot_tx_write_str(response); + return; + } else if (status == FASTBOOT_LOCK_ERROR) { + error("write lock status into device!\n"); + fastboot_set_lock_stat(FASTBOOT_LOCK); + strcpy(response, "FAIL device is locked."); + fastboot_tx_write_str(response); + return; + } #endif + rx_process_erase(cmd, response); fastboot_tx_write_str(response); } #endif |