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