commit-grub
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[2008] 2009-02-27 Robert Millan <address@hidden>


From: Robert Millan
Subject: [2008] 2009-02-27 Robert Millan <address@hidden>
Date: Fri, 27 Feb 2009 23:04:47 +0000

Revision: 2008
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=2008
Author:   robertmh
Date:     2009-02-27 23:04:46 +0000 (Fri, 27 Feb 2009)
Log Message:
-----------
2009-02-27  Robert Millan  <address@hidden>

        Factorize elf32 / elf64 code in Multiboot loader.  This will
        prevent it from getting out of sync again.

        * loader/i386/multiboot.c (grub_multiboot_is_elf32,
        grub_multiboot_load_elf32, grub_multiboot_is_elf64,
        grub_multiboot_load_elf64): Move from here ...
        * loader/i386/multiboot_elfxx.c (grub_multiboot_is_elf,
        grub_multiboot_load_elf): ... to here (new file).

Modified Paths:
--------------
    trunk/grub2/ChangeLog
    trunk/grub2/loader/i386/multiboot.c

Added Paths:
-----------
    trunk/grub2/loader/i386/multiboot_elfxx.c

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog       2009-02-27 21:37:07 UTC (rev 2007)
+++ trunk/grub2/ChangeLog       2009-02-27 23:04:46 UTC (rev 2008)
@@ -1,5 +1,16 @@
 2009-02-27  Robert Millan  <address@hidden>
 
+       Factorize elf32 / elf64 code in Multiboot loader.  This will
+       prevent it from getting out of sync again.
+
+       * loader/i386/multiboot.c (grub_multiboot_is_elf32,
+       grub_multiboot_load_elf32, grub_multiboot_is_elf64,
+       grub_multiboot_load_elf64): Move from here ...
+       * loader/i386/multiboot_elfxx.c (grub_multiboot_is_elf,
+       grub_multiboot_load_elf): ... to here (new file).
+
+2009-02-27  Robert Millan  <address@hidden>
+
        * util/grub.d/10_linux.in: Rename "single-user mode" to
        "recovery mode".
 

Modified: trunk/grub2/loader/i386/multiboot.c
===================================================================
--- trunk/grub2/loader/i386/multiboot.c 2009-02-27 21:37:07 UTC (rev 2007)
+++ trunk/grub2/loader/i386/multiboot.c 2009-02-27 23:04:46 UTC (rev 2008)
@@ -124,181 +124,14 @@
   grub_machine_mmap_iterate (hook);
 }
 
-/* Check if BUFFER contains ELF32.  */
-static int
-grub_multiboot_is_elf32 (void *buffer)
-{
-  Elf32_Ehdr *ehdr = (Elf32_Ehdr *) buffer;
+#define MULTIBOOT_LOAD_ELF64
+#include "multiboot_elfxx.c"
+#undef MULTIBOOT_LOAD_ELF64
 
-  return ehdr->e_ident[EI_CLASS] == ELFCLASS32;
-}
+#define MULTIBOOT_LOAD_ELF32
+#include "multiboot_elfxx.c"
+#undef MULTIBOOT_LOAD_ELF32
 
-static grub_err_t
-grub_multiboot_load_elf32 (grub_file_t file, void *buffer)
-{
-  Elf32_Ehdr *ehdr = (Elf32_Ehdr *) buffer;
-  char *phdr_base;
-  int lowest_segment = 0, highest_segment = 0;
-  int i;
-
-  if (ehdr->e_ident[EI_CLASS] != ELFCLASS32)
-    return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
-
-  if (grub_dl_check_header (ehdr, sizeof(Elf32_Ehdr)))
-    return grub_error (GRUB_ERR_UNKNOWN_OS, "no valid ELF header found");
-
-  if (ehdr->e_type != ET_EXEC)
-    return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
-
-  /* FIXME: Should we support program headers at strange locations?  */
-  if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH)
-    return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
-
-  phdr_base = (char *) buffer + ehdr->e_phoff;
-#define phdr(i)                        ((Elf32_Phdr *) (phdr_base + (i) * 
ehdr->e_phentsize))
-
-  for (i = 0; i < ehdr->e_phnum; i++)
-    if (phdr(i)->p_type == PT_LOAD && phdr(i)->p_filesz != 0)
-      {
-       if (phdr(i)->p_paddr < phdr(lowest_segment)->p_paddr)
-         lowest_segment = i;
-       if (phdr(i)->p_paddr > phdr(highest_segment)->p_paddr)
-         highest_segment = i;
-      }
-  grub_multiboot_payload_size += (phdr(highest_segment)->p_paddr + 
phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
-  grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr;
-
-  playground = grub_malloc (RELOCATOR_SIZEOF(forward) + 
grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
-  if (! playground)
-    return grub_errno;
-
-  grub_multiboot_payload_orig = (long) playground + RELOCATOR_SIZEOF(forward);
-
-  /* Load every loadable segment in memory.  */
-  for (i = 0; i < ehdr->e_phnum; i++)
-    {
-      if (phdr(i)->p_type == PT_LOAD && phdr(i)->p_filesz != 0)
-        {
-         char *load_this_module_at = (char *) (grub_multiboot_payload_orig + 
(phdr(i)->p_paddr - phdr(lowest_segment)->p_paddr));
-
-         grub_dprintf ("multiboot_loader", "segment %d: paddr=%p, 
memsz=0x%x\n",
-                       i, (void *) phdr(i)->p_paddr, phdr(i)->p_memsz);
-
-         if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset)
-             == (grub_off_t) -1)
-           return grub_error (GRUB_ERR_BAD_OS,
-                              "invalid offset in program header");
-
-          if (grub_file_read (file, load_this_module_at, phdr(i)->p_filesz)
-              != (grub_ssize_t) phdr(i)->p_filesz)
-           return grub_error (GRUB_ERR_BAD_OS,
-                              "couldn't read segment from file");
-
-          if (phdr(i)->p_filesz < phdr(i)->p_memsz)
-            grub_memset (load_this_module_at + phdr(i)->p_filesz, 0,
-                        phdr(i)->p_memsz - phdr(i)->p_filesz);
-        }
-    }
-
-  grub_multiboot_payload_entry_offset = ehdr->e_entry - 
phdr(lowest_segment)->p_vaddr;
-
-#undef phdr
-
-  return grub_errno;
-}
-
-/* Check if BUFFER contains ELF64.  */
-static int
-grub_multiboot_is_elf64 (void *buffer)
-{
-  Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer;
-
-  return ehdr->e_ident[EI_CLASS] == ELFCLASS64;
-}
-
-static grub_err_t
-grub_multiboot_load_elf64 (grub_file_t file, void *buffer)
-{
-  Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer;
-  char *phdr_base;
-  grub_addr_t physical_entry_addr = 0;
-  int i;
-
-  if (ehdr->e_ident[EI_CLASS] != ELFCLASS64)
-    return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
-
-  if (ehdr->e_ident[EI_MAG0] != ELFMAG0
-      || ehdr->e_ident[EI_MAG1] != ELFMAG1
-      || ehdr->e_ident[EI_MAG2] != ELFMAG2
-      || ehdr->e_ident[EI_MAG3] != ELFMAG3
-      || ehdr->e_version != EV_CURRENT
-      || ehdr->e_ident[EI_DATA] != ELFDATA2LSB
-      || ehdr->e_machine != EM_X86_64)
-    return grub_error(GRUB_ERR_UNKNOWN_OS, "no valid ELF header found");
-
-  if (ehdr->e_type != ET_EXEC)
-    return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
-
-  /* FIXME: Should we support program headers at strange locations?  */
-  if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH)
-    return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
-
-  /* We still in 32-bit mode */
-  if (ehdr->e_entry > 0xffffffff)
-    return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64");
-
-  entry = ehdr->e_entry;
-
-  phdr_base = (char *) buffer + ehdr->e_phoff;
-#define phdr(i)                        ((Elf64_Phdr *) (phdr_base + (i) * 
ehdr->e_phentsize))
-
-  /* Load every loadable segment in memory.  */
-  for (i = 0; i < ehdr->e_phnum; i++)
-    {
-      if (phdr(i)->p_type == PT_LOAD)
-        {
-          /* The segment should fit in the area reserved for the OS.  */
-          if (phdr(i)->p_paddr < (grub_uint64_t) grub_os_area_addr)
-           return grub_error (GRUB_ERR_BAD_OS,
-                              "segment doesn't fit in memory reserved for the 
OS (0x%lx < 0x%lx)",
-                              phdr(i)->p_paddr, (grub_uint64_t) 
grub_os_area_addr);
-          if (phdr(i)->p_paddr + phdr(i)->p_memsz
-                 > (grub_uint64_t) grub_os_area_addr + (grub_uint64_t) 
grub_os_area_size)
-           return grub_error (GRUB_ERR_BAD_OS,
-                              "segment doesn't fit in memory reserved for the 
OS (0x%lx > 0x%lx)",
-                              phdr(i)->p_paddr + phdr(i)->p_memsz,
-                              (grub_uint64_t) grub_os_area_addr + 
(grub_uint64_t) grub_os_area_size);
-
-         if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset)
-             == (grub_off_t) -1)
-           return grub_error (GRUB_ERR_BAD_OS,
-                              "invalid offset in program header");
-
-         if (grub_file_read (file, (void *) ((grub_uint32_t) phdr(i)->p_paddr),
-                             phdr(i)->p_filesz)
-              != (grub_ssize_t) phdr(i)->p_filesz)
-           return grub_error (GRUB_ERR_BAD_OS,
-                              "couldn't read segment from file");
-
-          if (phdr(i)->p_filesz < phdr(i)->p_memsz)
-           grub_memset (((char *) ((grub_uint32_t) phdr(i)->p_paddr)
-                         + phdr(i)->p_filesz),
-                        0,
-                        phdr(i)->p_memsz - phdr(i)->p_filesz);
-
-         if ((entry >= phdr(i)->p_vaddr) &&
-             (entry < phdr(i)->p_vaddr + phdr(i)->p_memsz))
-           physical_entry_addr = entry + phdr(i)->p_paddr - phdr(i)->p_vaddr;
-        }
-    }
-#undef phdr
-
-  if (physical_entry_addr)
-    entry = physical_entry_addr;
-
-  return grub_errno;
-}
-
 /* Load ELF32 or ELF64.  */
 static grub_err_t
 grub_multiboot_load_elf (grub_file_t file, void *buffer)
@@ -460,7 +293,7 @@
 
   grub_multiboot_payload_size = ALIGN_UP (grub_multiboot_payload_size, 
MULTIBOOT_INFO_ALIGN);
 
-  mbi = grub_multiboot_payload_orig + grub_multiboot_payload_size - 
mmap_length - sizeof (struct grub_multiboot_info);
+  mbi = (void *) (grub_multiboot_payload_orig + grub_multiboot_payload_size - 
mmap_length - sizeof (struct grub_multiboot_info));
   grub_memset (mbi, 0, sizeof (struct grub_multiboot_info));
   mbi->mmap_length = mmap_length;
       

Added: trunk/grub2/loader/i386/multiboot_elfxx.c
===================================================================
--- trunk/grub2/loader/i386/multiboot_elfxx.c                           (rev 0)
+++ trunk/grub2/loader/i386/multiboot_elfxx.c   2009-02-27 23:04:46 UTC (rev 
2008)
@@ -0,0 +1,137 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009  Free 
Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if defined(MULTIBOOT_LOAD_ELF32)
+# define XX            32
+# define E_MACHINE     EM_386
+# define ELFCLASSXX    ELFCLASS32
+# define Elf_Ehdr      Elf32_Ehdr
+# define Elf_Phdr      Elf32_Phdr
+#elif defined(MULTIBOOT_LOAD_ELF64)
+# define XX            64
+# define E_MACHINE     EM_X86_64
+# define ELFCLASSXX    ELFCLASS64
+# define Elf_Ehdr      Elf64_Ehdr
+# define Elf_Phdr      Elf64_Phdr
+#else
+#error "I'm confused"
+#endif
+
+#define CONCAT(a,b)    CONCAT_(a, b)
+#define CONCAT_(a,b)   a ## b
+
+/* Check if BUFFER contains ELF32 (or ELF64).  */
+static int
+CONCAT(grub_multiboot_is_elf, XX) (void *buffer)
+{
+  Elf_Ehdr *ehdr = (Elf_Ehdr *) buffer;
+
+  return ehdr->e_ident[EI_CLASS] == ELFCLASSXX;
+}
+
+static grub_err_t
+CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
+{
+  Elf_Ehdr *ehdr = (Elf_Ehdr *) buffer;
+  char *phdr_base;
+  int lowest_segment = 0, highest_segment = 0;
+  int i;
+
+  if (ehdr->e_ident[EI_CLASS] != ELFCLASSXX)
+    return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
+
+  if (ehdr->e_ident[EI_MAG0] != ELFMAG0
+      || ehdr->e_ident[EI_MAG1] != ELFMAG1
+      || ehdr->e_ident[EI_MAG2] != ELFMAG2
+      || ehdr->e_ident[EI_MAG3] != ELFMAG3
+      || ehdr->e_version != EV_CURRENT
+      || ehdr->e_ident[EI_DATA] != ELFDATA2LSB
+      || ehdr->e_machine != E_MACHINE)
+    return grub_error(GRUB_ERR_UNKNOWN_OS, "no valid ELF header found");
+
+  if (ehdr->e_type != ET_EXEC)
+    return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
+
+  /* FIXME: Should we support program headers at strange locations?  */
+  if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH)
+    return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
+
+#ifdef MULTIBOOT_LOAD_ELF64
+  /* We still in 32-bit mode.  */
+  if (ehdr->e_entry > 0xffffffff)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64");
+#endif
+
+  phdr_base = (char *) buffer + ehdr->e_phoff;
+#define phdr(i)                        ((Elf_Phdr *) (phdr_base + (i) * 
ehdr->e_phentsize))
+
+  for (i = 0; i < ehdr->e_phnum; i++)
+    if (phdr(i)->p_type == PT_LOAD && phdr(i)->p_filesz != 0)
+      {
+       if (phdr(i)->p_paddr < phdr(lowest_segment)->p_paddr)
+         lowest_segment = i;
+       if (phdr(i)->p_paddr > phdr(highest_segment)->p_paddr)
+         highest_segment = i;
+      }
+  grub_multiboot_payload_size += (phdr(highest_segment)->p_paddr + 
phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
+  grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr;
+
+  playground = grub_malloc (RELOCATOR_SIZEOF(forward) + 
grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
+  if (! playground)
+    return grub_errno;
+
+  grub_multiboot_payload_orig = (long) playground + RELOCATOR_SIZEOF(forward);
+
+  /* Load every loadable segment in memory.  */
+  for (i = 0; i < ehdr->e_phnum; i++)
+    {
+      if (phdr(i)->p_type == PT_LOAD && phdr(i)->p_filesz != 0)
+        {
+         char *load_this_module_at = (char *) (grub_multiboot_payload_orig + 
(long) (phdr(i)->p_paddr - phdr(lowest_segment)->p_paddr));
+
+         grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, 
memsz=0x%lx\n",
+                       i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz);
+
+         if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset)
+             == (grub_off_t) -1)
+           return grub_error (GRUB_ERR_BAD_OS,
+                              "invalid offset in program header");
+
+          if (grub_file_read (file, load_this_module_at, phdr(i)->p_filesz)
+              != (grub_ssize_t) phdr(i)->p_filesz)
+           return grub_error (GRUB_ERR_BAD_OS,
+                              "couldn't read segment from file");
+
+          if (phdr(i)->p_filesz < phdr(i)->p_memsz)
+            grub_memset (load_this_module_at + phdr(i)->p_filesz, 0,
+                        phdr(i)->p_memsz - phdr(i)->p_filesz);
+        }
+    }
+
+  grub_multiboot_payload_entry_offset = ehdr->e_entry - 
phdr(lowest_segment)->p_vaddr;
+
+#undef phdr
+
+  return grub_errno;
+}
+
+#undef XX
+#undef E_MACHINE
+#undef ELFCLASSXX
+#undef Elf_Ehdr
+#undef Elf_Phdr





reply via email to

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