Exemple #1
0
static int bitfile_do_big_chunk(const struct firmware *fw, bitfile_chunk_t *chunk, int *i) {
    if (*i + 4 > fw->size) {
        HM2_PRINT_NO_LL("bitfile chunk extends past end of firmware\n");
        return -ENODATA;
    }

    chunk->size = ((__u32)fw->data[*i] << 24) + ((__u32)fw->data[*i + 1] << 16) + ((__u32)fw->data[*i + 2] << 8) + fw->data[*i + 3];
    (*i) += 4;

    if (*i + chunk->size > fw->size) {
        HM2_PRINT_NO_LL("bitfile chunk extends past end of firmware\n");
        return -ENODATA;
    }

    chunk->data = &fw->data[*i];
    (*i) += chunk->size;

    return 0;
}
static int bitfile_parse_and_verify_chunk(const struct firmware *fw, bitfile_t *bitfile, int *i) {
    char tag;

    tag = fw->data[*i];
    (*i) ++;

    if ((*i) > fw->size) {
        HM2_PRINT_NO_LL("bitfile chunk '%c' size fell off the end!\n", tag);
        return -ENODATA;
    }

    switch (tag) {
        case 'a':
            // Design name
            return bitfile_do_small_chunk(fw, &bitfile->a, i);

        case 'b':
            // Part ID
            return bitfile_do_small_chunk(fw, &bitfile->b, i);

        case 'c':
            // Design date
            return bitfile_do_small_chunk(fw, &bitfile->c, i);

        case 'd':
            // Design time
            return bitfile_do_small_chunk(fw, &bitfile->d, i);

        case 'e':
            return bitfile_do_big_chunk(fw, &bitfile->e, i);

        default: {
            HM2_PRINT_NO_LL("bitfile has unknown chunk '%c'\n", tag);
            break;
        }
    }

    // unknown chunks cause error, because we don't know if they're big or small
    return -EINVAL;
}
int bitfile_parse_and_verify(const struct firmware *fw, bitfile_t *bitfile) {
    int i;
    int r;

    const unsigned char bitfile_header[BITFILE_HEADERLEN] = {
        0x00, 0x09,
        0x0f, 0xf0, 0x0f, 0xf0,
        0x0f, 0xf0, 0x0f, 0xf0,
        0x00, 0x00, 0x01
    };


    //
    // initialize all the bitfile chunks
    //

    bitfile->a.size = 0;
    bitfile->a.data = NULL;

    bitfile->b.size = 0;
    bitfile->b.data = NULL;

    bitfile->c.size = 0;
    bitfile->c.data = NULL;

    bitfile->d.size = 0;
    bitfile->d.data = NULL;

    bitfile->e.size = 0;
    bitfile->e.data = NULL;


    // 
    // verify the header
    //

    if (fw->size < BITFILE_HEADERLEN) {
        HM2_PRINT_NO_LL("bitfile is too short\n");
        return -ENODATA;
    }

    for (i = 0; i < BITFILE_HEADERLEN; i ++) {
        if (fw->data[i] != bitfile_header[i]) {
            HM2_PRINT_NO_LL("bitfile has invalid header\n");
            return -EINVAL;
        }
    }


    // 
    // parse and verify all the chunks
    //

    while (i < fw->size) {
        r = bitfile_parse_and_verify_chunk(fw, bitfile, &i);
        if (r != 0) return r;
    }


    // 
    // make sure we got all the required chunks
    //

    if (bitfile->b.data == NULL) {
        HM2_PRINT_NO_LL("bitfile lacks Part Name (chunk 'b')!\n");
        return -EINVAL;
    }

    if (bitfile->e.data == NULL) {
        HM2_PRINT_NO_LL("bitfile lacks FPGA Config (part 'e')!\n");
        return -EINVAL;
    }


    // looks like a good bitfile
    return 0;
}