/** * Block until the sequence of bytes * * "[^$]*\$[^#]*#.*" * * has been read from the client fd. This is one (or more) gdb * packet(s). */ static void read_packet(struct dbg_context* dbg) { byte* p; size_t checkedlen; /* Read and discard bytes until we see the start of a * packet. * * NB: we're ignoring "+/-" responses from gdb. There doesn't * seem to be any sane reason why we would send a damaged * packet to gdb over TCP, then see a "-" reply from gdb and * somehow magically fix our bug that led to the malformed * packet in the first place. */ while (skip_to_packet_start(dbg)) { read_data_once(dbg); } if (dbg->inbuf[0] == INTERRUPT_CHAR) { /* Interrupts are kind of an ugly duckling in the gdb * protocol ... */ dbg->packetend = 1; return; } /* Read until we see end-of-packet. */ for (checkedlen = 0; !(p = memchr(dbg->inbuf + checkedlen, '#', dbg->inlen)); checkedlen = dbg->inlen) { read_data_once(dbg); } dbg->packetend = (p - dbg->inbuf); /* NB: we're ignoring the gdb packet checksums here too. If * gdb is corrupted enough to garble a checksum over TCP, it's * not really clear why asking for the packet again might make * the bug go away. */ assert('$' == dbg->inbuf[0] && dbg->packetend < dbg->inlen); /* Acknowledge receipt of the packet. */ if (!dbg->no_ack) { write_data_raw(dbg, (byte*)"+", 1); write_flush(dbg); } }
static void cmd_flash(struct protocol_handle *phandle, const char *arg) { int partition; uint64_t sz; char data[BOOT_MAGIC_SIZE]; char path[PATH_MAX]; ssize_t header_sz = 0; int data_fd = 0; D(DEBUG, "cmd_flash %s\n", arg); if (try_handle_virtual_partition(phandle, arg)) { return; } if (phandle->download_fd < 0) { fastboot_fail(phandle, "no kernel file"); return; } if (flash_find_entry(arg, path, PATH_MAX)) { fastboot_fail(phandle, "partition table doesn't exist"); return; } if (flash_validate_certificate(phandle->download_fd, &data_fd) != 1) { fastboot_fail(phandle, "Access forbiden you need certificate"); return; } // TODO: Maybe its goot idea to check whether the partition is bootable if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) { if (read_data_once(data_fd, data, BOOT_MAGIC_SIZE) < BOOT_MAGIC_SIZE) { fastboot_fail(phandle, "incoming data read error, cannot read boot header"); return; } if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { fastboot_fail(phandle, "image is not a boot image"); return; } } partition = flash_get_partiton(path); sz = get_file_size64(data_fd); sz -= header_sz; if (sz > get_file_size64(partition)) { flash_close(partition); D(WARN, "size of file too large"); fastboot_fail(phandle, "size of file too large"); return; } D(INFO, "writing %"PRId64" bytes to '%s'\n", sz, arg); if (flash_write(partition, phandle->download_fd, sz, header_sz)) { fastboot_fail(phandle, "flash write failure"); return; } D(INFO, "partition '%s' updated\n", arg); flash_close(partition); close(data_fd); fastboot_okay(phandle, ""); }