1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/* cmd/sbc_harness/tests/test_ihex.c - Tests for ihex.c
*
* Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <stdio.h> /* for putchar() */
#include <string.h>
#include <libmisc/fmt.h>
#include "ihex.h"
struct stdout { size_t len; };
LO_IMPLEMENTATION_STATIC(fmt_dest, struct stdout, stdout);
static void stdout_putb(struct stdout *self, uint8_t b) {
putchar(b);
self->len++;
}
static size_t stdout_tell(struct stdout *self) {
return self->len;
}
static lo_interface fmt_dest fmt_stdout = lo_box_stdout_as_fmt_dest(&((struct stdout){}));
#define test_assert(expr) do { \
if (!(expr)) \
fmt_print( \
fmt_stdout, \
"test failure: ", __FILE__, ":", __LINE__, ":", __func__, \
": " #expr "\n"); \
} while (0)
static char *input =
/* ,-byte count
* | ,-address
* | | ,-record type
* | | | ,- checksum
*[][--][][..............................][]\r\n */
":020000041000EA\r\n" /* base_addr = linear(0x1000) = 0x1000<<16 */
":1000000000B5324B212058609868022188439860DF\r\n" /* memcpy(chip[base_addr+0x0000], "\x00\xB5\x32\x4B\x21\x20\x58\x60\x98\x68\x02\x21\x88\x43\x98\x60", 16) */
":10001000D860186158612E4B002199600221596106\r\n" /* memcpy(chip[base_addr+0x0010], "\xD8\x60\x18\x61\x58\x61\x2E\x4B\x00\x21\x99\x60\x02\x21\x59\x61", 16) */
":10BE9C000000000000000000000000000000000096\r\n" /* memcpy(chip[base_addr+0xBE9C], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) */
":04BEAC00CC4A00205C\r\n" /* memcpy(chip[base_addr+0xBEAC], "\x00\xCC\x4A\x00\x20", 5) */
":04000005100001E9FD\r\n" /* start_exec_at = linear(0x100001E9) */
":00000001FF\r\n"; /* EOF */
static int cnt = 0;
static error handle_data(void *, uint32_t off, uint8_t count, uint8_t *dat) {
switch (cnt) {
case 0:
test_assert(off == UINT32_C(0x10000000));
test_assert(count == 16);
test_assert(memcmp(dat, "\x00\xB5\x32\x4B\x21\x20\x58\x60\x98\x68\x02\x21\x88\x43\x98\x60", 16) == 0);
break;
case 1:
test_assert(off == UINT32_C(0x10000010));
test_assert(count == 16);
test_assert(memcmp(dat, "\xD8\x60\x18\x61\x58\x61\x2E\x4B\x00\x21\x99\x60\x02\x21\x59\x61", 16) == 0);
break;
case 2:
test_assert(off == UINT32_C(0x1000BE9C));
test_assert(count == 16);
test_assert(memcmp(dat, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0);
break;
case 4:
test_assert(off == UINT32_C(0x1000BE9C));
test_assert(count == 5);
test_assert(memcmp(dat, "\x00\xCC\x4A\x00\x20", 5) == 0);
break;
default:
test_assert(false);
}
cnt++;
return ERROR_NULL;
}
static error handle_set_exec_start_seg(void *, uint16_t LM_UNUSED(cs), uint16_t LM_UNUSED(ip)) {
switch (cnt) {
default:
test_assert(false);
}
cnt++;
return ERROR_NULL;
}
static error handle_set_exec_start_lin(void *, uint32_t eip) {
switch (cnt) {
case 5:
test_assert(eip == UINT32_C(0x100001E9));
break;
default:
test_assert(false);
}
cnt++;
return ERROR_NULL;
}
static error handle_eof(void *) {
switch (cnt) {
case 6:
break;
default:
test_assert(false);
}
cnt++;
return ERROR_NULL;
}
int main() {
struct ihex_decoder dec = {
.handle_data = handle_data,
.handle_set_exec_start_seg = handle_set_exec_start_seg,
.handle_set_exec_start_lin = handle_set_exec_start_lin,
.handle_eof = handle_eof,
};
size_t_and_error ret = ihex_decoder_writev(&dec, &((struct iovec){
.iov_base = input,
.iov_len = strlen(input),
}), 1);
fmt_print(fmt_stdout,
"ret = (", ret.size_t, ", ", (error, ret.err), ")\n",
"cnt = ", cnt, "\n");
test_assert(ret.size_t == strlen(input));
test_assert(ERROR_IS_NULL(ret.err));
test_assert(cnt == 6);
return 0;
}
|