summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/f_fastboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_fastboot.c')
-rw-r--r--drivers/usb/gadget/f_fastboot.c308
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