grub-devel
[Top][All Lists]
Advanced

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

ELF64 patch


From: Ruslan Nikolaev
Subject: ELF64 patch
Date: Wed, 13 Jul 2005 18:19:56 -0500

Hi all! 
 
I'm developing free x86_64 (amd64) operation system now. I decided to make the 
kernel 
 
multiboot-complient and use grub2 as a boot loader. 
Of course I have some problems: 
 
1. AMD64 processor require to enable paging and to fill page tables before 
entering 
long  
mode (64-bit mode). 
   In that case bootloader should leave processor in 32-bit protected mode. 
   All switching to 64-bit mode should be done by the kernel. 
   => we can use usual i386 boot loader 
 
2. It's better to have kernel and modules as ELF64 executables for amd64. 
   The patch below adds ELF64 support for multiboot (grub2): 
 
patch for file grub2/loader/i386/pc/multiboot.c: 
----------------------------------------------- 
 
diff -urN old/multiboot.c new/multiboot.c 
--- old/multiboot.c     Wed Jul  6 04:25:16 2005 
+++ new/multiboot.c     Fri Jul  8 02:38:12 2005 
@@ -81,6 +81,45 @@ 
   return GRUB_ERR_NONE; 
 } 
  
+/* the following routine allows to load x86_64 ELF */ 
+static void 
+x86_elf64to32(char *buffer) 
+{ 
+  register int i; 
+  union 
+    { 
+      Elf32_Ehdr *addr32; 
+      Elf64_Ehdr *addr64; 
+    } ehdr; 
+  union 
+    { 
+      Elf32_Phdr *addr32; 
+      Elf64_Phdr *addr64; 
+    } phdr; 
+ 
+  /* convert header */ 
+  ehdr.addr64 = (Elf64_Ehdr *)buffer; 
+  ehdr.addr32->e_entry = ehdr.addr64->e_entry; 
+  ehdr.addr32->e_phoff = ehdr.addr64->e_phoff; 
+  ehdr.addr32->e_shoff = ehdr.addr64->e_shoff; 
+  memcpy(&ehdr.addr32->e_flags, &ehdr.addr64->e_flags, 16); 
+ 
+  /* convert program header table */ 
+  for (i = 0; i < ehdr.addr32->e_phnum; i++) 
+    { 
+      register Elf32_Word flags; 
+      phdr.addr64 = (Elf64_Phdr *)(buffer + ehdr.addr32->e_phoff + i * 
ehdr.addr32- 
>e_phentsize); 
+      flags = phdr.addr64->p_flags; 
+      phdr.addr32->p_offset = phdr.addr64->p_offset; 
+      phdr.addr32->p_vaddr = phdr.addr64->p_vaddr; 
+      phdr.addr32->p_paddr = phdr.addr64->p_paddr; 
+      phdr.addr32->p_filesz = phdr.addr64->p_filesz; 
+      phdr.addr32->p_memsz = phdr.addr64->p_memsz; 
+      phdr.addr32->p_align = phdr.addr64->p_align; 
+      phdr.addr32->p_flags = flags; 
+    } 
+} 
+ 
 void 
 grub_rescue_cmd_multiboot (int argc, char *argv[]) 
 { 
@@ -140,8 +179,20 @@ 
  
   ehdr = (Elf32_Ehdr *) buffer; 
  
-  if (grub_dl_check_header (ehdr, sizeof(*ehdr))) 
+  /* convert ELF64 for x86_64 to ELF32 for i386 */ 
+  if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) 
+    { 
+      ehdr->e_ident[EI_CLASS] = ELFCLASS32; 
+      if (ehdr->e_machine == EM_X86_64) 
+          ehdr->e_machine = EM_386; 
+      if (grub_dl_check_header(ehdr, sizeof(*ehdr))) 
+          goto bad_header; 
+      x86_elf64to32(buffer); 
+    } 
+  /* usual ELF32 for i386 */ 
+  else if (grub_dl_check_header (ehdr, sizeof(*ehdr))) 
     { 
+      bad_header: 
       grub_error (GRUB_ERR_UNKNOWN_OS, "No valid ELF header found"); 
       goto fail; 
     } 
 
-------------- 
Best regards, 
Ruslan Nikolaev 

-- 
___________________________________________________________
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]