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.
This commit is contained in:
parent
146dfd0356
commit
a1aeff27ce
3 changed files with 55 additions and 12 deletions
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2009, 2012-2013 ARM Limited
|
# Copyright (c) 2009, 2012-2013, 2015 ARM Limited
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# The license below extends only to copyright in the software and shall
|
# 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"
|
cxx_header = "arch/arm/system.hh"
|
||||||
load_addr_mask = 0xffffffff
|
load_addr_mask = 0xffffffff
|
||||||
multi_proc = Param.Bool(True, "Multiprocessor system?")
|
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")
|
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")
|
flags_addr = Param.Addr(0, "Address of the flags register for MP booting")
|
||||||
have_security = Param.Bool(False,
|
have_security = Param.Bool(False,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010, 2012-2013 ARM Limited
|
* Copyright (c) 2010, 2012-2013, 2015 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -54,7 +54,9 @@ using namespace std;
|
||||||
using namespace Linux;
|
using namespace Linux;
|
||||||
|
|
||||||
ArmSystem::ArmSystem(Params *p)
|
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),
|
_haveLPAE(p->have_lpae),
|
||||||
_haveVirtualization(p->have_virtualization),
|
_haveVirtualization(p->have_virtualization),
|
||||||
_genericTimer(nullptr),
|
_genericTimer(nullptr),
|
||||||
|
@ -72,12 +74,27 @@ ArmSystem::ArmSystem(Params *p)
|
||||||
fatal("Invalid physical address range (%d)\n", _physAddrRange64);
|
fatal("Invalid physical address range (%d)\n", _physAddrRange64);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->boot_loader != "") {
|
bootLoaders.reserve(p->boot_loader.size());
|
||||||
bootldr = createObjectFile(p->boot_loader);
|
for (const auto &bl : p->boot_loader) {
|
||||||
|
std::unique_ptr<ObjectFile> obj;
|
||||||
|
obj.reset(createObjectFile(bl));
|
||||||
|
|
||||||
if (!bootldr)
|
fatal_if(!obj, "Could not read bootloader: %s\n", bl);
|
||||||
fatal("Could not read bootloader: %s\n", p->boot_loader);
|
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) {
|
if ((bootldr->getArch() == ObjectFile::Arm64) && !_highestELIs64) {
|
||||||
warn("Highest ARM exception-level set to AArch32 but bootloader "
|
warn("Highest ARM exception-level set to AArch32 but bootloader "
|
||||||
"is for AArch64. Assuming you wanted these to match.\n");
|
"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");
|
"is for AArch32. Assuming you wanted these to match.\n");
|
||||||
_highestELIs64 = false;
|
_highestELIs64 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bootldr->loadGlobalSymbols(debugSymbolTable);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
|
debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +183,17 @@ ArmSystem::~ArmSystem()
|
||||||
delete debugPrintkEvent;
|
delete debugPrintkEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObjectFile *
|
||||||
|
ArmSystem::getBootLoader(ObjectFile *const obj)
|
||||||
|
{
|
||||||
|
for (auto &bl : bootLoaders) {
|
||||||
|
if (bl->getArch() == obj->getArch())
|
||||||
|
return bl.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ArmSystem::haveLPAE(ThreadContext *tc)
|
ArmSystem::haveLPAE(ThreadContext *tc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010, 2012-2013 ARM Limited
|
* Copyright (c) 2010, 2012-2013, 2015 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -43,6 +43,7 @@
|
||||||
#ifndef __ARCH_ARM_SYSTEM_HH__
|
#ifndef __ARCH_ARM_SYSTEM_HH__
|
||||||
#define __ARCH_ARM_SYSTEM_HH__
|
#define __ARCH_ARM_SYSTEM_HH__
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -64,6 +65,9 @@ class ArmSystem : public System
|
||||||
*/
|
*/
|
||||||
Linux::DebugPrintkEvent *debugPrintkEvent;
|
Linux::DebugPrintkEvent *debugPrintkEvent;
|
||||||
|
|
||||||
|
/** Bootloaders */
|
||||||
|
std::vector<std::unique_ptr<ObjectFile>> bootLoaders;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to the bootloader object
|
* Pointer to the bootloader object
|
||||||
*/
|
*/
|
||||||
|
@ -112,6 +116,16 @@ class ArmSystem : public System
|
||||||
*/
|
*/
|
||||||
const bool _haveLargeAsid64;
|
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:
|
public:
|
||||||
typedef ArmSystemParams Params;
|
typedef ArmSystemParams Params;
|
||||||
const Params *
|
const Params *
|
||||||
|
|
Loading…
Reference in a new issue