diff options
Diffstat (limited to 'fastboot')
| -rw-r--r-- | fastboot/bootimg.c | 19 | ||||
| -rw-r--r-- | fastboot/fastboot.c | 112 | ||||
| -rw-r--r-- | fastboot/fastboot_protocol.txt | 173 |
3 files changed, 251 insertions, 53 deletions
diff --git a/fastboot/bootimg.c b/fastboot/bootimg.c index 9e0e45c..240784f 100644 --- a/fastboot/bootimg.c +++ b/fastboot/bootimg.c @@ -37,10 +37,10 @@ void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline) strcpy((char*) h->cmdline, cmdline); } -boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, - void *ramdisk, unsigned ramdisk_size, - void *second, unsigned second_size, - unsigned page_size, unsigned base, +boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset, + void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset, + void *second, unsigned second_size, unsigned second_offset, + unsigned page_size, unsigned base, unsigned tags_offset, unsigned *bootimg_size) { unsigned kernel_actual; @@ -68,12 +68,15 @@ boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, hdr->kernel_size = kernel_size; hdr->ramdisk_size = ramdisk_size; hdr->second_size = second_size; - hdr->kernel_addr = base + 0x00008000; - hdr->ramdisk_addr = base + 0x01000000; - hdr->second_addr = base + 0x00F00000; - hdr->tags_addr = base + 0x00000100; + + hdr->kernel_addr = base + kernel_offset; + hdr->ramdisk_addr = base + ramdisk_offset; + hdr->second_addr = base + second_offset; + hdr->tags_addr = base + tags_offset; + hdr->page_size = page_size; + memcpy(hdr->magic + page_size, kernel, kernel_size); memcpy(hdr->magic + page_size + kernel_actual, diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c index 3de6d7d..447b257 100644 --- a/fastboot/fastboot.c +++ b/fastboot/fastboot.c @@ -58,10 +58,10 @@ char cur_product[FB_RESPONSE_SZ + 1]; void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline); -boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, - void *ramdisk, unsigned ramdisk_size, - void *second, unsigned second_size, - unsigned page_size, unsigned base, +boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset, + void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset, + void *second, unsigned second_size, unsigned second_offset, + unsigned page_size, unsigned base, unsigned tags_offset, unsigned *bootimg_size); static usb_handle *usb = 0; @@ -74,7 +74,13 @@ static int long_listing = 0; static int64_t sparse_limit = -1; static int64_t target_sparse_limit = -1; -static unsigned base_addr = 0x10000000; +unsigned page_size = 2048; +unsigned base_addr = 0x10000000; +unsigned kernel_offset = 0x00008000; +unsigned ramdisk_offset = 0x01000000; +unsigned second_offset = 0x00f00000; +unsigned tags_offset = 0x00000100; + void die(const char *fmt, ...) { @@ -186,11 +192,6 @@ oops: } #endif -int match_fastboot(usb_ifc_info *info) -{ - return match_fastboot_with_serial(info, serial); -} - int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial) { if(!(vendor_id && (info->dev_vendor == vendor_id)) && @@ -217,6 +218,11 @@ int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial) return 0; } +int match_fastboot(usb_ifc_info *info) +{ + return match_fastboot_with_serial(info, serial); +} + int list_devices_callback(usb_ifc_info *info) { if (match_fastboot_with_serial(info, NULL) == 0) { @@ -297,14 +303,14 @@ 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\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" ); } -void *load_bootable_image(unsigned page_size, const char *kernel, const char *ramdisk, +void *load_bootable_image(const char *kernel, const char *ramdisk, unsigned *sz, const char *cmdline) { void *kdata = 0, *rdata = 0; @@ -345,7 +351,10 @@ void *load_bootable_image(unsigned page_size, const char *kernel, const char *ra } fprintf(stderr,"creating boot image...\n"); - bdata = mkbootimg(kdata, ksize, rdata, rsize, 0, 0, page_size, base_addr, &bsize); + bdata = mkbootimg(kdata, ksize, kernel_offset, + rdata, rsize, ramdisk_offset, + 0, 0, second_offset, + page_size, base_addr, tags_offset, &bsize); if(bdata == 0) { fprintf(stderr,"failed to create boot.img\n"); return 0; @@ -806,35 +815,64 @@ int main(int argc, char **argv) int erase_first = 1; void *data; unsigned sz; - unsigned page_size = 2048; int status; int c; int r; - const struct option longopts = { 0, 0, 0, 0 }; + 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'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0} + }; serial = getenv("ANDROID_SERIAL"); while (1) { - c = getopt_long(argc, argv, "wub:n:s:S:lp:c:i:m:h", &longopts, NULL); + int option_index = 0; + c = getopt_long(argc, argv, "wub:k:n:r:s:S:lp:c:i:m:h", longopts, NULL); if (c < 0) { break; } - + /* Alphabetical cases */ switch (c) { - case 'w': - wants_wipe = 1; - break; - case 'u': - erase_first = 0; - break; case 'b': base_addr = strtoul(optarg, 0, 16); break; + case 'c': + cmdline = optarg; + break; + case 'h': + usage(); + return 1; + case 'i': { + char *endptr = NULL; + unsigned long val; + + val = strtoul(optarg, &endptr, 0); + if (!endptr || *endptr != '\0' || (val & ~0xffff)) + die("invalid vendor id '%s'", optarg); + vendor_id = (unsigned short)val; + break; + } + case 'k': + kernel_offset = strtoul(optarg, 0, 16); + break; + case 'l': + long_listing = 1; + break; case 'n': page_size = (unsigned)strtoul(optarg, NULL, 0); if (!page_size) die("invalid page size"); break; + case 'p': + product = optarg; + break; + case 'r': + ramdisk_offset = strtoul(optarg, 0, 16); + break; case 's': serial = optarg; break; @@ -844,28 +882,12 @@ int main(int argc, char **argv) die("invalid sparse limit"); } break; - case 'l': - long_listing = 1; - break; - case 'p': - product = optarg; + case 'u': + erase_first = 0; break; - case 'c': - cmdline = optarg; + case 'w': + wants_wipe = 1; break; - case 'i': { - char *endptr = NULL; - unsigned long val; - - val = strtoul(optarg, &endptr, 0); - if (!endptr || *endptr != '\0' || (val & ~0xffff)) - die("invalid vendor id '%s'", optarg); - vendor_id = (unsigned short)val; - break; - } - case 'h': - usage(); - return 1; case '?': return 1; default: @@ -944,7 +966,7 @@ int main(int argc, char **argv) rname = argv[0]; skip(1); } - data = load_bootable_image(page_size, kname, rname, &sz, cmdline); + data = load_bootable_image(kname, rname, &sz, cmdline); if (data == 0) return 1; fb_queue_download("boot.img", data, sz); fb_queue_command("boot", "booting"); @@ -975,7 +997,7 @@ int main(int argc, char **argv) } else { skip(3); } - data = load_bootable_image(page_size, kname, rname, &sz, cmdline); + data = load_bootable_image(kname, rname, &sz, cmdline); if (data == 0) die("cannot load bootable image"); fb_queue_flash(pname, data, sz); } else if(!strcmp(*argv, "flashall")) { diff --git a/fastboot/fastboot_protocol.txt b/fastboot/fastboot_protocol.txt new file mode 100644 index 0000000..2248992 --- /dev/null +++ b/fastboot/fastboot_protocol.txt @@ -0,0 +1,173 @@ + +FastBoot Version 0.4 +---------------------- + +The fastboot protocol is a mechanism for communicating with bootloaders +over USB. It is designed to be very straightforward to implement, to +allow it to be used across a wide range of devices and from hosts running +Linux, Windows, or OSX. + + +Basic Requirements +------------------ + +* Two bulk endpoints (in, out) are required +* Max packet size must be 64 bytes for full-speed and 512 bytes for + high-speed USB +* The protocol is entirely host-driven and synchronous (unlike the + multi-channel, bi-directional, asynchronous ADB protocol) + + +Transport and Framing +--------------------- + +1. Host sends a command, which is an ascii string in a single + packet no greater than 64 bytes. + +2. Client response with a single packet no greater than 64 bytes. + The first four bytes of the response are "OKAY", "FAIL", "DATA", + or "INFO". Additional bytes may contain an (ascii) informative + message. + + a. INFO -> the remaining 60 bytes are an informative message + (providing progress or diagnostic messages). They should + be displayed and then step #2 repeats + + b. FAIL -> the requested command failed. The remaining 60 bytes + of the response (if present) provide a textual failure message + to present to the user. Stop. + + c. OKAY -> the requested command completed successfully. Go to #5 + + d. DATA -> the requested command is ready for the data phase. + A DATA response packet will be 12 bytes long, in the form of + DATA00000000 where the 8 digit hexidecimal number represents + the total data size to transfer. + +3. Data phase. Depending on the command, the host or client will + send the indicated amount of data. Short packets are always + acceptable and zero-length packets are ignored. This phase continues + until the client has sent or received the number of bytes indicated + in the "DATA" response above. + +4. Client responds with a single packet no greater than 64 bytes. + The first four bytes of the response are "OKAY", "FAIL", or "INFO". + Similar to #2: + + a. INFO -> display the remaining 60 bytes and return to #4 + + b. FAIL -> display the remaining 60 bytes (if present) as a failure + reason and consider the command failed. Stop. + + c. OKAY -> success. Go to #5 + +5. Success. Stop. + + +Example Session +--------------- + +Host: "getvar:version" request version variable + +Client: "OKAY0.4" return version "0.4" + +Host: "getvar:nonexistant" request some undefined variable + +Client: "OKAY" return value "" + +Host: "download:00001234" request to send 0x1234 bytes of data + +Client: "DATA00001234" ready to accept data + +Host: < 0x1234 bytes > send data + +Client: "OKAY" success + +Host: "flash:bootloader" request to flash the data to the bootloader + +Client: "INFOerasing flash" indicate status / progress + "INFOwriting flash" + "OKAY" indicate success + +Host: "powerdown" send a command + +Client: "FAILunknown command" indicate failure + + +Command Reference +----------------- + +* Command parameters are indicated by printf-style escape sequences. + +* Commands are ascii strings and sent without the quotes (which are + for illustration only here) and without a trailing 0 byte. + +* Commands that begin with a lowercase letter are reserved for this + specification. OEM-specific commands should not begin with a + lowercase letter, to prevent incompatibilities with future specs. + + "getvar:%s" Read a config/version variable from the bootloader. + The variable contents will be returned after the + OKAY response. + + "download:%08x" Write data to memory which will be later used + by "boot", "ramdisk", "flash", etc. The client + will reply with "DATA%08x" if it has enough + space in RAM or "FAIL" if not. The size of + the download is remembered. + + "verify:%08x" Send a digital signature to verify the downloaded + data. Required if the bootloader is "secure" + otherwise "flash" and "boot" will be ignored. + + "flash:%s" Write the previously downloaded image to the + named partition (if possible). + + "erase:%s" Erase the indicated partition (clear to 0xFFs) + + "boot" The previously downloaded data is a boot.img + and should be booted according to the normal + procedure for a boot.img + + "continue" Continue booting as normal (if possible) + + "reboot" Reboot the device. + + "reboot-bootloader" Reboot back into the bootloader. + Useful for upgrade processes that require upgrading + the bootloader and then upgrading other partitions + using the new bootloader. + + "powerdown" Power off the device. + + + +Client Variables +---------------- + +The "getvar:%s" command is used to read client variables which +represent various information about the device and the software +on it. + +The various currently defined names are: + + version Version of FastBoot protocol supported. + It should be "0.3" for this document. + + version-bootloader Version string for the Bootloader. + + version-baseband Version string of the Baseband Software + + product Name of the product + + serialno Product serial number + + secure If the value is "yes", this is a secure + bootloader requiring a signature before + it will install or boot images. + +Names starting with a lowercase character are reserved by this +specification. OEM-specific names should not start with lowercase +characters. + + |
