summaryrefslogtreecommitdiff
path: root/src/arch/arm/system.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm/system.cc')
-rw-r--r--src/arch/arm/system.cc57
1 files changed, 55 insertions, 2 deletions
diff --git a/src/arch/arm/system.cc b/src/arch/arm/system.cc
index d61db4cfe..8431bfff2 100644
--- a/src/arch/arm/system.cc
+++ b/src/arch/arm/system.cc
@@ -43,20 +43,73 @@
#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()
{
- delete debugPrintkEvent;
+ if (debugPrintkEvent)
+ delete debugPrintkEvent;
}