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):
|
||||
type = 'ArmSystem'
|
||||
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):
|
||||
type = 'LinuxArmSystem'
|
||||
load_addr_mask = 0x0fffffff
|
||||
machine_type = Param.ArmMachineType('RealView_PBX',
|
||||
"Machine id from http://www.arm.linux.org.uk/developer/machines/")
|
||||
|
||||
|
||||
|
|
|
@ -123,15 +123,12 @@ void
|
|||
LinuxArmSystem::initState()
|
||||
{
|
||||
ArmSystem::initState();
|
||||
ThreadContext *tc = threadContexts[0];
|
||||
|
||||
// Set the initial PC to be at start of the kernel code
|
||||
tc->pcState(tc->getSystemPtr()->kernelEntry & loadAddrMask);
|
||||
|
||||
// Setup the machine type
|
||||
tc->setIntReg(0, 0);
|
||||
tc->setIntReg(1, params()->machine_type);
|
||||
tc->setIntReg(2, ParamsList);
|
||||
for (int i = 0; i < threadContexts.size(); i++) {
|
||||
threadContexts[i]->setIntReg(0, 0);
|
||||
threadContexts[i]->setIntReg(1, params()->machine_type);
|
||||
threadContexts[i]->setIntReg(2, ParamsList);
|
||||
}
|
||||
}
|
||||
|
||||
LinuxArmSystem::~LinuxArmSystem()
|
||||
|
|
|
@ -43,19 +43,72 @@
|
|||
#include <iostream>
|
||||
|
||||
#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 Linux;
|
||||
|
||||
ArmSystem::ArmSystem(Params *p)
|
||||
: System(p)
|
||||
: System(p), bootldr(NULL)
|
||||
{
|
||||
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()
|
||||
{
|
||||
if (debugPrintkEvent)
|
||||
delete debugPrintkEvent;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,11 +60,24 @@ class ArmSystem : public System
|
|||
*/
|
||||
Linux::DebugPrintkEvent *debugPrintkEvent;
|
||||
|
||||
/**
|
||||
* Pointer to the bootloader object
|
||||
*/
|
||||
ObjectFile *bootldr;
|
||||
|
||||
public:
|
||||
typedef ArmSystemParams Params;
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
ArmSystem(Params *p);
|
||||
~ArmSystem();
|
||||
|
||||
void initState();
|
||||
|
||||
virtual Addr fixFuncEventAddr(Addr addr)
|
||||
{
|
||||
// Remove the low bit that thumb symbols have set
|
||||
|
|
|
@ -60,7 +60,6 @@ initCPU(ThreadContext *tc, int cpuId)
|
|||
// FPEXC.EN = 0
|
||||
|
||||
static Fault reset = new Reset;
|
||||
if (cpuId == 0)
|
||||
reset->invoke(tc);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue