diff --git a/ChangeLog b/ChangeLog index 9c0aeb2f0..a12ce00e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2007-02-12 Hollis Blanchard + + * include/grub/ieee1275/ieee1275.h: Update copyright. + * kern/powerpc/ieee1275/init.c: Likewise. + * kern/powerpc/ieee1275/openfw.c: Likewise. + + * loader/powerpc/ieee1275/linux.c: Likewise. + * include/grub/elfload.h: Likewise. + * kern/elf.c: Likewise. + (grub_elf32_load): Pass `base' and `size' parameters. Update all + callers. + (grub_elf64_load): Likewise. + (grub_elf32_load_segment): Move to a nested function. + (grub_elf64_load_segment): Likewise. + 2007-02-12 Hollis Blanchard * include/grub/ieee1275/ieee1275.h (grub_available_iterate): New diff --git a/include/grub/elfload.h b/include/grub/elfload.h index ad8c78125..7e17435d8 100644 --- a/include/grub/elfload.h +++ b/include/grub/elfload.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -46,10 +46,12 @@ grub_err_t grub_elf_close (grub_elf_t); int grub_elf_is_elf32 (grub_elf_t); grub_size_t grub_elf32_size (grub_elf_t); -grub_err_t grub_elf32_load (grub_elf_t, grub_elf32_load_hook_t); +grub_err_t grub_elf32_load (grub_elf_t, grub_elf32_load_hook_t, grub_addr_t *, + grub_size_t *); int grub_elf_is_elf64 (grub_elf_t); grub_size_t grub_elf64_size (grub_elf_t); -grub_err_t grub_elf64_load (grub_elf_t, grub_elf64_load_hook_t); +grub_err_t grub_elf64_load (grub_elf_t, grub_elf64_load_hook_t, grub_addr_t *, + grub_size_t *); #endif /* ! GRUB_ELFLOAD_HEADER */ diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index d6cccf529..09c7fcb3e 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -1,7 +1,7 @@ /* ieee1275.h - Access the Open Firmware client interface. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/kern/elf.c b/kern/elf.c index ecffadfd3..d10dca08d 100644 --- a/kern/elf.c +++ b/kern/elf.c @@ -1,7 +1,7 @@ /* elf.c - load ELF files */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -112,42 +112,6 @@ grub_elf_is_elf32 (grub_elf_t elf) return elf->ehdr.ehdr32.e_ident[EI_CLASS] == ELFCLASS32; } -static int -grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook) -{ - grub_elf32_load_hook_t load_hook = (grub_elf32_load_hook_t) hook; - grub_addr_t load_addr; - - if (phdr->p_type != PT_LOAD) - return 0; - - load_addr = phdr->p_paddr; - if (load_hook && load_hook (phdr, &load_addr)) - return 1; - - grub_dprintf ("elf", "Loading segment at %llx, size 0x%llx\n", - (unsigned long long) load_addr, - (unsigned long long) phdr->p_filesz); - - if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) - { - return grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program header"); - } - - if (phdr->p_filesz - && grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz) - != (grub_ssize_t) phdr->p_filesz) - { - return grub_error (GRUB_ERR_BAD_OS, "Couldn't load segment"); - } - - if (phdr->p_filesz < phdr->p_memsz) - grub_memset ((void *) (long) (load_addr + phdr->p_filesz), - 0, phdr->p_memsz - phdr->p_filesz); - - return 0; -} - static grub_err_t grub_elf32_load_phdrs (grub_elf_t elf) { @@ -240,11 +204,65 @@ grub_elf32_size (grub_elf_t elf) } -/* Load every loadable segment into memory specified by `load_hook'. */ +/* Load every loadable segment into memory specified by `_load_hook'. */ grub_err_t -grub_elf32_load (grub_elf_t elf, grub_elf32_load_hook_t load_hook) +grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook, + grub_addr_t *base, grub_size_t *size) { - return grub_elf32_phdr_iterate (elf, grub_elf32_load_segment, load_hook); + grub_addr_t load_base = (grub_addr_t) -1ULL; + grub_size_t load_size = 0; + grub_err_t err; + + auto int grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, + void *hook); + int grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook) + { + grub_elf32_load_hook_t load_hook = (grub_elf32_load_hook_t) hook; + grub_addr_t load_addr; + + if (phdr->p_type != PT_LOAD) + return 0; + + load_addr = phdr->p_paddr; + if (load_hook && load_hook (phdr, &load_addr)) + return 1; + + if (load_addr < load_base) + load_base = load_addr; + + grub_dprintf ("elf", "Loading segment at %llx, size 0x%llx\n", + (unsigned long long) load_addr, + (unsigned long long) phdr->p_filesz); + + if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) + { + return grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program header"); + } + + if (phdr->p_filesz + && grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz) + != (grub_ssize_t) phdr->p_filesz) + { + return grub_error (GRUB_ERR_BAD_OS, "Couldn't load segment"); + } + + if (phdr->p_filesz < phdr->p_memsz) + grub_memset ((void *) (long) (load_addr + phdr->p_filesz), + 0, phdr->p_memsz - phdr->p_filesz); + + load_size += phdr->p_memsz; + + return 0; + } + + err = grub_elf32_phdr_iterate (_elf, grub_elf32_load_segment, _load_hook); + + if (base) + *base = load_base; + if (size) + *size = load_size; + + return err; } @@ -257,41 +275,6 @@ grub_elf_is_elf64 (grub_elf_t elf) return elf->ehdr.ehdr64.e_ident[EI_CLASS] == ELFCLASS64; } -static int -grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr, void *hook) -{ - grub_elf64_load_hook_t load_hook = (grub_elf64_load_hook_t) hook; - grub_addr_t load_addr; - - if (phdr->p_type != PT_LOAD) - return 0; - - load_addr = phdr->p_paddr; - if (load_hook && load_hook (phdr, &load_addr)) - return 1; - - grub_dprintf ("elf", "Loading segment at %llx, size 0x%llx\n", - (unsigned long long) load_addr, - (unsigned long long) phdr->p_filesz); - - if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) - { - return grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program header"); - } - - if (grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz) - != (grub_ssize_t) phdr->p_filesz) - { - return grub_error (GRUB_ERR_BAD_OS, "Couldn't load segment"); - } - - if (phdr->p_filesz < phdr->p_memsz) - grub_memset ((void *) (long) (load_addr + phdr->p_filesz), - 0, phdr->p_memsz - phdr->p_filesz); - - return 0; -} - static grub_err_t grub_elf64_load_phdrs (grub_elf_t elf) { @@ -384,10 +367,65 @@ grub_elf64_size (grub_elf_t elf) } -/* Load every loadable segment into memory specified by `load_hook'. */ +/* Load every loadable segment into memory specified by `_load_hook'. */ grub_err_t -grub_elf64_load (grub_elf_t elf, grub_elf64_load_hook_t load_hook) +grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook, + grub_addr_t *base, grub_size_t *size) { - return grub_elf64_phdr_iterate (elf, grub_elf64_load_segment, load_hook); + grub_addr_t load_base = (grub_addr_t) -1ULL; + grub_size_t load_size = 0; + grub_err_t err; + + auto int grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr, + void *hook); + int grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr, void *hook) + { + grub_elf64_load_hook_t load_hook = (grub_elf64_load_hook_t) hook; + grub_addr_t load_addr; + + if (phdr->p_type != PT_LOAD) + return 0; + + load_addr = phdr->p_paddr; + if (load_hook && load_hook (phdr, &load_addr)) + return 1; + + if (load_addr < load_base) + load_base = load_addr; + + grub_dprintf ("elf", "Loading segment at %llx, size 0x%llx\n", + (unsigned long long) load_addr, + (unsigned long long) phdr->p_filesz); + + if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) + { + return grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program header"); + } + + if (phdr->p_filesz + && grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz) + != (grub_ssize_t) phdr->p_filesz) + { + return grub_error (GRUB_ERR_BAD_OS, "Couldn't load segment"); + } + + if (phdr->p_filesz < phdr->p_memsz) + grub_memset ((void *) (long) (load_addr + phdr->p_filesz), + 0, phdr->p_memsz - phdr->p_filesz); + + load_size += phdr->p_memsz; + + return 0; + } + + err = grub_elf64_phdr_iterate (_elf, grub_elf64_load_segment, _load_hook); + + if (base) + *base = load_base; + if (size) + *size = load_size; + + return err; } + diff --git a/kern/powerpc/ieee1275/init.c b/kern/powerpc/ieee1275/init.c index f28f5192f..435cc5360 100644 --- a/kern/powerpc/ieee1275/init.c +++ b/kern/powerpc/ieee1275/init.c @@ -1,7 +1,7 @@ /* init.c -- Initialize GRUB on the newworld mac (PPC). */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/kern/powerpc/ieee1275/openfw.c b/kern/powerpc/ieee1275/openfw.c index 30b4428cb..d2c885f66 100644 --- a/kern/powerpc/ieee1275/openfw.c +++ b/kern/powerpc/ieee1275/openfw.c @@ -1,7 +1,7 @@ /* openfw.c -- Open firmware support funtions. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/loader/powerpc/ieee1275/linux.c b/loader/powerpc/ieee1275/linux.c index b27402024..696e8ba01 100644 --- a/loader/powerpc/ieee1275/linux.c +++ b/loader/powerpc/ieee1275/linux.c @@ -1,7 +1,7 @@ /* linux.c - boot Linux */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -140,7 +140,7 @@ grub_linux_load32 (grub_elf_t elf) *addr = (phdr->p_paddr & ~ELF32_LOADMASK) + linux_addr; return 0; } - return grub_elf32_load (elf, offset_phdr); + return grub_elf32_load (elf, offset_phdr, 0, 0); } static grub_err_t @@ -183,7 +183,7 @@ grub_linux_load64 (grub_elf_t elf) *addr = (phdr->p_paddr & ~ELF64_LOADMASK) + linux_addr; return 0; } - return grub_elf64_load (elf, offset_phdr); + return grub_elf64_load (elf, offset_phdr, 0, 0); } void