grub-devel
[Top][All Lists]
Advanced

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

[PATCH] Updated ELF64 multiboot


From: Ruslan Nikolaev
Subject: [PATCH] Updated ELF64 multiboot
Date: Wed, 27 Jul 2005 17:56:34 -0500

Hi!

I've found some time and update patch. Now it contains functions grub_load_elf32, grub_load_elf64 and grub_load_elf. The changes are the same but now code splitted into 3 functions.

In fact I don't have free time at all now :(

 

New patch:

diff -urN old/multiboot.c new/multiboot.c
--- old/multiboot.c 2005-07-17 02:50:11.000000000 +0400
+++ new/multiboot.c 2005-07-27 18:52:44.000000000 +0400
@@ -81,6 +81,171 @@
   return GRUB_ERR_NONE;
 }
 
+static int
+grub_load_elf32(grub_file_t file, void *buffer)
+{
+  Elf32_Ehdr *ehdr = (Elf32_Ehdr *) buffer;
+  Elf32_Phdr *phdr;
+  int i;
+
+  if (ehdr->e_ident[EI_CLASS] != ELFCLASS32)
+    return -1;
+
+  if (grub_dl_check_header (ehdr, sizeof(Elf32_Ehdr)))
+    {
+      grub_error (GRUB_ERR_UNKNOWN_OS, "No valid ELF header found");
+      return -1;
+    }
+
+  if (ehdr->e_type != ET_EXEC)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
+      return -1;
+    }
+
+  /* FIXME: Should we support program headers at strange locations?  */
+  if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_MB_SEARCH)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_OS, "Program header at a too high offset");
+      return -1;
+    }
+  entry = ehdr->e_entry;
+
+  /* Load every loadable segment in memory.  */
+  for (i = 0; i < ehdr->e_phnum; i++)
+    {
+      phdr = (Elf32_Phdr *) ((char *) 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");
+              return -1;
+            }
+
+          if (grub_file_seek (file, phdr->p_offset) == -1)
+            {
+              grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program header");
+              return -1;
+            }
+
+          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");
+              return -1;
+            }
+
+          if (phdr->p_filesz < phdr->p_memsz)
+            grub_memset ((char *) phdr->p_paddr + phdr->p_filesz, 0,
+                phdr->p_memsz - phdr->p_filesz);
+        }
+    }
+  return 0;
+}
+
+static int
+grub_load_elf64(grub_file_t file, void *buffer)
+{
+  Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer;
+  Elf64_Phdr *phdr;
+  int i;
+
+  if (ehdr->e_ident[EI_CLASS] != ELFCLASS64)
+    return -1;
+
+  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)
+    {
+      grub_error(GRUB_ERR_UNKNOWN_OS, "No valid ELF header found");
+      return -1;
+    }
+  if (ehdr->e_type != ET_EXEC)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
+      return -1;
+    }
+
+  /* FIXME: Should we support program headers at strange locations?  */
+  if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_MB_SEARCH)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_OS, "Program header at a too high offset");
+      return -1;
+    }
+  /* We still in 32-bit mode */
+  if (ehdr->e_entry > 0xffffffff)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_OS, "Invalid entry point for ELF64");
+      return -1;
+    }
+    entry = ehdr->e_entry;
+
+  /* Load every loadable segment in memory.  */
+  for (i = 0; i < ehdr->e_phnum; i++)
+    {
+      phdr = (Elf64_Phdr *) ((char *) 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_uint64_t) grub_os_area_addr)
+              || (phdr->p_paddr + phdr->p_memsz
+              > (grub_uint64_t) grub_os_area_addr + (grub_uint64_t) grub_os_area_size))
+            {
+              grub_error (GRUB_ERR_BAD_OS,
+                  "Segment doesn't fit in memory reserved for the OS");
+              return -1;
+            }
+
+           if (grub_file_seek (file, phdr->p_offset) == -1)
+            {
+              grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program header");
+              return -1;
+            }
+
+           if (grub_file_read (file, (void *) ((grub_uint32_t) phdr->p_paddr), phdr->p_filesz)
+              != (grub_ssize_t) phdr->p_filesz)
+            {
+              grub_error (GRUB_ERR_BAD_OS, "Couldn't read segment from file");
+              return -1;
+            }
+
+          if (phdr->p_filesz < phdr->p_memsz)
+           grub_memset ((char *) ((grub_uint32_t) phdr->p_paddr) + phdr->p_filesz, 0,
+                 phdr->p_memsz - phdr->p_filesz);
+        }
+    }
+  return 0;
+}
+
+static void grub_load_elf(grub_file_t file, void *buffer)
+{
+  if (grub_load_elf32(file, buffer) < 0)
+    {
+       /* Error occured during loading ELF32 */
+       if (grub_errno)
+         return;
+
+       /* Otherwise it's possible that ELFCLASS is not 32-bit */
+       if (grub_load_elf64(file, buffer) < 0)
+         {
+            if (grub_errno)
+              return;
+
+            grub_error(GRUB_ERR_BAD_OS, "Class of ELF file is unsupported");
+         }
+    }
+}
+
 void
 grub_rescue_cmd_multiboot (int argc, char *argv[])
 {
@@ -89,7 +254,6 @@
   struct grub_multiboot_header *header;
   grub_ssize_t len;
   int i;
-  Elf32_Ehdr *ehdr;
 
   grub_dl_ref (my_mod);
 
@@ -138,65 +302,10 @@
       goto fail;
     }
 
-  ehdr = (Elf32_Ehdr *) buffer;
-
-  if (grub_dl_check_header (ehdr, sizeof(*ehdr)))
-    {
-      grub_error (GRUB_ERR_UNKNOWN_OS, "No valid ELF header found");
-      goto fail;
-    }
-
-  if (ehdr->e_type != ET_EXEC)
-    {
-      grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
-      goto fail;
-    }
-
-  /* FIXME: Should we support program headers at strange locations?  */
-  if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_MB_SEARCH)
-    {
-      grub_error (GRUB_ERR_UNKNOWN_OS, "Program header at a too high offset");
-      goto fail;
-    }
-
-  entry = ehdr->e_entry;
-
-  /* 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);
- }
-    }
+  /* Load ELF file */
+  grub_load_elf(file, buffer);
+  if (grub_errno)
+    goto fail;
 
   mbi = grub_malloc (sizeof (struct grub_multiboot_info));
   if (!mbi)


--

___________________________________________________________
Sign-up for Ads Free at Mail.com
http://www.mail.com/?sr=signup


reply via email to

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