Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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);
}