-# Copyright (c) 2009, 2012-2013 ARM Limited
+# Copyright (c) 2009, 2012-2013, 2015 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
     cxx_header = "arch/arm/system.hh"
     load_addr_mask = 0xffffffff
     multi_proc = Param.Bool(True, "Multiprocessor system?")
-    boot_loader = Param.String("", "File that contains the boot loader code if any")
+    boot_loader = VectorParam.String([],
+        "File that contains the boot loader code. Zero or more files may be "
+        "specified. The first boot loader that matches the kernel's "
+        "architecture will be used.")
     gic_cpu_addr = Param.Addr(0, "Addres of the GIC CPU interface")
     flags_addr = Param.Addr(0, "Address of the flags register for MP booting")
     have_security = Param.Bool(False,
 
 /*
- * Copyright (c) 2010, 2012-2013 ARM Limited
+ * Copyright (c) 2010, 2012-2013, 2015 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
 using namespace Linux;
 
 ArmSystem::ArmSystem(Params *p)
-    : System(p), bootldr(NULL), _haveSecurity(p->have_security),
+    : System(p),
+      bootLoaders(), bootldr(nullptr),
+      _haveSecurity(p->have_security),
       _haveLPAE(p->have_lpae),
       _haveVirtualization(p->have_virtualization),
       _genericTimer(nullptr),
         fatal("Invalid physical address range (%d)\n", _physAddrRange64);
     }
 
-    if (p->boot_loader != "") {
-        bootldr = createObjectFile(p->boot_loader);
+    bootLoaders.reserve(p->boot_loader.size());
+    for (const auto &bl : p->boot_loader) {
+        std::unique_ptr<ObjectFile> obj;
+        obj.reset(createObjectFile(bl));
 
-        if (!bootldr)
-            fatal("Could not read bootloader: %s\n", p->boot_loader);
+        fatal_if(!obj, "Could not read bootloader: %s\n", bl);
+        bootLoaders.emplace_back(std::move(obj));
+    }
+
+    if (kernel) {
+        bootldr = getBootLoader(kernel);
+    } else if (!bootLoaders.empty()) {
+        // No kernel specified, default to the first boot loader
+        bootldr = bootLoaders[0].get();
+    }
+
+    if (!bootLoaders.empty() && !bootldr)
+        fatal("Can't find a matching boot loader / kernel combination!");
 
+    if (bootldr) {
+        bootldr->loadGlobalSymbols(debugSymbolTable);
         if ((bootldr->getArch() == ObjectFile::Arm64) && !_highestELIs64) {
             warn("Highest ARM exception-level set to AArch32 but bootloader "
                   "is for AArch64. Assuming you wanted these to match.\n");
                   "is for AArch32. Assuming you wanted these to match.\n");
             _highestELIs64 = false;
         }
-
-        bootldr->loadGlobalSymbols(debugSymbolTable);
-
     }
+
     debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
 }
 
         delete debugPrintkEvent;
 }
 
+ObjectFile *
+ArmSystem::getBootLoader(ObjectFile *const obj)
+{
+    for (auto &bl : bootLoaders) {
+        if (bl->getArch() == obj->getArch())
+            return bl.get();
+    }
+
+    return nullptr;
+}
+
 bool
 ArmSystem::haveLPAE(ThreadContext *tc)
 {
 
 /*
- * Copyright (c) 2010, 2012-2013 ARM Limited
+ * Copyright (c) 2010, 2012-2013, 2015 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
 #ifndef __ARCH_ARM_SYSTEM_HH__
 #define __ARCH_ARM_SYSTEM_HH__
 
+#include <memory>
 #include <string>
 #include <vector>
 
      */
     Linux::DebugPrintkEvent *debugPrintkEvent;
 
+    /** Bootloaders */
+    std::vector<std::unique_ptr<ObjectFile>> bootLoaders;
+
     /**
      * Pointer to the bootloader object
      */
      */
     const bool _haveLargeAsid64;
 
+  protected:
+    /**
+     * Get a boot loader that matches the kernel.
+     *
+     * @param obj Kernel binary
+     * @return Pointer to boot loader ObjectFile or nullptr if there
+     *         is no matching boot loader.
+     */
+    ObjectFile *getBootLoader(ObjectFile *const obj);
+
   public:
     typedef ArmSystemParams Params;
     const Params *