diff --git a/ChangeLog b/ChangeLog index a6dd60a80..9c0aeb2f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-02-12 Hollis Blanchard + + * include/grub/ieee1275/ieee1275.h (grub_available_iterate): New + prototype. + * kern/powerpc/ieee1275/init.c (grub_heap_start): Removed. + (grub_heap_len): Likewise. + (HEAP_SIZE): New macro. + (grub_claim_heap): New function. + (grub_machine_init): Don't claim heap directly. Call + `grub_claim_heap'. + * kern/powerpc/ieee1275/openfw.c: Include alloca.h. + (grub_available_iterate): New function. + 2007-02-03 Thomas Schwinge * aclocal.m4 (grub_CHECK_STACK_PROTECTOR): New definition. diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index 9da492923..d6cccf529 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -145,6 +145,8 @@ grub_err_t EXPORT_FUNC(grub_devalias_iterate) (int (*hook) (struct grub_ieee1275_devalias *alias)); grub_err_t EXPORT_FUNC(grub_children_iterate) (char *devpath, int (*hook) (struct grub_ieee1275_devalias *alias)); +grub_err_t EXPORT_FUNC(grub_available_iterate) + (int (*hook) (grub_uint64_t, grub_uint64_t)); int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size); char *EXPORT_FUNC(grub_ieee1275_encode_devname) (const char *path); diff --git a/kern/powerpc/ieee1275/init.c b/kern/powerpc/ieee1275/init.c index 0c9766e0c..f28f5192f 100644 --- a/kern/powerpc/ieee1275/init.c +++ b/kern/powerpc/ieee1275/init.c @@ -34,9 +34,7 @@ #include #include -/* Apple OF 1.0.5 reserves 0x0 to 0x4000 for the exception handlers. */ -static const grub_addr_t grub_heap_start = 0x4000; -static grub_addr_t grub_heap_len; +#define HEAP_SIZE (8<<20) /* 8 MiB */ void grub_exit (void) @@ -112,27 +110,44 @@ grub_machine_set_prefix (void) grub_free (prefix); } +/* Claim some available memory in the first /memory node. */ +static void grub_claim_heap (unsigned long heapsize) +{ + unsigned long total = 0; + + auto int heap_init (grub_uint64_t addr, grub_uint64_t len); + int heap_init (grub_uint64_t addr, grub_uint64_t len) + { + len -= 1; /* Required for some firmware. */ + + /* Limit heap to `heapsize'. */ + if (total + len > heapsize) + len = heapsize - total; + + /* Claim and use it. */ + if (grub_claimmap (addr, len) < 0) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "Failed to claim heap at 0x%llx, len 0x%llx\n", + addr, len); + grub_mm_init_region ((void *) (grub_addr_t) addr, len); + + total += len; + if (total >= heapsize) + return 1; + return 0; + } + + grub_available_iterate (heap_init); +} + void grub_machine_init (void) { char args[256]; int actual; - extern char _start; grub_console_init (); - - /* Apple OF 3.1.1 reserves an extra 0x1000 bytes below the load address - of an ELF file. */ - grub_heap_len = (grub_addr_t) &_start - 0x1000 - grub_heap_start; - - if (grub_ieee1275_claim (grub_heap_start, grub_heap_len, 0, 0)) - { - grub_printf ("Failed to claim heap at 0x%x, len 0x%x\n", grub_heap_start, - grub_heap_len); - grub_abort (); - } - grub_mm_init_region ((void *) grub_heap_start, grub_heap_len); - + grub_claim_heap (HEAP_SIZE); grub_ofdisk_init (); /* Process commandline. */ diff --git a/kern/powerpc/ieee1275/openfw.c b/kern/powerpc/ieee1275/openfw.c index 4e4f4248c..30b4428cb 100644 --- a/kern/powerpc/ieee1275/openfw.c +++ b/kern/powerpc/ieee1275/openfw.c @@ -18,6 +18,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include #include #include #include @@ -135,6 +137,53 @@ nextprop: return 0; } +grub_err_t grub_available_iterate (int (*hook) (grub_uint64_t, grub_uint64_t)) +{ + grub_ieee1275_phandle_t root; + grub_ieee1275_phandle_t memory; + grub_uint32_t available[32]; + int address_cells = 1; + int size_cells = 1; + unsigned int i; + + /* Determine the format of each entry in `available'. */ + grub_ieee1275_finddevice ("/", &root); + grub_ieee1275_get_property (root, "#address-cells", &address_cells, + sizeof address_cells, 0); + grub_ieee1275_get_property (root, "#size-cells", &size_cells, + sizeof size_cells, 0); + + /* Load `/memory/available'. */ + if (grub_ieee1275_finddevice ("/memory", &memory)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "Couldn't find /memory node"); + if (grub_ieee1275_get_property (memory, "available", available, + sizeof available, 0)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "Couldn't examine /memory/available propery"); + + /* Decode each entry and call `hook'. */ + i = 0; + while (i < sizeof (*available)) + { + grub_uint64_t address; + grub_uint64_t size; + + address = available[i++]; + if (address_cells == 2) + address = (address << 32) | available[i++]; + + size = available[i++]; + if (size_cells == 2) + size = (size << 32) | available[i++]; + + if (hook (address, size)) + break; + } + + return grub_errno; +} + /* Call the "map" method of /chosen/mmu. */ static int grub_map (grub_addr_t phys, grub_addr_t virt, grub_uint32_t size,