]>
Commit | Line | Data |
---|---|---|
0ac24d56 AF |
1 | /* |
2 | * QEMU RISC-V Boot Helper | |
3 | * | |
4 | * Copyright (c) 2017 SiFive, Inc. | |
5 | * Copyright (c) 2019 Alistair Francis <alistair.francis@wdc.com> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms and conditions of the GNU General Public License, | |
9 | * version 2 or later, as published by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope it will be useful, but WITHOUT | |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 | * more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License along with | |
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include "qemu/osdep.h" | |
21 | #include "qemu/units.h" | |
22 | #include "qemu/error-report.h" | |
23 | #include "exec/cpu-defs.h" | |
24 | #include "hw/loader.h" | |
25 | #include "hw/riscv/boot.h" | |
b3042223 | 26 | #include "hw/boards.h" |
0ac24d56 AF |
27 | #include "elf.h" |
28 | ||
b3042223 AF |
29 | #if defined(TARGET_RISCV32) |
30 | # define KERNEL_BOOT_ADDRESS 0x80400000 | |
31 | #else | |
32 | # define KERNEL_BOOT_ADDRESS 0x80200000 | |
33 | #endif | |
34 | ||
35 | target_ulong riscv_load_firmware(const char *firmware_filename, | |
36 | hwaddr firmware_load_addr) | |
37 | { | |
38 | uint64_t firmware_entry, firmware_start, firmware_end; | |
39 | ||
40 | if (load_elf(firmware_filename, NULL, NULL, NULL, &firmware_entry, | |
41 | &firmware_start, &firmware_end, 0, EM_RISCV, 1, 0) > 0) { | |
42 | return firmware_entry; | |
43 | } | |
44 | ||
45 | if (load_image_targphys_as(firmware_filename, firmware_load_addr, | |
46 | ram_size, NULL) > 0) { | |
47 | return firmware_load_addr; | |
48 | } | |
49 | ||
50 | error_report("could not load firmware '%s'", firmware_filename); | |
51 | exit(1); | |
52 | } | |
53 | ||
0ac24d56 AF |
54 | target_ulong riscv_load_kernel(const char *kernel_filename) |
55 | { | |
56 | uint64_t kernel_entry, kernel_high; | |
57 | ||
58 | if (load_elf(kernel_filename, NULL, NULL, NULL, | |
395fd695 AF |
59 | &kernel_entry, NULL, &kernel_high, 0, EM_RISCV, 1, 0) > 0) { |
60 | return kernel_entry; | |
0ac24d56 AF |
61 | } |
62 | ||
395fd695 AF |
63 | if (load_uimage_as(kernel_filename, &kernel_entry, NULL, NULL, |
64 | NULL, NULL, NULL) > 0) { | |
65 | return kernel_entry; | |
66 | } | |
67 | ||
68 | if (load_image_targphys_as(kernel_filename, KERNEL_BOOT_ADDRESS, | |
69 | ram_size, NULL) > 0) { | |
70 | return KERNEL_BOOT_ADDRESS; | |
71 | } | |
72 | ||
73 | error_report("could not load kernel '%s'", kernel_filename); | |
74 | exit(1); | |
0ac24d56 AF |
75 | } |
76 | ||
77 | hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size, | |
78 | uint64_t kernel_entry, hwaddr *start) | |
79 | { | |
80 | int size; | |
81 | ||
82 | /* | |
83 | * We want to put the initrd far enough into RAM that when the | |
84 | * kernel is uncompressed it will not clobber the initrd. However | |
85 | * on boards without much RAM we must ensure that we still leave | |
86 | * enough room for a decent sized initrd, and on boards with large | |
87 | * amounts of RAM we must avoid the initrd being so far up in RAM | |
88 | * that it is outside lowmem and inaccessible to the kernel. | |
89 | * So for boards with less than 256MB of RAM we put the initrd | |
90 | * halfway into RAM, and for boards with 256MB of RAM or more we put | |
91 | * the initrd at 128MB. | |
92 | */ | |
93 | *start = kernel_entry + MIN(mem_size / 2, 128 * MiB); | |
94 | ||
95 | size = load_ramdisk(filename, *start, mem_size - *start); | |
96 | if (size == -1) { | |
97 | size = load_image_targphys(filename, *start, mem_size - *start); | |
98 | if (size == -1) { | |
99 | error_report("could not load ramdisk '%s'", filename); | |
100 | exit(1); | |
101 | } | |
102 | } | |
103 | ||
104 | return *start + size; | |
105 | } |