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; }