From 4b2ec20b411f9829eafc639963a2f0812d8e046d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 21 Apr 2010 19:13:45 +0200 Subject: [PATCH] Second part of p2v support --- include/grub/relocator.h | 20 +++- include/grub/relocator_private.h | 2 +- lib/i386/relocator.c | 41 ++++---- lib/relocator.c | 42 +++++--- loader/i386/bsd.c | 159 ++++++++++++++++++++----------- loader/i386/bsdXX.c | 51 ++++++---- loader/i386/linux.c | 44 +++++---- loader/i386/multiboot_mbi.c | 10 +- loader/i386/pc/linux.c | 48 ++++++---- loader/i386/pc/ntldr.c | 24 +++-- loader/multiboot.c | 24 +++-- loader/multiboot_elfxx.c | 48 ++++++---- loader/multiboot_mbi2.c | 12 ++- loader/xnu.c | 4 +- loader/xnu_resume.c | 44 +++++---- 15 files changed, 361 insertions(+), 212 deletions(-) diff --git a/include/grub/relocator.h b/include/grub/relocator.h index 32bab7053..89e746088 100644 --- a/include/grub/relocator.h +++ b/include/grub/relocator.h @@ -21,19 +21,29 @@ #include #include +#include struct grub_relocator; +struct grub_relocator_chunk; +typedef const struct grub_relocator_chunk *grub_relocator_chunk_t; struct grub_relocator *grub_relocator_new (void); grub_err_t -grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, void **src, - grub_addr_t target, grub_size_t size); +grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, + grub_relocator_chunk_t *out, + grub_phys_addr_t target, grub_size_t size); + +void * +get_virtual_current_address (grub_relocator_chunk_t in); +grub_phys_addr_t +get_physical_target_address (grub_relocator_chunk_t in); grub_err_t -grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src, - grub_addr_t *target, - grub_addr_t min_addr, grub_addr_t max_addr, +grub_relocator_alloc_chunk_align (struct grub_relocator *rel, + grub_relocator_chunk_t *out, + grub_phys_addr_t min_addr, + grub_phys_addr_t max_addr, grub_size_t size, grub_size_t align, int preference); diff --git a/include/grub/relocator_private.h b/include/grub/relocator_private.h index d12a0f05a..10e445bfe 100644 --- a/include/grub/relocator_private.h +++ b/include/grub/relocator_private.h @@ -32,7 +32,7 @@ void grub_cpu_relocator_init (void); grub_err_t grub_relocator_prepare_relocs (struct grub_relocator *rel, - void *addr, + grub_addr_t addr, void **relstart, grub_size_t *relsize); void grub_cpu_relocator_forward (void *rels, void *src, void *tgt, grub_size_t size); diff --git a/lib/i386/relocator.c b/lib/i386/relocator.c index 5dd4cde75..55e6b5578 100644 --- a/lib/i386/relocator.c +++ b/lib/i386/relocator.c @@ -84,12 +84,6 @@ grub_size_t grub_relocator_jumper_size = 12; grub_size_t grub_relocator_jumper_size = 7; #endif -static inline void * -ptov (grub_addr_t a) -{ - return (void *) a; -} - void grub_cpu_relocator_init (void) { @@ -154,12 +148,11 @@ grub_err_t grub_relocator32_boot (struct grub_relocator *rel, struct grub_relocator32_state state) { - grub_phys_addr_t target; - void *src; grub_err_t err; void *relst; + grub_relocator_chunk_t ch; - err = grub_relocator_alloc_chunk_align (rel, &src, &target, 0, + err = grub_relocator_alloc_chunk_align (rel, &ch, 0, (0xffffffff - RELOCATOR_SIZEOF (32)) + 1, RELOCATOR_SIZEOF (32), 16, GRUB_RELOCATOR_PREFERENCE_NONE); @@ -174,9 +167,11 @@ grub_relocator32_boot (struct grub_relocator *rel, grub_relocator32_esp = state.esp; grub_relocator32_esi = state.esi; - grub_memmove (src, &grub_relocator32_start, RELOCATOR_SIZEOF (32)); + grub_memmove (get_virtual_current_address (ch), &grub_relocator32_start, + RELOCATOR_SIZEOF (32)); - err = grub_relocator_prepare_relocs (rel, ptov (target), &relst, NULL); + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); if (err) return err; @@ -191,12 +186,11 @@ grub_err_t grub_relocator16_boot (struct grub_relocator *rel, struct grub_relocator16_state state) { - grub_phys_addr_t target; - void *src; grub_err_t err; void *relst; + grub_relocator_chunk_t ch; - err = grub_relocator_alloc_chunk_align (rel, &src, &target, 0, + err = grub_relocator_alloc_chunk_align (rel, &ch, 0, 0xa0000 - RELOCATOR_SIZEOF (16), RELOCATOR_SIZEOF (16), 16, GRUB_RELOCATOR_PREFERENCE_NONE); @@ -216,12 +210,16 @@ grub_relocator16_boot (struct grub_relocator *rel, grub_relocator16_edx = state.edx; - grub_memmove (src, &grub_relocator16_start, RELOCATOR_SIZEOF (16)); + grub_memmove (get_virtual_current_address (ch), &grub_relocator16_start, + RELOCATOR_SIZEOF (16)); - err = grub_relocator_prepare_relocs (rel, ptov (target), &relst, NULL); + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); if (err) return err; + grub_printf ("%p\n", relst); + asm volatile ("cli"); ((void (*) (void)) relst) (); @@ -234,12 +232,11 @@ grub_relocator64_boot (struct grub_relocator *rel, struct grub_relocator64_state state, grub_addr_t min_addr, grub_addr_t max_addr) { - grub_phys_addr_t target; - void *src; grub_err_t err; void *relst; + grub_relocator_chunk_t ch; - err = grub_relocator_alloc_chunk_align (rel, &src, &target, min_addr, + err = grub_relocator_alloc_chunk_align (rel, &ch, min_addr, max_addr - RELOCATOR_SIZEOF (64), RELOCATOR_SIZEOF (64), 16, GRUB_RELOCATOR_PREFERENCE_NONE); @@ -255,9 +252,11 @@ grub_relocator64_boot (struct grub_relocator *rel, grub_relocator64_rsi = state.rsi; grub_relocator64_cr3 = state.cr3; - grub_memmove (src, &grub_relocator64_start, RELOCATOR_SIZEOF (64)); + grub_memmove (get_virtual_current_address (ch), &grub_relocator64_start, + RELOCATOR_SIZEOF (64)); - err = grub_relocator_prepare_relocs (rel, ptov (target), &relst, NULL); + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); if (err) return err; diff --git a/lib/relocator.c b/lib/relocator.c index b559d12ea..e43463e4d 100644 --- a/lib/relocator.c +++ b/lib/relocator.c @@ -81,6 +81,18 @@ struct grub_relocator_fw_leftover *leftovers; struct grub_relocator_extra_block *extra_blocks; +void * +get_virtual_current_address (grub_relocator_chunk_t in) +{ + return in->srcv; +} + +grub_phys_addr_t +get_physical_target_address (grub_relocator_chunk_t in) +{ + return in->target; +} + struct grub_relocator * grub_relocator_new (void) { @@ -1126,7 +1138,8 @@ adjust_limits (struct grub_relocator *rel, } grub_err_t -grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, void **src, +grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, + grub_relocator_chunk_t *out, grub_phys_addr_t target, grub_size_t size) { struct grub_relocator_chunk *chunk; @@ -1221,13 +1234,14 @@ grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, void **src, grub_dprintf ("relocator", "cur = %p, next = %p\n", rel->chunks, rel->chunks->next); - *src = chunk->srcv = grub_map_memory (chunk->src, chunk->size); + chunk->srcv = grub_map_memory (chunk->src, chunk->size); + *out = chunk; return GRUB_ERR_NONE; } grub_err_t -grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src, - grub_phys_addr_t *target, +grub_relocator_alloc_chunk_align (struct grub_relocator *rel, + grub_relocator_chunk_t *out, grub_phys_addr_t min_addr, grub_phys_addr_t max_addr, grub_size_t size, grub_size_t align, @@ -1262,8 +1276,8 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src, chunk->size = size; chunk->next = rel->chunks; rel->chunks = chunk; - *src = (void *) chunk->src; - *target = chunk->target; + chunk->srcv = grub_map_memory (chunk->src, chunk->size); + *out = chunk; return GRUB_ERR_NONE; } @@ -1300,12 +1314,12 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src, return 0; candidate = ALIGN_UP (addr, align); if (candidate < min_addr) - candidate = min_addr; - if (candidate + size >= addr + sz + candidate = ALIGN_UP (min_addr, align); + if (candidate + size > addr + sz || candidate > ALIGN_DOWN (max_addr, align)) return 0; if (preference == GRUB_RELOCATOR_PREFERENCE_HIGH) - candidate = ALIGN_DOWN (addr + sz - size, align); + candidate = ALIGN_DOWN (min (addr + sz - size, max_addr), align); if (!found || (preference == GRUB_RELOCATOR_PREFERENCE_HIGH && candidate > chunk->target)) chunk->target = candidate; @@ -1353,8 +1367,8 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src, rel->chunks = chunk; grub_dprintf ("relocator", "cur = %p, next = %p\n", rel->chunks, rel->chunks->next); - *src = chunk->srcv = grub_map_memory (chunk->src, chunk->size); - *target = chunk->target; + chunk->srcv = grub_map_memory (chunk->src, chunk->size); + *out = chunk; return GRUB_ERR_NONE; } @@ -1378,7 +1392,7 @@ grub_relocator_unload (struct grub_relocator *rel) } grub_err_t -grub_relocator_prepare_relocs (struct grub_relocator *rel, void *addr, +grub_relocator_prepare_relocs (struct grub_relocator *rel, grub_addr_t addr, void **relstart, grub_size_t *relsize) { grub_uint8_t *rels; @@ -1395,12 +1409,12 @@ grub_relocator_prepare_relocs (struct grub_relocator *rel, void *addr, grub_relocator_align, rel->relocators_size, &movers_chunk, 1, 1)) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); - rels = rels0 = movers_chunk.srcv; + rels = rels0 = grub_map_memory (movers_chunk.src, movers_chunk.size); if (relsize) *relsize = rel->relocators_size; - grub_dprintf ("relocator", "Relocs allocated\n"); + grub_dprintf ("relocator", "Relocs allocated at %p\n", movers_chunk.srcv); { unsigned i; diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c index cfd10713d..1b2fadd80 100644 --- a/loader/i386/bsd.c +++ b/loader/i386/bsd.c @@ -606,10 +606,14 @@ grub_freebsd_boot (void) if (is_64bit) p_size += 4096 * 3; - err = grub_relocator_alloc_chunk_addr (relocator, (void **) &p, - kern_end, p_size); - if (err) - return err; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + kern_end, p_size); + if (err) + return err; + p = get_virtual_current_address (ch); + } p_target = kern_end; p0 = p; kern_end += p_size; @@ -682,14 +686,18 @@ grub_freebsd_boot (void) grub_uint32_t *stack; grub_addr_t stack_target; - err = grub_relocator_alloc_chunk_align (relocator, (void **) &stack, - &stack_target, - 0x10000, 0x90000, - 3 * sizeof (grub_uint32_t) - + sizeof (bi), 4, - GRUB_RELOCATOR_PREFERENCE_NONE); - if (err) - return err; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, + 0x10000, 0x90000, + 3 * sizeof (grub_uint32_t) + + sizeof (bi), 4, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + stack = get_virtual_current_address (ch); + stack_target = get_physical_target_address (ch); + } #ifdef GRUB_MACHINE_EFI err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL); @@ -714,14 +722,19 @@ grub_freebsd_boot (void) struct grub_relocator32_state state; grub_uint32_t *stack; grub_addr_t stack_target; - err = grub_relocator_alloc_chunk_align (relocator, (void **) &stack, - &stack_target, - 0x10000, 0x90000, - 9 * sizeof (grub_uint32_t) - + sizeof (bi), 4, - GRUB_RELOCATOR_PREFERENCE_NONE); - if (err) - return err; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, + 0x10000, 0x90000, + 9 * sizeof (grub_uint32_t) + + sizeof (bi), 4, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + stack = get_virtual_current_address (ch); + stack_target = get_physical_target_address (ch); + } #ifdef GRUB_MACHINE_EFI err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL); @@ -772,12 +785,16 @@ grub_openbsd_boot (void) } buf_target = GRUB_BSD_TEMP_BUFFER - 9 * sizeof (grub_uint32_t); - err = grub_relocator_alloc_chunk_addr (relocator, &buf0, - buf_target, tag_buf_len - + sizeof (struct grub_openbsd_bootargs) - + 9 * sizeof (grub_uint32_t)); - if (err) - return err; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, buf_target, + tag_buf_len + + sizeof (struct grub_openbsd_bootargs) + + 9 * sizeof (grub_uint32_t)); + if (err) + return err; + buf0 = get_virtual_current_address (ch); + } stack = (grub_uint32_t *) buf0; arg0 = curarg = stack + 9; @@ -976,12 +993,16 @@ grub_netbsd_boot (void) } arg_target = kern_end; - err = grub_relocator_alloc_chunk_addr (relocator, &curarg, - arg_target, tag_buf_len - + sizeof (struct grub_netbsd_bootinfo) - + tag_count * sizeof (grub_uint32_t)); - if (err) - return err; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + arg_target, tag_buf_len + + sizeof (struct grub_netbsd_bootinfo) + + tag_count * sizeof (grub_uint32_t)); + if (err) + return err; + curarg = get_virtual_current_address (ch); + } arg0 = curarg; bootinfo = (void *) ((grub_uint8_t *) arg0 + tag_buf_len); @@ -1004,12 +1025,16 @@ grub_netbsd_boot (void) } } - err = grub_relocator_alloc_chunk_align (relocator, (void **) &stack, - &stack_target, 0x10000, 0x90000, - 7 * sizeof (grub_uint32_t), 4, - GRUB_RELOCATOR_PREFERENCE_NONE); - if (err) - return err; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x10000, 0x90000, + 7 * sizeof (grub_uint32_t), 4, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + stack = get_virtual_current_address (ch); + stack_target = get_physical_target_address (ch); + } #ifdef GRUB_MACHINE_EFI err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL); @@ -1107,10 +1132,15 @@ grub_bsd_load_aout (grub_file_t file) if (!relocator) return grub_errno; - err = grub_relocator_alloc_chunk_addr (relocator, &kern_chunk_src, - kern_start, kern_end - kern_start); - if (err) - return err; + { + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + kern_start, kern_end - kern_start); + if (err) + return err; + kern_chunk_src = get_virtual_current_address (ch); + } return grub_aout_load (file, ofs, kern_chunk_src, ah.aout32.a_text + ah.aout32.a_data, @@ -1210,15 +1240,19 @@ grub_bsd_load_elf (grub_elf_t elf) if (grub_elf_is_elf32 (elf)) { + grub_relocator_chunk_t ch; + entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF; err = grub_elf32_phdr_iterate (elf, grub_bsd_elf32_size_hook, NULL); if (err) return err; - err = grub_relocator_alloc_chunk_addr (relocator, &kern_chunk_src, + err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_start, kern_end - kern_start); if (err) return err; + kern_chunk_src = get_virtual_current_address (ch); + return grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0); } else if (grub_elf_is_elf64 (elf)) @@ -1246,10 +1280,15 @@ grub_bsd_load_elf (grub_elf_t elf) grub_dprintf ("bsd", "kern_start = %lx, kern_end = %lx\n", (unsigned long) kern_start, (unsigned long) kern_end); - err = grub_relocator_alloc_chunk_addr (relocator, &kern_chunk_src, - kern_start, kern_end - kern_start); - if (err) - return err; + { + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_start, + kern_end - kern_start); + if (err) + return err; + kern_chunk_src = get_virtual_current_address (ch); + } return grub_elf64_load (elf, grub_bsd_elf64_hook, 0, 0); } @@ -1682,10 +1721,15 @@ grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)), if ((!file) || (!file->size)) goto fail; - err = grub_relocator_alloc_chunk_addr (relocator, &src, kern_end, - file->size); - if (err) - goto fail; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_end, + file->size); + if (err) + goto fail; + src = get_virtual_current_address (ch); + } + grub_file_read (file, src, file->size); if (grub_errno) @@ -1728,10 +1772,15 @@ grub_netbsd_module_load (char *filename, grub_uint32_t type) if ((!file) || (!file->size)) goto fail; - err = grub_relocator_alloc_chunk_addr (relocator, &src, kern_end, - file->size); - if (err) - goto fail; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_end, + file->size); + if (err) + goto fail; + + src = get_virtual_current_address (ch); + } grub_file_read (file, src, file->size); if (grub_errno) diff --git a/loader/i386/bsdXX.c b/loader/i386/bsdXX.c index 734633704..85f4c6236 100644 --- a/loader/i386/bsdXX.c +++ b/loader/i386/bsdXX.c @@ -103,10 +103,14 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator, chunk_size += s->sh_size; } - err = grub_relocator_alloc_chunk_addr (relocator, &chunk_src, - module, chunk_size); - if (err) - return err; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + module, chunk_size); + if (err) + return err; + chunk_src = get_virtual_current_address (ch); + } for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize); @@ -191,10 +195,16 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, chunk_size = s->sh_addr + s->sh_size; } - err = grub_relocator_alloc_chunk_addr (relocator, &chunk_src, - module, chunk_size); - if (err) - return err; + { + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + module, chunk_size); + if (err) + return err; + + chunk_src = get_virtual_current_address (ch); + } for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize); @@ -300,10 +310,15 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, + 2 * sizeof (grub_freebsd_addr_t); symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t)); - err = grub_relocator_alloc_chunk_addr (relocator, &sym_chunk, - symtarget, chunk_size); - if (err) - return err; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + symtarget, chunk_size); + if (err) + return err; + sym_chunk = get_virtual_current_address (ch); + } symstart = symtarget; symend = symstart + chunk_size; @@ -413,10 +428,14 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, + sizeof (e) + e.e_shnum * e.e_shentsize; symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t)); - err = grub_relocator_alloc_chunk_addr (relocator, &sym_chunk, - symtarget, chunk_size); - if (err) - return err; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + symtarget, chunk_size); + if (err) + return err; + sym_chunk = get_virtual_current_address (ch); + } symtab.nsyms = 1; symtab.ssyms = symtarget; diff --git a/loader/i386/linux.c b/loader/i386/linux.c index ef1b8309e..e05225f25 100644 --- a/loader/i386/linux.c +++ b/loader/i386/linux.c @@ -412,20 +412,28 @@ allocate_pages (grub_size_t prot_size) goto fail; } - err = grub_relocator_alloc_chunk_addr (relocator, &real_mode_mem, - real_mode_target, - (real_size + mmap_size - + efi_mmap_size)); - if (err) - goto fail; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + real_mode_target, + (real_size + mmap_size + + efi_mmap_size)); + if (err) + goto fail; + real_mode_mem = get_virtual_current_address (ch); + } efi_mmap_buf = (grub_uint8_t *) real_mode_mem + real_size + mmap_size; prot_mode_target = GRUB_LINUX_BZIMAGE_ADDR; - err = grub_relocator_alloc_chunk_addr (relocator, &prot_mode_mem, - prot_mode_target, prot_size); - if (err) - goto fail; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + prot_mode_target, prot_size); + if (err) + goto fail; + prot_mode_mem = get_virtual_current_address (ch); + } grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, " "prot_mode_mem = %lx, prot_mode_pages = %x\n", @@ -1111,12 +1119,16 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - err = grub_relocator_alloc_chunk_align (relocator, &initrd_mem, - &initrd_mem_target, - addr_min, addr, size, 0x1000, - GRUB_RELOCATOR_PREFERENCE_HIGH); - if (err) - return err; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, + addr_min, addr, size, 0x1000, + GRUB_RELOCATOR_PREFERENCE_HIGH); + if (err) + return err; + initrd_mem = get_virtual_current_address (ch); + initrd_mem_target = get_physical_target_address (ch); + } if (grub_file_read (file, initrd_mem, size) != size) { diff --git a/loader/i386/multiboot_mbi.c b/loader/i386/multiboot_mbi.c index 2f32c3f4e..ea1385be7 100644 --- a/loader/i386/multiboot_mbi.c +++ b/loader/i386/multiboot_mbi.c @@ -108,6 +108,7 @@ grub_multiboot_load (grub_file_t file) header->load_end_addr - header->load_addr); grub_size_t code_size; void *source; + grub_relocator_chunk_t ch; if (header->bss_end_addr) code_size = (header->bss_end_addr - header->load_addr); @@ -115,7 +116,7 @@ grub_multiboot_load (grub_file_t file) code_size = load_size; err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, - &source, header->load_addr, + &ch, header->load_addr, code_size); if (err) { @@ -123,6 +124,7 @@ grub_multiboot_load (grub_file_t file) grub_free (buffer); return err; } + source = get_virtual_current_address (ch); if ((grub_file_seek (file, offset)) == (grub_off_t) -1) { @@ -322,16 +324,18 @@ grub_multiboot_make_mbi (grub_uint32_t *target) grub_err_t err; grub_size_t bufsize; + grub_relocator_chunk_t ch; bufsize = grub_multiboot_get_mbi_size (); - err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, - (void **) &ptrorig, &ptrdest, + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, 0, 0xffffffff - bufsize, bufsize, 4, GRUB_RELOCATOR_PREFERENCE_NONE); if (err) return err; + ptrorig = get_virtual_current_address (ch); + ptrdest = (grub_addr_t) get_virtual_current_address (ch); *target = ptrdest; diff --git a/loader/i386/pc/linux.c b/loader/i386/pc/linux.c index 176220a2b..82640d77d 100644 --- a/loader/i386/pc/linux.c +++ b/loader/i386/pc/linux.c @@ -255,12 +255,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), } } - err = grub_relocator_alloc_chunk_addr (relocator, (void **) - &grub_linux_real_chunk, - grub_linux_real_target, - GRUB_LINUX_SETUP_MOVE_SIZE); - if (err) - return err; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + grub_linux_real_target, + GRUB_LINUX_SETUP_MOVE_SIZE); + if (err) + return err; + grub_linux_real_chunk = get_virtual_current_address (ch); + } /* Put the real mode code at the temporary address. */ grub_memmove (grub_linux_real_chunk, &lh, sizeof (lh)); @@ -301,12 +304,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), grub_linux_prot_target = GRUB_LINUX_BZIMAGE_ADDR; else grub_linux_prot_target = GRUB_LINUX_ZIMAGE_ADDR; - err = grub_relocator_alloc_chunk_addr (relocator, - (void **) &grub_linux_prot_chunk, - grub_linux_prot_target, - grub_linux16_prot_size); - if (err) - return err; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + grub_linux_prot_target, + grub_linux16_prot_size); + if (err) + return err; + grub_linux_prot_chunk = get_virtual_current_address (ch); + } len = grub_linux16_prot_size; if (grub_file_read (file, grub_linux_prot_chunk, grub_linux16_prot_size) @@ -398,13 +404,17 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), size = grub_file_size (file); - err = grub_relocator_alloc_chunk_align (relocator, (void **) &initrd_chunk, - &initrd_addr, - addr_min, addr_max - size, - size, 0x1000, - GRUB_RELOCATOR_PREFERENCE_HIGH); - if (err) - return err; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, + addr_min, addr_max - size, + size, 0x1000, + GRUB_RELOCATOR_PREFERENCE_HIGH); + if (err) + return err; + initrd_chunk = get_virtual_current_address (ch); + initrd_addr = get_physical_target_address (ch); + } if (grub_file_read (file, initrd_chunk, size) != size) { diff --git a/loader/i386/pc/ntldr.c b/loader/i386/pc/ntldr.c index 1368694fb..0c33a0680 100644 --- a/loader/i386/pc/ntldr.c +++ b/loader/i386/pc/ntldr.c @@ -90,10 +90,14 @@ grub_cmd_ntldr (grub_command_t cmd __attribute__ ((unused)), if (! file) goto fail; - err = grub_relocator_alloc_chunk_addr (rel, &bs, 0x7C00, - GRUB_DISK_SECTOR_SIZE); - if (err) - goto fail; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (rel, &ch, 0x7C00, + GRUB_DISK_SECTOR_SIZE); + if (err) + goto fail; + bs = get_virtual_current_address (ch); + } edx = grub_get_root_biosnumber (); dev = grub_device_open (0); @@ -112,10 +116,14 @@ grub_cmd_ntldr (grub_command_t cmd __attribute__ ((unused)), grub_device_close (dev); ntldrsize = grub_file_size (file); - err = grub_relocator_alloc_chunk_addr (rel, &ntldr, GRUB_NTLDR_SEGMENT << 4, - ntldrsize); - if (err) - goto fail; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_NTLDR_SEGMENT << 4, + ntldrsize); + if (err) + goto fail; + ntldr = get_virtual_current_address (ch); + } if (grub_file_read (file, ntldr, ntldrsize) != (grub_ssize_t) ntldrsize) diff --git a/loader/multiboot.c b/loader/multiboot.c index a3ca6266f..6c6afcee9 100644 --- a/loader/multiboot.c +++ b/loader/multiboot.c @@ -284,16 +284,20 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), return grub_errno; size = grub_file_size (file); - err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &module, - &target, - 0, (0xffffffff - size) + 1, - size, MULTIBOOT_MOD_ALIGN, - GRUB_RELOCATOR_PREFERENCE_NONE); - if (err) - { - grub_file_close (file); - return err; - } + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, + 0, (0xffffffff - size) + 1, + size, MULTIBOOT_MOD_ALIGN, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + { + grub_file_close (file); + return err; + } + module = get_virtual_current_address (ch); + target = (grub_addr_t) get_virtual_current_address (ch); + } err = grub_multiboot_add_module (target, size, argc - 1, argv + 1); if (err) diff --git a/loader/multiboot_elfxx.c b/loader/multiboot_elfxx.c index 561c7572c..880e93ce5 100644 --- a/loader/multiboot_elfxx.c +++ b/loader/multiboot_elfxx.c @@ -92,14 +92,18 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n", i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr); - err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, - &source, phdr(i)->p_paddr, - phdr(i)->p_memsz); - if (err) - { - grub_dprintf ("multiboot_loader", "Error loading phdr %d\n", i); - return err; - } + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, + &ch, phdr(i)->p_paddr, + phdr(i)->p_memsz); + if (err) + { + grub_dprintf ("multiboot_loader", "Error loading phdr %d\n", i); + return err; + } + source = get_virtual_current_address (ch); + } if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset) == (grub_off_t) -1) @@ -163,18 +167,22 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) if (sh->sh_size == 0) continue; - err - = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, - &src, &target, 0, - (0xffffffff - sh->sh_size) + 1, - sh->sh_size, - sh->sh_addralign, - GRUB_RELOCATOR_PREFERENCE_NONE); - if (err) - { - grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i); - return err; - } + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, + &ch, 0, + (0xffffffff - sh->sh_size) + + 1, sh->sh_size, + sh->sh_addralign, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + { + grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i); + return err; + } + src = get_virtual_current_address (ch); + target = get_physical_target_address (ch); + } if (grub_file_seek (file, sh->sh_offset) == (grub_off_t) -1) return grub_error (GRUB_ERR_BAD_OS, diff --git a/loader/multiboot_mbi2.c b/loader/multiboot_mbi2.c index c5929f10f..5f4a52800 100644 --- a/loader/multiboot_mbi2.c +++ b/loader/multiboot_mbi2.c @@ -191,6 +191,7 @@ grub_multiboot_load (grub_file_t file) addr_tag->load_end_addr - addr_tag->load_addr); grub_size_t code_size; void *source; + grub_relocator_chunk_t ch; if (addr_tag->bss_end_addr) code_size = (addr_tag->bss_end_addr - addr_tag->load_addr); @@ -198,7 +199,7 @@ grub_multiboot_load (grub_file_t file) code_size = load_size; err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, - &source, addr_tag->load_addr, + &ch, addr_tag->load_addr, code_size); if (err) { @@ -206,6 +207,7 @@ grub_multiboot_load (grub_file_t file) grub_free (buffer); return err; } + source = get_virtual_current_address (ch); if ((grub_file_seek (file, offset)) == (grub_off_t) -1) { @@ -460,19 +462,19 @@ grub_multiboot_make_mbi (grub_uint32_t *target) grub_uint8_t *mbistart; grub_err_t err; grub_size_t bufsize; - grub_addr_t ptrdest; + grub_relocator_chunk_t ch; bufsize = grub_multiboot_get_mbi_size (); - err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, - (void **) &ptrorig, &ptrdest, + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, 0, 0xffffffff - bufsize, bufsize, 4, GRUB_RELOCATOR_PREFERENCE_NONE); if (err) return err; - *target = ptrdest; + ptrorig = get_virtual_current_address (ch); + *target = get_physical_target_address (ch); mbistart = ptrorig; ptrorig += 2 * sizeof (grub_uint32_t); diff --git a/loader/xnu.c b/loader/xnu.c index f1d372b73..17f850018 100644 --- a/loader/xnu.c +++ b/loader/xnu.c @@ -51,13 +51,15 @@ grub_err_t grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target) { grub_err_t err; + grub_relocator_chunk_t ch; - err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, src, + err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch, grub_xnu_heap_target_start + grub_xnu_heap_size, size); if (err) return err; + *src = get_virtual_current_address (ch); *target = grub_xnu_heap_target_start + grub_xnu_heap_size; grub_xnu_heap_size += size; grub_dprintf ("xnu", "val=%p\n", *src); diff --git a/loader/xnu_resume.c b/loader/xnu_resume.c index 2d47df601..6aebc1f34 100644 --- a/loader/xnu_resume.c +++ b/loader/xnu_resume.c @@ -103,25 +103,33 @@ grub_xnu_resume (char *imagename) return grub_errno; } - err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &code, - codedest, codesize + GRUB_XNU_PAGESIZE); - if (err) - { - grub_file_close (file); - return err; - } + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch, codedest, + codesize + GRUB_XNU_PAGESIZE); + if (err) + { + grub_file_close (file); + return err; + } + code = get_virtual_current_address (ch); + } - err = grub_relocator_alloc_chunk_align (grub_xnu_relocator, &image, - &target_image, 0, - (0xffffffff - hibhead.image_size) + 1, - hibhead.image_size, - GRUB_XNU_PAGESIZE, - GRUB_RELOCATOR_PREFERENCE_NONE); - if (err) - { - grub_file_close (file); - return err; - } + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (grub_xnu_relocator, &ch, 0, + (0xffffffff - hibhead.image_size) + 1, + hibhead.image_size, + GRUB_XNU_PAGESIZE, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + { + grub_file_close (file); + return err; + } + image = get_virtual_current_address (ch); + target_image = get_physical_target_address (ch); + } /* Read code part. */ if (grub_file_seek (file, total_header_size) == (grub_off_t) -1