boot services avoid code based on the patch by Matthew Garrett

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2012-03-03 20:06:41 +01:00
parent 86e5ab4b81
commit 9be4c45dbe
18 changed files with 136 additions and 37 deletions

View file

@ -38,7 +38,8 @@ grub_reboot (void)
while (1); while (1);
err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000, 0x1000, err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000, 0x1000,
grub_reboot_end - grub_reboot_start, grub_reboot_end - grub_reboot_start,
16, GRUB_RELOCATOR_PREFERENCE_NONE); 16, GRUB_RELOCATOR_PREFERENCE_NONE,
0);
if (err) if (err)
while (1); while (1);
buf = get_virtual_current_address (ch); buf = get_virtual_current_address (ch);

View file

@ -155,7 +155,8 @@ grub_cpu_relocator_forward (void *ptr, void *src, void *dest,
grub_err_t grub_err_t
grub_relocator32_boot (struct grub_relocator *rel, grub_relocator32_boot (struct grub_relocator *rel,
struct grub_relocator32_state state) struct grub_relocator32_state state,
int avoid_efi_bootservices)
{ {
grub_err_t err; grub_err_t err;
void *relst; void *relst;
@ -164,7 +165,8 @@ grub_relocator32_boot (struct grub_relocator *rel,
err = grub_relocator_alloc_chunk_align (rel, &ch, 0, err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
(0xffffffff - RELOCATOR_SIZEOF (32)) (0xffffffff - RELOCATOR_SIZEOF (32))
+ 1, RELOCATOR_SIZEOF (32), 16, + 1, RELOCATOR_SIZEOF (32), 16,
GRUB_RELOCATOR_PREFERENCE_NONE); GRUB_RELOCATOR_PREFERENCE_NONE,
avoid_efi_bootservices);
if (err) if (err)
return err; return err;
@ -207,7 +209,8 @@ grub_relocator16_boot (struct grub_relocator *rel,
- GRUB_RELOCATOR16_STACK_SIZE, - GRUB_RELOCATOR16_STACK_SIZE,
RELOCATOR_SIZEOF (16) RELOCATOR_SIZEOF (16)
+ GRUB_RELOCATOR16_STACK_SIZE, 16, + GRUB_RELOCATOR16_STACK_SIZE, 16,
GRUB_RELOCATOR_PREFERENCE_NONE); GRUB_RELOCATOR_PREFERENCE_NONE,
0);
if (err) if (err)
return err; return err;
@ -261,7 +264,8 @@ grub_relocator64_boot (struct grub_relocator *rel,
err = grub_relocator_alloc_chunk_align (rel, &ch, min_addr, err = grub_relocator_alloc_chunk_align (rel, &ch, min_addr,
max_addr - RELOCATOR_SIZEOF (64), max_addr - RELOCATOR_SIZEOF (64),
RELOCATOR_SIZEOF (64), 16, RELOCATOR_SIZEOF (64), 16,
GRUB_RELOCATOR_PREFERENCE_NONE); GRUB_RELOCATOR_PREFERENCE_NONE,
0);
if (err) if (err)
return err; return err;

View file

@ -1319,7 +1319,8 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
grub_phys_addr_t min_addr, grub_phys_addr_t min_addr,
grub_phys_addr_t max_addr, grub_phys_addr_t max_addr,
grub_size_t size, grub_size_t align, grub_size_t size, grub_size_t align,
int preference) int preference,
int avoid_efi_boot_services)
{ {
grub_addr_t min_addr2 = 0, max_addr2; grub_addr_t min_addr2 = 0, max_addr2;
struct grub_relocator_chunk *chunk; struct grub_relocator_chunk *chunk;
@ -1406,7 +1407,12 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
return 0; return 0;
} }
grub_machine_mmap_iterate (hook); #ifdef GRUB_MACHINE_EFI
grub_efi_mmap_iterate (hook, avoid_efi_boot_services);
#else
(void) avoid_efi_boot_services;
grub_mmap_iterate (hook);
#endif
if (!found) if (!found)
return grub_error (GRUB_ERR_BAD_OS, "couldn't find suitable memory target"); return grub_error (GRUB_ERR_BAD_OS, "couldn't find suitable memory target");
} }

View file

@ -723,7 +723,8 @@ grub_freebsd_boot (void)
0x10000, 0x90000, 0x10000, 0x90000,
3 * sizeof (grub_uint32_t) 3 * sizeof (grub_uint32_t)
+ sizeof (bi), 4, + sizeof (bi), 4,
GRUB_RELOCATOR_PREFERENCE_NONE); GRUB_RELOCATOR_PREFERENCE_NONE,
0);
if (err) if (err)
return err; return err;
stack = get_virtual_current_address (ch); stack = get_virtual_current_address (ch);
@ -760,7 +761,8 @@ grub_freebsd_boot (void)
0x10000, 0x90000, 0x10000, 0x90000,
9 * sizeof (grub_uint32_t) 9 * sizeof (grub_uint32_t)
+ sizeof (bi), 4, + sizeof (bi), 4,
GRUB_RELOCATOR_PREFERENCE_NONE); GRUB_RELOCATOR_PREFERENCE_NONE,
0);
if (err) if (err)
return err; return err;
stack = get_virtual_current_address (ch); stack = get_virtual_current_address (ch);
@ -786,7 +788,7 @@ grub_freebsd_boot (void)
stack[6] = stack_target + 9 * sizeof (grub_uint32_t); stack[6] = stack_target + 9 * sizeof (grub_uint32_t);
stack[7] = bi.tags; stack[7] = bi.tags;
stack[8] = kern_end; stack[8] = kern_end;
return grub_relocator32_boot (relocator, state); return grub_relocator32_boot (relocator, state, 0);
} }
/* Not reached. */ /* Not reached. */
@ -873,7 +875,7 @@ grub_openbsd_boot (void)
stack[7] = (grub_uint8_t *) curarg - (grub_uint8_t *) arg0; stack[7] = (grub_uint8_t *) curarg - (grub_uint8_t *) arg0;
stack[8] = ((grub_uint8_t *) arg0 - (grub_uint8_t *) buf0) + buf_target; stack[8] = ((grub_uint8_t *) arg0 - (grub_uint8_t *) buf0) + buf_target;
return grub_relocator32_boot (relocator, state); return grub_relocator32_boot (relocator, state, 0);
} }
static grub_err_t static grub_err_t
@ -1144,7 +1146,8 @@ grub_netbsd_boot (void)
grub_relocator_chunk_t ch; grub_relocator_chunk_t ch;
err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x10000, 0x90000, err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x10000, 0x90000,
7 * sizeof (grub_uint32_t), 4, 7 * sizeof (grub_uint32_t), 4,
GRUB_RELOCATOR_PREFERENCE_NONE); GRUB_RELOCATOR_PREFERENCE_NONE,
0);
if (err) if (err)
return err; return err;
stack = get_virtual_current_address (ch); stack = get_virtual_current_address (ch);
@ -1168,7 +1171,7 @@ grub_netbsd_boot (void)
stack[5] = grub_mmap_get_upper () >> 10; stack[5] = grub_mmap_get_upper () >> 10;
stack[6] = grub_mmap_get_lower () >> 10; stack[6] = grub_mmap_get_lower () >> 10;
return grub_relocator32_boot (relocator, state); return grub_relocator32_boot (relocator, state, 0);
} }
static grub_err_t static grub_err_t

View file

@ -43,7 +43,7 @@ grub_chain_boot (void)
grub_video_set_mode ("text", 0, 0); grub_video_set_mode ("text", 0, 0);
state.eip = entry; state.eip = entry;
return grub_relocator32_boot (relocator, state); return grub_relocator32_boot (relocator, state, 0);
} }
static grub_err_t static grub_err_t

View file

@ -189,7 +189,9 @@ free_pages (void)
/* Allocate pages for the real mode code and the protected mode code /* Allocate pages for the real mode code and the protected mode code
for linux as well as a memory map buffer. */ for linux as well as a memory map buffer. */
static grub_err_t static grub_err_t
allocate_pages (grub_size_t prot_size) allocate_pages (grub_size_t prot_size, grub_size_t *align,
grub_size_t min_align, int relocatable,
grub_uint64_t prefered_address)
{ {
grub_size_t real_size, mmap_size; grub_size_t real_size, mmap_size;
grub_err_t err; grub_err_t err;
@ -254,7 +256,11 @@ allocate_pages (grub_size_t prot_size)
return 0; return 0;
} }
#ifdef GRUB_MACHINE_EFI
grub_efi_mmap_iterate (hook, 1);
#else
grub_mmap_iterate (hook); grub_mmap_iterate (hook);
#endif
if (! real_mode_target) if (! real_mode_target)
{ {
err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages"); err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
@ -273,15 +279,36 @@ allocate_pages (grub_size_t prot_size)
} }
efi_mmap_buf = (grub_uint8_t *) real_mode_mem + real_size + mmap_size; efi_mmap_buf = (grub_uint8_t *) real_mode_mem + real_size + mmap_size;
prot_mode_target = GRUB_LINUX_BZIMAGE_ADDR;
{ {
grub_relocator_chunk_t ch; grub_relocator_chunk_t ch;
if (relocatable)
{
err = grub_relocator_alloc_chunk_align (relocator, &ch,
prefered_address,
prefered_address,
prot_size, 1,
GRUB_RELOCATOR_PREFERENCE_LOW,
1);
for (; err && *align >= min_align; (*align)--)
{
grub_errno = GRUB_ERR_NONE;
err = grub_relocator_alloc_chunk_align (relocator, &ch,
0x1000000, 0xffffffff,
prot_size, 1 << *align,
GRUB_RELOCATOR_PREFERENCE_LOW,
1);
}
if (err)
goto fail;
}
else
err = grub_relocator_alloc_chunk_addr (relocator, &ch, err = grub_relocator_alloc_chunk_addr (relocator, &ch,
prot_mode_target, prot_size); prefered_address,
prot_size);
if (err) if (err)
goto fail; goto fail;
prot_mode_mem = get_virtual_current_address (ch); prot_mode_mem = get_virtual_current_address (ch);
prot_mode_target = get_physical_target_address (ch);
} }
grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, " grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
@ -612,7 +639,7 @@ grub_linux_boot (void)
state.esi = real_mode_target; state.esi = real_mode_target;
state.esp = real_mode_target; state.esp = real_mode_target;
state.eip = params->code32_start; state.eip = params->code32_start;
return grub_relocator32_boot (relocator, state); return grub_relocator32_boot (relocator, state, 0);
} }
static grub_err_t static grub_err_t
@ -634,6 +661,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_size_t real_size, prot_size; grub_size_t real_size, prot_size;
grub_ssize_t len; grub_ssize_t len;
int i; int i;
grub_size_t align, min_align;
int relocatable;
grub_uint64_t preffered_address = GRUB_LINUX_BZIMAGE_ADDR;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -707,7 +737,37 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
real_size = setup_sects << GRUB_DISK_SECTOR_BITS; real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE; prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
if (allocate_pages (prot_size)) if (grub_le_to_cpu16 (lh.version) >= 0x205
&& lh.kernel_alignment != 0
&& ((lh.kernel_alignment - 1) & lh.kernel_alignment) == 0)
{
for (align = 0; align < 32; align++)
if (grub_le_to_cpu32 (lh.kernel_alignment) & (1 << align))
break;
relocatable = grub_le_to_cpu32 (lh.relocatable);
}
else
{
align = 0;
relocatable = 0;
}
if (grub_le_to_cpu16 (lh.version) >= 0x020a)
{
min_align = lh.min_alignment;
prot_size = grub_le_to_cpu32 (lh.init_size);
preffered_address = grub_le_to_cpu64 (lh.pref_address);
}
else
{
min_align = 0;
prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
preffered_address = grub_le_to_cpu32 (lh.code32_start);
}
if (allocate_pages (prot_size, &align,
min_align, relocatable,
preffered_address))
goto fail; goto fail;
params = (struct linux_kernel_params *) real_mode_mem; params = (struct linux_kernel_params *) real_mode_mem;
@ -1021,7 +1081,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
grub_relocator_chunk_t ch; grub_relocator_chunk_t ch;
err = grub_relocator_alloc_chunk_align (relocator, &ch, err = grub_relocator_alloc_chunk_align (relocator, &ch,
addr_min, addr, size, 0x1000, addr_min, addr, size, 0x1000,
GRUB_RELOCATOR_PREFERENCE_HIGH); GRUB_RELOCATOR_PREFERENCE_HIGH,
1);
if (err) if (err)
return err; return err;
initrd_mem = get_virtual_current_address (ch); initrd_mem = get_virtual_current_address (ch);

View file

@ -454,7 +454,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
0x10000, 0x100000 - bufsize, 0x10000, 0x100000 - bufsize,
bufsize, 4, bufsize, 4,
GRUB_RELOCATOR_PREFERENCE_NONE); GRUB_RELOCATOR_PREFERENCE_NONE, 0);
if (err) if (err)
return err; return err;
ptrorig = get_virtual_current_address (ch); ptrorig = get_virtual_current_address (ch);

View file

@ -429,7 +429,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
err = grub_relocator_alloc_chunk_align (relocator, &ch, err = grub_relocator_alloc_chunk_align (relocator, &ch,
addr_min, addr_max - size, addr_min, addr_max - size,
size, 0x1000, size, 0x1000,
GRUB_RELOCATOR_PREFERENCE_HIGH); GRUB_RELOCATOR_PREFERENCE_HIGH, 0);
if (err) if (err)
return err; return err;
initrd_chunk = get_virtual_current_address (ch); initrd_chunk = get_virtual_current_address (ch);

View file

@ -90,7 +90,7 @@ grub_plan9_boot (void)
}; };
grub_video_set_mode ("text", 0, 0); grub_video_set_mode ("text", 0, 0);
return grub_relocator32_boot (rel, state); return grub_relocator32_boot (rel, state, 0);
} }
static grub_err_t static grub_err_t

View file

@ -842,7 +842,7 @@ grub_xnu_boot_resume (void)
state.eip = grub_xnu_entry_point; state.eip = grub_xnu_entry_point;
state.eax = grub_xnu_arg1; state.eax = grub_xnu_arg1;
return grub_relocator32_boot (grub_xnu_relocator, state); return grub_relocator32_boot (grub_xnu_relocator, state, 0);
} }
/* Setup video for xnu. */ /* Setup video for xnu. */
@ -1150,7 +1150,7 @@ grub_xnu_boot (void)
grub_outb (0xff, 0x21); grub_outb (0xff, 0x21);
grub_outb (0xff, 0xa1); grub_outb (0xff, 0xa1);
return grub_relocator32_boot (grub_xnu_relocator, state); return grub_relocator32_boot (grub_xnu_relocator, state, 0);
} }
static grub_command_t cmd_devprop_load; static grub_command_t cmd_devprop_load;

View file

@ -134,7 +134,7 @@ grub_multiboot_boot (void)
return err; return err;
#endif #endif
grub_relocator32_boot (grub_multiboot_relocator, state); grub_relocator32_boot (grub_multiboot_relocator, state, 0);
/* Not reached. */ /* Not reached. */
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
@ -307,7 +307,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
0, (0xffffffff - size) + 1, 0, (0xffffffff - size) + 1,
size, MULTIBOOT_MOD_ALIGN, size, MULTIBOOT_MOD_ALIGN,
GRUB_RELOCATOR_PREFERENCE_NONE); GRUB_RELOCATOR_PREFERENCE_NONE, 0);
if (err) if (err)
{ {
grub_file_close (file); grub_file_close (file);

View file

@ -200,7 +200,8 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
(0xffffffff - sh->sh_size) (0xffffffff - sh->sh_size)
+ 1, sh->sh_size, + 1, sh->sh_size,
sh->sh_addralign, sh->sh_addralign,
GRUB_RELOCATOR_PREFERENCE_NONE); GRUB_RELOCATOR_PREFERENCE_NONE,
0);
if (err) if (err)
{ {
grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i); grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i);

View file

@ -588,7 +588,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
0, 0xffffffff - bufsize, 0, 0xffffffff - bufsize,
bufsize, MULTIBOOT_TAG_ALIGN, bufsize, MULTIBOOT_TAG_ALIGN,
GRUB_RELOCATOR_PREFERENCE_NONE); GRUB_RELOCATOR_PREFERENCE_NONE, 0);
if (err) if (err)
return err; return err;

View file

@ -125,7 +125,7 @@ grub_xnu_resume (char *imagename)
(0xffffffff - hibhead.image_size) + 1, (0xffffffff - hibhead.image_size) + 1,
hibhead.image_size, hibhead.image_size,
GRUB_XNU_PAGESIZE, GRUB_XNU_PAGESIZE,
GRUB_RELOCATOR_PREFERENCE_NONE); GRUB_RELOCATOR_PREFERENCE_NONE, 0);
if (err) if (err)
{ {
grub_file_close (file); grub_file_close (file);

View file

@ -29,7 +29,7 @@
((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
grub_err_t grub_err_t
grub_machine_mmap_iterate (grub_memory_hook_t hook) grub_efi_mmap_iterate (grub_memory_hook_t hook, int avoid_efi_boot_services)
{ {
grub_efi_uintn_t mmap_size = 0; grub_efi_uintn_t mmap_size = 0;
grub_efi_memory_descriptor_t *map_buf = 0; grub_efi_memory_descriptor_t *map_buf = 0;
@ -65,6 +65,13 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook)
+ desc->num_pages * 4096, desc->type); + desc->num_pages * 4096, desc->type);
switch (desc->type) switch (desc->type)
{ {
case GRUB_EFI_BOOT_SERVICES_CODE:
if (!avoid_efi_boot_services)
{
hook (desc->physical_start, desc->num_pages * 4096,
GRUB_MEMORY_AVAILABLE);
break;
}
case GRUB_EFI_RUNTIME_SERVICES_CODE: case GRUB_EFI_RUNTIME_SERVICES_CODE:
hook (desc->physical_start, desc->num_pages * 4096, hook (desc->physical_start, desc->num_pages * 4096,
GRUB_MEMORY_CODE); GRUB_MEMORY_CODE);
@ -79,6 +86,13 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook)
grub_printf ("Unknown memory type %d, considering reserved\n", grub_printf ("Unknown memory type %d, considering reserved\n",
desc->type); desc->type);
case GRUB_EFI_BOOT_SERVICES_DATA:
if (!avoid_efi_boot_services)
{
hook (desc->physical_start, desc->num_pages * 4096,
GRUB_MEMORY_AVAILABLE);
break;
}
case GRUB_EFI_RESERVED_MEMORY_TYPE: case GRUB_EFI_RESERVED_MEMORY_TYPE:
case GRUB_EFI_RUNTIME_SERVICES_DATA: case GRUB_EFI_RUNTIME_SERVICES_DATA:
case GRUB_EFI_MEMORY_MAPPED_IO: case GRUB_EFI_MEMORY_MAPPED_IO:
@ -90,8 +104,6 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook)
case GRUB_EFI_LOADER_CODE: case GRUB_EFI_LOADER_CODE:
case GRUB_EFI_LOADER_DATA: case GRUB_EFI_LOADER_DATA:
case GRUB_EFI_BOOT_SERVICES_CODE:
case GRUB_EFI_BOOT_SERVICES_DATA:
case GRUB_EFI_CONVENTIONAL_MEMORY: case GRUB_EFI_CONVENTIONAL_MEMORY:
hook (desc->physical_start, desc->num_pages * 4096, hook (desc->physical_start, desc->num_pages * 4096,
GRUB_MEMORY_AVAILABLE); GRUB_MEMORY_AVAILABLE);
@ -112,6 +124,12 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
grub_err_t
grub_machine_mmap_iterate (grub_memory_hook_t hook, int avoid_efi_boot_services)
{
return grub_efi_mmap_iterate (hook, 0);
}
static inline grub_efi_memory_type_t static inline grub_efi_memory_type_t
make_efi_memtype (int type) make_efi_memtype (int type)
{ {

View file

@ -85,4 +85,7 @@ extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle);
extern int EXPORT_VAR(grub_efi_is_finished); extern int EXPORT_VAR(grub_efi_is_finished);
grub_err_t
grub_efi_mmap_iterate (grub_memory_hook_t hook, int avoid_efi_boot_services);
#endif /* ! GRUB_EFI_EFI_HEADER */ #endif /* ! GRUB_EFI_EFI_HEADER */

View file

@ -68,7 +68,8 @@ grub_err_t grub_relocator16_boot (struct grub_relocator *rel,
struct grub_relocator16_state state); struct grub_relocator16_state state);
grub_err_t grub_relocator32_boot (struct grub_relocator *rel, grub_err_t grub_relocator32_boot (struct grub_relocator *rel,
struct grub_relocator32_state state); struct grub_relocator32_state state,
int avoid_efi_bootservices);
grub_err_t grub_relocator64_boot (struct grub_relocator *rel, grub_err_t grub_relocator64_boot (struct grub_relocator *rel,
struct grub_relocator64_state state, struct grub_relocator64_state state,

View file

@ -46,7 +46,8 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
grub_phys_addr_t min_addr, grub_phys_addr_t min_addr,
grub_phys_addr_t max_addr, grub_phys_addr_t max_addr,
grub_size_t size, grub_size_t align, grub_size_t size, grub_size_t align,
int preference); int preference,
int avoid_efi_boot_services);
#define GRUB_RELOCATOR_PREFERENCE_NONE 0 #define GRUB_RELOCATOR_PREFERENCE_NONE 0
#define GRUB_RELOCATOR_PREFERENCE_LOW 1 #define GRUB_RELOCATOR_PREFERENCE_LOW 1