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