]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/ihex.c
ihex.c fix memory alloc
[z180-stamp.git] / avr / ihex.c
1 /*
2 * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include "common.h"
8 #include <stdlib.h>
9 #include <ctype.h>
10 #include <stdbool.h>
11
12 #include "command.h"
13 #include "con-utils.h"
14 #include "z80-if.h"
15 //#include "debug.h"
16
17
18 typedef enum {
19 IHX_OK,
20 IHX_BROKEN,
21 IHX_CHKSUMERR
22 } ihx_rstat_t;
23
24 typedef struct {
25 ihx_rstat_t status;
26 int8_t type;
27 uint8_t len;
28 uint16_t address;
29 uint8_t *data;
30 } ihex_t;
31
32
33 static
34 int get_hexdigit(void) {
35
36 int c;
37 c = toupper(my_getchar(1));
38 if (isxdigit(c)) {
39 c -= '0';
40 if (c > 9)
41 c -= ('A' - '0' - 10);
42 return c;
43 } else
44 return -1;
45 }
46
47 static
48 int get_hexbyte(void) {
49
50 uint8_t i,j;
51
52 if ((i = (uint8_t) get_hexdigit()) < 0x10)
53 if ((j = (uint8_t) get_hexdigit()) < 0x10) {
54 return (i<<4) + j;
55 }
56
57 return -1;
58 }
59
60 static
61 ihex_t ihex_get_record() {
62
63 int i;
64 uint8_t sum, c;
65 ihex_t rec = { IHX_BROKEN, 0, 0, 0, 0 };
66
67
68 while ((c = my_getchar(0)) != ':')
69 if (c == 0x03)
70 return rec;
71
72 if ((i = get_hexbyte()) < 0) /* Start code */
73 return rec;
74 sum = i;
75 rec.len = i;
76 if ((i = get_hexbyte()) < 0) /* Byte Count */
77 return rec;
78 sum += i;
79 rec.address = i * 256;
80 if ((i = get_hexbyte()) < 0) /* Address */
81 return rec;
82 sum += i;
83 rec.address += i;
84 if ((i = get_hexbyte()) < 0) /* Record type */
85 return rec;
86 sum += i;
87 rec.type = i;
88
89 if (rec.len) { /* Record Data */
90 uint8_t *p; int k;
91 if ((rec.data = malloc(rec.len)) == 0)
92 return rec;
93
94 for (p=rec.data, k=rec.len; k; k--) {
95 if ((i = get_hexbyte()) < 0)
96 break;
97 sum += i;
98 *p++ = i;
99 }
100
101 if (k) {
102 free(rec.data); rec.data = 0;
103 return rec;
104 }
105 }
106
107 i = get_hexbyte(); /* Check sum */
108
109 if (i >= 0) {
110 sum += i;
111 if (sum == 0)
112 rec.status = IHX_OK;
113 else
114 rec.status = IHX_CHKSUMERR;
115 }
116
117 if (rec.status != IHX_OK) {
118 free(rec.data);
119 rec.data = 0;
120 }
121
122 return rec;
123 }
124
125
126 command_ret_t do_loadihex(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
127 {
128 long offset = 0;
129 uint32_t base_address = 0;
130 uint32_t address_low = 0xffffffff;
131 uint32_t address_high = 0;
132 bool done = false;
133 command_ret_t rcode = CMD_RET_FAILURE;
134 ihex_t rec;
135
136 (void) cmdtp;
137 (void) flag;
138
139 if (argc > 1)
140 offset = strtol(argv[1], NULL, 16);
141
142 while (!done) {
143 rec = ihex_get_record();
144
145 if (rec.status == IHX_OK) {
146 switch (rec.type) {
147 case 0: /* Data record */
148 if (rec.len) {
149 uint32_t addr = base_address + rec.address + offset;
150 if (addr < address_low)
151 address_low = addr;
152 if (addr+rec.len > address_high)
153 address_high = addr + rec.len;
154
155 z80_bus_cmd(Request);
156 z80_write_block(rec.data, /* src */
157 addr, /* dest */
158 rec.len); /* len */
159 z80_bus_cmd(Release);
160 }
161 continue;
162 break;
163
164 case 1: /* EOF record */
165
166 done = true;
167 break;
168
169 case 2: /* Extended Segment Address Record */
170 base_address = ((rec.data[0] << 8) + rec.data[1]) << 4;
171 continue;
172 break;
173
174 case 4: /* Extended Linear Address Record */
175 base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 16;
176 continue;
177 break;
178
179 case 3: /* Start Segment Address Record (ignored)*/
180 case 5: /* Start Linear Address Record (ignored)*/
181 continue;
182 break;
183
184 }
185
186 } else
187 done = true;
188
189 free(rec.data);
190 rec.data = 0;
191
192 }
193
194 switch (rec.status) {
195 case IHX_OK:
196 rcode = CMD_RET_SUCCESS;
197 break;
198
199 case IHX_BROKEN:
200 case IHX_CHKSUMERR:
201 printf_P(PSTR("Broken Hex Record or loading interrupted!\n"));
202 break;
203 }
204
205 printf_P(PSTR("Data loaded - "));
206 if (address_low >= address_high)
207 printf_P(PSTR("None.\n"));
208 else
209 printf_P(PSTR("low: 0x%.5lX high: 0x%.5lX\n"), address_low, address_high);
210
211 return rcode;
212 }