diff --git a/src/mem/AbstractMemory.py b/src/mem/AbstractMemory.py index 897e9e3cd5..4c21d529ce 100644 --- a/src/mem/AbstractMemory.py +++ b/src/mem/AbstractMemory.py @@ -64,3 +64,8 @@ class AbstractMemory(ClockedObject): # configuration information about the physical memory layout to # the kernel, e.g. using ATAG or ACPI conf_table_reported = Param.Bool(True, "Report to configuration table") + + # Image file to load into this memory as its initial contents. This is + # particularly useful for ROMs. + image_file = Param.String('', + "Image to load into memory as its initial contents") diff --git a/src/mem/abstract_mem.cc b/src/mem/abstract_mem.cc index b5412badf4..aa800113be 100644 --- a/src/mem/abstract_mem.cc +++ b/src/mem/abstract_mem.cc @@ -43,6 +43,8 @@ #include #include "arch/locked_mem.hh" +#include "base/loader/memory_image.hh" +#include "base/loader/object_file.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" #include "debug/LLSC.hh" @@ -66,6 +68,38 @@ AbstractMemory::AbstractMemory(const Params *p) : range.to_string()); } +void +AbstractMemory::initState() +{ + ClockedObject::initState(); + + const auto &file = params()->image_file; + if (file == "") + return; + + auto *object = createObjectFile(file, true); + fatal_if(!object, "%s: Could not load %s.", name(), file); + + panic_if(!object->loadGlobalSymbols(debugSymbolTable), + "%s: Could not load symbols from %s.", name(), file); + + MemoryImage image = object->buildImage(); + + AddrRange image_range(image.minAddr(), image.maxAddr()); + if (!range.contains(image_range.start())) { + warn("%s: Moving image from %s to memory address range %s.", + name(), image_range.to_string(), range.to_string()); + image = image.offset(range.start()); + image_range = AddrRange(image.minAddr(), image.maxAddr()); + } + panic_if(!image_range.isSubset(range), "%s: memory image %s doesn't fit.", + name(), file); + + PortProxy proxy([this](PacketPtr pkt) { functionalAccess(pkt); }, size()); + + panic_if(!image.write(proxy), "%s: Unable to write image."); +} + void AbstractMemory::setBackingStore(uint8_t* pmem_addr) { diff --git a/src/mem/abstract_mem.hh b/src/mem/abstract_mem.hh index b1d54fdebe..616fd0e265 100644 --- a/src/mem/abstract_mem.hh +++ b/src/mem/abstract_mem.hh @@ -209,6 +209,8 @@ class AbstractMemory : public ClockedObject AbstractMemory(const Params* p); virtual ~AbstractMemory() {} + void initState() override; + /** * See if this is a null memory that should never store data and * always return zero.