=== modified file 'grub-core/loader/powerpc/ieee1275/linux.c' --- grub-core/loader/powerpc/ieee1275/linux.c 2010-09-05 11:05:36 +0000 +++ grub-core/loader/powerpc/ieee1275/linux.c 2010-11-03 19:55:00 +0000 @@ -26,6 +26,7 @@ #include #include #include +#include #define ELF32_LOADMASK (0xc0000000UL) #define ELF64_LOADMASK (0xc000000000000000ULL) @@ -45,6 +46,51 @@ typedef void (*kernel_entry_t) (void *, unsigned long, int (void *), unsigned long, unsigned long); +static grub_addr_t +grub_linux_claimmap_iterate (grub_addr_t target, grub_size_t size, + grub_size_t align) +{ + grub_addr_t found_addr = (grub_addr_t) -1; + + auto int NESTED_FUNC_ATTR alloc_mem (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type); + int NESTED_FUNC_ATTR alloc_mem (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type) + { + grub_uint64_t end = addr + len; + addr = ALIGN_UP (addr, align); + target = ALIGN_UP (target, align); + + /* Target above the memory chunk. */ + if (type != GRUB_MEMORY_AVAILABLE || target > end) + return 0; + + /* Target inside the memory chunk. */ + if (target >= addr && target < end && size <= end - target) + { + if (grub_claimmap (target, size) == GRUB_ERR_NONE) + { + found_addr = target; + return 1; + } + } + /* Target below the memory chunk. */ + if (target < addr && addr + size <= end) + { + if (grub_claimmap (addr, size) == GRUB_ERR_NONE) + { + found_addr = addr; + return 1; + } + } + return 0; + } + + grub_machine_mmap_iterate (alloc_mem); + + return found_addr; +} + static grub_err_t grub_linux_boot (void) { @@ -103,7 +149,6 @@ grub_linux_load32 (grub_elf_t elf) { Elf32_Addr entry; - int found_addr = 0; /* Linux's entry point incorrectly contains a virtual address. */ entry = elf->ehdr.ehdr32.e_entry & ~ELF32_LOADMASK; @@ -119,15 +164,8 @@ /* On some systems, firmware occupies the memory we're trying to use. * Happily, Linux can be loaded anywhere (it relocates itself). Iterate * until we find an open area. */ - for (linux_addr = entry; linux_addr < entry + 200 * 0x100000; linux_addr += 0x100000) - { - grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n", - linux_addr, linux_size); - found_addr = grub_claimmap (linux_addr, linux_size); - if (found_addr != -1) - break; - } - if (found_addr == -1) + linux_addr = grub_linux_claimmap_iterate (entry, linux_size, 0x100000); + if (linux_addr == (grub_addr_t) -1) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't claim memory"); /* Now load the segments into the area we claimed. */ @@ -153,7 +191,6 @@ grub_linux_load64 (grub_elf_t elf) { Elf64_Addr entry; - int found_addr = 0; /* Linux's entry point incorrectly contains a virtual address. */ entry = elf->ehdr.ehdr64.e_entry & ~ELF64_LOADMASK; @@ -169,15 +206,8 @@ /* On some systems, firmware occupies the memory we're trying to use. * Happily, Linux can be loaded anywhere (it relocates itself). Iterate * until we find an open area. */ - for (linux_addr = entry; linux_addr < entry + 200 * 0x100000; linux_addr += 0x100000) - { - grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n", - linux_addr, linux_size); - found_addr = grub_claimmap (linux_addr, linux_size); - if (found_addr != -1) - break; - } - if (found_addr == -1) + linux_addr = grub_linux_claimmap_iterate (entry, linux_size, 0x100000); + if (linux_addr == (grub_addr_t) -1) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't claim memory"); /* Now load the segments into the area we claimed. */ @@ -287,7 +317,6 @@ grub_ssize_t size; grub_addr_t first_addr; grub_addr_t addr; - int found_addr = 0; if (argc == 0) { @@ -311,20 +340,9 @@ /* Attempt to claim at a series of addresses until successful in the same way that grub_rescue_cmd_linux does. */ - for (addr = first_addr; addr < first_addr + 200 * 0x100000; addr += 0x100000) - { - grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n", - addr, size); - found_addr = grub_claimmap (addr, size); - if (found_addr != -1) - break; - } - - if (found_addr == -1) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot claim memory"); + addr = grub_linux_claimmap_iterate (first_addr, size, 0x100000); + if (addr == (grub_addr_t) -1) goto fail; - } grub_dprintf ("loader", "Loading initrd at 0x%x, size 0x%x\n", addr, size);