target/image: allow loading of 64-bit ELF files
[openocd.git] / src / target / image.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007,2008 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * Copyright (C) 2008 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
10 * *
11 * Copyright (C) 2009 by Franck Hereson *
12 * franck.hereson@secad.fr *
13 * *
14 * Copyright (C) 2018 by Advantest *
15 * florian.meister@advantest.com *
16 * *
17 * This program is free software; you can redistribute it and/or modify *
18 * it under the terms of the GNU General Public License as published by *
19 * the Free Software Foundation; either version 2 of the License, or *
20 * (at your option) any later version. *
21 * *
22 * This program is distributed in the hope that it will be useful, *
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
25 * GNU General Public License for more details. *
26 * *
27 * You should have received a copy of the GNU General Public License *
28 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
29 ***************************************************************************/
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include "image.h"
36 #include "target.h"
37 #include <helper/log.h>
38
39 /* convert ELF header field to host endianness */
40 #define field16(elf, field) \
41 ((elf->endianness == ELFDATA2LSB) ? \
42 le_to_h_u16((uint8_t *)&field) : be_to_h_u16((uint8_t *)&field))
43
44 #define field32(elf, field) \
45 ((elf->endianness == ELFDATA2LSB) ? \
46 le_to_h_u32((uint8_t *)&field) : be_to_h_u32((uint8_t *)&field))
47
48 #define field64(elf, field) \
49 ((elf->endianness == ELFDATA2LSB) ? \
50 le_to_h_u64((uint8_t *)&field) : be_to_h_u64((uint8_t *)&field))
51
52 static int autodetect_image_type(struct image *image, const char *url)
53 {
54 int retval;
55 struct fileio *fileio;
56 size_t read_bytes;
57 uint8_t buffer[9];
58
59 /* read the first 9 bytes of image */
60 retval = fileio_open(&fileio, url, FILEIO_READ, FILEIO_BINARY);
61 if (retval != ERROR_OK)
62 return retval;
63 retval = fileio_read(fileio, 9, buffer, &read_bytes);
64
65 if (retval == ERROR_OK) {
66 if (read_bytes != 9)
67 retval = ERROR_FILEIO_OPERATION_FAILED;
68 }
69 fileio_close(fileio);
70
71 if (retval != ERROR_OK)
72 return retval;
73
74 /* check header against known signatures */
75 if (strncmp((char *)buffer, ELFMAG, SELFMAG) == 0) {
76 LOG_DEBUG("ELF image detected.");
77 image->type = IMAGE_ELF;
78 } else if ((buffer[0] == ':') /* record start byte */
79 && (isxdigit(buffer[1]))
80 && (isxdigit(buffer[2]))
81 && (isxdigit(buffer[3]))
82 && (isxdigit(buffer[4]))
83 && (isxdigit(buffer[5]))
84 && (isxdigit(buffer[6]))
85 && (buffer[7] == '0') /* record type : 00 -> 05 */
86 && (buffer[8] >= '0') && (buffer[8] < '6')) {
87 LOG_DEBUG("IHEX image detected.");
88 image->type = IMAGE_IHEX;
89 } else if ((buffer[0] == 'S') /* record start byte */
90 && (isxdigit(buffer[1]))
91 && (isxdigit(buffer[2]))
92 && (isxdigit(buffer[3]))
93 && (buffer[1] >= '0') && (buffer[1] < '9')) {
94 LOG_DEBUG("S19 image detected.");
95 image->type = IMAGE_SRECORD;
96 } else
97 image->type = IMAGE_BINARY;
98
99 return ERROR_OK;
100 }
101
102 static int identify_image_type(struct image *image, const char *type_string, const char *url)
103 {
104 if (type_string) {
105 if (!strcmp(type_string, "bin"))
106 image->type = IMAGE_BINARY;
107 else if (!strcmp(type_string, "ihex"))
108 image->type = IMAGE_IHEX;
109 else if (!strcmp(type_string, "elf"))
110 image->type = IMAGE_ELF;
111 else if (!strcmp(type_string, "mem"))
112 image->type = IMAGE_MEMORY;
113 else if (!strcmp(type_string, "s19"))
114 image->type = IMAGE_SRECORD;
115 else if (!strcmp(type_string, "build"))
116 image->type = IMAGE_BUILDER;
117 else
118 return ERROR_IMAGE_TYPE_UNKNOWN;
119 } else
120 return autodetect_image_type(image, url);
121
122 return ERROR_OK;
123 }
124
125 static int image_ihex_buffer_complete_inner(struct image *image,
126 char *lpszLine,
127 struct imagesection *section)
128 {
129 struct image_ihex *ihex = image->type_private;
130 struct fileio *fileio = ihex->fileio;
131 uint32_t full_address;
132 uint32_t cooked_bytes;
133 bool end_rec = false;
134
135 /* we can't determine the number of sections that we'll have to create ahead of time,
136 * so we locally hold them until parsing is finished */
137
138 size_t filesize;
139 int retval;
140 retval = fileio_size(fileio, &filesize);
141 if (retval != ERROR_OK)
142 return retval;
143
144 ihex->buffer = malloc(filesize >> 1);
145 cooked_bytes = 0x0;
146 image->num_sections = 0;
147
148 while (!fileio_feof(fileio)) {
149 full_address = 0x0;
150 section[image->num_sections].private = &ihex->buffer[cooked_bytes];
151 section[image->num_sections].base_address = 0x0;
152 section[image->num_sections].size = 0x0;
153 section[image->num_sections].flags = 0;
154
155 while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK) {
156 uint32_t count;
157 uint32_t address;
158 uint32_t record_type;
159 uint32_t checksum;
160 uint8_t cal_checksum = 0;
161 size_t bytes_read = 0;
162
163 /* skip comments and blank lines */
164 if ((lpszLine[0] == '#') || (strlen(lpszLine + strspn(lpszLine, "\n\t\r ")) == 0))
165 continue;
166
167 if (sscanf(&lpszLine[bytes_read], ":%2" SCNx32 "%4" SCNx32 "%2" SCNx32, &count,
168 &address, &record_type) != 3)
169 return ERROR_IMAGE_FORMAT_ERROR;
170 bytes_read += 9;
171
172 cal_checksum += (uint8_t)count;
173 cal_checksum += (uint8_t)(address >> 8);
174 cal_checksum += (uint8_t)address;
175 cal_checksum += (uint8_t)record_type;
176
177 if (record_type == 0) { /* Data Record */
178 if ((full_address & 0xffff) != address) {
179 /* we encountered a nonconsecutive location, create a new section,
180 * unless the current section has zero size, in which case this specifies
181 * the current section's base address
182 */
183 if (section[image->num_sections].size != 0) {
184 image->num_sections++;
185 if (image->num_sections >= IMAGE_MAX_SECTIONS) {
186 /* too many sections */
187 LOG_ERROR("Too many sections found in IHEX file");
188 return ERROR_IMAGE_FORMAT_ERROR;
189 }
190 section[image->num_sections].size = 0x0;
191 section[image->num_sections].flags = 0;
192 section[image->num_sections].private =
193 &ihex->buffer[cooked_bytes];
194 }
195 section[image->num_sections].base_address =
196 (full_address & 0xffff0000) | address;
197 full_address = (full_address & 0xffff0000) | address;
198 }
199
200 while (count-- > 0) {
201 unsigned value;
202 sscanf(&lpszLine[bytes_read], "%2x", &value);
203 ihex->buffer[cooked_bytes] = (uint8_t)value;
204 cal_checksum += (uint8_t)ihex->buffer[cooked_bytes];
205 bytes_read += 2;
206 cooked_bytes += 1;
207 section[image->num_sections].size += 1;
208 full_address++;
209 }
210 } else if (record_type == 1) { /* End of File Record */
211 /* finish the current section */
212 image->num_sections++;
213
214 /* copy section information */
215 image->sections = malloc(sizeof(struct imagesection) * image->num_sections);
216 for (unsigned int i = 0; i < image->num_sections; i++) {
217 image->sections[i].private = section[i].private;
218 image->sections[i].base_address = section[i].base_address;
219 image->sections[i].size = section[i].size;
220 image->sections[i].flags = section[i].flags;
221 }
222
223 end_rec = true;
224 break;
225 } else if (record_type == 2) { /* Linear Address Record */
226 uint16_t upper_address;
227
228 sscanf(&lpszLine[bytes_read], "%4hx", &upper_address);
229 cal_checksum += (uint8_t)(upper_address >> 8);
230 cal_checksum += (uint8_t)upper_address;
231 bytes_read += 4;
232
233 if ((full_address >> 4) != upper_address) {
234 /* we encountered a nonconsecutive location, create a new section,
235 * unless the current section has zero size, in which case this specifies
236 * the current section's base address
237 */
238 if (section[image->num_sections].size != 0) {
239 image->num_sections++;
240 if (image->num_sections >= IMAGE_MAX_SECTIONS) {
241 /* too many sections */
242 LOG_ERROR("Too many sections found in IHEX file");
243 return ERROR_IMAGE_FORMAT_ERROR;
244 }
245 section[image->num_sections].size = 0x0;
246 section[image->num_sections].flags = 0;
247 section[image->num_sections].private =
248 &ihex->buffer[cooked_bytes];
249 }
250 section[image->num_sections].base_address =
251 (full_address & 0xffff) | (upper_address << 4);
252 full_address = (full_address & 0xffff) | (upper_address << 4);
253 }
254 } else if (record_type == 3) { /* Start Segment Address Record */
255 uint32_t dummy;
256
257 /* "Start Segment Address Record" will not be supported
258 * but we must consume it, and do not create an error. */
259 while (count-- > 0) {
260 sscanf(&lpszLine[bytes_read], "%2" SCNx32, &dummy);
261 cal_checksum += (uint8_t)dummy;
262 bytes_read += 2;
263 }
264 } else if (record_type == 4) { /* Extended Linear Address Record */
265 uint16_t upper_address;
266
267 sscanf(&lpszLine[bytes_read], "%4hx", &upper_address);
268 cal_checksum += (uint8_t)(upper_address >> 8);
269 cal_checksum += (uint8_t)upper_address;
270 bytes_read += 4;
271
272 if ((full_address >> 16) != upper_address) {
273 /* we encountered a nonconsecutive location, create a new section,
274 * unless the current section has zero size, in which case this specifies
275 * the current section's base address
276 */
277 if (section[image->num_sections].size != 0) {
278 image->num_sections++;
279 if (image->num_sections >= IMAGE_MAX_SECTIONS) {
280 /* too many sections */
281 LOG_ERROR("Too many sections found in IHEX file");
282 return ERROR_IMAGE_FORMAT_ERROR;
283 }
284 section[image->num_sections].size = 0x0;
285 section[image->num_sections].flags = 0;
286 section[image->num_sections].private =
287 &ihex->buffer[cooked_bytes];
288 }
289 section[image->num_sections].base_address =
290 (full_address & 0xffff) | (upper_address << 16);
291 full_address = (full_address & 0xffff) | (upper_address << 16);
292 }
293 } else if (record_type == 5) { /* Start Linear Address Record */
294 uint32_t start_address;
295
296 sscanf(&lpszLine[bytes_read], "%8" SCNx32, &start_address);
297 cal_checksum += (uint8_t)(start_address >> 24);
298 cal_checksum += (uint8_t)(start_address >> 16);
299 cal_checksum += (uint8_t)(start_address >> 8);
300 cal_checksum += (uint8_t)start_address;
301 bytes_read += 8;
302
303 image->start_address_set = true;
304 image->start_address = be_to_h_u32((uint8_t *)&start_address);
305 } else {
306 LOG_ERROR("unhandled IHEX record type: %i", (int)record_type);
307 return ERROR_IMAGE_FORMAT_ERROR;
308 }
309
310 sscanf(&lpszLine[bytes_read], "%2" SCNx32, &checksum);
311
312 if ((uint8_t)checksum != (uint8_t)(~cal_checksum + 1)) {
313 /* checksum failed */
314 LOG_ERROR("incorrect record checksum found in IHEX file");
315 return ERROR_IMAGE_CHECKSUM;
316 }
317
318 if (end_rec) {
319 end_rec = false;
320 LOG_WARNING("continuing after end-of-file record: %.40s", lpszLine);
321 }
322 }
323 }
324
325 if (end_rec)
326 return ERROR_OK;
327 else {
328 LOG_ERROR("premature end of IHEX file, no matching end-of-file record found");
329 return ERROR_IMAGE_FORMAT_ERROR;
330 }
331 }
332
333 /**
334 * Allocate memory dynamically instead of on the stack. This
335 * is important w/embedded hosts.
336 */
337 static int image_ihex_buffer_complete(struct image *image)
338 {
339 char *lpszLine = malloc(1023);
340 if (lpszLine == NULL) {
341 LOG_ERROR("Out of memory");
342 return ERROR_FAIL;
343 }
344 struct imagesection *section = malloc(sizeof(struct imagesection) * IMAGE_MAX_SECTIONS);
345 if (section == NULL) {
346 free(lpszLine);
347 LOG_ERROR("Out of memory");
348 return ERROR_FAIL;
349 }
350 int retval;
351
352 retval = image_ihex_buffer_complete_inner(image, lpszLine, section);
353
354 free(section);
355 free(lpszLine);
356
357 return retval;
358 }
359
360 static int image_elf32_read_headers(struct image *image)
361 {
362 struct image_elf *elf = image->type_private;
363 size_t read_bytes;
364 uint32_t i, j;
365 int retval;
366 uint32_t nload;
367 bool load_to_vaddr = false;
368
369 retval = fileio_seek(elf->fileio, 0);
370 if (retval != ERROR_OK) {
371 LOG_ERROR("cannot seek to ELF file header, read failed");
372 return retval;
373 }
374
375 elf->header32 = malloc(sizeof(Elf32_Ehdr));
376
377 if (elf->header32 == NULL) {
378 LOG_ERROR("insufficient memory to perform operation");
379 return ERROR_FILEIO_OPERATION_FAILED;
380 }
381
382 retval = fileio_read(elf->fileio, sizeof(Elf32_Ehdr), (uint8_t *)elf->header32, &read_bytes);
383 if (retval != ERROR_OK) {
384 LOG_ERROR("cannot read ELF file header, read failed");
385 return ERROR_FILEIO_OPERATION_FAILED;
386 }
387 if (read_bytes != sizeof(Elf32_Ehdr)) {
388 LOG_ERROR("cannot read ELF file header, only partially read");
389 return ERROR_FILEIO_OPERATION_FAILED;
390 }
391
392 elf->segment_count = field16(elf, elf->header32->e_phnum);
393 if (elf->segment_count == 0) {
394 LOG_ERROR("invalid ELF file, no program headers");
395 return ERROR_IMAGE_FORMAT_ERROR;
396 }
397
398 retval = fileio_seek(elf->fileio, field32(elf, elf->header32->e_phoff));
399 if (retval != ERROR_OK) {
400 LOG_ERROR("cannot seek to ELF program header table, read failed");
401 return retval;
402 }
403
404 elf->segments32 = malloc(elf->segment_count*sizeof(Elf32_Phdr));
405 if (elf->segments32 == NULL) {
406 LOG_ERROR("insufficient memory to perform operation");
407 return ERROR_FILEIO_OPERATION_FAILED;
408 }
409
410 retval = fileio_read(elf->fileio, elf->segment_count*sizeof(Elf32_Phdr),
411 (uint8_t *)elf->segments32, &read_bytes);
412 if (retval != ERROR_OK) {
413 LOG_ERROR("cannot read ELF segment headers, read failed");
414 return retval;
415 }
416 if (read_bytes != elf->segment_count*sizeof(Elf32_Phdr)) {
417 LOG_ERROR("cannot read ELF segment headers, only partially read");
418 return ERROR_FILEIO_OPERATION_FAILED;
419 }
420
421 /* count useful segments (loadable), ignore BSS section */
422 image->num_sections = 0;
423 for (i = 0; i < elf->segment_count; i++)
424 if ((field32(elf,
425 elf->segments32[i].p_type) == PT_LOAD) &&
426 (field32(elf, elf->segments32[i].p_filesz) != 0))
427 image->num_sections++;
428
429 assert(image->num_sections > 0);
430
431 /**
432 * some ELF linkers produce binaries with *all* the program header
433 * p_paddr fields zero (there can be however one loadable segment
434 * that has valid physical address 0x0).
435 * If we have such a binary with more than
436 * one PT_LOAD header, then use p_vaddr instead of p_paddr
437 * (ARM ELF standard demands p_paddr = 0 anyway, and BFD
438 * library uses this approach to workaround zero-initialized p_paddrs
439 * when obtaining lma - look at elf.c of BDF)
440 */
441 for (nload = 0, i = 0; i < elf->segment_count; i++)
442 if (elf->segments32[i].p_paddr != 0)
443 break;
444 else if ((field32(elf,
445 elf->segments32[i].p_type) == PT_LOAD) &&
446 (field32(elf, elf->segments32[i].p_memsz) != 0))
447 ++nload;
448
449 if (i >= elf->segment_count && nload > 1)
450 load_to_vaddr = true;
451
452 /* alloc and fill sections array with loadable segments */
453 image->sections = malloc(image->num_sections * sizeof(struct imagesection));
454 if (image->sections == NULL) {
455 LOG_ERROR("insufficient memory to perform operation");
456 return ERROR_FILEIO_OPERATION_FAILED;
457 }
458
459 for (i = 0, j = 0; i < elf->segment_count; i++) {
460 if ((field32(elf,
461 elf->segments32[i].p_type) == PT_LOAD) &&
462 (field32(elf, elf->segments32[i].p_filesz) != 0)) {
463 image->sections[j].size = field32(elf, elf->segments32[i].p_filesz);
464 if (load_to_vaddr)
465 image->sections[j].base_address = field32(elf,
466 elf->segments32[i].p_vaddr);
467 else
468 image->sections[j].base_address = field32(elf,
469 elf->segments32[i].p_paddr);
470 image->sections[j].private = &elf->segments32[i];
471 image->sections[j].flags = field32(elf, elf->segments32[i].p_flags);
472 j++;
473 }
474 }
475
476 image->start_address_set = true;
477 image->start_address = field32(elf, elf->header32->e_entry);
478
479 return ERROR_OK;
480 }
481
482 static int image_elf64_read_headers(struct image *image)
483 {
484 struct image_elf *elf = image->type_private;
485 size_t read_bytes;
486 uint32_t i, j;
487 int retval;
488 uint32_t nload;
489 bool load_to_vaddr = false;
490
491 retval = fileio_seek(elf->fileio, 0);
492 if (retval != ERROR_OK) {
493 LOG_ERROR("cannot seek to ELF file header, read failed");
494 return retval;
495 }
496
497 elf->header64 = malloc(sizeof(Elf64_Ehdr));
498
499 if (elf->header64 == NULL) {
500 LOG_ERROR("insufficient memory to perform operation");
501 return ERROR_FILEIO_OPERATION_FAILED;
502 }
503
504 retval = fileio_read(elf->fileio, sizeof(Elf64_Ehdr), (uint8_t *)elf->header64, &read_bytes);
505 if (retval != ERROR_OK) {
506 LOG_ERROR("cannot read ELF file header, read failed");
507 return ERROR_FILEIO_OPERATION_FAILED;
508 }
509 if (read_bytes != sizeof(Elf64_Ehdr)) {
510 LOG_ERROR("cannot read ELF file header, only partially read");
511 return ERROR_FILEIO_OPERATION_FAILED;
512 }
513
514 elf->segment_count = field16(elf, elf->header64->e_phnum);
515 if (elf->segment_count == 0) {
516 LOG_ERROR("invalid ELF file, no program headers");
517 return ERROR_IMAGE_FORMAT_ERROR;
518 }
519
520 retval = fileio_seek(elf->fileio, field64(elf, elf->header64->e_phoff));
521 if (retval != ERROR_OK) {
522 LOG_ERROR("cannot seek to ELF program header table, read failed");
523 return retval;
524 }
525
526 elf->segments64 = malloc(elf->segment_count*sizeof(Elf64_Phdr));
527 if (elf->segments64 == NULL) {
528 LOG_ERROR("insufficient memory to perform operation");
529 return ERROR_FILEIO_OPERATION_FAILED;
530 }
531
532 retval = fileio_read(elf->fileio, elf->segment_count*sizeof(Elf64_Phdr),
533 (uint8_t *)elf->segments64, &read_bytes);
534 if (retval != ERROR_OK) {
535 LOG_ERROR("cannot read ELF segment headers, read failed");
536 return retval;
537 }
538 if (read_bytes != elf->segment_count*sizeof(Elf64_Phdr)) {
539 LOG_ERROR("cannot read ELF segment headers, only partially read");
540 return ERROR_FILEIO_OPERATION_FAILED;
541 }
542
543 /* count useful segments (loadable), ignore BSS section */
544 image->num_sections = 0;
545 for (i = 0; i < elf->segment_count; i++)
546 if ((field32(elf,
547 elf->segments64[i].p_type) == PT_LOAD) &&
548 (field64(elf, elf->segments64[i].p_filesz) != 0))
549 image->num_sections++;
550
551 assert(image->num_sections > 0);
552
553 /**
554 * some ELF linkers produce binaries with *all* the program header
555 * p_paddr fields zero (there can be however one loadable segment
556 * that has valid physical address 0x0).
557 * If we have such a binary with more than
558 * one PT_LOAD header, then use p_vaddr instead of p_paddr
559 * (ARM ELF standard demands p_paddr = 0 anyway, and BFD
560 * library uses this approach to workaround zero-initialized p_paddrs
561 * when obtaining lma - look at elf.c of BDF)
562 */
563 for (nload = 0, i = 0; i < elf->segment_count; i++)
564 if (elf->segments64[i].p_paddr != 0)
565 break;
566 else if ((field32(elf,
567 elf->segments64[i].p_type) == PT_LOAD) &&
568 (field64(elf, elf->segments64[i].p_memsz) != 0))
569 ++nload;
570
571 if (i >= elf->segment_count && nload > 1)
572 load_to_vaddr = true;
573
574 /* alloc and fill sections array with loadable segments */
575 image->sections = malloc(image->num_sections * sizeof(struct imagesection));
576 if (image->sections == NULL) {
577 LOG_ERROR("insufficient memory to perform operation");
578 return ERROR_FILEIO_OPERATION_FAILED;
579 }
580
581 for (i = 0, j = 0; i < elf->segment_count; i++) {
582 if ((field32(elf,
583 elf->segments64[i].p_type) == PT_LOAD) &&
584 (field64(elf, elf->segments64[i].p_filesz) != 0)) {
585 image->sections[j].size = field64(elf, elf->segments64[i].p_filesz);
586 if (load_to_vaddr)
587 image->sections[j].base_address = field64(elf,
588 elf->segments64[i].p_vaddr);
589 else
590 image->sections[j].base_address = field64(elf,
591 elf->segments64[i].p_paddr);
592 image->sections[j].private = &elf->segments64[i];
593 image->sections[j].flags = field32(elf, elf->segments64[i].p_flags);
594 j++;
595 }
596 }
597
598 image->start_address_set = true;
599 image->start_address = field64(elf, elf->header64->e_entry);
600
601 return ERROR_OK;
602 }
603
604 static int image_elf_read_headers(struct image *image)
605 {
606 struct image_elf *elf = image->type_private;
607 size_t read_bytes;
608 unsigned char e_ident[EI_NIDENT];
609 int retval;
610
611 retval = fileio_read(elf->fileio, EI_NIDENT, e_ident, &read_bytes);
612 if (retval != ERROR_OK) {
613 LOG_ERROR("cannot read ELF file header, read failed");
614 return ERROR_FILEIO_OPERATION_FAILED;
615 }
616 if (read_bytes != EI_NIDENT) {
617 LOG_ERROR("cannot read ELF file header, only partially read");
618 return ERROR_FILEIO_OPERATION_FAILED;
619 }
620
621 if (strncmp((char *)e_ident, ELFMAG, SELFMAG) != 0) {
622 LOG_ERROR("invalid ELF file, bad magic number");
623 return ERROR_IMAGE_FORMAT_ERROR;
624 }
625
626 elf->endianness = e_ident[EI_DATA];
627 if ((elf->endianness != ELFDATA2LSB)
628 && (elf->endianness != ELFDATA2MSB)) {
629 LOG_ERROR("invalid ELF file, unknown endianness setting");
630 return ERROR_IMAGE_FORMAT_ERROR;
631 }
632
633 switch (e_ident[EI_CLASS]) {
634 case ELFCLASS32:
635 LOG_DEBUG("ELF32 image detected.");
636 elf->is_64_bit = false;
637 return image_elf32_read_headers(image);
638
639 case ELFCLASS64:
640 LOG_DEBUG("ELF64 image detected.");
641 elf->is_64_bit = true;
642 return image_elf64_read_headers(image);
643
644 default:
645 LOG_ERROR("invalid ELF file, only 32/64 bit ELF files are supported");
646 return ERROR_IMAGE_FORMAT_ERROR;
647 }
648 }
649
650 static int image_elf32_read_section(struct image *image,
651 int section,
652 target_addr_t offset,
653 uint32_t size,
654 uint8_t *buffer,
655 size_t *size_read)
656 {
657 struct image_elf *elf = image->type_private;
658 Elf32_Phdr *segment = (Elf32_Phdr *)image->sections[section].private;
659 size_t read_size, really_read;
660 int retval;
661
662 *size_read = 0;
663
664 LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size);
665
666 /* read initialized data in current segment if any */
667 if (offset < field32(elf, segment->p_filesz)) {
668 /* maximal size present in file for the current segment */
669 read_size = MIN(size, field32(elf, segment->p_filesz) - offset);
670 LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size,
671 field32(elf, segment->p_offset) + offset);
672 /* read initialized area of the segment */
673 retval = fileio_seek(elf->fileio, field32(elf, segment->p_offset) + offset);
674 if (retval != ERROR_OK) {
675 LOG_ERROR("cannot find ELF segment content, seek failed");
676 return retval;
677 }
678 retval = fileio_read(elf->fileio, read_size, buffer, &really_read);
679 if (retval != ERROR_OK) {
680 LOG_ERROR("cannot read ELF segment content, read failed");
681 return retval;
682 }
683 size -= read_size;
684 *size_read += read_size;
685 /* need more data ? */
686 if (!size)
687 return ERROR_OK;
688 }
689
690 return ERROR_OK;
691 }
692
693 static int image_elf64_read_section(struct image *image,
694 int section,
695 target_addr_t offset,
696 uint32_t size,
697 uint8_t *buffer,
698 size_t *size_read)
699 {
700 struct image_elf *elf = image->type_private;
701 Elf64_Phdr *segment = (Elf64_Phdr *)image->sections[section].private;
702 size_t read_size, really_read;
703 int retval;
704
705 *size_read = 0;
706
707 LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size);
708
709 /* read initialized data in current segment if any */
710 if (offset < field64(elf, segment->p_filesz)) {
711 /* maximal size present in file for the current segment */
712 read_size = MIN(size, field64(elf, segment->p_filesz) - offset);
713 LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size,
714 field64(elf, segment->p_offset) + offset);
715 /* read initialized area of the segment */
716 retval = fileio_seek(elf->fileio, field64(elf, segment->p_offset) + offset);
717 if (retval != ERROR_OK) {
718 LOG_ERROR("cannot find ELF segment content, seek failed");
719 return retval;
720 }
721 retval = fileio_read(elf->fileio, read_size, buffer, &really_read);
722 if (retval != ERROR_OK) {
723 LOG_ERROR("cannot read ELF segment content, read failed");
724 return retval;
725 }
726 size -= read_size;
727 *size_read += read_size;
728 /* need more data ? */
729 if (!size)
730 return ERROR_OK;
731 }
732
733 return ERROR_OK;
734 }
735
736 static int image_elf_read_section(struct image *image,
737 int section,
738 target_addr_t offset,
739 uint32_t size,
740 uint8_t *buffer,
741 size_t *size_read)
742 {
743 struct image_elf *elf = image->type_private;
744
745 if (elf->is_64_bit)
746 return image_elf64_read_section(image, section, offset, size, buffer, size_read);
747 else
748 return image_elf32_read_section(image, section, offset, size, buffer, size_read);
749 }
750
751 static int image_mot_buffer_complete_inner(struct image *image,
752 char *lpszLine,
753 struct imagesection *section)
754 {
755 struct image_mot *mot = image->type_private;
756 struct fileio *fileio = mot->fileio;
757 uint32_t full_address;
758 uint32_t cooked_bytes;
759 bool end_rec = false;
760
761 /* we can't determine the number of sections that we'll have to create ahead of time,
762 * so we locally hold them until parsing is finished */
763
764 int retval;
765 size_t filesize;
766 retval = fileio_size(fileio, &filesize);
767 if (retval != ERROR_OK)
768 return retval;
769
770 mot->buffer = malloc(filesize >> 1);
771 cooked_bytes = 0x0;
772 image->num_sections = 0;
773
774 while (!fileio_feof(fileio)) {
775 full_address = 0x0;
776 section[image->num_sections].private = &mot->buffer[cooked_bytes];
777 section[image->num_sections].base_address = 0x0;
778 section[image->num_sections].size = 0x0;
779 section[image->num_sections].flags = 0;
780
781 while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK) {
782 uint32_t count;
783 uint32_t address;
784 uint32_t record_type;
785 uint32_t checksum;
786 uint8_t cal_checksum = 0;
787 uint32_t bytes_read = 0;
788
789 /* skip comments and blank lines */
790 if ((lpszLine[0] == '#') || (strlen(lpszLine + strspn(lpszLine, "\n\t\r ")) == 0))
791 continue;
792
793 /* get record type and record length */
794 if (sscanf(&lpszLine[bytes_read], "S%1" SCNx32 "%2" SCNx32, &record_type,
795 &count) != 2)
796 return ERROR_IMAGE_FORMAT_ERROR;
797
798 bytes_read += 4;
799 cal_checksum += (uint8_t)count;
800
801 /* skip checksum byte */
802 count -= 1;
803
804 if (record_type == 0) {
805 /* S0 - starting record (optional) */
806 int iValue;
807
808 while (count-- > 0) {
809 sscanf(&lpszLine[bytes_read], "%2x", &iValue);
810 cal_checksum += (uint8_t)iValue;
811 bytes_read += 2;
812 }
813 } else if (record_type >= 1 && record_type <= 3) {
814 switch (record_type) {
815 case 1:
816 /* S1 - 16 bit address data record */
817 sscanf(&lpszLine[bytes_read], "%4" SCNx32, &address);
818 cal_checksum += (uint8_t)(address >> 8);
819 cal_checksum += (uint8_t)address;
820 bytes_read += 4;
821 count -= 2;
822 break;
823
824 case 2:
825 /* S2 - 24 bit address data record */
826 sscanf(&lpszLine[bytes_read], "%6" SCNx32, &address);
827 cal_checksum += (uint8_t)(address >> 16);
828 cal_checksum += (uint8_t)(address >> 8);
829 cal_checksum += (uint8_t)address;
830 bytes_read += 6;
831 count -= 3;
832 break;
833
834 case 3:
835 /* S3 - 32 bit address data record */
836 sscanf(&lpszLine[bytes_read], "%8" SCNx32, &address);
837 cal_checksum += (uint8_t)(address >> 24);
838 cal_checksum += (uint8_t)(address >> 16);
839 cal_checksum += (uint8_t)(address >> 8);
840 cal_checksum += (uint8_t)address;
841 bytes_read += 8;
842 count -= 4;
843 break;
844
845 }
846
847 if (full_address != address) {
848 /* we encountered a nonconsecutive location, create a new section,
849 * unless the current section has zero size, in which case this specifies
850 * the current section's base address
851 */
852 if (section[image->num_sections].size != 0) {
853 image->num_sections++;
854 section[image->num_sections].size = 0x0;
855 section[image->num_sections].flags = 0;
856 section[image->num_sections].private =
857 &mot->buffer[cooked_bytes];
858 }
859 section[image->num_sections].base_address = address;
860 full_address = address;
861 }
862
863 while (count-- > 0) {
864 unsigned value;
865 sscanf(&lpszLine[bytes_read], "%2x", &value);
866 mot->buffer[cooked_bytes] = (uint8_t)value;
867 cal_checksum += (uint8_t)mot->buffer[cooked_bytes];
868 bytes_read += 2;
869 cooked_bytes += 1;
870 section[image->num_sections].size += 1;
871 full_address++;
872 }
873 } else if (record_type == 5 || record_type == 6) {
874 /* S5 and S6 are the data count records, we ignore them */
875 uint32_t dummy;
876
877 while (count-- > 0) {
878 sscanf(&lpszLine[bytes_read], "%2" SCNx32, &dummy);
879 cal_checksum += (uint8_t)dummy;
880 bytes_read += 2;
881 }
882 } else if (record_type >= 7 && record_type <= 9) {
883 /* S7, S8, S9 - ending records for 32, 24 and 16bit */
884 image->num_sections++;
885
886 /* copy section information */
887 image->sections = malloc(sizeof(struct imagesection) * image->num_sections);
888 for (unsigned int i = 0; i < image->num_sections; i++) {
889 image->sections[i].private = section[i].private;
890 image->sections[i].base_address = section[i].base_address;
891 image->sections[i].size = section[i].size;
892 image->sections[i].flags = section[i].flags;
893 }
894
895 end_rec = true;
896 break;
897 } else {
898 LOG_ERROR("unhandled S19 record type: %i", (int)(record_type));
899 return ERROR_IMAGE_FORMAT_ERROR;
900 }
901
902 /* account for checksum, will always be 0xFF */
903 sscanf(&lpszLine[bytes_read], "%2" SCNx32, &checksum);
904 cal_checksum += (uint8_t)checksum;
905
906 if (cal_checksum != 0xFF) {
907 /* checksum failed */
908 LOG_ERROR("incorrect record checksum found in S19 file");
909 return ERROR_IMAGE_CHECKSUM;
910 }
911
912 if (end_rec) {
913 end_rec = false;
914 LOG_WARNING("continuing after end-of-file record: %.40s", lpszLine);
915 }
916 }
917 }
918
919 if (end_rec)
920 return ERROR_OK;
921 else {
922 LOG_ERROR("premature end of S19 file, no matching end-of-file record found");
923 return ERROR_IMAGE_FORMAT_ERROR;
924 }
925 }
926
927 /**
928 * Allocate memory dynamically instead of on the stack. This
929 * is important w/embedded hosts.
930 */
931 static int image_mot_buffer_complete(struct image *image)
932 {
933 char *lpszLine = malloc(1023);
934 if (lpszLine == NULL) {
935 LOG_ERROR("Out of memory");
936 return ERROR_FAIL;
937 }
938 struct imagesection *section = malloc(sizeof(struct imagesection) * IMAGE_MAX_SECTIONS);
939 if (section == NULL) {
940 free(lpszLine);
941 LOG_ERROR("Out of memory");
942 return ERROR_FAIL;
943 }
944 int retval;
945
946 retval = image_mot_buffer_complete_inner(image, lpszLine, section);
947
948 free(section);
949 free(lpszLine);
950
951 return retval;
952 }
953
954 int image_open(struct image *image, const char *url, const char *type_string)
955 {
956 int retval = ERROR_OK;
957
958 retval = identify_image_type(image, type_string, url);
959 if (retval != ERROR_OK)
960 return retval;
961
962 if (image->type == IMAGE_BINARY) {
963 struct image_binary *image_binary;
964
965 image_binary = image->type_private = malloc(sizeof(struct image_binary));
966
967 retval = fileio_open(&image_binary->fileio, url, FILEIO_READ, FILEIO_BINARY);
968 if (retval != ERROR_OK)
969 return retval;
970 size_t filesize;
971 retval = fileio_size(image_binary->fileio, &filesize);
972 if (retval != ERROR_OK) {
973 fileio_close(image_binary->fileio);
974 return retval;
975 }
976
977 image->num_sections = 1;
978 image->sections = malloc(sizeof(struct imagesection));
979 image->sections[0].base_address = 0x0;
980 image->sections[0].size = filesize;
981 image->sections[0].flags = 0;
982 } else if (image->type == IMAGE_IHEX) {
983 struct image_ihex *image_ihex;
984
985 image_ihex = image->type_private = malloc(sizeof(struct image_ihex));
986
987 retval = fileio_open(&image_ihex->fileio, url, FILEIO_READ, FILEIO_TEXT);
988 if (retval != ERROR_OK)
989 return retval;
990
991 retval = image_ihex_buffer_complete(image);
992 if (retval != ERROR_OK) {
993 LOG_ERROR(
994 "failed buffering IHEX image, check server output for additional information");
995 fileio_close(image_ihex->fileio);
996 return retval;
997 }
998 } else if (image->type == IMAGE_ELF) {
999 struct image_elf *image_elf;
1000
1001 image_elf = image->type_private = malloc(sizeof(struct image_elf));
1002
1003 retval = fileio_open(&image_elf->fileio, url, FILEIO_READ, FILEIO_BINARY);
1004 if (retval != ERROR_OK)
1005 return retval;
1006
1007 retval = image_elf_read_headers(image);
1008 if (retval != ERROR_OK) {
1009 fileio_close(image_elf->fileio);
1010 return retval;
1011 }
1012 } else if (image->type == IMAGE_MEMORY) {
1013 struct target *target = get_target(url);
1014
1015 if (target == NULL) {
1016 LOG_ERROR("target '%s' not defined", url);
1017 return ERROR_FAIL;
1018 }
1019
1020 struct image_memory *image_memory;
1021
1022 image->num_sections = 1;
1023 image->sections = malloc(sizeof(struct imagesection));
1024 image->sections[0].base_address = 0x0;
1025 image->sections[0].size = 0xffffffff;
1026 image->sections[0].flags = 0;
1027
1028 image_memory = image->type_private = malloc(sizeof(struct image_memory));
1029
1030 image_memory->target = target;
1031 image_memory->cache = NULL;
1032 image_memory->cache_address = 0x0;
1033 } else if (image->type == IMAGE_SRECORD) {
1034 struct image_mot *image_mot;
1035
1036 image_mot = image->type_private = malloc(sizeof(struct image_mot));
1037
1038 retval = fileio_open(&image_mot->fileio, url, FILEIO_READ, FILEIO_TEXT);
1039 if (retval != ERROR_OK)
1040 return retval;
1041
1042 retval = image_mot_buffer_complete(image);
1043 if (retval != ERROR_OK) {
1044 LOG_ERROR(
1045 "failed buffering S19 image, check server output for additional information");
1046 fileio_close(image_mot->fileio);
1047 return retval;
1048 }
1049 } else if (image->type == IMAGE_BUILDER) {
1050 image->num_sections = 0;
1051 image->base_address_set = false;
1052 image->sections = NULL;
1053 image->type_private = NULL;
1054 }
1055
1056 if (image->base_address_set) {
1057 /* relocate */
1058 for (unsigned int section = 0; section < image->num_sections; section++)
1059 image->sections[section].base_address += image->base_address;
1060 /* we're done relocating. The two statements below are mainly
1061 * for documentation purposes: stop anyone from empirically
1062 * thinking they should use these values henceforth. */
1063 image->base_address = 0;
1064 image->base_address_set = false;
1065 }
1066
1067 return retval;
1068 };
1069
1070 int image_read_section(struct image *image,
1071 int section,
1072 target_addr_t offset,
1073 uint32_t size,
1074 uint8_t *buffer,
1075 size_t *size_read)
1076 {
1077 int retval;
1078
1079 /* don't read past the end of a section */
1080 if (offset + size > image->sections[section].size) {
1081 LOG_DEBUG(
1082 "read past end of section: 0x%8.8" TARGET_PRIxADDR " + 0x%8.8" PRIx32 " > 0x%8.8" PRIx32 "",
1083 offset,
1084 size,
1085 image->sections[section].size);
1086 return ERROR_COMMAND_SYNTAX_ERROR;
1087 }
1088
1089 if (image->type == IMAGE_BINARY) {
1090 struct image_binary *image_binary = image->type_private;
1091
1092 /* only one section in a plain binary */
1093 if (section != 0)
1094 return ERROR_COMMAND_SYNTAX_ERROR;
1095
1096 /* seek to offset */
1097 retval = fileio_seek(image_binary->fileio, offset);
1098 if (retval != ERROR_OK)
1099 return retval;
1100
1101 /* return requested bytes */
1102 retval = fileio_read(image_binary->fileio, size, buffer, size_read);
1103 if (retval != ERROR_OK)
1104 return retval;
1105 } else if (image->type == IMAGE_IHEX) {
1106 memcpy(buffer, (uint8_t *)image->sections[section].private + offset, size);
1107 *size_read = size;
1108
1109 return ERROR_OK;
1110 } else if (image->type == IMAGE_ELF) {
1111 return image_elf_read_section(image, section, offset, size, buffer, size_read);
1112 } else if (image->type == IMAGE_MEMORY) {
1113 struct image_memory *image_memory = image->type_private;
1114 uint32_t address = image->sections[section].base_address + offset;
1115
1116 *size_read = 0;
1117
1118 while ((size - *size_read) > 0) {
1119 uint32_t size_in_cache;
1120
1121 if (!image_memory->cache
1122 || (address < image_memory->cache_address)
1123 || (address >=
1124 (image_memory->cache_address + IMAGE_MEMORY_CACHE_SIZE))) {
1125 if (!image_memory->cache)
1126 image_memory->cache = malloc(IMAGE_MEMORY_CACHE_SIZE);
1127
1128 if (target_read_buffer(image_memory->target, address &
1129 ~(IMAGE_MEMORY_CACHE_SIZE - 1),
1130 IMAGE_MEMORY_CACHE_SIZE, image_memory->cache) != ERROR_OK) {
1131 free(image_memory->cache);
1132 image_memory->cache = NULL;
1133 return ERROR_IMAGE_TEMPORARILY_UNAVAILABLE;
1134 }
1135 image_memory->cache_address = address &
1136 ~(IMAGE_MEMORY_CACHE_SIZE - 1);
1137 }
1138
1139 size_in_cache =
1140 (image_memory->cache_address + IMAGE_MEMORY_CACHE_SIZE) - address;
1141
1142 memcpy(buffer + *size_read,
1143 image_memory->cache + (address - image_memory->cache_address),
1144 (size_in_cache > size) ? size : size_in_cache
1145 );
1146
1147 *size_read += (size_in_cache > size) ? size : size_in_cache;
1148 address += (size_in_cache > size) ? size : size_in_cache;
1149 }
1150 } else if (image->type == IMAGE_SRECORD) {
1151 memcpy(buffer, (uint8_t *)image->sections[section].private + offset, size);
1152 *size_read = size;
1153
1154 return ERROR_OK;
1155 } else if (image->type == IMAGE_BUILDER) {
1156 memcpy(buffer, (uint8_t *)image->sections[section].private + offset, size);
1157 *size_read = size;
1158
1159 return ERROR_OK;
1160 }
1161
1162 return ERROR_OK;
1163 }
1164
1165 int image_add_section(struct image *image, target_addr_t base, uint32_t size, int flags, uint8_t const *data)
1166 {
1167 struct imagesection *section;
1168
1169 /* only image builder supports adding sections */
1170 if (image->type != IMAGE_BUILDER)
1171 return ERROR_COMMAND_SYNTAX_ERROR;
1172
1173 /* see if there's a previous section */
1174 if (image->num_sections) {
1175 section = &image->sections[image->num_sections - 1];
1176
1177 /* see if it's enough to extend the last section,
1178 * adding data to previous sections or merging is not supported */
1179 if (((section->base_address + section->size) == base) &&
1180 (section->flags == flags)) {
1181 section->private = realloc(section->private, section->size + size);
1182 memcpy((uint8_t *)section->private + section->size, data, size);
1183 section->size += size;
1184 return ERROR_OK;
1185 }
1186 }
1187
1188 /* allocate new section */
1189 image->num_sections++;
1190 image->sections =
1191 realloc(image->sections, sizeof(struct imagesection) * image->num_sections);
1192 section = &image->sections[image->num_sections - 1];
1193 section->base_address = base;
1194 section->size = size;
1195 section->flags = flags;
1196 section->private = malloc(sizeof(uint8_t) * size);
1197 memcpy((uint8_t *)section->private, data, size);
1198
1199 return ERROR_OK;
1200 }
1201
1202 void image_close(struct image *image)
1203 {
1204 if (image->type == IMAGE_BINARY) {
1205 struct image_binary *image_binary = image->type_private;
1206
1207 fileio_close(image_binary->fileio);
1208 } else if (image->type == IMAGE_IHEX) {
1209 struct image_ihex *image_ihex = image->type_private;
1210
1211 fileio_close(image_ihex->fileio);
1212
1213 free(image_ihex->buffer);
1214 image_ihex->buffer = NULL;
1215 } else if (image->type == IMAGE_ELF) {
1216 struct image_elf *image_elf = image->type_private;
1217
1218 fileio_close(image_elf->fileio);
1219
1220 if (image_elf->is_64_bit) {
1221 free(image_elf->header64);
1222 image_elf->header64 = NULL;
1223
1224 free(image_elf->segments64);
1225 image_elf->segments64 = NULL;
1226 } else {
1227 free(image_elf->header32);
1228 image_elf->header32 = NULL;
1229
1230 free(image_elf->segments32);
1231 image_elf->segments32 = NULL;
1232 }
1233 } else if (image->type == IMAGE_MEMORY) {
1234 struct image_memory *image_memory = image->type_private;
1235
1236 free(image_memory->cache);
1237 image_memory->cache = NULL;
1238 } else if (image->type == IMAGE_SRECORD) {
1239 struct image_mot *image_mot = image->type_private;
1240
1241 fileio_close(image_mot->fileio);
1242
1243 free(image_mot->buffer);
1244 image_mot->buffer = NULL;
1245 } else if (image->type == IMAGE_BUILDER) {
1246 for (unsigned int i = 0; i < image->num_sections; i++) {
1247 free(image->sections[i].private);
1248 image->sections[i].private = NULL;
1249 }
1250 }
1251
1252 free(image->type_private);
1253 image->type_private = NULL;
1254
1255 free(image->sections);
1256 image->sections = NULL;
1257 }
1258
1259 int image_calculate_checksum(const uint8_t *buffer, uint32_t nbytes, uint32_t *checksum)
1260 {
1261 uint32_t crc = 0xffffffff;
1262 LOG_DEBUG("Calculating checksum");
1263
1264 static uint32_t crc32_table[256];
1265
1266 static bool first_init;
1267 if (!first_init) {
1268 /* Initialize the CRC table and the decoding table. */
1269 unsigned int i, j, c;
1270 for (i = 0; i < 256; i++) {
1271 /* as per gdb */
1272 for (c = i << 24, j = 8; j > 0; --j)
1273 c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
1274 crc32_table[i] = c;
1275 }
1276
1277 first_init = true;
1278 }
1279
1280 while (nbytes > 0) {
1281 int run = nbytes;
1282 if (run > 32768)
1283 run = 32768;
1284 nbytes -= run;
1285 while (run--) {
1286 /* as per gdb */
1287 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buffer++) & 255];
1288 }
1289 keep_alive();
1290 }
1291
1292 LOG_DEBUG("Calculating checksum done; checksum=0x%" PRIx32, crc);
1293
1294 *checksum = crc;
1295 return ERROR_OK;
1296 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)