grub-devel
[Top][All Lists]
Advanced

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

[PATCH] new ELF64 patch


From: Ruslan Nikolaev
Subject: [PATCH] new ELF64 patch
Date: Sat, 16 Jul 2005 17:54:39 -0500

Hi! 
 
Ok patch for x86_64 ELF64 support was rewritten. 
 
diff -urN old/multiboot.c new/multiboot.c 
--- old/multiboot.c     2005-07-17 02:50:11.978394408 +0400 
+++ new/multiboot.c     2005-07-17 02:49:41.069093336 +0400 
@@ -89,7 +89,14 @@ 
   struct grub_multiboot_header *header; 
   grub_ssize_t len; 
   int i; 
-  Elf32_Ehdr *ehdr; 
+  union { 
+    Elf32_Ehdr *ehdr32; 
+    Elf64_Ehdr *ehdr64; 
+  } hdr; 
+  union { 
+    Elf32_Phdr *phdr32; 
+    Elf64_Phdr *phdr64; 
+  } seg; 
  
   grub_dl_ref (my_mod); 
  
@@ -138,64 +145,136 @@ 
       goto fail; 
     } 
  
-  ehdr = (Elf32_Ehdr *) buffer; 
+  hdr.ehdr32 = (Elf32_Ehdr *) buffer; 
  
-  if (grub_dl_check_header (ehdr, sizeof(*ehdr))) 
+  if (hdr.ehdr32->e_ident[EI_CLASS] == ELFCLASS64) /* ELF64 */ 
     { 
-      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; 
-    } 
+      /* we can't use grub_dl_check_header() for ELF64 under i386/amd64 */ 
+      if (hdr.ehdr64->e_ident[EI_MAG0] != ELFMAG0 
+          || hdr.ehdr64->e_ident[EI_MAG1] != ELFMAG1 
+          || hdr.ehdr64->e_ident[EI_MAG2] != ELFMAG2 
+          || hdr.ehdr64->e_ident[EI_MAG3] != ELFMAG3 
+          || hdr.ehdr64->e_version != EV_CURRENT 
+          || hdr.ehdr64->e_ident[EI_DATA] != ELFDATA2LSB 
+          || hdr.ehdr64->e_machine != EM_X86_64) 
+        { 
+          grub_error(GRUB_ERR_UNKNOWN_OS, "No valid ELF header found"); 
+          goto fail; 
+        } 
+      if (hdr.ehdr64->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 (hdr.ehdr64->e_phoff + hdr.ehdr64->e_phnum * hdr.ehdr64->e_phentsize 
> GRUB_MB_SEARCH) 
+        { 
+          grub_error (GRUB_ERR_UNKNOWN_OS, "Program header at a too high 
offset"); 
+          goto fail; 
+        } 
+      /* we still in 32-bit mode */ 
+      if (hdr.ehdr64->e_entry >= 0xffffffff) 
+        { 
+          grub_error (GRUB_ERR_UNKNOWN_OS, "Invalid entry point for ELF64"); 
+          goto fail; 
+        } 
+      entry = hdr.ehdr64->e_entry; 
+ 
+      /* Load every loadable segment in memory.  */ 
+      for (i = 0; i < hdr.ehdr64->e_phnum; i++) 
+        { 
+          seg.phdr64 = (Elf64_Phdr *) (buffer + hdr.ehdr64->e_phoff + i * 
hdr.ehdr64->e_phentsize); 
+ 
+          if (seg.phdr64->p_type == PT_LOAD) 
+        { 
+          /* The segment should fit in the area reserved for the OS.  */ 
+          if ((seg.phdr64->p_paddr < (grub_uint64_t)grub_os_area_addr)  
+              || (seg.phdr64->p_paddr + seg.phdr64->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"); 
+              goto fail; 
+            } 
+ 
+           if (grub_file_seek (file, seg.phdr64->p_offset) == -1) 
+            { 
+              grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program 
header"); 
+              goto fail; 
+            } 
+ 
+           if (grub_file_read (file, (void 
*)((grub_uint32_t)seg.phdr64->p_paddr), seg.phdr64->p_filesz)  
+              != (grub_ssize_t) seg.phdr64->p_filesz) 
+            { 
+              grub_error (GRUB_ERR_BAD_OS, "Couldn't read segment from file"); 
+              goto fail; 
+            } 
+ 
+          if (seg.phdr64->p_filesz < seg.phdr64->p_memsz) 
+           grub_memset ((char *)((grub_uint32_t)seg.phdr64->p_paddr) + 
seg.phdr64->p_filesz, 0,  
+                 seg.phdr64->p_memsz - seg.phdr64->p_filesz); 
+        } 
+        }       
+    } 
+  else /* ELF32 */ 
+    { 
+      if (grub_dl_check_header (hdr.ehdr32, sizeof(Elf32_Ehdr))) 
+        { 
+          grub_error (GRUB_ERR_UNKNOWN_OS, "No valid ELF header found"); 
+          goto fail; 
+        } 
+ 
+      if (hdr.ehdr32->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 (hdr.ehdr32->e_phoff + hdr.ehdr32->e_phnum * hdr.ehdr32->e_phentsize 
> GRUB_MB_SEARCH) 
+        { 
+          grub_error (GRUB_ERR_UNKNOWN_OS, "Program header at a too high 
offset"); 
+          goto fail; 
+        } 
+ 
+      entry = hdr.ehdr32->e_entry; 
+ 
+      /* Load every loadable segment in memory.  */ 
+      for (i = 0; i < hdr.ehdr32->e_phnum; i++) 
+        { 
+          seg.phdr32 = (Elf32_Phdr *) (buffer + hdr.ehdr32->e_phoff + i * 
hdr.ehdr32->e_phentsize); 
  
-  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)) 
+          if (seg.phdr32->p_type == PT_LOAD) 
            { 
-             grub_error (GRUB_ERR_BAD_OS,  
-                         "Segment doesn't fit in memory reserved for the OS"); 
-             goto fail; 
-           } 
+             /* The segment should fit in the area reserved for the OS.  */ 
+             if ((seg.phdr32->p_paddr < grub_os_area_addr)  
+                 || (seg.phdr32->p_paddr + seg.phdr32->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_seek (file, seg.phdr32->p_offset) == -1) 
+               { 
+                 grub_error (GRUB_ERR_BAD_OS, "Invalid offset in program 
header"); 
+                 goto fail; 
+               } 
+ 
+              if (grub_file_read (file, (void *) seg.phdr32->p_paddr, 
seg.phdr32->p_filesz)  
+                 != (grub_ssize_t) seg.phdr32->p_filesz) 
+               { 
+                 grub_error (GRUB_ERR_BAD_OS, "Couldn't read segment from 
file"); 
+                 goto fail; 
+               } 
+ 
+             if (seg.phdr32->p_filesz < seg.phdr32->p_memsz) 
+              grub_memset ((char *) seg.phdr32->p_paddr + 
seg.phdr32->p_filesz, 0,  
+                            seg.phdr32->p_memsz - seg.phdr32->p_filesz); 
            } 
- 
-         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); 
-       } 
+        } 
     } 
  
   mbi = grub_malloc (sizeof (struct grub_multiboot_info)); 
 

-- 
___________________________________________________________
Sign-up for Ads Free at Mail.com
http://promo.mail.com/adsfreejump.htm





reply via email to

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