int dump_image(char* partition_name, char* filename, dump_image_callback callback) { MtdReadContext *in; const MtdPartition *partition; char buf[BLOCK_SIZE + SPARE_SIZE]; size_t partition_size; size_t read_size; size_t total; int fd; int wrote; int len; if (mtd_scan_partitions() <= 0) return die("error scanning partitions"); partition = mtd_find_partition_by_name(partition_name); if (partition == NULL) return die("can't find %s partition", partition_name); if (mtd_partition_info(partition, &partition_size, NULL, NULL)) { return die("can't get info of partition %s", partition_name); } if (!strcmp(filename, "-")) { fd = fileno(stdout); } else { fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); } if (fd < 0) return die("error opening %s", filename); in = mtd_read_partition(partition); if (in == NULL) { close(fd); unlink(filename); return die("error opening %s: %s\n", partition_name, strerror(errno)); } total = 0; while ((len = mtd_read_data(in, buf, BLOCK_SIZE)) > 0) { wrote = write(fd, buf, len); if (wrote != len) { close(fd); unlink(filename); return die("error writing %s", filename); } total += BLOCK_SIZE; if (callback != NULL) callback(total, partition_size); } mtd_read_close(in); if (close(fd)) { unlink(filename); return die("error closing %s", filename); } return 0; }
int get_bootloader_message(struct bootloader_message *out) { size_t write_size; const MtdPartition *part = get_root_mtd_partition(MISC_NAME); if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { LOGE("Can't find %s\n", MISC_NAME); return -1; } MtdReadContext *read = mtd_read_partition(part); if (read == NULL) { LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } const ssize_t size = write_size * MISC_PAGES; char data[size]; ssize_t r = mtd_read_data(read, data, size); if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); mtd_read_close(read); if (r != size) return -1; #ifdef LOG_VERBOSE printf("\n--- get_bootloader_message ---\n"); dump_data(data, size); printf("\n"); #endif memcpy(out, &data[write_size * MISC_COMMAND_PAGE], sizeof(*out)); return 0; }
static int get_bootloader_message_mtd(bootloader_message* out, const Volume* v) { size_t write_size; mtd_scan_partitions(); const MtdPartition* part = mtd_find_partition_by_name(v->blk_device); if (part == nullptr || mtd_partition_info(part, nullptr, nullptr, &write_size)) { LOGE("failed to find \"%s\"\n", v->blk_device); return -1; } MtdReadContext* read = mtd_read_partition(part); if (read == nullptr) { LOGE("failed to open \"%s\": %s\n", v->blk_device, strerror(errno)); return -1; } const ssize_t size = write_size * MISC_PAGES; char data[size]; ssize_t r = mtd_read_data(read, data, size); if (r != size) LOGE("failed to read \"%s\": %s\n", v->blk_device, strerror(errno)); mtd_read_close(read); if (r != size) return -1; memcpy(out, &data[write_size * MISC_COMMAND_PAGE], sizeof(*out)); return 0; }
int ubifs_exist(const char *part_name) { const MtdPartition *partition; MtdReadContext *mtd_read; char buf[64] = {0}; __u32 *magic; mtd_scan_partitions(); partition = mtd_find_partition_by_name(part_name); if (partition == NULL) { fprintf(stderr,"1. failed to find \"%s\" partition\n", part_name); return 0; } mtd_read = mtd_read_partition(partition); if (mtd_read == NULL) { fprintf(stderr,"2. failed to open \"%s\" partition\n", part_name); return 0; } if (64 != mtd_read_data(mtd_read, buf, 64)) { fprintf(stderr,"3. failed to read \"%s\" partition\n", part_name); mtd_read_close(mtd_read); return 0; } mtd_read_close(mtd_read); magic = (__u32 *)buf; if (*magic == UBI_EC_HDR_MAGIC) { return 1; } return 0; }
static int get_bootloader_message_mtd(struct bootloader_message *out, const Volume* v) { size_t write_size; mtd_scan_partitions(); const MtdPartition *part = mtd_find_partition_by_name(v->device); if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { LOGE("Can't find %s\n", v->device); return -1; } MtdReadContext *read = mtd_read_partition(part); if (read == NULL) { LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno)); return -1; } const ssize_t size = write_size * MISC_PAGES; char data[size]; ssize_t r = mtd_read_data(read, data, size); if (r != size) LOGE("Can't read %s\n(%s)\n", v->device, strerror(errno)); mtd_read_close(read); if (r != size) return -1; memcpy(out, &data[write_size * MISC_COMMAND_PAGE], sizeof(*out)); return 0; }
static int set_bootloader_message_mtd (const struct bootloader_message *in, const Volume * v) { size_t write_size; mtd_scan_partitions (); const MtdPartition *part = mtd_find_partition_by_name (v->device); if (part == NULL || mtd_partition_info (part, NULL, NULL, &write_size)) { LOGE ("Can't find %s\n", v->device); return -1; } MtdReadContext *read = mtd_read_partition (part); if (read == NULL) { LOGE ("Can't open %s\n(%s)\n", v->device, strerror (errno)); return -1; } ssize_t size = write_size * MISC_PAGES; char data[size]; ssize_t r = mtd_read_data (read, data, size); if (r != size) LOGE ("Can't read %s\n(%s)\n", v->device, strerror (errno)); mtd_read_close (read); if (r != size) return -1; memcpy (&data[write_size * MISC_COMMAND_PAGE], in, sizeof (*in)); MtdWriteContext *write = mtd_write_partition (part); if (write == NULL) { LOGE ("Can't open %s\n(%s)\n", v->device, strerror (errno)); return -1; } if (mtd_write_data (write, data, size) != size) { LOGE ("Can't write %s\n(%s)\n", v->device, strerror (errno)); mtd_write_close (write); return -1; } if (mtd_write_close (write)) { LOGE ("Can't finish %s\n(%s)\n", v->device, strerror (errno)); return -1; } LOGI ("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : ""); return 0; }
// FOTA cookie indicates that an android or modem image package // is available for delta update int set_fota_cookie_mtd(void) { size_t write_size; mtd_scan_partitions(); const MtdPartition *part = mtd_find_partition_by_name("FOTA"); if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { LOGE("Can't find FOTA\n"); return -1; } MtdReadContext *read = mtd_read_partition(part); if (read == NULL) { LOGE("Can't open FOTA\n(%s)\n", strerror(errno)); return -1; } ssize_t size = write_size; //writing 1 page is enough char data[size]; ssize_t r = mtd_read_data(read, data, size); if (r != size) LOGE("Can't read FOTA\n(%s)\n", strerror(errno)); mtd_read_close(read); if (r != size) return -1; //setting FOTA cookie value, 0x64645343 memset(data, 0x0, sizeof(data)); data[0] = 0x43; data[1] = 0x53; data[2] = 0x64; data[3] = 0x64; MtdWriteContext *write = mtd_write_partition(part); if (write == NULL) { LOGE("Can't open FOTA\n(%s)\n", strerror(errno)); return -1; } if (mtd_write_data(write, data, size) != size) { LOGE("Can't write FOTA\n(%s)\n", strerror(errno)); mtd_write_close(write); return -1; } if (mtd_write_close(write)) { LOGE("Can't finish FOTA\n(%s)\n", strerror(errno)); return -1; } LOGI("Set FOTA cookie done.\n"); return 0; }
int set_bootloader_message(const struct bootloader_message *in) { size_t write_size; const MtdPartition *part = get_root_mtd_partition(MISC_NAME); if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { LOGE("Can't find %s\n", MISC_NAME); return -1; } MtdReadContext *read = mtd_read_partition(part); if (read == NULL) { LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } ssize_t size = write_size * MISC_PAGES; char data[size]; ssize_t r = mtd_read_data(read, data, size); if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); mtd_read_close(read); if (r != size) return -1; memcpy(&data[write_size * MISC_COMMAND_PAGE], in, sizeof(*in)); #ifdef LOG_VERBOSE printf("\n--- set_bootloader_message ---\n"); dump_data(data, size); printf("\n"); #endif MtdWriteContext *write = mtd_write_partition(part); if (write == NULL) { LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } if (mtd_write_data(write, data, size) != size) { LOGE("Can't write %s\n(%s)\n", MISC_NAME, strerror(errno)); mtd_write_close(write); return -1; } if (mtd_write_close(write)) { LOGE("Can't finish %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } LOGI("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : ""); return 0; }
static int LoadPartitionContents(const char* filename, FileContents* file) { char* copy = strdup(filename); const char* magic = strtok(copy, ":"); enum PartitionType type; if (strcmp(magic, "MTD") == 0) { type = MTD; } else if (strcmp(magic, "EMMC") == 0) { type = EMMC; } else { printf("LoadPartitionContents called with bad filename (%s)\n", filename); return -1; } const char* partition = strtok(NULL, ":"); int i; int colons = 0; for (i = 0; filename[i] != '\0'; ++i) { if (filename[i] == ':') { ++colons; } } if (colons < 3 || colons%2 == 0) { printf("LoadPartitionContents called with bad filename (%s)\n", filename); } int pairs = (colons-1)/2; // # of (size,sha1) pairs in filename int* index = malloc(pairs * sizeof(int)); size_t* size = malloc(pairs * sizeof(size_t)); char** sha1sum = malloc(pairs * sizeof(char*)); for (i = 0; i < pairs; ++i) { const char* size_str = strtok(NULL, ":"); size[i] = strtol(size_str, NULL, 10); if (size[i] == 0) { printf("LoadPartitionContents called with bad size (%s)\n", filename); return -1; } sha1sum[i] = strtok(NULL, ":"); index[i] = i; } // sort the index[] array so it indexes the pairs in order of // increasing size. size_array = size; qsort(index, pairs, sizeof(int), compare_size_indices); MtdReadContext* ctx = NULL; FILE* dev = NULL; switch (type) { case MTD: if (!mtd_partitions_scanned) { mtd_scan_partitions(); mtd_partitions_scanned = 1; } const MtdPartition* mtd = mtd_find_partition_by_name(partition); if (mtd == NULL) { printf("mtd partition \"%s\" not found (loading %s)\n", partition, filename); return -1; } ctx = mtd_read_partition(mtd); if (ctx == NULL) { printf("failed to initialize read of mtd partition \"%s\"\n", partition); return -1; } break; case EMMC: dev = fopen(partition, "rb"); if (dev == NULL) { printf("failed to open emmc partition \"%s\": %s\n", partition, strerror(errno)); return -1; } } SHA_CTX sha_ctx; SHA_init(&sha_ctx); uint8_t parsed_sha[SHA_DIGEST_SIZE]; // allocate enough memory to hold the largest size. file->data = malloc(size[index[pairs-1]]); char* p = (char*)file->data; file->size = 0; // # bytes read so far for (i = 0; i < pairs; ++i) { // Read enough additional bytes to get us up to the next size // (again, we're trying the possibilities in order of increasing // size). size_t next = size[index[i]] - file->size; size_t read = 0; if (next > 0) { switch (type) { case MTD: read = mtd_read_data(ctx, p, next); break; case EMMC: read = fread(p, 1, next, dev); break; } if (next != read) { printf("short read (%zu bytes of %zu) for partition \"%s\"\n", read, next, partition); free(file->data); file->data = NULL; return -1; } SHA_update(&sha_ctx, p, read); file->size += read; } // Duplicate the SHA context and finalize the duplicate so we can // check it against this pair's expected hash. SHA_CTX temp_ctx; memcpy(&temp_ctx, &sha_ctx, sizeof(SHA_CTX)); const uint8_t* sha_so_far = SHA_final(&temp_ctx); if (ParseSha1(sha1sum[index[i]], parsed_sha) != 0) { printf("failed to parse sha1 %s in %s\n", sha1sum[index[i]], filename); free(file->data); file->data = NULL; return -1; } if (memcmp(sha_so_far, parsed_sha, SHA_DIGEST_SIZE) == 0) { // we have a match. stop reading the partition; we'll return // the data we've read so far. printf("partition read matched size %zu sha %s\n", size[index[i]], sha1sum[index[i]]); break; } p += read; } switch (type) { case MTD: mtd_read_close(ctx); break; case EMMC: fclose(dev); break; } if (i == pairs) { // Ran off the end of the list of (size,sha1) pairs without // finding a match. printf("contents of partition \"%s\" didn't match %s\n", partition, filename); free(file->data); file->data = NULL; return -1; } const uint8_t* sha_final = SHA_final(&sha_ctx); for (i = 0; i < SHA_DIGEST_SIZE; ++i) { file->sha1[i] = sha_final[i]; } // Fake some stat() info. file->st.st_mode = 0644; file->st.st_uid = 0; file->st.st_gid = 0; free(copy); free(index); free(size); free(sha1sum); return 0; }
int cmd_mtd_restore_raw_partition (const char *partition_name, const char *filename) { const MtdPartition *ptn; MtdWriteContext *write; void *data; unsigned sz; if (mtd_scan_partitions () <= 0) { printf ("error scanning partitions"); return -1; } const MtdPartition *partition = mtd_find_partition_by_name (partition_name); if (partition == NULL) { printf ("can't find %s partition", partition_name); return -1; } // If the first part of the file matches the partition, skip writing int fd = open (filename, O_RDONLY); if (fd < 0) { printf ("error opening %s", filename); return -1; } char header[HEADER_SIZE]; int headerlen = read (fd, header, sizeof (header)); if (headerlen <= 0) { printf ("error reading %s header", filename); return -1; } MtdReadContext *in = mtd_read_partition (partition); if (in == NULL) { printf ("error opening %s: %s\n", partition, strerror (errno)); // just assume it needs re-writing } else { char check[HEADER_SIZE]; int checklen = mtd_read_data (in, check, sizeof (check)); if (checklen <= 0) { printf ("error reading %s: %s\n", partition_name, strerror (errno)); // just assume it needs re-writing } else if (checklen == headerlen && !memcmp (header, check, headerlen)) { printf ("header is the same, not flashing %s\n", partition_name); return 0; } mtd_read_close (in); } // Skip the header (we'll come back to it), write everything else printf ("flashing %s from %s\n", partition_name, filename); MtdWriteContext *out = mtd_write_partition (partition); if (out == NULL) { printf ("error writing %s", partition_name); return -1; } char buf[HEADER_SIZE]; memset (buf, 0, headerlen); int wrote = mtd_write_data (out, buf, headerlen); if (wrote != headerlen) { printf ("error writing %s", partition_name); return -1; } int len; while ((len = read (fd, buf, sizeof (buf))) > 0) { wrote = mtd_write_data (out, buf, len); if (wrote != len) { printf ("error writing %s", partition_name); return -1; } } if (len < 0) { printf ("error reading %s", filename); return -1; } if (mtd_write_close (out)) { printf ("error closing %s", partition_name); return -1; } // Now come back and write the header last out = mtd_write_partition (partition); if (out == NULL) { printf ("error re-opening %s", partition_name); return -1; } wrote = mtd_write_data (out, header, headerlen); if (wrote != headerlen) { printf ("error re-writing %s", partition_name); return -1; } // Need to write a complete block, so write the rest of the first block size_t block_size; if (mtd_partition_info (partition, NULL, &block_size, NULL)) { printf ("error getting %s block size", partition_name); return -1; } if (lseek (fd, headerlen, SEEK_SET) != headerlen) { printf ("error rewinding %s", filename); return -1; } int left = block_size - headerlen; while (left < 0) left += block_size; while (left > 0) { len = read (fd, buf, left > (int) sizeof (buf) ? (int) sizeof (buf) : left); if (len <= 0) { printf ("error reading %s", filename); return -1; } if (mtd_write_data (out, buf, len) != len) { printf ("error writing %s", partition_name); return -1; } left -= len; } if (mtd_write_close (out)) { printf ("error closing %s", partition_name); return -1; } return 0; }
int set_bootloader_message(const struct bootloader_message *in) { // INFO("Enter set_bootloader_message\n"); if(in->command[0] != 0) { LOGI("command:\n%s\n", in->command); LOGI("status:\n%s\n", in->status); LOGI("recovery:\n%s\n", in->recovery); } else LOGI("bootloader_message is empty\n"); size_t write_size; const MtdPartition *part = get_root_mtd_partition(MISC_NAME); if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) { LOGE("Can't find %s\n", MISC_NAME); return -1; } MtdReadContext *read = mtd_read_partition(part); if (read == NULL) { LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } //cmy: 以sector为单位 ssize_t size = write_size * MISC_PAGES; char data[size<<9];//cmy ssize_t r = mtd_read_data(read, data, size); if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno)); mtd_read_close(read); if (r != size) return -1; memcpy(&data[(write_size<<9) * MISC_COMMAND_PAGE], in, sizeof(*in)); #ifdef LOG_VERBOSE printf("\n--- set_bootloader_message ---\n"); dump_data(data, size<<9); printf("\n"); #endif // INFO("\n--- set_bootloader_message ---\n"); // dump_data(data, size); // INFO("\n"); // CMY:由于底层写数据时会自动执行擦除操作,因些我们可以直接写数据而不考虑擦除动作 #if 1 MtdWriteContext *write = mtd_write_partition(part); if (write == NULL) { LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } LOGI("Write bootloader message\n"); if (mtd_write_data(write, data, size) != size) { LOGE("Can't write %s\n(%s)\n", MISC_NAME, strerror(errno)); mtd_write_close(write); return -1; } if (mtd_write_close(write)) { LOGE("Can't finish %s\n(%s)\n", MISC_NAME, strerror(errno)); return -1; } #endif LOGI("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : ""); return 0; }
/* Read an image file and write it to a flash partition. */ int main(int argc, char **argv) { const MtdPartition *ptn; MtdWriteContext *write; void *data; unsigned sz; int i; char *partitionName = NULL, *imageFile = NULL; int deleteImage = 0; if (argc < 3) { printUsage(argv[0]); return 2; } partitionName = argv[1]; imageFile = argv[2]; if (partitionName == NULL || imageFile == NULL) { printUsage(argv[0]); return 2; } if (mtd_scan_partitions() <= 0) die("error scanning partitions"); const MtdPartition *partition = mtd_find_partition_by_name(partitionName); if (partition == NULL) die("can't find %s partition", partitionName); // If the first part of the file matches the partition, skip writing int fd = open(imageFile, O_RDONLY); if (fd < 0) die("error opening %s", imageFile); char header[HEADER_SIZE]; int headerlen = read(fd, header, sizeof(header)); if (headerlen <= 0) die("error reading %s header", imageFile); MtdReadContext *in = mtd_read_partition(partition); if (in == NULL) { LOGW("error opening %s: %s\n", partitionName, strerror(errno)); // just assume it needs re-writing } else { char check[HEADER_SIZE]; int checklen = mtd_read_data(in, check, sizeof(check)); if (checklen <= 0) { LOGW("error reading %s: %s\n", partitionName, strerror(errno)); // just assume it needs re-writing } else if (checklen == headerlen && !memcmp(header, check, headerlen)) { LOGI("header is the same, not flashing %s\n", argv[1]); if (deleteImage) unlink(imageFile); return 0; } mtd_read_close(in); } // Skip the header (we'll come back to it), write everything else LOGI("flashing %s from %s\n", partitionName, imageFile); MtdWriteContext *out = mtd_write_partition(partition); if (out == NULL) die("error writing %s", partitionName); char buf[HEADER_SIZE]; memset(buf, 0, headerlen); int wrote = mtd_write_data(out, buf, headerlen); if (wrote != headerlen) die("error writing %s", partitionName); int len; while ((len = read(fd, buf, sizeof(buf))) > 0) { wrote = mtd_write_data(out, buf, len); if (wrote != len) die("error writing %s", partitionName); } if (len < 0) die("error reading %s", imageFile); if (mtd_write_close(out)) die("error closing %s", partitionName); // Now come back and write the header last out = mtd_write_partition(partition); if (out == NULL) die("error re-opening %s", partitionName); wrote = mtd_write_data(out, header, headerlen); if (wrote != headerlen) die("error re-writing %s", partitionName); // Need to write a complete block, so write the rest of the first block size_t block_size; if (mtd_partition_info(partition, NULL, &block_size, NULL)) die("error getting %s block size", partitionName); if (lseek(fd, headerlen, SEEK_SET) != headerlen) die("error rewinding %s", imageFile); int left = block_size - headerlen; while (left < 0) left += block_size; while (left > 0) { len = read(fd, buf, left > (int)sizeof(buf) ? (int)sizeof(buf) : left); if (len <= 0) die("error reading %s", imageFile); if (mtd_write_data(out, buf, len) != len) die("error writing %s", partitionName); left -= len; } if (mtd_write_close(out)) die("error closing %s", partitionName); if (deleteImage) unlink(imageFile); return 0; }
int main(int argc, char **argv) { const MtdPartition *ptn; MtdWriteContext *write; void *data; unsigned sz; LOGI("enter\n"); if (argc != 3) { LOGI("exit1\n"); fprintf(stderr, "usage: %s partition file.img\n", argv[0]); return 2; } int fd = open(argv[2], O_RDONLY); if (fd < 0) die("error opening %s", argv[2]); close(fd); if (mtd_scan_partitions() <= 0) die("error scanning partitions"); const MtdPartition *partition = mtd_find_partition_by_name(argv[1]); if (partition == NULL) die("can't find %s partition", argv[1]); LOGI("flashing %s from %s\n", argv[1], argv[2]); if( 0 == write_recovery(argv[2], argv[1]) ) { if( remove(argv[2]) == 0 ) LOGI("flash success!\n"); else die("error remove file: %s", argv[2]); } else die("error closing %s", argv[1]); #if 0 const MtdPartition *partition = mtd_find_partition_by_name(argv[1]); if (partition == NULL) die("can't find %s partition", argv[1]); // If the first part of the file matches the partition, skip writing int fd = open(argv[2], O_RDONLY); if (fd < 0) die("error opening %s", argv[2]); LOGI("read header!\n"); char header[HEADER_SIZE]; int headerlen = read(fd, header, sizeof(header)); if (headerlen <= 0) die("error reading %s header", argv[2]); MtdReadContext *in = mtd_read_partition(partition); if (in == NULL) { LOGW("error opening %s: %s\n", argv[1], strerror(errno)); // just assume it needs re-writing } else { LOGI("mtd_read_data\n"); char check[HEADER_SIZE]; int checklen = mtd_read_data(in, check, sizeof(check)); if (checklen <= 0) { LOGW("error reading %s: %s\n", argv[1], strerror(errno)); // just assume it needs re-writing } else if (checklen == headerlen && !memcmp(header, check, headerlen)) { LOGI("header is the same, not flashing %s\n", argv[1]); return 0; } mtd_read_close(in); } // Skip the header (we'll come back to it), write everything else LOGI("flashing %s from %s\n", argv[1], argv[2]); MtdWriteContext *out = mtd_write_partition(partition); if (out == NULL) die("error writing %s", argv[1]); char buf[HEADER_SIZE]; memset(buf, 0, headerlen); int wrote = mtd_write_data(out, buf, headerlen); if (wrote != headerlen) die("error writing %s", argv[1]); int len; while ((len = read(fd, buf, sizeof(buf))) > 0) { wrote = mtd_write_data(out, buf, len); if (wrote != len) die("error writing %s", argv[1]); } if (len < 0) die("error reading %s", argv[2]); if (mtd_write_close(out)) die("error closing %s", argv[1]); // Now come back and write the header last out = mtd_write_partition(partition); if (out == NULL) die("error re-opening %s", argv[1]); wrote = mtd_write_data(out, header, headerlen); if (wrote != headerlen) die("error re-writing %s", argv[1]); // Need to write a complete block, so write the rest of the first block size_t block_size; if (mtd_partition_info(partition, NULL, &block_size, NULL)) die("error getting %s block size", argv[1]); if (lseek(fd, headerlen, SEEK_SET) != headerlen) die("error rewinding %s", argv[2]); int left = block_size - headerlen; while (left < 0) left += block_size; while (left > 0) { len = read(fd, buf, left > (int)sizeof(buf) ? (int)sizeof(buf) : left); if (len <= 0) die("error reading %s", argv[2]); if (mtd_write_data(out, buf, len) != len) die("error writing %s", argv[1]); left -= len; } if (mtd_write_close(out)) die("error closing %s", argv[1]); #endif return 0; }
static int LoadPartitionContents(const char* filename, FileContents* file) { std::string copy(filename); std::vector<std::string> pieces = android::base::Split(copy, ":"); if (pieces.size() < 4 || pieces.size() % 2 != 0) { printf("LoadPartitionContents called with bad filename (%s)\n", filename); return -1; } enum PartitionType type; if (pieces[0] == "MTD") { type = MTD; } else if (pieces[0] == "EMMC") { type = EMMC; } else { printf("LoadPartitionContents called with bad filename (%s)\n", filename); return -1; } const char* partition = pieces[1].c_str(); size_t pairs = (pieces.size() - 2) / 2; // # of (size, sha1) pairs in filename std::vector<size_t> index(pairs); std::vector<size_t> size(pairs); std::vector<std::string> sha1sum(pairs); for (size_t i = 0; i < pairs; ++i) { size[i] = strtol(pieces[i*2+2].c_str(), NULL, 10); if (size[i] == 0) { printf("LoadPartitionContents called with bad size (%s)\n", filename); return -1; } sha1sum[i] = pieces[i*2+3].c_str(); index[i] = i; } // Sort the index[] array so it indexes the pairs in order of increasing size. sort(index.begin(), index.end(), [&](const size_t& i, const size_t& j) { return (size[i] < size[j]); } ); MtdReadContext* ctx = NULL; FILE* dev = NULL; switch (type) { case MTD: { if (!mtd_partitions_scanned) { mtd_scan_partitions(); mtd_partitions_scanned = true; } const MtdPartition* mtd = mtd_find_partition_by_name(partition); if (mtd == NULL) { printf("mtd partition \"%s\" not found (loading %s)\n", partition, filename); return -1; } ctx = mtd_read_partition(mtd); if (ctx == NULL) { printf("failed to initialize read of mtd partition \"%s\"\n", partition); return -1; } break; } case EMMC: dev = fopen(partition, "rb"); if (dev == NULL) { printf("failed to open emmc partition \"%s\": %s\n", partition, strerror(errno)); return -1; } } SHA_CTX sha_ctx; SHA_init(&sha_ctx); uint8_t parsed_sha[SHA_DIGEST_SIZE]; // Allocate enough memory to hold the largest size. file->data = reinterpret_cast<unsigned char*>(malloc(size[index[pairs-1]])); char* p = (char*)file->data; file->size = 0; // # bytes read so far bool found = false; for (size_t i = 0; i < pairs; ++i) { // Read enough additional bytes to get us up to the next size. (Again, // we're trying the possibilities in order of increasing size). size_t next = size[index[i]] - file->size; size_t read = 0; if (next > 0) { switch (type) { case MTD: read = mtd_read_data(ctx, p, next); break; case EMMC: read = fread(p, 1, next, dev); break; } if (next != read) { printf("short read (%zu bytes of %zu) for partition \"%s\"\n", read, next, partition); free(file->data); file->data = NULL; return -1; } SHA_update(&sha_ctx, p, read); file->size += read; } // Duplicate the SHA context and finalize the duplicate so we can // check it against this pair's expected hash. SHA_CTX temp_ctx; memcpy(&temp_ctx, &sha_ctx, sizeof(SHA_CTX)); const uint8_t* sha_so_far = SHA_final(&temp_ctx); if (ParseSha1(sha1sum[index[i]].c_str(), parsed_sha) != 0) { printf("failed to parse sha1 %s in %s\n", sha1sum[index[i]].c_str(), filename); free(file->data); file->data = NULL; return -1; } if (memcmp(sha_so_far, parsed_sha, SHA_DIGEST_SIZE) == 0) { // we have a match. stop reading the partition; we'll return // the data we've read so far. printf("partition read matched size %zu sha %s\n", size[index[i]], sha1sum[index[i]].c_str()); found = true; break; } p += read; } switch (type) { case MTD: mtd_read_close(ctx); break; case EMMC: fclose(dev); break; } if (!found) { // Ran off the end of the list of (size,sha1) pairs without finding a match. printf("contents of partition \"%s\" didn't match %s\n", partition, filename); free(file->data); file->data = NULL; return -1; } const uint8_t* sha_final = SHA_final(&sha_ctx); for (size_t i = 0; i < SHA_DIGEST_SIZE; ++i) { file->sha1[i] = sha_final[i]; } // Fake some stat() info. file->st.st_mode = 0644; file->st.st_uid = 0; file->st.st_gid = 0; return 0; }
int main(int argc, char **argv) { const MtdPartition *ptn; MtdWriteContext *write; void *data; unsigned sz; if (argc != 4) { fprintf(stderr, "usage: %s type [partition|device] [image_file_path]\n", argv[0]); return 2; } if (0 == strcmp("MTD", argv[1])) { if (mtd_scan_partitions() <= 0) die("error scanning partitions"); const MtdPartition *partition = mtd_find_partition_by_name(argv[1]); if (partition == NULL) die("can't find %s partition", argv[1]); // If the first part of the file matches the partition, skip writing int fd = open(argv[2], O_RDONLY); if (fd < 0) die("error opening %s", argv[2]); char header[HEADER_SIZE]; int headerlen = read(fd, header, sizeof(header)); if (headerlen <= 0) die("error reading %s header", argv[2]); MtdReadContext *in = mtd_read_partition(partition); if (in == NULL) { LOGW("error opening %s: %s\n", argv[1], strerror(errno)); // just assume it needs re-writing } else { char check[HEADER_SIZE]; int checklen = mtd_read_data(in, check, sizeof(check)); if (checklen <= 0) { LOGW("error reading %s: %s\n", argv[1], strerror(errno)); // just assume it needs re-writing } else if (checklen == headerlen && !memcmp(header, check, headerlen)) { LOGI("header is the same, not flashing %s\n", argv[1]); return 0; } mtd_read_close(in); } // Skip the header (we'll come back to it), write everything else LOGI("flashing %s from %s\n", argv[1], argv[2]); MtdWriteContext *out = mtd_write_partition(partition); if (out == NULL) die("error writing %s", argv[1]); char buf[HEADER_SIZE]; memset(buf, 0, headerlen); int wrote = mtd_write_data(out, buf, headerlen); if (wrote != headerlen) die("error writing %s", argv[1]); int len; while ((len = read(fd, buf, sizeof(buf))) > 0) { wrote = mtd_write_data(out, buf, len); if (wrote != len) die("error writing %s", argv[1]); } if (len < 0) die("error reading %s", argv[2]); if (mtd_write_close(out)) die("error closing %s", argv[1]); // Now come back and write the header last out = mtd_write_partition(partition); if (out == NULL) die("error re-opening %s", argv[1]); wrote = mtd_write_data(out, header, headerlen); if (wrote != headerlen) die("error re-writing %s", argv[1]); // Need to write a complete block, so write the rest of the first block size_t block_size; if (mtd_partition_info(partition, NULL, &block_size, NULL)) die("error getting %s block size", argv[1]); if (lseek(fd, headerlen, SEEK_SET) != headerlen) die("error rewinding %s", argv[2]); int left = block_size - headerlen; while (left < 0) left += block_size; while (left > 0) { len = read(fd, buf, left > (int)sizeof(buf) ? (int)sizeof(buf) : left); if (len == 0) break; if (len < 0) die("error reading %s", argv[2]); if (mtd_write_data(out, buf, len) != len) die("error writing %s", argv[1]); left -= len; } // If there is more to write, input data was less than block_size, so pad // with nulls. memset(buf, 0, sizeof(buf)); while (left > 0) { int pad_len = left > (int)sizeof(buf) ? (int)sizeof(buf) : left; if (mtd_write_data(out, buf, pad_len) != pad_len) die("error writing %s", argv[1]); left -= pad_len; } if (mtd_write_close(out)) die("error closing %s", argv[1]); return 0; } else if (0 == strcmp("EMMC", argv[1]) || 0 == strcmp("INAND",argv[1])) { int fd = open(argv[3], O_RDONLY); if (fd < 0) die("error opening %s", argv[3]); char header[HEADER_SIZE]; int headerlen = read(fd, header, sizeof(header)); if (headerlen != sizeof(header)) die("error reading %s header", argv[3]); FILE* f = fopen(argv[2], "rb"); if (f == NULL ) die("error opening %s", argv[2]); char check[HEADER_SIZE]; int checklen = fread(&check, 1, sizeof(check), f); if (checklen != sizeof(check)) die("error reading %s header", argv[3]); fclose(f); if(!memcmp(header, check, headerlen)) { printf("header is the same, not flashing %s\n", argv[2]); close(fd); return 0; } f = fopen(argv[2], "wb"); char buf[HEADER_SIZE]; int wrote = fwrite(header, sizeof(header), 1, f); if (wrote != 1) { close(fd); fclose(f); die("error writing %s", argv[2]); } int len; while ((len = read(fd, buf, sizeof(buf))) > 0) { wrote = fwrite(buf, sizeof(buf), 1, f); if (wrote != 1) { close(fd); fclose(f); die("error writing %s", argv[2]); } } if (len < 0) { close(fd); fclose(f); die("error reading %s", argv[3]); } close(fd); fclose(f); } else { die("wrong type %s, it should be MTD or EMMC", argv[1]); } printf("flash image %s to %s successfully\n", argv[3], argv[2] ); return 0; }
int main(int argc, char **argv) { const MtdPartition *ptn; MtdWriteContext *write; void *data; unsigned sz; int rc = 0; if (argc != 3) { fprintf(stderr, "usage: %s partition file.img\n", argv[0]); return -EINVAL; } rc = mtd_scan_partitions(); if (rc < 0) { fprintf(stderr, "error scanning partitions\n"); return rc; } else if (rc == 0) { fprintf(stderr, "no partitions found\n"); return -ENODEV; } const MtdPartition *partition = mtd_find_partition_by_name(argv[1]); if (partition == NULL) { fprintf(stderr, "can't find %s partition\n", argv[1]); return -ENODEV; } // If the first part of the file matches the partition, skip writing int fd = open(argv[2], O_RDONLY); if (fd < 0) { fprintf(stderr, "error opening %s\n", argv[2]); return fd; } char header[HEADER_SIZE]; int headerlen = TEMP_FAILURE_RETRY(read(fd, header, sizeof(header))); if (headerlen <= 0) { fprintf(stderr, "error reading %s header\n", argv[2]); rc = -EIO; goto exit; } MtdReadContext *in = mtd_read_partition(partition); if (in == NULL) { fprintf(stderr, "error opening %s: %s\n", argv[1], strerror(errno)); rc = -ENXIO; goto exit; // just assume it needs re-writing } else { char check[HEADER_SIZE]; int checklen = mtd_read_data(in, check, sizeof(check)); if (checklen <= 0) { fprintf(stderr, "error reading %s: %s\n", argv[1], strerror(errno)); rc = -EIO; goto exit; // just assume it needs re-writing } else if (checklen == headerlen && !memcmp(header, check, headerlen)) { fprintf(stderr, "header is the same, not flashing %s\n", argv[1]); rc = -EINVAL; goto exit; } mtd_read_close(in); } // Skip the header (we'll come back to it), write everything else printf("flashing %s from %s\n", argv[1], argv[2]); MtdWriteContext *out = mtd_write_partition(partition); if (out == NULL) { fprintf(stderr, "error writing %s\n", argv[1]); rc = -EIO; goto exit; } char buf[HEADER_SIZE]; memset(buf, 0, headerlen); int wrote = mtd_write_data(out, buf, headerlen); if (wrote != headerlen) { fprintf(stderr, "error writing %s\n", argv[1]); rc = -EIO; goto exit; } int len; while ((len = TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf)))) > 0) { wrote = mtd_write_data(out, buf, len); if (wrote != len) { fprintf(stderr, "error writing %s\n", argv[1]); rc = -EIO; goto exit; } } if (len < 0) { fprintf(stderr, "error reading %s\n", argv[2]); rc = -EIO; goto exit; } rc = mtd_write_close(out); if (rc < 0) { fprintf(stderr, "error closing %s\n", argv[1]); goto exit; } // Now come back and write the header last out = mtd_write_partition(partition); if (out == NULL) { fprintf(stderr, "error re-opening %s\n", argv[1]); rc = -EIO; goto exit; } wrote = mtd_write_data(out, header, headerlen); if (wrote != headerlen) { fprintf(stderr, "error re-writing %s\n", argv[1]); rc = -EIO; goto exit; } // Need to write a complete block, so write the rest of the first block size_t block_size; rc = mtd_partition_info(partition, NULL, &block_size, NULL); if (rc < 0) { fprintf(stderr, "error getting %s block size\n", argv[1]); goto exit; } if (TEMP_FAILURE_RETRY(lseek(fd, headerlen, SEEK_SET)) != headerlen) { fprintf(stderr, "error rewinding %s\n", argv[2]); rc = -ESPIPE; goto exit; } int left = block_size - headerlen; while (left < 0) left += block_size; while (left > 0) { len = TEMP_FAILURE_RETRY(read(fd, buf, left > (int)sizeof(buf) ? (int)sizeof(buf) : left)); if (len <= 0) { fprintf(stderr, "error reading %s\n", argv[2]); rc = -EIO; goto exit; } if (mtd_write_data(out, buf, len) != len) { fprintf(stderr, "error writing %s\n", argv[1]); rc = -EIO; goto exit; } left -= len; } rc = mtd_write_close(out); if (rc < 0) { fprintf(stderr, "error closing %s\n", argv[1]); goto exit; } rc = 0; exit: close(fd); return rc; }