ihex.c revision 1.1.1.11 1 1.1 skrll /* BFD back-end for Intel Hex objects.
2 1.1.1.11 christos Copyright (C) 1995-2025 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.1.9 christos static bool inited;
164 1.1 skrll
165 1.1 skrll if (! inited)
166 1.1 skrll {
167 1.1.1.9 christos 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.1.9 christos static bool
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.1.9 christos 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.1.9 christos 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.1.9 christos static inline int
193 1.1.1.9 christos ihex_get_byte (bfd *abfd, bool *errorptr)
194 1.1 skrll {
195 1.1 skrll bfd_byte c;
196 1.1 skrll
197 1.1.1.10 christos if (bfd_read (&c, 1, abfd) != 1)
198 1.1 skrll {
199 1.1 skrll if (bfd_get_error () != bfd_error_file_truncated)
200 1.1.1.9 christos *errorptr = true;
201 1.1 skrll return EOF;
202 1.1 skrll }
203 1.1 skrll
204 1.1.1.10 christos return 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.1.9 christos ihex_bad_byte (bfd *abfd, unsigned int lineno, int c, bool 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.1.6 christos _bfd_error_handler
229 1.1.1.6 christos /* xgettext:c-format */
230 1.1.1.7 christos (_("%pB:%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.1.9 christos static bool
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.1.9 christos bool 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.1.10 christos if (bfd_seek (abfd, 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.1.9 christos 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.1.4 christos unsigned 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.1.10 christos if (bfd_read (hdr, 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.10 christos buf = bfd_realloc (buf, 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.1.10 christos if (bfd_read (buf, 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.1.4 christos ihex_bad_byte (abfd, lineno, buf[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.1.6 christos _bfd_error_handler
337 1.1.1.6 christos /* xgettext:c-format */
338 1.1.1.7 christos (_("%pB:%u: bad checksum in Intel Hex file (expected %u, found %u)"),
339 1.1 skrll abfd, lineno,
340 1.1 skrll (- chksum) & 0xff, (unsigned int) HEX2 (buf + 2 * i));
341 1.1 skrll bfd_set_error (bfd_error_bad_value);
342 1.1 skrll goto error_return;
343 1.1 skrll }
344 1.1 skrll
345 1.1 skrll switch (type)
346 1.1 skrll {
347 1.1 skrll case 0:
348 1.1 skrll /* This is a data record. */
349 1.1 skrll if (sec != NULL
350 1.1 skrll && sec->vma + sec->size == extbase + segbase + addr)
351 1.1 skrll {
352 1.1 skrll /* This data goes at the end of the section we are
353 1.1.1.6 christos currently building. */
354 1.1 skrll sec->size += len;
355 1.1 skrll }
356 1.1 skrll else if (len > 0)
357 1.1 skrll {
358 1.1 skrll char secbuf[20];
359 1.1 skrll char *secname;
360 1.1.1.9 christos size_t amt;
361 1.1 skrll flagword flags;
362 1.1 skrll
363 1.1 skrll sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
364 1.1 skrll amt = strlen (secbuf) + 1;
365 1.1.1.2 christos secname = (char *) bfd_alloc (abfd, amt);
366 1.1 skrll if (secname == NULL)
367 1.1 skrll goto error_return;
368 1.1 skrll strcpy (secname, secbuf);
369 1.1 skrll flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
370 1.1 skrll sec = bfd_make_section_with_flags (abfd, secname, flags);
371 1.1 skrll if (sec == NULL)
372 1.1 skrll goto error_return;
373 1.1 skrll sec->vma = extbase + segbase + addr;
374 1.1 skrll sec->lma = extbase + segbase + addr;
375 1.1 skrll sec->size = len;
376 1.1 skrll sec->filepos = pos;
377 1.1 skrll }
378 1.1 skrll break;
379 1.1 skrll
380 1.1 skrll case 1:
381 1.1 skrll /* An end record. */
382 1.1 skrll if (abfd->start_address == 0)
383 1.1 skrll abfd->start_address = addr;
384 1.1.1.9 christos free (buf);
385 1.1.1.9 christos 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.1.6 christos _bfd_error_handler
392 1.1.1.6 christos /* xgettext:c-format */
393 1.1.1.7 christos (_("%pB:%u: bad extended address record length in Intel Hex file"),
394 1.1 skrll abfd, lineno);
395 1.1 skrll bfd_set_error (bfd_error_bad_value);
396 1.1 skrll goto error_return;
397 1.1 skrll }
398 1.1 skrll
399 1.1 skrll segbase = HEX4 (buf) << 4;
400 1.1 skrll
401 1.1 skrll sec = NULL;
402 1.1 skrll
403 1.1 skrll break;
404 1.1 skrll
405 1.1 skrll case 3:
406 1.1 skrll /* An extended start address record. */
407 1.1 skrll if (len != 4)
408 1.1 skrll {
409 1.1.1.6 christos _bfd_error_handler
410 1.1.1.6 christos /* xgettext:c-format */
411 1.1.1.7 christos (_("%pB:%u: bad extended start address length in Intel Hex file"),
412 1.1 skrll abfd, lineno);
413 1.1 skrll bfd_set_error (bfd_error_bad_value);
414 1.1 skrll goto error_return;
415 1.1 skrll }
416 1.1 skrll
417 1.1 skrll abfd->start_address += (HEX4 (buf) << 4) + HEX4 (buf + 4);
418 1.1 skrll
419 1.1 skrll sec = NULL;
420 1.1 skrll
421 1.1 skrll break;
422 1.1 skrll
423 1.1 skrll case 4:
424 1.1 skrll /* An extended linear address record. */
425 1.1 skrll if (len != 2)
426 1.1 skrll {
427 1.1.1.6 christos _bfd_error_handler
428 1.1.1.6 christos /* xgettext:c-format */
429 1.1.1.7 christos (_("%pB:%u: bad extended linear address record length in Intel Hex file"),
430 1.1 skrll abfd, lineno);
431 1.1 skrll bfd_set_error (bfd_error_bad_value);
432 1.1 skrll goto error_return;
433 1.1 skrll }
434 1.1 skrll
435 1.1 skrll extbase = HEX4 (buf) << 16;
436 1.1 skrll
437 1.1 skrll sec = NULL;
438 1.1 skrll
439 1.1 skrll break;
440 1.1 skrll
441 1.1 skrll case 5:
442 1.1 skrll /* An extended linear start address record. */
443 1.1 skrll if (len != 2 && len != 4)
444 1.1 skrll {
445 1.1.1.6 christos _bfd_error_handler
446 1.1.1.6 christos /* xgettext:c-format */
447 1.1.1.7 christos (_("%pB:%u: bad extended linear start address length in Intel Hex file"),
448 1.1 skrll abfd, lineno);
449 1.1 skrll bfd_set_error (bfd_error_bad_value);
450 1.1 skrll goto error_return;
451 1.1 skrll }
452 1.1 skrll
453 1.1 skrll if (len == 2)
454 1.1 skrll abfd->start_address += HEX4 (buf) << 16;
455 1.1 skrll else
456 1.1 skrll abfd->start_address = (HEX4 (buf) << 16) + HEX4 (buf + 4);
457 1.1 skrll
458 1.1 skrll sec = NULL;
459 1.1 skrll
460 1.1 skrll break;
461 1.1 skrll
462 1.1 skrll default:
463 1.1.1.6 christos _bfd_error_handler
464 1.1.1.6 christos /* xgettext:c-format */
465 1.1.1.7 christos (_("%pB:%u: unrecognized ihex type %u in Intel Hex file"),
466 1.1 skrll abfd, lineno, type);
467 1.1 skrll bfd_set_error (bfd_error_bad_value);
468 1.1 skrll goto error_return;
469 1.1 skrll }
470 1.1 skrll }
471 1.1 skrll }
472 1.1 skrll
473 1.1 skrll if (error)
474 1.1 skrll goto error_return;
475 1.1 skrll
476 1.1.1.9 christos free (buf);
477 1.1.1.9 christos return true;
478 1.1 skrll
479 1.1 skrll error_return:
480 1.1.1.9 christos free (buf);
481 1.1.1.9 christos return false;
482 1.1 skrll }
483 1.1 skrll
484 1.1 skrll /* Try to recognize an Intel Hex file. */
485 1.1 skrll
486 1.1.1.9 christos static bfd_cleanup
487 1.1 skrll ihex_object_p (bfd *abfd)
488 1.1 skrll {
489 1.1 skrll bfd_byte b[9];
490 1.1 skrll unsigned int i;
491 1.1 skrll unsigned int type;
492 1.1 skrll
493 1.1 skrll ihex_init ();
494 1.1 skrll
495 1.1.1.10 christos if (bfd_seek (abfd, 0, SEEK_SET) != 0)
496 1.1 skrll return NULL;
497 1.1.1.10 christos if (bfd_read (b, 9, abfd) != 9)
498 1.1 skrll {
499 1.1 skrll if (bfd_get_error () == bfd_error_file_truncated)
500 1.1 skrll bfd_set_error (bfd_error_wrong_format);
501 1.1 skrll return NULL;
502 1.1 skrll }
503 1.1 skrll
504 1.1 skrll if (b[0] != ':')
505 1.1 skrll {
506 1.1 skrll bfd_set_error (bfd_error_wrong_format);
507 1.1 skrll return NULL;
508 1.1 skrll }
509 1.1 skrll
510 1.1 skrll for (i = 1; i < 9; i++)
511 1.1 skrll {
512 1.1 skrll if (! ISHEX (b[i]))
513 1.1 skrll {
514 1.1 skrll bfd_set_error (bfd_error_wrong_format);
515 1.1 skrll return NULL;
516 1.1 skrll }
517 1.1 skrll }
518 1.1 skrll
519 1.1 skrll type = HEX2 (b + 7);
520 1.1 skrll if (type > 5)
521 1.1 skrll {
522 1.1 skrll bfd_set_error (bfd_error_wrong_format);
523 1.1 skrll return NULL;
524 1.1 skrll }
525 1.1 skrll
526 1.1 skrll /* OK, it looks like it really is an Intel Hex file. */
527 1.1.1.11 christos if (!ihex_mkobject (abfd))
528 1.1.1.11 christos return NULL;
529 1.1.1.11 christos
530 1.1.1.11 christos if (!ihex_scan (abfd))
531 1.1 skrll {
532 1.1.1.11 christos bfd_release (abfd, abfd->tdata.any);
533 1.1 skrll return NULL;
534 1.1 skrll }
535 1.1 skrll
536 1.1.1.9 christos return _bfd_no_cleanup;
537 1.1 skrll }
538 1.1 skrll
539 1.1 skrll /* Read the contents of a section in an Intel Hex file. */
540 1.1 skrll
541 1.1.1.9 christos static bool
542 1.1 skrll ihex_read_section (bfd *abfd, asection *section, bfd_byte *contents)
543 1.1 skrll {
544 1.1 skrll int c;
545 1.1 skrll bfd_byte *p;
546 1.1 skrll bfd_byte *buf = NULL;
547 1.1 skrll size_t bufsize;
548 1.1.1.9 christos bool error;
549 1.1 skrll
550 1.1 skrll if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
551 1.1 skrll goto error_return;
552 1.1 skrll
553 1.1 skrll p = contents;
554 1.1 skrll bufsize = 0;
555 1.1.1.9 christos error = false;
556 1.1 skrll while ((c = ihex_get_byte (abfd, &error)) != EOF)
557 1.1 skrll {
558 1.1.1.4 christos unsigned char hdr[8];
559 1.1 skrll unsigned int len;
560 1.1 skrll unsigned int type;
561 1.1 skrll unsigned int i;
562 1.1 skrll
563 1.1 skrll if (c == '\r' || c == '\n')
564 1.1 skrll continue;
565 1.1 skrll
566 1.1 skrll /* This is called after ihex_scan has succeeded, so we ought to
567 1.1.1.6 christos know the exact format. */
568 1.1 skrll BFD_ASSERT (c == ':');
569 1.1 skrll
570 1.1.1.10 christos if (bfd_read (hdr, 8, abfd) != 8)
571 1.1 skrll goto error_return;
572 1.1 skrll
573 1.1 skrll len = HEX2 (hdr);
574 1.1 skrll type = HEX2 (hdr + 6);
575 1.1 skrll
576 1.1 skrll /* We should only see type 0 records here. */
577 1.1 skrll if (type != 0)
578 1.1 skrll {
579 1.1.1.6 christos _bfd_error_handler
580 1.1.1.7 christos (_("%pB: internal error in ihex_read_section"), abfd);
581 1.1 skrll bfd_set_error (bfd_error_bad_value);
582 1.1 skrll goto error_return;
583 1.1 skrll }
584 1.1 skrll
585 1.1 skrll if (len * 2 > bufsize)
586 1.1 skrll {
587 1.1.1.10 christos buf = bfd_realloc (buf, len * 2);
588 1.1 skrll if (buf == NULL)
589 1.1 skrll goto error_return;
590 1.1 skrll bufsize = len * 2;
591 1.1 skrll }
592 1.1 skrll
593 1.1.1.10 christos if (bfd_read (buf, len * 2, abfd) != len * 2)
594 1.1 skrll goto error_return;
595 1.1 skrll
596 1.1 skrll for (i = 0; i < len; i++)
597 1.1 skrll *p++ = HEX2 (buf + 2 * i);
598 1.1 skrll if ((bfd_size_type) (p - contents) >= section->size)
599 1.1 skrll {
600 1.1 skrll /* We've read everything in the section. */
601 1.1.1.9 christos free (buf);
602 1.1.1.9 christos return true;
603 1.1 skrll }
604 1.1 skrll
605 1.1 skrll /* Skip the checksum. */
606 1.1.1.10 christos if (bfd_read (buf, 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.1.6 christos _bfd_error_handler
613 1.1.1.7 christos (_("%pB: 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.1.9 christos free (buf);
619 1.1.1.9 christos return true;
620 1.1 skrll
621 1.1 skrll error_return:
622 1.1.1.9 christos free (buf);
623 1.1.1.9 christos return false;
624 1.1 skrll }
625 1.1 skrll
626 1.1 skrll /* Get the contents of a section in an Intel Hex file. */
627 1.1 skrll
628 1.1.1.9 christos static bool
629 1.1 skrll ihex_get_section_contents (bfd *abfd,
630 1.1 skrll asection *section,
631 1.1 skrll void * location,
632 1.1 skrll file_ptr offset,
633 1.1 skrll bfd_size_type count)
634 1.1 skrll {
635 1.1 skrll if (section->used_by_bfd == NULL)
636 1.1 skrll {
637 1.1 skrll section->used_by_bfd = bfd_alloc (abfd, section->size);
638 1.1 skrll if (section->used_by_bfd == NULL)
639 1.1.1.9 christos return false;
640 1.1.1.2 christos if (! ihex_read_section (abfd, section,
641 1.1.1.6 christos (bfd_byte *) section->used_by_bfd))
642 1.1.1.9 christos return false;
643 1.1 skrll }
644 1.1 skrll
645 1.1 skrll memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
646 1.1 skrll (size_t) count);
647 1.1 skrll
648 1.1.1.9 christos return true;
649 1.1 skrll }
650 1.1 skrll
651 1.1 skrll /* Set the contents of a section in an Intel Hex file. */
652 1.1 skrll
653 1.1.1.9 christos static bool
654 1.1 skrll ihex_set_section_contents (bfd *abfd,
655 1.1 skrll asection *section,
656 1.1 skrll const void * location,
657 1.1 skrll file_ptr offset,
658 1.1 skrll bfd_size_type count)
659 1.1 skrll {
660 1.1 skrll struct ihex_data_list *n;
661 1.1 skrll bfd_byte *data;
662 1.1 skrll struct ihex_data_struct *tdata;
663 1.1 skrll
664 1.1 skrll if (count == 0
665 1.1 skrll || (section->flags & SEC_ALLOC) == 0
666 1.1 skrll || (section->flags & SEC_LOAD) == 0)
667 1.1.1.9 christos return true;
668 1.1 skrll
669 1.1.1.2 christos n = (struct ihex_data_list *) bfd_alloc (abfd, sizeof (* n));
670 1.1 skrll if (n == NULL)
671 1.1.1.9 christos return false;
672 1.1 skrll
673 1.1.1.2 christos data = (bfd_byte *) bfd_alloc (abfd, count);
674 1.1 skrll if (data == NULL)
675 1.1.1.9 christos return false;
676 1.1 skrll memcpy (data, location, (size_t) count);
677 1.1 skrll
678 1.1 skrll n->data = data;
679 1.1 skrll n->where = section->lma + offset;
680 1.1 skrll n->size = count;
681 1.1 skrll
682 1.1 skrll /* Sort the records by address. Optimize for the common case of
683 1.1 skrll adding a record to the end of the list. */
684 1.1 skrll tdata = abfd->tdata.ihex_data;
685 1.1 skrll if (tdata->tail != NULL
686 1.1 skrll && n->where >= tdata->tail->where)
687 1.1 skrll {
688 1.1 skrll tdata->tail->next = n;
689 1.1 skrll n->next = NULL;
690 1.1 skrll tdata->tail = n;
691 1.1 skrll }
692 1.1 skrll else
693 1.1 skrll {
694 1.1 skrll struct ihex_data_list **pp;
695 1.1 skrll
696 1.1 skrll for (pp = &tdata->head;
697 1.1 skrll *pp != NULL && (*pp)->where < n->where;
698 1.1 skrll pp = &(*pp)->next)
699 1.1 skrll ;
700 1.1 skrll n->next = *pp;
701 1.1 skrll *pp = n;
702 1.1 skrll if (n->next == NULL)
703 1.1 skrll tdata->tail = n;
704 1.1 skrll }
705 1.1 skrll
706 1.1.1.9 christos return true;
707 1.1 skrll }
708 1.1 skrll
709 1.1 skrll /* Write a record out to an Intel Hex file. */
710 1.1 skrll
711 1.1.1.9 christos static bool
712 1.1 skrll ihex_write_record (bfd *abfd,
713 1.1 skrll size_t count,
714 1.1 skrll unsigned int addr,
715 1.1 skrll unsigned int type,
716 1.1 skrll bfd_byte *data)
717 1.1 skrll {
718 1.1 skrll static const char digs[] = "0123456789ABCDEF";
719 1.1 skrll char buf[9 + CHUNK * 2 + 4];
720 1.1 skrll char *p;
721 1.1 skrll unsigned int chksum;
722 1.1 skrll unsigned int i;
723 1.1 skrll size_t total;
724 1.1 skrll
725 1.1 skrll #define TOHEX(buf, v) \
726 1.1 skrll ((buf)[0] = digs[((v) >> 4) & 0xf], (buf)[1] = digs[(v) & 0xf])
727 1.1 skrll
728 1.1 skrll buf[0] = ':';
729 1.1 skrll TOHEX (buf + 1, count);
730 1.1 skrll TOHEX (buf + 3, (addr >> 8) & 0xff);
731 1.1 skrll TOHEX (buf + 5, addr & 0xff);
732 1.1 skrll TOHEX (buf + 7, type);
733 1.1 skrll
734 1.1 skrll chksum = count + addr + (addr >> 8) + type;
735 1.1 skrll
736 1.1 skrll for (i = 0, p = buf + 9; i < count; i++, p += 2, data++)
737 1.1 skrll {
738 1.1 skrll TOHEX (p, *data);
739 1.1 skrll chksum += *data;
740 1.1 skrll }
741 1.1 skrll
742 1.1 skrll TOHEX (p, (- chksum) & 0xff);
743 1.1 skrll p[2] = '\r';
744 1.1 skrll p[3] = '\n';
745 1.1 skrll
746 1.1 skrll total = 9 + count * 2 + 4;
747 1.1.1.10 christos if (bfd_write (buf, total, abfd) != total)
748 1.1.1.9 christos return false;
749 1.1 skrll
750 1.1.1.9 christos return true;
751 1.1 skrll }
752 1.1 skrll
753 1.1 skrll /* Write out an Intel Hex file. */
754 1.1 skrll
755 1.1.1.9 christos static bool
756 1.1 skrll ihex_write_object_contents (bfd *abfd)
757 1.1 skrll {
758 1.1 skrll bfd_vma segbase;
759 1.1 skrll bfd_vma extbase;
760 1.1 skrll struct ihex_data_list *l;
761 1.1 skrll
762 1.1 skrll segbase = 0;
763 1.1 skrll extbase = 0;
764 1.1 skrll for (l = abfd->tdata.ihex_data->head; l != NULL; l = l->next)
765 1.1 skrll {
766 1.1 skrll bfd_vma where;
767 1.1 skrll bfd_byte *p;
768 1.1 skrll bfd_size_type count;
769 1.1 skrll
770 1.1 skrll where = l->where;
771 1.1.1.8 christos
772 1.1.1.8 christos #ifdef BFD64
773 1.1.1.8 christos /* IHex only supports 32-bit addresses, and we want to check
774 1.1.1.8 christos that 64-bit addresses are in range. This isn't quite as
775 1.1.1.8 christos obvious as it may seem, since some targets have 32-bit
776 1.1.1.8 christos addresses that are sign extended to 64 bits. So complain
777 1.1.1.8 christos only if addresses overflow both unsigned and signed 32-bit
778 1.1.1.8 christos integers. */
779 1.1.1.8 christos if (where > 0xffffffff
780 1.1.1.8 christos && where + 0x80000000 > 0xffffffff)
781 1.1.1.8 christos {
782 1.1.1.8 christos _bfd_error_handler
783 1.1.1.8 christos /* xgettext:c-format */
784 1.1.1.8 christos (_("%pB 64-bit address %#" PRIx64
785 1.1.1.8 christos " out of range for Intel Hex file"),
786 1.1.1.8 christos abfd, (uint64_t) where);
787 1.1.1.8 christos bfd_set_error (bfd_error_bad_value);
788 1.1.1.9 christos return false;
789 1.1.1.8 christos }
790 1.1.1.8 christos where &= 0xffffffff;
791 1.1.1.8 christos #endif
792 1.1.1.8 christos
793 1.1 skrll p = l->data;
794 1.1 skrll count = l->size;
795 1.1 skrll
796 1.1 skrll while (count > 0)
797 1.1 skrll {
798 1.1 skrll size_t now;
799 1.1 skrll unsigned int rec_addr;
800 1.1 skrll
801 1.1 skrll now = count;
802 1.1 skrll if (count > CHUNK)
803 1.1 skrll now = CHUNK;
804 1.1 skrll
805 1.1.1.9 christos if (where < extbase
806 1.1.1.9 christos || where - extbase < segbase
807 1.1.1.9 christos || where - extbase - segbase > 0xffff)
808 1.1 skrll {
809 1.1 skrll bfd_byte addr[2];
810 1.1 skrll
811 1.1 skrll /* We need a new base address. */
812 1.1.1.9 christos if (extbase == 0 && where <= 0xfffff)
813 1.1 skrll {
814 1.1 skrll segbase = where & 0xf0000;
815 1.1 skrll addr[0] = (bfd_byte)(segbase >> 12) & 0xff;
816 1.1 skrll addr[1] = (bfd_byte)(segbase >> 4) & 0xff;
817 1.1 skrll if (! ihex_write_record (abfd, 2, 0, 2, addr))
818 1.1.1.9 christos return false;
819 1.1 skrll }
820 1.1 skrll else
821 1.1 skrll {
822 1.1 skrll /* The extended address record and the extended
823 1.1.1.6 christos linear address record are combined, at least by
824 1.1.1.6 christos some readers. We need an extended linear address
825 1.1.1.6 christos record here, so if we've already written out an
826 1.1.1.6 christos extended address record, zero it out to avoid
827 1.1.1.6 christos confusion. */
828 1.1 skrll if (segbase != 0)
829 1.1 skrll {
830 1.1 skrll addr[0] = 0;
831 1.1 skrll addr[1] = 0;
832 1.1 skrll if (! ihex_write_record (abfd, 2, 0, 2, addr))
833 1.1.1.9 christos return false;
834 1.1 skrll segbase = 0;
835 1.1 skrll }
836 1.1 skrll
837 1.1 skrll extbase = where & 0xffff0000;
838 1.1 skrll if (where > extbase + 0xffff)
839 1.1 skrll {
840 1.1.1.6 christos _bfd_error_handler
841 1.1.1.6 christos /* xgettext:c-format */
842 1.1.1.7 christos (_("%pB: address %#" PRIx64
843 1.1.1.7 christos " out of range for Intel Hex file"),
844 1.1.1.7 christos abfd, (uint64_t) where);
845 1.1 skrll bfd_set_error (bfd_error_bad_value);
846 1.1.1.9 christos return false;
847 1.1 skrll }
848 1.1 skrll addr[0] = (bfd_byte)(extbase >> 24) & 0xff;
849 1.1 skrll addr[1] = (bfd_byte)(extbase >> 16) & 0xff;
850 1.1 skrll if (! ihex_write_record (abfd, 2, 0, 4, addr))
851 1.1.1.9 christos return false;
852 1.1 skrll }
853 1.1 skrll }
854 1.1 skrll
855 1.1 skrll rec_addr = where - (extbase + segbase);
856 1.1 skrll
857 1.1.1.6 christos /* Output records shouldn't cross 64K boundaries. */
858 1.1.1.6 christos if (rec_addr + now > 0xffff)
859 1.1.1.6 christos now = 0x10000 - rec_addr;
860 1.1 skrll
861 1.1 skrll if (! ihex_write_record (abfd, now, rec_addr, 0, p))
862 1.1.1.9 christos return false;
863 1.1 skrll
864 1.1 skrll where += now;
865 1.1 skrll p += now;
866 1.1 skrll count -= now;
867 1.1 skrll }
868 1.1 skrll }
869 1.1 skrll
870 1.1 skrll if (abfd->start_address != 0)
871 1.1 skrll {
872 1.1 skrll bfd_vma start;
873 1.1 skrll bfd_byte startbuf[4];
874 1.1 skrll
875 1.1 skrll start = abfd->start_address;
876 1.1 skrll
877 1.1 skrll if (start <= 0xfffff)
878 1.1 skrll {
879 1.1 skrll startbuf[0] = (bfd_byte)((start & 0xf0000) >> 12) & 0xff;
880 1.1 skrll startbuf[1] = 0;
881 1.1 skrll startbuf[2] = (bfd_byte)(start >> 8) & 0xff;
882 1.1 skrll startbuf[3] = (bfd_byte)start & 0xff;
883 1.1 skrll if (! ihex_write_record (abfd, 4, 0, 3, startbuf))
884 1.1.1.9 christos return false;
885 1.1 skrll }
886 1.1 skrll else
887 1.1 skrll {
888 1.1 skrll startbuf[0] = (bfd_byte)(start >> 24) & 0xff;
889 1.1 skrll startbuf[1] = (bfd_byte)(start >> 16) & 0xff;
890 1.1 skrll startbuf[2] = (bfd_byte)(start >> 8) & 0xff;
891 1.1 skrll startbuf[3] = (bfd_byte)start & 0xff;
892 1.1 skrll if (! ihex_write_record (abfd, 4, 0, 5, startbuf))
893 1.1.1.9 christos return false;
894 1.1 skrll }
895 1.1 skrll }
896 1.1 skrll
897 1.1 skrll if (! ihex_write_record (abfd, 0, 0, 1, NULL))
898 1.1.1.9 christos return false;
899 1.1 skrll
900 1.1.1.9 christos return true;
901 1.1 skrll }
902 1.1 skrll
903 1.1 skrll /* Set the architecture for the output file. The architecture is
904 1.1 skrll irrelevant, so we ignore errors about unknown architectures. */
905 1.1 skrll
906 1.1.1.9 christos static bool
907 1.1 skrll ihex_set_arch_mach (bfd *abfd,
908 1.1 skrll enum bfd_architecture arch,
909 1.1 skrll unsigned long mach)
910 1.1 skrll {
911 1.1 skrll if (! bfd_default_set_arch_mach (abfd, arch, mach))
912 1.1 skrll {
913 1.1 skrll if (arch != bfd_arch_unknown)
914 1.1.1.9 christos return false;
915 1.1 skrll }
916 1.1.1.9 christos return true;
917 1.1 skrll }
918 1.1 skrll
919 1.1 skrll /* Some random definitions for the target vector. */
920 1.1 skrll
921 1.1.1.6 christos #define ihex_close_and_cleanup _bfd_generic_close_and_cleanup
922 1.1.1.6 christos #define ihex_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
923 1.1.1.6 christos #define ihex_new_section_hook _bfd_generic_new_section_hook
924 1.1.1.11 christos #define ihex_sizeof_headers _bfd_nolink_sizeof_headers
925 1.1.1.6 christos #define ihex_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
926 1.1.1.6 christos #define ihex_bfd_relax_section bfd_generic_relax_section
927 1.1.1.6 christos #define ihex_bfd_gc_sections bfd_generic_gc_sections
928 1.1.1.6 christos #define ihex_bfd_lookup_section_flags bfd_generic_lookup_section_flags
929 1.1.1.6 christos #define ihex_bfd_merge_sections bfd_generic_merge_sections
930 1.1.1.6 christos #define ihex_bfd_is_group_section bfd_generic_is_group_section
931 1.1.1.8 christos #define ihex_bfd_group_name bfd_generic_group_name
932 1.1.1.6 christos #define ihex_bfd_discard_group bfd_generic_discard_group
933 1.1.1.6 christos #define ihex_section_already_linked _bfd_generic_section_already_linked
934 1.1.1.6 christos #define ihex_bfd_define_common_symbol bfd_generic_define_common_symbol
935 1.1.1.7 christos #define ihex_bfd_link_hide_symbol _bfd_generic_link_hide_symbol
936 1.1.1.6 christos #define ihex_bfd_define_start_stop bfd_generic_define_start_stop
937 1.1.1.6 christos #define ihex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
938 1.1.1.6 christos #define ihex_bfd_link_add_symbols _bfd_generic_link_add_symbols
939 1.1.1.6 christos #define ihex_bfd_link_just_syms _bfd_generic_link_just_syms
940 1.1.1.6 christos #define ihex_bfd_copy_link_hash_symbol_type _bfd_generic_copy_link_hash_symbol_type
941 1.1.1.6 christos #define ihex_bfd_final_link _bfd_generic_final_link
942 1.1.1.6 christos #define ihex_bfd_link_split_section _bfd_generic_link_split_section
943 1.1.1.6 christos #define ihex_bfd_link_check_relocs _bfd_generic_link_check_relocs
944 1.1 skrll
945 1.1 skrll /* The Intel Hex target vector. */
946 1.1 skrll
947 1.1 skrll const bfd_target ihex_vec =
948 1.1 skrll {
949 1.1 skrll "ihex", /* Name. */
950 1.1 skrll bfd_target_ihex_flavour,
951 1.1 skrll BFD_ENDIAN_UNKNOWN, /* Target byte order. */
952 1.1 skrll BFD_ENDIAN_UNKNOWN, /* Target headers byte order. */
953 1.1 skrll 0, /* Object flags. */
954 1.1 skrll (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD), /* Section flags. */
955 1.1 skrll 0, /* Leading underscore. */
956 1.1 skrll ' ', /* AR_pad_char. */
957 1.1 skrll 16, /* AR_max_namelen. */
958 1.1.1.3 christos 0, /* match priority. */
959 1.1.1.9 christos TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
960 1.1 skrll bfd_getb64, bfd_getb_signed_64, bfd_putb64,
961 1.1 skrll bfd_getb32, bfd_getb_signed_32, bfd_putb32,
962 1.1 skrll bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */
963 1.1 skrll bfd_getb64, bfd_getb_signed_64, bfd_putb64,
964 1.1 skrll bfd_getb32, bfd_getb_signed_32, bfd_putb32,
965 1.1 skrll bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */
966 1.1 skrll
967 1.1 skrll {
968 1.1 skrll _bfd_dummy_target,
969 1.1 skrll ihex_object_p, /* bfd_check_format. */
970 1.1 skrll _bfd_dummy_target,
971 1.1 skrll _bfd_dummy_target,
972 1.1 skrll },
973 1.1 skrll {
974 1.1.1.7 christos _bfd_bool_bfd_false_error,
975 1.1 skrll ihex_mkobject,
976 1.1.1.11 christos _bfd_bool_bfd_false_error,
977 1.1.1.7 christos _bfd_bool_bfd_false_error,
978 1.1 skrll },
979 1.1 skrll { /* bfd_write_contents. */
980 1.1.1.7 christos _bfd_bool_bfd_false_error,
981 1.1 skrll ihex_write_object_contents,
982 1.1.1.11 christos _bfd_bool_bfd_false_error,
983 1.1.1.7 christos _bfd_bool_bfd_false_error,
984 1.1 skrll },
985 1.1 skrll
986 1.1 skrll BFD_JUMP_TABLE_GENERIC (ihex),
987 1.1 skrll BFD_JUMP_TABLE_COPY (_bfd_generic),
988 1.1 skrll BFD_JUMP_TABLE_CORE (_bfd_nocore),
989 1.1 skrll BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
990 1.1.1.11 christos BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
991 1.1 skrll BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
992 1.1 skrll BFD_JUMP_TABLE_WRITE (ihex),
993 1.1 skrll BFD_JUMP_TABLE_LINK (ihex),
994 1.1 skrll BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
995 1.1 skrll
996 1.1 skrll NULL,
997 1.1 skrll
998 1.1 skrll NULL
999 1.1 skrll };
1000