aboutsummaryrefslogtreecommitdiff
path: root/hw/arm/boot.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/arm/boot.c')
-rw-r--r--hw/arm/boot.c73
1 files changed, 40 insertions, 33 deletions
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index d480a7d..becd827 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -14,15 +14,18 @@
#include <libfdt.h>
#include "hw/arm/boot.h"
#include "hw/arm/linux-boot-if.h"
-#include "sysemu/kvm.h"
-#include "sysemu/tcg.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/numa.h"
+#include "cpu.h"
+#include "exec/target_page.h"
+#include "system/kvm.h"
+#include "system/tcg.h"
+#include "system/system.h"
+#include "system/memory.h"
+#include "system/numa.h"
#include "hw/boards.h"
-#include "sysemu/reset.h"
+#include "system/reset.h"
#include "hw/loader.h"
#include "elf.h"
-#include "sysemu/device_tree.h"
+#include "system/device_tree.h"
#include "qemu/config-file.h"
#include "qemu/option.h"
#include "qemu/units.h"
@@ -432,13 +435,12 @@ out:
return ret;
}
-static void fdt_add_psci_node(void *fdt)
+static void fdt_add_psci_node(void *fdt, ARMCPU *armcpu)
{
uint32_t cpu_suspend_fn;
uint32_t cpu_off_fn;
uint32_t cpu_on_fn;
uint32_t migrate_fn;
- ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
const char *psci_method;
int64_t psci_conduit;
int rc;
@@ -512,7 +514,8 @@ static void fdt_add_psci_node(void *fdt)
}
int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
- hwaddr addr_limit, AddressSpace *as, MachineState *ms)
+ hwaddr addr_limit, AddressSpace *as, MachineState *ms,
+ ARMCPU *cpu)
{
void *fdt = NULL;
int size, rc, n = 0;
@@ -524,7 +527,7 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
if (binfo->dtb_filename) {
char *filename;
- filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
+ filename = qemu_find_file(QEMU_FILE_TYPE_DTB, binfo->dtb_filename);
if (!filename) {
fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
goto fail;
@@ -655,14 +658,12 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
}
}
- fdt_add_psci_node(fdt);
+ fdt_add_psci_node(fdt, cpu);
if (binfo->modify_dtb) {
binfo->modify_dtb(binfo, fdt);
}
- qemu_fdt_dumpdtb(fdt, size);
-
/* Put the DTB into the memory map as a ROM image: this will ensure
* the DTB is copied again upon reset, even if addr points into RAM.
*/
@@ -743,7 +744,7 @@ static void do_cpu_reset(void *opaque)
} else {
if (arm_feature(env, ARM_FEATURE_EL3) &&
(info->secure_boot ||
- (info->secure_board_setup && cs == first_cpu))) {
+ (info->secure_board_setup && cpu == info->primary_cpu))) {
/* Start this CPU in Secure SVC */
target_el = 3;
}
@@ -751,7 +752,7 @@ static void do_cpu_reset(void *opaque)
arm_emulate_firmware_reset(cs, target_el);
- if (cs == first_cpu) {
+ if (cpu == info->primary_cpu) {
AddressSpace *as = arm_boot_address_space(cpu, info);
cpu_set_pc(cs, info->loader_start);
@@ -798,24 +799,28 @@ static ssize_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
Elf64_Ehdr h64;
} elf_header;
int data_swab = 0;
- bool big_endian;
- ssize_t ret = -1;
+ int elf_data_order;
+ ssize_t ret;
Error *err = NULL;
load_elf_hdr(info->kernel_filename, &elf_header, &elf_is64, &err);
if (err) {
+ /*
+ * If the file is not an ELF file we silently return.
+ * The caller will fall back to try other formats.
+ */
error_free(err);
- return ret;
+ return -1;
}
if (elf_is64) {
- big_endian = elf_header.h64.e_ident[EI_DATA] == ELFDATA2MSB;
- info->endianness = big_endian ? ARM_ENDIANNESS_BE8
- : ARM_ENDIANNESS_LE;
+ elf_data_order = elf_header.h64.e_ident[EI_DATA];
+ info->endianness = elf_data_order == ELFDATA2MSB ? ARM_ENDIANNESS_BE8
+ : ARM_ENDIANNESS_LE;
} else {
- big_endian = elf_header.h32.e_ident[EI_DATA] == ELFDATA2MSB;
- if (big_endian) {
+ elf_data_order = elf_header.h32.e_ident[EI_DATA];
+ if (elf_data_order == ELFDATA2MSB) {
if (bswap32(elf_header.h32.e_flags) & EF_ARM_BE8) {
info->endianness = ARM_ENDIANNESS_BE8;
} else {
@@ -835,10 +840,12 @@ static ssize_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
}
ret = load_elf_as(info->kernel_filename, NULL, NULL, NULL,
- pentry, lowaddr, highaddr, NULL, big_endian, elf_machine,
- 1, data_swab, as);
+ pentry, lowaddr, highaddr, NULL, elf_data_order,
+ elf_machine, 1, data_swab, as);
if (ret <= 0) {
/* The header loaded but the image didn't */
+ error_report("Couldn't load elf '%s': %s",
+ info->kernel_filename, load_elf_strerror(ret));
exit(1);
}
@@ -851,7 +858,7 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
uint64_t kernel_size = 0;
uint8_t *buffer;
- int size;
+ ssize_t size;
/* On aarch64, it's the bootloader's job to uncompress the kernel. */
size = load_image_gzipped_buffer(filename, LOAD_IMAGE_MAX_GUNZIP_BYTES,
@@ -1232,6 +1239,9 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
info->dtb_filename = ms->dtb;
info->dtb_limit = 0;
+ /* We assume the CPU passed as argument is the primary CPU. */
+ info->primary_cpu = cpu;
+
/* Load the kernel. */
if (!info->kernel_filename || info->firmware_loaded) {
arm_setup_firmware_boot(cpu, info);
@@ -1281,12 +1291,8 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
object_property_set_int(cpuobj, "psci-conduit", info->psci_conduit,
&error_abort);
- /*
- * Secondary CPUs start in PSCI powered-down state. Like the
- * code in do_cpu_reset(), we assume first_cpu is the primary
- * CPU.
- */
- if (cs != first_cpu) {
+ /* Secondary CPUs start in PSCI powered-down state. */
+ if (ARM_CPU(cs) != info->primary_cpu) {
object_property_set_bool(cpuobj, "start-powered-off", true,
&error_abort);
}
@@ -1321,7 +1327,8 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
* decided whether to enable PSCI and set the psci-conduit CPU properties.
*/
if (!info->skip_dtb_autoload && have_dtb(info)) {
- if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms) < 0) {
+ if (arm_load_dtb(info->dtb_start, info, info->dtb_limit,
+ as, ms, cpu) < 0) {
exit(1);
}
}