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

[Xen-devel] [PATCH] loader for ReactOS (2nd try)


  • To: xen-devel@xxxxxxxxxxxxxxxxxxx
  • From: Ge van Geldorp <gvg@xxxxxxxxxxx>
  • Date: Fri, 3 Jun 2005 19:55:38 +0200
  • Delivery-date: Fri, 03 Jun 2005 17:55:09 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>

Suggestions by Christian Limpach taken into account in the patch below.

Ge van Geldorp.

Signed-Off-By: Ge van Geldorp <gvg@xxxxxxxxxxx>

--- orig/tools/libxc/xc_private.h       2005-05-24 23:17:28 +02:00
+++ new/tools/libxc/xc_private.h        2005-06-03 18:52:42 +02:00
@@ -48,6 +48,31 @@
 #define l2_table_offset(_a) \
           ((_a) >> L2_PAGETABLE_SHIFT)
 
+struct xc_domain_setup_info
+{
+    unsigned long v_start;
+    unsigned long v_end;
+    unsigned long v_kernstart;
+    unsigned long v_kernend;
+    unsigned long v_kernentry;
+
+    unsigned int  load_symtab;
+    unsigned long symtab_addr;
+    unsigned long symtab_len;
+};
+
+typedef int (*parseimagefunc)(
+    char *image, unsigned long image_size, struct xc_domain_setup_info *dsi);
+typedef int (*loadimagefunc)(
+    char *image, unsigned long image_size, int xch, u32 dom,
+    unsigned long *parray, struct xc_domain_setup_info *dsi);
+
+struct xc_load_funcs
+{
+   parseimagefunc parseimage;
+   loadimagefunc loadimage;
+};
+
 #define ERROR(_m, _a...)  \
     fprintf(stderr, "ERROR: " _m "\n" , ## _a )
 
@@ -249,5 +274,11 @@
 
 int pin_table(
     int xc_handle, unsigned int type, unsigned long mfn, domid_t dom);
+
+/* image loading */
+int xc_elf_probe(
+    char *image, unsigned long image_size, struct xc_load_funcs *funcs);
+int xc_bin_probe(
+    char *image, unsigned long image_size, struct xc_load_funcs *funcs);
 
 #endif /* __XC_PRIVATE_H__ */
--- orig/tools/libxc/xc_linux_build.c   2005-05-16 12:50:00 +02:00
+++ new/tools/libxc/xc_linux_build.c    2005-06-03 18:35:29 +02:00
@@ -3,8 +3,6 @@
  */
 
 #include "xc_private.h"
-#define ELFSIZE 32
-#include "xc_elf.h"
 #include <stdlib.h>
 #include <zlib.h>
 
@@ -14,30 +12,19 @@
 #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
 #define round_pgdown(_p)  ((_p)&PAGE_MASK)
 
-struct domain_setup_info
+static int probeimageformat(char *image,
+                            unsigned long image_size,
+                            struct xc_load_funcs *load_funcs)
 {
-    unsigned long v_start;
-    unsigned long v_end;
-    unsigned long v_kernstart;
-    unsigned long v_kernend;
-    unsigned long v_kernentry;
-
-    unsigned int  load_symtab;
-    unsigned long symtab_addr;
-    unsigned long symtab_len;
-};
-
-static int
-parseelfimage(
-    char *elfbase, unsigned long elfsize, struct domain_setup_info *dsi);
-static int
-loadelfimage(
-    char *elfbase, int xch, u32 dom, unsigned long *parray,
-    struct domain_setup_info *dsi);
-static int
-loadelfsymtab(
-    char *elfbase, int xch, u32 dom, unsigned long *parray,
-    struct domain_setup_info *dsi);
+    if ( 0 != xc_elf_probe(image, image_size, load_funcs) &&
+         0 != xc_bin_probe(image, image_size, load_funcs) )
+    {
+        ERROR( "Unrecognized image format" );
+        return -EINVAL;
+    }
+
+    return 0;
+}
 
 static int setup_guest(int xc_handle,
                          u32 dom,
@@ -52,6 +39,7 @@
                          unsigned long flags,
                          unsigned int vcpus)
 {
+    struct xc_load_funcs load_funcs;
     l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
     l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
     unsigned long *page_array = NULL;
@@ -67,7 +55,7 @@
     unsigned long ppt_alloc;
     unsigned long *physmap, *physmap_e, physmap_pfn;
 
-    struct domain_setup_info dsi;
+    struct xc_domain_setup_info dsi;
     unsigned long vinitrd_start;
     unsigned long vinitrd_end;
     unsigned long vphysmap_start;
@@ -80,9 +68,13 @@
     unsigned long vpt_end;
     unsigned long v_end;
 
-    memset(&dsi, 0, sizeof(struct domain_setup_info));
+    rc = probeimageformat(image, image_size, &load_funcs);
+    if ( rc != 0 )
+        goto error_out;
+
+    memset(&dsi, 0, sizeof(struct xc_domain_setup_info));
 
-    rc = parseelfimage(image, image_size, &dsi);
+    rc = (load_funcs.parseimage)(image, image_size, &dsi);
     if ( rc != 0 )
         goto error_out;
 
@@ -156,7 +148,7 @@
         goto error_out;
     }
 
-    loadelfimage(image, xc_handle, dom, page_array, &dsi);
+    (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array, 
&dsi);
 
     /* Load the initial ramdisk image. */
     if ( initrd_len != 0 )
@@ -471,267 +463,4 @@
         free(image);
 
     return -1;
-}
-
-static inline int is_loadable_phdr(Elf_Phdr *phdr)
-{
-    return ((phdr->p_type == PT_LOAD) &&
-            ((phdr->p_flags & (PF_W|PF_X)) != 0));
-}
-
-static int parseelfimage(char *elfbase, 
-                         unsigned long elfsize,
-                         struct domain_setup_info *dsi)
-{
-    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
-    Elf_Phdr *phdr;
-    Elf_Shdr *shdr;
-    unsigned long kernstart = ~0UL, kernend=0UL;
-    char *shstrtab, *guestinfo=NULL, *p;
-    int h;
-
-    if ( !IS_ELF(*ehdr) )
-    {
-        ERROR("Kernel image does not have an ELF header.");
-        return -EINVAL;
-    }
-
-    if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
-    {
-        ERROR("ELF program headers extend beyond end of image.");
-        return -EINVAL;
-    }
-
-    if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
-    {
-        ERROR("ELF section headers extend beyond end of image.");
-        return -EINVAL;
-    }
-
-    /* Find the section-header strings table. */
-    if ( ehdr->e_shstrndx == SHN_UNDEF )
-    {
-        ERROR("ELF image has no section-header strings table (shstrtab).");
-        return -EINVAL;
-    }
-    shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + 
-                        (ehdr->e_shstrndx*ehdr->e_shentsize));
-    shstrtab = elfbase + shdr->sh_offset;
-    
-    /* Find the special '__xen_guest' section and check its contents. */
-    for ( h = 0; h < ehdr->e_shnum; h++ )
-    {
-        shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + (h*ehdr->e_shentsize));
-        if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
-            continue;
-
-        guestinfo = elfbase + shdr->sh_offset;
-
-        if ( (strstr(guestinfo, "LOADER=generic") == NULL) &&
-             (strstr(guestinfo, "GUEST_OS=linux") == NULL) )
-        {
-            ERROR("Will only load images built for the generic loader "
-                  "or Linux images");
-            ERROR("Actually saw: '%s'", guestinfo);
-            return -EINVAL;
-        }
-
-        if ( (strstr(guestinfo, "XEN_VER=3.0") == NULL) )
-        {
-            ERROR("Will only load images built for Xen v3.0");
-            ERROR("Actually saw: '%s'", guestinfo);
-            return -EINVAL;
-        }
-
-        break;
-    }
-    if ( guestinfo == NULL )
-    {
-        ERROR("Not a Xen-ELF image: '__xen_guest' section not found.");
-        return -EINVAL;
-    }
-
-    for ( h = 0; h < ehdr->e_phnum; h++ ) 
-    {
-        phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
-        if ( !is_loadable_phdr(phdr) )
-            continue;
-        if ( phdr->p_paddr < kernstart )
-            kernstart = phdr->p_paddr;
-        if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
-            kernend = phdr->p_paddr + phdr->p_memsz;
-    }
-
-    if ( (kernstart > kernend) || 
-         (ehdr->e_entry < kernstart) || 
-         (ehdr->e_entry > kernend) )
-    {
-        ERROR("Malformed ELF image.");
-        return -EINVAL;
-    }
-
-    dsi->v_start = kernstart;
-    if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
-        dsi->v_start = strtoul(p+10, &p, 0);
-
-    if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
-        dsi->load_symtab = 1;
-
-    dsi->v_kernstart = kernstart;
-    dsi->v_kernend   = kernend;
-    dsi->v_kernentry = ehdr->e_entry;
-    dsi->v_end       = dsi->v_kernend;
-
-    loadelfsymtab(elfbase, 0, 0, NULL, dsi);
-
-    return 0;
-}
-
-static int
-loadelfimage(
-    char *elfbase, int xch, u32 dom, unsigned long *parray,
-    struct domain_setup_info *dsi)
-{
-    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
-    Elf_Phdr *phdr;
-    int h;
-
-    char         *va;
-    unsigned long pa, done, chunksz;
-
-    for ( h = 0; h < ehdr->e_phnum; h++ ) 
-    {
-        phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
-        if ( !is_loadable_phdr(phdr) )
-            continue;
-        
-        for ( done = 0; done < phdr->p_filesz; done += chunksz )
-        {
-            pa = (phdr->p_paddr + done) - dsi->v_start;
-            va = xc_map_foreign_range(
-                xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
-            chunksz = phdr->p_filesz - done;
-            if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
-                chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
-            memcpy(va + (pa & (PAGE_SIZE-1)),
-                   elfbase + phdr->p_offset + done, chunksz);
-            munmap(va, PAGE_SIZE);
-        }
-
-        for ( ; done < phdr->p_memsz; done += chunksz )
-        {
-            pa = (phdr->p_paddr + done) - dsi->v_start;
-            va = xc_map_foreign_range(
-                xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
-            chunksz = phdr->p_memsz - done;
-            if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
-                chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
-            memset(va + (pa & (PAGE_SIZE-1)), 0, chunksz);
-            munmap(va, PAGE_SIZE);
-        }
-    }
-
-    loadelfsymtab(elfbase, xch, dom, parray, dsi);
-
-    return 0;
-}
-
-#define ELFROUND (ELFSIZE / 8)
-
-static int
-loadelfsymtab(
-    char *elfbase, int xch, u32 dom, unsigned long *parray,
-    struct domain_setup_info *dsi)
-{
-    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr;
-    Elf_Shdr *shdr;
-    unsigned long maxva, symva;
-    char *p;
-    int h, i;
-
-    if ( !dsi->load_symtab )
-        return 0;
-
-    p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
-               ehdr->e_shnum * sizeof(Elf_Shdr));
-    if (p == NULL)
-        return 0;
-
-    maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
-    symva = maxva;
-    maxva += sizeof(int);
-    dsi->symtab_addr = maxva;
-    dsi->symtab_len = 0;
-    maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
-    maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
-
-    shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
-    memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
-
-    for ( h = 0; h < ehdr->e_shnum; h++ ) 
-    {
-        if ( shdr[h].sh_type == SHT_STRTAB )
-        {
-            /* Look for a strtab @i linked to symtab @h. */
-            for ( i = 0; i < ehdr->e_shnum; i++ )
-                if ( (shdr[i].sh_type == SHT_SYMTAB) &&
-                     (shdr[i].sh_link == h) )
-                    break;
-            /* Skip symtab @h if we found no corresponding strtab @i. */
-            if ( i == ehdr->e_shnum )
-            {
-                shdr[h].sh_offset = 0;
-                continue;
-            }
-        }
-
-        if ( (shdr[h].sh_type == SHT_STRTAB) ||
-             (shdr[h].sh_type == SHT_SYMTAB) )
-        {
-            if ( parray != NULL )
-                xc_map_memcpy(maxva, elfbase + shdr[h].sh_offset, 
shdr[h].sh_size,
-                           xch, dom, parray, dsi->v_start);
-
-            /* Mangled to be based on ELF header location. */
-            shdr[h].sh_offset = maxva - dsi->symtab_addr;
-
-            dsi->symtab_len += shdr[h].sh_size;
-            maxva += shdr[h].sh_size;
-            maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
-        }
-
-        shdr[h].sh_name = 0;  /* Name is NULL. */
-    }
-
-    if ( dsi->symtab_len == 0 )
-    {
-        dsi->symtab_addr = 0;
-        goto out;
-    }
-
-    if ( parray != NULL )
-    {
-        *(int *)p = maxva - dsi->symtab_addr;
-        sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
-        memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
-        sym_ehdr->e_phoff = 0;
-        sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
-        sym_ehdr->e_phentsize = 0;
-        sym_ehdr->e_phnum = 0;
-        sym_ehdr->e_shstrndx = SHN_UNDEF;
-
-        /* Copy total length, crafted ELF header and section header table */
-        xc_map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
-                   ehdr->e_shnum * sizeof(Elf_Shdr), xch, dom, parray,
-                   dsi->v_start);
-    }
-
-    dsi->symtab_len = maxva - dsi->symtab_addr;
-    dsi->v_end = round_pgup(maxva);
-
- out:
-    if ( p != NULL )
-        free(p);
-
-    return 0;
 }
--- orig/tools/libxc/Makefile   2005-05-25 00:20:35 +02:00
+++ new/tools/libxc/Makefile    2005-06-03 17:38:51 +02:00
@@ -14,9 +14,11 @@
 
 SRCS     :=
 SRCS     += xc_sedf.c
+SRCS     += xc_bin_load.c
 SRCS     += xc_bvtsched.c
 SRCS     += xc_core.c
 SRCS     += xc_domain.c
+SRCS     += xc_elf_load.c
 SRCS     += xc_evtchn.c
 SRCS     += xc_gnttab.c
 SRCS     += xc_linux_build.c
--- /dev/null   2005-06-03 14:57:54.380000000 +0200
+++ new/tools/libxc/xc_elf_load.c       2005-06-03 18:54:38.000000000 +0200
@@ -0,0 +1,303 @@
+/******************************************************************************
+ * xc_elf_load.c
+ */
+
+#include "xc_private.h"
+#define ELFSIZE 32
+#include "xc_elf.h"
+#include <stdlib.h>
+
+#define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
+#define round_pgdown(_p)  ((_p)&PAGE_MASK)
+
+static int
+parseelfimage(
+    char *image, unsigned long image_size, struct xc_domain_setup_info *dsi);
+static int
+loadelfimage(
+    char *image, unsigned long image_size, int xch, u32 dom,
+    unsigned long *parray, struct xc_domain_setup_info *dsi);
+static int
+loadelfsymtab(
+    char *image, int xch, u32 dom, unsigned long *parray,
+    struct xc_domain_setup_info *dsi);
+
+int xc_elf_probe(char *image,
+                 unsigned long image_size,
+                 struct xc_load_funcs *load_funcs)
+{
+    Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
+
+    if ( !IS_ELF(*ehdr) )
+    {
+        return -EINVAL;
+    }
+
+    load_funcs->parseimage = parseelfimage;
+    load_funcs->loadimage = loadelfimage;
+
+    return 0;
+}
+
+static inline int is_loadable_phdr(Elf_Phdr *phdr)
+{
+    return ((phdr->p_type == PT_LOAD) &&
+            ((phdr->p_flags & (PF_W|PF_X)) != 0));
+}
+
+static int parseelfimage(char *image, 
+                         unsigned long elfsize,
+                         struct xc_domain_setup_info *dsi)
+{
+    Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
+    Elf_Phdr *phdr;
+    Elf_Shdr *shdr;
+    unsigned long kernstart = ~0UL, kernend=0UL;
+    char *shstrtab, *guestinfo=NULL, *p;
+    int h;
+
+    if ( !IS_ELF(*ehdr) )
+    {
+        ERROR("Kernel image does not have an ELF header.");
+        return -EINVAL;
+    }
+
+    if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
+    {
+        ERROR("ELF program headers extend beyond end of image.");
+        return -EINVAL;
+    }
+
+    if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
+    {
+        ERROR("ELF section headers extend beyond end of image.");
+        return -EINVAL;
+    }
+
+    /* Find the section-header strings table. */
+    if ( ehdr->e_shstrndx == SHN_UNDEF )
+    {
+        ERROR("ELF image has no section-header strings table (shstrtab).");
+        return -EINVAL;
+    }
+    shdr = (Elf_Shdr *)(image + ehdr->e_shoff + 
+                        (ehdr->e_shstrndx*ehdr->e_shentsize));
+    shstrtab = image + shdr->sh_offset;
+    
+    /* Find the special '__xen_guest' section and check its contents. */
+    for ( h = 0; h < ehdr->e_shnum; h++ )
+    {
+        shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
+        if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
+            continue;
+
+        guestinfo = image + shdr->sh_offset;
+
+        if ( (strstr(guestinfo, "LOADER=generic") == NULL) &&
+             (strstr(guestinfo, "GUEST_OS=linux") == NULL) )
+        {
+            ERROR("Will only load images built for the generic loader "
+                  "or Linux images");
+            ERROR("Actually saw: '%s'", guestinfo);
+            return -EINVAL;
+        }
+
+        if ( (strstr(guestinfo, "XEN_VER=3.0") == NULL) )
+        {
+            ERROR("Will only load images built for Xen v3.0");
+            ERROR("Actually saw: '%s'", guestinfo);
+            return -EINVAL;
+        }
+
+        break;
+    }
+    if ( guestinfo == NULL )
+    {
+        ERROR("Not a Xen-ELF image: '__xen_guest' section not found.");
+        return -EINVAL;
+    }
+
+    for ( h = 0; h < ehdr->e_phnum; h++ ) 
+    {
+        phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
+        if ( !is_loadable_phdr(phdr) )
+            continue;
+        if ( phdr->p_paddr < kernstart )
+            kernstart = phdr->p_paddr;
+        if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
+            kernend = phdr->p_paddr + phdr->p_memsz;
+    }
+
+    if ( (kernstart > kernend) || 
+         (ehdr->e_entry < kernstart) || 
+         (ehdr->e_entry > kernend) )
+    {
+        ERROR("Malformed ELF image.");
+        return -EINVAL;
+    }
+
+    dsi->v_start = kernstart;
+    if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
+        dsi->v_start = strtoul(p+10, &p, 0);
+
+    if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
+        dsi->load_symtab = 1;
+
+    dsi->v_kernstart = kernstart;
+    dsi->v_kernend   = kernend;
+    dsi->v_kernentry = ehdr->e_entry;
+    dsi->v_end       = dsi->v_kernend;
+
+    loadelfsymtab(image, 0, 0, NULL, dsi);
+
+    return 0;
+}
+
+static int
+loadelfimage(
+    char *image, unsigned long image_size, int xch, u32 dom,
+    unsigned long *parray, struct xc_domain_setup_info *dsi)
+{
+    Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
+    Elf_Phdr *phdr;
+    int h;
+
+    char         *va;
+    unsigned long pa, done, chunksz;
+
+    for ( h = 0; h < ehdr->e_phnum; h++ ) 
+    {
+        phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
+        if ( !is_loadable_phdr(phdr) )
+            continue;
+        
+        for ( done = 0; done < phdr->p_filesz; done += chunksz )
+        {
+            pa = (phdr->p_paddr + done) - dsi->v_start;
+            va = xc_map_foreign_range(
+                xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
+            chunksz = phdr->p_filesz - done;
+            if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
+                chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
+            memcpy(va + (pa & (PAGE_SIZE-1)),
+                   image + phdr->p_offset + done, chunksz);
+            munmap(va, PAGE_SIZE);
+        }
+
+        for ( ; done < phdr->p_memsz; done += chunksz )
+        {
+            pa = (phdr->p_paddr + done) - dsi->v_start;
+            va = xc_map_foreign_range(
+                xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
+            chunksz = phdr->p_memsz - done;
+            if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
+                chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
+            memset(va + (pa & (PAGE_SIZE-1)), 0, chunksz);
+            munmap(va, PAGE_SIZE);
+        }
+    }
+
+    loadelfsymtab(image, xch, dom, parray, dsi);
+
+    return 0;
+}
+
+#define ELFROUND (ELFSIZE / 8)
+
+static int
+loadelfsymtab(
+    char *image, int xch, u32 dom, unsigned long *parray,
+    struct xc_domain_setup_info *dsi)
+{
+    Elf_Ehdr *ehdr = (Elf_Ehdr *)image, *sym_ehdr;
+    Elf_Shdr *shdr;
+    unsigned long maxva, symva;
+    char *p;
+    int h, i;
+
+    if ( !dsi->load_symtab )
+        return 0;
+
+    p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
+               ehdr->e_shnum * sizeof(Elf_Shdr));
+    if (p == NULL)
+        return 0;
+
+    maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
+    symva = maxva;
+    maxva += sizeof(int);
+    dsi->symtab_addr = maxva;
+    dsi->symtab_len = 0;
+    maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
+    maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
+
+    shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
+    memcpy(shdr, image + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
+
+    for ( h = 0; h < ehdr->e_shnum; h++ ) 
+    {
+        if ( shdr[h].sh_type == SHT_STRTAB )
+        {
+            /* Look for a strtab @i linked to symtab @h. */
+            for ( i = 0; i < ehdr->e_shnum; i++ )
+                if ( (shdr[i].sh_type == SHT_SYMTAB) &&
+                     (shdr[i].sh_link == h) )
+                    break;
+            /* Skip symtab @h if we found no corresponding strtab @i. */
+            if ( i == ehdr->e_shnum )
+            {
+                shdr[h].sh_offset = 0;
+                continue;
+            }
+        }
+
+        if ( (shdr[h].sh_type == SHT_STRTAB) ||
+             (shdr[h].sh_type == SHT_SYMTAB) )
+        {
+            if ( parray != NULL )
+                xc_map_memcpy(maxva, image + shdr[h].sh_offset, 
shdr[h].sh_size,
+                           xch, dom, parray, dsi->v_start);
+
+            /* Mangled to be based on ELF header location. */
+            shdr[h].sh_offset = maxva - dsi->symtab_addr;
+
+            dsi->symtab_len += shdr[h].sh_size;
+            maxva += shdr[h].sh_size;
+            maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
+        }
+
+        shdr[h].sh_name = 0;  /* Name is NULL. */
+    }
+
+    if ( dsi->symtab_len == 0 )
+    {
+        dsi->symtab_addr = 0;
+        goto out;
+    }
+
+    if ( parray != NULL )
+    {
+        *(int *)p = maxva - dsi->symtab_addr;
+        sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
+        memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
+        sym_ehdr->e_phoff = 0;
+        sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
+        sym_ehdr->e_phentsize = 0;
+        sym_ehdr->e_phnum = 0;
+        sym_ehdr->e_shstrndx = SHN_UNDEF;
+
+        /* Copy total length, crafted ELF header and section header table */
+        xc_map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
+                   ehdr->e_shnum * sizeof(Elf_Shdr), xch, dom, parray,
+                   dsi->v_start);
+    }
+
+    dsi->symtab_len = maxva - dsi->symtab_addr;
+    dsi->v_end = round_pgup(maxva);
+
+ out:
+    if ( p != NULL )
+        free(p);
+
+    return 0;
+}
--- /dev/null   2005-06-03 14:57:54.380000000 +0200
+++ new/tools/libxc/xc_bin_load.c       2005-06-03 19:05:51.000000000 +0200
@@ -0,0 +1,299 @@
+/******************************************************************************
+ * xc_bin_load.c
+ *
+ * Based on xc_elf_load.c
+ *
+ * Loads simple binary images. It's like a .COM file in MS-DOS. No headers are
+ * present. The only requirement is that it must have a xen_bin_image table
+ * somewhere in the first 8192 bytes, starting on a 32-bit aligned address.
+ * Those familiar with the multiboot specification should recognize this, it's
+ * (almost) the same as the multiboot header.
+ * The layout of the xen_bin_image table is:
+ *
+ * Offset Type Name          Note
+ * 0      u32  magic         required
+ * 4      u32  flags         required
+ * 8      u32  checksum      required
+ * 12     u32  header_addr   required
+ * 16     u32  load_addr     required
+ * 20     u32  load_end_addr required
+ * 24     u32  bss_end_addr  required
+ * 28     u32  entry_addr    required
+ *
+ * - magic
+ *   Magic number identifying the table. For images to be loaded by Xen 3, the
+ *   magic value is 0x336ec578 ("xEn3" with the 0x80 bit of the "E" set).
+ * - flags
+ *   bit 0: indicates whether the image needs to be loaded on a page boundary
+ *   bit 1: reserved, must be 0 (the multiboot spec uses this bit to indicate
+ *          that memory info should be passed to the image)
+ *   bit 2: reserved, must be 0 (the multiboot spec uses this bit to indicate
+ *          that the bootloader should pass video mode info to the image)
+ *   bit 16: reserved, must be 1 (the multiboot spec uses this bit to indicate
+ *           that the values in the fields header_addr - entry_addr are
+ *           valid)
+ *   All other bits should be set to 0.
+ * - checksum
+ *   When added to "magic" and "flags", the resulting value should be 0.
+ * - header_addr
+ *   Contains the virtual address corresponding to the beginning of the
+ *   table - the memory location at which the magic value is supposed to be
+ *   loaded. This field serves to synchronize the mapping between OS image
+ *   offsets and virtual memory addresses.
+ * - load_addr
+ *   Contains the virtual address of the beginning of the text segment. The
+ *   offset in the OS image file at which to start loading is defined by the
+ *   offset at which the table was found, minus (header addr - load addr).
+ *   load addr must be less than or equal to header addr.
+ * - load_end_addr
+ *   Contains the virtual address of the end of the data segment.
+ *   (load_end_addr - load_addr) specifies how much data to load. This implies
+ *   that the text and data segments must be consecutive in the OS image. If
+ *   this field is zero, the domain builder assumes that the text and data
+ *   segments occupy the whole OS image file.
+ * - bss_end_addr
+ *   Contains the virtual address of the end of the bss segment. The domain
+ *   builder initializes this area to zero, and reserves the memory it occupies
+ *   to avoid placing boot modules and other data relevant to the loaded image
+ *   in that area. If this field is zero, the domain builder assumes that no 
bss
+ *   segment is present.
+ * - entry_addr
+ *   The virtual address at which to start execution of the loaded image.
+ *
+ * Some of the field descriptions were copied from "The Multiboot
+ * Specification", Copyright 1995, 96 Bryan Ford <baford@xxxxxxxxxxx>,
+ * Erich Stefan Boleyn <erich@xxxxxxxx> Copyright 1999, 2000, 2001, 2002
+ * Free Software Foundation, Inc.
+ */
+
+#include "xc_private.h"
+#include <stdlib.h>
+
+#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
+#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
+
+#define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
+#define round_pgdown(_p)  ((_p)&PAGE_MASK)
+
+struct xen_bin_image_table
+{
+    unsigned long magic;
+    unsigned long flags;
+    unsigned long checksum;
+    unsigned long header_addr;
+    unsigned long load_addr;
+    unsigned long load_end_addr;
+    unsigned long bss_end_addr;
+    unsigned long entry_addr;
+};
+
+#define XEN_REACTOS_MAGIC3 0x336ec578
+
+#define XEN_REACTOS_FLAG_ALIGN4K     0x00000001
+#define XEN_REACTOS_FLAG_NEEDMEMINFO 0x00000002
+#define XEN_REACTOS_FLAG_NEEDVIDINFO 0x00000004
+#define XEN_REACTOS_FLAG_ADDRSVALID  0x00010000
+
+/* Flags we test for */
+#define FLAGS_MASK     ((~ 0) & (~ XEN_REACTOS_FLAG_ALIGN4K))
+#define FLAGS_REQUIRED XEN_REACTOS_FLAG_ADDRSVALID
+
+static struct xen_bin_image_table *
+findtable(char *image, unsigned long image_size);
+static int
+parsebinimage(
+    char *image, unsigned long image_size, struct xc_domain_setup_info *dsi);
+static int
+loadbinimage(
+    char *image, unsigned long image_size, int xch, u32 dom,
+    unsigned long *parray, struct xc_domain_setup_info *dsi);
+
+int xc_bin_probe(char *image,
+                 unsigned long image_size,
+                 struct xc_load_funcs *load_funcs)
+{
+    if ( NULL == findtable(image, image_size) )
+    {
+        return -EINVAL;
+    }
+
+    load_funcs->parseimage = parsebinimage;
+    load_funcs->loadimage = loadbinimage;
+
+    return 0;
+}
+
+static struct xen_bin_image_table *
+findtable(char *image, unsigned long image_size)
+{
+    struct xen_bin_image_table *table;
+    unsigned long *probe_ptr;
+    unsigned probe_index;
+    unsigned probe_count;
+
+    /* Don't go outside the image */
+    if ( image_size < sizeof(struct xen_bin_image_table) )
+    {
+        return NULL;
+    }
+    probe_count = image_size;
+    /* Restrict to first 8k */
+    if ( 8192 < probe_count )
+    {
+        probe_count = 8192;
+    }
+    probe_count = (probe_count - sizeof(struct xen_bin_image_table)) /
+                  sizeof(unsigned long);
+
+    /* Search for the magic header */
+    probe_ptr = (unsigned long *) image;
+    table = NULL;
+    for ( probe_index = 0; probe_index < probe_count; probe_index++ )
+    {
+        if ( XEN_REACTOS_MAGIC3 == *probe_ptr )
+        {
+            table = (struct xen_bin_image_table *) probe_ptr;
+            /* Checksum correct? */
+            if ( 0 == table->magic + table->flags + table->checksum )
+            {
+                return table;
+            }
+        }
+        probe_ptr++;
+    }
+
+    return NULL;
+}
+
+static int parsebinimage(char *image, 
+                         unsigned long image_size,
+                         struct xc_domain_setup_info *dsi)
+{
+    struct xen_bin_image_table *image_info;
+    unsigned long start_addr;
+    unsigned long end_addr;
+
+    image_info = findtable(image, image_size);
+    if ( NULL == image_info )
+    {
+        ERROR("Image does not have a valid xen_bin_image_table table.");
+        return -EINVAL;
+    }
+
+    /* Check the flags */
+    if ( FLAGS_REQUIRED != (image_info->flags & FLAGS_MASK) )
+    {
+        ERROR("xen_bin_image_table flags required 0x%08x found 0x%08lx",
+              FLAGS_REQUIRED, image_info->flags & FLAGS_MASK);
+        return -EINVAL;
+    }
+
+    /* Sanity check on the addresses */
+    if ( image_info->header_addr < image_info->load_addr ||
+         ((char *) image_info - image) <
+         (image_info->header_addr - image_info->load_addr) )
+    {
+        ERROR("Invalid header_addr.");
+        return -EINVAL;
+    }
+    start_addr = image_info->header_addr - ((char *) image_info - image);
+    if ( 0 != image_info->load_end_addr &&
+         ( image_info->load_end_addr < image_info->load_end_addr ||
+           start_addr + image_size < image_info->load_end_addr ) )
+    {
+        ERROR("Invalid load_end_addr");
+        return -EINVAL;
+    }
+    end_addr = (0 == image_info->load_end_addr ? start_addr + image_size :
+                                                 image_info->load_end_addr);
+    if ( 0 != image_info->bss_end_addr &&
+         image_info->bss_end_addr < end_addr )
+    {
+        ERROR("Invalid bss_end_addr");
+        return -EINVAL;
+    }
+
+    dsi->v_start = image_info->load_addr;
+    if ( 0 != image_info->bss_end_addr )
+    {
+        dsi->v_end = image_info->bss_end_addr;
+    }
+    else if ( 0 != image_info->load_end_addr )
+    {
+        dsi->v_end = image_info->load_end_addr;
+    }
+    else
+    {
+        dsi->v_end = image_info->load_addr + image_size -
+                     (((char *) image_info - image) -
+                      (image_info->header_addr - image_info->load_addr));
+    }
+    dsi->v_kernstart = dsi->v_start;
+    dsi->v_kernend = dsi->v_end;
+    dsi->v_kernentry = image_info->entry_addr;
+
+    return 0;
+}
+
+static int
+loadbinimage(
+    char *image, unsigned long image_size, int xch, u32 dom,
+    unsigned long *parray, struct xc_domain_setup_info *dsi)
+{
+    unsigned long size;
+    char         *va;
+    unsigned long done, chunksz;
+    struct xen_bin_image_table *image_info;
+
+    image_info = findtable(image, image_size);
+    if ( NULL == image_info )
+    {
+        ERROR("Image does not have a valid xen_bin_image_table table.");
+        return -EINVAL;
+    }
+
+    /* Determine image size */
+    if ( 0 == image_info->load_end_addr )
+    {
+        size = image_size  - (((char *) image_info - image) -
+                              (image_info->header_addr -
+                               image_info->load_addr));
+    }
+    else
+    {
+        size = image_info->load_end_addr - image_info->load_addr;
+    }
+
+    /* It's possible that we need to skip the first part of the image */
+    image += ((char *)image_info - image) -
+             (image_info->header_addr - image_info->load_addr);
+
+    for ( done = 0; done < size; done += chunksz )
+    {
+        va = xc_map_foreign_range(
+            xch, dom, PAGE_SIZE, PROT_WRITE, parray[done>>PAGE_SHIFT]);
+        chunksz = size - done;
+        if ( chunksz > PAGE_SIZE )
+            chunksz = PAGE_SIZE;
+        memcpy(va, image + done, chunksz);
+        munmap(va, PAGE_SIZE);
+    }
+
+    if ( 0 != image_info->bss_end_addr &&
+         image_info->load_addr + size < image_info->bss_end_addr )
+    {
+        size = image_info->bss_end_addr - image_info->load_addr;
+    }
+    for ( ; done < size; done += chunksz )
+    {
+        va = xc_map_foreign_range(
+            xch, dom, PAGE_SIZE, PROT_WRITE, parray[done>>PAGE_SHIFT]);
+        chunksz = size - done;
+        if ( chunksz > (PAGE_SIZE - (done & (PAGE_SIZE-1))) )
+            chunksz = PAGE_SIZE - (done & (PAGE_SIZE-1));
+        memset(va + (done & (PAGE_SIZE-1)), 0, chunksz);
+        munmap(va, PAGE_SIZE);
+    }
+
+    return 0;
+}

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

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