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 struct partition_header parthdr = { 323 .len_enc = cpu_to_le32(len / 4), 324 .len_unenc = cpu_to_le32(len / 4), 325 .len = cpu_to_le32(len / 4), 326 .entry_point = cpu_to_le64(bf->entry), 327 .load_address = cpu_to_le64(bf->load), 328 }; 329 int r; 330 uint32_t csum; 331 332 if (bf->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE)) 333 return bif_add_pmufw(bf, data, len); 334 335 r = bif_add_blob(data, len, &bf->offset); 336 if (r) 337 return r; 338 339 parthdr.offset = cpu_to_le32(bf->offset / 4); 340 341 if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) { 342 if (bif_output.last_part) { 343 printf("ERROR: Bootloader expected before others\n"); 344 return -1; 345 } 346 347 parthdr.offset = cpu_to_le32(bif_output.header->image_offset); 348 parthdr.len = cpu_to_le32((bf->offset + len - 349 bif_output.header->image_offset) / 4); 350 parthdr.len_enc = parthdr.len; 351 parthdr.len_unenc = parthdr.len; 352 } 353 354 /* Normalize EL */ 355 bf->exp_lvl = bf->exp_lvl ? bf->exp_lvl - 1 : 3; 356 parthdr.attributes |= bf->exp_lvl << PART_ATTR_TARGET_EL_SHIFT; 357 parthdr.attributes |= bf->dest_dev; 358 parthdr.attributes |= bf->dest_cpu; 359 if (bf->flags & (1ULL << BIF_FLAG_TZ)) 360 parthdr.attributes |= PART_ATTR_TZ_SECURE; 361 if (bf->flags & (1ULL << BIF_FLAG_PART_OWNER_UBOOT)) 362 parthdr.attributes |= PART_ATTR_PART_OWNER_UBOOT; 363 switch (bf->dest_cpu) { 364 case PART_ATTR_DEST_CPU_NONE: 365 case PART_ATTR_DEST_CPU_A53_0: 366 case PART_ATTR_DEST_CPU_A53_1: 367 case PART_ATTR_DEST_CPU_A53_2: 368 case PART_ATTR_DEST_CPU_A53_3: 369 if (bf->flags & (1ULL << BIF_FLAG_AARCH32)) 370 parthdr.attributes |= PART_ATTR_A53_EXEC_AARCH32; 371 } 372 373 csum = zynqmp_csum(&parthdr, &parthdr.checksum); 374 parthdr.checksum = cpu_to_le32(csum); 375 376 r = bif_add_blob(&parthdr, sizeof(parthdr), &parthdr_offset); 377 if (r) 378 return r; 379 380 /* Add image header table if not there yet */ 381 if (!bif_output.imgheader) { 382 size_t imghdr_off = 0; 383 struct image_header_table imghdr = { 384 .version = cpu_to_le32(0x01020000), 385 .nr_parts = 0, 386 }; 387 388 r = bif_add_blob(&imghdr, sizeof(imghdr), &imghdr_off); 389 if (r) 390 return r; 391 392 bif_output.header->image_header_table_offset = imghdr_off; 393 bif_output.imgheader = (void *)(bif_output.data + imghdr_off); 394 } 395 396 bif_output.imgheader->nr_parts = cpu_to_le32(le32_to_cpu( 397 bif_output.imgheader->nr_parts) + 1); 398 399 /* Link to this partition header */ 400 if (bif_output.last_part) { 401 bif_output.last_part->next_partition_offset = 402 cpu_to_le32(parthdr_offset / 4); 403 404 /* Recalc checksum of last_part */ 405 csum = zynqmp_csum(bif_output.last_part, 406 &bif_output.last_part->checksum); 407 bif_output.last_part->checksum = cpu_to_le32(csum); 408 } else { 409 bif_output.imgheader->partition_header_offset = 410 cpu_to_le32(parthdr_offset / 4); 411 } 412 bif_output.last_part = (void *)(bif_output.data + parthdr_offset); 413 414 if (bf->flags & (1ULL << BIF_FLAG_BOOTLOADER)) { 415 bif_output.header->image_load = cpu_to_le32(bf->load); 416 if (!bif_output.header->image_offset) 417 bif_output.header->image_offset = 418 cpu_to_le32(bf->offset); 419 bif_output.header->image_size = cpu_to_le32(len); 420 bif_output.header->image_stored_size = cpu_to_le32(len); 421 422 bif_output.header->image_attributes &= ~HEADER_CPU_SELECT_MASK; 423 switch (bf->dest_cpu) { 424 default: 425 case PART_ATTR_DEST_CPU_A53_0: 426 if (bf->flags & BIF_FLAG_AARCH32) 427 bif_output.header->image_attributes |= 428 HEADER_CPU_SELECT_A53_32BIT; 429 else 430 bif_output.header->image_attributes |= 431 HEADER_CPU_SELECT_A53_64BIT; 432 break; 433 case PART_ATTR_DEST_CPU_R5_0: 434 bif_output.header->image_attributes |= 435 HEADER_CPU_SELECT_R5_SINGLE; 436 break; 437 case PART_ATTR_DEST_CPU_R5_L: 438 bif_output.header->image_attributes |= 439 HEADER_CPU_SELECT_R5_DUAL; 440 break; 441 } 442 } 443 444 return 0; 445 } 446 447 /* Add .bit bitstream */ 448 static int bif_add_bit(struct bif_entry *bf) 449 { 450 char *bit = read_full_file(bf->filename, NULL); 451 char *bitbin; 452 uint8_t initial_header[] = { 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 453 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61 }; 454 uint16_t len; 455 uint32_t bitlen; 456 int i; 457 458 if (!bit) 459 return -1; 460 461 /* Skip initial header */ 462 if (memcmp(bit, initial_header, sizeof(initial_header))) 463 return -1; 464 465 bit += sizeof(initial_header); 466 467 /* Design name */ 468 len = be16_to_cpu(*(uint16_t *)bit); 469 bit += sizeof(uint16_t); 470 debug("Design: %s\n", bit); 471 bit += len; 472 473 /* Device identifier */ 474 if (*bit != 'b') 475 return -1; 476 bit++; 477 len = be16_to_cpu(*(uint16_t *)bit); 478 bit += sizeof(uint16_t); 479 debug("Device: %s\n", bit); 480 bit += len; 481 482 /* Date */ 483 if (*bit != 'c') 484 return -1; 485 bit++; 486 len = be16_to_cpu(*(uint16_t *)bit); 487 bit += sizeof(uint16_t); 488 debug("Date: %s\n", bit); 489 bit += len; 490 491 /* Time */ 492 if (*bit != 'd') 493 return -1; 494 bit++; 495 len = be16_to_cpu(*(uint16_t *)bit); 496 bit += sizeof(uint16_t); 497 debug("Time: %s\n", bit); 498 bit += len; 499 500 /* Bitstream length */ 501 if (*bit != 'e') 502 return -1; 503 bit++; 504 bitlen = be32_to_cpu(*(uint32_t *)bit); 505 bit += sizeof(uint32_t); 506 bitbin = bit; 507 508 debug("Bitstream Length: 0x%x\n", bitlen); 509 for (i = 0; i < bitlen; i += sizeof(uint32_t)) { 510 uint32_t *bitbin32 = (uint32_t *)&bitbin[i]; 511 *bitbin32 = __swab32(*bitbin32); 512 } 513 514 if (!bf->dest_dev) 515 bf->dest_dev = PART_ATTR_DEST_DEVICE_PL; 516 517 bf->load = 0xffffffff; 518 bf->entry = 0; 519 520 bf->flags |= 1ULL << BIF_FLAG_BIT_FILE; 521 return bif_add_part(bf, bit, bitlen); 522 } 523 524 /* Add .bin bitstream */ 525 static int bif_add_bin(struct bif_entry *bf) 526 { 527 size_t size; 528 char *bin = read_full_file(bf->filename, &size); 529 530 if (!bf->dest_dev) 531 bf->dest_dev = PART_ATTR_DEST_DEVICE_PS; 532 533 bf->flags |= 1ULL << BIF_FLAG_BIN_FILE; 534 return bif_add_part(bf, bin, size); 535 } 536 537 /* Add elf file */ 538 static char *elf2flat64(char *elf, size_t *flat_size, size_t *load_addr) 539 { 540 Elf64_Ehdr *ehdr; 541 Elf64_Shdr *shdr; 542 size_t min_addr = -1, max_addr = 0; 543 char *flat; 544 int i; 545 546 ehdr = (void *)elf; 547 shdr = (void *)(elf + le64_to_cpu(ehdr->e_shoff)); 548 549 /* Look for smallest / biggest address */ 550 for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++, shdr++) { 551 if (!shdr->sh_size || !shdr->sh_addr || 552 !(shdr->sh_flags & SHF_ALLOC) || 553 (shdr->sh_type == SHT_NOBITS)) 554 continue; 555 556 if (le64_to_cpu(shdr->sh_addr) < min_addr) 557 min_addr = le64_to_cpu(shdr->sh_addr); 558 if ((le64_to_cpu(shdr->sh_addr) + le64_to_cpu(shdr->sh_size)) > 559 max_addr) 560 max_addr = le64_to_cpu(shdr->sh_addr) + 561 le64_to_cpu(shdr->sh_size); 562 } 563 564 *load_addr = min_addr; 565 *flat_size = max_addr - min_addr; 566 flat = calloc(1, *flat_size); 567 if (!flat) 568 return NULL; 569 570 shdr = (void *)(elf + le64_to_cpu(ehdr->e_shoff)); 571 for (i = 0; i < le64_to_cpu(ehdr->e_shnum); i++, shdr++) { 572 char *dst = flat + le64_to_cpu(shdr->sh_addr) - min_addr; 573 char *src = elf + le64_to_cpu(shdr->sh_offset); 574 575 if (!shdr->sh_size || !shdr->sh_addr || 576 !(shdr->sh_flags & SHF_ALLOC)) 577 continue; 578 579 if (shdr->sh_type != SHT_NOBITS) 580 memcpy(dst, src, le64_to_cpu(shdr->sh_size)); 581 } 582 583 return flat; 584 } 585 586 static char *elf2flat32(char *elf, size_t *flat_size, size_t *load_addr) 587 { 588 Elf32_Ehdr *ehdr; 589 Elf32_Shdr *shdr; 590 size_t min_addr = -1, max_addr = 0; 591 char *flat; 592 int i; 593 594 ehdr = (void *)elf; 595 shdr = (void *)(elf + le32_to_cpu(ehdr->e_shoff)); 596 597 /* Look for smallest / biggest address */ 598 for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++, shdr++) { 599 if (!shdr->sh_size || !shdr->sh_addr || 600 !(shdr->sh_flags & SHF_ALLOC) || 601 (shdr->sh_type == SHT_NOBITS)) 602 continue; 603 604 if (le32_to_cpu(shdr->sh_addr) < min_addr) 605 min_addr = le32_to_cpu(shdr->sh_addr); 606 if ((le32_to_cpu(shdr->sh_addr) + le32_to_cpu(shdr->sh_size)) > 607 max_addr) 608 max_addr = le32_to_cpu(shdr->sh_addr) + 609 le32_to_cpu(shdr->sh_size); 610 } 611 612 *load_addr = min_addr; 613 *flat_size = max_addr - min_addr; 614 flat = calloc(1, *flat_size); 615 if (!flat) 616 return NULL; 617 618 shdr = (void *)(elf + le32_to_cpu(ehdr->e_shoff)); 619 for (i = 0; i < le32_to_cpu(ehdr->e_shnum); i++, shdr++) { 620 char *dst = flat + le32_to_cpu(shdr->sh_addr) - min_addr; 621 char *src = elf + le32_to_cpu(shdr->sh_offset); 622 623 if (!shdr->sh_size || !shdr->sh_addr || 624 !(shdr->sh_flags & SHF_ALLOC)) 625 continue; 626 627 if (shdr->sh_type != SHT_NOBITS) 628 memcpy(dst, src, le32_to_cpu(shdr->sh_size)); 629 } 630 631 return flat; 632 } 633 634 static int bif_add_elf(struct bif_entry *bf) 635 { 636 size_t size; 637 size_t elf_size; 638 char *elf; 639 char *flat; 640 size_t load_addr; 641 Elf32_Ehdr *ehdr32; 642 Elf64_Ehdr *ehdr64; 643 644 elf = read_full_file(bf->filename, &elf_size); 645 if (!elf) 646 return -1; 647 648 ehdr32 = (void *)elf; 649 ehdr64 = (void *)elf; 650 651 switch (ehdr32->e_ident[EI_CLASS]) { 652 case ELFCLASS32: 653 flat = elf2flat32(elf, &size, &load_addr); 654 bf->entry = le32_to_cpu(ehdr32->e_entry); 655 bf->flags |= 1ULL << BIF_FLAG_AARCH32; 656 break; 657 case ELFCLASS64: 658 flat = elf2flat64(elf, &size, &load_addr); 659 bf->entry = le64_to_cpu(ehdr64->e_entry); 660 break; 661 default: 662 printf("Unknown ELF class: %d\n", ehdr32->e_ident[EI_CLASS]); 663 return -1; 664 } 665 666 if (!flat) 667 return -1; 668 669 bf->load = load_addr; 670 if (!bf->dest_dev) 671 bf->dest_dev = PART_ATTR_DEST_DEVICE_PS; 672 673 bf->flags |= 1ULL << BIF_FLAG_ELF_FILE; 674 return bif_add_part(bf, flat, size); 675 } 676 677 static const struct bif_file_type bif_file_types[] = { 678 { 679 .name = "bitstream (.bit)", 680 .header = 0x00090ff0, 681 .add = bif_add_bit, 682 }, 683 684 { 685 .name = "ELF", 686 .header = 0x7f454c46, 687 .add = bif_add_elf, 688 }, 689 690 /* Anything else is a .bin file */ 691 { 692 .name = ".bin", 693 .add = bif_add_bin, 694 }, 695 }; 696 697 static int bif_fsbl_config(struct bif_entry *fsbl_config, 698 struct bif_entry *entries, int nr_entries) 699 { 700 int i; 701 int config_set = 0; 702 struct { 703 const char *name; 704 uint64_t flags; 705 uint64_t dest_cpu; 706 } configs[] = { 707 { .name = "a5x_x64", .dest_cpu = PART_ATTR_DEST_CPU_A53_0 }, 708 { .name = "a53_x64", .dest_cpu = PART_ATTR_DEST_CPU_A53_0 }, 709 { .name = "a5x_x32", .dest_cpu = PART_ATTR_DEST_CPU_A53_0, 710 .flags = 1ULL << BIF_FLAG_AARCH32 }, 711 { .name = "a53_x32", .dest_cpu = PART_ATTR_DEST_CPU_A53_0, 712 .flags = 1ULL << BIF_FLAG_AARCH32 }, 713 { .name = "r5_single", .dest_cpu = PART_ATTR_DEST_CPU_R5_0 }, 714 { .name = "r5_dual", .dest_cpu = PART_ATTR_DEST_CPU_R5_L }, 715 }; 716 717 /* Set target CPU of bootloader entry */ 718 for (i = 0; i < nr_entries; i++) { 719 struct bif_entry *b = &entries[i]; 720 const char *config_attr = fsbl_config->filename; 721 int j; 722 723 if (!(b->flags & (1ULL << BIF_FLAG_BOOTLOADER))) 724 continue; 725 726 for (j = 0; j < ARRAY_SIZE(configs); j++) { 727 if (!strncmp(config_attr, configs[j].name, 728 strlen(configs[j].name))) { 729 b->dest_cpu = configs[j].dest_cpu; 730 b->flags |= configs[j].flags; 731 config_set = 1; 732 } 733 } 734 735 if (!config_set) { 736 printf("ERROR: Unsupported fsbl_config: %s\n", 737 config_attr); 738 return -1; 739 } 740 } 741 742 if (!config_set) { 743 printf("ERROR: fsbl_config w/o bootloader\n"); 744 return -1; 745 } 746 747 return 0; 748 } 749 750 static const struct bif_flags *find_flag(char *str) 751 { 752 const struct bif_flags *bf; 753 int i; 754 755 for (i = 0; i < ARRAY_SIZE(bif_flags); i++) { 756 bf = &bif_flags[i]; 757 if (!strncmp(bf->name, str, strlen(bf->name))) 758 return bf; 759 } 760 761 printf("ERROR: Flag '%s' not found\n", str); 762 763 return NULL; 764 } 765 766 static int bif_open_file(struct bif_entry *entry) 767 { 768 int fd = open(entry->filename, O_RDONLY); 769 770 if (fd < 0) 771 printf("Error opening file %s\n", entry->filename); 772 773 return fd; 774 } 775 776 static const struct bif_file_type *get_file_type(struct bif_entry *entry) 777 { 778 int fd = bif_open_file(entry); 779 uint32_t header; 780 int i; 781 782 if (fd < 0) 783 return NULL; 784 785 if (read(fd, &header, sizeof(header)) != sizeof(header)) { 786 printf("Error reading file %s", entry->filename); 787 return NULL; 788 } 789 790 close(fd); 791 792 for (i = 0; i < ARRAY_SIZE(bif_file_types); i++) { 793 const struct bif_file_type *type = &bif_file_types[i]; 794 795 if (!type->header) 796 return type; 797 if (type->header == be32_to_cpu(header)) 798 return type; 799 } 800 801 return NULL; 802 } 803 804 #define NEXT_CHAR(str, chr) ({ \ 805 char *_n = strchr(str, chr); \ 806 if (!_n) \ 807 goto err; \ 808 _n; \ 809 }) 810 811 static char *skip_whitespace(char *str) 812 { 813 while (*str == ' ' || *str == '\t') 814 str++; 815 816 return str; 817 } 818 819 int zynqmpbif_copy_image(int outfd, struct image_tool_params *mparams) 820 { 821 char *bif, *bifp, *bifpn; 822 char *line; 823 struct bif_entry entries[32] = { { 0 } }; 824 int nr_entries = 0; 825 struct bif_entry *entry = entries; 826 size_t len; 827 int i; 828 uint32_t csum; 829 int bldr = -1; 830 831 bif_init(); 832 833 /* Read .bif input file */ 834 bif = read_full_file(mparams->datafile, NULL); 835 if (!bif) 836 goto err; 837 838 /* Interpret .bif file */ 839 bifp = bif; 840 841 /* A bif description starts with a { section */ 842 bifp = NEXT_CHAR(bifp, '{') + 1; 843 844 /* Read every line */ 845 while (1) { 846 bifpn = NEXT_CHAR(bifp, '\n'); 847 848 if (bifpn[-1] == '\r') 849 bifpn[-1] = '\0'; 850 851 *bifpn = '\0'; 852 bifpn++; 853 line = bifp; 854 855 line = skip_whitespace(line); 856 857 /* Attributes? */ 858 if (*line == '[') { 859 line++; 860 while (1) { 861 const struct bif_flags *bf; 862 863 line = skip_whitespace(line); 864 bf = find_flag(line); 865 if (!bf) 866 goto err; 867 868 line += strlen(bf->name); 869 if (bf->parse) 870 line = bf->parse(line, entry); 871 else 872 entry->flags |= 1ULL << bf->flag; 873 874 if (!line) 875 goto err; 876 877 /* Go to next attribute or quit */ 878 if (*line == ']') { 879 line++; 880 break; 881 } 882 if (*line == ',') 883 line++; 884 } 885 } 886 887 /* End of image description */ 888 if (*line == '}') 889 break; 890 891 if (*line) { 892 line = skip_whitespace(line); 893 entry->filename = line; 894 nr_entries++; 895 entry++; 896 } 897 898 /* Use next line */ 899 bifp = bifpn; 900 } 901 902 for (i = 0; i < nr_entries; i++) { 903 debug("Entry flags=%#lx name=%s\n", entries[i].flags, 904 entries[i].filename); 905 } 906 907 /* 908 * Some entries are actually configuration option for other ones, 909 * let's apply them in an intermediate step. 910 */ 911 for (i = 0; i < nr_entries; i++) { 912 struct bif_entry *entry = &entries[i]; 913 914 if (entry->flags & (1ULL << BIF_FLAG_FSBL_CONFIG)) 915 if (bif_fsbl_config(entry, entries, nr_entries)) 916 goto err; 917 } 918 919 /* Make sure PMUFW comes before bootloader */ 920 for (i = 0; i < nr_entries; i++) { 921 struct bif_entry *entry = &entries[i]; 922 923 if (entry->flags & (1ULL << BIF_FLAG_BOOTLOADER)) 924 bldr = i; 925 if (entry->flags & (1ULL << BIF_FLAG_PMUFW_IMAGE)) { 926 if (bldr >= 0) { 927 struct bif_entry tmp = *entry; 928 929 *entry = entries[bldr]; 930 entries[bldr] = tmp; 931 } 932 } 933 } 934 935 for (i = 0; i < nr_entries; i++) { 936 struct bif_entry *entry = &entries[i]; 937 const struct bif_file_type *type; 938 int r; 939 940 if (entry->flags & (1ULL << BIF_FLAG_FSBL_CONFIG)) 941 continue; 942 943 type = get_file_type(entry); 944 if (!type) 945 goto err; 946 947 debug("type=%s file=%s\n", type->name, entry->filename); 948 r = type->add(entry); 949 if (r) 950 goto err; 951 } 952 953 /* Calculate checksums */ 954 csum = zynqmp_csum(&bif_output.header->width_detection, 955 &bif_output.header->checksum); 956 bif_output.header->checksum = cpu_to_le32(csum); 957 958 if (bif_output.imgheader) { 959 csum = zynqmp_csum(bif_output.imgheader, 960 &bif_output.imgheader->checksum); 961 bif_output.imgheader->checksum = cpu_to_le32(csum); 962 } 963 964 /* Write headers and components */ 965 if (lseek(outfd, 0, SEEK_SET) != 0) 966 goto err; 967 968 len = bif_output.data_len; 969 bifp = bif_output.data; 970 while (len) { 971 int r; 972 973 r = write(outfd, bifp, len); 974 if (r < 0) 975 goto err; 976 len -= r; 977 bifp += r; 978 } 979 980 return 0; 981 982 err: 983 fprintf(stderr, "Error: Failed to create image.\n"); 984 return -1; 985 } 986 987 /* Needs to be stubbed out so we can print after creation */ 988 static void zynqmpbif_set_header(void *ptr, struct stat *sbuf, int ifd, 989 struct image_tool_params *params) 990 { 991 } 992 993 static struct zynqmp_header zynqmpimage_header; 994 995 U_BOOT_IMAGE_TYPE( 996 zynqmpbif, 997 "Xilinx ZynqMP Boot Image support (bif)", 998 sizeof(struct zynqmp_header), 999 (void *)&zynqmpimage_header, 1000 zynqmpbif_check_params, 1001 NULL, 1002 zynqmpimage_print_header, 1003 zynqmpbif_set_header, 1004 NULL, 1005 zynqmpbif_check_image_types, 1006 NULL, 1007 NULL 1008 ); 1009