diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/arm/ArmSystem.py | 8 | ||||
-rw-r--r-- | src/arch/arm/linux/system.cc | 99 | ||||
-rw-r--r-- | src/base/loader/object_file.hh | 5 |
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; } }; |