[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
new ELF loader module
From: |
Guillem Jover |
Subject: |
new ELF loader module |
Date: |
Tue, 1 Feb 2005 05:56:32 +0100 |
User-agent: |
Mutt/1.5.6+20040907i |
Hi,
This patch merges some of the ELF static image loading functionality
into an independent elf module. Please test on PPC as I've only tested
this on x86.
2005-02-01 Guillem Jover <address@hidden>
* conf/i386-pc.rmk (pkg_MODULES): Add `elf.mod'.
(elf_mod_SOURCES): New variable.
(elf_mod_CFLAGS): Likewise.
* conf/powerpc-ieee1275.rmk: Likewise.
* loader/elf.c: New file.
* loader/i386/pc/multiboot.c (grub_rescue_cmd_multiboot): Use
grub_elf_load_static instead of explicit load loop.
* loader/powerpc/ieee1275/linux.c (grub_rescue_cmd_linux): Likewise.
Use grub_elf_phdr instead of explicit header load.
diff -Naupr -x CVS grub2.dl/conf/i386-pc.rmk grub2.elf/conf/i386-pc.rmk
--- grub2.dl/conf/i386-pc.rmk 2005-01-31 23:42:57.000000000 +0100
+++ grub2.elf/conf/i386-pc.rmk 2005-02-01 03:21:36.000000000 +0100
@@ -81,7 +81,8 @@ grub_emu_LDFLAGS = -lncurses
genmoddep_SOURCES = util/genmoddep.c
# Modules.
-pkgdata_MODULES = _chain.mod _linux.mod linux.mod fat.mod ufs.mod ext2.mod
minix.mod \
+pkgdata_MODULES = _chain.mod _linux.mod linux.mod elf.mod \
+ fat.mod ufs.mod ext2.mod minix.mod \
hfs.mod jfs.mod normal.mod hello.mod vga.mod font.mod _multiboot.mod
ls.mod \
boot.mod cmp.mod cat.mod terminal.mod fshelp.mod chain.mod
multiboot.mod \
amiga.mod apple.mod pc.mod loopback.mod reboot.mod halt.mod help.mod
@@ -126,6 +127,10 @@ jfs_mod_CFLAGS = $(COMMON_CFLAGS)
iso9660_mod_SOURCES = fs/iso9660.c
iso9660_mod_CFLAGS = $(COMMON_CFLAGS)
+# For elf.mod.
+elf_mod_SOURCES = loader/elf.c
+elf_mod_CFLAGS = $(COMMON_CFLAGS)
+
# For _linux.mod.
_linux_mod_SOURCES = loader/i386/pc/linux.c
_linux_mod_CFLAGS = $(COMMON_CFLAGS)
diff -Naupr -x CVS grub2.dl/conf/powerpc-ieee1275.rmk
grub2.elf/conf/powerpc-ieee1275.rmk
--- grub2.dl/conf/powerpc-ieee1275.rmk 2005-01-31 23:42:57.000000000 +0100
+++ grub2.elf/conf/powerpc-ieee1275.rmk 2005-02-01 03:21:36.000000000 +0100
@@ -62,7 +62,8 @@ grubof_LDFLAGS = -nostdlib -static-libgc
genmoddep_SOURCES = util/genmoddep.c
# Modules.
-pkgdata_MODULES = _linux.mod linux.mod fat.mod ufs.mod ext2.mod minix.mod \
+pkgdata_MODULES = _linux.mod linux.mod elf.mod \
+ fat.mod ufs.mod ext2.mod minix.mod \
hfs.mod jfs.mod normal.mod hello.mod font.mod \
boot.mod cmp.mod cat.mod terminal.mod fshelp.mod amiga.mod apple.mod \
pc.mod suspend.mod loopback.mod help.mod reboot.mod halt.mod
@@ -107,6 +108,10 @@ _linux_mod_CFLAGS = $(COMMON_CFLAGS)
linux_mod_SOURCES = loader/powerpc/ieee1275/linux_normal.c
linux_mod_CFLAGS = $(COMMON_CFLAGS)
+# For elf.mod.
+elf_mod_SOURCES = loader/elf.c
+elf_mod_CFLAGS = $(COMMON_CFLAGS)
+
# For normal.mod.
normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/main.c \
normal/menu.c normal/arg.c normal/powerpc/setjmp.S
diff -Naupr -x CVS grub2.dl/loader/elf.c grub2.elf/loader/elf.c
--- grub2.dl/loader/elf.c 1970-01-01 01:00:00.000000000 +0100
+++ grub2.elf/loader/elf.c 2005-02-01 05:52:12.000000000 +0100
@@ -0,0 +1,104 @@
+/* elf.c - ELF helper functions */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003, 2004, 2005 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/loader.h>
+#include <grub/elf.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+
+#if GRUB_HOST_SIZEOF_VOID_P == 4
+
+typedef Elf32_Addr Elf_Addr;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Phdr Elf_Phdr;
+
+#elif GRUB_HOST_SIZEOF_VOID_P == 8
+
+typedef Elf64_Addr Elf_Addr;
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Phdr Elf_Phdr;
+
+#endif
+
+
+Elf_Phdr *
+grub_elf_get_phdr (grub_file_t file, Elf_Ehdr *ehdr)
+{
+ Elf_Phdr *phdr = 0;
+
+ phdr = (Elf_Phdr *) grub_malloc (ehdr->e_phnum * ehdr->e_phentsize);
+
+ if (grub_file_seek (file, ehdr->e_phoff) == -1)
+ {
+ grub_error (GRUB_ERR_BAD_OS, "Invalid offset in ELF header");
+ return 0;
+ }
+
+ if (grub_file_read (file, (void *) phdr, ehdr->e_phnum * ehdr->e_phentsize)
+ != ehdr->e_phnum * ehdr->e_phentsize)
+ {
+ grub_error (GRUB_ERR_BAD_OS, "Couldn't read program header from file");
+ return 0;
+ }
+
+ return phdr;
+}
+
+grub_err_t
+grub_elf_load_static (grub_file_t file, Elf_Ehdr *ehdr, Elf_Phdr *phdrs,
+ Elf_Addr base_offs,
+ grub_addr_t base_addr, grub_size_t base_size)
+{
+ int i;
+
+ /* Load every loadable segment in memory. */
+ for (i = 0; i < ehdr->e_phnum; i++)
+ {
+ Elf_Phdr *phdr = (Elf_Phdr *) ((char *) phdrs + i * ehdr->e_phentsize);
+
+ if (phdr->p_type == PT_LOAD)
+ {
+ /* The segment should fit in the area reserved for the image. */
+ if ((phdr->p_paddr < base_addr)
+ || (phdr->p_paddr + phdr->p_memsz
+ > base_addr + base_size))
+ return grub_error (GRUB_ERR_BAD_OS,
+ "Segment doesn't fit in memory reserved for the
image");
+
+ if (grub_file_seek (file, phdr->p_offset) == -1)
+ return grub_error (GRUB_ERR_BAD_OS,
+ "Invalid offset in program header");
+
+ if (grub_file_read (file, (void *) (phdr->p_paddr + base_offs),
+ phdr->p_filesz)
+ != (grub_ssize_t) phdr->p_filesz)
+ return grub_error (GRUB_ERR_BAD_OS,
+ "Couldn't read segment from file");
+
+ if (phdr->p_filesz < phdr->p_memsz)
+ grub_memset ((char *) phdr->p_paddr + base_offs + phdr->p_filesz, 0,
+ phdr->p_memsz - phdr->p_filesz);
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
diff -Naupr -x CVS grub2.dl/loader/i386/pc/multiboot.c
grub2.elf/loader/i386/pc/multiboot.c
--- grub2.dl/loader/i386/pc/multiboot.c 2005-02-01 04:35:25.000000000 +0100
+++ grub2.elf/loader/i386/pc/multiboot.c 2005-02-01 04:40:29.000000000
+0100
@@ -90,6 +90,7 @@ grub_rescue_cmd_multiboot (int argc, cha
grub_ssize_t len;
int i;
Elf32_Ehdr *ehdr;
+ Elf32_Phdr *phdr;
grub_dl_ref (my_mod);
@@ -161,43 +162,11 @@ grub_rescue_cmd_multiboot (int argc, cha
}
entry = ehdr->e_entry;
+ phdr = (Elf32_Phdr *) (buffer + ehdr->e_phoff);
- /* Load every loadable segment in memory. */
- for (i = 0; i < ehdr->e_phnum; i++)
- {
- Elf32_Phdr *phdr;
- phdr = (Elf32_Phdr *) (buffer + ehdr->e_phoff + i * ehdr->e_phentsize);
-
- if (phdr->p_type == PT_LOAD)
- {
- /* The segment should fit in the area reserved for the OS. */
- if ((phdr->p_paddr < grub_os_area_addr)
- || (phdr->p_paddr + phdr->p_memsz
- > grub_os_area_addr + grub_os_area_size))
- {
- grub_error (GRUB_ERR_BAD_OS,
- "Segment doesn't fit in memory reserved for the OS");
- goto fail;
- }
-
- if (grub_file_seek (file, phdr->p_offset) == -1)
- {
- grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program header");
- goto fail;
- }
-
- if (grub_file_read (file, (void *) phdr->p_paddr, phdr->p_filesz)
- != (grub_ssize_t) phdr->p_filesz)
- {
- grub_error (GRUB_ERR_BAD_OS, "Couldn't read segment from file");
- goto fail;
- }
-
- if (phdr->p_filesz < phdr->p_memsz)
- grub_memset ((char *) phdr->p_paddr + phdr->p_filesz, 0,
- phdr->p_memsz - phdr->p_filesz);
- }
- }
+ if (grub_elf_load_static (file, ehdr, phdr, 0, grub_os_area_addr,
+ grub_os_area_size))
+ goto fail;
mbi = grub_malloc (sizeof (struct grub_multiboot_info));
if (!mbi)
diff -Naupr -x CVS grub2.dl/loader/powerpc/ieee1275/linux.c
grub2.elf/loader/powerpc/ieee1275/linux.c
--- grub2.dl/loader/powerpc/ieee1275/linux.c 2005-02-01 04:03:26.000000000
+0100
+++ grub2.elf/loader/powerpc/ieee1275/linux.c 2005-02-01 04:41:31.000000000
+0100
@@ -147,8 +147,9 @@ grub_rescue_cmd_linux (int argc, char *a
else
vmlinux = 0;
- phdrs = (Elf32_Phdr *) grub_malloc (ehdr.e_phnum * ehdr.e_phentsize);
- grub_file_read (file, (void *) phdrs, ehdr.e_phnum * ehdr.e_phentsize);
+ phdrs = grub_elf_get_phdr (file, ehdr);
+ if (! phdrs)
+ goto fail;
/* Release the previously used memory. */
grub_loader_unset ();
@@ -180,31 +181,10 @@ grub_rescue_cmd_linux (int argc, char *a
goto fail;
}
entry = linux_addr;
-
- /* Load every loadable segment in memory. */
- for (i = 0; i < ehdr.e_phnum; i++)
- {
- Elf32_Phdr *phdr = phdrs + i;
- if (phdr->p_type == PT_LOAD)
- {
- if (grub_file_seek (file, phdr->p_offset) == -1)
- {
- grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program header");
- goto fail;
- }
-
- if (grub_file_read (file, (void *) (((char *) entry) + offset) ,
phdr->p_filesz)
- != (grub_ssize_t) phdr->p_filesz)
- goto fail;
-
- if (phdr->p_filesz < phdr->p_memsz)
- grub_memset ((char *) (((char *) entry) + offset) + phdr->p_filesz,
0,
- phdr->p_memsz - phdr->p_filesz);
+ if (grub_elf_load_static (file, ehdr, phdrs, entry, linux_addr, linux_size))
+ goto fail;
- offset += phdr->p_filesz;
- }
- }
size = 0;
for (i = 0; i < argc; i++)
- new ELF loader module,
Guillem Jover <=