[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] loader for ReactOS (2nd try)
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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |