-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial implementation for bitstream file parser
- Loading branch information
Showing
3 changed files
with
231 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#ifndef _BIT_H | ||
#define _BIT_H | ||
|
||
#include <memory.h> | ||
|
||
struct bit { | ||
const void* data; | ||
size_t size; | ||
|
||
const char* ncd_filename; | ||
const char* part_name; | ||
const char* date; | ||
const char* time; | ||
size_t bit_length; | ||
|
||
const char* error_str; | ||
}; | ||
|
||
int bit_init(struct bit* bit, const void* data, size_t size); | ||
|
||
const char* bit_get_error_string(struct bit* bit); | ||
|
||
#endif // _BIT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
#include <bit.h> | ||
|
||
#include <stdint.h> | ||
#include <string.h> | ||
|
||
#include <arpa/inet.h> | ||
|
||
static int bit_do_parse_field1_2(struct bit* bit) { | ||
static const uint8_t header[] = {0x00,0x09,0x0f,0xf0,0x0f,0xf0,0x0f,0xf0,0x0f,0xf0,0x00,0x00,0x01}; | ||
|
||
if (bit->size < sizeof(header) || memcmp(bit->data, header, sizeof(header)) != 0) { | ||
bit->error_str = "Wrong bit header"; | ||
return -1; | ||
} | ||
|
||
bit->data += sizeof(header); | ||
bit->size -= sizeof(header); | ||
|
||
return 0; | ||
} | ||
|
||
static int bit_do_parse_field_str(struct bit* bit, uint8_t key, const char** str) { | ||
uint16_t len; | ||
|
||
if (bit->size < sizeof(key) + sizeof(len)) { | ||
bit->error_str = "Too few bytes"; | ||
return -1; | ||
} | ||
|
||
if (((uint8_t*)bit->data)[0] != key) { | ||
bit->error_str = "Incorrent field key"; | ||
return -1; | ||
} | ||
|
||
bit->data += sizeof(key); | ||
bit->size -= sizeof(key); | ||
|
||
memcpy(&len, bit->data, sizeof(len)); | ||
len = htons(len); | ||
|
||
bit->data += sizeof(len); | ||
bit->size -= sizeof(len); | ||
|
||
if (bit->size < len) { | ||
bit->error_str = "Too few bytes"; | ||
return -1; | ||
} | ||
|
||
/* string is null-terminated */ | ||
*str = bit->data; | ||
bit->data += len; | ||
bit->size -= len; | ||
|
||
return 0; | ||
} | ||
|
||
static int bit_do_parse_field2_3(struct bit* bit) { | ||
return bit_do_parse_field_str(bit, 'a', &bit->ncd_filename); | ||
} | ||
|
||
static int bit_do_parse_field4(struct bit* bit) { | ||
return bit_do_parse_field_str(bit, 'b', &bit->part_name); | ||
} | ||
|
||
static int bit_do_parse_field5(struct bit* bit) { | ||
return bit_do_parse_field_str(bit, 'c', &bit->date); | ||
} | ||
|
||
static int bit_do_parse_field6(struct bit* bit) { | ||
return bit_do_parse_field_str(bit, 'd', &bit->time); | ||
} | ||
|
||
static int bit_do_parse_field7(struct bit* bit) { | ||
uint32_t len; | ||
const uint8_t key = 'e'; | ||
|
||
if (bit->size < sizeof(key) + sizeof(len)) { | ||
bit->error_str = "Too few bytes"; | ||
return -1; | ||
} | ||
|
||
if (((uint8_t*)bit->data)[0] != key) { | ||
bit->error_str = "Incorrent field key"; | ||
return -1; | ||
} | ||
|
||
bit->data += sizeof(key); | ||
bit->size -= sizeof(key); | ||
|
||
memcpy(&len, bit->data, sizeof(len)); | ||
len = htonl(len); | ||
|
||
bit->bit_length = len; | ||
bit->data += sizeof(len); | ||
bit->size -= sizeof(len); | ||
|
||
if (bit->size < len) { | ||
bit->error_str = "Too few bytes"; | ||
return -1; | ||
} | ||
|
||
bit->data += len; | ||
bit->size -= len; | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* http://www.fpga-faq.com/FAQ_Pages/0026_Tell_me_about_bit_files.htm | ||
*/ | ||
static int bit_do_parse(struct bit* bit) { | ||
if (bit_do_parse_field1_2(bit) < 0) | ||
return -1; | ||
if (bit_do_parse_field2_3(bit) < 0) | ||
return -1; | ||
if (bit_do_parse_field4(bit) < 0) | ||
return -1; | ||
if (bit_do_parse_field5(bit) < 0) | ||
return -1; | ||
if (bit_do_parse_field6(bit) < 0) | ||
return -1; | ||
if (bit_do_parse_field7(bit) < 0) | ||
return -1; | ||
|
||
return 0; | ||
} | ||
|
||
int bit_init(struct bit* bit, const void* data, size_t size) { | ||
bit->data = data; | ||
bit->size = size; | ||
|
||
return bit_do_parse(bit); | ||
} | ||
|
||
const char* bit_get_error_string(struct bit* bit) { | ||
return bit->error_str; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#include <check.h> | ||
#include <stdlib.h> | ||
|
||
#include <bit.h> | ||
|
||
START_TEST (test_bit_init1) { | ||
static const uint8_t data[] = { | ||
0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61, 0x00, 0x0a, | ||
0x78, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x6e, 0x63, 0x64, 0x00, 0x62, 0x00, 0x0c, 0x76, 0x31, 0x30, | ||
0x30, 0x30, 0x65, 0x66, 0x67, 0x38, 0x36, 0x30, 0x00, 0x63, 0x00, 0x0b, 0x32, 0x30, 0x30, 0x31, | ||
0x2f, 0x30, 0x38, 0x2f, 0x31, 0x30, 0x00, 0x64, 0x00, 0x09, 0x30, 0x36, 0x3a, 0x35, 0x35, 0x3a, | ||
0x30, 0x34, 0x00, 0x65, 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff}; | ||
|
||
struct bit bit; | ||
ck_assert_int_eq(bit_init(&bit, data, sizeof(data)), 0); | ||
ck_assert_str_eq(bit.ncd_filename, "xform.ncd"); | ||
ck_assert_str_eq(bit.part_name, "v1000efg860"); | ||
ck_assert_str_eq(bit.date, "2001/08/10"); | ||
ck_assert_str_eq(bit.time, "06:55:04"); | ||
ck_assert_uint_eq(bit.bit_length, 4); | ||
} | ||
END_TEST | ||
|
||
START_TEST (test_bit_init2) { | ||
static const uint8_t data[] = { | ||
0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61, 0x00, 0x1a, | ||
0x6f, 0x76, 0x33, 0x2e, 0x6e, 0x63, 0x64, 0x3b, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x3d, 0x30, | ||
0x78, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x00, 0x62, 0x00, 0x0c, 0x36, 0x73, 0x6c, | ||
0x78, 0x39, 0x74, 0x71, 0x67, 0x31, 0x34, 0x34, 0x00, 0x63, 0x00, 0x0b, 0x32, 0x30, 0x31, 0x34, | ||
0x2f, 0x31, 0x31, 0x2f, 0x31, 0x30, 0x00, 0x64, 0x00, 0x09, 0x31, 0x36, 0x3a, 0x33, 0x31, 0x3a, | ||
0x30, 0x37, 0x00, 0x65, 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff}; | ||
|
||
struct bit bit; | ||
ck_assert_int_eq(bit_init(&bit, data, sizeof(data)), 0); | ||
ck_assert_str_eq(bit.ncd_filename, "ov3.ncd;UserID=0xFFFFFFFF"); | ||
ck_assert_str_eq(bit.part_name, "6slx9tqg144"); | ||
ck_assert_str_eq(bit.date, "2014/11/10"); | ||
ck_assert_str_eq(bit.time, "16:31:07"); | ||
ck_assert_uint_eq(bit.bit_length, 4); | ||
} | ||
END_TEST | ||
|
||
Suite* range_suite(void) { | ||
Suite *s; | ||
TCase *tc_core; | ||
|
||
s = suite_create("bit"); | ||
|
||
tc_core = tcase_create("Core"); | ||
|
||
tcase_add_test(tc_core, test_bit_init1); | ||
tcase_add_test(tc_core, test_bit_init2); | ||
suite_add_tcase(s, tc_core); | ||
|
||
return s; | ||
} | ||
|
||
int main(void) { | ||
int number_failed; | ||
Suite *s; | ||
SRunner *sr; | ||
|
||
s = range_suite(); | ||
sr = srunner_create(s); | ||
|
||
srunner_run_all(sr, CK_NORMAL); | ||
number_failed = srunner_ntests_failed(sr); | ||
srunner_free(sr); | ||
return (number_failed == 0) ? 0 : 1; | ||
} | ||
|