static int LoadPartitionContents(const char* filename, FileContents* file) { char* copy = strdup(filename); const char* magic = strtok(copy, ":"); enum PartitionType type; #if 0 //wschen 2012-05-24 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; } #else switch (phone_type()) { case NAND_TYPE: type = MTD; break; case EMMC_TYPE: type = EMMC; break; default: printf("LoadPartitionContents called with bad filename (%s)\n", filename); return -1; } #endif 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; int dev = -1; 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: printf("open emmc partition \"%s\"\n", partition); if (!strcmp(partition, "boot")) { dev = open("/dev/bootimg", O_RDWR); if (dev == -1) { printf("failed to open emmc partition \"/dev/bootimg\": %s\n", strerror(errno)); return -1; } } else { char dev_name[32]; strcpy(dev_name, "/dev/"); strcat(dev_name, partition); dev = open(dev_name, O_RDWR); if (dev == -1) { printf("failed to open emmc partition \"%s\": %s\n", dev_name, strerror(errno)); return -1; } } break; } 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_cnt = 0; if (next > 0) { switch (type) { case MTD: read_cnt = mtd_read_data(ctx, p, next); break; case EMMC: read_cnt = read(dev, p, next); break; } if (next != read_cnt) { printf("short read (%d bytes of %d) for partition \"%s\"\n", read_cnt, next, partition); free(file->data); file->data = NULL; return -1; } SHA_update(&sha_ctx, p, read_cnt); file->size += read_cnt; } // 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 %d sha %s\n", size[index[i]], sha1sum[index[i]]); break; } p += read_cnt; } switch (type) { case MTD: mtd_read_close(ctx); break; case EMMC: close(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; }
// Write a memory buffer to 'target' partition, a string of the form // "MTD:<partition>[:...]" or "EMMC:<partition_device>:". Return 0 on // success. int WriteToPartition(unsigned char* data, size_t len, const char* target) { char* copy = strdup(target); const char* magic = strtok(copy, ":"); enum PartitionType type; #if 0 //wschen 2012-05-24 if (strcmp(magic, "MTD") == 0) { type = MTD; } else if (strcmp(magic, "EMMC") == 0) { type = EMMC; } else { printf("WriteToPartition called with bad target (%s)\n", target); free(copy); return -1; } #else switch (phone_type()) { case NAND_TYPE: type = MTD; break; case EMMC_TYPE: type = EMMC; break; default: printf("WriteToPartition called with bad target (%s)\n", target); free(copy); return -1; } #endif const char* partition = strtok(NULL, ":"); if (partition == NULL) { printf("bad partition target name \"%s\"\n", target); free(copy); return -1; } 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 for writing\n", partition); free(copy); return -1; } MtdWriteContext* ctx = mtd_write_partition(mtd); if (ctx == NULL) { printf("failed to init mtd partition \"%s\" for writing\n", partition); free(copy); return -1; } size_t written = mtd_write_data(ctx, (char*)data, len); if (written != len) { printf("only wrote %d of %d bytes to MTD %s\n", written, len, partition); mtd_write_close(ctx); free(copy); return -1; } if (mtd_erase_blocks(ctx, -1) < 0) { printf("error finishing mtd write of %s\n", partition); mtd_write_close(ctx); free(copy); return -1; } if (mtd_write_close(ctx)) { printf("error closing mtd write of %s\n", partition); free(copy); return -1; } break; case EMMC: ; #if 0 //wschen 2011-11-29 FILE* f = fopen(partition, "wb"); if (fwrite(data, 1, len, f) != len) { printf("short write writing to %s (%s)\n", partition, strerror(errno)); free(copy); return -1; } if (fclose(f) != 0) { printf("error closing %s (%s)\n", partition, strerror(errno)); free(copy); return -1; } #else int dev; if (!strcmp(partition, "boot")) { dev = open("/dev/bootimg", O_RDWR | O_SYNC); if (dev == -1) { printf("failed to open emmc partition \"/dev/bootimg\": %s\n", strerror(errno)); free(copy); return -1; } } else { char dev_name[32]; snprintf(dev_name, sizeof(dev_name), "/dev/%s", partition); dev = open(dev_name, O_RDWR | O_SYNC); if (dev == -1) { printf("failed to open emmc partition \"%s\": %s\n", dev_name, strerror(errno)); free(copy); return -1; } } if (write(dev, data, len) != len) { printf("short write writing to %s (%s)\n", partition, strerror(errno)); close(dev); free(copy); return -1; } close(dev); sync(); #endif break; } free(copy); return 0; }
int phone_read (char *filename) /*------------------------------------------------------------* * read in the phone file filename *------------------------------------------------------------*/ { int32 retval = 0; FILE *fs = NULL; char phone_str[1024]; int32 phone_id = 0; int32 base_id = 0; int32 field1; int32 field2; int32 model_len, j; int32 tmp_num_phones; /* * Find #phones and set hash and list tables size hints. * (Otherwise, the simple-minded PC malloc library goes berserk.) */ fs = CM_fopen (filename, "r"); for (j = 1;; j++) if (fgets (phone_str, sizeof(phone_str), fs) == NULL) break; phones.size_hint = j; phones_list.size_hint = j; phone_base_map.size_hint = j; phone_model_len.size_hint = j; phone_type_map.size_hint = j; rewind(fs); while (EOF != fscanf (fs, "%s%d%d%d%d\n", phone_str, &field1, &field2, &base_id, &phone_id)) { /* * field1 is 0 for ciPhones */ if (field1 == 0) numCiPhones++; /* * Phones marked with a '-2' account for more than one model */ if (field1 == -2) { numWdPhones++; model_len = field2; } else model_len = 1; if (model_len <= 0) { E_WARN("%s has length %d\n", phone_str, model_len); } add_phone (phone_str, phone_id, base_id, field1, model_len); } tmp_num_phones = phone_id; /* * Next availiable phone id */ phone_id++; for (j = 0; j < tmp_num_phones; j++) { /* * If the phone is one of these within word phones then * create model_len-1 additional phones name ...(1) ...(2) and * and so on up to ...(model_len-1). It's these phones the * word refers to for it pronunciation */ if (phone_type(j) == -2) { int32 i; int32 model_len = phone_len (j); for (i = 1; i < model_len; i++) { char tmpstr[256]; sprintf (tmpstr, "%s(%d)", phone_from_id(j), i); add_phone (tmpstr, phone_id, j, 1000+i, 1); phone_id++; } } } mk_phone_map(); if (fs) fclose (fs); return (retval); }