Suggestions by Christian Limpach taken into account in the patch below. Ge van Geldorp. Signed-Off-By: Ge van Geldorp <gvg@reactos.com> --- 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@cs.utah.edu>, + * Erich Stefan Boleyn <erich@uruk.org> 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@lists.xensource.com http://lists.xensource.com/xen-devel
Christian Limpach
2005-Jun-06 09:10 UTC
Re: [Xen-devel] [PATCH] loader for ReactOS (2nd try)
On 6/3/05, Ge van Geldorp <gvg@reactos.com> wrote:> Suggestions by Christian Limpach taken into account in the patch below.Thanks! I''ve applied the patch. Now, if someone could merge the plan9 builder with this, that would be brilliant! Ron? christian _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel