grub-devel
[Top][All Lists]
Advanced

[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++)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]