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

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



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.

Signed-off-by: Oleksandr Tyshchenko <oleksandr.tyshchenko@xxxxxxxxxxxxxxx>
---
 tools/libxc/Makefile              |   1 +
 tools/libxc/xc_dom.h              |   3 +
 tools/libxc/xc_dom_qnxifsloader.c | 199 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 203 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.h b/tools/libxc/xc_dom.h
index 92db8d0..bf9ea3c 100644
--- a/tools/libxc/xc_dom.h
+++ b/tools/libxc/xc_dom.h
@@ -151,6 +151,9 @@ struct xc_dom_image {
     struct xc_dom_arch *arch_hooks;
     /* allocate up to virt_alloc_end */
     int (*allocate) (struct xc_dom_image * dom, xen_vaddr_t up_to);
+
+    /* qnx loader */
+    uint32_t startup_vaddr;
 };
 
 /* --- pluggable kernel loader ------------------------------------- */
diff --git a/tools/libxc/xc_dom_qnxifsloader.c 
b/tools/libxc/xc_dom_qnxifsloader.c
new file mode 100644
index 0000000..3137897
--- /dev/null
+++ b/tools/libxc/xc_dom_qnxifsloader.c
@@ -0,0 +1,199 @@
+/*
+ * 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 addr, uint32_t size)
+{
+    int sum = 0;
+    uint32_t *ptr = (uint32_t *)addr;
+
+    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;
+    uint32_t start_addr, end_addr;
+
+    if ( dom->kernel_blob == NULL )
+    {
+        xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
+                     "%s: no QNX IFS loaded", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    /* Scan 4KB boundaries for the valid OS signature */
+    start_addr = *(uint32_t *)&dom->kernel_blob;
+    end_addr = start_addr + 0x1000;
+    while ( start_addr < end_addr )
+    {
+        startup_hdr = (struct startup_header *)(uintptr_t)start_addr;
+        if ( startup_hdr->signature == STARTUP_HDR_SIGNATURE )
+            break;
+        start_addr += 4;
+       }
+
+    if ( start_addr >= end_addr )
+    {
+        xc_dom_printf(dom->xch, "%s: image is not a QNX IFS", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    /* Performs a checksums on the startup and the OS image filesystem */
+    if ( (calc_checksum(start_addr, startup_hdr->startup_size) != 0) ||
+         (calc_checksum(start_addr + startup_hdr->startup_size,
+          startup_hdr->stored_size - startup_hdr->startup_size) != 0) )
+    {
+        xc_dom_printf(dom->xch, "%s: QNX IFS has wrong checksum", 
__FUNCTION__);
+        return -EINVAL;
+    }
+
+    if ( (startup_hdr->stored_size + startup_hdr->preboot_size) != 
dom->kernel_size )
+    {
+        xc_dom_printf(dom->xch, "%s: QNX IFS has wrong size", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    dom->startup_vaddr = startup_hdr->startup_vaddr;
+
+    return 0;
+}
+
+static int xc_dom_parse_qnx_ifs(struct xc_dom_image *dom)
+{
+    uint64_t v_start, v_end;
+    uint64_t rambase = GUEST_RAM_BASE;
+
+    DOMPRINTF_CALLED(dom->xch);
+
+    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;
+
+    /* find kernel segment */
+    dom->kernel_seg.vstart = v_start;
+    dom->kernel_seg.vend   = v_end;
+
+    dom->parms.virt_entry = dom->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®.