[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Remove old elf-parsing code from tools and from Xen.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1171535139 0 # Node ID 0d488e53446a1d0dd74481b52f49e704c362254c # Parent 82f66bc01da2cb14062c0651a63dbf7286cfd1e7 Remove old elf-parsing code from tools and from Xen. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- tools/libxc/xc_linux_build.c | 1319 ------------------------------------------- tools/libxc/xc_load_bin.c | 306 --------- tools/libxc/xc_load_elf.c | 684 ---------------------- xen/common/elf.c | 520 ---------------- tools/libxc/Makefile | 4 tools/libxc/xc_private.c | 20 tools/libxc/xg_private.h | 77 -- 7 files changed, 2930 deletions(-) diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/Makefile --- a/tools/libxc/Makefile Wed Feb 14 12:18:32 2007 -0800 +++ b/tools/libxc/Makefile Thu Feb 15 10:25:39 2007 +0000 @@ -22,11 +22,7 @@ CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptra CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptrace.c xc_ptrace_core.c GUEST_SRCS-y := -GUEST_SRCS-y += xc_load_bin.c -GUEST_SRCS-y += xc_load_elf.c GUEST_SRCS-y += xg_private.c -#GUEST_SRCS-$(CONFIG_X86) += xc_linux_build.c -#GUEST_SRCS-$(CONFIG_IA64) += xc_linux_build.c GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c xc_hvm_restore.c xc_hvm_save.c diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/xc_linux_build.c --- a/tools/libxc/xc_linux_build.c Wed Feb 14 12:18:32 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1319 +0,0 @@ -/****************************************************************************** - * xc_linux_build.c - */ - -#include <stddef.h> -#include "xg_private.h" -#include "xc_private.h" -#include <xenctrl.h> - -#include "xc_elf.h" -#include <stdlib.h> -#include <unistd.h> -#include <inttypes.h> -#include <zlib.h> - -/* Handy for printing out '0' prepended values at native pointer size */ -#define _p(a) ((void *) ((ulong)a)) - -#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) -#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) -#if defined(__i386__) -#define L3_PROT (_PAGE_PRESENT) -#elif defined(__x86_64__) -#define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) -#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) -#endif - -#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) -#define round_pgdown(_p) ((_p)&PAGE_MASK) - -struct initrd_info { - enum { INITRD_none, INITRD_file, INITRD_mem } type; - /* - * .len must be filled in by the user for type==INITRD_mem. It is - * filled in by load_initrd() for INITRD_file and unused for - * INITRD_none. - */ - unsigned long len; - union { - gzFile file_handle; - char *mem_addr; - } u; -}; - -static const char *feature_names[XENFEAT_NR_SUBMAPS*32] = { - [XENFEAT_writable_page_tables] = "writable_page_tables", - [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables", - [XENFEAT_auto_translated_physmap] = "auto_translated_physmap", - [XENFEAT_supervisor_mode_kernel] = "supervisor_mode_kernel", - [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb" -}; - -static inline void set_feature_bit (int nr, uint32_t *addr) -{ - addr[nr>>5] |= (1<<(nr&31)); -} - -static inline int test_feature_bit(int nr, uint32_t *addr) -{ - return !!(addr[nr>>5] & (1<<(nr&31))); -} - -static int parse_features( - const char *feats, - uint32_t supported[XENFEAT_NR_SUBMAPS], - uint32_t required[XENFEAT_NR_SUBMAPS]) -{ - const char *end, *p; - int i, req; - - if ( (end = strchr(feats, ',')) == NULL ) - end = feats + strlen(feats); - - while ( feats < end ) - { - p = strchr(feats, '|'); - if ( (p == NULL) || (p > end) ) - p = end; - - req = (*feats == '!'); - if ( req ) - feats++; - - for ( i = 0; i < XENFEAT_NR_SUBMAPS*32; i++ ) - { - if ( feature_names[i] == NULL ) - continue; - - if ( strncmp(feature_names[i], feats, p-feats) == 0 ) - { - set_feature_bit(i, supported); - if ( required && req ) - set_feature_bit(i, required); - break; - } - } - - if ( i == XENFEAT_NR_SUBMAPS*32 ) - { - ERROR("Unknown feature \"%.*s\".", (int)(p-feats), feats); - if ( req ) - { - ERROR("Kernel requires an unknown hypervisor feature."); - return -EINVAL; - } - } - - feats = p; - if ( *feats == '|' ) - feats++; - } - - return -EINVAL; -} - -static int probeimageformat(const char *image, - unsigned long image_size, - struct load_funcs *load_funcs) -{ - if ( probe_elf(image, image_size, load_funcs) && - probe_bin(image, image_size, load_funcs) ) - { - xc_set_error(XC_INVALID_KERNEL, "Not a valid ELF or raw kernel image"); - return -EINVAL; - } - - return 0; -} - -static int load_initrd(int xc_handle, domid_t dom, - struct initrd_info *initrd, - unsigned long physbase, - xen_pfn_t *phys_to_mach) -{ - char page[PAGE_SIZE]; - unsigned long pfn_start, pfn; - - if ( initrd->type == INITRD_none ) - return 0; - - pfn_start = physbase >> PAGE_SHIFT; - - if ( initrd->type == INITRD_mem ) - { - unsigned long nr_pages = (initrd->len + PAGE_SIZE - 1) >> PAGE_SHIFT; - - for ( pfn = pfn_start; pfn < (pfn_start + nr_pages); pfn++ ) - { - xc_copy_to_domain_page( - xc_handle, dom, phys_to_mach[pfn], - &initrd->u.mem_addr[(pfn - pfn_start) << PAGE_SHIFT]); - } - } - else - { - int readlen; - - pfn = pfn_start; - initrd->len = 0; - - /* gzread returns 0 on EOF */ - while ( (readlen = gzread(initrd->u.file_handle, page, PAGE_SIZE)) ) - { - if ( readlen < 0 ) - { - PERROR("Error reading initrd image, could not"); - return -EINVAL; - } - - initrd->len += readlen; - xc_copy_to_domain_page(xc_handle, dom, phys_to_mach[pfn++], page); - } - } - - return 0; -} - -#define alloc_pt(ltab, vltab) \ -do { \ - ltab = ppt_alloc++; \ - ltab = (uint64_t)page_array[ltab] << PAGE_SHIFT; \ - if ( vltab != NULL ) \ - munmap(vltab, PAGE_SIZE); \ - if ( (vltab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, \ - PROT_READ|PROT_WRITE, \ - ltab >> PAGE_SHIFT)) == NULL ) \ - goto error_out; \ - memset(vltab, 0x0, PAGE_SIZE); \ -} while ( 0 ) - -#if defined(__i386__) - -static int setup_pg_tables(int xc_handle, uint32_t dom, - vcpu_guest_context_t *ctxt, - unsigned long dsi_v_start, - unsigned long v_end, - xen_pfn_t *page_array, - unsigned long vpt_start, - unsigned long vpt_end, - unsigned shadow_mode_enabled) -{ - l1_pgentry_t *vl1tab=NULL, *vl1e=NULL; - l2_pgentry_t *vl2tab=NULL, *vl2e=NULL; - unsigned long l1tab = 0; - unsigned long l2tab = 0; - unsigned long ppt_alloc; - unsigned long count; - - ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT; - alloc_pt(l2tab, vl2tab); - vl2e = &vl2tab[l2_table_offset(dsi_v_start)]; - ctxt->ctrlreg[3] = xen_pfn_to_cr3(l2tab >> PAGE_SHIFT); - - for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++ ) - { - if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) - { - alloc_pt(l1tab, vl1tab); - vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))]; - *vl2e++ = l1tab | L2_PROT; - } - - *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT; - - if ( !shadow_mode_enabled ) - if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) && - (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) ) - *vl1e &= ~_PAGE_RW; - - vl1e++; - } - munmap(vl1tab, PAGE_SIZE); - munmap(vl2tab, PAGE_SIZE); - return 0; - - error_out: - if (vl1tab) - munmap(vl1tab, PAGE_SIZE); - if (vl2tab) - munmap(vl2tab, PAGE_SIZE); - return -1; -} - -static int setup_pg_tables_pae(int xc_handle, uint32_t dom, - vcpu_guest_context_t *ctxt, - unsigned long dsi_v_start, - unsigned long v_end, - xen_pfn_t *page_array, - unsigned long vpt_start, - unsigned long vpt_end, - unsigned shadow_mode_enabled, - unsigned pae_mode) -{ - l1_pgentry_64_t *vl1tab = NULL, *vl1e = NULL; - l2_pgentry_64_t *vl2tab = NULL, *vl2e = NULL; - l3_pgentry_64_t *vl3tab = NULL, *vl3e = NULL; - uint64_t l1tab, l2tab, l3tab; - unsigned long ppt_alloc, count, nmfn; - - /* First allocate page for page dir. */ - ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT; - - if ( pae_mode == PAEKERN_extended_cr3 ) - { - ctxt->vm_assist |= (1UL << VMASST_TYPE_pae_extended_cr3); - } - else if ( page_array[ppt_alloc] > 0xfffff ) - { - nmfn = xc_make_page_below_4G(xc_handle, dom, page_array[ppt_alloc]); - if ( nmfn == 0 ) - { - DPRINTF("Couldn't get a page below 4GB :-(\n"); - goto error_out; - } - page_array[ppt_alloc] = nmfn; - } - - alloc_pt(l3tab, vl3tab); - vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)]; - ctxt->ctrlreg[3] = xen_pfn_to_cr3(l3tab >> PAGE_SHIFT); - - for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++) - { - if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) ) - { - if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) ) - { - alloc_pt(l2tab, vl2tab); - vl2e = &vl2tab[l2_table_offset_pae( - dsi_v_start + (count << PAGE_SHIFT))]; - *vl3e++ = l2tab | L3_PROT; - } - - alloc_pt(l1tab, vl1tab); - vl1e = &vl1tab[l1_table_offset_pae( - dsi_v_start + (count << PAGE_SHIFT))]; - *vl2e++ = l1tab | L2_PROT; - - } - - *vl1e = ((uint64_t)page_array[count] << PAGE_SHIFT) | L1_PROT; - - if ( !shadow_mode_enabled ) - if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) && - (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) ) - *vl1e &= ~_PAGE_RW; - - vl1e++; - } - - /* Xen requires a mid-level pgdir mapping 0xC0000000 region. */ - if ( (vl3tab[3] & _PAGE_PRESENT) == 0 ) - { - alloc_pt(l2tab, vl2tab); - vl3tab[3] = l2tab | L3_PROT; - } - - munmap(vl1tab, PAGE_SIZE); - munmap(vl2tab, PAGE_SIZE); - munmap(vl3tab, PAGE_SIZE); - return 0; - - error_out: - if (vl1tab) - munmap(vl1tab, PAGE_SIZE); - if (vl2tab) - munmap(vl2tab, PAGE_SIZE); - if (vl3tab) - munmap(vl3tab, PAGE_SIZE); - return -1; -} - -#endif - -#if defined(__x86_64__) - -static int setup_pg_tables_64(int xc_handle, uint32_t dom, - vcpu_guest_context_t *ctxt, - unsigned long dsi_v_start, - unsigned long v_end, - xen_pfn_t *page_array, - unsigned long vpt_start, - unsigned long vpt_end, - int shadow_mode_enabled) -{ - l1_pgentry_t *vl1tab=NULL, *vl1e=NULL; - l2_pgentry_t *vl2tab=NULL, *vl2e=NULL; - l3_pgentry_t *vl3tab=NULL, *vl3e=NULL; - l4_pgentry_t *vl4tab=NULL, *vl4e=NULL; - unsigned long l2tab = 0; - unsigned long l1tab = 0; - unsigned long l3tab = 0; - unsigned long l4tab = 0; - unsigned long ppt_alloc; - unsigned long count; - - /* First allocate page for page dir. */ - ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT; - alloc_pt(l4tab, vl4tab); - vl4e = &vl4tab[l4_table_offset(dsi_v_start)]; - ctxt->ctrlreg[3] = xen_pfn_to_cr3(l4tab >> PAGE_SHIFT); - - for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++) - { - if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) ) - { - alloc_pt(l1tab, vl1tab); - - if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) ) - { - alloc_pt(l2tab, vl2tab); - if ( !((unsigned long)vl3e & (PAGE_SIZE-1)) ) - { - alloc_pt(l3tab, vl3tab); - vl3e = &vl3tab[l3_table_offset(dsi_v_start + (count<<PAGE_SHIFT))]; - *vl4e++ = l3tab | L4_PROT; - } - vl2e = &vl2tab[l2_table_offset(dsi_v_start + (count<<PAGE_SHIFT))]; - *vl3e++ = l2tab | L3_PROT; - } - vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))]; - *vl2e++ = l1tab | L2_PROT; - } - - *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT; - - if ( !shadow_mode_enabled ) - if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) && - (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) ) - *vl1e &= ~_PAGE_RW; - - vl1e++; - } - - munmap(vl1tab, PAGE_SIZE); - munmap(vl2tab, PAGE_SIZE); - munmap(vl3tab, PAGE_SIZE); - munmap(vl4tab, PAGE_SIZE); - return 0; - - error_out: - if (vl1tab) - munmap(vl1tab, PAGE_SIZE); - if (vl2tab) - munmap(vl2tab, PAGE_SIZE); - if (vl3tab) - munmap(vl3tab, PAGE_SIZE); - if (vl4tab) - munmap(vl4tab, PAGE_SIZE); - return -1; -} -#endif - -#ifdef __ia64__ -static int setup_guest(int xc_handle, - uint32_t dom, - const char *image, unsigned long image_size, - struct initrd_info *initrd, - unsigned long nr_pages, - unsigned long *pvsi, unsigned long *pvke, - unsigned long *pvss, vcpu_guest_context_t *ctxt, - const char *cmdline, - unsigned long shared_info_frame, - unsigned long flags, - unsigned int store_evtchn, unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn, - uint32_t required_features[XENFEAT_NR_SUBMAPS]) -{ - xen_pfn_t *page_array = NULL; - struct load_funcs load_funcs; - struct domain_setup_info dsi; - unsigned long vinitrd_start; - unsigned long vinitrd_end; - unsigned long v_end; - unsigned long start_page, pgnr; - start_info_t *start_info; - unsigned long start_info_mpa; - struct xen_ia64_boot_param *bp; - shared_info_t *shared_info; - int i; - DECLARE_DOMCTL; - int rc; - - rc = probeimageformat(image, image_size, &load_funcs); - if ( rc != 0 ) - goto error_out; - - memset(&dsi, 0, sizeof(struct domain_setup_info)); - - rc = (load_funcs.parseimage)(image, image_size, &dsi); - if ( rc != 0 ) - goto error_out; - - if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL ) - { - PERROR("Could not allocate memory"); - goto error_out; - } - for ( i = 0; i < nr_pages; i++ ) - page_array[i] = i; - if ( xc_domain_memory_populate_physmap(xc_handle, dom, nr_pages, - 0, 0, page_array) ) - { - PERROR("Could not allocate memory for PV guest.\n"); - goto error_out; - } - - dsi.v_start = round_pgdown(dsi.v_start); - vinitrd_start = round_pgup(dsi.v_end); - start_info_mpa = (nr_pages - 3) << PAGE_SHIFT; - *pvke = dsi.v_kernentry; - - /* Build firmware. */ - memset(&domctl.u.arch_setup, 0, sizeof(domctl.u.arch_setup)); - domctl.u.arch_setup.flags = 0; - domctl.u.arch_setup.bp = start_info_mpa + sizeof (start_info_t); - domctl.u.arch_setup.maxmem = (nr_pages - 3) << PAGE_SHIFT; - domctl.cmd = XEN_DOMCTL_arch_setup; - domctl.domain = (domid_t)dom; - if ( xc_domctl(xc_handle, &domctl) ) - goto error_out; - - start_page = dsi.v_start >> PAGE_SHIFT; - /* in order to get initrd->len, we need to load initrd image at first */ - if ( load_initrd(xc_handle, dom, initrd, - vinitrd_start - dsi.v_start, page_array + start_page) ) - goto error_out; - - vinitrd_end = vinitrd_start + initrd->len; - v_end = round_pgup(vinitrd_end); - pgnr = (v_end - dsi.v_start) >> PAGE_SHIFT; - if ( pgnr > nr_pages ) - { - PERROR("too small memory is specified. " - "At least %ld kb is necessary.\n", - pgnr << (PAGE_SHIFT - 10)); - } - - IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" - " Loaded kernel: %p->%p\n" - " Init. ramdisk: %p->%p\n" - " TOTAL: %p->%p\n", - _p(dsi.v_kernstart), _p(dsi.v_kernend), - _p(vinitrd_start), _p(vinitrd_end), - _p(dsi.v_start), _p(v_end)); - IPRINTF(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry)); - - (load_funcs.loadimage)(image, image_size, xc_handle, dom, - page_array + start_page, &dsi); - - *store_mfn = page_array[nr_pages - 2]; //XXX - *console_mfn = page_array[nr_pages - 1]; //XXX - IPRINTF("start_info: 0x%lx at 0x%lx, " - "store_mfn: 0x%lx at 0x%lx, " - "console_mfn: 0x%lx at 0x%lx\n", - page_array[nr_pages - 3], nr_pages - 3, - *store_mfn, nr_pages - 2, - *console_mfn, nr_pages - 1); - - start_info = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, - page_array[nr_pages - 3]); - if ( start_info == NULL ) - goto error_out; - - memset(start_info, 0, sizeof(*start_info)); - rc = xc_version(xc_handle, XENVER_version, NULL); - sprintf(start_info->magic, "xen-%i.%i-ia64", rc >> 16, rc & (0xFFFF)); - start_info->flags = flags; - start_info->store_mfn = nr_pages - 2; - start_info->store_evtchn = store_evtchn; - start_info->console.domU.mfn = nr_pages - 1; - start_info->console.domU.evtchn = console_evtchn; - start_info->nr_pages = nr_pages; // FIXME?: nr_pages - 2 ???? - - bp = (struct xen_ia64_boot_param *)(start_info + 1); - bp->command_line = start_info_mpa + offsetof(start_info_t, cmd_line); - if ( cmdline != NULL ) - { - strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE); - start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = 0; - } - if ( initrd->len != 0 ) - { - bp->initrd_start = vinitrd_start; - bp->initrd_size = initrd->len; - } - ctxt->user_regs.r28 = start_info_mpa + sizeof (start_info_t); - munmap(start_info, PAGE_SIZE); - - /* - * shared_info is assiged into guest pseudo physical address space - * by XEN_DOMCTL_arch_setup. shared_info_frame is stale value until that. - * So passed shared_info_frame is stale. obtain the right value here. - */ - domctl.cmd = XEN_DOMCTL_getdomaininfo; - domctl.domain = (domid_t)dom; - if ( (xc_domctl(xc_handle, &domctl) < 0) || - ((uint16_t)domctl.domain != dom) ) - { - PERROR("Could not get info on domain"); - goto error_out; - } - shared_info_frame = domctl.u.getdomaininfo.shared_info_frame; - - /* shared_info page starts its life empty. */ - shared_info = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame); - printf("shared_info = %p frame=%lx\n", - shared_info, shared_info_frame); - //memset(shared_info, 0, PAGE_SIZE); - /* Mask all upcalls... */ - for ( i = 0; i < MAX_VIRT_CPUS; i++ ) - shared_info->vcpu_info[i].evtchn_upcall_mask = 1; - shared_info->arch.start_info_pfn = nr_pages - 3; - - munmap(shared_info, PAGE_SIZE); - free(page_array); - return 0; - - error_out: - free(page_array); - return -1; -} -#else /* x86 */ - -/* Check if the platform supports the guest kernel format */ -static int compat_check(int xc_handle, struct domain_setup_info *dsi) -{ - xen_capabilities_info_t xen_caps = ""; - - if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) { - xc_set_error(XC_INVALID_KERNEL, - "Cannot determine host capabilities."); - return 0; - } - -#ifndef __x86_64__//temp - if (strstr(xen_caps, "xen-3.0-x86_32p")) { - if (dsi->pae_kernel == PAEKERN_bimodal) { - dsi->pae_kernel = PAEKERN_extended_cr3; - } else if (dsi->pae_kernel == PAEKERN_no) { - xc_set_error(XC_INVALID_KERNEL, - "Non PAE-kernel on PAE host."); - return 0; - } - } else { - if (dsi->pae_kernel == PAEKERN_bimodal) { - dsi->pae_kernel = PAEKERN_no; - } else if (dsi->pae_kernel != PAEKERN_no) { - xc_set_error(XC_INVALID_KERNEL, - "PAE-kernel on non-PAE host."); - return 0; - } - } -#endif - - return 1; -} - -static inline int increment_ulong(unsigned long *pval, unsigned long inc) -{ - if ( inc >= -*pval ) - { - ERROR("Value wrapped to zero: image too large?"); - return 0; - } - *pval += inc; - return 1; -} - -static int setup_guest(int xc_handle, - uint32_t dom, - const char *image, unsigned long image_size, - struct initrd_info *initrd, - unsigned long nr_pages, - unsigned long *pvsi, unsigned long *pvke, - unsigned long *pvss, vcpu_guest_context_t *ctxt, - const char *cmdline, - unsigned long shared_info_frame, - unsigned long flags, - unsigned int store_evtchn, unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn, - uint32_t required_features[XENFEAT_NR_SUBMAPS]) -{ - xen_pfn_t *page_array = NULL; - unsigned long count, i; - unsigned long long hypercall_page; - int hypercall_page_defined; - start_info_t *start_info; - shared_info_t *shared_info; - const char *p; - DECLARE_DOMCTL; - int rc; - - unsigned long nr_pt_pages; - unsigned long physmap_pfn; - xen_pfn_t *physmap, *physmap_e; - - struct load_funcs load_funcs; - struct domain_setup_info dsi; - unsigned long vinitrd_start; - unsigned long vphysmap_start; - unsigned long vstartinfo_start; - unsigned long vstoreinfo_start; - unsigned long vconsole_start; - unsigned long vsharedinfo_start = 0; /* XXX gcc */ - unsigned long vstack_start; - unsigned long vstack_end; - unsigned long vpt_start; - unsigned long vpt_end; - unsigned long v_end; - unsigned long guest_store_mfn, guest_console_mfn, guest_shared_info_mfn; - unsigned long shadow_mode_enabled; - uint32_t supported_features[XENFEAT_NR_SUBMAPS] = { 0, }; - - rc = probeimageformat(image, image_size, &load_funcs); - if ( rc != 0 ) - goto error_out; - - memset(&dsi, 0, sizeof(struct domain_setup_info)); - - rc = (load_funcs.parseimage)(image, image_size, &dsi); - if ( rc != 0 ) - goto error_out; - - if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 ) - { - PERROR("Guest OS must load to a page boundary."); - goto error_out; - } - - if ( !compat_check(xc_handle, &dsi) ) - goto error_out; - - /* Parse and validate kernel features. */ - if ( (p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES)) != NULL ) - { - if ( !parse_features(p, supported_features, required_features) ) - { - ERROR("Failed to parse guest kernel features."); - goto error_out; - } - - IPRINTF("Supported features = { %08x }.\n", supported_features[0]); - IPRINTF("Required features = { %08x }.\n", required_features[0]); - } - - for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ ) - { - if ( (supported_features[i] & required_features[i]) != - required_features[i] ) - { - ERROR("Guest kernel does not support a required feature."); - goto error_out; - } - } - - shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap, - required_features); - - if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ) - { - PERROR("Could not allocate memory"); - goto error_out; - } - - for ( i = 0; i < nr_pages; i++ ) - page_array[i] = i; - - if ( xc_domain_memory_populate_physmap(xc_handle, dom, nr_pages, - 0, 0, page_array) ) - { - PERROR("Could not allocate memory for PV guest.\n"); - goto error_out; - } - - - if ( shadow_mode_enabled ) - { - /* - * Enable shadow translate mode. This must happen after - * populate physmap because the p2m reservation is based on - * the domain's current memory allocation. - */ - if ( xc_shadow_control(xc_handle, dom, - XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE, - NULL, 0, NULL, 0, NULL) < 0 ) - { - PERROR("Could not enable translation mode"); - goto error_out; - } - - /* Reinitialise the gpfn->gmfn array. */ - for ( i = 0; i < nr_pages; i++ ) - page_array[i] = i; - } - - rc = (load_funcs.loadimage)(image, image_size, - xc_handle, dom, page_array, - &dsi); - if ( rc != 0 ) - goto error_out; - - /* - * Why do we need this? The number of page-table frames depends on the - * size of the bootstrap address space. But the size of the address space - * depends on the number of page-table frames (since each one is mapped - * read-only). We have a pair of simultaneous equations in two unknowns, - * which we solve by exhaustive search. - */ - v_end = round_pgup(dsi.v_end); - if ( v_end == 0 ) - { - ERROR("End of mapped kernel image too close to end of memory"); - goto error_out; - } - - vinitrd_start = v_end; - if ( load_initrd(xc_handle, dom, initrd, - vinitrd_start - dsi.v_start, page_array) ) - goto error_out; - if ( !increment_ulong(&v_end, round_pgup(initrd->len)) ) - goto error_out; - - vphysmap_start = v_end; - if ( !increment_ulong(&v_end, round_pgup(nr_pages * sizeof(long))) ) - goto error_out; - vstartinfo_start = v_end; - if ( !increment_ulong(&v_end, PAGE_SIZE) ) - goto error_out; - vstoreinfo_start = v_end; - if ( !increment_ulong(&v_end, PAGE_SIZE) ) - goto error_out; - vconsole_start = v_end; - if ( !increment_ulong(&v_end, PAGE_SIZE) ) - goto error_out; - if ( shadow_mode_enabled ) { - vsharedinfo_start = v_end; - if ( !increment_ulong(&v_end, PAGE_SIZE) ) - goto error_out; - } - vpt_start = v_end; - - for ( nr_pt_pages = 2; ; nr_pt_pages++ ) - { - /* vpt_end = vpt_staret + (nr_pt_pages * PAGE_SIZE); */ - vpt_end = vpt_start; - if ( !increment_ulong(&vpt_end, nr_pt_pages * PAGE_SIZE) ) - goto error_out; - - vstack_start = vpt_end; - /* vstack_end = vstack_start + PAGE_SIZE; */ - vstack_end = vstack_start; - if ( !increment_ulong(&vstack_end, PAGE_SIZE) ) - goto error_out; - - /* v_end = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1); */ - v_end = vstack_end; - if ( !increment_ulong(&v_end, (1UL<<22)-1) ) - goto error_out; - v_end &= ~((1UL<<22)-1); - - if ( (v_end - vstack_end) < (512UL << 10) ) - { - /* Add extra 4MB to get >= 512kB padding. */ - if ( !increment_ulong(&v_end, 1UL << 22) ) - goto error_out; - } - -#define NR(_l,_h,_s) \ - (((((unsigned long)(_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \ - ((unsigned long)(_l) & ~((1UL<<(_s))-1))) >> (_s)) -#if defined(__i386__) - if ( dsi.pae_kernel != PAEKERN_no ) - { - if ( (1 + /* # L3 */ - NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT_PAE) + /* # L2 */ - NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT_PAE) + /* # L1 */ - /* Include a fourth mid-level page directory for Xen. */ - (v_end <= (3 << L3_PAGETABLE_SHIFT_PAE))) - <= nr_pt_pages ) - break; - } - else - { - if ( (1 + /* # L2 */ - NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */ - <= nr_pt_pages ) - break; - } -#elif defined(__x86_64__) - if ( (1 + /* # L4 */ - NR(dsi.v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */ - NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) + /* # L2 */ - NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */ - <= nr_pt_pages ) - break; -#endif - } - - IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"); - IPRINTF(" Loaded kernel: %p->%p\n", _p(dsi.v_kernstart), - _p(dsi.v_kernend)); - if ( initrd->len ) - IPRINTF(" Initial ramdisk: %p->%p\n", _p(vinitrd_start), - _p(vinitrd_start + initrd->len)); - IPRINTF(" Phys-Mach map: %p\n", _p(vphysmap_start)); - IPRINTF(" Start info: %p\n", _p(vstartinfo_start)); - IPRINTF(" Store page: %p\n", _p(vstoreinfo_start)); - IPRINTF(" Console page: %p\n", _p(vconsole_start)); - if ( shadow_mode_enabled ) - IPRINTF(" Shared Info page: %p\n", _p(vsharedinfo_start)); - IPRINTF(" Page tables: %p\n", _p(vpt_start)); - IPRINTF(" Boot stack: %p\n", _p(vstack_start)); - IPRINTF(" TOTAL: %p->%p\n", _p(dsi.v_start), _p(v_end)); - IPRINTF(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry)); - - if ( ((v_end - dsi.v_start)>>PAGE_SHIFT) > nr_pages ) - { - PERROR("Initial guest OS requires too much space\n" - "(%pMB is greater than %luMB limit)\n", - _p((v_end-dsi.v_start)>>20), nr_pages>>(20-PAGE_SHIFT)); - goto error_out; - } - -#if defined(__i386__) - if ( dsi.pae_kernel != PAEKERN_no ) - rc = setup_pg_tables_pae(xc_handle, dom, ctxt, - dsi.v_start, v_end, - page_array, vpt_start, vpt_end, - shadow_mode_enabled, dsi.pae_kernel); - else - rc = setup_pg_tables(xc_handle, dom, ctxt, - dsi.v_start, v_end, - page_array, vpt_start, vpt_end, - shadow_mode_enabled); -#endif -#if defined(__x86_64__) - rc = setup_pg_tables_64(xc_handle, dom, ctxt, - dsi.v_start, v_end, - page_array, vpt_start, vpt_end, - shadow_mode_enabled); -#endif - if ( rc != 0 ) - goto error_out; - - /* - * Pin down l2tab addr as page dir page - causes hypervisor to provide - * correct protection for the page - */ - if ( !shadow_mode_enabled ) - { -#if defined(__i386__) - if ( dsi.pae_kernel != PAEKERN_no ) - { - if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE, - xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) - goto error_out; - } - else - { - if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE, - xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) - goto error_out; - } -#elif defined(__x86_64__) - /* - * Pin down l4tab addr as page dir page - causes hypervisor to provide - * correct protection for the page - */ - if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE, - xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) ) - goto error_out; -#endif - } - - /* Write the phys->machine table entries (machine->phys already done). */ - physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT; - physmap = physmap_e = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, - page_array[physmap_pfn++]); - for ( count = 0; count < nr_pages; count++ ) - { - *physmap_e++ = page_array[count]; - if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 ) - { - munmap(physmap, PAGE_SIZE); - physmap = physmap_e = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, - page_array[physmap_pfn++]); - } - } - munmap(physmap, PAGE_SIZE); - - if ( shadow_mode_enabled ) - { - struct xen_add_to_physmap xatp; - - guest_shared_info_mfn = (vsharedinfo_start-dsi.v_start) >> PAGE_SHIFT; - - /* Map shared info frame into guest physmap. */ - xatp.domid = dom; - xatp.space = XENMAPSPACE_shared_info; - xatp.idx = 0; - xatp.gpfn = guest_shared_info_mfn; - rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp); - if ( rc != 0 ) - { - PERROR("Cannot map shared info pfn"); - goto error_out; - } - - /* Map grant table frames into guest physmap. */ - for ( i = 0; ; i++ ) - { - xatp.domid = dom; - xatp.space = XENMAPSPACE_grant_table; - xatp.idx = i; - xatp.gpfn = nr_pages + i; - rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp); - if ( rc != 0 ) - { - if ( errno == EINVAL ) - break; /* done all grant tables */ - PERROR("Cannot map grant table pfn"); - goto error_out; - } - } - } - else - { - guest_shared_info_mfn = shared_info_frame; - } - - *store_mfn = page_array[(vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT]; - *console_mfn = page_array[(vconsole_start-dsi.v_start) >> PAGE_SHIFT]; - if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) || - xc_clear_domain_page(xc_handle, dom, *console_mfn) ) - goto error_out; - if ( shadow_mode_enabled ) - { - guest_store_mfn = (vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT; - guest_console_mfn = (vconsole_start-dsi.v_start) >> PAGE_SHIFT; - } - else - { - guest_store_mfn = *store_mfn; - guest_console_mfn = *console_mfn; - } - - start_info = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, - page_array[(vstartinfo_start-dsi.v_start)>>PAGE_SHIFT]); - /*shared_info, start_info */ - memset(start_info, 0, sizeof(*start_info)); - rc = xc_version(xc_handle, XENVER_version, NULL); - sprintf(start_info->magic, "xen-%i.%i-x86_%d%s", - rc >> 16, rc & (0xFFFF), (unsigned int)sizeof(long)*8, - (dsi.pae_kernel != PAEKERN_no) ? "p" : ""); - start_info->nr_pages = nr_pages; - start_info->shared_info = guest_shared_info_mfn << PAGE_SHIFT; - start_info->flags = flags; - start_info->pt_base = vpt_start; - start_info->nr_pt_frames = nr_pt_pages; - start_info->mfn_list = vphysmap_start; - start_info->store_mfn = guest_store_mfn; - start_info->store_evtchn = store_evtchn; - start_info->console.domU.mfn = guest_console_mfn; - start_info->console.domU.evtchn = console_evtchn; - if ( initrd->len != 0 ) - { - start_info->mod_start = vinitrd_start; - start_info->mod_len = initrd->len; - } - if ( cmdline != NULL ) - { - strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE); - start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0'; - } - munmap(start_info, PAGE_SIZE); - - /* shared_info page starts its life empty. */ - shared_info = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame); - memset(shared_info, 0, PAGE_SIZE); - /* Mask all upcalls... */ - for ( i = 0; i < MAX_VIRT_CPUS; i++ ) - shared_info->vcpu_info[i].evtchn_upcall_mask = 1; - - munmap(shared_info, PAGE_SIZE); - - hypercall_page = xen_elfnote_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, - &hypercall_page_defined); - if ( hypercall_page_defined ) - { - unsigned long long pfn = (hypercall_page - dsi.v_start) >> PAGE_SHIFT; - if ( pfn >= nr_pages ) - goto error_out; - domctl.domain = (domid_t)dom; - domctl.u.hypercall_init.gmfn = page_array[pfn]; - domctl.cmd = XEN_DOMCTL_hypercall_init; - if ( xc_domctl(xc_handle, &domctl) ) - goto error_out; - } - - free(page_array); - - *pvsi = vstartinfo_start; - *pvss = vstack_start; - *pvke = dsi.v_kernentry; - - return 0; - - error_out: - free(page_array); - return -1; -} -#endif - -static int xc_linux_build_internal(int xc_handle, - uint32_t domid, - unsigned int mem_mb, - const char *image, - unsigned long image_size, - struct initrd_info *initrd, - const char *cmdline, - const char *features, - unsigned long flags, - unsigned int store_evtchn, - unsigned long *store_mfn, - unsigned int console_evtchn, - unsigned long *console_mfn) -{ - struct xen_domctl launch_domctl; - DECLARE_DOMCTL; - int rc; - struct vcpu_guest_context st_ctxt, *ctxt = &st_ctxt; - unsigned long vstartinfo_start, vkern_entry, vstack_start; - uint32_t features_bitmap[XENFEAT_NR_SUBMAPS] = { 0, }; - - if ( features != NULL ) - { - if ( !parse_features(features, features_bitmap, NULL) ) - { - PERROR("Failed to parse configured features\n"); - goto error_out; - } - } - - memset(ctxt, 0, sizeof(*ctxt)); - - if ( lock_pages(ctxt, sizeof(*ctxt) ) ) - { - PERROR("%s: ctxt lock failed", __func__); - return 1; - } - - domctl.cmd = XEN_DOMCTL_getdomaininfo; - domctl.domain = (domid_t)domid; - if ( (xc_domctl(xc_handle, &domctl) < 0) || - ((uint16_t)domctl.domain != domid) ) - { - PERROR("Could not get info on domain"); - goto error_out; - } - - if ( setup_guest(xc_handle, domid, image, image_size, - initrd, - mem_mb << (20 - PAGE_SHIFT), - &vstartinfo_start, &vkern_entry, - &vstack_start, ctxt, cmdline, - domctl.u.getdomaininfo.shared_info_frame, - flags, store_evtchn, store_mfn, - console_evtchn, console_mfn, - features_bitmap) < 0 ) - { - goto error_out; - } - -#ifdef __ia64__ - /* based on new_thread in xen/arch/ia64/domain.c */ - ctxt->user_regs.cr_iip = vkern_entry; - ctxt->user_regs.cr_ifs = 1UL << 63; - ctxt->user_regs.ar_fpsr = xc_ia64_fpsr_default(); -#else /* x86 */ - /* - * Initial register values: - * DS,ES,FS,GS = FLAT_KERNEL_DS - * CS:EIP = FLAT_KERNEL_CS:start_pc - * SS:ESP = FLAT_KERNEL_DS:start_stack - * ESI = start_info - * [EAX,EBX,ECX,EDX,EDI,EBP are zero] - * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1) - */ - ctxt->user_regs.ds = FLAT_KERNEL_DS; - ctxt->user_regs.es = FLAT_KERNEL_DS; - ctxt->user_regs.fs = FLAT_KERNEL_DS; - ctxt->user_regs.gs = FLAT_KERNEL_DS; - ctxt->user_regs.ss = FLAT_KERNEL_SS; - ctxt->user_regs.cs = FLAT_KERNEL_CS; - ctxt->user_regs.eip = vkern_entry; - ctxt->user_regs.esp = vstack_start + PAGE_SIZE; - ctxt->user_regs.esi = vstartinfo_start; - ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */ - - ctxt->flags = VGCF_IN_KERNEL; - - ctxt->kernel_ss = ctxt->user_regs.ss; - ctxt->kernel_sp = ctxt->user_regs.esp; -#endif /* x86 */ - - memset(&launch_domctl, 0, sizeof(launch_domctl)); - - launch_domctl.domain = (domid_t)domid; - launch_domctl.u.vcpucontext.vcpu = 0; - set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, ctxt); - - launch_domctl.cmd = XEN_DOMCTL_setvcpucontext; - rc = xc_domctl(xc_handle, &launch_domctl); - - return rc; - - error_out: - return -1; -} - -int xc_linux_build_mem(int xc_handle, - uint32_t domid, - unsigned int mem_mb, - const char *image_buffer, - unsigned long image_size, - const char *initrd, - unsigned long initrd_len, - const char *cmdline, - const char *features, - unsigned long flags, - unsigned int store_evtchn, - unsigned long *store_mfn, - unsigned int console_evtchn, - unsigned long *console_mfn) -{ - int sts; - char *img_buf; - unsigned long img_len; - struct initrd_info initrd_info = { .type = INITRD_none }; - - /* A kernel buffer is required */ - if ( (image_buffer == NULL) || (image_size == 0) ) - { - ERROR("kernel image buffer not present"); - return -1; - } - - /* If it's gzipped, inflate it; otherwise, use as is */ - /* xc_inflate_buffer may return the same buffer pointer if */ - /* the buffer is already inflated */ - img_buf = xc_inflate_buffer(image_buffer, image_size, &img_len); - if ( img_buf == NULL ) - { - ERROR("unable to inflate kernel image buffer"); - return -1; - } - - /* RAM disks are optional; if we get one, inflate it */ - if ( initrd != NULL ) - { - initrd_info.type = INITRD_mem; - initrd_info.u.mem_addr = xc_inflate_buffer( - initrd, initrd_len, &initrd_info.len); - if ( initrd_info.u.mem_addr == NULL ) - { - ERROR("unable to inflate ram disk buffer"); - sts = -1; - goto out; - } - } - - sts = xc_linux_build_internal(xc_handle, domid, mem_mb, img_buf, img_len, - &initrd_info, cmdline, features, flags, - store_evtchn, store_mfn, - console_evtchn, console_mfn); - - out: - /* The inflation routines may pass back the same buffer so be */ - /* sure that we have a buffer and that it's not the one passed in. */ - /* Don't unnecessarily annoy/surprise/confound the caller */ - if ( (img_buf != NULL) && (img_buf != image_buffer) ) - free(img_buf); - if ( (initrd_info.u.mem_addr != NULL) && - (initrd_info.u.mem_addr != initrd) ) - free(initrd_info.u.mem_addr); - - return sts; -} - -int xc_linux_build(int xc_handle, - uint32_t domid, - unsigned int mem_mb, - const char *image_name, - const char *initrd_name, - const char *cmdline, - const char *features, - unsigned long flags, - unsigned int store_evtchn, - unsigned long *store_mfn, - unsigned int console_evtchn, - unsigned long *console_mfn) -{ - char *image = NULL; - unsigned long image_size; - struct initrd_info initrd_info = { .type = INITRD_none }; - int fd = -1, sts = -1; - - if ( (image_name == NULL) || - ((image = xc_read_image(image_name, &image_size)) == NULL )) - return -1; - - if ( (initrd_name != NULL) && (strlen(initrd_name) != 0) ) - { - initrd_info.type = INITRD_file; - - if ( (fd = open(initrd_name, O_RDONLY)) < 0 ) - { - PERROR("Could not open the initial ramdisk image"); - goto error_out; - } - - if ( (initrd_info.u.file_handle = gzdopen(fd, "rb")) == NULL ) - { - PERROR("Could not allocate decompression state for initrd"); - goto error_out; - } - } - - sts = xc_linux_build_internal(xc_handle, domid, mem_mb, image, image_size, - &initrd_info, cmdline, features, flags, - store_evtchn, store_mfn, - console_evtchn, console_mfn); - - error_out: - free(image); - if ( initrd_info.type == INITRD_file && initrd_info.u.file_handle ) - gzclose(initrd_info.u.file_handle); - else if ( fd >= 0 ) - close(fd); - - return sts; -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/xc_load_bin.c --- a/tools/libxc/xc_load_bin.c Wed Feb 14 12:18:32 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,306 +0,0 @@ -/****************************************************************************** - * 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 uint32_t magic required - * 4 uint32_t flags required - * 8 uint32_t checksum required - * 12 uint32_t header_addr required - * 16 uint32_t load_addr required - * 20 uint32_t load_end_addr required - * 24 uint32_t bss_end_addr required - * 28 uint32_t 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 "xg_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 const struct xen_bin_image_table * -findtable(const char *image, unsigned long image_size); -static int -parsebinimage( - const char *image, unsigned long image_size, - struct domain_setup_info *dsi); -static int -loadbinimage( - const char *image, unsigned long image_size, int xch, uint32_t dom, - xen_pfn_t *parray, struct domain_setup_info *dsi); - -int probe_bin(const char *image, - unsigned long image_size, - struct load_funcs *load_funcs) -{ - if ( findtable(image, image_size) == NULL ) - return -EINVAL; - - load_funcs->parseimage = parsebinimage; - load_funcs->loadimage = loadbinimage; - - return 0; -} - -static const struct xen_bin_image_table * -findtable(const char *image, unsigned long image_size) -{ - const struct xen_bin_image_table *table; - const 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 ( probe_count > 8192 ) - probe_count = 8192; - probe_count = (probe_count - sizeof(struct xen_bin_image_table)) / - sizeof(unsigned long); - - /* Search for the magic header */ - probe_ptr = (const unsigned long *) image; - table = NULL; - for ( probe_index = 0; probe_index < probe_count; probe_index++ ) - { - if ( XEN_REACTOS_MAGIC3 == *probe_ptr ) - { - table = (const 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(const char *image, - unsigned long image_size, - struct domain_setup_info *dsi) -{ - const 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 || - ((const char *) image_info - image) < - (image_info->header_addr - image_info->load_addr) ) - { - ERROR("Invalid header_addr."); - return -EINVAL; - } - start_addr = image_info->header_addr - ((const 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 - - (((const 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; - dsi->__xen_guest_string = NULL; - - return 0; -} - -static int -loadbinimage( - const char *image, unsigned long image_size, int xch, uint32_t dom, - xen_pfn_t *parray, struct domain_setup_info *dsi) -{ - unsigned long size; - char *va; - unsigned long done, chunksz; - const 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 - (((const 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 += ((const 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; -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/xc_load_elf.c --- a/tools/libxc/xc_load_elf.c Wed Feb 14 12:18:32 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,684 +0,0 @@ -/****************************************************************************** - * xc_elf_load.c - */ - -#include "xg_private.h" -#include "xc_elf.h" -#include <stdlib.h> -#include <inttypes.h> - -#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) -#define round_pgdown(_p) ((_p)&PAGE_MASK) - -static int -parseelfimage( - const char *image, unsigned long image_size, - struct domain_setup_info *dsi); -static int -loadelfimage( - const char *image, unsigned long image_size, int xch, uint32_t dom, - xen_pfn_t *parray, struct domain_setup_info *dsi); -static int -loadelfsymtab( - const char *image, int xch, uint32_t dom, xen_pfn_t *parray, - struct domain_setup_info *dsi); - -/* - * Elf header attributes we require for each supported host platform. - * These are checked in parseelfimage(). - */ -#if defined(__ia64__) -#define ELFCLASS ELFCLASS64 -#define ELFCLASS_DESC "64-bit" - -#define ELFDATA ELFDATA2LSB -#define ELFDATA_DESC "Little-Endian" - -#define ELFMACHINE EM_IA_64 -#define ELFMACHINE_DESC "ia64" - - -#elif defined(__i386__) -#define ELFCLASS ELFCLASS32 -#define ELFCLASS_DESC "32-bit" - -#define ELFDATA ELFDATA2LSB -#define ELFDATA_DESC "Little-Endian" - -#define ELFMACHINE EM_386 -#define ELFMACHINE_DESC "i386" - - -#elif defined(__x86_64__) -#define ELFCLASS ELFCLASS64 -#define ELFCLASS_DESC "64-bit" - -#define ELFDATA ELFDATA2LSB -#define ELFDATA_DESC "Little-Endian" - -#define ELFMACHINE EM_X86_64 -#define ELFMACHINE_DESC "x86_64" - - -#elif defined(__powerpc__) -#define ELFCLASS ELFCLASS64 -#define ELFCLASS_DESC "64-bit" - -#define ELFDATA ELFDATA2MSB -#define ELFDATA_DESC "Big-Endian" - -#define ELFMACHINE EM_PPC64 -#define ELFMACHINE_DESC "ppc64" -#endif - -int probe_elf(const char *image, - unsigned long image_size, - struct load_funcs *load_funcs) -{ - const Elf_Ehdr *ehdr = (const 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(const Elf_Phdr *phdr) -{ - return ((phdr->p_type == PT_LOAD) && - ((phdr->p_flags & (PF_W|PF_X)) != 0)); -} - -/* - * Fallback for kernels containing only the legacy __xen_guest string - * and no ELF notes. - */ -static int is_xen_guest_section(const Elf_Shdr *shdr, const char *shstrtab) -{ - return strcmp(&shstrtab[shdr->sh_name], "__xen_guest") == 0; -} - -static const char *xen_guest_lookup( - const struct domain_setup_info *dsi, int type) -{ - const char *xenguest_fallbacks[] = { - [XEN_ELFNOTE_ENTRY] = "VIRT_ENTRY=", - [XEN_ELFNOTE_HYPERCALL_PAGE] = "HYPERCALL_PAGE=", - [XEN_ELFNOTE_VIRT_BASE] = "VIRT_BASE=", - [XEN_ELFNOTE_PADDR_OFFSET] = "ELF_PADDR_OFFSET=", - [XEN_ELFNOTE_XEN_VERSION] = "XEN_VER=", - [XEN_ELFNOTE_GUEST_OS] = "GUEST_OS=", - [XEN_ELFNOTE_GUEST_VERSION] = "GUEST_VER=", - [XEN_ELFNOTE_LOADER] = "LOADER=", - [XEN_ELFNOTE_PAE_MODE] = "PAE=", - [XEN_ELFNOTE_FEATURES] = "FEATURES=", - [XEN_ELFNOTE_BSD_SYMTAB] = "BSD_SYMTAB=", - }; - const char *fallback; - const char *p; - - if ( !dsi->__xen_guest_string ) - return NULL; - - if ( type > sizeof(xenguest_fallbacks) ) - return NULL; - - if ( (fallback = xenguest_fallbacks[type]) == NULL ) - return NULL; - - if ( (p = strstr(dsi->__xen_guest_string,fallback)) == NULL ) - return NULL; - - return p + strlen(fallback); -} - -static const char *xen_guest_string( - const struct domain_setup_info *dsi, int type) -{ - const char *p = xen_guest_lookup(dsi, type); - - /* - * We special case this since the __xen_guest_section treats the - * mere precense of the BSD_SYMTAB string as true or false. - */ - if ( type == XEN_ELFNOTE_BSD_SYMTAB ) - return p ? "yes" : "no"; - - return p; -} - -static unsigned long long xen_guest_numeric( - const struct domain_setup_info *dsi, int type, int *defined) -{ - const char *p = xen_guest_lookup(dsi, type); - unsigned long long value; - - if ( p == NULL ) - return 0; - - errno = 0; - value = strtoull(p, NULL, 0); - if ( errno < 0 ) - return 0; - - /* We special case this since __xen_guest_section contains a PFN - * for this field not a virtual address. - */ - if (type == XEN_ELFNOTE_HYPERCALL_PAGE) - value = dsi->v_start + (value<<PAGE_SHIFT); - - *defined = 1; - return value; -} - -/* - * Interface to the Xen ELF notes. - */ -#define ELFNOTE_NAME(_n_) ((const char*)(_n_) + sizeof(*(_n_))) -#define ELFNOTE_DESC(_n_) (ELFNOTE_NAME(_n_) + (((_n_)->namesz+3)&~3)) -#define ELFNOTE_NEXT(_n_) (ELFNOTE_DESC(_n_) + (((_n_)->descsz+3)&~3)) - -static int is_xen_elfnote_section(const char *image, const Elf_Shdr *shdr) -{ - const Elf_Note *note; - - if ( shdr->sh_type != SHT_NOTE ) - return 0; - - for ( note = (const Elf_Note *)(image + shdr->sh_offset); - note < (const Elf_Note *)(image + shdr->sh_offset + shdr->sh_size); - note = (const Elf_Note *)ELFNOTE_NEXT(note) ) - { - if ( !strncmp(ELFNOTE_NAME(note), "Xen", 4) ) - return 1; - } - - return 0; -} - -static const Elf_Note *xen_elfnote_lookup( - const struct domain_setup_info *dsi, int type) -{ - const Elf_Note *note; - - if ( !dsi->__elfnote_section ) - return NULL; - - for ( note = (const Elf_Note *)dsi->__elfnote_section; - note < (const Elf_Note *)dsi->__elfnote_section_end; - note = (const Elf_Note *)ELFNOTE_NEXT(note) ) - { - if ( strncmp(ELFNOTE_NAME(note), "Xen", 4) ) - continue; - - if ( note->type == type ) - return note; - } - - return NULL; -} - -const char *xen_elfnote_string(const struct domain_setup_info *dsi, int type) -{ - const Elf_Note *note; - - if ( !dsi->__elfnote_section ) - return xen_guest_string(dsi, type); - - note = xen_elfnote_lookup(dsi, type); - if ( note == NULL ) - return NULL; - - return (const char *)ELFNOTE_DESC(note); -} - -unsigned long long xen_elfnote_numeric(const struct domain_setup_info *dsi, - int type, int *defined) -{ - const Elf_Note *note; - - *defined = 0; - - if ( !dsi->__elfnote_section ) - return xen_guest_numeric(dsi, type, defined); - - note = xen_elfnote_lookup(dsi, type); - if ( note == NULL ) - { - return 0; - } - - switch ( note->descsz ) - { - case 4: - *defined = 1; - return *(const uint32_t*)ELFNOTE_DESC(note); - case 8: - *defined = 1; - return *(const uint64_t*)ELFNOTE_DESC(note); - default: - xc_set_error(XC_INVALID_KERNEL, - "elfnotes: unknown data size %#x for numeric type note %#x\n", - note->descsz, type); - return 0; - } -} - -static int parseelfimage(const char *image, - unsigned long image_len, - struct domain_setup_info *dsi) -{ - const Elf_Ehdr *ehdr = (const Elf_Ehdr *)image; - const Elf_Phdr *phdr; - const Elf_Shdr *shdr; - Elf_Addr kernstart = ~0, kernend = 0, vaddr, virt_entry; - const char *shstrtab, *p; - int h, virt_base_defined, elf_pa_off_defined, virt_entry_defined; - - if ( !IS_ELF(*ehdr) ) - { - xc_set_error(XC_INVALID_KERNEL, - "Kernel image does not have an ELF header."); - return -EINVAL; - } - - if (ehdr->e_machine != ELFMACHINE) - { - xc_set_error(XC_INVALID_KERNEL, - "Kernel ELF architecture '%d' does not match Xen architecture '%d' (%s)", - ehdr->e_machine, ELFMACHINE, ELFMACHINE_DESC); - return -EINVAL; - } - if (ehdr->e_ident[EI_CLASS] != ELFCLASS) - { - xc_set_error(XC_INVALID_KERNEL, - "Kernel ELF wordsize '%d' does not match Xen wordsize '%d' (%s)", - ehdr->e_ident[EI_CLASS], ELFCLASS, ELFCLASS_DESC); - return -EINVAL; - } - if (ehdr->e_ident[EI_DATA] != ELFDATA) - { - xc_set_error(XC_INVALID_KERNEL, - "Kernel ELF endianness '%d' does not match Xen endianness '%d' (%s)", - ehdr->e_ident[EI_DATA], ELFDATA, ELFDATA_DESC); - return -EINVAL; - } - if (ehdr->e_type != ET_EXEC) - { - xc_set_error(XC_INVALID_KERNEL, - "Kernel ELF type '%d' does not match Xen type '%d'", - ehdr->e_type, ET_EXEC); - return -EINVAL; - } - - if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > image_len ) - { - xc_set_error(XC_INVALID_KERNEL, - "ELF program headers extend beyond end of image."); - return -EINVAL; - } - - if ( (ehdr->e_shoff + (ehdr->e_shnum*ehdr->e_shentsize)) > image_len ) - { - xc_set_error(XC_INVALID_KERNEL, - "ELF section headers extend beyond end of image."); - return -EINVAL; - } - - dsi->__elfnote_section = NULL; - dsi->__xen_guest_string = NULL; - - /* Look for .notes segment containing at least one Xen note */ - for ( h = 0; h < ehdr->e_shnum; h++ ) - { - shdr = (const Elf_Shdr *)( - image + ehdr->e_shoff + (h*ehdr->e_shentsize)); - if ( !is_xen_elfnote_section(image, shdr) ) - continue; - dsi->__elfnote_section = (const char *)image + shdr->sh_offset; - dsi->__elfnote_section_end = - (const char *)image + shdr->sh_offset + shdr->sh_size; - break; - } - - /* Fall back to looking for the special '__xen_guest' section. */ - if ( dsi->__elfnote_section == NULL ) - { - /* Find the section-header strings table. */ - if ( ehdr->e_shstrndx == SHN_UNDEF ) - { - xc_set_error(XC_INVALID_KERNEL, - "ELF image has no section-header strings table."); - return -EINVAL; - } - shdr = (const Elf_Shdr *)(image + ehdr->e_shoff + - (ehdr->e_shstrndx*ehdr->e_shentsize)); - shstrtab = image + shdr->sh_offset; - - for ( h = 0; h < ehdr->e_shnum; h++ ) - { - shdr = (const Elf_Shdr *)( - image + ehdr->e_shoff + (h*ehdr->e_shentsize)); - if ( is_xen_guest_section(shdr, shstrtab) ) - { - dsi->__xen_guest_string = - (const char *)image + shdr->sh_offset; - break; - } - } - } - - /* Check the contents of the Xen notes or guest string. */ - if ( dsi->__elfnote_section || dsi->__xen_guest_string ) - { - const char *loader = xen_elfnote_string(dsi, XEN_ELFNOTE_LOADER); - const char *guest_os = xen_elfnote_string(dsi, XEN_ELFNOTE_GUEST_OS); - const char *xen_version = - xen_elfnote_string(dsi, XEN_ELFNOTE_XEN_VERSION); - - if ( ( loader == NULL || strncmp(loader, "generic", 7) ) && - ( guest_os == NULL || strncmp(guest_os, "linux", 5) ) ) - { - xc_set_error(XC_INVALID_KERNEL, - "Will only load images built for the generic loader " - "or Linux images"); - return -EINVAL; - } - - if ( xen_version == NULL || strncmp(xen_version, "xen-3.0", 7) ) - { - xc_set_error(XC_INVALID_KERNEL, - "Will only load images built for Xen v3.0"); - return -EINVAL; - } - } - else - { -#if defined(__x86_64__) || defined(__i386__) - xc_set_error(XC_INVALID_KERNEL, - "Not a Xen-ELF image: " - "No ELF notes or '__xen_guest' section found."); - return -EINVAL; -#endif - } - - /* - * A "bimodal" ELF note indicates the kernel will adjust to the current - * paging mode, including handling extended cr3 syntax. If we have ELF - * notes then PAE=yes implies that we must support the extended cr3 syntax. - * Otherwise we need to find the [extended-cr3] syntax in the __xen_guest - * string. We use strstr() to look for "bimodal" to allow guests to use - * "yes,bimodal" or "no,bimodal" for compatibility reasons. - */ - - dsi->pae_kernel = PAEKERN_no; - if ( dsi->__elfnote_section ) - { - p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE); - if ( p != NULL && strstr(p, "bimodal") != NULL ) - dsi->pae_kernel = PAEKERN_bimodal; - else if ( p != NULL && strncmp(p, "yes", 3) == 0 ) - dsi->pae_kernel = PAEKERN_extended_cr3; - - } - else - { - p = xen_guest_lookup(dsi, XEN_ELFNOTE_PAE_MODE); - if ( p != NULL && strncmp(p, "yes", 3) == 0 ) - { - dsi->pae_kernel = PAEKERN_yes; - if ( !strncmp(p+3, "[extended-cr3]", 14) ) - dsi->pae_kernel = PAEKERN_extended_cr3; - } - } - - /* Initial guess for v_start is 0 if it is not explicitly defined. */ - dsi->v_start = - xen_elfnote_numeric(dsi, XEN_ELFNOTE_VIRT_BASE, &virt_base_defined); - if ( !virt_base_defined ) - dsi->v_start = 0; - - /* - * If we are using the legacy __xen_guest section then elf_pa_off - * defaults to v_start in order to maintain compatibility with - * older hypervisors which set padd in the ELF header to - * virt_base. - * - * If we are using the modern ELF notes interface then the default - * is 0. - */ - dsi->elf_paddr_offset = xen_elfnote_numeric(dsi, XEN_ELFNOTE_PADDR_OFFSET, - &elf_pa_off_defined); - if ( !elf_pa_off_defined ) - { - if ( dsi->__elfnote_section ) - dsi->elf_paddr_offset = 0; - else - dsi->elf_paddr_offset = dsi->v_start; - } - - if ( elf_pa_off_defined && !virt_base_defined ) - { - xc_set_error(XC_INVALID_KERNEL, - "Neither ELF_PADDR_OFFSET nor VIRT_BASE found in ELF " - " notes or __xen_guest section."); - return -EINVAL; - } - - for ( h = 0; h < ehdr->e_phnum; h++ ) - { - phdr = (const Elf_Phdr *)( - image + ehdr->e_phoff + (h*ehdr->e_phentsize)); - if ( !is_loadable_phdr(phdr) ) - continue; - vaddr = phdr->p_paddr - dsi->elf_paddr_offset + dsi->v_start; - if ( (vaddr + phdr->p_memsz) < vaddr ) - { - xc_set_error(XC_INVALID_KERNEL, - "ELF program header %d is too large.", h); - return -EINVAL; - } - - if ( vaddr < kernstart ) - kernstart = vaddr; - if ( (vaddr + phdr->p_memsz) > kernend ) - kernend = vaddr + phdr->p_memsz; - } - - dsi->v_kernentry = ehdr->e_entry; - - virt_entry = - xen_elfnote_numeric(dsi, XEN_ELFNOTE_ENTRY, &virt_entry_defined); - if ( virt_entry_defined ) - dsi->v_kernentry = virt_entry; - - if ( (kernstart > kernend) || - (dsi->v_kernentry < kernstart) || - (dsi->v_kernentry > kernend) || - (dsi->v_start > kernstart) ) - { - xc_set_error(XC_INVALID_KERNEL, - "ELF start or entries are out of bounds."); - return -EINVAL; - } - - p = xen_elfnote_string(dsi, XEN_ELFNOTE_BSD_SYMTAB); - if ( p != NULL && strncmp(p, "yes", 3) == 0 ) - dsi->load_symtab = 1; - - dsi->v_kernstart = kernstart; - dsi->v_kernend = kernend; - dsi->v_end = dsi->v_kernend; - - loadelfsymtab(image, 0, 0, NULL, dsi); - - return 0; -} - -static int -loadelfimage( - const char *image, unsigned long elfsize, int xch, uint32_t dom, - xen_pfn_t *parray, struct domain_setup_info *dsi) -{ - const Elf_Ehdr *ehdr = (const Elf_Ehdr *)image; - const Elf_Phdr *phdr; - int h; - - char *va; - unsigned long pa, done, chunksz; - - for ( h = 0; h < ehdr->e_phnum; h++ ) - { - phdr = (const 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->elf_paddr_offset; - va = xc_map_foreign_range( - xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]); - if ( va == NULL ) - return -1; - 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->elf_paddr_offset; - va = xc_map_foreign_range( - xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]); - if ( va == NULL ) - return -1; - 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( - const char *image, int xch, uint32_t dom, xen_pfn_t *parray, - struct domain_setup_info *dsi) -{ - const Elf_Ehdr *ehdr = (const Elf_Ehdr *)image; - Elf_Ehdr *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: - free(p); - - return 0; -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/xc_private.c --- a/tools/libxc/xc_private.c Wed Feb 14 12:18:32 2007 -0800 +++ b/tools/libxc/xc_private.c Thu Feb 15 10:25:39 2007 +0000 @@ -377,26 +377,6 @@ int xc_clear_domain_page(int xc_handle, return 0; } -void xc_map_memcpy(unsigned long dst, const char *src, unsigned long size, - int xch, uint32_t dom, xen_pfn_t *parray, - unsigned long vstart) -{ - char *va; - unsigned long chunksz, done, pa; - - for ( done = 0; done < size; done += chunksz ) - { - pa = dst + done - vstart; - va = xc_map_foreign_range( - xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]); - chunksz = size - done; - if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) ) - chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1)); - memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz); - munmap(va, PAGE_SIZE); - } -} - int xc_domctl(int xc_handle, struct xen_domctl *domctl) { return do_domctl(xc_handle, domctl); diff -r 82f66bc01da2 -r 0d488e53446a tools/libxc/xg_private.h --- a/tools/libxc/xg_private.h Wed Feb 14 12:18:32 2007 -0800 +++ b/tools/libxc/xg_private.h Thu Feb 15 10:25:39 2007 +0000 @@ -139,92 +139,15 @@ typedef l4_pgentry_64_t l4_pgentry_t; #define PAGE_SIZE_IA64 (1UL << PAGE_SHIFT_IA64) #define PAGE_MASK_IA64 (~(PAGE_SIZE_IA64-1)) -struct domain_setup_info -{ - uint64_t v_start; - uint64_t v_end; - uint64_t v_kernstart; - uint64_t v_kernend; - uint64_t v_kernentry; - - uint64_t elf_paddr_offset; - #define PAEKERN_no 0 #define PAEKERN_yes 1 #define PAEKERN_extended_cr3 2 #define PAEKERN_bimodal 3 - unsigned int pae_kernel; - - unsigned int load_symtab; - unsigned long symtab_addr; - unsigned long symtab_len; - - /* - * Only one of __elfnote_* or __xen_guest_string will be - * non-NULL. - * - * You should use the xen_elfnote_* accessors below in order to - * pickup the correct one and retain backwards compatibility. - */ - const void *__elfnote_section, *__elfnote_section_end; - const char *__xen_guest_string; -}; - -typedef int (*parseimagefunc)(const char *image, unsigned long image_size, - struct domain_setup_info *dsi); -typedef int (*loadimagefunc)(const char *image, unsigned long image_size, - int xch, - uint32_t dom, xen_pfn_t *parray, - struct domain_setup_info *dsi); - -/* - * If an ELF note of the given type is found then the value contained - * in the note is returned and *defined is set to non-zero. If no such - * note is found then *defined is set to 0 and 0 is returned. - */ -extern unsigned long long xen_elfnote_numeric(const struct domain_setup_info *dsi, - int type, int *defined); - -/* - * If an ELF note of the given type is found then the string contained - * in the value is returned, otherwise NULL is returned. - */ -extern const char * xen_elfnote_string(const struct domain_setup_info *dsi, - int type); - -struct load_funcs -{ - parseimagefunc parseimage; - loadimagefunc loadimage; -}; - -#define mfn_mapper_queue_size 128 - -typedef struct mfn_mapper { - int xc_handle; - int size; - int prot; - int error; - int max_queue_size; - void * addr; - privcmd_mmap_t ioctl; - -} mfn_mapper_t; int xc_copy_to_domain_page(int xc_handle, uint32_t domid, unsigned long dst_pfn, const char *src_page); -void xc_map_memcpy(unsigned long dst, const char *src, unsigned long size, - int xch, uint32_t dom, xen_pfn_t *parray, - unsigned long vstart); - int pin_table(int xc_handle, unsigned int type, unsigned long mfn, domid_t dom); -/* image loading */ -int probe_elf(const char *image, unsigned long image_size, - struct load_funcs *funcs); -int probe_bin(const char *image, unsigned long image_size, - struct load_funcs *funcs); - #endif /* XG_PRIVATE_H */ diff -r 82f66bc01da2 -r 0d488e53446a xen/common/elf.c --- a/xen/common/elf.c Wed Feb 14 12:18:32 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,520 +0,0 @@ -/****************************************************************************** - * elf.c - * - * Generic Elf-loading routines. - */ - -#include <xen/config.h> -#include <xen/init.h> -#include <xen/lib.h> -#include <xen/mm.h> -#include <xen/elf.h> -#include <xen/sched.h> -#include <xen/errno.h> -#include <xen/inttypes.h> - -#include <public/elfnote.h> - -static void loadelfsymtab(struct domain_setup_info *dsi, int doload); -static inline int is_loadable_phdr(const Elf_Phdr *phdr) -{ - return ((phdr->p_type == PT_LOAD) && - ((phdr->p_flags & (PF_W|PF_X)) != 0)); -} - -/* - * Fallback for kernels containing only the legacy __xen_guest string - * and no ELF notes. - */ -static int is_xen_guest_section(const Elf_Shdr *shdr, const char *shstrtab) -{ - return strcmp(&shstrtab[shdr->sh_name], "__xen_guest") == 0; -} - -static const char *xen_guest_lookup(struct domain_setup_info *dsi, int type) -{ - const char *xenguest_fallbacks[] = { - [XEN_ELFNOTE_ENTRY] = "VIRT_ENTRY=", - [XEN_ELFNOTE_HYPERCALL_PAGE] = "HYPERCALL_PAGE=", - [XEN_ELFNOTE_VIRT_BASE] = "VIRT_BASE=", - [XEN_ELFNOTE_PADDR_OFFSET] = "ELF_PADDR_OFFSET=", - [XEN_ELFNOTE_XEN_VERSION] = "XEN_VER=", - [XEN_ELFNOTE_GUEST_OS] = "GUEST_OS=", - [XEN_ELFNOTE_GUEST_VERSION] = "GUEST_VER=", - [XEN_ELFNOTE_LOADER] = "LOADER=", - [XEN_ELFNOTE_PAE_MODE] = "PAE=", - [XEN_ELFNOTE_FEATURES] = "FEATURES=", - [XEN_ELFNOTE_BSD_SYMTAB] = "BSD_SYMTAB=", - }; - const char *fallback; - const char *p; - - if ( !dsi->__xen_guest_string ) - return NULL; - - if ( type > sizeof(xenguest_fallbacks) ) - return NULL; - - if ( (fallback = xenguest_fallbacks[type]) == NULL ) - return NULL; - - if ( (p = strstr(dsi->__xen_guest_string,fallback)) == NULL ) - return NULL; - - return p + strlen(fallback); -} - -static const char *xen_guest_string(struct domain_setup_info *dsi, int type) -{ - const char *p = xen_guest_lookup(dsi, type); - - /* - * We special case this since the __xen_guest_section treats the - * mere precense of the BSD_SYMTAB string as true or false. - */ - if ( type == XEN_ELFNOTE_BSD_SYMTAB ) - return p ? "yes" : "no"; - - return p; -} - -static unsigned long long xen_guest_numeric(struct domain_setup_info *dsi, - int type, int *defined) -{ - const char *p = xen_guest_lookup(dsi, type); - unsigned long long value; - - if ( p == NULL ) - return 0; - - value = simple_strtoull(p, NULL, 0); - - /* We special case this since __xen_guest_section contains a PFN - * for this field not a virtual address. - */ - if (type == XEN_ELFNOTE_HYPERCALL_PAGE) - value = dsi->v_start + (value<<PAGE_SHIFT); - - *defined = 1; - return value; -} - - -static int is_xen_elfnote_section(const char *image, const Elf_Shdr *shdr) -{ - const Elf_Note *note; - - if ( shdr->sh_type != SHT_NOTE ) - return 0; - - for ( note = (const Elf_Note *)(image + shdr->sh_offset); - note < (const Elf_Note *)(image + shdr->sh_offset + shdr->sh_size); - note = ELFNOTE_NEXT(note) ) - { - if ( !strncmp(ELFNOTE_NAME(note), "Xen", 4) ) - return 1; - } - - return 0; -} - -static const Elf_Note *xen_elfnote_lookup( - struct domain_setup_info *dsi, int type) -{ - const Elf_Note *note; - - if ( !dsi->__elfnote_section ) - return NULL; - - for ( note = (const Elf_Note *)dsi->__elfnote_section; - note < (const Elf_Note *)dsi->__elfnote_section_end; - note = ELFNOTE_NEXT(note) ) - { - if ( strncmp(ELFNOTE_NAME(note), "Xen", 4) ) - continue; - - if ( note->type == type ) - return note; - } - - return NULL; -} - -const char *xen_elfnote_string(struct domain_setup_info *dsi, int type) -{ - const Elf_Note *note; - - if ( !dsi->__elfnote_section ) - return xen_guest_string(dsi, type); - - note = xen_elfnote_lookup(dsi, type); - if ( note == NULL ) - return NULL; - - return (const char *)ELFNOTE_DESC(note); -} - -unsigned long long xen_elfnote_numeric(struct domain_setup_info *dsi, - int type, int *defined) -{ - const Elf_Note *note; - - *defined = 0; - - if ( !dsi->__elfnote_section ) - return xen_guest_numeric(dsi, type, defined); - - note = xen_elfnote_lookup(dsi, type); - if ( note == NULL ) - { - return 0; - } - - switch ( note->descsz ) - { - case 4: - *defined = 1; - return *(const uint32_t*)ELFNOTE_DESC(note); - case 8: - *defined = 1; - return *(const uint64_t*)ELFNOTE_DESC(note); - default: - printk("ERROR: unknown data size %#x for numeric type note %#x\n", - note->descsz, type); - return 0; - } -} - -int parseelfimage(struct domain_setup_info *dsi) -{ - const Elf_Ehdr *ehdr = (const Elf_Ehdr *)dsi->image_addr; - const Elf_Phdr *phdr; - const Elf_Shdr *shdr; - Elf_Addr kernstart = ~0, kernend = 0, vaddr, virt_entry; - const char *shstrtab, *p; - const char *image = (char *)dsi->image_addr; - const unsigned long image_len = dsi->image_len; - int h, virt_base_defined, elf_pa_off_defined, virt_entry_defined; - - if ( !elf_sanity_check(ehdr) ) - return -ENOSYS; - - if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > image_len ) - { - printk("ELF program headers extend beyond end of image.\n"); - return -EINVAL; - } - - if ( (ehdr->e_shoff + (ehdr->e_shnum*ehdr->e_shentsize)) > image_len ) - { - printk("ELF section headers extend beyond end of image.\n"); - return -EINVAL; - } - - dsi->__elfnote_section = NULL; - dsi->__xen_guest_string = NULL; - - /* Look for .notes segment containing at least one Xen note */ - for ( h = 0; h < ehdr->e_shnum; h++ ) - { - shdr = (const Elf_Shdr *)( - image + ehdr->e_shoff + (h*ehdr->e_shentsize)); - if ( !is_xen_elfnote_section(image, shdr) ) - continue; - dsi->__elfnote_section = (const char *)image + shdr->sh_offset; - dsi->__elfnote_section_end = - (const char *)image + shdr->sh_offset + shdr->sh_size; - break; - } - - /* Fall back to looking for the special '__xen_guest' section. */ - if ( dsi->__elfnote_section == NULL ) - { - /* Find the section-header strings table. */ - if ( ehdr->e_shstrndx == SHN_UNDEF ) - { - printk("ELF image has no section-header strings table.\n"); - return -EINVAL; - } - shdr = (const Elf_Shdr *)(image + ehdr->e_shoff + - (ehdr->e_shstrndx*ehdr->e_shentsize)); - shstrtab = image + shdr->sh_offset; - - for ( h = 0; h < ehdr->e_shnum; h++ ) - { - shdr = (const Elf_Shdr *)( - image + ehdr->e_shoff + (h*ehdr->e_shentsize)); - if ( is_xen_guest_section(shdr, shstrtab) ) - { - dsi->__xen_guest_string = - (const char *)image + shdr->sh_offset; - break; - } - } - } - - /* Check the contents of the Xen notes or guest string. */ - if ( dsi->__elfnote_section || dsi->__xen_guest_string ) - { - const char *loader = xen_elfnote_string(dsi, XEN_ELFNOTE_LOADER); - const char *guest_os = xen_elfnote_string(dsi, XEN_ELFNOTE_GUEST_OS); - const char *xen_version = - xen_elfnote_string(dsi, XEN_ELFNOTE_XEN_VERSION); - - if ( ( loader == NULL || strncmp(loader, "generic", 7) ) && - ( guest_os == NULL || strncmp(guest_os, "linux", 5) ) ) - { - printk("ERROR: Will only load images built for the generic " - "loader or Linux images"); - return -EINVAL; - } - - if ( xen_version == NULL || strncmp(xen_version, "xen-3.0", 7) ) - { - printk("ERROR: Xen will only load images built for Xen v3.0\n"); - } - } - else - { -#if defined(__x86_64__) || defined(__i386__) - printk("ERROR: Not a Xen-ELF image: " - "No ELF notes or '__xen_guest' section found.\n"); - return -EINVAL; -#endif - } - - /* - * A "bimodal" ELF note indicates the kernel will adjust to the - * current paging mode, including handling extended cr3 syntax. - * If we have ELF notes then PAE=yes implies that we must support - * the extended cr3 syntax. Otherwise we need to find the - * [extended-cr3] syntax in the __xen_guest string. - */ - dsi->pae_kernel = PAEKERN_no; - if ( dsi->__elfnote_section ) - { - p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE); - if ( p != NULL && strstr(p, "bimodal") != NULL ) - dsi->pae_kernel = PAEKERN_bimodal; - else if ( p != NULL && strncmp(p, "yes", 3) == 0 ) - dsi->pae_kernel = PAEKERN_extended_cr3; - } - else - { - p = xen_guest_lookup(dsi, XEN_ELFNOTE_PAE_MODE); - if ( p != NULL && strncmp(p, "yes", 3) == 0 ) - { - dsi->pae_kernel = PAEKERN_yes; - if ( !strncmp(p+3, "[extended-cr3]", 14) ) - dsi->pae_kernel = PAEKERN_extended_cr3; - } - } - - /* Initial guess for v_start is 0 if it is not explicitly defined. */ - dsi->v_start = - xen_elfnote_numeric(dsi, XEN_ELFNOTE_VIRT_BASE, &virt_base_defined); - if ( !virt_base_defined ) - dsi->v_start = 0; - - /* - * If we are using the legacy __xen_guest section then elf_pa_off - * defaults to v_start in order to maintain compatibility with - * older hypervisors which set padd in the ELF header to - * virt_base. - * - * If we are using the modern ELF notes interface then the default - * is 0. - */ - dsi->elf_paddr_offset = xen_elfnote_numeric(dsi, XEN_ELFNOTE_PADDR_OFFSET, - &elf_pa_off_defined); - if ( !elf_pa_off_defined ) - { - if ( dsi->__elfnote_section ) - dsi->elf_paddr_offset = 0; - else - dsi->elf_paddr_offset = dsi->v_start; - } - - if ( elf_pa_off_defined && !virt_base_defined ) - { - printk("ERROR: Neither ELF_PADDR_OFFSET nor VIRT_BASE found in" - " Xen ELF notes.\n"); - return -EINVAL; - } - - for ( h = 0; h < ehdr->e_phnum; h++ ) - { - phdr = (const Elf_Phdr *)( - image + ehdr->e_phoff + (h*ehdr->e_phentsize)); - if ( !is_loadable_phdr(phdr) ) - continue; - vaddr = phdr->p_paddr - dsi->elf_paddr_offset + dsi->v_start; - if ( (vaddr + phdr->p_memsz) < vaddr ) - { - printk("ERROR: ELF program header %d is too large.\n", h); - return -EINVAL; - } - - if ( vaddr < kernstart ) - kernstart = vaddr; - if ( (vaddr + phdr->p_memsz) > kernend ) - kernend = vaddr + phdr->p_memsz; - } - - dsi->v_kernentry = ehdr->e_entry; - - virt_entry = - xen_elfnote_numeric(dsi, XEN_ELFNOTE_ENTRY, &virt_entry_defined); - if ( virt_entry_defined ) - dsi->v_kernentry = virt_entry; - - if ( (kernstart > kernend) || - (dsi->v_kernentry < kernstart) || - (dsi->v_kernentry > kernend) || - (dsi->v_start > kernstart) ) - { - printk("ERROR: ELF start or entries are out of bounds.\n"); - return -EINVAL; - } - - p = xen_elfnote_string(dsi, XEN_ELFNOTE_BSD_SYMTAB); - if ( p != NULL && strncmp(p, "yes", 3) == 0 ) - dsi->load_symtab = 1; - - dsi->v_kernstart = kernstart; - dsi->v_kernend = kernend; - dsi->v_end = dsi->v_kernend; - - loadelfsymtab(dsi, 0); - - return 0; -} - -int loadelfimage(struct domain_setup_info *dsi) -{ - char *image = (char *)dsi->image_addr; - Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr; - Elf_Phdr *phdr; - unsigned long vaddr; - int h; - - 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; - vaddr = phdr->p_paddr - dsi->elf_paddr_offset + dsi->v_start; - if ( phdr->p_filesz != 0 ) - memcpy((char *)vaddr, image + phdr->p_offset, phdr->p_filesz); - if ( phdr->p_memsz > phdr->p_filesz ) - memset((char *)vaddr + phdr->p_filesz, 0, - phdr->p_memsz - phdr->p_filesz); - } - - loadelfsymtab(dsi, 1); - - return 0; -} - -#define ELFROUND (ELFSIZE / 8) - -static void loadelfsymtab(struct domain_setup_info *dsi, int doload) -{ - Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr, *sym_ehdr; - Elf_Shdr *shdr; - unsigned long maxva, symva; - char *p, *image = (char *)dsi->image_addr; - int h, i; - - if ( !dsi->load_symtab ) - return; - - 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); - if ( doload ) - { - p = (void *)symva; - shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr)); - memcpy(shdr, image + ehdr->e_shoff, ehdr->e_shnum*sizeof(Elf_Shdr)); - } - else - { - p = NULL; - shdr = (Elf_Shdr *)(image + ehdr->e_shoff); - } - - 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 ) - { - if (doload) { - shdr[h].sh_offset = 0; - } - continue; - } - } - - if ( (shdr[h].sh_type == SHT_STRTAB) || - (shdr[h].sh_type == SHT_SYMTAB) ) - { - if (doload) { - memcpy((void *)maxva, image + shdr[h].sh_offset, - shdr[h].sh_size); - - /* 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); - } - - if ( doload ) - shdr[h].sh_name = 0; /* Name is NULL. */ - } - - if ( dsi->symtab_len == 0 ) - { - dsi->symtab_addr = 0; - return; - } - - if ( doload ) - { - *(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; - } - - dsi->symtab_len = maxva - dsi->symtab_addr; - dsi->v_end = maxva; -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |