aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_dom_armzimageloader.c
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@citrix.com>2012-10-09 15:05:30 +0100
committerIan Campbell <ian.campbell@citrix.com>2012-10-09 15:05:30 +0100
commit417597de7559f7ea68133878c7d1b893cf7404b6 (patch)
treee92bd879be1d8faa3f0aaf2260d0f5971412c3b3 /tools/libxc/xc_dom_armzimageloader.c
parent9595ef77ab11f44144705e8f6fb20b8759144d70 (diff)
downloadxen-417597de7559f7ea68133878c7d1b893cf7404b6.tar.gz
xen-417597de7559f7ea68133878c7d1b893cf7404b6.tar.bz2
xen-417597de7559f7ea68133878c7d1b893cf7404b6.zip
libxc: add ARM support to xc_dom (PV domain building)
Includes ARM zImage support. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <Stefano.Stabellini@eu.citrix.com> Committed-by: Ian Campbell <ian.campbell@citrix.com>
Diffstat (limited to 'tools/libxc/xc_dom_armzimageloader.c')
-rw-r--r--tools/libxc/xc_dom_armzimageloader.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/tools/libxc/xc_dom_armzimageloader.c b/tools/libxc/xc_dom_armzimageloader.c
new file mode 100644
index 0000000000..f316e87c46
--- /dev/null
+++ b/tools/libxc/xc_dom_armzimageloader.c
@@ -0,0 +1,174 @@
+/*
+ * Xen domain builder -- ARM zImage bits
+ *
+ * Parse and load ARM zImage kernel images.
+ *
+ * Copyright (C) 2012, Citrix Systems.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "xg_private.h"
+#include "xc_dom.h"
+
+#include <arpa/inet.h> /* XXX ntohl is not the right function... */
+
+/*
+ * Guest virtual RAM starts here. This must be consistent with the DTB
+ * appended to the guest kernel.
+ */
+#define GUEST_RAM_BASE 0x80000000
+
+#define ZIMAGE_MAGIC_OFFSET 0x24
+#define ZIMAGE_START_OFFSET 0x28
+#define ZIMAGE_END_OFFSET 0x2c
+
+#define ZIMAGE_MAGIC 0x016f2818
+
+struct minimal_dtb_header {
+ uint32_t magic;
+ uint32_t total_size;
+ /* There are other fields but we don't use them yet. */
+};
+
+#define DTB_MAGIC 0xd00dfeed
+
+static int xc_dom_probe_zimage_kernel(struct xc_dom_image *dom)
+{
+ uint32_t *zimage;
+ uint32_t end;
+
+ if ( dom->kernel_blob == NULL )
+ {
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
+ "%s: no kernel image loaded", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ if ( dom->kernel_size < 0x30 /*sizeof(struct setup_header)*/ )
+ {
+ xc_dom_printf(dom->xch, "%s: kernel image too small", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ zimage = (uint32_t *)dom->kernel_blob;
+ if ( zimage[ZIMAGE_MAGIC_OFFSET/4] != ZIMAGE_MAGIC )
+ {
+ xc_dom_printf(dom->xch, "%s: kernel is not a bzImage", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ end = zimage[ZIMAGE_END_OFFSET/4];
+
+ /*
+ * Check for an appended DTB.
+ */
+ if ( end + sizeof(struct minimal_dtb_header) < dom->kernel_size ) {
+ struct minimal_dtb_header *dtb_hdr;
+ dtb_hdr = (struct minimal_dtb_header *)(dom->kernel_blob + end);
+ if (ntohl/*be32_to_cpu*/(dtb_hdr->magic) == DTB_MAGIC) {
+ xc_dom_printf(dom->xch, "%s: found an appended DTB", __FUNCTION__);
+ end += ntohl/*be32_to_cpu*/(dtb_hdr->total_size);
+ }
+ }
+
+ dom->kernel_size = end;
+
+ return 0;
+}
+
+static int xc_dom_parse_zimage_kernel(struct xc_dom_image *dom)
+{
+ uint32_t *zimage;
+ uint32_t start, entry_addr;
+ uint64_t v_start, v_end;
+ uint64_t rambase = GUEST_RAM_BASE;
+
+ DOMPRINTF_CALLED(dom->xch);
+
+ zimage = (uint32_t *)dom->kernel_blob;
+
+ dom->rambase_pfn = rambase >> XC_PAGE_SHIFT;
+
+ /* Do not load kernel at the very first RAM address */
+ v_start = rambase + 0x8000;
+ v_end = v_start + dom->kernel_size;
+
+ start = zimage[ZIMAGE_START_OFFSET/4];
+
+ if (start == 0)
+ entry_addr = v_start;
+ else
+ entry_addr = start;
+
+ /* find kernel segment */
+ dom->kernel_seg.vstart = v_start;
+ dom->kernel_seg.vend = v_end;
+
+ dom->parms.virt_entry = entry_addr;
+
+ dom->guest_type = "xen-3.0-armv7l";
+ DOMPRINTF("%s: %s: RAM starts at %"PRI_xen_pfn,
+ __FUNCTION__, dom->guest_type, dom->rambase_pfn);
+ DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
+ __FUNCTION__, dom->guest_type,
+ dom->kernel_seg.vstart, dom->kernel_seg.vend);
+ return 0;
+}
+
+static int xc_dom_load_zimage_kernel(struct xc_dom_image *dom)
+{
+ void *dst;
+
+ DOMPRINTF_CALLED(dom->xch);
+
+ dst = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
+
+ DOMPRINTF("%s: kernel sed %#"PRIx64"-%#"PRIx64,
+ __func__, dom->kernel_seg.vstart, dom->kernel_seg.vend);
+ DOMPRINTF("%s: copy %zd bytes from blob %p to dst %p",
+ __func__, dom->kernel_size, dom->kernel_blob, dst);
+
+ memcpy(dst, dom->kernel_blob, dom->kernel_size);
+
+ return 0;
+}
+
+static struct xc_dom_loader zimage_loader = {
+ .name = "Linux zImage (ARM)",
+ .probe = xc_dom_probe_zimage_kernel,
+ .parser = xc_dom_parse_zimage_kernel,
+ .loader = xc_dom_load_zimage_kernel,
+};
+
+static void __init register_loader(void)
+{
+ xc_dom_register_loader(&zimage_loader);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */