=== 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-10-18 02:47:23 +0000 @@ -26,6 +26,7 @@ #include #include #include +#include #define ELF32_LOADMASK (0xc0000000UL) #define ELF64_LOADMASK (0xc000000000000000ULL) @@ -45,6 +46,50 @@ static char *linux_args; 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 = 0; + 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 addr_ant; + addr_ant = addr; + addr = ALIGN_UP (addr, align); + target = ALIGN_UP (target, align); + len -= addr - addr_ant; + + /*target above the memory chunk */ + if (type != 1 || target > addr + len) + return 0; + + /*target inside the memory chunk */ + if (target >= addr && target < addr + len && size <= addr + len - target) + { + if (grub_claimmap (target, size) == GRUB_ERR_NONE) + { + found = target; + return 1; + } + } + /*target below the memory chunk */ + if (target < addr && size <= len) + { + if (grub_claimmap (addr, size) == GRUB_ERR_NONE) + { + found = addr; + return 1; + } + } + return 0; + } + grub_machine_mmap_iterate (alloc_mem); + return found; +} + static grub_err_t grub_linux_boot (void) { @@ -103,7 +148,6 @@ static grub_err_t 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 +163,7 @@ grub_linux_load32 (grub_elf_t elf) /* 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) + if (!(linux_addr = grub_linux_claimmap_iterate (entry, linux_size, 0x100000))) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't claim memory"); /* Now load the segments into the area we claimed. */ @@ -153,7 +189,6 @@ static grub_err_t 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 +204,7 @@ grub_linux_load64 (grub_elf_t elf) /* 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) + if (!(linux_addr = grub_linux_claimmap_iterate (entry, linux_size, 0x100000))) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't claim memory"); /* Now load the segments into the area we claimed. */ @@ -287,7 +314,6 @@ grub_cmd_initrd (grub_command_t cmd __at grub_ssize_t size; grub_addr_t first_addr; grub_addr_t addr; - int found_addr = 0; if (argc == 0) { @@ -311,16 +337,7 @@ grub_cmd_initrd (grub_command_t cmd __at /* 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) + if (!(addr = grub_linux_claimmap_iterate (first_addr, size, 0x100000))) { grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot claim memory"); goto fail;