aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-03-24 11:06:48 +0000
committerKeir Fraser <keir.fraser@citrix.com>2010-03-24 11:06:48 +0000
commit13e06c39087d32d6bc592cb30059828fc4257f8f (patch)
tree8ef3a5fc1a3e4cd56adb25e42464f4e3e297d243
parent6a9ca8b206be15720a1a59185ce5acf333ff72e0 (diff)
downloadxen-13e06c39087d32d6bc592cb30059828fc4257f8f.tar.gz
xen-13e06c39087d32d6bc592cb30059828fc4257f8f.tar.bz2
xen-13e06c39087d32d6bc592cb30059828fc4257f8f.zip
Fix 21051:bcc09eb7379f "x86_32: Relocate multiboot modules to below 1GB."
Copy the modules in ascending order in memory, rather than decsending order. This reduces the likelihood of the second relocation (in setup.c) corrupting modules through accidental overwriting. Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--xen/arch/x86/boot/reloc.c36
1 files changed, 22 insertions, 14 deletions
diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c
index 233a94f347..47b558b29c 100644
--- a/xen/arch/x86/boot/reloc.c
+++ b/xen/arch/x86/boot/reloc.c
@@ -68,29 +68,37 @@ multiboot_info_t *reloc(multiboot_info_t *mbi_old)
{
module_t *mods = reloc_mbi_struct(
(module_t *)mbi->mods_addr, mbi->mods_count * sizeof(module_t));
+ u32 max_addr = 0;
+
mbi->mods_addr = (u32)mods;
+
for ( i = 0; i < mbi->mods_count; i++ )
{
-#if XEN_BITSPERLONG == 32
- /*
- * 32-bit Xen only maps bottom 1GB of memory at boot time.
- * Relocate modules which extend beyond this (GRUB2 in particular
- * likes to place modules as high as possible below 4GB).
- */
+ if ( mods[i].string )
+ mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string);
+ if ( mods[i].mod_end > max_addr )
+ max_addr = mods[i].mod_end;
+ }
+
+ /*
+ * 32-bit Xen only maps bottom 1GB of memory at boot time. Relocate
+ * modules which extend beyond this (GRUB2 in particular likes to
+ * place modules as high as possible below 4GB).
+ */
#define BOOTMAP_END (1ul<<30) /* 1GB */
- static void *mod_alloc = (void *)BOOTMAP_END;
- u32 mod_len = mods[i].mod_end - mods[i].mod_start;
- if ( mods[i].mod_end > BOOTMAP_END )
+ if ( (XEN_BITSPERLONG == 32) && (max_addr > BOOTMAP_END) )
+ {
+ char *mod_alloc = (char *)BOOTMAP_END;
+ for ( i = 0; i < mbi->mods_count; i++ )
+ mod_alloc -= mods[i].mod_end - mods[i].mod_start;
+ for ( i = 0; i < mbi->mods_count; i++ )
{
- mod_alloc = (void *)
- (((unsigned long)mod_alloc - mod_len) & ~15ul);
+ u32 mod_len = mods[i].mod_end - mods[i].mod_start;
mods[i].mod_start = (u32)memcpy(
mod_alloc, (char *)mods[i].mod_start, mod_len);
mods[i].mod_end = mods[i].mod_start + mod_len;
+ mod_alloc += mod_len;
}
-#endif
- if ( mods[i].string )
- mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string);
}
}