1 /* 2 * SPDX-License-Identifier: GPL-2.0-or-later 3 * 4 * QEMU OpenRISC boot helpers. 5 * 6 * (c) 2022 Stafford Horne <shorne@gmail.com> 7 */ 8 9 #include "qemu/osdep.h" 10 #include "cpu.h" 11 #include "exec/cpu-defs.h" 12 #include "elf.h" 13 #include "hw/loader.h" 14 #include "hw/openrisc/boot.h" 15 #include "sysemu/device_tree.h" 16 #include "sysemu/qtest.h" 17 #include "sysemu/reset.h" 18 19 #include <libfdt.h> 20 21 #define KERNEL_LOAD_ADDR 0x100 22 23 hwaddr openrisc_load_kernel(ram_addr_t ram_size, 24 const char *kernel_filename, 25 uint32_t *bootstrap_pc) 26 { 27 long kernel_size; 28 uint64_t elf_entry; 29 uint64_t high_addr; 30 hwaddr entry; 31 32 if (kernel_filename && !qtest_enabled()) { 33 kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, 34 &elf_entry, NULL, &high_addr, NULL, 1, 35 EM_OPENRISC, 1, 0); 36 entry = elf_entry; 37 if (kernel_size < 0) { 38 kernel_size = load_uimage(kernel_filename, 39 &entry, NULL, NULL, NULL, NULL); 40 high_addr = entry + kernel_size; 41 } 42 if (kernel_size < 0) { 43 kernel_size = load_image_targphys(kernel_filename, 44 KERNEL_LOAD_ADDR, 45 ram_size - KERNEL_LOAD_ADDR); 46 high_addr = KERNEL_LOAD_ADDR + kernel_size; 47 } 48 49 if (entry <= 0) { 50 entry = KERNEL_LOAD_ADDR; 51 } 52 53 if (kernel_size < 0) { 54 error_report("couldn't load the kernel '%s'", kernel_filename); 55 exit(1); 56 } 57 *bootstrap_pc = entry; 58 59 return high_addr; 60 } 61 return 0; 62 } 63 64 hwaddr openrisc_load_initrd(void *fdt, const char *filename, 65 hwaddr load_start, uint64_t mem_size) 66 { 67 int size; 68 hwaddr start; 69 70 /* We put the initrd right after the kernel; page aligned. */ 71 start = TARGET_PAGE_ALIGN(load_start); 72 73 size = load_ramdisk(filename, start, mem_size - start); 74 if (size < 0) { 75 size = load_image_targphys(filename, start, mem_size - start); 76 if (size < 0) { 77 error_report("could not load ramdisk '%s'", filename); 78 exit(1); 79 } 80 } 81 82 if (fdt) { 83 qemu_fdt_setprop_cell(fdt, "/chosen", 84 "linux,initrd-start", start); 85 qemu_fdt_setprop_cell(fdt, "/chosen", 86 "linux,initrd-end", start + size); 87 } 88 89 return start + size; 90 } 91 92 uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start, 93 uint64_t mem_size) 94 { 95 uint32_t fdt_addr; 96 int ret; 97 int fdtsize = fdt_totalsize(fdt); 98 99 if (fdtsize <= 0) { 100 error_report("invalid device-tree"); 101 exit(1); 102 } 103 104 /* We put fdt right after the kernel and/or initrd. */ 105 fdt_addr = TARGET_PAGE_ALIGN(load_start); 106 107 ret = fdt_pack(fdt); 108 /* Should only fail if we've built a corrupted tree */ 109 g_assert(ret == 0); 110 /* copy in the device tree */ 111 qemu_fdt_dumpdtb(fdt, fdtsize); 112 113 rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr, 114 &address_space_memory); 115 qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds, 116 rom_ptr_for_as(&address_space_memory, fdt_addr, fdtsize)); 117 118 return fdt_addr; 119 } 120