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
|