fastboot: support for overriding format fs-type and size

This changes allows overriding the fs-type and size that
are normally returned by the booloader.

This is in preparation for supporting other FSes.

Change-Id: I8d141a0d4d14df9fe84d3b131484e9696fcd8870
Signed-off-by: JP Abgrall <jpa@google.com>
diff --git a/fastboot/engine.c b/fastboot/engine.c
index 0fab703..5a6709b 100644
--- a/fastboot/engine.c
+++ b/fastboot/engine.c
@@ -102,18 +102,20 @@
  * Not all devices report the filesystem type, so don't report any errors,
  * just return false.
  */
-int fb_format_supported(usb_handle *usb, const char *partition)
+int fb_format_supported(usb_handle *usb, const char *partition, const char *type_override)
 {
-    char response[FB_RESPONSE_SZ + 1] = {0,};
+    char fs_type[FB_RESPONSE_SZ + 1] = {0,};
     int status;
     unsigned int i;
 
-    status = fb_getvar(usb, response, "partition-type:%s", partition);
+    if (type_override) {
+        return !!fs_get_generator(type_override);
+    }
+    status = fb_getvar(usb, fs_type, "partition-type:%s", partition);
     if (status) {
         return 0;
     }
-
-    return !!fs_get_generator(response);
+    return !!fs_get_generator(fs_type);
 }
 
 static int cb_default(Action *a, int status, char *resp)
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index f98268e..4d3e0af 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -33,6 +33,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <string.h>
+
 #include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
@@ -288,10 +289,13 @@
             "\n"
             "commands:\n"
             "  update <filename>                        reflash device from update.zip\n"
-            "  flashall                                 flash boot, system, and if found, recovery, tos\n"
+            "  flashall                                 flash boot, system, and if found,\n"
+            "                                           recovery, tos\n"
             "  flash <partition> [ <filename> ]         write a file to a flash partition\n"
             "  erase <partition>                        erase a flash partition\n"
-            "  format <partition>                       format a flash partition \n"
+            "  format[:[<fs type>][:[<size>]] <partition> format a flash partition.\n"
+            "                                           Can override the fs type and/or\n"
+            "                                           size the bootloader reports.\n"
             "  getvar <variable>                        display a bootloader variable\n"
             "  boot <kernel> [ <ramdisk> ]              download and boot kernel\n"
             "  flash:raw boot <kernel> [ <ramdisk> ]    create bootimage and flash it\n"
@@ -312,10 +316,12 @@
             "  -p <product>                             specify product name\n"
             "  -c <cmdline>                             override kernel commandline\n"
             "  -i <vendor id>                           specify a custom USB vendor id\n"
-            "  -b <base_addr>                           specify a custom kernel base address. default: 0x10000000\n"
-            "  -n <page size>                           specify the nand page size. default: 2048\n"
-            "  -S <size>[K|M|G]                         automatically sparse files greater than\n"
-            "                                           size.  0 to disable\n"
+            "  -b <base_addr>                           specify a custom kernel base address.\n"
+            "                                           default: 0x10000000\n"
+            "  -n <page size>                           specify the nand page size.\n"
+            "                                           default: 2048\n"
+            "  -S <size>[K|M|G]                         automatically sparse files greater\n"
+            "                                           than size.  0 to disable\n"
         );
 }
 
@@ -616,7 +622,7 @@
     /* The function fb_format_supported() currently returns the value
      * we want, so just call it.
      */
-     return fb_format_supported(usb, part);
+     return fb_format_supported(usb, part, NULL);
 }
 
 static int load_buf_fd(usb_handle *usb, int fd,
@@ -879,9 +885,12 @@
     return num;
 }
 
-void fb_perform_format(const char *partition, int skip_if_not_supported)
+void fb_perform_format(const char *partition, int skip_if_not_supported,
+                       const char *type_override, const char *size_override)
 {
-    char pType[FB_RESPONSE_SZ + 1], pSize[FB_RESPONSE_SZ + 1];
+    char pTypeBuff[FB_RESPONSE_SZ + 1], pSizeBuff[FB_RESPONSE_SZ + 1];
+    char *pType = pTypeBuff;
+    char *pSize = pSizeBuff;
     unsigned int limit = INT_MAX;
     struct fastboot_buffer buf;
     const char *errMsg = NULL;
@@ -900,12 +909,28 @@
         errMsg = "Can't determine partition type.\n";
         goto failed;
     }
+    if (type_override) {
+        if (strcmp(type_override, pType)) {
+            fprintf(stderr,
+                    "Warning: %s type is %s, but %s was requested for formating.\n",
+                    partition, pType, type_override);
+        }
+        pType = type_override;
+    }
 
     status = fb_getvar(usb, pSize, "partition-size:%s", partition);
     if (status) {
         errMsg = "Unable to get partition size\n";
         goto failed;
     }
+    if (size_override) {
+        if (strcmp(size_override, pSize)) {
+            fprintf(stderr,
+                    "Warning: %s size is %s, but %s was requested for formating.\n",
+                    partition, pSize, size_override);
+        }
+        pSize = size_override;
+    }
 
     gen = fs_get_generator(pType);
     if (!gen) {
@@ -1067,18 +1092,42 @@
         } else if(!strcmp(*argv, "erase")) {
             require(2);
 
-            if (fb_format_supported(usb, argv[1])) {
+            if (fb_format_supported(usb, argv[1], NULL)) {
                 fprintf(stderr, "******** Did you mean to fastboot format this partition?\n");
             }
 
             fb_queue_erase(argv[1]);
             skip(2);
-        } else if(!strcmp(*argv, "format")) {
+        } else if(!strncmp(*argv, "format", strlen("format"))) {
+            char *overrides;
+            char *type_override = NULL;
+            char *size_override = NULL;
             require(2);
+            /*
+             * Parsing for: "format[:[type][:[size]]]"
+             * Some valid things:
+             *  - select ontly the size, and leave default fs type:
+             *    format::0x4000000 userdata
+             *  - default fs type and size:
+             *    format userdata
+             *    format:: userdata
+             */
+            overrides = strchr(*argv, ':');
+            if (overrides) {
+                overrides++;
+                size_override = strchr(overrides, ':');
+                if (size_override) {
+                    size_override[0] = '\0';
+                    size_override++;
+                }
+                type_override = overrides;
+            }
+            if (type_override && !type_override[0]) type_override = NULL;
+            if (size_override && !size_override[0]) size_override = NULL;
             if (erase_first && needs_erase(argv[1])) {
                 fb_queue_erase(argv[1]);
             }
-            fb_perform_format(argv[1], 0);
+            fb_perform_format(argv[1], 0, type_override, size_override);
             skip(2);
         } else if(!strcmp(*argv, "signature")) {
             require(2);
@@ -1166,9 +1215,9 @@
 
     if (wants_wipe) {
         fb_queue_erase("userdata");
-        fb_perform_format("userdata", 1);
+        fb_perform_format("userdata", 1, NULL, NULL);
         fb_queue_erase("cache");
-        fb_perform_format("cache", 1);
+        fb_perform_format("cache", 1, NULL, NULL);
     }
     if (wants_reboot) {
         fb_queue_reboot();
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index c510a36..fc5d4f4 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -45,7 +45,7 @@
 
 /* engine.c - high level command queue engine */
 int fb_getvar(struct usb_handle *usb, char *response, const char *fmt, ...);
-int fb_format_supported(usb_handle *usb, const char *partition);
+int fb_format_supported(usb_handle *usb, const char *partition, const char *type_override);
 void fb_queue_flash(const char *ptn, void *data, unsigned sz);
 void fb_queue_flash_sparse(const char *ptn, struct sparse_file *s, unsigned sz);
 void fb_queue_erase(const char *ptn);
diff --git a/fastboot/fs.c b/fastboot/fs.c
index 6a1f9e6..cd4b880 100644
--- a/fastboot/fs.c
+++ b/fastboot/fs.c
@@ -39,12 +39,12 @@
 
 };
 
-const struct fs_generator* fs_get_generator(const char* name)
+const struct fs_generator* fs_get_generator(const char *fs_type)
 {
     unsigned i;
 
     for (i = 0; i < sizeof(generators) / sizeof(*generators); i++)
-        if (!strcmp(generators[i].fs_type, name))
+        if (!strcmp(generators[i].fs_type, fs_type))
             return generators + i;
 
     return NULL;
diff --git a/fastboot/fs.h b/fastboot/fs.h
index 65b9555..8388629 100644
--- a/fastboot/fs.h
+++ b/fastboot/fs.h
@@ -5,7 +5,7 @@
 
 struct fs_generator;
 
-const struct fs_generator* fs_get_generator(const char* name);
+const struct fs_generator* fs_get_generator(const char *fs_type);
 int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize);
 
 #endif