ihex.c revision 1.1.1.4 1 1.1 skrll /* BFD back-end for Intel Hex objects.
2 1.1.1.4 christos Copyright (C) 1995-2015 Free Software Foundation, Inc.
3 1.1 skrll Written by Ian Lance Taylor of Cygnus Support <ian (at) cygnus.com>.
4 1.1 skrll
5 1.1 skrll This file is part of BFD, the Binary File Descriptor library.
6 1.1 skrll
7 1.1 skrll This program is free software; you can redistribute it and/or modify
8 1.1 skrll it under the terms of the GNU General Public License as published by
9 1.1 skrll the Free Software Foundation; either version 3 of the License, or
10 1.1 skrll (at your option) any later version.
11 1.1 skrll
12 1.1 skrll This program is distributed in the hope that it will be useful,
13 1.1 skrll but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 skrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 skrll GNU General Public License for more details.
16 1.1 skrll
17 1.1 skrll You should have received a copy of the GNU General Public License
18 1.1 skrll along with this program; if not, write to the Free Software
19 1.1 skrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 1.1 skrll MA 02110-1301, USA. */
21 1.1 skrll
22 1.1 skrll
23 1.1 skrll /* This is what Intel Hex files look like:
24 1.1 skrll
25 1.1 skrll 1. INTEL FORMATS
26 1.1 skrll
27 1.1 skrll A. Intel 1
28 1.1 skrll
29 1.1 skrll 16-bit address-field format, for files 64k bytes in length or less.
30 1.1 skrll
31 1.1 skrll DATA RECORD
32 1.1 skrll Byte 1 Header = colon(:)
33 1.1 skrll 2..3 The number of data bytes in hex notation
34 1.1 skrll 4..5 High byte of the record load address
35 1.1 skrll 6..7 Low byte of the record load address
36 1.1 skrll 8..9 Record type, must be "00"
37 1.1 skrll 10..x Data bytes in hex notation:
38 1.1 skrll x = (number of bytes - 1) * 2 + 11
39 1.1 skrll x+1..x+2 Checksum in hex notation
40 1.1 skrll x+3..x+4 Carriage return, line feed
41 1.1 skrll
42 1.1 skrll END RECORD
43 1.1 skrll Byte 1 Header = colon (:)
44 1.1 skrll 2..3 The byte count, must be "00"
45 1.1 skrll 4..7 Transfer-address (usually "0000")
46 1.1 skrll the jump-to address, execution start address
47 1.1 skrll 8..9 Record type, must be "01"
48 1.1 skrll 10..11 Checksum, in hex notation
49 1.1 skrll 12..13 Carriage return, line feed
50 1.1 skrll
51 1.1 skrll B. INTEL 2
52 1.1 skrll
53 1.1 skrll MCS-86 format, using a 20-bit address for files larger than 64K bytes.
54 1.1 skrll
55 1.1 skrll DATA RECORD
56 1.1 skrll Byte 1 Header = colon (:)
57 1.1 skrll 2..3 The byte count of this record, hex notation
58 1.1 skrll 4..5 High byte of the record load address
59 1.1 skrll 6..7 Low byte of the record load address
60 1.1 skrll 8..9 Record type, must be "00"
61 1.1 skrll 10..x The data bytes in hex notation:
62 1.1 skrll x = (number of data bytes - 1) * 2 + 11
63 1.1 skrll x+1..x+2 Checksum in hex notation
64 1.1 skrll x+3..x+4 Carriage return, line feed
65 1.1 skrll
66 1.1 skrll EXTENDED ADDRESS RECORD
67 1.1 skrll Byte 1 Header = colon(:)
68 1.1 skrll 2..3 The byte count, must be "02"
69 1.1 skrll 4..7 Load address, must be "0000"
70 1.1 skrll 8..9 Record type, must be "02"
71 1.1 skrll 10..11 High byte of the offset address
72 1.1 skrll 12..13 Low byte of the offset address
73 1.1 skrll 14..15 Checksum in hex notation
74 1.1 skrll 16..17 Carriage return, line feed
75 1.1 skrll
76 1.1 skrll The checksums are the two's complement of the 8-bit sum
77 1.1 skrll without carry of the byte count, offset address, and the
78 1.1 skrll record type.
79 1.1 skrll
80 1.1 skrll START ADDRESS RECORD
81 1.1 skrll Byte 1 Header = colon (:)
82 1.1 skrll 2..3 The byte count, must be "04"
83 1.1 skrll 4..7 Load address, must be "0000"
84 1.1 skrll 8..9 Record type, must be "03"
85 1.1 skrll 10..13 8086 CS value
86 1.1 skrll 14..17 8086 IP value
87 1.1 skrll 18..19 Checksum in hex notation
88 1.1 skrll 20..21 Carriage return, line feed
89 1.1 skrll
90 1.1 skrll Another document reports these additional types:
91 1.1 skrll
92 1.1 skrll EXTENDED LINEAR ADDRESS RECORD
93 1.1 skrll Byte 1 Header = colon (:)
94 1.1 skrll 2..3 The byte count, must be "02"
95 1.1 skrll 4..7 Load address, must be "0000"
96 1.1 skrll 8..9 Record type, must be "04"
97 1.1 skrll 10..13 Upper 16 bits of address of subsequent records
98 1.1 skrll 14..15 Checksum in hex notation
99 1.1 skrll 16..17 Carriage return, line feed
100 1.1 skrll
101 1.1 skrll START LINEAR ADDRESS RECORD
102 1.1 skrll Byte 1 Header = colon (:)
103 1.1 skrll 2..3 The byte count, must be "02"
104 1.1 skrll 4..7 Load address, must be "0000"
105 1.1 skrll 8..9 Record type, must be "05"
106 1.1 skrll 10..13 Upper 16 bits of start address
107 1.1 skrll 14..15 Checksum in hex notation
108 1.1 skrll 16..17 Carriage return, line feed
109 1.1 skrll
110 1.1 skrll The MRI compiler uses this, which is a repeat of type 5:
111 1.1 skrll
112 1.1 skrll EXTENDED START RECORD
113 1.1 skrll Byte 1 Header = colon (:)
114 1.1 skrll 2..3 The byte count, must be "04"
115 1.1 skrll 4..7 Load address, must be "0000"
116 1.1 skrll 8..9 Record type, must be "05"
117 1.1 skrll 10..13 Upper 16 bits of start address
118 1.1 skrll 14..17 Lower 16 bits of start address
119 1.1 skrll 18..19 Checksum in hex notation
120 1.1 skrll 20..21 Carriage return, line feed. */
121 1.1 skrll
122 1.1 skrll #include "sysdep.h"
123 1.1 skrll #include "bfd.h"
124 1.1 skrll #include "libbfd.h"
125 1.1 skrll #include "libiberty.h"
126 1.1 skrll #include "safe-ctype.h"
127 1.1 skrll
128 1.1 skrll /* The number of bytes we put on one line during output. */
129 1.1 skrll
130 1.1 skrll #define CHUNK 16
131 1.1 skrll
132 1.1 skrll /* Macros for converting between hex and binary. */
133 1.1 skrll
134 1.1 skrll #define NIBBLE(x) (hex_value (x))
135 1.1 skrll #define HEX2(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
136 1.1 skrll #define HEX4(buffer) ((HEX2 (buffer) << 8) + HEX2 ((buffer) + 2))
137 1.1 skrll #define ISHEX(x) (hex_p (x))
138 1.1 skrll
139 1.1 skrll /* When we write out an ihex value, the values can not be output as
140 1.1 skrll they are seen. Instead, we hold them in memory in this structure. */
141 1.1 skrll
142 1.1 skrll struct ihex_data_list
143 1.1 skrll {
144 1.1 skrll struct ihex_data_list *next;
145 1.1 skrll bfd_byte *data;
146 1.1 skrll bfd_vma where;
147 1.1 skrll bfd_size_type size;
148 1.1 skrll };
149 1.1 skrll
150 1.1 skrll /* The ihex tdata information. */
151 1.1 skrll
152 1.1 skrll struct ihex_data_struct
153 1.1 skrll {
154 1.1 skrll struct ihex_data_list *head;
155 1.1 skrll struct ihex_data_list *tail;
156 1.1 skrll };
157 1.1 skrll
158 1.1 skrll /* Initialize by filling in the hex conversion array. */
159 1.1 skrll
160 1.1 skrll static void
161 1.1 skrll ihex_init (void)
162 1.1 skrll {
163 1.1 skrll static bfd_boolean inited;
164 1.1 skrll
165 1.1 skrll if (! inited)
166 1.1 skrll {
167 1.1 skrll inited = TRUE;
168 1.1 skrll hex_init ();
169 1.1 skrll }
170 1.1 skrll }
171 1.1 skrll
172 1.1 skrll /* Create an ihex object. */
173 1.1 skrll
174 1.1 skrll static bfd_boolean
175 1.1 skrll ihex_mkobject (bfd *abfd)
176 1.1 skrll {
177 1.1 skrll struct ihex_data_struct *tdata;
178 1.1 skrll
179 1.1.1.2 christos tdata = (struct ihex_data_struct *) bfd_alloc (abfd, sizeof (* tdata));
180 1.1 skrll if (tdata == NULL)
181 1.1 skrll return FALSE;
182 1.1 skrll
183 1.1 skrll abfd->tdata.ihex_data = tdata;
184 1.1 skrll tdata->head = NULL;
185 1.1 skrll tdata->tail = NULL;
186 1.1 skrll return TRUE;
187 1.1 skrll }
188 1.1 skrll
189 1.1 skrll /* Read a byte from a BFD. Set *ERRORPTR if an error occurred.
190 1.1 skrll Return EOF on error or end of file. */
191 1.1 skrll
192 1.1 skrll static INLINE int
193 1.1 skrll ihex_get_byte (bfd *abfd, bfd_boolean *errorptr)
194 1.1 skrll {
195 1.1 skrll bfd_byte c;
196 1.1 skrll
197 1.1 skrll if (bfd_bread (&c, (bfd_size_type) 1, abfd) != 1)
198 1.1 skrll {
199 1.1 skrll if (bfd_get_error () != bfd_error_file_truncated)
200 1.1 skrll *errorptr = TRUE;
201 1.1 skrll return EOF;
202 1.1 skrll }
203 1.1 skrll
204 1.1 skrll return (int) (c & 0xff);
205 1.1 skrll }
206 1.1 skrll
207 1.1 skrll /* Report a problem in an Intel Hex file. */
208 1.1 skrll
209 1.1 skrll static void
210 1.1 skrll ihex_bad_byte (bfd *abfd, unsigned int lineno, int c, bfd_boolean error)
211 1.1 skrll {
212 1.1 skrll if (c == EOF)
213 1.1 skrll {
214 1.1 skrll if (! error)
215 1.1 skrll bfd_set_error (bfd_error_file_truncated);
216 1.1 skrll }
217 1.1 skrll else
218 1.1 skrll {
219 1.1 skrll char buf[10];
220 1.1 skrll
221 1.1 skrll if (! ISPRINT (c))
222 1.1.1.4 christos sprintf (buf, "\\%03o", (unsigned int) c & 0xff);
223 1.1 skrll else
224 1.1 skrll {
225 1.1 skrll buf[0] = c;
226 1.1 skrll buf[1] = '\0';
227 1.1 skrll }
228 1.1 skrll (*_bfd_error_handler)
229 1.1 skrll (_("%B:%d: unexpected character `%s' in Intel Hex file"),
230 1.1 skrll abfd, lineno, buf);
231 1.1 skrll bfd_set_error (bfd_error_bad_value);
232 1.1 skrll }
233 1.1 skrll }
234 1.1 skrll
235 1.1 skrll /* Read an Intel hex file and turn it into sections. We create a new
236 1.1 skrll section for each contiguous set of bytes. */
237 1.1 skrll
238 1.1 skrll static bfd_boolean
239 1.1 skrll ihex_scan (bfd *abfd)
240 1.1 skrll {
241 1.1 skrll bfd_vma segbase;
242 1.1 skrll bfd_vma extbase;
243 1.1 skrll asection *sec;
244 1.1 skrll unsigned int lineno;
245 1.1 skrll bfd_boolean error;
246 1.1 skrll bfd_byte *buf = NULL;
247 1.1 skrll size_t bufsize;
248 1.1 skrll int c;
249 1.1 skrll
250 1.1 skrll if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
251 1.1 skrll goto error_return;
252 1.1 skrll
253 1.1 skrll abfd->start_address = 0;
254 1.1 skrll
255 1.1 skrll segbase = 0;
256 1.1 skrll extbase = 0;
257 1.1 skrll sec = NULL;
258 1.1 skrll lineno = 1;
259 1.1 skrll error = FALSE;
260 1.1 skrll bufsize = 0;
261 1.1 skrll
262 1.1 skrll while ((c = ihex_get_byte (abfd, &error)) != EOF)
263 1.1 skrll {
264 1.1 skrll if (c == '\r')
265 1.1 skrll continue;
266 1.1 skrll else if (c == '\n')
267 1.1 skrll {
268 1.1 skrll ++lineno;
269 1.1 skrll continue;
270 1.1 skrll }
271 1.1 skrll else if (c != ':')
272 1.1 skrll {
273 1.1 skrll ihex_bad_byte (abfd, lineno, c, error);
274 1.1 skrll goto error_return;
275 1.1 skrll }
276 1.1 skrll else
277 1.1 skrll {
278 1.1 skrll file_ptr pos;
279 1.1.1.4 christos unsigned char hdr[8];
280 1.1 skrll unsigned int i;
281 1.1 skrll unsigned int len;
282 1.1 skrll bfd_vma addr;
283 1.1 skrll unsigned int type;
284 1.1 skrll unsigned int chars;
285 1.1 skrll unsigned int chksum;
286 1.1 skrll
287 1.1 skrll /* This is a data record. */
288 1.1 skrll pos = bfd_tell (abfd) - 1;
289 1.1 skrll
290 1.1 skrll /* Read the header bytes. */
291 1.1 skrll if (bfd_bread (hdr, (bfd_size_type) 8, abfd) != 8)
292 1.1 skrll goto error_return;
293 1.1 skrll
294 1.1 skrll for (i = 0; i < 8; i++)
295 1.1 skrll {
296 1.1 skrll if (! ISHEX (hdr[i]))
297 1.1 skrll {
298 1.1 skrll ihex_bad_byte (abfd, lineno, hdr[i], error);
299 1.1 skrll goto error_return;
300 1.1 skrll }
301 1.1 skrll }
302 1.1 skrll
303 1.1 skrll len = HEX2 (hdr);
304 1.1 skrll addr = HEX4 (hdr + 2);
305 1.1 skrll type = HEX2 (hdr + 6);
306 1.1 skrll
307 1.1 skrll /* Read the data bytes. */
308 1.1 skrll chars = len * 2 + 2;
309 1.1 skrll if (chars >= bufsize)
310 1.1 skrll {
311 1.1.1.2 christos buf = (bfd_byte *) bfd_realloc (buf, (bfd_size_type) chars);
312 1.1 skrll if (buf == NULL)
313 1.1 skrll goto error_return;
314 1.1 skrll bufsize = chars;
315 1.1 skrll }
316 1.1 skrll
317 1.1 skrll if (bfd_bread (buf, (bfd_size_type) chars, abfd) != chars)
318 1.1 skrll goto error_return;
319 1.1 skrll
320 1.1 skrll for (i = 0; i < chars; i++)
321 1.1 skrll {
322 1.1 skrll if (! ISHEX (buf[i]))
323 1.1 skrll {
324 1.1.1.4 christos ihex_bad_byte (abfd, lineno, buf[i], error);
325 1.1 skrll goto error_return;
326 1.1 skrll }
327 1.1 skrll }
328 1.1 skrll
329 1.1 skrll /* Check the checksum. */
330 1.1 skrll chksum = len + addr + (addr >> 8) + type;
331 1.1 skrll for (i = 0; i < len; i++)
332 1.1 skrll chksum += HEX2 (buf + 2 * i);
333 1.1 skrll if (((- chksum) & 0xff) != (unsigned int) HEX2 (buf + 2 * i))
334 1.1 skrll {
335 1.1 skrll (*_bfd_error_handler)
336 1.1 skrll (_("%B:%u: bad checksum in Intel Hex file (expected %u, found %u)"),
337 1.1 skrll abfd, lineno,
338 1.1 skrll (- chksum) & 0xff, (unsigned int) HEX2 (buf + 2 * i));
339 1.1 skrll bfd_set_error (bfd_error_bad_value);
340 1.1 skrll goto error_return;
341 1.1 skrll }
342 1.1 skrll
343 1.1 skrll switch (type)
344 1.1 skrll {
345 1.1 skrll case 0:
346 1.1 skrll /* This is a data record. */
347 1.1 skrll if (sec != NULL
348 1.1 skrll && sec->vma + sec->size == extbase + segbase + addr)
349 1.1 skrll {
350 1.1 skrll /* This data goes at the end of the section we are
351 1.1 skrll currently building. */
352 1.1 skrll sec->size += len;
353 1.1 skrll }
354 1.1 skrll else if (len > 0)
355 1.1 skrll {
356 1.1 skrll char secbuf[20];
357 1.1 skrll char *secname;
358 1.1 skrll bfd_size_type amt;
359 1.1 skrll flagword flags;
360 1.1 skrll
361 1.1 skrll sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
362 1.1 skrll amt = strlen (secbuf) + 1;
363 1.1.1.2 christos secname = (char *) bfd_alloc (abfd, amt);
364 1.1 skrll if (secname == NULL)
365 1.1 skrll goto error_return;
366 1.1 skrll strcpy (secname, secbuf);
367 1.1 skrll flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
368 1.1 skrll sec = bfd_make_section_with_flags (abfd, secname, flags);
369 1.1 skrll if (sec == NULL)
370 1.1 skrll goto error_return;
371 1.1 skrll sec->vma = extbase + segbase + addr;
372 1.1 skrll sec->lma = extbase + segbase + addr;
373 1.1 skrll sec->size = len;
374 1.1 skrll sec->filepos = pos;
375 1.1 skrll }
376 1.1 skrll break;
377 1.1 skrll
378 1.1 skrll case 1:
379 1.1 skrll /* An end record. */
380 1.1 skrll if (abfd->start_address == 0)
381 1.1 skrll abfd->start_address = addr;
382 1.1 skrll if (buf != NULL)
383 1.1 skrll free (buf);
384 1.1 skrll return TRUE;
385 1.1 skrll
386 1.1 skrll case 2:
387 1.1 skrll /* An extended address record. */
388 1.1 skrll if (len != 2)
389 1.1 skrll {
390 1.1 skrll (*_bfd_error_handler)
391 1.1 skrll (_("%B:%u: bad extended address record length in Intel Hex file"),
392 1.1 skrll abfd, lineno);
393 1.1 skrll bfd_set_error (bfd_error_bad_value);
394 1.1 skrll goto error_return;
395 1.1 skrll }
396 1.1 skrll
397 1.1 skrll segbase = HEX4 (buf) << 4;
398 1.1 skrll
399 1.1 skrll sec = NULL;
400 1.1 skrll
401 1.1 skrll break;
402 1.1 skrll
403 1.1 skrll case 3:
404 1.1 skrll /* An extended start address record. */
405 1.1 skrll if (len != 4)
406 1.1 skrll {
407 1.1 skrll (*_bfd_error_handler)
408 1.1 skrll (_("%B:%u: bad extended start address length in Intel Hex file"),
409 1.1 skrll abfd, lineno);
410 1.1 skrll bfd_set_error (bfd_error_bad_value);
411 1.1 skrll goto error_return;
412 1.1 skrll }
413 1.1 skrll
414 1.1 skrll abfd->start_address += (HEX4 (buf) << 4) + HEX4 (buf + 4);
415 1.1 skrll
416 1.1 skrll sec = NULL;
417 1.1 skrll
418 1.1 skrll break;
419 1.1 skrll
420 1.1 skrll case 4:
421 1.1 skrll /* An extended linear address record. */
422 1.1 skrll if (len != 2)
423 1.1 skrll {
424 1.1 skrll (*_bfd_error_handler)
425 1.1 skrll (_("%B:%u: bad extended linear address record length in Intel Hex file"),
426 1.1 skrll abfd, lineno);
427 1.1 skrll bfd_set_error (bfd_error_bad_value);
428 1.1 skrll goto error_return;
429 1.1 skrll }
430 1.1 skrll
431 1.1 skrll extbase = HEX4 (buf) << 16;
432 1.1 skrll
433 1.1 skrll sec = NULL;
434 1.1 skrll
435 1.1 skrll break;
436 1.1 skrll
437 1.1 skrll case 5:
438 1.1 skrll /* An extended linear start address record. */
439 1.1 skrll if (len != 2 && len != 4)
440 1.1 skrll {
441 1.1 skrll (*_bfd_error_handler)
442 1.1 skrll (_("%B:%u: bad extended linear start address length in Intel Hex file"),
443 1.1 skrll abfd, lineno);
444 1.1 skrll bfd_set_error (bfd_error_bad_value);
445 1.1 skrll goto error_return;
446 1.1 skrll }
447 1.1 skrll
448 1.1 skrll if (len == 2)
449 1.1 skrll abfd->start_address += HEX4 (buf) << 16;
450 1.1 skrll else
451 1.1 skrll abfd->start_address = (HEX4 (buf) << 16) + HEX4 (buf + 4);
452 1.1 skrll
453 1.1 skrll sec = NULL;
454 1.1 skrll
455 1.1 skrll break;
456 1.1 skrll
457 1.1 skrll default:
458 1.1 skrll (*_bfd_error_handler)
459 1.1 skrll (_("%B:%u: unrecognized ihex type %u in Intel Hex file"),
460 1.1 skrll abfd, lineno, type);
461 1.1 skrll bfd_set_error (bfd_error_bad_value);
462 1.1 skrll goto error_return;
463 1.1 skrll }
464 1.1 skrll }
465 1.1 skrll }
466 1.1 skrll
467 1.1 skrll if (error)
468 1.1 skrll goto error_return;
469 1.1 skrll
470 1.1 skrll if (buf != NULL)
471 1.1 skrll free (buf);
472 1.1 skrll
473 1.1 skrll return TRUE;
474 1.1 skrll
475 1.1 skrll error_return:
476 1.1 skrll if (buf != NULL)
477 1.1 skrll free (buf);
478 1.1 skrll return FALSE;
479 1.1 skrll }
480 1.1 skrll
481 1.1 skrll /* Try to recognize an Intel Hex file. */
482 1.1 skrll
483 1.1 skrll static const bfd_target *
484 1.1 skrll ihex_object_p (bfd *abfd)
485 1.1 skrll {
486 1.1 skrll void * tdata_save;
487 1.1 skrll bfd_byte b[9];
488 1.1 skrll unsigned int i;
489 1.1 skrll unsigned int type;
490 1.1 skrll
491 1.1 skrll ihex_init ();
492 1.1 skrll
493 1.1 skrll if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
494 1.1 skrll return NULL;
495 1.1 skrll if (bfd_bread (b, (bfd_size_type) 9, abfd) != 9)
496 1.1 skrll {
497 1.1 skrll if (bfd_get_error () == bfd_error_file_truncated)
498 1.1 skrll bfd_set_error (bfd_error_wrong_format);
499 1.1 skrll return NULL;
500 1.1 skrll }
501 1.1 skrll
502 1.1 skrll if (b[0] != ':')
503 1.1 skrll {
504 1.1 skrll bfd_set_error (bfd_error_wrong_format);
505 1.1 skrll return NULL;
506 1.1 skrll }
507 1.1 skrll
508 1.1 skrll for (i = 1; i < 9; i++)
509 1.1 skrll {
510 1.1 skrll if (! ISHEX (b[i]))
511 1.1 skrll {
512 1.1 skrll bfd_set_error (bfd_error_wrong_format);
513 1.1 skrll return NULL;
514 1.1 skrll }
515 1.1 skrll }
516 1.1 skrll
517 1.1 skrll type = HEX2 (b + 7);
518 1.1 skrll if (type > 5)
519 1.1 skrll {
520 1.1 skrll bfd_set_error (bfd_error_wrong_format);
521 1.1 skrll return NULL;
522 1.1 skrll }
523 1.1 skrll
524 1.1 skrll /* OK, it looks like it really is an Intel Hex file. */
525 1.1 skrll tdata_save = abfd->tdata.any;
526 1.1 skrll if (! ihex_mkobject (abfd) || ! ihex_scan (abfd))
527 1.1 skrll {
528 1.1 skrll if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
529 1.1 skrll bfd_release (abfd, abfd->tdata.any);
530 1.1 skrll abfd->tdata.any = tdata_save;
531 1.1 skrll return NULL;
532 1.1 skrll }
533 1.1 skrll
534 1.1 skrll return abfd->xvec;
535 1.1 skrll }
536 1.1 skrll
537 1.1 skrll /* Read the contents of a section in an Intel Hex file. */
538 1.1 skrll
539 1.1 skrll static bfd_boolean
540 1.1 skrll ihex_read_section (bfd *abfd, asection *section, bfd_byte *contents)
541 1.1 skrll {
542 1.1 skrll int c;
543 1.1 skrll bfd_byte *p;
544 1.1 skrll bfd_byte *buf = NULL;
545 1.1 skrll size_t bufsize;
546 1.1 skrll bfd_boolean error;
547 1.1 skrll
548 1.1 skrll if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
549 1.1 skrll goto error_return;
550 1.1 skrll
551 1.1 skrll p = contents;
552 1.1 skrll bufsize = 0;
553 1.1 skrll error = FALSE;
554 1.1 skrll while ((c = ihex_get_byte (abfd, &error)) != EOF)
555 1.1 skrll {
556 1.1.1.4 christos unsigned char hdr[8];
557 1.1 skrll unsigned int len;
558 1.1 skrll unsigned int type;
559 1.1 skrll unsigned int i;
560 1.1 skrll
561 1.1 skrll if (c == '\r' || c == '\n')
562 1.1 skrll continue;
563 1.1 skrll
564 1.1 skrll /* This is called after ihex_scan has succeeded, so we ought to
565 1.1 skrll know the exact format. */
566 1.1 skrll BFD_ASSERT (c == ':');
567 1.1 skrll
568 1.1 skrll if (bfd_bread (hdr, (bfd_size_type) 8, abfd) != 8)
569 1.1 skrll goto error_return;
570 1.1 skrll
571 1.1 skrll len = HEX2 (hdr);
572 1.1 skrll type = HEX2 (hdr + 6);
573 1.1 skrll
574 1.1 skrll /* We should only see type 0 records here. */
575 1.1 skrll if (type != 0)
576 1.1 skrll {
577 1.1 skrll (*_bfd_error_handler)
578 1.1 skrll (_("%B: internal error in ihex_read_section"), abfd);
579 1.1 skrll bfd_set_error (bfd_error_bad_value);
580 1.1 skrll goto error_return;
581 1.1 skrll }
582 1.1 skrll
583 1.1 skrll if (len * 2 > bufsize)
584 1.1 skrll {
585 1.1.1.2 christos buf = (bfd_byte *) bfd_realloc (buf, (bfd_size_type) len * 2);
586 1.1 skrll if (buf == NULL)
587 1.1 skrll goto error_return;
588 1.1 skrll bufsize = len * 2;
589 1.1 skrll }
590 1.1 skrll
591 1.1 skrll if (bfd_bread (buf, (bfd_size_type) len * 2, abfd) != len * 2)
592 1.1 skrll goto error_return;
593 1.1 skrll
594 1.1 skrll for (i = 0; i < len; i++)
595 1.1 skrll *p++ = HEX2 (buf + 2 * i);
596 1.1 skrll if ((bfd_size_type) (p - contents) >= section->size)
597 1.1 skrll {
598 1.1 skrll /* We've read everything in the section. */
599 1.1 skrll if (buf != NULL)
600 1.1 skrll free (buf);
601 1.1 skrll return TRUE;
602 1.1 skrll }
603 1.1 skrll
604 1.1 skrll /* Skip the checksum. */
605 1.1 skrll if (bfd_bread (buf, (bfd_size_type) 2, abfd) != 2)
606 1.1 skrll goto error_return;
607 1.1 skrll }
608 1.1 skrll
609 1.1 skrll if ((bfd_size_type) (p - contents) < section->size)
610 1.1 skrll {
611 1.1 skrll (*_bfd_error_handler)
612 1.1 skrll (_("%B: bad section length in ihex_read_section"), abfd);
613 1.1 skrll bfd_set_error (bfd_error_bad_value);
614 1.1 skrll goto error_return;
615 1.1 skrll }
616 1.1 skrll
617 1.1 skrll if (buf != NULL)
618 1.1 skrll free (buf);
619 1.1 skrll
620 1.1 skrll return TRUE;
621 1.1 skrll
622 1.1 skrll error_return:
623 1.1 skrll if (buf != NULL)
624 1.1 skrll free (buf);
625 1.1 skrll return FALSE;
626 1.1 skrll }
627 1.1 skrll
628 1.1 skrll /* Get the contents of a section in an Intel Hex file. */
629 1.1 skrll
630 1.1 skrll static bfd_boolean
631 1.1 skrll ihex_get_section_contents (bfd *abfd,
632 1.1 skrll asection *section,
633 1.1 skrll void * location,
634 1.1 skrll file_ptr offset,
635 1.1 skrll bfd_size_type count)
636 1.1 skrll {
637 1.1 skrll if (section->used_by_bfd == NULL)
638 1.1 skrll {
639 1.1 skrll section->used_by_bfd = bfd_alloc (abfd, section->size);
640 1.1 skrll if (section->used_by_bfd == NULL)
641 1.1 skrll return FALSE;
642 1.1.1.2 christos if (! ihex_read_section (abfd, section,
643 1.1.1.2 christos (bfd_byte *) section->used_by_bfd))
644 1.1 skrll return FALSE;
645 1.1 skrll }
646 1.1 skrll
647 1.1 skrll memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
648 1.1 skrll (size_t) count);
649 1.1 skrll
650 1.1 skrll return TRUE;
651 1.1 skrll }
652 1.1 skrll
653 1.1 skrll /* Set the contents of a section in an Intel Hex file. */
654 1.1 skrll
655 1.1 skrll static bfd_boolean
656 1.1 skrll ihex_set_section_contents (bfd *abfd,
657 1.1 skrll asection *section,
658 1.1 skrll const void * location,
659 1.1 skrll file_ptr offset,
660 1.1 skrll bfd_size_type count)
661 1.1 skrll {
662 1.1 skrll struct ihex_data_list *n;
663 1.1 skrll bfd_byte *data;
664 1.1 skrll struct ihex_data_struct *tdata;
665 1.1 skrll
666 1.1 skrll if (count == 0
667 1.1 skrll || (section->flags & SEC_ALLOC) == 0
668 1.1 skrll || (section->flags & SEC_LOAD) == 0)
669 1.1 skrll return TRUE;
670 1.1 skrll
671 1.1.1.2 christos n = (struct ihex_data_list *) bfd_alloc (abfd, sizeof (* n));
672 1.1 skrll if (n == NULL)
673 1.1 skrll return FALSE;
674 1.1 skrll
675 1.1.1.2 christos data = (bfd_byte *) bfd_alloc (abfd, count);
676 1.1 skrll if (data == NULL)
677 1.1 skrll return FALSE;
678 1.1 skrll memcpy (data, location, (size_t) count);
679 1.1 skrll
680 1.1 skrll n->data = data;
681 1.1 skrll n->where = section->lma + offset;
682 1.1 skrll n->size = count;
683 1.1 skrll
684 1.1 skrll /* Sort the records by address. Optimize for the common case of
685 1.1 skrll adding a record to the end of the list. */
686 1.1 skrll tdata = abfd->tdata.ihex_data;
687 1.1 skrll if (tdata->tail != NULL
688 1.1 skrll && n->where >= tdata->tail->where)
689 1.1 skrll {
690 1.1 skrll tdata->tail->next = n;
691 1.1 skrll n->next = NULL;
692 1.1 skrll tdata->tail = n;
693 1.1 skrll }
694 1.1 skrll else
695 1.1 skrll {
696 1.1 skrll struct ihex_data_list **pp;
697 1.1 skrll
698 1.1 skrll for (pp = &tdata->head;
699 1.1 skrll *pp != NULL && (*pp)->where < n->where;
700 1.1 skrll pp = &(*pp)->next)
701 1.1 skrll ;
702 1.1 skrll n->next = *pp;
703 1.1 skrll *pp = n;
704 1.1 skrll if (n->next == NULL)
705 1.1 skrll tdata->tail = n;
706 1.1 skrll }
707 1.1 skrll
708 1.1 skrll return TRUE;
709 1.1 skrll }
710 1.1 skrll
711 1.1 skrll /* Write a record out to an Intel Hex file. */
712 1.1 skrll
713 1.1 skrll static bfd_boolean
714 1.1 skrll ihex_write_record (bfd *abfd,
715 1.1 skrll size_t count,
716 1.1 skrll unsigned int addr,
717 1.1 skrll unsigned int type,
718 1.1 skrll bfd_byte *data)
719 1.1 skrll {
720 1.1 skrll static const char digs[] = "0123456789ABCDEF";
721 1.1 skrll char buf[9 + CHUNK * 2 + 4];
722 1.1 skrll char *p;
723 1.1 skrll unsigned int chksum;
724 1.1 skrll unsigned int i;
725 1.1 skrll size_t total;
726 1.1 skrll
727 1.1 skrll #define TOHEX(buf, v) \
728 1.1 skrll ((buf)[0] = digs[((v) >> 4) & 0xf], (buf)[1] = digs[(v) & 0xf])
729 1.1 skrll
730 1.1 skrll buf[0] = ':';
731 1.1 skrll TOHEX (buf + 1, count);
732 1.1 skrll TOHEX (buf + 3, (addr >> 8) & 0xff);
733 1.1 skrll TOHEX (buf + 5, addr & 0xff);
734 1.1 skrll TOHEX (buf + 7, type);
735 1.1 skrll
736 1.1 skrll chksum = count + addr + (addr >> 8) + type;
737 1.1 skrll
738 1.1 skrll for (i = 0, p = buf + 9; i < count; i++, p += 2, data++)
739 1.1 skrll {
740 1.1 skrll TOHEX (p, *data);
741 1.1 skrll chksum += *data;
742 1.1 skrll }
743 1.1 skrll
744 1.1 skrll TOHEX (p, (- chksum) & 0xff);
745 1.1 skrll p[2] = '\r';
746 1.1 skrll p[3] = '\n';
747 1.1 skrll
748 1.1 skrll total = 9 + count * 2 + 4;
749 1.1 skrll if (bfd_bwrite (buf, (bfd_size_type) total, abfd) != total)
750 1.1 skrll return FALSE;
751 1.1 skrll
752 1.1 skrll return TRUE;
753 1.1 skrll }
754 1.1 skrll
755 1.1 skrll /* Write out an Intel Hex file. */
756 1.1 skrll
757 1.1 skrll static bfd_boolean
758 1.1 skrll ihex_write_object_contents (bfd *abfd)
759 1.1 skrll {
760 1.1 skrll bfd_vma segbase;
761 1.1 skrll bfd_vma extbase;
762 1.1 skrll struct ihex_data_list *l;
763 1.1 skrll
764 1.1 skrll segbase = 0;
765 1.1 skrll extbase = 0;
766 1.1 skrll for (l = abfd->tdata.ihex_data->head; l != NULL; l = l->next)
767 1.1 skrll {
768 1.1 skrll bfd_vma where;
769 1.1 skrll bfd_byte *p;
770 1.1 skrll bfd_size_type count;
771 1.1 skrll
772 1.1 skrll where = l->where;
773 1.1 skrll p = l->data;
774 1.1 skrll count = l->size;
775 1.1 skrll
776 1.1 skrll while (count > 0)
777 1.1 skrll {
778 1.1 skrll size_t now;
779 1.1 skrll unsigned int rec_addr;
780 1.1 skrll
781 1.1 skrll now = count;
782 1.1 skrll if (count > CHUNK)
783 1.1 skrll now = CHUNK;
784 1.1 skrll
785 1.1 skrll if (where > segbase + extbase + 0xffff)
786 1.1 skrll {
787 1.1 skrll bfd_byte addr[2];
788 1.1 skrll
789 1.1 skrll /* We need a new base address. */
790 1.1 skrll if (where <= 0xfffff)
791 1.1 skrll {
792 1.1 skrll /* The addresses should be sorted. */
793 1.1 skrll BFD_ASSERT (extbase == 0);
794 1.1 skrll
795 1.1 skrll segbase = where & 0xf0000;
796 1.1 skrll addr[0] = (bfd_byte)(segbase >> 12) & 0xff;
797 1.1 skrll addr[1] = (bfd_byte)(segbase >> 4) & 0xff;
798 1.1 skrll if (! ihex_write_record (abfd, 2, 0, 2, addr))
799 1.1 skrll return FALSE;
800 1.1 skrll }
801 1.1 skrll else
802 1.1 skrll {
803 1.1 skrll /* The extended address record and the extended
804 1.1 skrll linear address record are combined, at least by
805 1.1 skrll some readers. We need an extended linear address
806 1.1 skrll record here, so if we've already written out an
807 1.1 skrll extended address record, zero it out to avoid
808 1.1 skrll confusion. */
809 1.1 skrll if (segbase != 0)
810 1.1 skrll {
811 1.1 skrll addr[0] = 0;
812 1.1 skrll addr[1] = 0;
813 1.1 skrll if (! ihex_write_record (abfd, 2, 0, 2, addr))
814 1.1 skrll return FALSE;
815 1.1 skrll segbase = 0;
816 1.1 skrll }
817 1.1 skrll
818 1.1 skrll extbase = where & 0xffff0000;
819 1.1 skrll if (where > extbase + 0xffff)
820 1.1 skrll {
821 1.1 skrll char buf[20];
822 1.1 skrll
823 1.1 skrll sprintf_vma (buf, where);
824 1.1 skrll (*_bfd_error_handler)
825 1.1 skrll (_("%s: address 0x%s out of range for Intel Hex file"),
826 1.1 skrll bfd_get_filename (abfd), buf);
827 1.1 skrll bfd_set_error (bfd_error_bad_value);
828 1.1 skrll return FALSE;
829 1.1 skrll }
830 1.1 skrll addr[0] = (bfd_byte)(extbase >> 24) & 0xff;
831 1.1 skrll addr[1] = (bfd_byte)(extbase >> 16) & 0xff;
832 1.1 skrll if (! ihex_write_record (abfd, 2, 0, 4, addr))
833 1.1 skrll return FALSE;
834 1.1 skrll }
835 1.1 skrll }
836 1.1 skrll
837 1.1 skrll rec_addr = where - (extbase + segbase);
838 1.1 skrll
839 1.1 skrll /* Output records shouldn't cross 64K boundaries. */
840 1.1 skrll if (rec_addr + now > 0xffff)
841 1.1 skrll now = 0x10000 - rec_addr;
842 1.1 skrll
843 1.1 skrll if (! ihex_write_record (abfd, now, rec_addr, 0, p))
844 1.1 skrll return FALSE;
845 1.1 skrll
846 1.1 skrll where += now;
847 1.1 skrll p += now;
848 1.1 skrll count -= now;
849 1.1 skrll }
850 1.1 skrll }
851 1.1 skrll
852 1.1 skrll if (abfd->start_address != 0)
853 1.1 skrll {
854 1.1 skrll bfd_vma start;
855 1.1 skrll bfd_byte startbuf[4];
856 1.1 skrll
857 1.1 skrll start = abfd->start_address;
858 1.1 skrll
859 1.1 skrll if (start <= 0xfffff)
860 1.1 skrll {
861 1.1 skrll startbuf[0] = (bfd_byte)((start & 0xf0000) >> 12) & 0xff;
862 1.1 skrll startbuf[1] = 0;
863 1.1 skrll startbuf[2] = (bfd_byte)(start >> 8) & 0xff;
864 1.1 skrll startbuf[3] = (bfd_byte)start & 0xff;
865 1.1 skrll if (! ihex_write_record (abfd, 4, 0, 3, startbuf))
866 1.1 skrll return FALSE;
867 1.1 skrll }
868 1.1 skrll else
869 1.1 skrll {
870 1.1 skrll startbuf[0] = (bfd_byte)(start >> 24) & 0xff;
871 1.1 skrll startbuf[1] = (bfd_byte)(start >> 16) & 0xff;
872 1.1 skrll startbuf[2] = (bfd_byte)(start >> 8) & 0xff;
873 1.1 skrll startbuf[3] = (bfd_byte)start & 0xff;
874 1.1 skrll if (! ihex_write_record (abfd, 4, 0, 5, startbuf))
875 1.1 skrll return FALSE;
876 1.1 skrll }
877 1.1 skrll }
878 1.1 skrll
879 1.1 skrll if (! ihex_write_record (abfd, 0, 0, 1, NULL))
880 1.1 skrll return FALSE;
881 1.1 skrll
882 1.1 skrll return TRUE;
883 1.1 skrll }
884 1.1 skrll
885 1.1 skrll /* Set the architecture for the output file. The architecture is
886 1.1 skrll irrelevant, so we ignore errors about unknown architectures. */
887 1.1 skrll
888 1.1 skrll static bfd_boolean
889 1.1 skrll ihex_set_arch_mach (bfd *abfd,
890 1.1 skrll enum bfd_architecture arch,
891 1.1 skrll unsigned long mach)
892 1.1 skrll {
893 1.1 skrll if (! bfd_default_set_arch_mach (abfd, arch, mach))
894 1.1 skrll {
895 1.1 skrll if (arch != bfd_arch_unknown)
896 1.1 skrll return FALSE;
897 1.1 skrll }
898 1.1 skrll return TRUE;
899 1.1 skrll }
900 1.1 skrll
901 1.1 skrll /* Get the size of the headers, for the linker. */
902 1.1 skrll
903 1.1 skrll static int
904 1.1 skrll ihex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
905 1.1 skrll struct bfd_link_info *info ATTRIBUTE_UNUSED)
906 1.1 skrll {
907 1.1 skrll return 0;
908 1.1 skrll }
909 1.1 skrll
910 1.1 skrll /* Some random definitions for the target vector. */
911 1.1 skrll
912 1.1 skrll #define ihex_close_and_cleanup _bfd_generic_close_and_cleanup
913 1.1 skrll #define ihex_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
914 1.1 skrll #define ihex_new_section_hook _bfd_generic_new_section_hook
915 1.1 skrll #define ihex_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
916 1.1 skrll #define ihex_get_symtab_upper_bound bfd_0l
917 1.1 skrll #define ihex_canonicalize_symtab ((long (*) (bfd *, asymbol **)) bfd_0l)
918 1.1 skrll #define ihex_make_empty_symbol _bfd_generic_make_empty_symbol
919 1.1 skrll #define ihex_print_symbol _bfd_nosymbols_print_symbol
920 1.1 skrll #define ihex_get_symbol_info _bfd_nosymbols_get_symbol_info
921 1.1.1.4 christos #define ihex_get_symbol_version_string _bfd_nosymbols_get_symbol_version_string
922 1.1 skrll #define ihex_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
923 1.1 skrll #define ihex_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
924 1.1 skrll #define ihex_get_lineno _bfd_nosymbols_get_lineno
925 1.1 skrll #define ihex_find_nearest_line _bfd_nosymbols_find_nearest_line
926 1.1.1.4 christos #define ihex_find_line _bfd_nosymbols_find_line
927 1.1 skrll #define ihex_find_inliner_info _bfd_nosymbols_find_inliner_info
928 1.1 skrll #define ihex_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
929 1.1 skrll #define ihex_read_minisymbols _bfd_nosymbols_read_minisymbols
930 1.1 skrll #define ihex_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
931 1.1 skrll #define ihex_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
932 1.1 skrll #define ihex_bfd_relax_section bfd_generic_relax_section
933 1.1 skrll #define ihex_bfd_gc_sections bfd_generic_gc_sections
934 1.1.1.3 christos #define ihex_bfd_lookup_section_flags bfd_generic_lookup_section_flags
935 1.1 skrll #define ihex_bfd_merge_sections bfd_generic_merge_sections
936 1.1 skrll #define ihex_bfd_is_group_section bfd_generic_is_group_section
937 1.1 skrll #define ihex_bfd_discard_group bfd_generic_discard_group
938 1.1 skrll #define ihex_section_already_linked _bfd_generic_section_already_linked
939 1.1.1.2 christos #define ihex_bfd_define_common_symbol bfd_generic_define_common_symbol
940 1.1 skrll #define ihex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
941 1.1 skrll #define ihex_bfd_link_add_symbols _bfd_generic_link_add_symbols
942 1.1 skrll #define ihex_bfd_link_just_syms _bfd_generic_link_just_syms
943 1.1.1.2 christos #define ihex_bfd_copy_link_hash_symbol_type \
944 1.1.1.2 christos _bfd_generic_copy_link_hash_symbol_type
945 1.1 skrll #define ihex_bfd_final_link _bfd_generic_final_link
946 1.1 skrll #define ihex_bfd_link_split_section _bfd_generic_link_split_section
947 1.1 skrll
948 1.1 skrll /* The Intel Hex target vector. */
949 1.1 skrll
950 1.1 skrll const bfd_target ihex_vec =
951 1.1 skrll {
952 1.1 skrll "ihex", /* Name. */
953 1.1 skrll bfd_target_ihex_flavour,
954 1.1 skrll BFD_ENDIAN_UNKNOWN, /* Target byte order. */
955 1.1 skrll BFD_ENDIAN_UNKNOWN, /* Target headers byte order. */
956 1.1 skrll 0, /* Object flags. */
957 1.1 skrll (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD), /* Section flags. */
958 1.1 skrll 0, /* Leading underscore. */
959 1.1 skrll ' ', /* AR_pad_char. */
960 1.1 skrll 16, /* AR_max_namelen. */
961 1.1.1.3 christos 0, /* match priority. */
962 1.1 skrll bfd_getb64, bfd_getb_signed_64, bfd_putb64,
963 1.1 skrll bfd_getb32, bfd_getb_signed_32, bfd_putb32,
964 1.1 skrll bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */
965 1.1 skrll bfd_getb64, bfd_getb_signed_64, bfd_putb64,
966 1.1 skrll bfd_getb32, bfd_getb_signed_32, bfd_putb32,
967 1.1 skrll bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */
968 1.1 skrll
969 1.1 skrll {
970 1.1 skrll _bfd_dummy_target,
971 1.1 skrll ihex_object_p, /* bfd_check_format. */
972 1.1 skrll _bfd_dummy_target,
973 1.1 skrll _bfd_dummy_target,
974 1.1 skrll },
975 1.1 skrll {
976 1.1 skrll bfd_false,
977 1.1 skrll ihex_mkobject,
978 1.1 skrll _bfd_generic_mkarchive,
979 1.1 skrll bfd_false,
980 1.1 skrll },
981 1.1 skrll { /* bfd_write_contents. */
982 1.1 skrll bfd_false,
983 1.1 skrll ihex_write_object_contents,
984 1.1 skrll _bfd_write_archive_contents,
985 1.1 skrll bfd_false,
986 1.1 skrll },
987 1.1 skrll
988 1.1 skrll BFD_JUMP_TABLE_GENERIC (ihex),
989 1.1 skrll BFD_JUMP_TABLE_COPY (_bfd_generic),
990 1.1 skrll BFD_JUMP_TABLE_CORE (_bfd_nocore),
991 1.1 skrll BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
992 1.1 skrll BFD_JUMP_TABLE_SYMBOLS (ihex),
993 1.1 skrll BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
994 1.1 skrll BFD_JUMP_TABLE_WRITE (ihex),
995 1.1 skrll BFD_JUMP_TABLE_LINK (ihex),
996 1.1 skrll BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
997 1.1 skrll
998 1.1 skrll NULL,
999 1.1 skrll
1000 1.1 skrll NULL
1001 1.1 skrll };
1002