summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorAndreas Sandberg <andreas.sandberg@arm.com>2015-12-03 23:53:37 +0000
committerAndreas Sandberg <andreas.sandberg@arm.com>2015-12-03 23:53:37 +0000
commita1aeff27ce2978bb5fd0a3da66878d914cfb4da2 (patch)
tree6ec8b023033566edef0276710153fabc2917e33e /src/arch
parent146dfd0356c4a086e397679eba1ffb57b19ce07a (diff)
downloadgem5-a1aeff27ce2978bb5fd0a3da66878d914cfb4da2.tar.xz
arm: Add support for automatic boot loader selection
Add support for automatically selecting a boot loader that matches the guest system's kernel. Instead of accepting a single boot loader, the ArmSystem class now accepts a vector of boot loaders. When initializing a system, the we now look for the first boot loader with an architecture that matches the kernel. This changeset makes it possible to use the same system for both 64-bit and 32-bit kernels.
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/arm/ArmSystem.py7
-rw-r--r--src/arch/arm/system.cc44
-rw-r--r--src/arch/arm/system.hh16
3 files changed, 55 insertions, 12 deletions
diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py
index b9769da4b..1e5acc4e6 100644
--- a/src/arch/arm/ArmSystem.py
+++ b/src/arch/arm/ArmSystem.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2009, 2012-2013 ARM Limited
+# Copyright (c) 2009, 2012-2013, 2015 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
@@ -50,7 +50,10 @@ class ArmSystem(System):
cxx_header = "arch/arm/system.hh"
load_addr_mask = 0xffffffff
multi_proc = Param.Bool(True, "Multiprocessor system?")
- boot_loader = Param.String("", "File that contains the boot loader code if any")
+ boot_loader = VectorParam.String([],
+ "File that contains the boot loader code. Zero or more files may be "
+ "specified. The first boot loader that matches the kernel's "
+ "architecture will be used.")
gic_cpu_addr = Param.Addr(0, "Addres of the GIC CPU interface")
flags_addr = Param.Addr(0, "Address of the flags register for MP booting")
have_security = Param.Bool(False,
diff --git a/src/arch/arm/system.cc b/src/arch/arm/system.cc
index 8e4e82571..f4241aa3c 100644
--- a/src/arch/arm/system.cc
+++ b/src/arch/arm/system.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2012-2013 ARM Limited
+ * Copyright (c) 2010, 2012-2013, 2015 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -54,7 +54,9 @@ using namespace std;
using namespace Linux;
ArmSystem::ArmSystem(Params *p)
- : System(p), bootldr(NULL), _haveSecurity(p->have_security),
+ : System(p),
+ bootLoaders(), bootldr(nullptr),
+ _haveSecurity(p->have_security),
_haveLPAE(p->have_lpae),
_haveVirtualization(p->have_virtualization),
_genericTimer(nullptr),
@@ -72,12 +74,27 @@ ArmSystem::ArmSystem(Params *p)
fatal("Invalid physical address range (%d)\n", _physAddrRange64);
}
- if (p->boot_loader != "") {
- bootldr = createObjectFile(p->boot_loader);
+ bootLoaders.reserve(p->boot_loader.size());
+ for (const auto &bl : p->boot_loader) {
+ std::unique_ptr<ObjectFile> obj;
+ obj.reset(createObjectFile(bl));
- if (!bootldr)
- fatal("Could not read bootloader: %s\n", p->boot_loader);
+ fatal_if(!obj, "Could not read bootloader: %s\n", bl);
+ bootLoaders.emplace_back(std::move(obj));
+ }
+
+ if (kernel) {
+ bootldr = getBootLoader(kernel);
+ } else if (!bootLoaders.empty()) {
+ // No kernel specified, default to the first boot loader
+ bootldr = bootLoaders[0].get();
+ }
+
+ if (!bootLoaders.empty() && !bootldr)
+ fatal("Can't find a matching boot loader / kernel combination!");
+ if (bootldr) {
+ bootldr->loadGlobalSymbols(debugSymbolTable);
if ((bootldr->getArch() == ObjectFile::Arm64) && !_highestELIs64) {
warn("Highest ARM exception-level set to AArch32 but bootloader "
"is for AArch64. Assuming you wanted these to match.\n");
@@ -87,10 +104,8 @@ ArmSystem::ArmSystem(Params *p)
"is for AArch32. Assuming you wanted these to match.\n");
_highestELIs64 = false;
}
-
- bootldr->loadGlobalSymbols(debugSymbolTable);
-
}
+
debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
}
@@ -168,6 +183,17 @@ ArmSystem::~ArmSystem()
delete debugPrintkEvent;
}
+ObjectFile *
+ArmSystem::getBootLoader(ObjectFile *const obj)
+{
+ for (auto &bl : bootLoaders) {
+ if (bl->getArch() == obj->getArch())
+ return bl.get();
+ }
+
+ return nullptr;
+}
+
bool
ArmSystem::haveLPAE(ThreadContext *tc)
{
diff --git a/src/arch/arm/system.hh b/src/arch/arm/system.hh
index 0b652f76c..511118d4d 100644
--- a/src/arch/arm/system.hh
+++ b/src/arch/arm/system.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2012-2013 ARM Limited
+ * Copyright (c) 2010, 2012-2013, 2015 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -43,6 +43,7 @@
#ifndef __ARCH_ARM_SYSTEM_HH__
#define __ARCH_ARM_SYSTEM_HH__
+#include <memory>
#include <string>
#include <vector>
@@ -64,6 +65,9 @@ class ArmSystem : public System
*/
Linux::DebugPrintkEvent *debugPrintkEvent;
+ /** Bootloaders */
+ std::vector<std::unique_ptr<ObjectFile>> bootLoaders;
+
/**
* Pointer to the bootloader object
*/
@@ -112,6 +116,16 @@ class ArmSystem : public System
*/
const bool _haveLargeAsid64;
+ protected:
+ /**
+ * Get a boot loader that matches the kernel.
+ *
+ * @param obj Kernel binary
+ * @return Pointer to boot loader ObjectFile or nullptr if there
+ * is no matching boot loader.
+ */
+ ObjectFile *getBootLoader(ObjectFile *const obj);
+
public:
typedef ArmSystemParams Params;
const Params *