aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>2006-05-11 17:30:50 +0100
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>2006-05-11 17:30:50 +0100
commit15efc30a115d80da597e88dabfd8bd4914645b35 (patch)
treec4a7c7ae0ccdaed8897c7f7e1690c30932ae1158 /tools
parent7e8cc1fb7f2b24c6c7724c231f72219f8034041a (diff)
downloadxen-15efc30a115d80da597e88dabfd8bd4914645b35.tar.gz
xen-15efc30a115d80da597e88dabfd8bd4914645b35.tar.bz2
xen-15efc30a115d80da597e88dabfd8bd4914645b35.zip
Add support to domain builders for loading kernels with physical addresses in the elf paddr and entry fields.
Add a new __xen_guest header field to distinguish between kernels with the previous use of the paddr field and the new use. Add a new __xen_guest header field to control the kernel entry point, since the elf header entry field now points to a physical address. This header field is also useful for supporting alternative entry points in kernel images which run both on xen and native. Also add a kernel config option to control whether the resulting kernel should include compatibility code to run on Xen 3.0.2 or whether such code such be left out, resulting in a kernel which will only run on newer Xen versions. Default to having compatibility enabled. Kernels built with the new use of the elf header fields would otherwise not work on Xen versions prior to this changeset. Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
Diffstat (limited to 'tools')
-rw-r--r--tools/libxc/xc_load_elf.c40
-rw-r--r--tools/libxc/xg_private.h5
2 files changed, 30 insertions, 15 deletions
diff --git a/tools/libxc/xc_load_elf.c b/tools/libxc/xc_load_elf.c
index a60fd42d2a..610f0a53df 100644
--- a/tools/libxc/xc_load_elf.c
+++ b/tools/libxc/xc_load_elf.c
@@ -58,7 +58,7 @@ static int parseelfimage(const char *image,
Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
Elf_Phdr *phdr;
Elf_Shdr *shdr;
- unsigned long kernstart = ~0UL, kernend=0UL;
+ unsigned long kernstart = ~0UL, kernend=0UL, vaddr, virt_base;
const char *shstrtab;
char *guestinfo=NULL, *p;
int h;
@@ -148,35 +148,47 @@ static int parseelfimage(const char *image,
dsi->xen_guest_string = guestinfo;
+ virt_base = 0;
+ if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
+ virt_base = strtoul(p+10, &p, 0);
+ dsi->elf_paddr_offset = virt_base;
+ if ( (p = strstr(guestinfo, "ELF_PADDR_OFFSET=")) != NULL )
+ dsi->elf_paddr_offset = strtoul(p+17, &p, 0);
+
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;
+ vaddr = phdr->p_paddr - dsi->elf_paddr_offset + virt_base;
+ if ( vaddr < kernstart )
+ kernstart = vaddr;
+ if ( (vaddr + phdr->p_memsz) > kernend )
+ kernend = vaddr + phdr->p_memsz;
}
+ if ( virt_base )
+ dsi->v_start = virt_base;
+ else
+ dsi->v_start = kernstart;
+
+ dsi->v_kernentry = ehdr->e_entry;
+ if ( (p = strstr(guestinfo, "VIRT_ENTRY=")) != NULL )
+ dsi->v_kernentry = strtoul(p+11, &p, 0);
+
if ( (kernstart > kernend) ||
- (ehdr->e_entry < kernstart) ||
- (ehdr->e_entry > kernend) )
+ (dsi->v_kernentry < kernstart) ||
+ (dsi->v_kernentry > 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);
@@ -204,7 +216,7 @@ loadelfimage(
for ( done = 0; done < phdr->p_filesz; done += chunksz )
{
- pa = (phdr->p_paddr + done) - dsi->v_start;
+ pa = (phdr->p_paddr + done) - dsi->elf_paddr_offset;
va = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
chunksz = phdr->p_filesz - done;
@@ -217,7 +229,7 @@ loadelfimage(
for ( ; done < phdr->p_memsz; done += chunksz )
{
- pa = (phdr->p_paddr + done) - dsi->v_start;
+ pa = (phdr->p_paddr + done) - dsi->elf_paddr_offset;
va = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
chunksz = phdr->p_memsz - done;
diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h
index f7e8efac5b..4284e0f79b 100644
--- a/tools/libxc/xg_private.h
+++ b/tools/libxc/xg_private.h
@@ -136,8 +136,11 @@ struct domain_setup_info
unsigned long v_kernend;
unsigned long v_kernentry;
- unsigned int load_symtab;
+ unsigned long elf_paddr_offset;
+
unsigned int pae_kernel;
+
+ unsigned int load_symtab;
unsigned long symtab_addr;
unsigned long symtab_len;