summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/ArmSystem.py8
-rw-r--r--src/arch/arm/linux/system.cc99
-rw-r--r--src/base/loader/object_file.hh5
3 files changed, 77 insertions, 35 deletions
diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py
index 54bf99e90..db0febe18 100644
--- a/src/arch/arm/ArmSystem.py
+++ b/src/arch/arm/ArmSystem.py
@@ -65,5 +65,9 @@ class LinuxArmSystem(ArmSystem):
load_addr_mask = 0x0fffffff
machine_type = Param.ArmMachineType('RealView_PBX',
"Machine id from http://www.arm.linux.org.uk/developer/machines/")
- atags_addr = Param.Addr(0x100, "Address where default atags structure should be written")
- early_kernel_symbols = Param.Bool(False, "enable early kernel symbol tables before MMU")
+ atags_addr = Param.Addr(0x100,
+ "Address where default atags structure should be written")
+ dtb_filename = Param.String("",
+ "File that contains the Device Tree Blob. Don't use DTB if empty.")
+ early_kernel_symbols = Param.Bool(False,
+ "enable early kernel symbol tables before MMU")
diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc
index d537717ec..d9684fe66 100644
--- a/src/arch/arm/linux/system.cc
+++ b/src/arch/arm/linux/system.cc
@@ -122,40 +122,73 @@ LinuxArmSystem::initState()
}
// Setup boot data structure
- AtagCore *ac = new AtagCore;
- ac->flags(1); // read-only
- ac->pagesize(8192);
- ac->rootdev(0);
-
- AddrRangeList atagRanges = physmem.getConfAddrRanges();
- if (atagRanges.size() != 1) {
- fatal("Expected a single ATAG memory entry but got %d\n",
- atagRanges.size());
+ Addr addr = 0;
+ // Check if the kernel image has a symbol that tells us it supports
+ // device trees.
+ bool kernel_has_fdt_support =
+ kernelSymtab->findAddress("unflatten_device_tree", addr);
+ bool dtb_file_specified = params()->dtb_filename != "";
+
+ if (kernel_has_fdt_support && dtb_file_specified) {
+ // Kernel supports flattened device tree and dtb file specified.
+ // Using Device Tree Blob to describe system configuration.
+ inform("Loading DTB file: %s\n", params()->dtb_filename);
+
+ ObjectFile *dtb_file = createObjectFile(params()->dtb_filename, true);
+ if (!dtb_file) {
+ fatal("couldn't load DTB file: %s\n", params()->dtb_filename);
+ }
+ dtb_file->setTextBase(params()->atags_addr);
+ dtb_file->loadSections(physProxy);
+ delete dtb_file;
+ } else {
+ // Using ATAGS
+ // Warn if the kernel supports FDT and we haven't specified one
+ if (kernel_has_fdt_support) {
+ assert(!dtb_file_specified);
+ warn("Kernel supports device tree, but no DTB file specified\n");
+ }
+ // Warn if the kernel doesn't support FDT and we have specified one
+ if (dtb_file_specified) {
+ assert(!kernel_has_fdt_support);
+ warn("DTB file specified, but no device tree support in kernel\n");
+ }
+
+ AtagCore *ac = new AtagCore;
+ ac->flags(1); // read-only
+ ac->pagesize(8192);
+ ac->rootdev(0);
+
+ AddrRangeList atagRanges = physmem.getConfAddrRanges();
+ if (atagRanges.size() != 1) {
+ fatal("Expected a single ATAG memory entry but got %d\n",
+ atagRanges.size());
+ }
+ AtagMem *am = new AtagMem;
+ am->memSize(atagRanges.begin()->size());
+ am->memStart(atagRanges.begin()->start);
+
+ AtagCmdline *ad = new AtagCmdline;
+ ad->cmdline(params()->boot_osflags);
+
+ DPRINTF(Loader, "boot command line %d bytes: %s\n", ad->size() <<2, params()->boot_osflags.c_str());
+
+ AtagNone *an = new AtagNone;
+
+ uint32_t size = ac->size() + am->size() + ad->size() + an->size();
+ uint32_t offset = 0;
+ uint8_t *boot_data = new uint8_t[size << 2];
+
+ offset += ac->copyOut(boot_data + offset);
+ offset += am->copyOut(boot_data + offset);
+ offset += ad->copyOut(boot_data + offset);
+ offset += an->copyOut(boot_data + offset);
+
+ DPRINTF(Loader, "Boot atags was %d bytes in total\n", size << 2);
+ DDUMP(Loader, boot_data, size << 2);
+
+ physProxy.writeBlob(params()->atags_addr, boot_data, size << 2);
}
- AtagMem *am = new AtagMem;
- am->memSize(atagRanges.begin()->size());
- am->memStart(atagRanges.begin()->start);
-
- AtagCmdline *ad = new AtagCmdline;
- ad->cmdline(params()->boot_osflags);
-
- DPRINTF(Loader, "boot command line %d bytes: %s\n", ad->size() <<2, params()->boot_osflags.c_str());
-
- AtagNone *an = new AtagNone;
-
- uint32_t size = ac->size() + am->size() + ad->size() + an->size();
- uint32_t offset = 0;
- uint8_t *boot_data = new uint8_t[size << 2];
-
- offset += ac->copyOut(boot_data + offset);
- offset += am->copyOut(boot_data + offset);
- offset += ad->copyOut(boot_data + offset);
- offset += an->copyOut(boot_data + offset);
-
- DPRINTF(Loader, "Boot atags was %d bytes in total\n", size << 2);
- DDUMP(Loader, boot_data, size << 2);
-
- physProxy.writeBlob(params()->atags_addr, boot_data, size << 2);
for (int i = 0; i < threadContexts.size(); i++) {
threadContexts[i]->setIntReg(0, 0);
diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh
index 2ec41bf12..4a789d321 100644
--- a/src/base/loader/object_file.hh
+++ b/src/base/loader/object_file.hh
@@ -127,6 +127,11 @@ class ObjectFile
size_t dataSize() const { return data.size; }
size_t bssSize() const { return bss.size; }
+ /* This function allows you to override the base address where
+ * a binary is going to be loaded or set it if the binary is just a
+ * blob that doesn't include an object header.
+ * @param a address to load the binary/text section at
+ */
void setTextBase(Addr a) { text.baseAddr = a; }
};