Second part of p2v support

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-04-21 19:13:45 +02:00
parent 368c17f85d
commit 4b2ec20b41
15 changed files with 361 additions and 212 deletions

View file

@ -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;

View file

@ -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;