[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v4] xen/tools: Introduce QNX IFS loader



This patch was developed according to instruction:
http://www.qnx.com/developers/docs/6.4.1/neutrino/building/load_process.html

Add ability to load QNX IFS image. The loader probe function
based on "Writing an IPL Program" howto from qnx.com
and performs image validation and startup entry point location.
Because of the fact that the image is already in place some
customizations have been done. Also in case of multiple images
(very seldom case) only the first image will be loaded.

There are some restrictions:
1. The base address of the image (image attribute) and the location
   of RAM in system must be synchronized with RAM base address in Xen.
2. The QNX IFS image must be created as a simple binary image.

Signed-off-by: Oleksandr Tyshchenko <oleksandr.tyshchenko@xxxxxxxxxxxxxxx>
Cc: Ian Campbell <ian.campbell@xxxxxxxxxx>
Cc: Julien Grall <julien.grall@xxxxxxxxxx>
---
 tools/libxc/Makefile              |   1 +
 tools/libxc/xc_dom_qnxifsloader.c | 228 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 229 insertions(+)
 create mode 100644 tools/libxc/xc_dom_qnxifsloader.c

diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 2cca2b2..1462f53 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -66,6 +66,7 @@ GUEST_SRCS-y                 += xc_dom_elfloader.c
 GUEST_SRCS-$(CONFIG_X86)     += xc_dom_bzimageloader.c
 GUEST_SRCS-$(CONFIG_X86)     += xc_dom_decompress_lz4.c
 GUEST_SRCS-$(CONFIG_ARM)     += xc_dom_armzimageloader.c
+GUEST_SRCS-$(CONFIG_ARM)     += xc_dom_qnxifsloader.c
 GUEST_SRCS-y                 += xc_dom_binloader.c
 GUEST_SRCS-y                 += xc_dom_compat_linux.c
 
diff --git a/tools/libxc/xc_dom_qnxifsloader.c 
b/tools/libxc/xc_dom_qnxifsloader.c
new file mode 100644
index 0000000..8b03885
--- /dev/null
+++ b/tools/libxc/xc_dom_qnxifsloader.c
@@ -0,0 +1,228 @@
+/*
+ * Xen domain builder -- QNX IFS bits
+ *
+ * Parse and load QNX IFS image.
+ *
+ * Copyright (C) 2014, Globallogic.
+ *
+ * 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"
+
+struct startup_header {
+    uint32_t signature;        /* Header sig */
+    uint16_t version;          /* Header vers */
+    uint8_t flags1;            /* Misc flags */
+    uint8_t flags2;            /* No flags defined yet */
+    uint16_t header_size;      /* sizeof(struct startup_header) */
+    uint16_t machine;          /* Machine type */
+    uint32_t startup_vaddr;    /* Virtual Address to transfer */
+                               /* to after IPL is done */
+    uint32_t paddr_bias;       /* Value to add to physical address */
+                               /* to get a value to put into a */
+                               /* pointer and indirected through */
+    uint32_t image_paddr;      /* Physical address of image */
+    uint32_t ram_paddr;        /* Physical address of RAM to copy */
+                               /* image to (startup_size bytes copied) */
+    uint32_t ram_size;         /* Amount of RAM used by the startup */
+                               /* program and executables contained */
+                               /* in the file system */
+    uint32_t startup_size;     /* Size of startup (never compressed) */
+    uint32_t stored_size;      /* Size of entire image */
+    uint32_t imagefs_paddr;    /* Set by IPL to where the imagefs is */
+                               /* when startup runs */
+    uint32_t imagefs_size;     /* Size of uncompressed imagefs */
+    uint16_t preboot_size;     /* Size of loaded before header */
+    uint16_t zero0;            /* Zeros */
+    uint32_t zero[3];          /* Zeros */
+    uint32_t info[48];         /* Array of startup_info* structures */
+};
+
+#define STARTUP_HDR_SIGNATURE    0x00ff7eeb
+
+static int calc_checksum(uint32_t *ptr, uint32_t size)
+{
+    int sum = 0;
+
+    while ( size > 0 )
+    {
+        sum += *ptr++;
+        size -= 4;
+    }
+
+    return sum;
+}
+
+static int xc_dom_probe_qnx_ifs(struct xc_dom_image *dom)
+{
+    struct startup_header *startup_hdr;
+
+    if ( dom->kernel_blob == NULL )
+    {
+        xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
+                     "%s: no QNX IFS loaded", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    /* Performs a preliminary checks for a valid image size */
+    if ( dom->kernel_size < sizeof(struct startup_header) )
+    {
+        xc_dom_printf(dom->xch, "%s: QNX IFS is too small", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    /*
+     * Performs a check for a valid OS signature. We assume that nothing
+     * preceded by startup header because we expect a simple binary image.
+     */
+    startup_hdr = (struct startup_header *)dom->kernel_blob;
+    if ( (startup_hdr->signature != STARTUP_HDR_SIGNATURE) ||
+         (startup_hdr->preboot_size != 0) )
+    {
+        xc_dom_printf(dom->xch, "%s: image is not a QNX IFS", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    /* Performs a check for a valid startup header size */
+    if ( startup_hdr->header_size != sizeof(struct startup_header) )
+    {
+        xc_dom_printf(dom->xch, "%s: QNX IFS has wrong startup header size", 
__FUNCTION__);
+        return -EINVAL;
+    }
+
+    /* Performs a check for a valid stored size */
+    if ( startup_hdr->stored_size != dom->kernel_size )
+    {
+        xc_dom_printf(dom->xch, "%s: QNX IFS has wrong stored size", 
__FUNCTION__);
+        return -EINVAL;
+    }
+
+    /* Performs a check for a valid startup size */
+    if ( startup_hdr->startup_size >= startup_hdr->stored_size )
+    {
+        xc_dom_printf(dom->xch, "%s: QNX IFS has wrong startup size", 
__FUNCTION__);
+        return -EINVAL;
+    }
+
+    /* Performs a checksums on the startup and the OS image filesystem */
+    if ( (calc_checksum((uint32_t *)startup_hdr, startup_hdr->startup_size) != 
0) ||
+         (calc_checksum((uint32_t *)startup_hdr + startup_hdr->startup_size/4,
+          startup_hdr->stored_size - startup_hdr->startup_size) != 0) )
+    {
+        xc_dom_printf(dom->xch, "%s: QNX IFS has wrong checksum", 
__FUNCTION__);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+static int xc_dom_parse_qnx_ifs(struct xc_dom_image *dom)
+{
+    struct startup_header *startup_hdr;
+    uint64_t v_start, v_end;
+    uint64_t rambase = dom->rambase_pfn << XC_PAGE_SHIFT;
+
+    DOMPRINTF_CALLED(dom->xch);
+
+    /* Do not load kernel at the very first RAM address */
+    v_start = rambase + 0x8000;
+
+    if ( dom->kernel_size > UINT64_MAX - v_start )
+    {
+        xc_dom_printf(dom->xch, "%s: QNX IFS is too big", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    v_end = v_start + dom->kernel_size;
+
+    /* find kernel segment */
+    dom->kernel_seg.vstart = v_start;
+    dom->kernel_seg.vend   = v_end;
+
+    startup_hdr = (struct startup_header *)dom->kernel_blob;
+
+    /* Performs a sanity check for a valid startup entry point */
+    if ( (startup_hdr->startup_vaddr < v_start) ||
+         (startup_hdr->startup_vaddr > v_end) )
+    {
+        xc_dom_printf(dom->xch, "%s: QNX IFS has wrong startup entry point", 
__FUNCTION__);
+        return -EINVAL;
+    }
+
+    dom->parms.virt_entry = startup_hdr->startup_vaddr;
+    dom->parms.virt_base = rambase;
+
+    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_qnx_ifs(struct xc_dom_image *dom)
+{
+    void *dst;
+
+    DOMPRINTF_CALLED(dom->xch);
+
+    dst = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
+    if ( dst == NULL )
+    {
+        DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->kernel_seg) => NULL",
+                  __func__);
+        return -1;
+    }
+
+    DOMPRINTF("%s: kernel seg %#"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 qnx_ifs_loader = {
+    .name = "QNX IFS",
+    .probe = xc_dom_probe_qnx_ifs,
+    .parser = xc_dom_parse_qnx_ifs,
+    .loader = xc_dom_load_qnx_ifs,
+};
+
+static void __init register_loader(void)
+{
+    xc_dom_register_loader(&qnx_ifs_loader);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.9.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.