ARM: Add support for loading the a bootloader and configuring parameters for it
This commit is contained in:
parent
1b505f5291
commit
42e7888855
5 changed files with 82 additions and 13 deletions
|
@ -46,9 +46,16 @@ class ArmMachineType(Enum):
|
||||||
class ArmSystem(System):
|
class ArmSystem(System):
|
||||||
type = 'ArmSystem'
|
type = 'ArmSystem'
|
||||||
load_addr_mask = 0xffffffff
|
load_addr_mask = 0xffffffff
|
||||||
|
boot_loader = Param.String("", "File that contains the boot loader code if any")
|
||||||
|
boot_loader_mem = Param.PhysicalMemory(NULL,
|
||||||
|
"Memory object that boot loader is to be loaded into")
|
||||||
|
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")
|
||||||
|
|
||||||
class LinuxArmSystem(ArmSystem):
|
class LinuxArmSystem(ArmSystem):
|
||||||
type = 'LinuxArmSystem'
|
type = 'LinuxArmSystem'
|
||||||
load_addr_mask = 0x0fffffff
|
load_addr_mask = 0x0fffffff
|
||||||
machine_type = Param.ArmMachineType('RealView_PBX',
|
machine_type = Param.ArmMachineType('RealView_PBX',
|
||||||
"Machine id from http://www.arm.linux.org.uk/developer/machines/")
|
"Machine id from http://www.arm.linux.org.uk/developer/machines/")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -123,15 +123,12 @@ void
|
||||||
LinuxArmSystem::initState()
|
LinuxArmSystem::initState()
|
||||||
{
|
{
|
||||||
ArmSystem::initState();
|
ArmSystem::initState();
|
||||||
ThreadContext *tc = threadContexts[0];
|
|
||||||
|
|
||||||
// Set the initial PC to be at start of the kernel code
|
for (int i = 0; i < threadContexts.size(); i++) {
|
||||||
tc->pcState(tc->getSystemPtr()->kernelEntry & loadAddrMask);
|
threadContexts[i]->setIntReg(0, 0);
|
||||||
|
threadContexts[i]->setIntReg(1, params()->machine_type);
|
||||||
// Setup the machine type
|
threadContexts[i]->setIntReg(2, ParamsList);
|
||||||
tc->setIntReg(0, 0);
|
}
|
||||||
tc->setIntReg(1, params()->machine_type);
|
|
||||||
tc->setIntReg(2, ParamsList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LinuxArmSystem::~LinuxArmSystem()
|
LinuxArmSystem::~LinuxArmSystem()
|
||||||
|
|
|
@ -43,20 +43,73 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "arch/arm/system.hh"
|
#include "arch/arm/system.hh"
|
||||||
|
#include "base/loader/object_file.hh"
|
||||||
|
#include "base/loader/symtab.hh"
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
#include "mem/physical.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Linux;
|
using namespace Linux;
|
||||||
|
|
||||||
ArmSystem::ArmSystem(Params *p)
|
ArmSystem::ArmSystem(Params *p)
|
||||||
: System(p)
|
: System(p), bootldr(NULL)
|
||||||
{
|
{
|
||||||
debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
|
debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
|
||||||
|
|
||||||
|
if ((p->boot_loader == "") != (p->boot_loader_mem == NULL))
|
||||||
|
fatal("If boot_loader is specifed, memory to load it must be also.\n");
|
||||||
|
|
||||||
|
if (p->boot_loader != "") {
|
||||||
|
bootldr = createObjectFile(p->boot_loader);
|
||||||
|
|
||||||
|
if (!bootldr)
|
||||||
|
fatal("Could not read bootloader: %s\n", p->boot_loader);
|
||||||
|
|
||||||
|
Port *mem_port;
|
||||||
|
FunctionalPort fp(name() + "-fport");
|
||||||
|
mem_port = p->boot_loader_mem->getPort("functional");
|
||||||
|
fp.setPeer(mem_port);
|
||||||
|
mem_port->setPeer(&fp);
|
||||||
|
|
||||||
|
bootldr->loadSections(&fp);
|
||||||
|
bootldr->loadGlobalSymbols(debugSymbolTable);
|
||||||
|
|
||||||
|
uint8_t jump_to_bl[] =
|
||||||
|
{
|
||||||
|
0x07, 0xf0, 0xa0, 0xe1 // branch to r7
|
||||||
|
};
|
||||||
|
functionalPort->writeBlob(0x0, jump_to_bl, sizeof(jump_to_bl));
|
||||||
|
|
||||||
|
inform("Using bootloader at address %#x\n", bootldr->entryPoint());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ArmSystem::initState()
|
||||||
|
{
|
||||||
|
System::initState();
|
||||||
|
if (bootldr) {
|
||||||
|
// Put the address of the boot loader into r7 so we know
|
||||||
|
// where to branch to after the reset fault
|
||||||
|
// All other values needed by the boot loader to know what to do
|
||||||
|
for (int i = 0; i < threadContexts.size(); i++) {
|
||||||
|
threadContexts[i]->setIntReg(3, kernelEntry & loadAddrMask);
|
||||||
|
threadContexts[i]->setIntReg(4, params()->gic_cpu_addr);
|
||||||
|
threadContexts[i]->setIntReg(5, params()->flags_addr);
|
||||||
|
threadContexts[i]->setIntReg(7, bootldr->entryPoint());
|
||||||
|
}
|
||||||
|
if (!params()->gic_cpu_addr || !params()->flags_addr)
|
||||||
|
fatal("gic_cpu_addr && flags_addr must be set with bootloader\n");
|
||||||
|
} else {
|
||||||
|
// Set the initial PC to be at start of the kernel code
|
||||||
|
threadContexts[0]->pcState(kernelEntry & loadAddrMask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArmSystem::~ArmSystem()
|
ArmSystem::~ArmSystem()
|
||||||
{
|
{
|
||||||
delete debugPrintkEvent;
|
if (debugPrintkEvent)
|
||||||
|
delete debugPrintkEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,11 +60,24 @@ class ArmSystem : public System
|
||||||
*/
|
*/
|
||||||
Linux::DebugPrintkEvent *debugPrintkEvent;
|
Linux::DebugPrintkEvent *debugPrintkEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to the bootloader object
|
||||||
|
*/
|
||||||
|
ObjectFile *bootldr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef ArmSystemParams Params;
|
typedef ArmSystemParams Params;
|
||||||
|
const Params *
|
||||||
|
params() const
|
||||||
|
{
|
||||||
|
return dynamic_cast<const Params *>(_params);
|
||||||
|
}
|
||||||
|
|
||||||
ArmSystem(Params *p);
|
ArmSystem(Params *p);
|
||||||
~ArmSystem();
|
~ArmSystem();
|
||||||
|
|
||||||
|
void initState();
|
||||||
|
|
||||||
virtual Addr fixFuncEventAddr(Addr addr)
|
virtual Addr fixFuncEventAddr(Addr addr)
|
||||||
{
|
{
|
||||||
// Remove the low bit that thumb symbols have set
|
// Remove the low bit that thumb symbols have set
|
||||||
|
|
|
@ -60,8 +60,7 @@ initCPU(ThreadContext *tc, int cpuId)
|
||||||
// FPEXC.EN = 0
|
// FPEXC.EN = 0
|
||||||
|
|
||||||
static Fault reset = new Reset;
|
static Fault reset = new Reset;
|
||||||
if (cpuId == 0)
|
reset->invoke(tc);
|
||||||
reset->invoke(tc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
|
|
Loading…
Reference in a new issue