summaryrefslogtreecommitdiffstats
path: root/fastboot/fastboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'fastboot/fastboot.c')
-rw-r--r--fastboot/fastboot.c124
1 files changed, 88 insertions, 36 deletions
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index 4fd1a8e..266d0b5 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -28,21 +28,21 @@
#define _LARGEFILE64_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <string.h>
+#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
-#include <unistd.h>
-#include <limits.h>
-#include <ctype.h>
#include <getopt.h>
-
+#include <inttypes.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <sys/stat.h>
+#include <unistd.h>
#include <bootimg.h>
#include <sparse/sparse.h>
@@ -71,7 +71,6 @@ static usb_handle *usb = 0;
static const char *serial = 0;
static const char *product = 0;
static const char *cmdline = 0;
-static int wipe_data = 0;
static unsigned short vendor_id = 0;
static int long_listing = 0;
static int64_t sparse_limit = -1;
@@ -100,10 +99,11 @@ static struct {
char sig_name[13];
char part_name[9];
bool is_optional;
-} images[3] = {
+} images[4] = {
{"boot.img", "boot.sig", "boot", false},
{"recovery.img", "recovery.sig", "recovery", true},
{"system.img", "system.sig", "system", false},
+ {"tos.img", "tos.sig", "tos", true},
};
void get_my_path(char *path);
@@ -120,6 +120,8 @@ char *find_item(const char *item, const char *product)
fn = "recovery.img";
} else if(!strcmp(item,"system")) {
fn = "system.img";
+ } else if(!strcmp(item,"tos")) {
+ fn = "tos.img";
} else if(!strcmp(item,"userdata")) {
fn = "userdata.img";
} else if(!strcmp(item,"cache")) {
@@ -266,7 +268,7 @@ usb_handle *open_device(void)
announce = 0;
fprintf(stderr,"< waiting for device >\n");
}
- sleep(1);
+ usleep(1000);
}
}
@@ -285,10 +287,13 @@ void usage(void)
"\n"
"commands:\n"
" update <filename> reflash device from update.zip\n"
- " flashall flash boot + recovery + system\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"
@@ -309,10 +314,12 @@ void usage(void)
" -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"
);
}
@@ -419,7 +426,7 @@ static int unzip_to_file(zipfile_t zip, char *name)
return -1;
}
- if (write(fd, data, sz) != sz) {
+ if (write(fd, data, sz) != (ssize_t)sz) {
fd = -1;
}
@@ -570,7 +577,7 @@ static int64_t get_target_sparse_limit(struct usb_handle *usb)
if (!status) {
limit = strtoul(response, NULL, 0);
if (limit > 0) {
- fprintf(stderr, "target reported max download size of %lld bytes\n",
+ fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n",
limit);
}
}
@@ -613,7 +620,7 @@ static int needs_erase(const char *part)
/* 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,
@@ -657,7 +664,7 @@ static int load_buf(usb_handle *usb, const char *fname,
fd = open(fname, O_RDONLY | O_BINARY);
if (fd < 0) {
- die("cannot open '%s'\n", fname);
+ return -1;
}
return load_buf_fd(usb, fd, buf);
@@ -713,7 +720,7 @@ void do_update(usb_handle *usb, char *fn, int erase_first)
int fd;
int rc;
struct fastboot_buffer buf;
- int i;
+ size_t i;
queue_info_dump();
@@ -787,7 +794,7 @@ void do_flashall(usb_handle *usb, int erase_first)
void *data;
unsigned sz;
struct fastboot_buffer buf;
- int i;
+ size_t i;
queue_info_dump();
@@ -819,7 +826,6 @@ void do_flashall(usb_handle *usb, int erase_first)
int do_oem_command(int argc, char **argv)
{
- int i;
char command[256];
if (argc <= 1) return 0;
@@ -876,9 +882,12 @@ static int64_t parse_num(const char *arg)
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;
@@ -897,12 +906,28 @@ void fb_perform_format(const char *partition, int skip_if_not_supported)
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 = (char *)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 = (char *)size_override;
+ }
gen = fs_get_generator(pType);
if (!gen) {
@@ -953,13 +978,13 @@ int main(int argc, char **argv)
unsigned sz;
int status;
int c;
- int r;
const struct option longopts[] = {
{"base", required_argument, 0, 'b'},
{"kernel_offset", required_argument, 0, 'k'},
{"page_size", required_argument, 0, 'n'},
{"ramdisk_offset", required_argument, 0, 'r'},
+ {"tags_offset", required_argument, 0, 't'},
{"help", 0, 0, 'h'},
{0, 0, 0, 0}
};
@@ -967,8 +992,7 @@ int main(int argc, char **argv)
serial = getenv("ANDROID_SERIAL");
while (1) {
- int option_index = 0;
- c = getopt_long(argc, argv, "wub:k:n:r:s:S:lp:c:i:m:h", longopts, NULL);
+ c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lp:c:i:m:h", longopts, NULL);
if (c < 0) {
break;
}
@@ -1009,6 +1033,9 @@ int main(int argc, char **argv)
case 'r':
ramdisk_offset = strtoul(optarg, 0, 16);
break;
+ case 't':
+ tags_offset = strtoul(optarg, 0, 16);
+ break;
case 's':
serial = optarg;
break;
@@ -1060,18 +1087,42 @@ int main(int argc, char **argv)
} 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);
@@ -1159,12 +1210,13 @@ int main(int argc, char **argv)
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();
+ fb_queue_wait_for_disconnect();
} else if (wants_reboot_bootloader) {
fb_queue_command("reboot-bootloader", "rebooting into bootloader");
fb_queue_wait_for_disconnect();