From mboxrd@z Thu Jan 1 00:00:00 1970 From: Steve Rae Date: Mon, 11 Aug 2014 12:52:11 -0700 Subject: [U-Boot] [PATCH 2/2 v2] fastboot: Flash command support In-Reply-To: <1407722379-29184-2-git-send-email-dileep.katta@linaro.org> References: <1407722379-29184-1-git-send-email-dileep.katta@linaro.org> <1407722379-29184-2-git-send-email-dileep.katta@linaro.org> Message-ID: <53E91EEB.7010506@broadcom.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 14-08-10 06:59 PM, Dileep Katta wrote: > Flash command internally uses DFU, and Fastboot command initialization is modified to add DFU and partition initialization > Added oem format functionality for GPT table creation > partitioning code is added as disk/part_fastboot.c for better usability > > Fastboot flash command code is enabled and being tested on BeagleBone Black. > OMAP3 Beagle configuration is modified to fix the build errors, but this configuration needs to be updated as per the flash functionality. > > Signed-off-by: Dileep Katta > --- > Changes for v2: > - Fixed coding style issues > > common/cmd_fastboot.c | 5 + > common/cmd_mmc.c | 2 +- > common/cmd_nvedit.c | 2 +- > disk/Makefile | 1 + > disk/part_fastboot.c | 379 ++++++++++++++++++++++++++++++++++++++++ > doc/README.android-fastboot | 26 +++ > drivers/usb/gadget/f_fastboot.c | 178 ++++++++++++++++++- > include/configs/am335x_evm.h | 23 ++- > include/configs/omap3_beagle.h | 12 ++ > include/usb/fastboot.h | 182 +++++++++++++++++++ > 10 files changed, 796 insertions(+), 14 deletions(-) > create mode 100644 disk/part_fastboot.c > create mode 100644 include/usb/fastboot.h > > diff --git a/common/cmd_fastboot.c b/common/cmd_fastboot.c > index 83fa7bd..6d0d0a4 100644 > --- a/common/cmd_fastboot.c > +++ b/common/cmd_fastboot.c > @@ -10,11 +10,15 @@ > #include > #include > #include > +#include > +#include > > static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) > { > int ret; > > + board_partition_init(); > + dfu_init_env_entities("mmc", CONFIG_FB_MMCDEV); > ret = g_dnl_register("usb_dnl_fastboot"); > if (ret) > return ret; > @@ -26,6 +30,7 @@ static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) > } > > g_dnl_unregister(); > + dfu_free_entities(); > return CMD_RET_SUCCESS; > } > > diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c > index 1e40983..dd7170d 100644 > --- a/common/cmd_mmc.c > +++ b/common/cmd_mmc.c > @@ -612,7 +612,7 @@ static cmd_tbl_t cmd_mmc[] = { > U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""), > }; > > -static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > +int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > { > cmd_tbl_t *cp; > > diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c > index 855808c..a100109 100644 > --- a/common/cmd_nvedit.c > +++ b/common/cmd_nvedit.c > @@ -686,7 +686,7 @@ ulong getenv_ulong(const char *name, int base, ulong default_val) > > #ifndef CONFIG_SPL_BUILD > #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) > -static int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, > +int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, > char * const argv[]) > { > printf("Saving Environment to %s...\n", env_name_spec); > diff --git a/disk/Makefile b/disk/Makefile > index 6970cec..4b7a9ef 100644 > --- a/disk/Makefile > +++ b/disk/Makefile > @@ -13,3 +13,4 @@ obj-$(CONFIG_DOS_PARTITION) += part_dos.o > obj-$(CONFIG_ISO_PARTITION) += part_iso.o > obj-$(CONFIG_AMIGA_PARTITION) += part_amiga.o > obj-$(CONFIG_EFI_PARTITION) += part_efi.o > +obj-$(CONFIG_CMD_FASTBOOT) += part_fastboot.o > diff --git a/disk/part_fastboot.c b/disk/part_fastboot.c > new file mode 100644 > index 0000000..4fa9f85 > --- /dev/null > +++ b/disk/part_fastboot.c > @@ -0,0 +1,379 @@ > +/* > + * Copyright (C) 2013 Texas Instruments > + * > + * Author : Pankaj Bharadiya > + * > + * Tom Rix and Sitara 2011 u-boot by > + * Mohammed Afzal M A > + * > + * Copyright (C) 2008 The Android Open Source Project > + * All rights reserved. > + * > + * Copyright 2014 Linaro, Ltd. > + * Dileep Katta > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define EFI_VERSION 0x00010000 > +#define EFI_ENTRIES 128 > +#define EFI_NAMELEN 36 > + > +struct partition_emmc { > + const char *name; > + unsigned size_kb; > +}; > + > +/* eMMC partition layout (All sizes are in kB) > + * Modify the below partition table to change the GPT configuration. > + * The entry for each partition can be modified as per the requirement. > + */ > +static struct partition_emmc partitions[] = { > + { "-", 128 }, /* Master Boot Record and GUID Partition Table */ > + { "spl", 128 }, /* First stage bootloader */ > + { "bootloader", 512 }, /* Second stage bootloader */ > + { "misc", 128 }, /* Rserved for internal purpose */ > + { "-", 128 }, /* Reserved */ > + { "recovery", 8*1024 }, /* Recovery partition */ > + { "boot", 8*1024 }, /* Partition contains kernel + ramdisk images */ > + { "system", 256*1024 }, /* Android file system */ > + { "cache", 256*1024 }, /* Store Application Cache */ > + { "userdata", 256*1024 }, /* User data */ > + { "media", 0 }, /* Media files */ > + { 0, 0 }, This hard-coded partition does not work for our boards -- what is your plan for supporting partition tables? [ have you considered allowing the host to format, download and flash the partition table? (that is what we are doing...) ] > +}; > + > + > +static const u8 partition_type[16] = { > + 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44, > + 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7, > +}; > + > +static const u8 random_uuid[16] = { > + 0xff, 0x1f, 0xf2, 0xf9, 0xd4, 0xa8, 0x0e, 0x5f, > + 0x97, 0x46, 0x59, 0x48, 0x69, 0xae, 0xc3, 0x4e, > +}; > + > +struct efi_entry { > + u8 type_uuid[16]; > + u8 uniq_uuid[16]; > + u64 first_lba; > + u64 last_lba; > + u64 attr; > + u16 name[EFI_NAMELEN]; > +}; > + > +struct efi_header { > + u8 magic[8]; > + > + u32 version; > + u32 header_sz; > + > + u32 crc32; > + u32 reserved; > + > + u64 header_lba; > + u64 backup_lba; > + u64 first_lba; > + u64 last_lba; > + > + u8 volume_uuid[16]; > + > + u64 entries_lba; > + > + u32 entries_count; > + u32 entries_size; > + u32 entries_crc32; > +} __packed; > + > +struct ptable { > + u8 mbr[512]; > + union { > + struct efi_header header; > + u8 block[512]; > + }; > + struct efi_entry entry[EFI_ENTRIES]; > +}; > + > +static void init_mbr(u8 *mbr, u32 blocks) > +{ > + mbr[0x1be] = 0x00; /* nonbootable */ > + mbr[0x1bf] = 0xFF; /* bogus CHS */ > + mbr[0x1c0] = 0xFF; > + mbr[0x1c1] = 0xFF; > + > + mbr[0x1c2] = 0xEE; /* GPT partition */ > + mbr[0x1c3] = 0xFF; /* bogus CHS */ > + mbr[0x1c4] = 0xFF; > + mbr[0x1c5] = 0xFF; > + > + mbr[0x1c6] = 0x01; /* start */ > + mbr[0x1c7] = 0x00; > + mbr[0x1c8] = 0x00; > + mbr[0x1c9] = 0x00; > + > + memcpy(mbr + 0x1ca, &blocks, sizeof(u32)); > + > + mbr[0x1fe] = 0x55; > + mbr[0x1ff] = 0xaa; > +} > + > + > +static void start_ptbl(struct ptable *ptbl, unsigned blocks) > +{ > + struct efi_header *hdr = &ptbl->header; > + > + memset(ptbl, 0, sizeof(*ptbl)); > + > + init_mbr(ptbl->mbr, blocks - 1); > + > + memcpy(hdr->magic, "EFI PART", 8); > + hdr->version = EFI_VERSION; > + hdr->header_sz = sizeof(struct efi_header); > + hdr->header_lba = 1; > + hdr->backup_lba = blocks - 1; > + hdr->first_lba = 34; > + hdr->last_lba = blocks - 1; > + memcpy(hdr->volume_uuid, random_uuid, 16); > + hdr->entries_lba = 2; > + hdr->entries_count = EFI_ENTRIES; > + hdr->entries_size = sizeof(struct efi_entry); > +} > + > +static void end_ptbl(struct ptable *ptbl) > +{ > + struct efi_header *hdr = &ptbl->header; > + u32 n; > + > + n = crc32(0, 0, 0); > + n = crc32(n, (void *)ptbl->entry, sizeof(ptbl->entry)); > + hdr->entries_crc32 = n; > + > + n = crc32(0, 0, 0); > + n = crc32(0, (void *)&ptbl->header, sizeof(ptbl->header)); > + hdr->crc32 = n; > +} > + > +int add_ptn(struct ptable *ptbl, u64 first, u64 last, const char *name) > +{ > + struct efi_header *hdr = &ptbl->header; > + struct efi_entry *entry = ptbl->entry; > + unsigned n; > + > + if (first < 34) { > + printf("partition '%s' overlaps partition table\n", name); > + return -1; > + } > + > + if (last > hdr->last_lba) { > + printf("partition '%s' does not fit\n", name); > + return -1; > + } > + for (n = 0; n < EFI_ENTRIES; n++, entry++) { > + if (entry->last_lba) > + continue; > + memcpy(entry->type_uuid, partition_type, 16); > + memcpy(entry->uniq_uuid, random_uuid, 16); > + entry->uniq_uuid[0] = n; > + entry->first_lba = first; > + entry->last_lba = last; > + for (n = 0; (n < EFI_NAMELEN) && *name; n++) > + entry->name[n] = *name++; > + return 0; > + } > + printf("out of partition table entries\n"); > + return -1; > +} > + > +void import_efi_partition(struct efi_entry *entry) > +{ > + struct fastboot_ptentry e; > + int n; > + if (memcmp(entry->type_uuid, partition_type, sizeof(partition_type))) > + return; > + for (n = 0; n < (sizeof(e.name)-1); n++) > + e.name[n] = entry->name[n]; > + e.name[n] = 0; > + e.start = entry->first_lba; > + e.length = (entry->last_lba - entry->first_lba + 1) * 512; > + e.flags = 0; > + > + if (!strcmp(e.name, "environment")) > + e.flags |= FASTBOOT_PTENTRY_FLAGS_WRITE_ENV; > + fastboot_flash_add_ptn(&e); > + > + if (e.length > 0x100000) > + printf("%8d %7dM %s\n", e.start, e.length/0x100000, e.name); > + else > + printf("%8d %7dK %s\n", e.start, e.length/0x400, e.name); > +} > + > +static int load_ptbl(void) > +{ > + static unsigned char data[512]; > + static struct efi_entry entry[4]; > + int n, m; > + char source[32], dest[32], length[32]; > + > + char *mmc_read[5] = {"mmc", "read", NULL, NULL, NULL}; > + > + /* read mbr */ > + mmc_read[2] = source; > + mmc_read[3] = dest; > + mmc_read[4] = length; > + > + sprintf(source, "%p", data); > + sprintf(dest, "0x%x", 0x1); > + sprintf(length, "0x%x", 1); > + > + if (do_mmcops(NULL, 0, 5, mmc_read)) { > + printf("Reading boot magic FAILED!\n"); > + return -1; > + } REALLY -- building a string and passing to the command interpreter !?!?! > + > + if (memcmp(data, "EFI PART", 8)) { > + printf("efi partition table not found\n"); > + return -1; > + } > + for (n = 0; n < (128/4); n++) { > + /* read partition */ > + source[0] = '\0'; > + dest[0] = '\0'; > + length[0] = '\0'; > + mmc_read[2] = source; > + mmc_read[3] = dest; > + mmc_read[4] = length; > + > + sprintf(source, "%p", entry); > + sprintf(dest, "0x%x", 0x1+n); > + sprintf(length, "0x%x", 1); > + > + if (do_mmcops(NULL, 0, 5, mmc_read)) { > + printf("Reading boot magic FAILED!\n"); > + return -1; > + } > + for (m = 0; m < 4; m++) > + import_efi_partition(entry + m); > + } > + return 0; > +} > + > +int board_mmc_fbtptn_init(void) > +{ > + char *mmc_init[2] = {"mmc", "rescan",}; > + char dev[2]; > + char *mmc_dev[3] = {"mmc", "dev", NULL}; > + > + mmc_dev[2] = dev; > + sprintf(dev, "0x%x", CONFIG_FB_MMCDEV); > + > + if (do_mmcops(NULL, 0, 3, mmc_dev)) { > + printf("MMC DEV: %d selection FAILED!\n", CONFIG_FB_MMCDEV); > + return -1; > + } > + > + if (do_mmcops(NULL, 0, 2, mmc_init)) { > + printf("FAIL:Init of MMC card\n"); > + return 1; > + } > + > + printf("Loading efi partition table:\n"); > + return load_ptbl(); > +} > + > + > +static struct ptable the_ptable; > + > +int do_format(void) > +{ > + struct ptable *ptbl = &the_ptable; > + /* unsigned sector_sz; */ > + unsigned blocks; > + unsigned next; > + int n; > + > + printf("\ndo_format ..!!"); > + /* get mmc info */ > + struct mmc *mmc = find_mmc_device(CONFIG_FB_MMCDEV); > + if (mmc == 0) { > + printf("no mmc device at slot %d", CONFIG_FB_MMCDEV); > + return -1; > + } > + > + mmc->has_init = 0; > + if (mmc_init(mmc)) { > + printf("\n mmc init FAILED"); > + return -1; > + } else{ > + printf("\nmmc capacity is: %llu", mmc->capacity); > + printf("\nmmc: number of blocks:0x%lx", mmc->block_dev.lba); > + printf("\nmmc: block size:0x%lx", mmc->block_dev.blksz); > + } > + > + blocks = mmc->block_dev.lba; > + /* sector_sz = mmc->block_dev.blksz; */ > + > + start_ptbl(ptbl, blocks); > + n = 0; > + next = 0; > + for (n = 0, next = 0; partitions[n].name; n++) { > + /* 10/11 : below line change size from KB to no of blocks */ > + unsigned sz = partitions[n].size_kb*2; > + if (!strcmp(partitions[n].name, "-")) { > + next += sz; > + continue; > + } > + if (sz == 0) > + sz = blocks - next; > + if (add_ptn(ptbl, next, next + sz - 1, partitions[n].name)) > + return -1; > + next += sz; > + } > + end_ptbl(ptbl); > + > + fastboot_flash_reset_ptn(); > + > + /* 10/11:modified as per PSP release support */ > + char *mmc_write[5] = {"mmc", "write", NULL, NULL, NULL}; > + char source[32], dest[32], length[32]; > + > + char dev[2]; > + char *mmc_dev[3] = {"mmc", "dev", NULL}; > + > + mmc_dev[2] = dev; > + sprintf(dev, "0x%x", CONFIG_FB_MMCDEV); > + > + if (do_mmcops(NULL, 0, 3, mmc_dev)) { > + printf("MMC DEV: %d selection FAILED!\n", CONFIG_FB_MMCDEV); > + return -1; > + } > + > + mmc_write[2] = source; > + mmc_write[3] = dest; > + mmc_write[4] = length; > + > + sprintf(source, "%p", (void *)ptbl); > + sprintf(dest, "0x%x", 0x00); > + sprintf(length, "0x%x", (sizeof(struct ptable)/512)+1); > + > + if (do_mmcops(NULL, 0, 5, mmc_write)) { > + printf("Writing mbr is FAILED!\n"); > + return -1; > + } else { > + printf("Writing mbr is DONE!\n"); > + } > + > + printf("\nnew partition table:\n"); > + load_ptbl(); > + > + return 0; > +} > diff --git a/doc/README.android-fastboot b/doc/README.android-fastboot > index f1d128c..5420e5e 100644 > --- a/doc/README.android-fastboot > +++ b/doc/README.android-fastboot > @@ -46,6 +46,14 @@ buffer should be as large as possible for a platform. The location of the > buffer and size are set with CONFIG_USB_FASTBOOT_BUF_ADDR and > CONFIG_USB_FASTBOOT_BUF_SIZE. > > +Fastboot flash command uses DFU and storage(NAND/MMC) specific > +functionality, and hence related definitions needs to be defined: > + > +DFU_ALT_INFO > +CONFIG_STORAGE_EMMC > +CONFIG_FB_MMCDEV > + > + > In Action > ========= > Enter into fastboot by executing the fastboot command in u-boot and you > @@ -89,3 +97,21 @@ and on the gadget side you should see: > |OK > | > |Starting kernel ... > + > +Flash command in action, on the client side: > + > +|>fastboot flash bootloader u-boot.img > +|target reported max download size of 1835008 bytes > +|sending 'bootloader' (395 KB)... > +|OKAY [ 0.144s] > +|writing 'bootloader'... > +|OKAY [ 0.009s] > +|finished. total time: 0.153s > + > +and on the gadget side you should see: > +|Starting download of 405019 bytes > +|... > +|downloading of 405019 bytes finished > +|download_bytes: 0x62e1b > +|Writing 'bootloader' > +|Writing 'bootloader' DONE! > diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c > index 7a1acb9..da2117c 100644 > --- a/drivers/usb/gadget/f_fastboot.c > +++ b/drivers/usb/gadget/f_fastboot.c > @@ -19,6 +19,9 @@ > #include > #include > #include > +#include > +#include > +#include > > #define FASTBOOT_VERSION "0.4" > > @@ -35,6 +38,15 @@ > > #define EP_BUFFER_SIZE 4096 > > +static struct fastboot_config *fb_cfg; > +static char *transfer_buffer = (void *)CONFIG_USB_FASTBOOT_BUF_ADDR; is this "transfer_buffer" really needed? > + > +/* To support the Android-style naming of flash */ > +#define MAX_PTN 16 > +static fastboot_ptentry ptable[MAX_PTN]; > +static unsigned int pcount; > +/* static int static_pcount = -1; */ > + > struct f_fastboot { > struct usb_function usb_function; > > @@ -119,6 +131,39 @@ static struct usb_gadget_strings *fastboot_strings[] = { > > static void rx_handler_command(struct usb_ep *ep, struct usb_request *req); > > +void set_fb_config(struct fastboot_config *cfg) > +{ > + fb_cfg = cfg; > +} > + > +/* > + * Android style flash utilties */ > +void fastboot_flash_reset_ptn(void) > +{ > +#ifdef DEBUG > + printf("fastboot flash reset partition..!!"); > +#endif > + pcount = 0; > +} > + > +void fastboot_flash_add_ptn(fastboot_ptentry *ptn) > +{ > + if (pcount < MAX_PTN) { > + memcpy((ptable + pcount), ptn, sizeof(*ptn)); > + pcount++; > + } > +} > + > +void fastboot_flash_dump_ptn(void) > +{ > + unsigned int n; > + for (n = 0; n < pcount; n++) { > + fastboot_ptentry *ptn = ptable + n; > + printf("ptn %d name='%s'", n, ptn->name); > + printf(" start=%d len=%d\n", ptn->start, ptn->length); > + } > +} > + > static void fastboot_complete(struct usb_ep *ep, struct usb_request *req) > { > int status = req->status; > @@ -308,6 +353,21 @@ static int fastboot_tx_write_str(const char *buffer) > return fastboot_tx_write(buffer, strlen(buffer)); > } > > +fastboot_ptentry *fastboot_flash_find_ptn(const char *name) > +{ > + unsigned int n; > + > + for (n = 0; n < pcount; n++) { > + /* Make sure a substring is not accepted */ > + if (strlen(name) == strlen(ptable[n].name)) { > + if (0 == strcmp(ptable[n].name, name)) > + return ptable + n; > + } > + } > + return 0; > +} > + > + > static void compl_do_reset(struct usb_ep *ep, struct usb_request *req) > { > do_reset(NULL, 0, 0, NULL); > @@ -346,7 +406,7 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req) > strncat(response, FASTBOOT_VERSION, chars_left); > } else if (!strcmp_l1("bootloader-version", cmd)) { > strncat(response, U_BOOT_VERSION, chars_left); > - } else if (!strcmp_l1("downloadsize", cmd)) { > + } else if (!strcmp_l1("max-download-size", cmd)) { why did this change? > char str_num[12]; > > sprintf(str_num, "%08x", CONFIG_USB_FASTBOOT_BUF_SIZE); > @@ -380,6 +440,7 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) > unsigned int transfer_size = download_size - download_bytes; > const unsigned char *buffer = req->buf; > unsigned int buffer_size = req->actual; > + int dnl_complete = 0; what is the purpose of this flag (and the code-change below) ??? > > if (req->status != 0) { > printf("Bad status: %d\n", req->status); > @@ -389,11 +450,9 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) > if (buffer_size < transfer_size) > transfer_size = buffer_size; > > - memcpy((void *)CONFIG_USB_FASTBOOT_BUF_ADDR + download_bytes, > - buffer, transfer_size); > + memcpy((void *)transfer_buffer + download_bytes, buffer, transfer_size); > > download_bytes += transfer_size; > - > /* Check if transfer is done */ > if (download_bytes >= download_size) { > /* > @@ -403,9 +462,7 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) > download_size = 0; > req->complete = rx_handler_command; > req->length = EP_BUFFER_SIZE; > - > - sprintf(response, "OKAY"); > - fastboot_tx_write_str(response); > + dnl_complete = 1; > > printf("\ndownloading of %d bytes finished\n", download_bytes); > } else { > @@ -419,6 +476,11 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) > if (!(download_bytes % (74 * BYTES_PER_DOT))) > putc('\n'); > } > + > + if (dnl_complete) { > + sprintf(response, "OKAY"); > + fastboot_tx_write_str(response); > + } > req->actual = 0; > usb_ep_queue(ep, req, 0); > } > @@ -469,6 +531,37 @@ static void cb_boot(struct usb_ep *ep, struct usb_request *req) > fastboot_tx_write_str("OKAY"); > } > > +static void cb_flash(struct usb_ep *ep, struct usb_request *req) > +{ > + char *cmdbuf = req->buf; > + char response[32]; > + char part_name[20] = {0,}; > + strncpy(part_name, cmdbuf + 6, req->actual - 6); > + handle_flash(part_name, response, transfer_buffer); > + fastboot_tx_write_str(response); > +} > + > +int fastboot_oem(const char *cmd) > +{ > + printf("fastboot_oem:%s", cmd); > + if (!strcmp(cmd, "format")) > + return do_format(); > + return -1; > +} > + > +static void cb_oem(struct usb_ep *ep, struct usb_request *req) > +{ > + char *cmd = req->buf; > + > + printf("calling fastboot oem!! : %s\n", cmd); > + int r = fastboot_oem(cmd + 4); > + if (r < 0) { > + fastboot_tx_write_str("FAIL"); > + } else { > + fastboot_tx_write_str("OKAY"); > + } > +} > + > struct cmd_dispatch_info { > char *cmd; > void (*cb)(struct usb_ep *ep, struct usb_request *req); > @@ -487,6 +580,12 @@ static const struct cmd_dispatch_info cmd_dispatch_info[] = { > }, { > .cmd = "boot", > .cb = cb_boot, > + }, { > + .cmd = "flash", > + .cb = cb_flash, > + }, { > + .cmd = "oem", > + .cb = cb_oem, > }, > }; > > @@ -496,6 +595,8 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) > void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL; > int i; > > + *(cmdbuf + req->actual) = '\0'; > + > for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) { > if (!strcmp_l1(cmd_dispatch_info[i].cmd, cmdbuf)) { > func_cb = cmd_dispatch_info[i].cb; > @@ -514,3 +615,66 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) > usb_ep_queue(ep, req, 0); > } > } > + > +static int alt_setting_num; > + > +int handle_flash(char *part_name, char *response, char *transfer_buffer) > +{ > + int status = 0; > + printf("download_bytes: 0x%x\n", download_bytes); > + if (download_bytes) { > + struct fastboot_ptentry *ptn; > + > + /* Next is the partition name */ > + ptn = fastboot_flash_find_ptn(part_name); FYI - disk/part_efi.c provides: get_partition_info_efi_by_name() > + > + if (ptn == 0) { > + printf("Partition:[%s] does not exist\n", part_name); > + sprintf(response, "FAILpartition does not exist"); > + } else if ((download_bytes > ptn->length) && > + !(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) { > + /* Check if this is not really a flash write, > + * but instead a saveenv > + */ > + unsigned int i = 0; > + /* Env file is expected with a NULL delimeter between > + * env variables So replace New line Feeds(0x0a) with > + * NULL (0x00) > + */ > + for (i = 0; i < download_bytes; i++) { > + if (transfer_buffer[i] == 0x0a) > + transfer_buffer[i] = 0x00; > + } > + memset(env_ptr->data, 0, ENV_SIZE); > + memcpy(env_ptr->data, transfer_buffer, download_bytes); > + do_env_save(NULL, 0, 1, NULL); > + printf("saveenv to '%s' DONE!\n", ptn->name); > + sprintf(response, "OKAY"); > + } else { > + /* Normal case */ > + alt_setting_num = dfu_get_alt(part_name); > + status = dfu_write(dfu_get_entity(alt_setting_num), > + transfer_buffer, download_bytes, 0); > + printf("Writing '%s'\n", ptn->name); > + if (status) { > + 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"); > + } > + return status; > +} > + > +int board_partition_init(void) > +{ > + board_mmc_fbtptn_init(); > + return 1; > +} > diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h > index 3999405..2227a88 100644 > --- a/include/configs/am335x_evm.h > +++ b/include/configs/am335x_evm.h > @@ -87,6 +87,7 @@ > "uuid_disk=${uuid_gpt_disk};" \ > "name=rootfs,start=2MiB,size=-,uuid=${uuid_gpt_rootfs}\0" \ > "optargs=\0" \ > + "dfu_alt_info=" DFU_ALT_INFO "\0" \ > "mmcdev=0\0" \ > "mmcroot=/dev/mmcblk0p2 ro\0" \ > "mmcrootfstype=ext4 rootwait\0" \ > @@ -303,6 +304,16 @@ > #endif > > #ifdef CONFIG_MUSB_GADGET > + > +#define CONFIG_FB_MMCDEV 1 > + > +/*Uncomment this to enable NAND fastboot*/ > +/*#define CONFIG_NAND */ > + > +/*Uncomment this to support eMMC booting*/ > +#define CONFIG_STORAGE_EMMC > + > + > #define CONFIG_USB_ETHER > #define CONFIG_USB_ETH_RNDIS > #define CONFIG_USBNET_HOST_ADDR "de:ad:be:af:00:00" > @@ -336,14 +347,13 @@ > #define CONFIG_DFU_MMC > #define CONFIG_CMD_DFU > #define DFU_ALT_INFO_MMC \ > - "dfu_alt_info_mmc=" \ > "boot part 0 1;" \ > "rootfs part 0 2;" \ > "MLO fat 0 1;" \ > - "MLO.raw mmc 0x100 0x100;" \ > - "u-boot.img.raw mmc 0x300 0x400;" \ > - "spl-os-args.raw mmc 0x80 0x80;" \ > - "spl-os-image.raw mmc 0x900 0x2000;" \ > + "MLO.raw raw 0x100 0x100;" \ > + "u-boot.img.raw raw 0x300 0x400;" \ > + "spl-os-args.raw raw 0x80 0x80;" \ > + "spl-os-image.raw raw 0x900 0x2000;" \ > "spl-os-args fat 0 1;" \ > "spl-os-image fat 0 1;" \ > "u-boot.img fat 0 1;" \ > @@ -374,6 +384,9 @@ > DFU_ALT_INFO_MMC \ > DFU_ALT_INFO_RAM \ > DFU_ALT_INFO_NAND > +#ifdef CONFIG_DFU_MMC > +#define DFU_ALT_INFO DFU_ALT_INFO_MMC > +#endif > #endif > > /* > diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h > index 644e97f..84594a0 100644 > --- a/include/configs/omap3_beagle.h > +++ b/include/configs/omap3_beagle.h > @@ -77,6 +77,18 @@ > #define CONFIG_USB_FASTBOOT_BUF_ADDR CONFIG_SYS_LOAD_ADDR > #define CONFIG_USB_FASTBOOT_BUF_SIZE 0x07000000 > > +#ifdef CONFIG_CMD_FASTBOOT > +#define CONFIG_FB_MMCDEV 1 > +#define CONFIG_DFU_FUNCTION > +#define CONFIG_DFU_MMC > +#define CONFIG_CMD_DFU > +#define DFU_ALT_INFO_MMC "" > +#endif > + > +#ifdef CONFIG_DFU_MMC > +#define DFU_ALT_INFO DFU_ALT_INFO_MMC > +#endif > + > /* USB EHCI */ > #define CONFIG_CMD_USB > #define CONFIG_USB_EHCI > diff --git a/include/usb/fastboot.h b/include/usb/fastboot.h > new file mode 100644 > index 0000000..a54778e > --- /dev/null > +++ b/include/usb/fastboot.h > @@ -0,0 +1,182 @@ > +/* > + * (C) Copyright 2008 - 2009 > + * Windriver, > + * Tom Rix > + * > + * Copyright (c) 2011 Sebastian Andrzej Siewior > + * > + * > + * Copyright (C) 2008 The Android Open Source Project > + * All rights reserved. > + * > + * Copyright 2014 Linaro, Ltd. > + * Dileep Katta > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef FASTBOOT_H > +#define FASTBOOT_H > + > +#include > +#include > +#include > +#include > +#include > + > +#ifdef DEBUG > +#define FBTDBG(fmt, args...)\ > + printf("DEBUG: [%s]: %d:\n"fmt, __func__, __LINE__, ##args) > +#else > +#define FBTDBG(fmt, args...) do {} while (0) > +#endif > + > +#ifdef INFO > +#define FBTINFO(fmt, args...)\ > + printf("INFO: [%s]: "fmt, __func__, ##args) > +#else > +#define FBTINFO(fmt, args...) do {} while (0) > +#endif > + > +#ifdef WARN > +#define FBTWARN(fmt, args...)\ > + printf("WARNING: [%s]: "fmt, __func__, ##args) > +#else > +#define FBTWARN(fmt, args...) do {} while (0) > +#endif > + > +#ifdef ERR > +#define FBTERR(fmt, args...)\ > + printf("ERROR: [%s]: "fmt, __func__, ##args) > +#else > +#define FBTERR(fmt, args...) do {} while (0) > +#endif > + > +struct fastboot_config { > + /* > + * Transfer buffer for storing data sent by the client. It should be > + * able to hold a kernel image and flash partitions. Care should be > + * take so it does not overrun bootloader memory > + */ > + unsigned char *transfer_buffer; > + > + /* Size of the buffer mentioned above */ > + unsigned int transfer_buffer_size; > + > + /* Total data to be downloaded */ > + unsigned int download_size; > + > + /* Data downloaded so far */ > + unsigned int download_bytes; > + > + unsigned int nand_block_size; > + > + unsigned int nand_oob_size; > + > + unsigned int download_bytes_unpadded; > +}; > + > +#define FB_STR_PRODUCT_IDX 1 > +#define FB_STR_SERIAL_IDX 2 > +#define FB_STR_CONFIG_IDX 3 > +#define FB_STR_INTERFACE_IDX 4 > +#define FB_STR_MANUFACTURER_IDX 5 > +#define FB_STR_PROC_REV_IDX 6 > +#define FB_STR_PROC_TYPE_IDX 7 > + > +#ifdef CONFIG_CMD_FASTBOOT > + > +int fastboot_init(void); > +void fastboot_shutdown(void); > +int fastboot_poll(void); > + > +int fastboot_board_init(struct fastboot_config *interface, > + struct usb_gadget_strings **str); > + > + > +/* Android-style flash naming */ > +typedef struct fastboot_ptentry fastboot_ptentry; > + > +/* flash partitions are defined in terms of blocks > + ** (flash erase units) > + */ > +struct fastboot_ptentry { > + /* The logical name for this partition, null terminated */ > + char name[16]; > + /* The start wrt the nand part, must be multiple of nand block size */ > + unsigned int start; > + /* The length of the partition, must be multiple of nand block size */ > + unsigned int length; > + /* Controls the details of how operations are done on the partition > + See the FASTBOOT_PTENTRY_FLAGS_*'s defined below */ > + unsigned int flags; > +}; > + > +/* Lower byte shows if the read/write/erase operation in > + repeated. The base address is incremented. > + Either 0 or 1 is ok for a default */ > + > +#define FASTBOOT_PTENTRY_FLAGS_REPEAT_MASK(n) (n & 0x0f) > +#define FASTBOOT_PTENTRY_FLAGS_REPEAT_4 0x00000004 > + > +/* Writes happen a block at a time. > + If the write fails, go to next block > + NEXT_GOOD_BLOCK and CONTIGOUS_BLOCK can not both be set */ > +#define FASTBOOT_PTENTRY_FLAGS_WRITE_NEXT_GOOD_BLOCK 0x00000010 > + > +/* Find a contiguous block big enough for a the whole file > + NEXT_GOOD_BLOCK and CONTIGOUS_BLOCK can not both be set */ > +#define FASTBOOT_PTENTRY_FLAGS_WRITE_CONTIGUOUS_BLOCK 0x00000020 > + > +/* Sets the ECC to software before writing > + HW and SW ECC should not both be set. */ > +#define FASTBOOT_PTENTRY_FLAGS_WRITE_SW_ECC 0x00000040 > + > +/* Sets the ECC to hardware before writing > + HW and SW ECC should not both be set. */ > +#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_ECC 0x00000080 > + > +/* Sets the ECC to hardware before writing > + HW and SW ECC should not both be set. */ > +#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_BCH4_ECC 0x00000100 > + > +/* Sets the ECC to hardware before writing > + HW and SW ECC should not both be set. */ > +#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_BCH8_ECC 0x00000200 > + > +/* Sets the ECC to hardware before writing > + HW and SW ECC should not both be set. */ > +#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_BCH16_ECC 0x00000400 > + > +/* Write the file with write.i */ > +#define FASTBOOT_PTENTRY_FLAGS_WRITE_I 0x00000800 > + > +/* Write the file with write.jffs2 */ > +#define FASTBOOT_PTENTRY_FLAGS_WRITE_JFFS2 0x00001000 > + > +/* Write the file as a series of variable/value pairs > + using the setenv and saveenv commands */ > +#define FASTBOOT_PTENTRY_FLAGS_WRITE_ENV 0x00002000 > + > + > +/* The Android-style flash handling */ > + > +/* tools to populate and query the partition table */ > +void fastboot_flash_add_ptn(fastboot_ptentry *ptn); > +fastboot_ptentry *fastboot_flash_find_ptn(const char *name); > +fastboot_ptentry *fastboot_flash_get_ptn(unsigned n); > +unsigned int fastboot_flash_get_ptn_count(void); > +void fastboot_flash_dump_ptn(void); > +int fastboot_oem(const char *cmd); > +int do_format(void); > +int board_mmc_fbtptn_init(void); > +void fastboot_flash_reset_ptn(void); > +int board_partition_init(void); > +int handle_flash(char *part_name, char *response, char *transfer_buffer); > + > +extern int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); > +extern int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); > +extern env_t *env_ptr; > + > +#endif > +#endif > My initial comments and questions Thanks, Steve