]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2009-05-17 Vladimir Serbinenko <phcoder@gmail.com>
authorphcoder <phcoder@localhost>
Sun, 17 May 2009 11:27:08 +0000 (11:27 +0000)
committerphcoder <phcoder@localhost>
Sun, 17 May 2009 11:27:08 +0000 (11:27 +0000)
trampoline for linux on 64-bit platform

* conf/x86_64-efi.rmk (linux_mod_SOURCES): added
loader/i386/efi/linux_trampoline.S
* include/grub/x86_64/efi/loader.h (grub_linux_real_boot): removed
declration
* kern/x86_64/efi/startup.S (grub_linux_real_boot): moved from here
* loader/i386/linux_trampoline.S: moved here
* loader/i386/efi/linux.c (allocate_pages): reserve space for trampoline
(jumpvector): removed
(grub_linux_trampoline_start): new declaration
(grub_linux_trampoline_end): likewise
(grub_linux_boot): use trampoline when on 64-bit platform
* loader/i386/linux.c: likewise

ChangeLog
conf/x86_64-efi.rmk
include/grub/x86_64/efi/loader.h
kern/x86_64/efi/startup.S
loader/i386/efi/linux.c
loader/i386/linux.c
loader/i386/linux_trampoline.S [new file with mode: 0644]

index 371a7ed3b7d15b5ed9fe1bf8323b9400c46c0f99..191ce8a344beecaef2267409bd3f114964f7f22f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2009-05-17  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       trampoline for linux on 64-bit platform
+
+       * conf/x86_64-efi.rmk (linux_mod_SOURCES): added 
+       loader/i386/efi/linux_trampoline.S 
+       * include/grub/x86_64/efi/loader.h (grub_linux_real_boot): removed 
+       declration
+       * kern/x86_64/efi/startup.S (grub_linux_real_boot): moved from here
+       * loader/i386/linux_trampoline.S: moved here
+       * loader/i386/efi/linux.c (allocate_pages): reserve space for trampoline
+       (jumpvector): removed
+       (grub_linux_trampoline_start): new declaration
+       (grub_linux_trampoline_end): likewise
+       (grub_linux_boot): use trampoline when on 64-bit platform
+       * loader/i386/linux.c: likewise
+
 2009-05-16  Pavel Roskin  <proski@gnu.org>
 
        * script/lua/grub_lib.c (grub_lua_getenv): Make name and value
index 391cda312ff42b3ff9df1c672bc35946b35a2cd9..5d342b37f656db1c8c185578b6ba861097ff54cf 100644 (file)
@@ -137,7 +137,7 @@ appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
 appleldr_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For linux.mod.
-linux_mod_SOURCES = loader/i386/efi/linux.c
+linux_mod_SOURCES = loader/i386/efi/linux.c loader/i386/linux_trampoline.S
 linux_mod_CFLAGS = $(COMMON_CFLAGS)
 linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
index fac67463b979fee96b5adb5ddf5f4a4abcb8b017..7c302e8a5b5c472565d5c940e0531f153207d463 100644 (file)
@@ -22,6 +22,5 @@
 #include <grub/types.h>
 #include <grub/symbol.h>
 
-void EXPORT_FUNC(grub_linux_real_boot) (void);
 
 #endif /* ! GRUB_LOADER_MACHINE_HEADER */
index 2cb1fd4a5c54c6f3f5f0ccf12f942c4b4367f3c6..fb4fc7b64b6d66bcf105a35afba9568a080c3c50 100644 (file)
@@ -61,26 +61,3 @@ codestart:
        call    EXT_C(grub_main)
        ret
 
-       .code32
-
-FUNCTION(grub_linux_real_boot)
-        /* Turn off PG bit in CR0 and set CR3 to zero.  */
-        movl    %cr0, %eax
-        andl    $0x7FFFFFFF, %eax
-        movl    %eax, %cr0
-
-        /* Setup EFER (Extended Feature Enable Register).  */
-        movl    $0xc0000080, %ecx
-        rdmsr
-
-        /* Disable Long Mode.  */
-        andl    $0xFFFFFEFF, %eax
-
-        /* Make changes effective.  */
-        wrmsr
-
-        /* Disable PAE.  */
-        xorl    %eax, %eax
-        movl    %eax, %cr4
-
-        jmp     *%ebx
index 9be88aa79930a547cde430af332d7e7d15c0a087..dae0f6dcdf4a0edbd1dbe77d0e4c523d8fa858f2 100644 (file)
@@ -241,7 +241,7 @@ allocate_pages (grub_size_t prot_size)
              
   /* Next, find free pages for the protected mode code.  */
   /* XXX what happens if anything is using this address?  */
-  prot_mode_mem = grub_efi_allocate_pages (0x100000, prot_mode_pages);
+  prot_mode_mem = grub_efi_allocate_pages (0x100000, prot_mode_pages + 1);
   if (! prot_mode_mem)
     {
       grub_error (GRUB_ERR_OUT_OF_MEMORY,
@@ -286,11 +286,8 @@ grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
 }
 
 #ifdef __x86_64__
-struct
-{
-  grub_uint32_t kernel_entry;
-  grub_uint32_t kernel_cs;
-} jumpvector;
+extern grub_uint8_t grub_linux_trampoline_start[];
+extern grub_uint8_t grub_linux_trampoline_end[];
 #endif
 
 static grub_err_t
@@ -384,6 +381,18 @@ grub_linux_boot (void)
       params->v0204.efi_mmap_size = mmap_size;
     }
 
+#ifdef __x86_64__
+  
+  grub_memcpy ((char *) prot_mode_mem + (prot_mode_pages << 12), 
+              grub_linux_trampoline_start, 
+              grub_linux_trampoline_end - grub_linux_trampoline_start);
+  
+  ((void (*) (unsigned long, void *)) ((char *) prot_mode_mem 
+                                     + (prot_mode_pages << 12)))
+    (params->code32_start, real_mode_mem);
+
+#else
+
   /* Hardware interrupts are not safe any longer.  */
   asm volatile ("cli" : : );
   
@@ -391,18 +400,6 @@ grub_linux_boot (void)
   asm volatile ("lidt %0" : : "m" (idt_desc));
   asm volatile ("lgdt %0" : : "m" (gdt_desc));
 
-#ifdef __x86_64__
-
-  jumpvector.kernel_entry = (grub_uint64_t) grub_linux_real_boot;
-  jumpvector.kernel_cs = 0x10;
-
-  asm volatile ( "mov %0, %%rbx" : : "m" (params->code32_start));
-  asm volatile ( "mov %0, %%rsi" : : "m" (real_mode_mem));
-
-  asm volatile ( "ljmp *%0" : : "m" (jumpvector));
-
-#else
-
   /* Pass parameters.  */
   asm volatile ("movl %0, %%ecx" : : "m" (params->code32_start));
   asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem));
index 8a7288ecd67f624b5cbc6c66bd51f1d97816d1f9..ca44fb46f8428f10b2d40b17c0022ca70bdf7ba4 100644 (file)
@@ -433,11 +433,8 @@ grub_linux_setup_video (struct linux_kernel_params *params)
 }
 
 #ifdef __x86_64__
-struct
-{
-  grub_uint32_t kernel_entry;
-  grub_uint32_t kernel_cs;
-} jumpvector;
+extern grub_uint8_t grub_linux_trampoline_start[];
+extern grub_uint8_t grub_linux_trampoline_end[];
 #endif
 
 static grub_err_t
@@ -549,6 +546,16 @@ grub_linux_boot (void)
   grub_mmap_iterate (hook);
   params->mmap_size = e820_num;
 
+#ifdef __x86_64__
+
+  grub_memcpy ((char *) prot_mode_mem + (prot_mode_pages << 12), 
+              grub_linux_trampoline_start, 
+              grub_linux_trampoline_end - grub_linux_trampoline_start);
+  
+  ((void (*) (unsigned long, void *)) ((char *) prot_mode_mem 
+                                      + (prot_mode_pages << 12)))
+    (params->code32_start, real_mode_mem);
+#else
 
   /* Hardware interrupts are not safe any longer.  */
   asm volatile ("cli" : : );
@@ -557,18 +564,6 @@ grub_linux_boot (void)
   asm volatile ("lidt %0" : : "m" (idt_desc));
   asm volatile ("lgdt %0" : : "m" (gdt_desc));
 
-#ifdef __x86_64__
-
-  jumpvector.kernel_entry = (grub_uint64_t) grub_linux_real_boot;
-  jumpvector.kernel_cs = 0x10;
-
-  asm volatile ( "mov %0, %%rbx" : : "m" (params->code32_start));
-  asm volatile ( "mov %0, %%rsi" : : "m" (real_mode_mem));
-
-  asm volatile ( "ljmp *%0" : : "m" (jumpvector));
-
-#else
-
   /* Pass parameters.  */
   asm volatile ("movl %0, %%ecx" : : "m" (params->code32_start));
   asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem));
diff --git a/loader/i386/linux_trampoline.S b/loader/i386/linux_trampoline.S
new file mode 100644 (file)
index 0000000..39821e1
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/symbol.h>
+       
+
+       .p2align        4       /* force 16-byte alignment */
+VARIABLE(grub_linux_trampoline_start)
+       cli
+       /* %rdi contains protected memory start and %rsi
+       contains real memory start. */
+
+       mov %rsi, %rbx
+       
+       call base
+base:  
+       pop %rsi
+       
+       lea (cont1-base)(%rsi, 1), %rax
+       mov %eax, (jump_vector-base)(%rsi,1)
+
+       lea (gdt-base)(%rsi, 1), %rax
+       mov %rax, (gdtaddr-base)(%rsi,1)
+       
+       /* Switch to compatibility mode. */
+
+       lidt (idtdesc-base)(%rsi,1)
+       lgdt (gdtdesc-base)(%rsi,1)
+       
+       /* Update %cs. Thanks to David Miller for pointing this mistake out. */
+       ljmp *(jump_vector-base)(%rsi,1)
+cont1:
+       .code32
+
+       /* Update other registers. */
+       mov $0x18, %eax
+       mov %eax, %ds 
+       mov %eax, %es
+       mov %eax, %fs
+       mov %eax, %gs
+       mov %eax, %ss
+
+       /* Disable paging. */
+       mov %cr0, %eax
+       and $0x7fffffff, %eax
+       mov %eax, %cr0
+
+       /* Disable amd64. */
+       mov $0xc0000080, %ecx
+       rdmsr
+       and $0xfffffeff, %eax
+       wrmsr
+
+       /* Turn off PAE. */
+       movl %cr4, %eax
+       and $0xffffffcf, %eax
+       mov %eax, %cr4
+
+       jmp cont2
+cont2: 
+       .code32
+       
+       mov %ebx, %esi
+
+       jmp *%edi
+
+       /* GDT. */
+       .p2align 4
+gdt:   
+       /* NULL.  */
+       .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       
+       /* Reserved.  */
+       .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       
+       /* Code segment.  */
+       .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00
+       
+       /* Data segment.  */
+       .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
+
+gdtdesc:       
+       .word 31
+gdtaddr:       
+       .quad gdt
+
+idtdesc:       
+       .word 0
+idtaddr:       
+       .quad 0
+
+       .p2align 4
+jump_vector:
+       /* Jump location. Is filled by the code */
+       .long 0
+       .long 0x10      
+VARIABLE(grub_linux_trampoline_end)