summaryrefslogtreecommitdiff
path: root/src/arch/arm/linux
diff options
context:
space:
mode:
authorDam Sunwoo <dam.sunwoo@arm.com>2012-09-25 11:49:41 -0500
committerDam Sunwoo <dam.sunwoo@arm.com>2012-09-25 11:49:41 -0500
commitacbb7a2eed15258061e038254469197ae3831165 (patch)
tree30bccf3e2f0ede2e050abfad2e87d7fb1c57379c /src/arch/arm/linux
parent5adb4ddc126385567f602568c5ddbaa1d6fe1d6f (diff)
downloadgem5-acbb7a2eed15258061e038254469197ae3831165.tar.xz
ARM: added support for flattened device tree blobs
Newer Linux kernels require DTB (device tree blobs) to specify platform configurations. The input DTB filename can be specified through gem5 parameters in LinuxArmSystem.
Diffstat (limited to 'src/arch/arm/linux')
-rw-r--r--src/arch/arm/linux/system.cc99
1 files changed, 66 insertions, 33 deletions
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);