All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alistair Francis <alistair.francis@xilinx.com>
To: qemu-devel@nongnu.org, peter.maydell@linaro.org
Cc: alistair.francis@xilinx.com, crosthwaitepeter@gmail.com,
	armbru@redhat.com, cov@codeaurora.org, pbonzini@redhat.com
Subject: [Qemu-devel] [PATCH v10 7/8] generic-loader: Add a generic loader
Date: Wed, 3 Aug 2016 13:06:50 -0700	[thread overview]
Message-ID: <4d6e70dc122fafbe81d85beb257ce3e0d6479fb1.1470253246.git.alistair.francis@xilinx.com> (raw)
In-Reply-To: <cover.1470253246.git.alistair.francis@xilinx.com>

Add a generic loader to QEMU which can be used to load images or set
memory values.

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
---
V10:
 - Split out the PC setting and data loading
V9:
 - Fix error messages
 - Updated some incorrect logic
 - Add address space loading support for all image types
 - Explain why the reset is manually registered
V8:
 - Code corrections
 - Rebase
V7:
 - Rebase
V6:
 - Add error checking
V5:
 - Rebase
V4:
 - Allow the loader to work with every architecture
 - Move the file to hw/core
 - Increase the maximum number of CPUs
 - Make the CPU operations conditional
 - Convert the cpu option to cpu-num
 - Require the user to specify endianess
V3:
 - Pass the ram_size to load_image_targphys()
V2:
 - Add maintainers entry
 - Perform bounds checking
 - Register and unregister the reset in the realise/unrealise
Changes since RFC:
 - Add BE support

 MAINTAINERS                      |   6 ++
 hw/core/Makefile.objs            |   2 +
 hw/core/generic-loader.c         | 195 +++++++++++++++++++++++++++++++++++++++
 include/hw/core/generic-loader.h |  46 +++++++++
 4 files changed, 249 insertions(+)
 create mode 100644 hw/core/generic-loader.c
 create mode 100644 include/hw/core/generic-loader.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9c88c44..cc34ae0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -984,6 +984,12 @@ M: Dmitry Fleytman <dmitry@daynix.com>
 S: Maintained
 F: hw/net/e1000e*
 
+Generic Loader
+M: Alistair Francis <alistair.francis@xilinx.com>
+S: Maintained
+F: hw/core/generic-loader.c
+F: include/hw/core/generic-loader.h
+
 Subsystems
 ----------
 Audio
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index cfd4840..939c94e 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -17,3 +17,5 @@ common-obj-$(CONFIG_SOFTMMU) += loader.o
 common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
 common-obj-$(CONFIG_SOFTMMU) += register.o
 common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
+
+obj-$(CONFIG_SOFTMMU) += generic-loader.o
diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
new file mode 100644
index 0000000..4ee71cb
--- /dev/null
+++ b/hw/core/generic-loader.c
@@ -0,0 +1,195 @@
+/*
+ * Generic Loader
+ *
+ * Copyright (C) 2014 Li Guang
+ * Copyright (C) 2016 Xilinx Inc.
+ * Written by Li Guang <lig.fnst@cn.fujitsu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "qom/cpu.h"
+#include "hw/sysbus.h"
+#include "sysemu/dma.h"
+#include "hw/loader.h"
+#include "qapi/error.h"
+#include "hw/core/generic-loader.h"
+
+#define CPU_NONE 0xFFFFFFFF
+
+static void generic_loader_reset(void *opaque)
+{
+    GenericLoaderState *s = GENERIC_LOADER(opaque);
+
+    if (s->set_pc && s->cpu) {
+        CPUClass *cc = CPU_GET_CLASS(s->cpu);
+        cpu_reset(s->cpu);
+        if (cc) {
+            cc->set_pc(s->cpu, s->addr);
+        }
+    }
+
+    if (s->data_len) {
+        assert(s->data_len < sizeof(s->data));
+        dma_memory_write((s->cpu ? s->cpu : first_cpu)->as, s->addr, &s->data,
+                         s->data_len);
+    }
+}
+
+static void generic_loader_realize(DeviceState *dev, Error **errp)
+{
+    GenericLoaderState *s = GENERIC_LOADER(dev);
+    hwaddr entry;
+    int big_endian;
+    int size = 0;
+
+    s->set_pc = false;
+
+    /* Perform some error checking on the user's options */
+    if (s->data || s->data_len  || s->data_be) {
+        /* User is loading memory values */
+        if (s->file) {
+            error_setg(errp, "Specifying a file is not supported when loading "
+                       "memory values");
+            return;
+        } else if (s->force_raw) {
+            error_setg(errp, "Specifying force-raw is not supported when "
+                       "loading memory values");
+            return;
+        } else if (!s->data || !s->data_len) {
+            error_setg(errp, "Both data and data-len must be specified");
+            return;
+        } else if (s->data_len > 8) {
+            error_setg(errp, "data-len cannot be greater then 8 bytes");
+            return;
+        } else if (s->data_len > sizeof(s->data)) {
+            error_setg(errp, "data-len cannot be more then the data size");
+            return;
+        }
+    } else if (s->file || s->force_raw)  {
+        /* User is loading an image */
+        if (s->data || s->data_len || s->data_be) {
+            error_setg(errp, "data can not be specified when loading an "
+                       "image");
+            return;
+        }
+        s->set_pc = true;
+    } else if (s->addr) {
+        /* User is setting the PC */
+        if (s->data || s->data_len || s->data_be) {
+            error_setg(errp, "data can not be specified when setting a "
+                       "program counter");
+            return;
+        }
+        s->set_pc = true;
+    } else {
+        /* Did the user specify anything? */
+        error_setg(errp, "please include valid arguments");
+        return;
+    }
+
+    qemu_register_reset(generic_loader_reset, dev);
+
+    if (s->cpu_num != CPU_NONE) {
+        s->cpu = qemu_get_cpu(s->cpu_num);
+        if (!s->cpu) {
+            error_setg(errp, "Specified boot CPU#%d is nonexistent",
+                       s->cpu_num);
+            return;
+        }
+    }
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    big_endian = 1;
+#else
+    big_endian = 0;
+#endif
+
+    if (s->file) {
+        if (!s->force_raw) {
+            size = load_elf_as(s->file, NULL, NULL, &entry, NULL, NULL,
+                               big_endian, 0, 0, 0,
+                               (s->cpu ? s->cpu : first_cpu)->as);
+
+            if (size < 0) {
+                size = load_uimage_as(s->file, &entry, NULL, NULL, NULL, NULL,
+                                      (s->cpu ? s->cpu : first_cpu)->as);
+            }
+        }
+
+        if (size < 0 || s->force_raw) {
+            /* Default to the maximum size being the machine's ram size */
+            size = load_image_targphys_as(s->file, s->addr, ram_size,
+                                          (s->cpu ? s->cpu : first_cpu)->as);
+        } else {
+            s->addr = entry;
+        }
+
+        if (size < 0) {
+            error_setg(errp, "Cannot load specified image %s", s->file);
+            return;
+        }
+    }
+
+    /* Convert the data endiannes */
+    if (s->data_be) {
+        s->data = cpu_to_be64(s->data);
+    } else {
+        s->data = cpu_to_le64(s->data);
+    }
+}
+
+static void generic_loader_unrealize(DeviceState *dev, Error **errp)
+{
+    qemu_unregister_reset(generic_loader_reset, dev);
+}
+
+static Property generic_loader_props[] = {
+    DEFINE_PROP_UINT64("addr", GenericLoaderState, addr, 0),
+    DEFINE_PROP_UINT64("data", GenericLoaderState, data, 0),
+    DEFINE_PROP_UINT8("data-len", GenericLoaderState, data_len, 0),
+    DEFINE_PROP_BOOL("data-be", GenericLoaderState, data_be, false),
+    DEFINE_PROP_UINT32("cpu-num", GenericLoaderState, cpu_num, CPU_NONE),
+    DEFINE_PROP_BOOL("force-raw", GenericLoaderState, force_raw, false),
+    DEFINE_PROP_STRING("file", GenericLoaderState, file),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void generic_loader_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    /* The reset function is not registered here and is instead registered in
+     * the realize function to allow this device to be added via the device_add
+     * command in the QEMU monitor.
+     * TODO: Improve the device_add functionality to allow resets to be
+     * connected
+     */
+    dc->realize = generic_loader_realize;
+    dc->unrealize = generic_loader_unrealize;
+    dc->props = generic_loader_props;
+    dc->desc = "Generic Loader";
+}
+
+static TypeInfo generic_loader_info = {
+    .name = TYPE_GENERIC_LOADER,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(GenericLoaderState),
+    .class_init = generic_loader_class_init,
+};
+
+static void generic_loader_register_type(void)
+{
+    type_register_static(&generic_loader_info);
+}
+
+type_init(generic_loader_register_type)
diff --git a/include/hw/core/generic-loader.h b/include/hw/core/generic-loader.h
new file mode 100644
index 0000000..dd27c42
--- /dev/null
+++ b/include/hw/core/generic-loader.h
@@ -0,0 +1,46 @@
+/*
+ * Generic Loader
+ *
+ * Copyright (C) 2014 Li Guang
+ * Written by Li Guang <lig.fnst@cn.fujitsu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef GENERIC_LOADER_H
+#define GENERIC_LOADER_H
+
+#include "elf.h"
+
+typedef struct GenericLoaderState {
+    /* <private> */
+    DeviceState parent_obj;
+
+    /* <public> */
+    CPUState *cpu;
+
+    uint64_t addr;
+    uint64_t data;
+    uint8_t data_len;
+    uint32_t cpu_num;
+
+    char *file;
+
+    bool force_raw;
+    bool data_be;
+    bool set_pc;
+} GenericLoaderState;
+
+#define TYPE_GENERIC_LOADER "loader"
+#define GENERIC_LOADER(obj) OBJECT_CHECK(GenericLoaderState, (obj), \
+                                         TYPE_GENERIC_LOADER)
+
+#endif
-- 
2.7.4

  parent reply	other threads:[~2016-08-03 20:07 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-03 20:06 [Qemu-devel] [PATCH v10 0/8] Add a generic loader Alistair Francis
2016-08-03 20:06 ` [Qemu-devel] [PATCH v10 1/8] loader: Allow ELF loader to auto-detect the ELF arch Alistair Francis
2016-08-09 17:35   ` Peter Maydell
2016-08-03 20:06 ` [Qemu-devel] [PATCH v10 2/8] loader: Use the specified MemoryRegion Alistair Francis
2016-08-03 20:06 ` [Qemu-devel] [PATCH v10 3/8] loader: Allow a custom AddressSpace when loading ROMs Alistair Francis
2016-08-09 18:44   ` Peter Maydell
2016-08-09 23:26     ` Alistair Francis
2016-08-03 20:06 ` [Qemu-devel] [PATCH v10 4/8] loader: Add AddressSpace loading support to ELFs Alistair Francis
2016-08-03 20:06 ` [Qemu-devel] [PATCH v10 5/8] loader: Add AddressSpace loading support to uImages Alistair Francis
2016-08-09 17:45   ` Peter Maydell
2016-08-03 20:06 ` [Qemu-devel] [PATCH v10 6/8] loader: Add AddressSpace loading support to targphys Alistair Francis
2016-08-09 17:53   ` Peter Maydell
2016-08-03 20:06 ` Alistair Francis [this message]
2016-08-09 18:17   ` [Qemu-devel] [PATCH v10 7/8] generic-loader: Add a generic loader Peter Maydell
2016-08-09 23:04     ` Alistair Francis
2016-08-03 20:06 ` [Qemu-devel] [PATCH v10 8/8] docs: Add a generic loader explanation document Alistair Francis
2016-08-09 18:19   ` Peter Maydell
2016-08-09 23:10     ` Alistair Francis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4d6e70dc122fafbe81d85beb257ce3e0d6479fb1.1470253246.git.alistair.francis@xilinx.com \
    --to=alistair.francis@xilinx.com \
    --cc=armbru@redhat.com \
    --cc=cov@codeaurora.org \
    --cc=crosthwaitepeter@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.