1 /* 2 * Copyright (C) 2018 Alexander Graf <agraf@suse.de> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include "imagetool.h" 8 #include "mkimage.h" 9 #include "zynqmpimage.h" 10 #include <elf.h> 11 #include <image.h> 12 13 struct bif_entry { 14 const char *filename; 15 uint64_t flags; 16 uint64_t dest_cpu; 17 uint64_t exp_lvl; 18 uint64_t dest_dev; 19 uint64_t load; 20 uint64_t entry; 21 size_t offset; 22 }; 23 24 enum bif_flag { 25 BIF_FLAG_AESKEYFILE, 26 BIF_FLAG_INIT, 27 BIF_FLAG_UDF_BH, 28 BIF_FLAG_HEADERSIGNATURE, 29 BIF_FLAG_PPKFILE, 30 BIF_FLAG_PSKFILE, 31 BIF_FLAG_SPKFILE, 32 BIF_FLAG_SSKFILE, 33 BIF_FLAG_SPKSIGNATURE, 34 BIF_FLAG_FSBL_CONFIG, 35 BIF_FLAG_AUTH_PARAMS, 36 BIF_FLAG_KEYSRC_ENCRYPTION, 37 BIF_FLAG_PMUFW_IMAGE, 38 BIF_FLAG_BOOTLOADER, 39 BIF_FLAG_TZ, 40 BIF_FLAG_BH_KEY_IV, 41 BIF_FLAG_BH_KEYFILE, 42 BIF_FLAG_PUF_FILE, 43 BIF_FLAG_AARCH32, 44 BIF_FLAG_PART_OWNER_UBOOT, 45 46 /* Internal flags */ 47 BIF_FLAG_BIT_FILE, 48 BIF_FLAG_ELF_FILE, 49 BIF_FLAG_BIN_FILE, 50 }; 51 52 struct bif_flags { 53 const char name[32]; 54 uint64_t flag; 55 char *(*parse)(char *line, struct bif_entry *bf); 56 }; 57 58 struct bif_file_type { 59 const char name[32]; 60 uint32_t header; 61 int (*add)(struct bif_entry *bf); 62 }; 63 64 struct bif_output { 65 size_t data_len; 66 char *data; 67 struct image_header_table *imgheader; 68 struct zynqmp_header *header; 69 struct partition_header *last_part; 70 }; 71 72 struct bif_output bif_output; 73 74 static uint32_t zynqmp_csum(void *start, void *end) 75 { 76 uint32_t checksum = 0; 77 uint32_t *ptr32 = start; 78 79 while (ptr32 != end) { 80 checksum += le32_to_cpu(*ptr32); 81 ptr32++; 82 } 83 84 return ~checksum; 85 } 86 87 static int zynqmpbif_check_params(struct image_tool_params *params) 88 { 89 if (!params) 90 return 0; 91 92 if (params->addr != 0x0) { 93 fprintf(stderr, "Error: Load Address can not be specified.\n"); 94 return -1; 95 } 96 97 if (params->eflag) { 98 fprintf(stderr, "Error: Entry Point can not be specified.\n"); 99 return -1; 100 } 101 102 return !(params->lflag || params->dflag); 103 } 104 105 static int zynqmpbif_check_image_types(uint8_t type) 106 { 107 return (type == IH_TYPE_ZYNQMPBIF) ? EXIT_SUCCESS : EXIT_FAILURE; 108 } 109 110 static char *parse_dest_cpu(char *line, struct bif_entry *bf) 111 { 112 uint64_t i; 113 114 for (i = 0; i < ARRAY_SIZE(dest_cpus); i++) { 115 if (!strncmp(line, dest_cpus[i], strlen(dest_cpus[i]))) { 116 bf->dest_cpu = i << PART_ATTR_DEST_CPU_SHIFT; 117 return line + strlen(dest_cpus[i]); 118 } 119 120 /* a5x can also be written as a53 */ 121 if (!strncmp(dest_cpus[i], "a5x", 3)) { 122 char a53[] = "a53-X"; 123 124 a53[4] = dest_cpus[i][4]; 125 if (!strncmp(line, a53, strlen(a53))) { 126 bf->dest_cpu = i << PART_ATTR_DEST_CPU_SHIFT; 127 return line + strlen(a53); 128 } 129 } 130 } 131 132 return line; 133 } 134 135 static char *parse_el(char *line, struct bif_entry *bf) 136 { 137 const char *dest_els[] = { "none", "el-0", "el-1", "el-2", "el-3" }; 138 int i; 139 140 for (i = 0; i < ARRAY_SIZE(dest_els); i++) { 141 if (!strncmp(line, dest_els[i], strlen(dest_els[i]))) { 142 bf->exp_lvl = i; 143 return line + strlen(dest_els[i]); 144 } 145 } 146 147 return line; 148 } 149 150 static char *parse_load(char *line, struct bif_entry *bf) 151 { 152 char *endptr; 153 154 bf->load = strtoll(line, &endptr, 0); 155 156 return endptr; 157 } 158 159 static char *parse_entry(char *line, struct bif_entry *bf) 160 { 161 char *endptr; 162 163 bf->entry = strtoll(line, &endptr, 0); 164 165 return endptr; 166 } 167 168 static char *parse_offset(char *line, struct bif_entry *bf) 169 { 170 char *endptr; 171 172 bf->offset = strtoll(line, &endptr, 0); 173 174 return endptr; 175 } 176 177 static char *parse_partition_owner(char *line, struct bif_entry *bf) 178 { 179 char *endptr = NULL; 180 181 if (!strncmp(line, "fsbl", 4)) { 182 endptr = line + 4; 183 } else if (!strncmp(line, "uboot", 5)) { 184 bf->flags |= 1ULL << BIF_FLAG_PART_OWNER_UBOOT; 185 endptr = line + 5; 186 } else { 187 printf("ERROR: Unknown partition type '%s'\n", line); 188 } 189 190 return endptr; 191 } 192 193 static const struct bif_flags bif_flags[] = { 194 { "fsbl_config", BIF_FLAG_FSBL_CONFIG }, 195 { "trustzone", BIF_FLAG_TZ }, 196 { "pmufw_image", BIF_FLAG_PMUFW_IMAGE }, 197 { "bootloader", BIF_FLAG_BOOTLOADER }, 198 { "destination_cpu=", 0, parse_dest_cpu }, 199 { "exception_level=", 0, parse_el }, 200 { "load=", 0, parse_load }, 201 { "startup=", 0, parse_entry }, 202 { "offset=", 0, parse_offset }, 203 { "partition_owner=", 0, parse_partition_owner }, 204 }; 205 206 static char *read_full_file(const char *filename, size_t *size) 207 { 208 char *buf, *bufp; 209 struct stat sbuf; 210 int len = 0, r, fd; 211 212 fd = open(filename, O_RDONLY); 213 if (fd < 0) 214 return NULL; 215 216 if (fstat(fd, &sbuf) < 0) 217 return NULL; 218 219 if (size) 220 *size = sbuf.st_size; 221 222 buf = malloc(sbuf.st_size); 223 if (!buf) 224 return NULL; 225 226 bufp = buf; 227 while (len < sbuf.st_size) { 228 r = read(fd, bufp, sbuf.st_size - len); 229 if (r < 0) 230 return NULL; 231 len += r; 232 bufp += r; 233 } 234 235 close(fd); 236 237 return buf; 238 } 239 240 static int bif_add_blob(const void *data, size_t len, size_t *offset) 241 { 242 size_t new_size; 243 uintptr_t header_off; 244 uintptr_t last_part_off; 245 uintptr_t imgheader_off; 246 uintptr_t old_data = (uintptr_t)bif_output.data; 247 void *new_data; 248 249 header_off = (uintptr_t)bif_output.header - old_data; 250 last_part_off = (uintptr_t)bif_output.last_part - old_data; 251 imgheader_off = (uintptr_t)bif_output.imgheader - old_data; 252 253 if (offset && *offset) { 254 /* Pad to a given offset */ 255 if (bif_output.data_len > *offset) { 256 printf("Can not pad to offset %zx\n", *offset); 257 return -1; 258 } 259 260 bif_output.data_len = *offset; 261 } 262 263 new_size = ROUND(bif_output.data_len + len, 64); 264 new_data = realloc(bif_output.data, new_size); 265 memcpy(new_data + bif_output.data_len, data, len); 266 if (offset) 267 *offset = bif_output.data_len; 268 bif_output.data = new_data; 269 bif_output.data_len = new_size; 270 271 /* Readjust internal pointers */ 272 if (bif_output.header) 273 bif_output.header = new_data + header_off; 274 if (bif_output.last_part) 275 bif_output.last_part = new_data + last_part_off; 276 if (bif_output.imgheader) 277 bif_output.imgheader = new_data + imgheader_off; 278 279 return 0; 280 } 281 282 static int bif_init(void) 283 { 284 struct zynqmp_header header = { { 0 } }; 285 int r; 286 287 zynqmpimage_default_header(&header); 288 289 r = bif_add_blob(&header, sizeof(header), NULL); 290 if (r) 291 return r; 292 293 bif_output.header = (void *)bif_output.data; 294 295 return 0; 296 } 297 298 static int bif_add_pmufw(struct bif_entry *bf, const char *data, size_t len) 299 { 300 int r; 301 302 if (bif_output.header->image_offset) { 303 printf("PMUFW expected before bootloader in your .bif file!\n"); 304 return -1; 305 } 306 307 r = bif_add_blob(data, len, &bf->offset); 308 if (r) 309 return r; 310 311 len = ROUND(len, 64); 312 bif_output.header->pfw_image_length = cpu_to_le32(len); 313 bif_output.header->total_pfw_image_length = cpu_to_le32(len); 314 bif_output.header->image_offset = cpu_to_le32(bf->offset); 315 316 return 0; 317 } 318 319 static int bif_add_part(struct bif_entry *bf, const char *data, size_t len) 320 { 321 size_t parthdr_offset = 0; 322 size_t len_padded = ROUND(len, 4); 323 324 struct partition_header parthdr = { 325 .len_enc = cpu_to_le32(len_padded / 4), 326 .len_unenc = cpu_to_le32(len_padded / 4), 327 .len = cpu_to_le32(len_padded / 4), 328 .entry_point = cpu_to_le64(bf->entry), 329 .load_address = cpu_to_le64(bf->load), 330 }; 331 int r; 332 uint32_t csum; 333 334 if (len < len_padded) { 335 char *newdata = malloc(len_padded); 336 memcpy(newdata, data, len); 337 memset(newdata + len, 0, len_padded - len); 338 data = newdata; 339 } 340 341 if (bf->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE)) 342 return bif_add_pmufw(bf, data, len); 343 344 r = bif_add_blob(data, len, &bf->offset); 345 if (r) 346 return r; 347 348 parthdr.offset = cpu_to_le32(bf->offset / 4); 349 350 if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) { 351 if (bif_output.last_part) { 352 printf("ERROR: Bootloader expected before others\n"); 353 return -1; 354 } 355 356 parthdr.offset = cpu_to_le32(bif_output.header->image_offset); 357 parthdr.len = cpu_to_le32((bf->offset + len - 358 bif_output.header->image_offset) / 4); 359 parthdr.len_enc = parthdr.len; 360 parthdr.len_unenc = parthdr.len; 361 } 362 363 /* Normalize EL */ 364 bf->exp_lvl = bf->exp_lvl ? bf->exp_lvl - 1 : 3; 365 parthdr.attributes |= bf->exp_lvl << PART_ATTR_TARGET_EL_SHIFT; 366 parthdr.attributes |= bf->dest_dev; 367 parthdr.attributes |= bf->dest_cpu; 368 if (bf->flags & (1ULL << BIF_FLAG_TZ)) 369 parthdr.attributes |= PART_ATTR_TZ_SECURE; 370 if (bf->flags & (1ULL << BIF_FLAG_PART_OWNER_UBOOT)) 371 parthdr.attributes |= PART_ATTR_PART_OWNER_UBOOT; 372 switch (bf->dest_cpu) { 373 case PART_ATTR_DEST_CPU_NONE: 374 case PART_ATTR_DEST_CPU_A53_0: 375 case PART_ATTR_DEST_CPU_A53_1: 376 case PART_ATTR_DEST_CPU_A53_2: 377 case PART_ATTR_DEST_CPU_A53_3: 378 if (bf->flags & (1ULL << BIF_FLAG_AARCH32)) 379 parthdr.attributes |= PART_ATTR_A53_EXEC_AARCH32; 380 } 381 382 csum = zynqmp_csum(&parthdr, &parthdr.checksum); 383 parthdr.checksum = cpu_to_le32(csum); 384 385 r = bif_add_blob(&parthdr, sizeof(parthdr), &parthdr_offset); 386 if (r) 387 return r; 388 389 /* Add image header table if not there yet */ 390 if (!bif_output.imgheader) { 391 size_t imghdr_off = 0; 392 struct image_header_table imghdr = { 393 .version = cpu_to_le32(0x01020000), 394 .nr_parts = 0, 395 }; 396 397 r = bif_add_blob(&imghdr, sizeof(imghdr), &imghdr_off); 398 if (r) 399 return r; 400 401 bif_output.header->image_header_table_offset = imghdr_off; 402 bif_output.imgheader = (void *)(bif_output.data + imghdr_off); 403 } 404 405 bif_output.imgheader->nr_parts = cpu_to_le32(le32_to_cpu( 406 bif_output.imgheader->nr_parts) + 1); 407 408 /* Link to this partition header */ 409 if (bif_output.last_part) { 410 bif_output.last_part->next_partition_offset = 411 cpu_to_le32(parthdr_offset / 4); 412 413 /* Recalc checksum of last_part */ 414 csum = zynqmp_csum(bif_output.last_part, 415 &bif_output.last_part->checksum); 416 bif_output.last_part->checksum = cpu_to_le32(csum); 417 } else { 418 bif_output.imgheader->partition_header_offset = 419 cpu_to_le32(parthdr_offset / 4); 420 } 421 bif_output.last_part = (void *)(bif_output.data + parthdr_offset); 422 423 if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) { 424 bif_output.header->image_load = cpu_to_le32(bf->load); 425 if (!bif_output.header->image_offset) 426 bif_output.header->image_offset = 427 cpu_to_le32(bf->offset); 428 bif_output.header->image_size = cpu_to_le32(len_padded); 429 bif_output.header->image_stored_size = cpu_to_le32(len_padded); 430 431 bif_output.header->image_attributes &= ~HEADER_CPU_SELECT_MASK; 432 switch (bf->dest_cpu) { 433 default: 434 case PART_ATTR_DEST_CPU_A53_0: 435 if (bf->flags & BIF_FLAG_AARCH32) 436 bif_output.header->image_attributes |= 437 HEADER_CPU_SELECT_A53_32BIT; 438 else 439 bif_output.header->image_attributes |= 440 HEADER_CPU_SELECT_A53_64BIT; 441 break; 442 case PART_ATTR_DEST_CPU_R5_0: 443 bif_output.header->image_attributes |= 444 HEADER_CPU_SELECT_R5_SINGLE; 445 break; 446 case PART_ATTR_DEST_CPU_R5_L: 447 bif_output.header->image_attributes |= 448 HEADER_CPU_SELECT_R5_DUAL; 449 break; 450 } 451 } 452 453 return 0; 454 } 455 456 /* Add .bit bitstream */ 457 static int bif_add_bit(struct bif_entry *bf) 458 { 459 char *bit = read_full_file(bf->filename, NULL); 460 char *bitbin; 461 uint8_t initial_header[] = { 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 462 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61 }; 463 uint16_t len; 464 uint32_t bitlen; 465 int i; 466 467 if (!bit) 468 return -1; 469 470 /* Skip initial header */ 471 if (memcmp(bit, initial_header, sizeof(initial_header))) 472 return -1; 473 474 bit += sizeof(initial_header); 475 476 /* Design name */ 477 len = be16_to_cpu(*(uint16_t *)bit); 478 bit += sizeof(uint16_t); 479 debug("Design: %s\n", bit); 480 bit += len; 481 482 /* Device identifier */ 483 if (*bit != 'b') 484 return -1; 485 bit++; 486 len = be16_to_cpu(*(uint16_t *)bit); 487 bit += sizeof(uint16_t); 488 debug("Device: %s\n", bit); 489 bit += len; 490 491 /* Date */ 492 if (*bit != 'c') 493 return -1; 494 bit++; 495 len = be16_to_cpu(*(uint16_t *)bit); 496 bit += sizeof(uint16_t); 497 debug("Date: %s\n", bit); 498 bit += len; 499 500 /* Time */ 501 if (*bit != 'd') 502 return -1; 503 bit++; 504 len = be16_to_cpu(*(uint16_t *)bit); 505 bit += sizeof(uint16_t); 506 debug("Time: %s\n", bit); 507 bit += len; 508 509 /* Bitstream length */ 510 if (*bit != 'e') 511 return -1; 512 bit++; 513 bitlen = be32_to_cpu(*(uint32_t *)bit); 514 bit += sizeof(uint32_t); 515 bitbin = bit; 516 517 debug("Bitstream Length: 0x%x\n", bitlen); 518 for (i = 0; i < bitlen; i += sizeof(uint32_t)) { 519 uint32_t *bitbin32 = (uint32_t *)&bitbin[i]; 520 *bitbin32 = __swab32(*bitbin32); 521 } 522 523 if (!bf->dest_dev) 524 bf->dest_dev = PART_ATTR_DEST_DEVICE_PL; 525 526 bf->load = 0xffffffff; 527 bf->entry = 0; 528 529 bf->flags |= 1ULL << BIF_FLAG_BIT_FILE; 530 return bif_add_part(bf, bit, bitlen); 531 } 532 533 /* Add .bin bitstream */ 534 static int bif_add_bin(struct bif_entry *bf) 535 { 536 size_t size; 537 char *bin = read_full_file(bf->filename, &size); 538 539 if (!bf->dest_dev) 540 bf->dest_dev = PART_ATTR_DEST_DEVICE_PS; 541 542 bf->flags |= 1ULL << BIF_FLAG_BIN_FILE; 543 return bif_add_part(bf, bin, size); 544 } 545 546 /* Add elf file */ 547 static char *elf2flat64(char *elf, size_t *flat_size, size_t *load_addr) 548 { 549 Elf64_Ehdr *ehdr; 550 Elf64_Shdr *shdr; 551 size_t min_addr = -1, max_addr = 0; 552 char *flat; 553 int i; 554 555 ehdr = (void *)elf; 556 shdr = (void *)(elf + le64_to_cpu(ehdr->e_shoff)); 557 558 /* Look for smallest / biggest address */ 559 for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++, shdr++) { 560 if (!shdr->sh_size || !shdr->sh_addr || 561 !(shdr->sh_flags & SHF_ALLOC) || 562 (shdr->sh_type == SHT_NOBITS)) 563 continue; 564 565 if (le64_to_cpu(shdr->sh_addr) < min_addr) 566 min_addr = le64_to_cpu(shdr->sh_addr); 567 if ((le64_to_cpu(shdr->sh_addr) + le64_to_cpu(shdr->sh_size)) > 568 max_addr) 569 max_addr = le64_to_cpu(shdr->sh_addr) + 570 le64_to_cpu(shdr->sh_size); 571 } 572 573 *load_addr = min_addr; 574 *flat_size = max_addr - min_addr; 575 flat = calloc(1, *flat_size); 576 if (!flat) 577 return NULL; 578 579 shdr = (void *)(elf + le64_to_cpu(ehdr->e_shoff)); 580 for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++, shdr++) { 581 char *dst = flat + le64_to_cpu(shdr->sh_addr) - min_addr; 582 char *src = elf + le64_to_cpu(shdr->sh_offset); 583 584 if (!shdr->sh_size || !shdr->sh_addr || 585 !(shdr->sh_flags & SHF_ALLOC)) 586 continue; 587 588 if (shdr->sh_type != SHT_NOBITS) 589 memcpy(dst, src, le64_to_cpu(shdr->sh_size)); 590 } 591 592 return flat; 593 } 594 595 static char *elf2flat32(char *elf, size_t *flat_size, size_t *load_addr) 596 { 597 Elf32_Ehdr *ehdr; 598 Elf32_Shdr *shdr; 599 size_t min_addr = -1, max_addr = 0; 600 char *flat; 601 int i; 602 603 ehdr = (void *)elf; 604 shdr = (void *)(elf + le32_to_cpu(ehdr->e_shoff)); 605 606 /* Look for smallest / biggest address */ 607 for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++, shdr++) { 608 if (!shdr->sh_size || !shdr->sh_addr || 609 !(shdr->sh_flags & SHF_ALLOC) || 610 (shdr->sh_type == SHT_NOBITS)) 611 continue; 612 613 if (le32_to_cpu(shdr->sh_addr) < min_addr) 614 min_addr = le32_to_cpu(shdr->sh_addr); 615 if ((le32_to_cpu(shdr->sh_addr) + le32_to_cpu(shdr->sh_size)) > 616 max_addr) 617 max_addr = le32_to_cpu(shdr->sh_addr) + 618 le32_to_cpu(shdr->sh_size); 619 } 620 621 *load_addr = min_addr; 622 *flat_size = max_addr - min_addr; 623 flat = calloc(1, *flat_size); 624 if (!flat) 625 return NULL; 626 627 shdr = (void *)(elf + le32_to_cpu(ehdr->e_shoff)); 628 for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++, shdr++) { 629 char *dst = flat + le32_to_cpu(shdr->sh_addr) - min_addr; 630 char *src = elf + le32_to_cpu(shdr->sh_offset); 631 632 if (!shdr->sh_size || !shdr->sh_addr || 633 !(shdr->sh_flags & SHF_ALLOC)) 634 continue; 635 636 if (shdr->sh_type != SHT_NOBITS) 637 memcpy(dst, src, le32_to_cpu(shdr->sh_size)); 638 } 639 640 return flat; 641 } 642 643 static int bif_add_elf(struct bif_entry *bf) 644 { 645 size_t size; 646 size_t elf_size; 647 char *elf; 648 char *flat; 649 size_t load_addr; 650 Elf32_Ehdr *ehdr32; 651 Elf64_Ehdr *ehdr64; 652 653 elf = read_full_file(bf->filename, &elf_size); 654 if (!elf) 655 return -1; 656 657 ehdr32 = (void *)elf; 658 ehdr64 = (void *)elf; 659 660 switch (ehdr32->e_ident[EI_CLASS]) { 661 case ELFCLASS32: 662 flat = elf2flat32(elf, &size, &load_addr); 663 bf->entry = le32_to_cpu(ehdr32->e_entry); 664 bf->flags |= 1ULL << BIF_FLAG_AARCH32; 665 break; 666 case ELFCLASS64: 667 flat = elf2flat64(elf, &size, &load_addr); 668 bf->entry = le64_to_cpu(ehdr64->e_entry); 669 break; 670 default: 671 printf("Unknown ELF class: %d\n", ehdr32->e_ident[EI_CLASS]); 672 return -1; 673 } 674 675 if (!flat) 676 return -1; 677 678 bf->load = load_addr; 679 if (!bf->dest_dev) 680 bf->dest_dev = PART_ATTR_DEST_DEVICE_PS; 681 682 bf->flags |= 1ULL << BIF_FLAG_ELF_FILE; 683 return bif_add_part(bf, flat, size); 684 } 685 686 static const struct bif_file_type bif_file_types[] = { 687 { 688 .name = "bitstream (.bit)", 689 .header = 0x00090ff0, 690 .add = bif_add_bit, 691 }, 692 693 { 694 .name = "ELF", 695 .header = 0x7f454c46, 696 .add = bif_add_elf, 697 }, 698 699 /* Anything else is a .bin file */ 700 { 701 .name = ".bin", 702 .add = bif_add_bin, 703 }, 704 }; 705 706 static int bif_fsbl_config(struct bif_entry *fsbl_config, 707 struct bif_entry *entries, int nr_entries) 708 { 709 int i; 710 int config_set = 0; 711 struct { 712 const char *name; 713 uint64_t flags; 714 uint64_t dest_cpu; 715 } configs[] = { 716 { .name = "a5x_x64", .dest_cpu = PART_ATTR_DEST_CPU_A53_0 }, 717 { .name = "a53_x64", .dest_cpu = PART_ATTR_DEST_CPU_A53_0 }, 718 { .name = "a5x_x32", .dest_cpu = PART_ATTR_DEST_CPU_A53_0, 719 .flags = 1ULL << BIF_FLAG_AARCH32 }, 720 { .name = "a53_x32", .dest_cpu = PART_ATTR_DEST_CPU_A53_0, 721 .flags = 1ULL << BIF_FLAG_AARCH32 }, 722 { .name = "r5_single", .dest_cpu = PART_ATTR_DEST_CPU_R5_0 }, 723 { .name = "r5_dual", .dest_cpu = PART_ATTR_DEST_CPU_R5_L }, 724 }; 725 726 /* Set target CPU of bootloader entry */ 727 for (i = 0; i < nr_entries; i++) { 728 struct bif_entry *b = &entries[i]; 729 const char *config_attr = fsbl_config->filename; 730 int j; 731 732 if (!(b->flags & (1ULL << BIF_FLAG_BOOTLOADER))) 733 continue; 734 735 for (j = 0; j < ARRAY_SIZE(configs); j++) { 736 if (!strncmp(config_attr, configs[j].name, 737 strlen(configs[j].name))) { 738 b->dest_cpu = configs[j].dest_cpu; 739 b->flags |= configs[j].flags; 740 config_set = 1; 741 } 742 } 743 744 if (!config_set) { 745 printf("ERROR: Unsupported fsbl_config: %s\n", 746 config_attr); 747 return -1; 748 } 749 } 750 751 if (!config_set) { 752 printf("ERROR: fsbl_config w/o bootloader\n"); 753 return -1; 754 } 755 756 return 0; 757 } 758 759 static const struct bif_flags *find_flag(char *str) 760 { 761 const struct bif_flags *bf; 762 int i; 763 764 for (i = 0; i < ARRAY_SIZE(bif_flags); i++) { 765 bf = &bif_flags[i]; 766 if (!strncmp(bf->name, str, strlen(bf->name))) 767 return bf; 768 } 769 770 printf("ERROR: Flag '%s' not found\n", str); 771 772 return NULL; 773 } 774 775 static int bif_open_file(struct bif_entry *entry) 776 { 777 int fd = open(entry->filename, O_RDONLY); 778 779 if (fd < 0) 780 printf("Error opening file %s\n", entry->filename); 781 782 return fd; 783 } 784 785 static const struct bif_file_type *get_file_type(struct bif_entry *entry) 786 { 787 int fd = bif_open_file(entry); 788 uint32_t header; 789 int i; 790 791 if (fd < 0) 792 return NULL; 793 794 if (read(fd, &header, sizeof(header)) != sizeof(header)) { 795 printf("Error reading file %s", entry->filename); 796 return NULL; 797 } 798 799 close(fd); 800 801 for (i = 0; i < ARRAY_SIZE(bif_file_types); i++) { 802 const struct bif_file_type *type = &bif_file_types[i]; 803 804 if (!type->header) 805 return type; 806 if (type->header == be32_to_cpu(header)) 807 return type; 808 } 809 810 return NULL; 811 } 812 813 #define NEXT_CHAR(str, chr) ({ \ 814 char *_n = strchr(str, chr); \ 815 if (!_n) \ 816 goto err; \ 817 _n; \ 818 }) 819 820 static char *skip_whitespace(char *str) 821 { 822 while (*str == ' ' || *str == '\t') 823 str++; 824 825 return str; 826 } 827 828 int zynqmpbif_copy_image(int outfd, struct image_tool_params *mparams) 829 { 830 char *bif, *bifp, *bifpn; 831 char *line; 832 struct bif_entry entries[32] = { { 0 } }; 833 int nr_entries = 0; 834 struct bif_entry *entry = entries; 835 size_t len; 836 int i; 837 uint32_t csum; 838 int bldr = -1; 839 840 bif_init(); 841 842 /* Read .bif input file */ 843 bif = read_full_file(mparams->datafile, NULL); 844 if (!bif) 845 goto err; 846 847 /* Interpret .bif file */ 848 bifp = bif; 849 850 /* A bif description starts with a { section */ 851 bifp = NEXT_CHAR(bifp, '{') + 1; 852 853 /* Read every line */ 854 while (1) { 855 bifpn = NEXT_CHAR(bifp, '\n'); 856 857 if (bifpn[-1] == '\r') 858 bifpn[-1] = '\0'; 859 860 *bifpn = '\0'; 861 bifpn++; 862 line = bifp; 863 864 line = skip_whitespace(line); 865 866 /* Attributes? */ 867 if (*line == '[') { 868 line++; 869 while (1) { 870 const struct bif_flags *bf; 871 872 line = skip_whitespace(line); 873 bf = find_flag(line); 874 if (!bf) 875 goto err; 876 877 line += strlen(bf->name); 878 if (bf->parse) 879 line = bf->parse(line, entry); 880 else 881 entry->flags |= 1ULL << bf->flag; 882 883 if (!line) 884 goto err; 885 886 /* Go to next attribute or quit */ 887 if (*line == ']') { 888 line++; 889 break; 890 } 891 if (*line == ',') 892 line++; 893 } 894 } 895 896 /* End of image description */ 897 if (*line == '}') 898 break; 899 900 if (*line) { 901 line = skip_whitespace(line); 902 entry->filename = line; 903 nr_entries++; 904 entry++; 905 } 906 907 /* Use next line */ 908 bifp = bifpn; 909 } 910 911 for (i = 0; i < nr_entries; i++) { 912 debug("Entry flags=%#lx name=%s\n", entries[i].flags, 913 entries[i].filename); 914 } 915 916 /* 917 * Some entries are actually configuration option for other ones, 918 * let's apply them in an intermediate step. 919 */ 920 for (i = 0; i < nr_entries; i++) { 921 struct bif_entry *entry = &entries[i]; 922 923 if (entry->flags & (1ULL << BIF_FLAG_FSBL_CONFIG)) 924 if (bif_fsbl_config(entry, entries, nr_entries)) 925 goto err; 926 } 927 928 /* Make sure PMUFW comes before bootloader */ 929 for (i = 0; i < nr_entries; i++) { 930 struct bif_entry *entry = &entries[i]; 931 932 if (entry->flags & (1ULL << BIF_FLAG_BOOTLOADER)) 933 bldr = i; 934 if (entry->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE)) { 935 if (bldr >= 0) { 936 struct bif_entry tmp = *entry; 937 938 *entry = entries[bldr]; 939 entries[bldr] = tmp; 940 } 941 } 942 } 943 944 for (i = 0; i < nr_entries; i++) { 945 struct bif_entry *entry = &entries[i]; 946 const struct bif_file_type *type; 947 int r; 948 949 if (entry->flags & (1ULL << BIF_FLAG_FSBL_CONFIG)) 950 continue; 951 952 type = get_file_type(entry); 953 if (!type) 954 goto err; 955 956 debug("type=%s file=%s\n", type->name, entry->filename); 957 r = type->add(entry); 958 if (r) 959 goto err; 960 } 961 962 /* Calculate checksums */ 963 csum = zynqmp_csum(&bif_output.header->width_detection, 964 &bif_output.header->checksum); 965 bif_output.header->checksum = cpu_to_le32(csum); 966 967 if (bif_output.imgheader) { 968 csum = zynqmp_csum(bif_output.imgheader, 969 &bif_output.imgheader->checksum); 970 bif_output.imgheader->checksum = cpu_to_le32(csum); 971 } 972 973 /* Write headers and components */ 974 if (lseek(outfd, 0, SEEK_SET) != 0) 975 goto err; 976 977 len = bif_output.data_len; 978 bifp = bif_output.data; 979 while (len) { 980 int r; 981 982 r = write(outfd, bifp, len); 983 if (r < 0) 984 goto err; 985 len -= r; 986 bifp += r; 987 } 988 989 return 0; 990 991 err: 992 fprintf(stderr, "Error: Failed to create image.\n"); 993 return -1; 994 } 995 996 /* Needs to be stubbed out so we can print after creation */ 997 static void zynqmpbif_set_header(void *ptr, struct stat *sbuf, int ifd, 998 struct image_tool_params *params) 999 { 1000 } 1001 1002 static struct zynqmp_header zynqmpimage_header; 1003 1004 U_BOOT_IMAGE_TYPE( 1005 zynqmpbif, 1006 "Xilinx ZynqMP Boot Image support (bif)", 1007 sizeof(struct zynqmp_header), 1008 (void *)&zynqmpimage_header, 1009 zynqmpbif_check_params, 1010 NULL, 1011 zynqmpimage_print_header, 1012 zynqmpbif_set_header, 1013 NULL, 1014 zynqmpbif_check_image_types, 1015 NULL, 1016 NULL 1017 ); 1018