Merge "aboot: cleanup fastboot related logic"
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index f2deb94..1e9dacd 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -33,7 +33,6 @@
 #include <app.h>
 #include <debug.h>
 #include <arch/arm.h>
-#include <dev/udc.h>
 #include <string.h>
 #include <stdlib.h>
 #include <kernel/thread.h>
@@ -124,14 +123,6 @@
 
 static device_info device = {DEVICE_MAGIC, 0, 0};
 
-static struct udc_device surf_udc_device = {
-	.vendor_id	= 0x18d1,
-	.product_id	= 0xD00D,
-	.version_id	= 0x0100,
-	.manufacturer	= "Google",
-	.product	= "Android",
-};
-
 struct atag_ptbl_entry
 {
 	char name[16];
@@ -1956,11 +1947,50 @@
 	}
 }
 
+/* register commands and variables for fastboot */
+void aboot_fastboot_register_commands(void)
+{
+	if (target_is_emmc_boot())
+	{
+		fastboot_register("flash:", cmd_flash_mmc);
+		fastboot_register("erase:", cmd_erase_mmc);
+	}
+	else
+	{
+		fastboot_register("flash:", cmd_flash);
+		fastboot_register("erase:", cmd_erase);
+	}
+
+	fastboot_register("boot",              cmd_boot);
+	fastboot_register("continue",          cmd_continue);
+	fastboot_register("reboot",            cmd_reboot);
+	fastboot_register("reboot-bootloader", cmd_reboot_bootloader);
+	fastboot_register("oem unlock",        cmd_oem_unlock);
+	fastboot_register("oem device-info",   cmd_oem_devinfo);
+	fastboot_register("preflash",          cmd_preflash);
+
+	/* publish variables and their values */
+	fastboot_publish("product",  TARGET(BOARD));
+	fastboot_publish("kernel",   "lk");
+	fastboot_publish("serialno", sn_buf);
+
+	/*
+	 * partition info is supported only for emmc partitions
+	 * Calling this for NAND prints some error messages which
+	 * is harmless but misleading. Avoid calling this for NAND
+	 * devices.
+	 */
+	if (target_is_emmc_boot())
+		publish_getvar_partition_info(part_info, ARRAY_SIZE(part_info));
+
+	/* Max download size supported */
+	snprintf(max_download_size, MAX_RSP_SIZE, "\t0x%x", target_get_max_flash_size());
+	fastboot_publish("max-download-size", (const char *) max_download_size);
+}
+
 void aboot_init(const struct app_descriptor *app)
 {
 	unsigned reboot_mode = 0;
-	unsigned usb_init = 0;
-	unsigned sz = 0;
 	bool boot_into_fastboot = false;
 
 	/* Setup page size information for nand/emmc reads */
@@ -1985,7 +2015,6 @@
 
 	target_serialno((unsigned char *) sn_buf);
 	dprintf(SPEW,"serial number: %s\n",sn_buf);
-	surf_udc_device.serialno = sn_buf;
 
 	/* Check if we should do something other than booting up */
 	if (keys_get_state(KEY_VOLUMEUP) && keys_get_state(KEY_VOLUMEDOWN))
@@ -2055,49 +2084,16 @@
 			"to fastboot mode.\n");
 	}
 
-	sz = target_get_max_flash_size();
+	/* We are here means regular boot did not happen. Start fastboot. */
 
-	target_fastboot_init();
+	/* register aboot specific fastboot commands */
+	aboot_fastboot_register_commands();
 
-	if(!usb_init)
-		udc_init(&surf_udc_device);
-
-	fastboot_register("boot", cmd_boot);
-
-	if (target_is_emmc_boot())
-	{
-		fastboot_register("flash:", cmd_flash_mmc);
-		fastboot_register("erase:", cmd_erase_mmc);
-	}
-	else
-	{
-		fastboot_register("flash:", cmd_flash);
-		fastboot_register("erase:", cmd_erase);
-	}
-
-	fastboot_register("continue", cmd_continue);
-	fastboot_register("reboot", cmd_reboot);
-	fastboot_register("reboot-bootloader", cmd_reboot_bootloader);
-	fastboot_register("oem unlock", cmd_oem_unlock);
-	fastboot_register("oem device-info", cmd_oem_devinfo);
-	fastboot_register("preflash", cmd_preflash);
-	fastboot_publish("product", TARGET(BOARD));
-	fastboot_publish("kernel", "lk");
-	fastboot_publish("serialno", sn_buf);
-	/*
-	 * fastboot publish is supported only for emmc partitions
-	 * Calling this for NAND prints some error messages which
-	 * is harmless but misleading. Avoid calling this for NAND
-	 * devices.
-	 */
-	if (target_is_emmc_boot())
-		publish_getvar_partition_info(part_info, ARRAY_SIZE(part_info));
-	/* Max download size supported */
-	snprintf(max_download_size, MAX_RSP_SIZE, "\t0x%x", sz);
-	fastboot_publish("max-download-size", (const char *) max_download_size);
+	/* dump partition table for debug info */
 	partition_dump();
-	fastboot_init(target_get_scratch_address(), sz);
-	udc_start();
+
+	/* initialize and start fastboot */
+	fastboot_init(target_get_scratch_address(), target_get_max_flash_size());
 }
 
 uint32_t get_page_size()
diff --git a/app/aboot/fastboot.c b/app/aboot/fastboot.c
index 262a08e..66d0437 100644
--- a/app/aboot/fastboot.c
+++ b/app/aboot/fastboot.c
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <platform.h>
+#include <target.h>
 #include <kernel/thread.h>
 #include <kernel/event.h>
 #include <dev/udc.h>
@@ -40,6 +41,26 @@
 #define MAX_USBFS_BULK_SIZE (32 * 1024)
 
 void boot_linux(void *bootimg, unsigned sz);
+static void fastboot_notify(struct udc_gadget *gadget, unsigned event);
+static struct udc_endpoint *fastboot_endpoints[2];
+
+static struct udc_device surf_udc_device = {
+	.vendor_id    = 0x18d1,
+	.product_id   = 0xD00D,
+	.version_id   = 0x0100,
+	.manufacturer = "Google",
+	.product      = "Android",
+};
+
+static struct udc_gadget fastboot_gadget = {
+	.notify        = fastboot_notify,
+	.ifc_class     = 0xff,
+	.ifc_subclass  = 0x42,
+	.ifc_protocol  = 0x03,
+	.ifc_endpoints = 2,
+	.ifc_string    = "fastboot",
+	.ept           = fastboot_endpoints,
+};
 
 /* todo: give lk strtoul and nuke this */
 static unsigned hex2unsigned(const char *x)
@@ -81,7 +102,7 @@
 	const char *name;
 	const char *value;
 };
-	
+
 static struct fastboot_cmd *cmdlist;
 
 void fastboot_register(const char *prefix,
@@ -305,6 +326,14 @@
 	}
 again:
 	while (fastboot_state != STATE_ERROR) {
+
+		/* Read buffer must be cleared first. If buffer is not cleared,
+		 * the original data in buf trailing the received command is
+		 * interpreted as part of the command.
+		 */
+		memset(buffer, 0, MAX_RSP_SIZE);
+		arch_clean_invalidate_cache_range((addr_t) buffer, MAX_RSP_SIZE);
+
 		r = usb_read(buffer, MAX_RSP_SIZE);
 		if (r < 0) break;
 		buffer[r] = 0;
@@ -322,7 +351,7 @@
 		}
 
 		fastboot_fail("unknown command");
-			
+
 	}
 	fastboot_state = STATE_OFFLINE;
 	dprintf(INFO,"fastboot: oops!\n");
@@ -345,26 +374,26 @@
 	}
 }
 
-static struct udc_endpoint *fastboot_endpoints[2];
-
-static struct udc_gadget fastboot_gadget = {
-	.notify		= fastboot_notify,
-	.ifc_class	= 0xff,
-	.ifc_subclass	= 0x42,
-	.ifc_protocol	= 0x03,
-	.ifc_endpoints	= 2,
-	.ifc_string	= "fastboot",
-	.ept		= fastboot_endpoints,
-};
-
 int fastboot_init(void *base, unsigned size)
 {
+	char sn_buf[13];
 	thread_t *thr;
 	dprintf(INFO, "fastboot_init()\n");
 
 	download_base = base;
 	download_max = size;
 
+	/* target specific initialization before going into fastboot. */
+	target_fastboot_init();
+
+	/* setup serialno */
+	target_serialno((unsigned char *) sn_buf);
+	dprintf(SPEW,"serial number: %s\n",sn_buf);
+	surf_udc_device.serialno = sn_buf;
+
+	/* register udc device */
+	udc_init(&surf_udc_device);
+
 	event_init(&usb_online, 0, EVENT_FLAG_AUTOUNSIGNAL);
 	event_init(&txn_done, 0, EVENT_FLAG_AUTOUNSIGNAL);
 
@@ -382,6 +411,7 @@
 	if (!req)
 		goto fail_alloc_req;
 
+	/* register gadget */
 	if (udc_register_gadget(&fastboot_gadget))
 		goto fail_udc_register;
 
@@ -395,12 +425,15 @@
 		goto fail_alloc_in;
 	}
 	thread_resume(thr);
+
+	udc_start();
+
 	return 0;
 
 fail_udc_register:
 	udc_request_free(req);
 fail_alloc_req:
-	udc_endpoint_free(out);	
+	udc_endpoint_free(out);
 fail_alloc_out:
 	udc_endpoint_free(in);
 fail_alloc_in: