1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2010 4 * Texas Instruments, <www.ti.com> 5 * 6 * Aneesh V <aneesh@ti.com> 7 */ 8 9 #include <common.h> 10 #include <bloblist.h> 11 #include <binman_sym.h> 12 #include <dm.h> 13 #include <handoff.h> 14 #include <spl.h> 15 #include <asm/u-boot.h> 16 #include <nand.h> 17 #include <fat.h> 18 #include <version.h> 19 #include <image.h> 20 #include <malloc.h> 21 #include <dm/root.h> 22 #include <linux/compiler.h> 23 #include <fdt_support.h> 24 #include <bootcount.h> 25 26 DECLARE_GLOBAL_DATA_PTR; 27 28 #ifndef CONFIG_SYS_UBOOT_START 29 #define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE 30 #endif 31 #ifndef CONFIG_SYS_MONITOR_LEN 32 /* Unknown U-Boot size, let's assume it will not be more than 200 KB */ 33 #define CONFIG_SYS_MONITOR_LEN (200 * 1024) 34 #endif 35 36 u32 *boot_params_ptr = NULL; 37 38 /* See spl.h for information about this */ 39 binman_sym_declare(ulong, u_boot_any, image_pos); 40 41 /* Define board data structure */ 42 static bd_t bdata __attribute__ ((section(".data"))); 43 44 /* 45 * Board-specific Platform code can reimplement show_boot_progress () if needed 46 */ 47 __weak void show_boot_progress(int val) {} 48 49 #if defined(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF) 50 /* weak, default platform-specific function to initialize dram banks */ 51 __weak int dram_init_banksize(void) 52 { 53 return 0; 54 } 55 #endif 56 57 /* 58 * Default function to determine if u-boot or the OS should 59 * be started. This implementation always returns 1. 60 * 61 * Please implement your own board specific funcion to do this. 62 * 63 * RETURN 64 * 0 to not start u-boot 65 * positive if u-boot should start 66 */ 67 #ifdef CONFIG_SPL_OS_BOOT 68 __weak int spl_start_uboot(void) 69 { 70 puts(SPL_TPL_PROMPT 71 "Please implement spl_start_uboot() for your board\n"); 72 puts(SPL_TPL_PROMPT "Direct Linux boot not active!\n"); 73 return 1; 74 } 75 76 /* 77 * Weak default function for arch specific zImage check. Return zero 78 * and fill start and end address if image is recognized. 79 */ 80 int __weak bootz_setup(ulong image, ulong *start, ulong *end) 81 { 82 return 1; 83 } 84 #endif 85 86 /* Weak default function for arch/board-specific fixups to the spl_image_info */ 87 void __weak spl_perform_fixups(struct spl_image_info *spl_image) 88 { 89 } 90 91 void spl_fixup_fdt(void) 92 { 93 #if defined(CONFIG_SPL_OF_LIBFDT) && defined(CONFIG_SYS_SPL_ARGS_ADDR) 94 void *fdt_blob = (void *)CONFIG_SYS_SPL_ARGS_ADDR; 95 int err; 96 97 err = fdt_check_header(fdt_blob); 98 if (err < 0) { 99 printf("fdt_root: %s\n", fdt_strerror(err)); 100 return; 101 } 102 103 /* fixup the memory dt node */ 104 err = fdt_shrink_to_minimum(fdt_blob, 0); 105 if (err == 0) { 106 printf(SPL_TPL_PROMPT "fdt_shrink_to_minimum err - %d\n", err); 107 return; 108 } 109 110 err = arch_fixup_fdt(fdt_blob); 111 if (err) { 112 printf(SPL_TPL_PROMPT "arch_fixup_fdt err - %d\n", err); 113 return; 114 } 115 #endif 116 } 117 118 /* 119 * Weak default function for board specific cleanup/preparation before 120 * Linux boot. Some boards/platforms might not need it, so just provide 121 * an empty stub here. 122 */ 123 __weak void spl_board_prepare_for_linux(void) 124 { 125 /* Nothing to do! */ 126 } 127 128 __weak void spl_board_prepare_for_boot(void) 129 { 130 /* Nothing to do! */ 131 } 132 133 __weak struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) 134 { 135 return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset); 136 } 137 138 void spl_set_header_raw_uboot(struct spl_image_info *spl_image) 139 { 140 ulong u_boot_pos = binman_sym(ulong, u_boot_any, image_pos); 141 142 spl_image->size = CONFIG_SYS_MONITOR_LEN; 143 144 /* 145 * Binman error cases: address of the end of the previous region or the 146 * start of the image's entry area (usually 0) if there is no previous 147 * region. 148 */ 149 if (u_boot_pos && u_boot_pos != BINMAN_SYM_MISSING) { 150 /* Binman does not support separated entry addresses */ 151 spl_image->entry_point = u_boot_pos; 152 spl_image->load_addr = u_boot_pos; 153 } else { 154 spl_image->entry_point = CONFIG_SYS_UBOOT_START; 155 spl_image->load_addr = CONFIG_SYS_TEXT_BASE; 156 } 157 spl_image->os = IH_OS_U_BOOT; 158 spl_image->name = "U-Boot"; 159 } 160 161 #ifdef CONFIG_SPL_LOAD_FIT_FULL 162 /* Parse and load full fitImage in SPL */ 163 static int spl_load_fit_image(struct spl_image_info *spl_image, 164 const struct image_header *header) 165 { 166 bootm_headers_t images; 167 const char *fit_uname_config = NULL; 168 const char *fit_uname_fdt = FIT_FDT_PROP; 169 const char *uname; 170 ulong fw_data = 0, dt_data = 0, img_data = 0; 171 ulong fw_len = 0, dt_len = 0, img_len = 0; 172 int idx, conf_noffset; 173 int ret; 174 175 #ifdef CONFIG_SPL_FIT_SIGNATURE 176 images.verify = 1; 177 #endif 178 ret = fit_image_load(&images, (ulong)header, 179 NULL, &fit_uname_config, 180 IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1, 181 FIT_LOAD_REQUIRED, &fw_data, &fw_len); 182 if (ret < 0) 183 return ret; 184 185 spl_image->size = fw_len; 186 spl_image->entry_point = fw_data; 187 spl_image->load_addr = fw_data; 188 spl_image->os = IH_OS_U_BOOT; 189 spl_image->name = "U-Boot"; 190 191 debug(SPL_TPL_PROMPT "payload image: %32s load addr: 0x%lx size: %d\n", 192 spl_image->name, spl_image->load_addr, spl_image->size); 193 194 #ifdef CONFIG_SPL_FIT_SIGNATURE 195 images.verify = 1; 196 #endif 197 fit_image_load(&images, (ulong)header, 198 &fit_uname_fdt, &fit_uname_config, 199 IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1, 200 FIT_LOAD_OPTIONAL, &dt_data, &dt_len); 201 202 conf_noffset = fit_conf_get_node((const void *)header, 203 fit_uname_config); 204 if (conf_noffset <= 0) 205 return 0; 206 207 for (idx = 0; 208 uname = fdt_stringlist_get((const void *)header, conf_noffset, 209 FIT_LOADABLE_PROP, idx, 210 NULL), uname; 211 idx++) 212 { 213 #ifdef CONFIG_SPL_FIT_SIGNATURE 214 images.verify = 1; 215 #endif 216 ret = fit_image_load(&images, (ulong)header, 217 &uname, &fit_uname_config, 218 IH_ARCH_DEFAULT, IH_TYPE_LOADABLE, -1, 219 FIT_LOAD_OPTIONAL_NON_ZERO, 220 &img_data, &img_len); 221 if (ret < 0) 222 return ret; 223 } 224 225 return 0; 226 } 227 #endif 228 229 int spl_parse_image_header(struct spl_image_info *spl_image, 230 const struct image_header *header) 231 { 232 #ifdef CONFIG_SPL_LOAD_FIT_FULL 233 int ret = spl_load_fit_image(spl_image, header); 234 235 if (!ret) 236 return ret; 237 #endif 238 if (image_get_magic(header) == IH_MAGIC) { 239 #ifdef CONFIG_SPL_LEGACY_IMAGE_SUPPORT 240 u32 header_size = sizeof(struct image_header); 241 242 if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) { 243 /* 244 * On some system (e.g. powerpc), the load-address and 245 * entry-point is located at address 0. We can't load 246 * to 0-0x40. So skip header in this case. 247 */ 248 spl_image->load_addr = image_get_load(header); 249 spl_image->entry_point = image_get_ep(header); 250 spl_image->size = image_get_data_size(header); 251 } else { 252 spl_image->entry_point = image_get_load(header); 253 /* Load including the header */ 254 spl_image->load_addr = spl_image->entry_point - 255 header_size; 256 spl_image->size = image_get_data_size(header) + 257 header_size; 258 } 259 spl_image->os = image_get_os(header); 260 spl_image->name = image_get_name(header); 261 debug(SPL_TPL_PROMPT 262 "payload image: %32s load addr: 0x%lx size: %d\n", 263 spl_image->name, spl_image->load_addr, spl_image->size); 264 #else 265 /* LEGACY image not supported */ 266 debug("Legacy boot image support not enabled, proceeding to other boot methods\n"); 267 return -EINVAL; 268 #endif 269 } else { 270 #ifdef CONFIG_SPL_PANIC_ON_RAW_IMAGE 271 /* 272 * CONFIG_SPL_PANIC_ON_RAW_IMAGE is defined when the 273 * code which loads images in SPL cannot guarantee that 274 * absolutely all read errors will be reported. 275 * An example is the LPC32XX MLC NAND driver, which 276 * will consider that a completely unreadable NAND block 277 * is bad, and thus should be skipped silently. 278 */ 279 panic("** no mkimage signature but raw image not supported"); 280 #endif 281 282 #ifdef CONFIG_SPL_OS_BOOT 283 ulong start, end; 284 285 if (!bootz_setup((ulong)header, &start, &end)) { 286 spl_image->name = "Linux"; 287 spl_image->os = IH_OS_LINUX; 288 spl_image->load_addr = CONFIG_SYS_LOAD_ADDR; 289 spl_image->entry_point = CONFIG_SYS_LOAD_ADDR; 290 spl_image->size = end - start; 291 debug(SPL_TPL_PROMPT 292 "payload zImage, load addr: 0x%lx size: %d\n", 293 spl_image->load_addr, spl_image->size); 294 return 0; 295 } 296 #endif 297 298 #ifdef CONFIG_SPL_RAW_IMAGE_SUPPORT 299 /* Signature not found - assume u-boot.bin */ 300 debug("mkimage signature not found - ih_magic = %x\n", 301 header->ih_magic); 302 spl_set_header_raw_uboot(spl_image); 303 #else 304 /* RAW image not supported, proceed to other boot methods. */ 305 debug("Raw boot image support not enabled, proceeding to other boot methods\n"); 306 return -EINVAL; 307 #endif 308 } 309 310 return 0; 311 } 312 313 __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) 314 { 315 typedef void __noreturn (*image_entry_noargs_t)(void); 316 317 image_entry_noargs_t image_entry = 318 (image_entry_noargs_t)spl_image->entry_point; 319 320 debug("image entry point: 0x%lx\n", spl_image->entry_point); 321 image_entry(); 322 } 323 324 #if CONFIG_IS_ENABLED(HANDOFF) 325 /** 326 * Set up the SPL hand-off information 327 * 328 * This is initially empty (zero) but can be written by 329 */ 330 static int setup_spl_handoff(void) 331 { 332 struct spl_handoff *ho; 333 334 ho = bloblist_ensure(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff)); 335 if (!ho) 336 return -ENOENT; 337 338 return 0; 339 } 340 341 static int write_spl_handoff(void) 342 { 343 struct spl_handoff *ho; 344 345 ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff)); 346 if (!ho) 347 return -ENOENT; 348 handoff_save_dram(ho); 349 #ifdef CONFIG_SANDBOX 350 ho->arch.magic = TEST_HANDOFF_MAGIC; 351 #endif 352 debug(SPL_TPL_PROMPT "Wrote SPL handoff\n"); 353 354 return 0; 355 } 356 #else 357 static inline int setup_spl_handoff(void) { return 0; } 358 static inline int write_spl_handoff(void) { return 0; } 359 360 #endif /* HANDOFF */ 361 362 static int spl_common_init(bool setup_malloc) 363 { 364 int ret; 365 366 #if CONFIG_VAL(SYS_MALLOC_F_LEN) 367 if (setup_malloc) { 368 #ifdef CONFIG_MALLOC_F_ADDR 369 gd->malloc_base = CONFIG_MALLOC_F_ADDR; 370 #endif 371 gd->malloc_limit = CONFIG_VAL(SYS_MALLOC_F_LEN); 372 gd->malloc_ptr = 0; 373 } 374 #endif 375 ret = bootstage_init(true); 376 if (ret) { 377 debug("%s: Failed to set up bootstage: ret=%d\n", __func__, 378 ret); 379 return ret; 380 } 381 bootstage_mark_name(BOOTSTAGE_ID_START_SPL, "spl"); 382 #if CONFIG_IS_ENABLED(LOG) 383 ret = log_init(); 384 if (ret) { 385 debug("%s: Failed to set up logging\n", __func__); 386 return ret; 387 } 388 #endif 389 if (CONFIG_IS_ENABLED(BLOBLIST)) { 390 ret = bloblist_init(); 391 if (ret) { 392 debug("%s: Failed to set up bloblist: ret=%d\n", 393 __func__, ret); 394 return ret; 395 } 396 } 397 if (CONFIG_IS_ENABLED(HANDOFF)) { 398 int ret; 399 400 ret = setup_spl_handoff(); 401 if (ret) { 402 puts(SPL_TPL_PROMPT "Cannot set up SPL handoff\n"); 403 hang(); 404 } 405 } 406 if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) { 407 ret = fdtdec_setup(); 408 if (ret) { 409 debug("fdtdec_setup() returned error %d\n", ret); 410 return ret; 411 } 412 } 413 if (CONFIG_IS_ENABLED(DM)) { 414 bootstage_start(BOOTSTATE_ID_ACCUM_DM_SPL, "dm_spl"); 415 /* With CONFIG_SPL_OF_PLATDATA, bring in all devices */ 416 ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA)); 417 bootstage_accum(BOOTSTATE_ID_ACCUM_DM_SPL); 418 if (ret) { 419 debug("dm_init_and_scan() returned error %d\n", ret); 420 return ret; 421 } 422 } 423 424 return 0; 425 } 426 427 void spl_set_bd(void) 428 { 429 /* 430 * NOTE: On some platforms (e.g. x86) bdata may be in flash and not 431 * writeable. 432 */ 433 if (!gd->bd) 434 gd->bd = &bdata; 435 } 436 437 int spl_early_init(void) 438 { 439 int ret; 440 441 debug("%s\n", __func__); 442 443 ret = spl_common_init(true); 444 if (ret) 445 return ret; 446 gd->flags |= GD_FLG_SPL_EARLY_INIT; 447 448 return 0; 449 } 450 451 int spl_init(void) 452 { 453 int ret; 454 bool setup_malloc = !(IS_ENABLED(CONFIG_SPL_STACK_R) && 455 IS_ENABLED(CONFIG_SPL_SYS_MALLOC_SIMPLE)); 456 457 debug("%s\n", __func__); 458 459 if (!(gd->flags & GD_FLG_SPL_EARLY_INIT)) { 460 ret = spl_common_init(setup_malloc); 461 if (ret) 462 return ret; 463 } 464 gd->flags |= GD_FLG_SPL_INIT; 465 466 return 0; 467 } 468 469 #ifndef BOOT_DEVICE_NONE 470 #define BOOT_DEVICE_NONE 0xdeadbeef 471 #endif 472 473 __weak void board_boot_order(u32 *spl_boot_list) 474 { 475 spl_boot_list[0] = spl_boot_device(); 476 } 477 478 static struct spl_image_loader *spl_ll_find_loader(uint boot_device) 479 { 480 struct spl_image_loader *drv = 481 ll_entry_start(struct spl_image_loader, spl_image_loader); 482 const int n_ents = 483 ll_entry_count(struct spl_image_loader, spl_image_loader); 484 struct spl_image_loader *entry; 485 486 for (entry = drv; entry != drv + n_ents; entry++) { 487 if (boot_device == entry->boot_device) 488 return entry; 489 } 490 491 /* Not found */ 492 return NULL; 493 } 494 495 static int spl_load_image(struct spl_image_info *spl_image, 496 struct spl_image_loader *loader) 497 { 498 struct spl_boot_device bootdev; 499 500 bootdev.boot_device = loader->boot_device; 501 bootdev.boot_device_name = NULL; 502 503 return loader->load_image(spl_image, &bootdev); 504 } 505 506 /** 507 * boot_from_devices() - Try loading an booting U-Boot from a list of devices 508 * 509 * @spl_image: Place to put the image details if successful 510 * @spl_boot_list: List of boot devices to try 511 * @count: Number of elements in spl_boot_list 512 * @return 0 if OK, -ve on error 513 */ 514 static int boot_from_devices(struct spl_image_info *spl_image, 515 u32 spl_boot_list[], int count) 516 { 517 int i; 518 519 for (i = 0; i < count && spl_boot_list[i] != BOOT_DEVICE_NONE; i++) { 520 struct spl_image_loader *loader; 521 522 loader = spl_ll_find_loader(spl_boot_list[i]); 523 #if defined(CONFIG_SPL_SERIAL_SUPPORT) && defined(CONFIG_SPL_LIBCOMMON_SUPPORT) 524 if (loader) 525 printf("Trying to boot from %s\n", loader->name); 526 else 527 puts(SPL_TPL_PROMPT "Unsupported Boot Device!\n"); 528 #endif 529 if (loader && !spl_load_image(spl_image, loader)) { 530 spl_image->boot_device = spl_boot_list[i]; 531 return 0; 532 } 533 } 534 535 return -ENODEV; 536 } 537 538 void board_init_r(gd_t *dummy1, ulong dummy2) 539 { 540 u32 spl_boot_list[] = { 541 BOOT_DEVICE_NONE, 542 BOOT_DEVICE_NONE, 543 BOOT_DEVICE_NONE, 544 BOOT_DEVICE_NONE, 545 BOOT_DEVICE_NONE, 546 }; 547 struct spl_image_info spl_image; 548 int ret; 549 550 debug(">>" SPL_TPL_PROMPT "board_init_r()\n"); 551 552 spl_set_bd(); 553 554 #if defined(CONFIG_SYS_SPL_MALLOC_START) 555 mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START, 556 CONFIG_SYS_SPL_MALLOC_SIZE); 557 gd->flags |= GD_FLG_FULL_MALLOC_INIT; 558 #endif 559 if (!(gd->flags & GD_FLG_SPL_INIT)) { 560 if (spl_init()) 561 hang(); 562 } 563 #if !defined(CONFIG_PPC) && !defined(CONFIG_ARCH_MX6) 564 /* 565 * timer_init() does not exist on PPC systems. The timer is initialized 566 * and enabled (decrementer) in interrupt_init() here. 567 */ 568 timer_init(); 569 #endif 570 571 #if CONFIG_IS_ENABLED(BOARD_INIT) 572 spl_board_init(); 573 #endif 574 575 if (IS_ENABLED(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF)) 576 dram_init_banksize(); 577 578 bootcount_inc(); 579 580 memset(&spl_image, '\0', sizeof(spl_image)); 581 #ifdef CONFIG_SYS_SPL_ARGS_ADDR 582 spl_image.arg = (void *)CONFIG_SYS_SPL_ARGS_ADDR; 583 #endif 584 spl_image.boot_device = BOOT_DEVICE_NONE; 585 board_boot_order(spl_boot_list); 586 587 if (boot_from_devices(&spl_image, spl_boot_list, 588 ARRAY_SIZE(spl_boot_list))) { 589 puts(SPL_TPL_PROMPT "failed to boot from all boot devices\n"); 590 hang(); 591 } 592 593 spl_perform_fixups(&spl_image); 594 if (CONFIG_IS_ENABLED(HANDOFF)) { 595 ret = write_spl_handoff(); 596 if (ret) 597 printf(SPL_TPL_PROMPT 598 "SPL hand-off write failed (err=%d)\n", ret); 599 } 600 if (CONFIG_IS_ENABLED(BLOBLIST)) { 601 ret = bloblist_finish(); 602 if (ret) 603 printf("Warning: Failed to finish bloblist (ret=%d)\n", 604 ret); 605 } 606 607 #ifdef CONFIG_CPU_V7M 608 spl_image.entry_point |= 0x1; 609 #endif 610 switch (spl_image.os) { 611 case IH_OS_U_BOOT: 612 debug("Jumping to U-Boot\n"); 613 break; 614 #if CONFIG_IS_ENABLED(ATF) 615 case IH_OS_ARM_TRUSTED_FIRMWARE: 616 debug("Jumping to U-Boot via ARM Trusted Firmware\n"); 617 spl_invoke_atf(&spl_image); 618 break; 619 #endif 620 #if CONFIG_IS_ENABLED(OPTEE) 621 case IH_OS_TEE: 622 debug("Jumping to U-Boot via OP-TEE\n"); 623 spl_optee_entry(NULL, NULL, spl_image.fdt_addr, 624 (void *)spl_image.entry_point); 625 break; 626 #endif 627 #ifdef CONFIG_SPL_OS_BOOT 628 case IH_OS_LINUX: 629 debug("Jumping to Linux\n"); 630 spl_fixup_fdt(); 631 spl_board_prepare_for_linux(); 632 jump_to_image_linux(&spl_image); 633 #endif 634 default: 635 debug("Unsupported OS image.. Jumping nevertheless..\n"); 636 } 637 #if CONFIG_VAL(SYS_MALLOC_F_LEN) && !defined(CONFIG_SYS_SPL_MALLOC_SIZE) 638 debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr, 639 gd->malloc_ptr / 1024); 640 #endif 641 #ifdef CONFIG_BOOTSTAGE_STASH 642 bootstage_mark_name(BOOTSTAGE_ID_END_SPL, "end_spl"); 643 ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR, 644 CONFIG_BOOTSTAGE_STASH_SIZE); 645 if (ret) 646 debug("Failed to stash bootstage: err=%d\n", ret); 647 #endif 648 649 debug("loaded - jumping to U-Boot...\n"); 650 spl_board_prepare_for_boot(); 651 jump_to_image_no_args(&spl_image); 652 } 653 654 #ifdef CONFIG_SPL_SERIAL_SUPPORT 655 /* 656 * This requires UART clocks to be enabled. In order for this to work the 657 * caller must ensure that the gd pointer is valid. 658 */ 659 void preloader_console_init(void) 660 { 661 gd->baudrate = CONFIG_BAUDRATE; 662 663 serial_init(); /* serial communications setup */ 664 665 gd->have_console = 1; 666 667 #if CONFIG_IS_ENABLED(BANNER_PRINT) 668 puts("\nU-Boot " SPL_TPL_NAME " " PLAIN_VERSION " (" U_BOOT_DATE " - " 669 U_BOOT_TIME " " U_BOOT_TZ ")\n"); 670 #endif 671 #ifdef CONFIG_SPL_DISPLAY_PRINT 672 spl_display_print(); 673 #endif 674 } 675 #endif 676 677 /** 678 * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution 679 * 680 * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM 681 * for the main board_init_r() execution. This is typically because we need 682 * more stack space for things like the MMC sub-system. 683 * 684 * This function calculates the stack position, copies the global_data into 685 * place, sets the new gd (except for ARM, for which setting GD within a C 686 * function may not always work) and returns the new stack position. The 687 * caller is responsible for setting up the sp register and, in the case 688 * of ARM, setting up gd. 689 * 690 * All of this is done using the same layout and alignments as done in 691 * board_init_f_init_reserve() / board_init_f_alloc_reserve(). 692 * 693 * @return new stack location, or 0 to use the same stack 694 */ 695 ulong spl_relocate_stack_gd(void) 696 { 697 #ifdef CONFIG_SPL_STACK_R 698 gd_t *new_gd; 699 ulong ptr = CONFIG_SPL_STACK_R_ADDR; 700 701 #if defined(CONFIG_SPL_SYS_MALLOC_SIMPLE) && CONFIG_VAL(SYS_MALLOC_F_LEN) 702 if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) { 703 ptr -= CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN; 704 gd->malloc_base = ptr; 705 gd->malloc_limit = CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN; 706 gd->malloc_ptr = 0; 707 } 708 #endif 709 /* Get stack position: use 8-byte alignment for ABI compliance */ 710 ptr = CONFIG_SPL_STACK_R_ADDR - roundup(sizeof(gd_t),16); 711 new_gd = (gd_t *)ptr; 712 memcpy(new_gd, (void *)gd, sizeof(gd_t)); 713 #if CONFIG_IS_ENABLED(DM) 714 dm_fixup_for_gd_move(new_gd); 715 #endif 716 #if !defined(CONFIG_ARM) 717 gd = new_gd; 718 #endif 719 return ptr; 720 #else 721 return 0; 722 #endif 723 } 724