2008-08-17 Robert Millan <rmh@aybabtu.com>

* conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pc/mmap.c'.

        * include/grub/i386/pc/init.h (GRUB_MACHINE_MEMORY_AVAILABLE)
        (GRUB_MACHINE_MEMORY_RESERVED): New macros.
        (grub_machine_mmap_iterate): New function declaration.
        * include/grub/multiboot.h (struct grub_multiboot_mmap_entry): New
        structure.
        (GRUB_MMAP_MEMORY_AVAILABLE, GRUB_MMAP_MEMORY_RESERVED): New
        macros.

        * kern/i386/pc/init.c (grub_machine_init): Replace hardcoded region
        type check value with `GRUB_MACHINE_MEMORY_AVAILABLE'.
        Move e820 parsing from here ...
        * kern/i386/pc/mmap.c: New file.
        (grub_machine_mmap_iterate): ... to here.

        * include/grub/i386/coreboot/memory.h: Remove `<grub/err.h>'.
        (GRUB_LINUXBIOS_MEMORY_AVAILABLE): Rename (for consistency) to ...
        (GRUB_MACHINE_MEMORY_AVAILABLE): ... this.  Update all users.
        (grub_available_iterate): Redeclare to return `void', and redeclare
        its hook to use grub_uint64_t as addr and size parameters, and rename
        to ...
        (grub_machine_mmap_iterate): ... this.  Update all users.

        * kern/i386/coreboot/mmap.c (grub_mmap_iterate): Simplify parser loop
        to make it more readable.  Rename to ...
        (grub_machine_mmap_iterate): ... this.

        * loader/i386/pc/multiboot.c (mmap_addr, mmap_length): New variables.
        (grub_get_multiboot_mmap_len, grub_fill_multiboot_mmap): New functions.
        (grub_multiboot): Allocate an extra region after the payload, and fill
        it with a Multiboot memory map.  Adjust a.out loader to calculate size
        with the extra space.
        (grub_multiboot_load_elf32): Adjust elf32 loader to calculate size
        with the extra space.
This commit is contained in:
robertmh 2008-08-17 16:32:18 +00:00
parent 9807deb97d
commit deceb3ecd3
10 changed files with 289 additions and 70 deletions

View file

@ -78,14 +78,60 @@ grub_multiboot_unload (void)
grub_free ((void *) mbi->cmdline);
grub_free (mbi);
}
mbi = 0;
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
/* FIXME: grub_uint32_t will break for addresses above 4 GiB, but is mandated
by the spec. Is there something we can do about it? */
static grub_uint32_t mmap_addr = 0;
static grub_uint32_t mmap_length;
/* Return the length of the Multiboot mmap that will be needed to allocate
our platform's map. */
static grub_uint32_t
grub_get_multiboot_mmap_len ()
{
grub_size_t count = 0;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)),
grub_uint64_t size __attribute__ ((unused)),
grub_uint32_t type __attribute__ ((unused)))
{
count++;
return 0;
}
grub_machine_mmap_iterate (hook);
return count * sizeof (struct grub_multiboot_mmap_entry);
}
/* Fill previously allocated Multiboot mmap. */
static void
grub_fill_multiboot_mmap (struct grub_multiboot_mmap_entry *first_entry)
{
struct grub_multiboot_mmap_entry *mmap_entry = (struct grub_multiboot_mmap_entry *) first_entry;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
{
mmap_entry->addr = addr;
mmap_entry->len = size;
mmap_entry->type = type;
mmap_entry->size = sizeof (struct grub_multiboot_mmap_entry) - sizeof (mmap_entry->size);
mmap_entry++;
return 0;
}
grub_machine_mmap_iterate (hook);
}
/* Check if BUFFER contains ELF32. */
static int
grub_multiboot_is_elf32 (void *buffer)
@ -127,7 +173,7 @@ grub_multiboot_load_elf32 (grub_file_t file, void *buffer)
if (phdr(i)->p_paddr > phdr(highest_segment)->p_paddr)
highest_segment = i;
}
grub_multiboot_payload_size = (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
grub_multiboot_payload_size += (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr;
playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
@ -379,6 +425,9 @@ grub_multiboot (int argc, char *argv[])
playground = NULL;
}
mmap_length = grub_get_multiboot_mmap_len ();
grub_multiboot_payload_size = mmap_length;
if (header->flags & MULTIBOOT_AOUT_KLUDGE)
{
int offset = ((char *) header - buffer -
@ -387,9 +436,9 @@ grub_multiboot (int argc, char *argv[])
header->load_end_addr - header->load_addr);
if (header->bss_end_addr)
grub_multiboot_payload_size = (header->bss_end_addr - header->load_addr);
grub_multiboot_payload_size += (header->bss_end_addr - header->load_addr);
else
grub_multiboot_payload_size = load_size;
grub_multiboot_payload_size += load_size;
grub_multiboot_payload_dest = header->load_addr;
playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
@ -416,6 +465,12 @@ grub_multiboot (int argc, char *argv[])
goto fail;
grub_fill_multiboot_mmap ((struct grub_mmap_entry *) (grub_multiboot_payload_orig
+ grub_multiboot_payload_size
- mmap_length));
mmap_addr = grub_multiboot_payload_dest + grub_multiboot_payload_size - mmap_length;
if (grub_multiboot_payload_dest >= grub_multiboot_payload_orig)
{
grub_memmove (playground, &grub_multiboot_forward_relocator, RELOCATOR_SIZEOF(forward));
@ -439,11 +494,14 @@ grub_multiboot (int argc, char *argv[])
grub_memset (mbi, 0, sizeof (struct grub_multiboot_info));
mbi->flags = MULTIBOOT_INFO_MEMORY;
/* Convert from bytes to kilobytes. */
mbi->mem_lower = grub_lower_mem / 1024;
mbi->mem_upper = grub_upper_mem / 1024;
mbi->flags |= MULTIBOOT_INFO_MEMORY;
mbi->mmap_addr = mmap_addr;
mbi->mmap_length = mmap_length;
mbi->flags |= MULTIBOOT_INFO_MEM_MAP;
for (i = 0, len = 0; i < argc; i++)
len += grub_strlen (argv[i]) + 1;