Skip to contentSkip to conversation

fastboot: oem format command implementation

PATCH New Dileep Katta 2 participants 3 messages Jan 30, 2015 – Feb 9, 2015 USB

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 fastboot: oem format command implementation

This is the Modified version of http://patchwork.ozlabs.org/patch/388084/
- As flash support is already in mainline, it is removed
- 'oem' command support is present
- 'oem format' command is implemented
- Handled review comments of the original patch

---
 common/cmd_fastboot.c           |   4 +
 common/cmd_mmc.c                |   2 +-
 disk/Makefile                   |   1 +
 disk/part_fastboot.c            | 363 ++++++++++++++++++++++++++++++++++++++++
 doc/README.android-fastboot     |   5 +-
 drivers/usb/gadget/f_fastboot.c |  85 ++++++++++
 include/usb/fastboot.h          | 108 ++++++++++++
 7 files changed, 564 insertions(+), 4 deletions(-)
 create mode 100644 disk/part_fastboot.c
 create mode 100644 include/usb/fastboot.h
common/cmd_fastboot.c +4 -0
index b72f4f3..efdf461 100644
@@ -10,12 +10,16 @@
 #include <common.h>
 #include <command.h>
 #include <g_dnl.h>
+#include <usb/fastboot.h>
 
 static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
 	int ret;
 
 	g_dnl_clear_detach();
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+	board_partition_init();
+#endif
 	ret = g_dnl_register("usb_dnl_fastboot");
 	if (ret)
 		return ret;
common/cmd_mmc.c +1 -1
index 4e28c9d..0ce747b 100644
@@ -809,7 +809,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;
 
disk/Makefile +1 -0
index 6970cec..4969656 100644
@@ -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_FASTBOOT_FLASH_MMC_DEV)	+=part_fastboot.o
disk/part_fastboot.c new file +363 -0

363 lines not on this page · raw message

doc/README.android-fastboot +2 -3
index 1677609..77cce8e 100644
@@ -6,9 +6,8 @@ Overview
 The protocol that is used over USB is described in
 README.android-fastboot-protocol in same directory.
 
-The current implementation does not yet support the erase command or the
-"oem format" command, and there is minimal support for the flash command;
-it only supports eMMC devices.
+The current implementation does not yet support the erase command, and
+there is minimal support for the flash command;it only supports eMMC devices.
 
 Client installation
 ===================
drivers/usb/gadget/f_fastboot.c +85 -0

124 lines not on this page · raw message

include/usb/fastboot.h new file +108 -0

108 lines not on this page · raw message

Signature · 1 line
1.8.3.2
#1 lore raw

PATCH 1/1 fastboot: oem format command implementation

Hi Dileep,

Quoted 108 lines

This is the Modified version of
http://patchwork.ozlabs.org/patch/388084/
- As flash support is already in mainline, it is removed
- 'oem' command support is present
- 'oem format' command is implemented
- Handled review comments of the original patch

---
 common/cmd_fastboot.c           |   4 +
 common/cmd_mmc.c                |   2 +-
 disk/Makefile                   |   1 +
 disk/part_fastboot.c            | 363
++++++++++++++++++++++++++++++++++++++++
doc/README.android-fastboot     |   5 +-
drivers/usb/gadget/f_fastboot.c |  85 ++++++++++
include/usb/fastboot.h          | 108 ++++++++++++ 7 files changed,

564 insertions(+), 4 deletions(-) create mode 100644 disk/part_fastboot.c create mode 100644 include/usb/fastboot.h

common/cmd_fastboot.c +4 -0
index b72f4f3..efdf461 100644
@@ -10,12 +10,16 @@
 #include <common.h>
 #include <command.h>
 #include <g_dnl.h>
+#include <usb/fastboot.h>
 
 static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char
 *const argv[]) {
 	int ret;
 
 	g_dnl_clear_detach();
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+	board_partition_init();
+#endif
 	ret = g_dnl_register("usb_dnl_fastboot");
 	if (ret)
 		return ret;
common/cmd_mmc.c +0 -1
index 4e28c9d..0ce747b 100644
@@ -809,7 +809,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;
disk/Makefile +1 -0
index 6970cec..4969656 100644
@@ -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_FASTBOOT_FLASH_MMC_DEV)	+=part_fastboot.o
disk/part_fastboot.c new file +39 -0
new file mode 100644
index 0000000..adf37af
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * Author : Pankaj Bharadiya <[email protected]>
+ *
+ * Tom Rix <[email protected]> and Sitara 2011 u-boot by
+ * Mohammed Afzal M A <[email protected]>
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Copyright 2014 Linaro, Ltd.
+ * Dileep Katta <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <usb/fastboot.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <environment.h>
+#include <mmc.h>
+#include <dfu.h>
+#include <asm/arch/mmc_host_def.h>
+
+#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
Quoted 3 lines

requirement.
+ */
+static struct partition_emmc partitions[] = {

Defining mmc partitions as a static struct in the code IMHO is not flexible.

Quoted 14 lines
disk/part_fastboot.c new file +1 -0
+	{ "-", 128 },	/* Master Boot Record and GUID

Partition Table */

disk/part_fastboot.c new file +3 -0
+	{ "spl", 128 },	/* First stage bootloader */
+	{ "bootloader", 512 },	/* Second stage bootloader */
+	{ "misc", 128 },		/* Rserved for internal

purpose */

disk/part_fastboot.c new file +3 -0
+	{ "-", 128 },			/* Reserved */
+	{ "recovery", 8*1024 },	/* Recovery partition  */
+	{ "boot", 8*1024 },	/* Partition contains kernel +

ramdisk images */

disk/part_fastboot.c new file +1 -0
+	{ "system", 256*1024 },		/* Android file

system */

disk/part_fastboot.c new file +1 -0
+	{ "cache", 256*1024 },		/* Store Application

Cache */

disk/part_fastboot.c line 54

Quoted 4 lines
disk/part_fastboot.c new file +4 -0
+	{ "userdata", 256*1024 },	/* User data */
+	{ "media", 0 },			/* Media files */
+	{ 0, 0 },
+};

Maybe it would be better if we could reuse $partitions ? With above code we introduce another (not compatible and flexible) way to specify eMMC partitions for the board.

disk/part_fastboot.c line 61

Quoted 7 lines
disk/part_fastboot.c new file +7 -0
+
+
+static const u8 partition_type[16] = {
+	0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
+	0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7,
+};
+

Please look into ./include/part_efi.h [1]

disk/part_fastboot.c line 65

Quoted 4 lines
disk/part_fastboot.c new file +4 -0
+static const u8 random_uuid[16] = {
+	0xff, 0x1f, 0xf2, 0xf9, 0xd4, 0xa8, 0x0e, 0x5f,
+	0x97, 0x46, 0x59, 0x48, 0x69, 0xae, 0xc3, 0x4e,
+};

I'm not sure if specifying "random" uuids via static const table is what you wanted.

For more flexible solution please refer to Trats2 automatic generation of UUIDs (either from HW or in SW).

Quoted 32 lines
disk/part_fastboot.c new file +32 -0
+
+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;

disk/part_fastboot.c line 107

Quoted 10 lines
disk/part_fastboot.c new file +10 -0
+
+struct ptable {
+	u8 mbr[512];
+	union {
+		struct efi_header header;
+		u8 block[512];
+	};
+	struct efi_entry entry[EFI_ENTRIES];
+};
+

Already defined at [1].

Quoted 13 lines
disk/part_fastboot.c new file +13 -0
+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 */

disk/part_fastboot.c line 130

Quoted 10 lines
disk/part_fastboot.c new file +10 -0
+	mbr[0x1c7] = 0x00;
+	mbr[0x1c8] = 0x00;
+	mbr[0x1c9] = 0x00;
+
+	memcpy(mbr + 0x1ca, &blocks, sizeof(u32));
+
+	mbr[0x1fe] = 0x55;
+	mbr[0x1ff] = 0xaa;
+}
+

Please refer to part_efi.c - code for mbr initialization is already there.

Quoted 57 lines
disk/part_fastboot.c new file +37 -0
+
+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;
+
+	/* Get the initial checksum by passing buf as NULL */
+	n = crc32(0, NULL, 0);
+	n = crc32(n, (void *)ptbl->entry, sizeof(ptbl->entry));
+	hdr->entries_crc32 = n;
+
+	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) +{

disk/part_fastboot.c new file +6 -0
+	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);

disk/part_fastboot.c new file +12 -0
+		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);

disk/part_fastboot.c line 196

Quoted 10 lines
disk/part_fastboot.c new file +10 -0
+		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;
+}

The same as above.

BTW - please use proper error values instead of -1.

Quoted 24 lines
disk/part_fastboot.c new file +6 -0
+
+void import_efi_partition(struct efi_entry *entry)
+{
+	struct fastboot_ptentry e;
+	int n;
+	if (memcmp(entry->type_uuid, partition_type,

sizeof(partition_type)))

disk/part_fastboot.c new file +14 -0
+		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);

disk/part_fastboot.c new file +2 -0
+	else
+		printf("%8d %7dK %s\n", e.start, e.length/0x400,
Quoted 1 line

e.name); +}

The above condition looks like a hard codded one. Please add rationale for this (#defines would help there)

Quoted 21 lines
disk/part_fastboot.c new file +20 -0
+
+static int load_ptbl(void)
+{
+	u64 ptbl_sectors = 0;
+	int i = 0, r = 0;
+
+	struct ptable gpt[sizeof(struct ptable)];
+	struct mmc *mmc = NULL;
+
+	mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
+	if (mmc == NULL) {
+		printf("No MMC in slot 1\n");
+		return -1;
+	}
+
+	int gpt_size = sizeof(struct ptable);
+
+	ptbl_sectors = (u64)(gpt_size / MMCSD_SECTOR_SIZE);
+
+	r = mmc->block_dev.block_read(1, 0, ptbl_sectors, (void

*)gpt);

disk/part_fastboot.c line 241

Quoted 2 lines
disk/part_fastboot.c new file +2 -0
+	if (r == -1) {
+		printf("error reading GPT\n");
		^^^^^ error()

disk/part_fastboot.c line 247

Quoted 6 lines
disk/part_fastboot.c new file +6 -0
+		goto fail;
+	}
+
+	if (memcmp(gpt->header.magic, "EFI PART", 8)) {
+		printf("efi partition table not found\n");
+		r = -1;

^^^ more often ret is used than r.

Quoted 6 lines
disk/part_fastboot.c new file +6 -0
+		goto fail;
+	}
+
+	for (i = 0; i < EFI_ENTRIES; i++)
+		import_efi_partition(&gpt->entry[i]);
+

disk/part_fastboot.c

Quoted 10 lines
disk/part_fastboot.c new file +10 -0
+fail:
+	return r;
+}
+
+int board_mmc_fbtptn_init(void)
+{
+	char *mmc_init[2] = {"mmc", "rescan",};
+	char dev[2];
+	char *mmc_dev[3] = {"mmc", "dev", dev};
+	unsigned fb_mmcdev = CONFIG_FASTOOT_FLASH_MMC_DEV;

Is your code working with either eMMC or SD card?

Quoted 144 lines
disk/part_fastboot.c new file +61 -0
+
+	sprintf(dev, "0x%x", fb_mmcdev);
+
+	if (do_mmcops(NULL, 0, 3, mmc_dev)) {
+		printf("MMC DEV: %d selection FAILED!\n", fb_mmcdev);
+		return -1;
+	}
+
+	if (do_mmcops(NULL, 0, 2, mmc_init)) {
+			printf("FAIL:Init of MMC card\n");
+			return -1;
+	}
+
+	return load_ptbl();
+}
+
+
+static struct ptable the_ptable;
+
+int do_format(void)
+{
+	struct ptable *ptbl = &the_ptable;
+	struct mmc *mmc = NULL;
+	unsigned blocks;
+	unsigned next;
+	unsigned sz;
+	int n;
+	unsigned fb_mmcdev = CONFIG_FASTBOOT_FLASH_MMC_DEV;
+
+	/* get mmc info */
+	mmc = find_mmc_device(fb_mmcdev);
+	if (mmc == 0) {
+		printf("no mmc device at slot %d", fb_mmcdev);
+		return -1;
+	}
+
+	mmc->has_init = 0;
+	if (mmc_init(mmc)) {
+		printf("\n mmc init FAILED");
+		return -1;
+	}
+
+	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;
+
+	start_ptbl(ptbl, blocks);
+	n = 0;
+	next = 0;
+	for (n = 0, next = 0; partitions[n].name; n++) {
+		/* below line change size from KB to no of blocks */
+		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))

disk/part_fastboot.c new file +39 -0
+			return -1;
+		next += sz;
+	}
+	end_ptbl(ptbl);
+
+	fastboot_flash_reset_ptn();
+
+	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", fb_mmcdev);
+
+	if (do_mmcops(NULL, 0, 3, mmc_dev)) {
+		printf("MMC DEV: %d selection FAILED!\n", 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("mbr write FAILED!\n");
+		return -1;
+	}
+
+	printf("\nnew partition table:\n");
+	load_ptbl();
+
+	return 0;
+}
doc/README.android-fastboot +0 -1
index 1677609..77cce8e 100644
@@ -6,9 +6,8 @@ Overview
 The protocol that is used over USB is described in
 README.android-fastboot-protocol in same directory.
 
-The current implementation does not yet support the erase command or

the -"oem format" command, and there is minimal support for the flash command; -it only supports eMMC devices.
+The current implementation does not yet support the erase command, and +there is minimal support for the flash command;it only supports eMMC devices.
Client installation
===================

(quoted diff) +0 -0

b/drivers/usb/gadget/f_fastboot.c index 310175a..76ccc55 100644

drivers/usb/gadget/f_fastboot.c +8 -0
@@ -23,6 +23,8 @@
 #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
 #include <fb_mmc.h>
 #endif
+#include <usb/fastboot.h>
+#include <command.h>
 
 #define FASTBOOT_VERSION		"0.4"
 
@@ -39,6 +41,12 @@
 
 #define EP_BUFFER_SIZE			4096
 
+/* To support the Android-style naming of flash */
+#define MAX_PTN 16
+static struct fastboot_ptentry ptable[MAX_PTN];
+static unsigned int pcount;
+/* static int static_pcount = -1; */
+
 struct f_fastboot {
 	struct usb_function usb_function;
 

drivers/usb/gadget/f_fastboot.c static struct usb_gadget_strings · line 139

Quoted 9 lines
drivers/usb/gadget/f_fastboot.c +6 -0
@@ -123,6 +131,33 @@ static struct usb_gadget_strings
 *fastboot_strings[] = { 
 static void rx_handler_command(struct usb_ep *ep, struct usb_request
 *req); 
+/* Android style flash utilties */
+void fastboot_flash_reset_ptn(void)
+{
+#ifdef DEBUG
+	printf("fastboot flash reset partition..!!");
+#endif

Please use debug().

Quoted 59 lines
drivers/usb/gadget/f_fastboot.c +21 -0
+	pcount = 0;
+}
+
+void fastboot_flash_add_ptn(struct 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++) {
+		struct 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) {
drivers/usb/gadget/f_fastboot.c +23 -0
 	int status = req->status;
@@ -312,6 +347,21 @@ static int fastboot_tx_write_str(const char
 *buffer) return fastboot_tx_write(buffer, strlen(buffer));
 }
 
+struct 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);
@@ -513,6 +563,27 @@ static void cb_flash(struct usb_ep *ep, struct
 usb_request *req) }
 #endif
 
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+int fastboot_oem(const char *cmd)
+{
+	if (!strcmp(cmd, "format"))
+		return do_format();
+	return -1;
+}
+

drivers/usb/gadget/f_fastboot.c static void cb_flash(struct usb_ep *ep, struct · line 583

Quoted 10 lines
drivers/usb/gadget/f_fastboot.c +10 -0
+static void cb_oem(struct usb_ep *ep, struct usb_request *req)
+{
+	char *cmd = req->buf;
+
+	int r = fastboot_oem(cmd + 4);
+	if (r < 0) {
+		fastboot_tx_write_str("FAIL");
+	} else {
+		fastboot_tx_write_str("OKAY");
+	}

Braces could be removed.

Quoted 148 lines
drivers/usb/gadget/f_fastboot.c +9 -0
+}
+#endif
+
 struct cmd_dispatch_info {
 	char *cmd;
 	void (*cb)(struct usb_ep *ep, struct usb_request *req);
@@ -541,6 +612,12 @@ static const struct cmd_dispatch_info
 cmd_dispatch_info[] = { .cb = cb_flash,
 	},
 #endif
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+	{
+		.cmd = "oem",
+		.cb = cb_oem,
+	},
+#endif
 };
 
 static void rx_handler_command(struct usb_ep *ep, struct usb_request

*req) @@ -576,3 +653,11 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) usb_ep_queue(ep, req, 0);

drivers/usb/gadget/f_fastboot.c +8 -0
 	}
 }
+
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+int board_partition_init(void)
+{
+	board_mmc_fbtptn_init();
+	return 1;
+}
+#endif
include/usb/fastboot.h new file +6 -0
new file mode 100644
index 0000000..8fee6fc
@@ -0,0 +1,108 @@
+/*
+ * (C) Copyright 2008 - 2009
+ * Windriver, <www.windriver.com>
+ * Tom Rix <[email protected]>
+ *
+ * Copyright (c) 2011 Sebastian Andrzej Siewior

<[email protected]>
+ *
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Copyright 2014 Linaro, Ltd.
+ * Dileep Katta <[email protected]>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */

include/usb/fastboot.h new file +19 -0
+
+#ifndef FASTBOOT_H
+#define FASTBOOT_H
+
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#ifdef CONFIG_CMD_FASTBOOT
+
+/* Android-style flash naming */
+
+/* flash partitions are defined in blocks (flash erase units) */
+struct fastboot_ptentry {
+	/* The logical name for this partition, null terminated */
+	char name[16];
+	/* start wrt the nand part, must be multiple of nand block

size */

include/usb/fastboot.h new file +2 -0
+	unsigned int start;
+	/* length of the partition, must be multiple of nand block

size */

include/usb/fastboot.h new file +3 -0
+	unsigned int length;
+	/*
+	 * Controls the details of how operations are done on the

partition

include/usb/fastboot.h new file +15 -0
+	 * See the FASTBOOT_PTENTRY_FLAGS_*'s defined below
+	 */
+	unsigned int flags;
+};
+
+/*
+ * Lower byte shows if the read/write/erase operation is 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
+ */

include/usb/fastboot.h new file +48 -0
+#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
+
+/*
+ * Following definitions are to set the ECC to software/Hardware
+ * before writing. HW and SW ECC should not both be set.
+ */
+
+
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_SW_ECC           0x00000040
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_ECC           0x00000080
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_BCH4_ECC      0x00000100
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_BCH8_ECC      0x00000200
+#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(struct fastboot_ptentry *ptn);
+struct fastboot_ptentry *fastboot_flash_find_ptn(const char *name);
+struct 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 do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const

argv[]); +

include/usb/fastboot.h line 108

Quoted 2 lines
include/usb/fastboot.h new file +2 -0
+#endif
+#endif

To sum up:

A lot of duplicated code - already present in part_efi.[ch] - is in this patch. Please rewrite it

Moreover, please consider using $partitions env variable with gpt write command to create eMMC partitions. This code is already tested and validated in u-boot.

Signature · 5 lines
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
#2 lore raw

PATCH 1/1 fastboot: oem format command implementation

Quoted 777 lines · Lukasz Majewski

Hi Dileep,

Quoted 108 lines

This is the Modified version of
http://patchwork.ozlabs.org/patch/388084/
- As flash support is already in mainline, it is removed
- 'oem' command support is present
- 'oem format' command is implemented
- Handled review comments of the original patch

---
 common/cmd_fastboot.c           |   4 +
 common/cmd_mmc.c                |   2 +-
 disk/Makefile                   |   1 +
 disk/part_fastboot.c            | 363
++++++++++++++++++++++++++++++++++++++++
doc/README.android-fastboot     |   5 +-
drivers/usb/gadget/f_fastboot.c |  85 ++++++++++
include/usb/fastboot.h          | 108 ++++++++++++ 7 files changed,

564 insertions(+), 4 deletions(-) create mode 100644 disk/part_fastboot.c create mode 100644 include/usb/fastboot.h

common/cmd_fastboot.c +4 -0
index b72f4f3..efdf461 100644
@@ -10,12 +10,16 @@
 #include <common.h>
 #include <command.h>
 #include <g_dnl.h>
+#include <usb/fastboot.h>
 
 static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char
 *const argv[]) {
      int ret;
 
      g_dnl_clear_detach();
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+     board_partition_init();
+#endif
      ret = g_dnl_register("usb_dnl_fastboot");
      if (ret)
              return ret;
common/cmd_mmc.c +0 -1
index 4e28c9d..0ce747b 100644
@@ -809,7 +809,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;
disk/Makefile +1 -0
index 6970cec..4969656 100644
@@ -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_FASTBOOT_FLASH_MMC_DEV) +=part_fastboot.o
disk/part_fastboot.c new file +39 -0
new file mode 100644
index 0000000..adf37af
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * Author : Pankaj Bharadiya <[email protected]>
+ *
+ * Tom Rix <[email protected]> and Sitara 2011 u-boot by
+ * Mohammed Afzal M A <[email protected]>
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Copyright 2014 Linaro, Ltd.
+ * Dileep Katta <[email protected]>
+ *
+ * SPDX-License-Identifier:  GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <usb/fastboot.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <environment.h>
+#include <mmc.h>
+#include <dfu.h>
+#include <asm/arch/mmc_host_def.h>
+
+#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
Quoted 3 lines

requirement.
+ */
+static struct partition_emmc partitions[] = {

Defining mmc partitions as a static struct in the code IMHO is not flexible.

Quoted 14 lines

+ { "-", 128 }, /* Master Boot Record and GUID
Partition Table */

disk/part_fastboot.c new file +3 -0
+     { "spl", 128 }, /* First stage bootloader */
+     { "bootloader", 512 },  /* Second stage bootloader */
+     { "misc", 128 },                /* Rserved for internal

purpose */

disk/part_fastboot.c new file +3 -0
+     { "-", 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 */

disk/part_fastboot.c line 54

Quoted 4 lines
disk/part_fastboot.c new file +4 -0
+     { "userdata", 256*1024 },       /* User data */
+     { "media", 0 },                 /* Media files */
+     { 0, 0 },
+};

Maybe it would be better if we could reuse $partitions ? With above code we introduce another (not compatible and flexible) way to specify eMMC partitions for the board.

disk/part_fastboot.c line 61

Quoted 7 lines
disk/part_fastboot.c new file +7 -0
+
+
+static const u8 partition_type[16] = {
+     0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
+     0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7,
+};
+

Please look into ./include/part_efi.h [1]

disk/part_fastboot.c line 65

Quoted 4 lines
disk/part_fastboot.c new file +4 -0
+static const u8 random_uuid[16] = {
+     0xff, 0x1f, 0xf2, 0xf9, 0xd4, 0xa8, 0x0e, 0x5f,
+     0x97, 0x46, 0x59, 0x48, 0x69, 0xae, 0xc3, 0x4e,
+};

I'm not sure if specifying "random" uuids via static const table is what you wanted.

For more flexible solution please refer to Trats2 automatic generation of UUIDs (either from HW or in SW).

Quoted 32 lines
disk/part_fastboot.c new file +32 -0
+
+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;

disk/part_fastboot.c line 107

Quoted 10 lines
disk/part_fastboot.c new file +10 -0
+
+struct ptable {
+     u8 mbr[512];
+     union {
+             struct efi_header header;
+             u8 block[512];
+     };
+     struct efi_entry entry[EFI_ENTRIES];
+};
+

Already defined at [1].

Quoted 13 lines
disk/part_fastboot.c new file +13 -0
+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 */

disk/part_fastboot.c line 130

Quoted 10 lines
disk/part_fastboot.c new file +10 -0
+     mbr[0x1c7] = 0x00;
+     mbr[0x1c8] = 0x00;
+     mbr[0x1c9] = 0x00;
+
+     memcpy(mbr + 0x1ca, &blocks, sizeof(u32));
+
+     mbr[0x1fe] = 0x55;
+     mbr[0x1ff] = 0xaa;
+}
+

Please refer to part_efi.c - code for mbr initialization is already there.

Quoted 57 lines
disk/part_fastboot.c new file +37 -0
+
+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;
+
+     /* Get the initial checksum by passing buf as NULL */
+     n = crc32(0, NULL, 0);
+     n = crc32(n, (void *)ptbl->entry, sizeof(ptbl->entry));
+     hdr->entries_crc32 = n;
+
+     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) +{

disk/part_fastboot.c new file +6 -0
+     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);

disk/part_fastboot.c new file +12 -0
+             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);

disk/part_fastboot.c line 196

Quoted 10 lines
disk/part_fastboot.c new file +10 -0
+             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;
+}

The same as above.

BTW - please use proper error values instead of -1.

Quoted 24 lines
disk/part_fastboot.c new file +6 -0
+
+void import_efi_partition(struct efi_entry *entry)
+{
+     struct fastboot_ptentry e;
+     int n;
+     if (memcmp(entry->type_uuid, partition_type,

sizeof(partition_type)))

disk/part_fastboot.c new file +14 -0
+             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);

disk/part_fastboot.c new file +2 -0
+     else
+             printf("%8d %7dK %s\n", e.start, e.length/0x400,
Quoted 1 line

e.name); +}

The above condition looks like a hard codded one. Please add rationale for this (#defines would help there)

Quoted 21 lines
disk/part_fastboot.c new file +20 -0
+
+static int load_ptbl(void)
+{
+     u64 ptbl_sectors = 0;
+     int i = 0, r = 0;
+
+     struct ptable gpt[sizeof(struct ptable)];
+     struct mmc *mmc = NULL;
+
+     mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
+     if (mmc == NULL) {
+             printf("No MMC in slot 1\n");
+             return -1;
+     }
+
+     int gpt_size = sizeof(struct ptable);
+
+     ptbl_sectors = (u64)(gpt_size / MMCSD_SECTOR_SIZE);
+
+     r = mmc->block_dev.block_read(1, 0, ptbl_sectors, (void

*)gpt);

disk/part_fastboot.c line 241

Quoted 2 lines
disk/part_fastboot.c new file +2 -0
+     if (r == -1) {
+             printf("error reading GPT\n");
                ^^^^^ error()

disk/part_fastboot.c line 247

Quoted 6 lines
disk/part_fastboot.c new file +6 -0
+             goto fail;
+     }
+
+     if (memcmp(gpt->header.magic, "EFI PART", 8)) {
+             printf("efi partition table not found\n");
+             r = -1;

^^^ more often ret is used than r.

Quoted 6 lines
disk/part_fastboot.c new file +6 -0
+             goto fail;
+     }
+
+     for (i = 0; i < EFI_ENTRIES; i++)
+             import_efi_partition(&gpt->entry[i]);
+

disk/part_fastboot.c

Quoted 10 lines
disk/part_fastboot.c new file +10 -0
+fail:
+     return r;
+}
+
+int board_mmc_fbtptn_init(void)
+{
+     char *mmc_init[2] = {"mmc", "rescan",};
+     char dev[2];
+     char *mmc_dev[3] = {"mmc", "dev", dev};
+     unsigned fb_mmcdev = CONFIG_FASTOOT_FLASH_MMC_DEV;

Is your code working with either eMMC or SD card?

Quoted 144 lines
disk/part_fastboot.c new file +61 -0
+
+     sprintf(dev, "0x%x", fb_mmcdev);
+
+     if (do_mmcops(NULL, 0, 3, mmc_dev)) {
+             printf("MMC DEV: %d selection FAILED!\n", fb_mmcdev);
+             return -1;
+     }
+
+     if (do_mmcops(NULL, 0, 2, mmc_init)) {
+                     printf("FAIL:Init of MMC card\n");
+                     return -1;
+     }
+
+     return load_ptbl();
+}
+
+
+static struct ptable the_ptable;
+
+int do_format(void)
+{
+     struct ptable *ptbl = &the_ptable;
+     struct mmc *mmc = NULL;
+     unsigned blocks;
+     unsigned next;
+     unsigned sz;
+     int n;
+     unsigned fb_mmcdev = CONFIG_FASTBOOT_FLASH_MMC_DEV;
+
+     /* get mmc info */
+     mmc = find_mmc_device(fb_mmcdev);
+     if (mmc == 0) {
+             printf("no mmc device at slot %d", fb_mmcdev);
+             return -1;
+     }
+
+     mmc->has_init = 0;
+     if (mmc_init(mmc)) {
+             printf("\n mmc init FAILED");
+             return -1;
+     }
+
+     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;
+
+     start_ptbl(ptbl, blocks);
+     n = 0;
+     next = 0;
+     for (n = 0, next = 0; partitions[n].name; n++) {
+             /* below line change size from KB to no of blocks */
+             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))

disk/part_fastboot.c new file +39 -0
+                     return -1;
+             next += sz;
+     }
+     end_ptbl(ptbl);
+
+     fastboot_flash_reset_ptn();
+
+     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", fb_mmcdev);
+
+     if (do_mmcops(NULL, 0, 3, mmc_dev)) {
+             printf("MMC DEV: %d selection FAILED!\n", 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("mbr write FAILED!\n");
+             return -1;
+     }
+
+     printf("\nnew partition table:\n");
+     load_ptbl();
+
+     return 0;
+}
doc/README.android-fastboot +0 -1
index 1677609..77cce8e 100644
@@ -6,9 +6,8 @@ Overview
 The protocol that is used over USB is described in
 README.android-fastboot-protocol in same directory.
 
-The current implementation does not yet support the erase command or

the -"oem format" command, and there is minimal support for the flash command; -it only supports eMMC devices.
+The current implementation does not yet support the erase command, and +there is minimal support for the flash command;it only supports eMMC devices.
Client installation
===================

(quoted diff) +0 -0

b/drivers/usb/gadget/f_fastboot.c index 310175a..76ccc55 100644

drivers/usb/gadget/f_fastboot.c +8 -0
@@ -23,6 +23,8 @@
 #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
 #include <fb_mmc.h>
 #endif
+#include <usb/fastboot.h>
+#include <command.h>
 
 #define FASTBOOT_VERSION             "0.4"
 
@@ -39,6 +41,12 @@
 
 #define EP_BUFFER_SIZE                       4096
 
+/* To support the Android-style naming of flash */
+#define MAX_PTN 16
+static struct fastboot_ptentry ptable[MAX_PTN];
+static unsigned int pcount;
+/* static int static_pcount = -1; */
+
 struct f_fastboot {
      struct usb_function usb_function;
 

drivers/usb/gadget/f_fastboot.c static struct usb_gadget_strings · line 139

Quoted 9 lines
drivers/usb/gadget/f_fastboot.c +6 -0
@@ -123,6 +131,33 @@ static struct usb_gadget_strings
 *fastboot_strings[] = {
 static void rx_handler_command(struct usb_ep *ep, struct usb_request
 *req);
+/* Android style flash utilties */
+void fastboot_flash_reset_ptn(void)
+{
+#ifdef DEBUG
+     printf("fastboot flash reset partition..!!");
+#endif

Please use debug().

Quoted 59 lines
drivers/usb/gadget/f_fastboot.c +21 -0
+     pcount = 0;
+}
+
+void fastboot_flash_add_ptn(struct 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++) {
+             struct 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;
drivers/usb/gadget/f_fastboot.c +23 -0
@@ -312,6 +347,21 @@ static int fastboot_tx_write_str(const char
 *buffer) return fastboot_tx_write(buffer, strlen(buffer));
 }
 
+struct 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);
@@ -513,6 +563,27 @@ static void cb_flash(struct usb_ep *ep, struct
 usb_request *req) }
 #endif
 
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+int fastboot_oem(const char *cmd)
+{
+     if (!strcmp(cmd, "format"))
+             return do_format();
+     return -1;
+}
+

drivers/usb/gadget/f_fastboot.c static void cb_flash(struct usb_ep *ep, struct · line 583

Quoted 10 lines
drivers/usb/gadget/f_fastboot.c +10 -0
+static void cb_oem(struct usb_ep *ep, struct usb_request *req)
+{
+     char *cmd = req->buf;
+
+     int r = fastboot_oem(cmd + 4);
+     if (r < 0) {
+             fastboot_tx_write_str("FAIL");
+     } else {
+             fastboot_tx_write_str("OKAY");
+     }

Braces could be removed.

Quoted 148 lines
drivers/usb/gadget/f_fastboot.c +9 -0
+}
+#endif
+
 struct cmd_dispatch_info {
      char *cmd;
      void (*cb)(struct usb_ep *ep, struct usb_request *req);
@@ -541,6 +612,12 @@ static const struct cmd_dispatch_info
 cmd_dispatch_info[] = { .cb = cb_flash,
      },
 #endif
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+     {
+             .cmd = "oem",
+             .cb = cb_oem,
+     },
+#endif
 };
 
 static void rx_handler_command(struct usb_ep *ep, struct usb_request

*req) @@ -576,3 +653,11 @@ static void rx_handler_command(struct

usb_ep *ep, struct usb_request *req) usb_ep_queue(ep, req, 0);
      }

}

drivers/usb/gadget/f_fastboot.c +8 -0
+
+#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
+int board_partition_init(void)
+{
+     board_mmc_fbtptn_init();
+     return 1;
+}
+#endif
include/usb/fastboot.h new file +6 -0
new file mode 100644
index 0000000..8fee6fc
@@ -0,0 +1,108 @@
+/*
+ * (C) Copyright 2008 - 2009
+ * Windriver, <www.windriver.com>
+ * Tom Rix <[email protected]>
+ *
+ * Copyright (c) 2011 Sebastian Andrzej Siewior

<[email protected]>
+ *
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Copyright 2014 Linaro, Ltd.
+ * Dileep Katta <[email protected]>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */

include/usb/fastboot.h new file +19 -0
+
+#ifndef FASTBOOT_H
+#define FASTBOOT_H
+
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#ifdef CONFIG_CMD_FASTBOOT
+
+/* Android-style flash naming */
+
+/* flash partitions are defined in blocks (flash erase units) */
+struct fastboot_ptentry {
+     /* The logical name for this partition, null terminated */
+     char name[16];
+     /* start wrt the nand part, must be multiple of nand block

size */

include/usb/fastboot.h new file +2 -0
+     unsigned int start;
+     /* length of the partition, must be multiple of nand block

size */

include/usb/fastboot.h new file +3 -0
+     unsigned int length;
+     /*
+      * Controls the details of how operations are done on the

partition

include/usb/fastboot.h new file +15 -0
+      * See the FASTBOOT_PTENTRY_FLAGS_*'s defined below
+      */
+     unsigned int flags;
+};
+
+/*
+ * Lower byte shows if the read/write/erase operation is 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
+ */

include/usb/fastboot.h new file +48 -0
+#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
+
+/*
+ * Following definitions are to set the ECC to software/Hardware
+ * before writing. HW and SW ECC should not both be set.
+ */
+
+
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_SW_ECC           0x00000040
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_ECC           0x00000080
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_BCH4_ECC      0x00000100
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_BCH8_ECC      0x00000200
+#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(struct fastboot_ptentry *ptn);
+struct fastboot_ptentry *fastboot_flash_find_ptn(const char *name);
+struct 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 do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const

argv[]); +

include/usb/fastboot.h line 108

Quoted 2 lines
include/usb/fastboot.h new file +2 -0
+#endif
+#endif

To sum up:

A lot of duplicated code - already present in part_efi.[ch] - is in this patch. Please rewrite it

Moreover, please consider using $partitions env variable with gpt write command to create eMMC partitions. This code is already tested and validated in u-boot.

Quoted 7 lines

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Thanks for the review. As an abstract patch for "oem format" by Rob Herring is in place, stopping this submission.

Regards,
Dileep