"Das U-Boot" Source Tree
at master 126 lines 3.7 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2019 Fraunhofer AISEC, 4 * Lukas Auer <lukas.auer@aisec.fraunhofer.de> 5 * 6 * Based on common/spl/spl_atf.c 7 */ 8#include <cpu_func.h> 9#include <errno.h> 10#include <hang.h> 11#include <image.h> 12#include <spl.h> 13#include <asm/global_data.h> 14#include <asm/smp.h> 15#include <opensbi.h> 16#include <linux/libfdt.h> 17#include <linux/printk.h> 18#include <mapmem.h> 19 20DECLARE_GLOBAL_DATA_PTR; 21 22struct fw_dynamic_info opensbi_info; 23 24static int spl_opensbi_find_os_node(void *blob, int *uboot_node, int os_type) 25{ 26 int fit_images_node, node; 27 const char *fit_os; 28 29 fit_images_node = fdt_path_offset(blob, "/fit-images"); 30 if (fit_images_node < 0) 31 return -ENODEV; 32 33 fdt_for_each_subnode(node, blob, fit_images_node) { 34 fit_os = fdt_getprop(blob, node, FIT_OS_PROP, NULL); 35 if (!fit_os) 36 continue; 37 38 if (genimg_get_os_id(fit_os) == os_type) { 39 *uboot_node = node; 40 return 0; 41 } 42 } 43 44 return -ENODEV; 45} 46 47void __noreturn spl_invoke_opensbi(struct spl_image_info *spl_image) 48{ 49 int ret, os_node; 50 ulong os_entry; 51 int os_type; 52 typedef void __noreturn (*opensbi_entry_t)(ulong hartid, ulong dtb, ulong info); 53 opensbi_entry_t opensbi_entry; 54 55 if (!spl_image->fdt_addr) { 56 pr_err("No device tree specified in SPL image\n"); 57 hang(); 58 } 59 60 /* 61 * Originally, u-boot-spl will place DTB directly after the kernel, 62 * but the size of the kernel did not include the BSS section, which 63 * means u-boot-spl will place the DTB in the kernel BSS section 64 * causing the DTB to be cleared by kernel BSS initializtion. 65 * Moving DTB in front of the kernel can avoid the error. 66 */ 67#if CONFIG_IS_ENABLED(LOAD_FIT_OPENSBI_OS_BOOT) && \ 68 CONFIG_VAL(PAYLOAD_ARGS_ADDR) 69 memcpy((void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR, spl_image->fdt_addr, 70 fdt_totalsize(spl_image->fdt_addr)); 71 spl_image->fdt_addr = map_sysmem(CONFIG_SPL_PAYLOAD_ARGS_ADDR, 0); 72#endif 73 74 /* 75 * Find next os image in /fit-images 76 * The next os image default is u-boot proper, once enable 77 * OpenSBI OS boot mode, the OS image should be linux. 78 */ 79 if (CONFIG_IS_ENABLED(LOAD_FIT_OPENSBI_OS_BOOT)) 80 os_type = IH_OS_LINUX; 81 else 82 os_type = IH_OS_U_BOOT; 83 84 ret = spl_opensbi_find_os_node(spl_image->fdt_addr, &os_node, os_type); 85 if (ret) { 86 pr_err("Can't find %s node for opensbi, %d\n", 87 genimg_get_os_name(os_type), ret); 88 hang(); 89 } 90 91 /* Get U-Boot entry point */ 92 ret = fit_image_get_entry(spl_image->fdt_addr, os_node, &os_entry); 93 if (ret) 94 ret = fit_image_get_load(spl_image->fdt_addr, os_node, &os_entry); 95 96 /* Prepare opensbi_info object */ 97 opensbi_info.magic = FW_DYNAMIC_INFO_MAGIC_VALUE; 98 opensbi_info.version = FW_DYNAMIC_INFO_VERSION; 99 opensbi_info.next_addr = os_entry; 100 opensbi_info.next_mode = FW_DYNAMIC_INFO_NEXT_MODE_S; 101 opensbi_info.options = CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS; 102 opensbi_info.boot_hart = gd->arch.boot_hart; 103 104 opensbi_entry = (opensbi_entry_t)spl_image->entry_point; 105 invalidate_icache_all(); 106 107#ifdef CONFIG_SPL_SMP 108 /* 109 * Start OpenSBI on all secondary harts and wait for acknowledgment. 110 * 111 * OpenSBI first relocates itself to its link address. This is done by 112 * the main hart. To make sure no hart is still running U-Boot SPL 113 * during relocation, we wait for all secondary harts to acknowledge 114 * the call-function request before entering OpenSBI on the main hart. 115 * Otherwise, code corruption can occur if the link address ranges of 116 * U-Boot SPL and OpenSBI overlap. 117 */ 118 ret = smp_call_function((ulong)spl_image->entry_point, 119 (ulong)spl_image->fdt_addr, 120 (ulong)&opensbi_info, 1); 121 if (ret) 122 hang(); 123#endif 124 opensbi_entry(gd->arch.boot_hart, (ulong)spl_image->fdt_addr, 125 (ulong)&opensbi_info); 126}