1 /* 2 * (C) Copyright 2019 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 #include <common.h> 7 #include <boot_rkimg.h> 8 #include <image.h> 9 #include <malloc.h> 10 #include <sysmem.h> 11 #include <asm/arch/fit.h> 12 #include <asm/arch/resource_img.h> 13 14 DECLARE_GLOBAL_DATA_PTR; 15 16 #define FIT_PLACEHOLDER_ADDR 0xffffffff 17 18 /* 19 * Must use args '-E -p' for mkimage to generate FIT image, 4K as max assumption. 20 */ 21 #define FIT_FDT_MAX_SIZE SZ_4K 22 23 static int fit_is_ext_type(void *fit) 24 { 25 return fdt_totalsize(fit) < FIT_FDT_MAX_SIZE; 26 } 27 28 static int fit_is_signed(void *fit, const void *sig_blob) 29 { 30 return fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME) < 0 ? 0 : 1; 31 } 32 33 static int fit_is_required(void *fit, const void *sig_blob) 34 { 35 int sig_node; 36 int noffset; 37 38 sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME); 39 if (sig_node < 0) 40 return 0; 41 42 fdt_for_each_subnode(noffset, sig_blob, sig_node) { 43 const char *required; 44 45 required = fdt_getprop(sig_blob, noffset, "required", NULL); 46 if (required && !strcmp(required, "conf")) 47 return 1; 48 } 49 50 return 0; 51 } 52 53 static int fit_get_image_defconf_node(void *fit, int *images, int *defconf) 54 { 55 int images_node, confs_node, defconf_node; 56 const char *def_name; 57 58 images_node = fdt_path_offset(fit, FIT_IMAGES_PATH); 59 if (images_node < 0) 60 return images_node; 61 62 confs_node = fdt_path_offset(fit, FIT_CONFS_PATH); 63 if (confs_node < 0) 64 return confs_node; 65 66 def_name = fdt_getprop(fit, confs_node, FIT_DEFAULT_PROP, NULL); 67 if (!def_name) 68 return -ENOENT; 69 70 defconf_node = fdt_subnode_offset(fit, confs_node, def_name); 71 if (defconf_node < 0) 72 return defconf_node; 73 74 *images = images_node; 75 *defconf = defconf_node; 76 77 return 0; 78 } 79 80 int fit_fixup_load_entry(void *fit, int images, int defconf, 81 char *name, ulong *load, ulong new_addr) 82 { 83 const char *uname; 84 int uname_cfg; 85 int err; 86 87 if ((*load != FIT_PLACEHOLDER_ADDR) || 88 fit_is_required(fit, gd_fdt_blob())) 89 return 0; 90 91 *load = new_addr; 92 93 uname = fdt_getprop(fit, defconf, name, NULL); 94 if (!uname) 95 return -ENODEV; 96 97 uname_cfg = fdt_subnode_offset(fit, images, uname); 98 if (uname_cfg < 0) 99 return -ENODEV; 100 101 err = fit_image_set_load(fit, uname_cfg, new_addr); 102 if (err) 103 return err; 104 105 fit_image_set_entry(fit, uname_cfg, new_addr); 106 107 return 0; 108 } 109 110 static int fit_get_load_and_data(void *fit, int images, int defconf, 111 const char *name, ulong *load, 112 int *offset, int *size) 113 { 114 const char *uname; 115 int uname_cfg; 116 int off, sz; 117 int err; 118 119 uname = fdt_getprop(fit, defconf, name, NULL); 120 if (!uname) 121 return -ENODEV; 122 123 uname_cfg = fdt_subnode_offset(fit, images, uname); 124 if (uname_cfg < 0) 125 return -ENODEV; 126 127 err = fit_image_get_data_size(fit, uname_cfg, &sz); 128 if (err) 129 return err; 130 131 err = fit_image_get_data_position(fit, uname_cfg, &off); 132 if (!err) { 133 off -= fdt_totalsize(fit); 134 } else { 135 err = fit_image_get_data_offset(fit, uname_cfg, &off); 136 if (err) 137 return err; 138 } 139 140 /* optional */ 141 if (load) { 142 err = fit_image_get_load(fit, uname_cfg, load); 143 if (err) 144 return err; 145 } 146 147 *offset = off; 148 *size = sz; 149 150 return 0; 151 } 152 153 int fit_image_fixup_and_sysmem_rsv(void *fit) 154 { 155 ulong load, kaddr, faddr, raddr; 156 int images, defconf; 157 int offset, size; 158 int err; 159 160 faddr = env_get_ulong("fdt_addr_r", 16, 0); 161 kaddr = env_get_ulong("kernel_addr_r", 16, 0); 162 raddr = env_get_ulong("ramdisk_addr_r", 16, 0); 163 164 if (!faddr || !kaddr || !raddr) 165 return -EINVAL; 166 167 if (fit_get_image_defconf_node(fit, &images, &defconf)) { 168 FIT_I("Failed to get default config\n"); 169 return -ENODEV; 170 } 171 172 /* fdt */ 173 if (fit_get_load_and_data(fit, images, defconf, FIT_FDT_PROP, 174 &load, &offset, &size)) { 175 FIT_I("Invalid fdt node\n"); 176 return -ENOENT; 177 } 178 179 #ifdef CONFIG_USING_KERNEL_DTB 180 sysmem_free((phys_addr_t)gd->fdt_blob); 181 #endif 182 if (fit_fixup_load_entry(fit, images, defconf, 183 FIT_FDT_PROP, &load, faddr)) { 184 FIT_I("Failed to fixup fdt load addr\n"); 185 return -EINVAL; 186 } 187 188 if (!sysmem_alloc_base(MEM_FDT, (phys_addr_t)load, 189 ALIGN(size, RK_BLK_SIZE))) 190 return -ENOMEM; 191 192 /* kernel */ 193 if (fit_get_load_and_data(fit, images, defconf, FIT_KERNEL_PROP, 194 &load, &offset, &size)) { 195 FIT_I("Invalid kernel node\n"); 196 return -EINVAL; 197 } 198 199 if (fit_fixup_load_entry(fit, images, defconf, 200 FIT_KERNEL_PROP, &load, kaddr)) { 201 FIT_I("Failed to fixup kernel load addr\n"); 202 return -EINVAL; 203 } 204 205 if (!sysmem_alloc_base(MEM_KERNEL, (phys_addr_t)load, 206 ALIGN(size, RK_BLK_SIZE))) 207 return -ENOMEM; 208 209 /* ramdisk(optional) */ 210 err = fit_get_load_and_data(fit, images, defconf, FIT_RAMDISK_PROP, 211 &load, &offset, &size); 212 if (err && err != -ENODEV) { 213 FIT_I("Invalid ramdisk node\n"); 214 return err; 215 } 216 217 if (size) { 218 if (fit_fixup_load_entry(fit, images, defconf, 219 FIT_RAMDISK_PROP, &load, raddr)) { 220 FIT_I("Failed to fixup ramdisk load addr\n"); 221 return -EINVAL; 222 } 223 224 if (!sysmem_alloc_base(MEM_RAMDISK, (phys_addr_t)load, 225 ALIGN(size, RK_BLK_SIZE))) 226 return -ENOMEM; 227 } 228 229 return 0; 230 } 231 232 int fit_sysmem_free_each(void *fit) 233 { 234 ulong raddr, kaddr, faddr; 235 236 raddr = env_get_ulong("ramdisk_addr_r", 16, 0); 237 kaddr = env_get_ulong("kernel_addr_r", 16, 0); 238 faddr = env_get_ulong("fdt_addr_r", 16, 0); 239 240 sysmem_free((phys_addr_t)fit); 241 sysmem_free((phys_addr_t)raddr); 242 sysmem_free((phys_addr_t)kaddr); 243 sysmem_free((phys_addr_t)faddr); 244 245 return 0; 246 } 247 248 static int fit_image_load_one(void *fit, struct blk_desc *dev_desc, 249 disk_partition_t *part, int images, 250 int defconf, char *name, void *dst) 251 { 252 u32 blknum, blkoff; 253 int offset, size; 254 255 if (fit_get_load_and_data(fit, images, defconf, name, 256 NULL, &offset, &size)) 257 return -EINVAL; 258 259 blkoff = (FIT_ALIGN(fdt_totalsize(fit)) + offset) / dev_desc->blksz; 260 blknum = DIV_ROUND_UP(size, dev_desc->blksz); 261 262 if (blk_dread(dev_desc, part->start + blkoff, blknum, dst) != blknum) 263 return -EIO; 264 265 return 0; 266 } 267 268 static int fit_image_load_fdt(void *fit, struct blk_desc *dev_desc, 269 disk_partition_t *part, int images, 270 int defconf, void *dst) 271 { 272 return fit_image_load_one(fit, dev_desc, part, images, 273 defconf, FIT_FDT_PROP, dst); 274 } 275 276 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE 277 static int fit_image_load_resource(void *fit, struct blk_desc *dev_desc, 278 disk_partition_t *part, int images, 279 int defconf, ulong *addr) 280 { 281 ulong fdt_addr_r, dst; 282 int offset, size; 283 int err; 284 285 err = fit_get_load_and_data(fit, images, defconf, FIT_MULTI_PROP, 286 NULL, &offset, &size); 287 if (err) 288 return err; 289 290 fdt_addr_r = env_get_ulong("fdt_addr_r", 16, 0); 291 if (!fdt_addr_r) 292 return -EINVAL; 293 294 /* reserve enough space before fdt */ 295 dst = fdt_addr_r - 296 ALIGN(size, dev_desc->blksz) - CONFIG_SYS_FDT_PAD; 297 298 if (!sysmem_alloc_base(MEM_RESOURCE, (phys_addr_t)dst, 299 ALIGN(size, dev_desc->blksz))) 300 return -ENOMEM; 301 302 *addr = dst; 303 304 return fit_image_load_one(fit, dev_desc, part, images, defconf, 305 FIT_MULTI_PROP, (void *)dst); 306 } 307 #endif 308 309 static void *fit_get_blob(struct blk_desc *dev_desc, disk_partition_t *part) 310 { 311 void *fit, *fdt; 312 int blknum; 313 314 blknum = DIV_ROUND_UP(sizeof(struct fdt_header), dev_desc->blksz); 315 fdt = memalign(ARCH_DMA_MINALIGN, blknum * dev_desc->blksz); 316 if (!fdt) 317 return NULL; 318 319 if (blk_dread(dev_desc, part->start, blknum, fdt) != blknum) { 320 FIT_I("Failed to read fdt header\n"); 321 goto fail; 322 } 323 324 if (fdt_check_header(fdt)) { 325 FIT_I("Invalid fdt header\n"); 326 goto fail; 327 } 328 329 if (!fit_is_ext_type(fdt)) { 330 FIT_I("Not external type\n"); 331 goto fail; 332 } 333 334 blknum = DIV_ROUND_UP(fdt_totalsize(fdt), dev_desc->blksz); 335 fit = memalign(ARCH_DMA_MINALIGN, blknum * dev_desc->blksz); 336 if (!fit) { 337 FIT_I("No memory\n"); 338 goto fail; 339 } 340 341 if (blk_dread(dev_desc, part->start, blknum, fit) != blknum) { 342 free(fit); 343 FIT_I("Failed to read fit\n"); 344 goto fail; 345 } 346 347 return fit; 348 349 fail: 350 free(fdt); 351 return NULL; 352 } 353 354 static int fit_image_get_fdt_hash(void *fit, int images, int defconf, 355 char **hash, int *hash_size) 356 { 357 const char *fdt_name; 358 const char *name; 359 uint8_t *fit_value2; 360 uint8_t *fit_value; 361 int fit_value_len; 362 int hash_off; 363 int fdt_off; 364 int found = 0; 365 char *algo; 366 367 fdt_name = fdt_getprop(fit, defconf, FIT_FDT_PROP, NULL); 368 if (!fdt_name) 369 return -EBADF; 370 371 fdt_off = fdt_subnode_offset(fit, images, fdt_name); 372 if (fdt_off < 0) 373 return -EBADF; 374 375 fdt_for_each_subnode(hash_off, fit, fdt_off) { 376 name = fit_get_name(fit, hash_off, NULL); 377 if (!strncmp(name, FIT_HASH_NODENAME, 378 strlen(FIT_HASH_NODENAME))) { 379 found = 1; 380 break; 381 } 382 } 383 384 if (!found) 385 return -ENODEV; 386 387 if (fit_image_hash_get_algo(fit, hash_off, &algo)) 388 return -EINVAL; 389 390 if (fit_image_hash_get_value(fit, hash_off, &fit_value, 391 &fit_value_len)) 392 return -EINVAL; 393 394 if (!strcmp(algo, "sha1")) 395 *hash_size = 20; 396 else if (!strcmp(algo, "sha256")) 397 *hash_size = 32; 398 else 399 return -EINVAL; 400 401 /* avoid freed */ 402 fit_value2 = malloc(fit_value_len); 403 if (!fit_value2) 404 return -ENOMEM; 405 406 memcpy(fit_value2, fit_value, fit_value_len); 407 *hash = (char *)fit_value2; 408 409 return 0; 410 } 411 412 ulong fit_image_get_bootable_size(void *fit) 413 { 414 ulong off[3] = { 0, 0, 0 }; 415 ulong max_off, load; 416 int images, defconf; 417 int offset, size; 418 419 if (fit_get_image_defconf_node(fit, &images, &defconf)) 420 return -ENODEV; 421 422 if (!fit_get_load_and_data(fit, images, defconf, FIT_FDT_PROP, 423 &load, &offset, &size)) 424 off[0] = offset + FIT_ALIGN(size); 425 426 if (!fit_get_load_and_data(fit, images, defconf, FIT_KERNEL_PROP, 427 &load, &offset, &size)) 428 off[1] = offset + FIT_ALIGN(size); 429 430 if (!fit_get_load_and_data(fit, images, defconf, FIT_RAMDISK_PROP, 431 &load, &offset, &size)) 432 off[2] = offset + FIT_ALIGN(size); 433 434 max_off = max(off[0], off[1]); 435 max_off = max(max_off, off[2]); 436 437 return FIT_ALIGN(fdt_totalsize(fit)) + max_off; 438 } 439 440 void *fit_image_load_bootables(ulong *size) 441 { 442 struct blk_desc *dev_desc; 443 disk_partition_t part; 444 char *part_name; 445 int blknum; 446 void *fit; 447 448 dev_desc = rockchip_get_bootdev(); 449 if (!dev_desc) { 450 FIT_I("No dev_desc\n"); 451 return NULL; 452 } 453 454 if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY) 455 part_name = PART_RECOVERY; 456 else 457 part_name = PART_BOOT; 458 459 if (part_get_info_by_name(dev_desc, part_name, &part) < 0) { 460 FIT_I("No %s partition\n", part_name); 461 return NULL; 462 } 463 464 fit = fit_get_blob(dev_desc, &part); 465 if (!fit) { 466 FIT_I("No fit blob\n"); 467 return NULL; 468 } 469 470 *size = fit_image_get_bootable_size(fit); 471 if (*size == 0) { 472 FIT_I("No bootable image size\n"); 473 return NULL; 474 } 475 476 blknum = DIV_ROUND_UP(*size, dev_desc->blksz); 477 fit = sysmem_alloc(MEM_FIT, blknum * dev_desc->blksz); 478 if (!fit) 479 return NULL; 480 481 if (blk_dread(dev_desc, part.start, blknum, fit) != blknum) { 482 FIT_I("Failed to load bootable images\n"); 483 return NULL; 484 } 485 486 return fit; 487 } 488 489 static void verbose_msg(void *fit, int defconf) 490 { 491 FIT_I("%ssigned, %srequired\n", 492 fit_is_signed(fit, gd_fdt_blob()) ? "" : "no ", 493 fit_is_required(fit, gd_fdt_blob()) ? "" : "no "); 494 495 printf("DTB: %s\n", 496 (char *)fdt_getprop(fit, defconf, FIT_FDT_PROP, NULL)); 497 } 498 499 int rockchip_read_fit_dtb(void *fdt_addr, char **hash, int *hash_size) 500 { 501 struct blk_desc *dev_desc; 502 disk_partition_t part; 503 char *part_name; 504 void *fit; 505 ulong rsce; 506 int images; 507 int defconf; 508 int err; 509 510 dev_desc = rockchip_get_bootdev(); 511 if (!dev_desc) { 512 FIT_I("No dev_desc!\n"); 513 return -ENODEV; 514 } 515 516 if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY) 517 part_name = PART_RECOVERY; 518 else 519 part_name = PART_BOOT; 520 521 err = part_get_info_by_name(dev_desc, part_name, &part); 522 if (err < 0) { 523 FIT_I("No %s partition\n", part_name); 524 return err; 525 } 526 527 fit = fit_get_blob(dev_desc, &part); 528 if (!fit) { 529 FIT_I("No fdt description\n"); 530 return -EINVAL; 531 } 532 533 if (fit_get_image_defconf_node(fit, &images, &defconf)) { 534 FIT_I("Failed to get /images and /configures default\n"); 535 err = -ENODEV; 536 goto out; 537 } 538 539 if (fit_image_load_fdt(fit, dev_desc, &part, 540 images, defconf, fdt_addr)) { 541 FIT_I("Failed to load fdt\n"); 542 err = -EINVAL; 543 goto out; 544 } 545 546 err = fit_image_get_fdt_hash(fit, images, defconf, hash, hash_size); 547 if (err && err != -ENODEV) { 548 FIT_I("Failed to get fdt hash\n"); 549 err = -EINVAL; 550 goto out; 551 } 552 553 verbose_msg(fit, defconf); 554 555 /* load resource file */ 556 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE 557 err = fit_image_load_resource(fit, dev_desc, &part, 558 images, defconf, &rsce); 559 if (!err) { 560 if (resource_create_ram_list(dev_desc, (void *)rsce)) 561 FIT_I("Failed to create resource list\n"); 562 } else if (err == -ENODEV) { 563 FIT_I("No resource file\n"); 564 } else { 565 FIT_I("Failed to load resource file\n"); 566 } 567 #endif 568 out: 569 free(fit); 570 571 return err; 572 } 573