diff options
Diffstat (limited to 'extra/source/grub/grub-0.97-x86_64.patch')
-rw-r--r-- | extra/source/grub/grub-0.97-x86_64.patch | 809 |
1 files changed, 809 insertions, 0 deletions
diff --git a/extra/source/grub/grub-0.97-x86_64.patch b/extra/source/grub/grub-0.97-x86_64.patch new file mode 100644 index 00000000..480e38fc --- /dev/null +++ b/extra/source/grub/grub-0.97-x86_64.patch @@ -0,0 +1,809 @@ +diff -Naur grub-0.97.orig/docs/multiboot.h grub-0.97.patched/docs/multiboot.h +--- grub-0.97.orig/docs/multiboot.h 2003-07-09 05:45:36.000000000 -0600 ++++ grub-0.97.patched/docs/multiboot.h 2006-08-26 22:44:02.000000000 -0600 +@@ -44,76 +44,81 @@ + /* Do not include here in boot.S. */ + + /* Types. */ ++#ifndef __x86_64__ ++typedef unsigned long UINT32; ++#else ++typedef unsigned UINT32; ++#endif + + /* The Multiboot header. */ + typedef struct multiboot_header + { +- unsigned long magic; +- unsigned long flags; +- unsigned long checksum; +- unsigned long header_addr; +- unsigned long load_addr; +- unsigned long load_end_addr; +- unsigned long bss_end_addr; +- unsigned long entry_addr; ++ UINT32 magic; ++ UINT32 flags; ++ UINT32 checksum; ++ UINT32 header_addr; ++ UINT32 load_addr; ++ UINT32 load_end_addr; ++ UINT32 bss_end_addr; ++ UINT32 entry_addr; + } multiboot_header_t; + + /* The symbol table for a.out. */ + typedef struct aout_symbol_table + { +- unsigned long tabsize; +- unsigned long strsize; +- unsigned long addr; +- unsigned long reserved; ++ UINT32 tabsize; ++ UINT32 strsize; ++ UINT32 addr; ++ UINT32 reserved; + } aout_symbol_table_t; + + /* The section header table for ELF. */ + typedef struct elf_section_header_table + { +- unsigned long num; +- unsigned long size; +- unsigned long addr; +- unsigned long shndx; ++ UINT32 num; ++ UINT32 size; ++ UINT32 addr; ++ UINT32 shndx; + } elf_section_header_table_t; + + /* The Multiboot information. */ + typedef struct multiboot_info + { +- unsigned long flags; +- unsigned long mem_lower; +- unsigned long mem_upper; +- unsigned long boot_device; +- unsigned long cmdline; +- unsigned long mods_count; +- unsigned long mods_addr; ++ UINT32 flags; ++ UINT32 mem_lower; ++ UINT32 mem_upper; ++ UINT32 boot_device; ++ UINT32 cmdline; ++ UINT32 mods_count; ++ UINT32 mods_addr; + union + { + aout_symbol_table_t aout_sym; + elf_section_header_table_t elf_sec; + } u; +- unsigned long mmap_length; +- unsigned long mmap_addr; ++ UINT32 mmap_length; ++ UINT32 mmap_addr; + } multiboot_info_t; + + /* The module structure. */ + typedef struct module + { +- unsigned long mod_start; +- unsigned long mod_end; +- unsigned long string; +- unsigned long reserved; ++ UINT32 mod_start; ++ UINT32 mod_end; ++ UINT32 string; ++ UINT32 reserved; + } module_t; + + /* The memory map. Be careful that the offset 0 is base_addr_low + but no size. */ + typedef struct memory_map + { +- unsigned long size; +- unsigned long base_addr_low; +- unsigned long base_addr_high; +- unsigned long length_low; +- unsigned long length_high; +- unsigned long type; ++ UINT32 size; ++ UINT32 base_addr_low; ++ UINT32 base_addr_high; ++ UINT32 length_low; ++ UINT32 length_high; ++ UINT32 type; + } memory_map_t; + + #endif /* ! ASM */ +diff -Naur grub-0.97.orig/docs/x86_64.txt grub-0.97.patched/docs/x86_64.txt +--- grub-0.97.orig/docs/x86_64.txt 1969-12-31 17:00:00.000000000 -0700 ++++ grub-0.97.patched/docs/x86_64.txt 2006-10-10 10:39:42.000000000 -0600 +@@ -0,0 +1,81 @@ ++[PATCH] - Make GRUB recognize and boot an x86_64 elf image ++ ++ ++HOW IT WORKS ++------------ ++* Grub interface is unchanged. ++* Upon passing an elf-x86_64 file via "kernel=", GRUB will load and parse it ++ correctly. ++* Upon the "boot" directive, GRUB will switch from protected 32-bit ++ mode to long 64-bit mode and transfer control to the image's entrypoint. ++ ++ ++INSTALL ++------- ++cd grub-0.97 ++patch -p1 < grub-x86_64-elf.patch ++./configure ++make ++su -c "make install" ++ ++Note: You do not need to re-install your bootsectors, but you WILL need ++ to copy the modified stage2 file(s) from /usr/share/grub to ++ your actual boot filesystem (usually /boot/grub for GNU/Linux). ++ ++ ++WHY? ++---- ++Because in our world, all elves and elf images are created equal, and have ++been endowed with the ability to be bootable. :-) ++ ++ ++THE NITTY GRITTY - GRUB SIDE ++---------------------------- ++* Since paging is manditory in 64-bit long mode, the first 4GB of physical ++ memory (whether present or not) is identity mapped into the linear ++ address space using 2MB pages. ++* Paging data structures are written to physical 0x70000-0x75fff in the ++ same area reserved for the raw device buffer. This happens after the ++ "boot" command is issued so the raw device buffer won't mind. Paging ++ can be relocated and reconfigured after the kernel is running. ++* Header files have been added to describe the x86_64 elf image structure. ++ ++ ++THE NITTY GRITTY - KERNEL SIDE ++------------------------------ ++* Parameters passed to the assembly entrypoint are unchanged including ++ magic number and pointer to multiboot info structure. ++* The assembly entrypoint should be designated as ".code64". ++* The Global Descriptor Table (GDT) shared by the GRUB and KERNEL sides ++ has been expanded to include 3 additional 64-bit ('L' bit set) segments: ++ 0x28 (code) and 0x30 (data). ++* An updated "multiboot.h" file is provided to reflect the difference in ++ "unsigned long" sizes between i386 and x86_64 architectures for use by ++ the client kernel. ++ ++ ++CAVEATS ++------- ++Possible collisions with existing GRUB patch sets are unknown. Use "darcs" ++and worry not. ++ ++ http://abridgegame.org/darcs ++ ++(An intelligent alternative to cvs and greying hair in the distributed ++post-mainframe age.) ++ ++ ++DOCUMENTATION CHANGES ++--------------------- ++This is it. Sorry, stuff to do. ++ ++ ++APOLOGIES TO GRUB2 ++------------------ ++We would have liked to use GRUB2 for this, but needed it today for our ++kernel. Of course there is probably no technical reason why this ++functionality cannot be in included in GRUB2 at a future time. Thank you ++for a way cool bootloader and may all your boots be bogon (and Vogon) free. ++ ++<mcnster@gmail.com> ++October 10, 2006 +diff -Naur grub-0.97.orig/grub/asmstub.c grub-0.97.patched/grub/asmstub.c +--- grub-0.97.orig/grub/asmstub.c 2005-02-16 13:45:14.000000000 -0700 ++++ grub-0.97.patched/grub/asmstub.c 2006-08-26 22:43:24.000000000 -0600 +@@ -313,6 +313,12 @@ + stop (); + } + ++void ++multi_boot_64bit_doit (int start, int mb_info) ++{ ++ stop (); ++} ++ + /* sets it to linear or wired A20 operation */ + void + gateA20 (int linear) +diff -Naur grub-0.97.orig/stage2/asm.S grub-0.97.patched/stage2/asm.S +--- grub-0.97.orig/stage2/asm.S 2004-06-19 10:55:22.000000000 -0600 ++++ grub-0.97.patched/stage2/asm.S 2006-09-25 14:59:48.000000000 -0600 +@@ -1809,6 +1809,54 @@ + /* error */ + call EXT_C(stop) + ++ENTRY(multi_boot_64bit_doit) ++ call EXT_C(stop_floppy) ++ ++ /* dont squash these! */ ++ movl 0x8(%esp), %esi ++ movl 0x4(%esp), %edi ++ ++ cli ++ ++ mov %cr0, %eax ++ and $0x7fffffff, %eax ++ mov %eax, %cr0 ++ ++ /* enable pae */ ++ mov %cr4, %eax ++ or $0x20, %eax ++ mov %eax, %cr4 ++ ++ /* load cr3 with pml4 */ ++ mov $PML4, %eax ++ mov %eax, %cr3 ++ ++ /* trigger long mode */ ++ mov $0xc0000080, %ecx ++ rdmsr ++ or $0x100, %eax ++ wrmsr ++ ++ /* enable paging to actually switch modes */ ++ mov %cr0, %eax ++ or $0x80000000, %eax ++ mov %eax, %cr0 ++ ++ /* jump to relocation, flush prefetch queue, and reload %cs */ ++ ljmp $0x28, $longmode ++.code64 ++longmode: ++ mov $0x2BADB002, %eax ++ ++ mov %rsi, %rbx ++ and $0xffffffff, %rsi ++ ++ and $0xffffffff, %rdi ++ call *%rdi ++ /* NOTREACHED */ ++ call EXT_C(stop) ++ ++.code32 + #endif /* ! STAGE1_5 */ + + /* +@@ -2341,27 +2389,35 @@ + + .p2align 2 /* force 4-byte alignment */ + gdt: +- .word 0, 0 ++ .word 0, 0 /* 0x0000 */ + .byte 0, 0, 0, 0 + +- /* code segment */ ++ /* code segment */ /* 0x0008 */ + .word 0xFFFF, 0 + .byte 0, 0x9A, 0xCF, 0 + +- /* data segment */ ++ /* data segment */ /* 0x0010 */ + .word 0xFFFF, 0 + .byte 0, 0x92, 0xCF, 0 + +- /* 16 bit real mode CS */ ++ /* 16 bit real mode CS */ /* 0x0018 */ + .word 0xFFFF, 0 + .byte 0, 0x9E, 0, 0 + +- /* 16 bit real mode DS */ ++ /* 16 bit real mode DS/SS */ /* 0x0020 */ + .word 0xFFFF, 0 + .byte 0, 0x92, 0, 0 + ++ /* 64 bit long mode CS */ /* 0x0028 */ ++ .word 0xFFFF, 0 ++ .byte 0, 0x9A, 0xAF, 0 ++ ++ /* 64-bit long mode SS */ /* 0x0030 */ ++ .word 0xFFFF, 0 ++ .byte 0, 0x92, 0xAF, 0 + + /* this is the GDT descriptor */ + gdtdesc: +- .word 0x27 /* limit */ ++ .word 0x33 /* limit */ + .long gdt /* addr */ ++ .long 0 /* in case we go to 64-bit mode */ +diff -Naur grub-0.97.orig/stage2/boot.c grub-0.97.patched/stage2/boot.c +--- grub-0.97.orig/stage2/boot.c 2004-03-30 04:44:08.000000000 -0700 ++++ grub-0.97.patched/stage2/boot.c 2006-08-25 22:20:17.000000000 -0600 +@@ -23,10 +23,11 @@ + + #include "freebsd.h" + #include "imgact_aout.h" +-#include "i386-elf.h" ++#include "elf.h" + + static int cur_addr; + entry_func entry_addr; ++unsigned long_64bit_mode = 0; + static struct mod_list mll[99]; + static int linux_mem_size; + +@@ -50,7 +51,7 @@ + { + struct multiboot_header *mb; + struct exec *aout; +- Elf32_Ehdr *elf; ++ Elf_Ehdr *elf; + } + pu; + /* presuming that MULTIBOOT_SEARCH is large enough to encompass an +@@ -100,21 +101,25 @@ + || pu.elf->e_ident[EI_OSABI] == ELFOSABI_FREEBSD + || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0 + || suggested_type == KERNEL_TYPE_NETBSD) +- && len > sizeof (Elf32_Ehdr) +- && BOOTABLE_I386_ELF ((*((Elf32_Ehdr *) buffer)))) ++ && len > SIZEOF_ELF_EHDR (pu.elf) ++ && (BOOTABLE_I386_ELF ((*((Elf32_Ehdr *) buffer))) ++ || BOOTABLE_X86_64_ELF ((*((Elf64_Ehdr *) buffer))))) + { ++ if (BOOTABLE_X86_64_ELF ((*((Elf64_Ehdr *) buffer)))) ++ long_64bit_mode = 1; ++ + if (type == KERNEL_TYPE_MULTIBOOT) +- entry_addr = (entry_func) pu.elf->e_entry; ++ entry_addr = (entry_func) E_ENTRY (pu.elf); + else +- entry_addr = (entry_func) (pu.elf->e_entry & 0xFFFFFF); ++ entry_addr = (entry_func) (E_ENTRY (pu.elf) & 0xFFFFFF); + + if (entry_addr < (entry_func) 0x100000) + errnum = ERR_BELOW_1MB; + + /* don't want to deal with ELF program header at some random + place in the file -- this generally won't happen */ +- if (pu.elf->e_phoff == 0 || pu.elf->e_phnum == 0 +- || ((pu.elf->e_phoff + (pu.elf->e_phentsize * pu.elf->e_phnum)) ++ if (E_PHOFF (pu.elf) == 0 || E_PHNUM (pu.elf) == 0 ++ || ((E_PHOFF (pu.elf) + (E_PHENTSIZE (pu.elf) * E_PHNUM (pu.elf))) + >= len)) + errnum = ERR_EXEC_FORMAT; + str = "elf"; +@@ -590,39 +595,38 @@ + /* ELF executable */ + { + unsigned loaded = 0, memaddr, memsiz, filesiz; +- Elf32_Phdr *phdr; ++ Elf_Phdr *phdr; + + /* reset this to zero for now */ + cur_addr = 0; + + /* scan for program segments */ +- for (i = 0; i < pu.elf->e_phnum; i++) ++ for (i = 0; i < E_PHNUM (pu.elf); i++) + { +- phdr = (Elf32_Phdr *) +- (pu.elf->e_phoff + ((int) buffer) +- + (pu.elf->e_phentsize * i)); +- if (phdr->p_type == PT_LOAD) ++ phdr = (Elf_Phdr *) (E_PHOFF (pu.elf) + ((int) buffer) ++ + (E_PHENTSIZE (pu.elf) * i)); ++ if (P_TYPE (pu.elf, phdr) == PT_LOAD) + { + /* offset into file */ +- grub_seek (phdr->p_offset); +- filesiz = phdr->p_filesz; ++ grub_seek (P_OFFSET (pu.elf, phdr)); ++ filesiz = P_FILESZ (pu.elf, phdr); + + if (type == KERNEL_TYPE_FREEBSD || type == KERNEL_TYPE_NETBSD) +- memaddr = RAW_ADDR (phdr->p_paddr & 0xFFFFFF); ++ memaddr = RAW_ADDR (P_PADDR (pu.elf, phdr) & 0xFFFFFF); + else +- memaddr = RAW_ADDR (phdr->p_paddr); ++ memaddr = RAW_ADDR (P_PADDR (pu.elf, phdr)); + +- memsiz = phdr->p_memsz; ++ memsiz = P_MEMSZ (pu.elf, phdr); + if (memaddr < RAW_ADDR (0x100000)) + errnum = ERR_BELOW_1MB; + + /* If the memory range contains the entry address, get the + physical address here. */ + if (type == KERNEL_TYPE_MULTIBOOT +- && (unsigned) entry_addr >= phdr->p_vaddr +- && (unsigned) entry_addr < phdr->p_vaddr + memsiz) ++ && (unsigned) entry_addr >= P_VADDR (pu.elf, phdr) ++ && (unsigned) entry_addr < P_VADDR (pu.elf, phdr) + memsiz) + real_entry_addr = (entry_func) ((unsigned) entry_addr +- + memaddr - phdr->p_vaddr); ++ + memaddr - P_VADDR (pu.elf, phdr)); + + /* make sure we only load what we're supposed to! */ + if (filesiz > memsiz) +@@ -654,26 +658,26 @@ + else + { + /* Load ELF symbols. */ +- Elf32_Shdr *shdr = NULL; ++ Elf_Shdr *shdr = NULL; + int tab_size, sec_size; + int symtab_err = 0; + +- mbi.syms.e.num = pu.elf->e_shnum; +- mbi.syms.e.size = pu.elf->e_shentsize; +- mbi.syms.e.shndx = pu.elf->e_shstrndx; ++ mbi.syms.e.num = E_SHNUM (pu.elf); ++ mbi.syms.e.size = E_SHENTSIZE (pu.elf); ++ mbi.syms.e.shndx = E_SHSTRNDX (pu.elf); + + /* We should align to a 4K boundary here for good measure. */ + if (align_4k) + cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000; + +- tab_size = pu.elf->e_shentsize * pu.elf->e_shnum; ++ tab_size = E_SHENTSIZE (pu.elf) * E_SHNUM (pu.elf); + +- grub_seek (pu.elf->e_shoff); ++ grub_seek (E_SHOFF (pu.elf)); + if (grub_read ((char *) RAW_ADDR (cur_addr), tab_size) + == tab_size) + { + mbi.syms.e.addr = cur_addr; +- shdr = (Elf32_Shdr *) mbi.syms.e.addr; ++ shdr = (Elf_Shdr *) mbi.syms.e.addr; + cur_addr += tab_size; + + printf (", shtab=0x%x", cur_addr); +@@ -682,20 +686,20 @@ + { + /* This section is a loaded section, + so we don't care. */ +- if (shdr[i].sh_addr != 0) ++ if (SH_ADDR_AT (pu.elf, shdr, i) != 0) + continue; + + /* This section is empty, so we don't care. */ +- if (shdr[i].sh_size == 0) ++ if (SH_SIZE_AT (pu.elf, shdr, i) == 0) + continue; + + /* Align the section to a sh_addralign bits boundary. */ +- cur_addr = ((cur_addr + shdr[i].sh_addralign) & +- - (int) shdr[i].sh_addralign); ++ cur_addr = ((cur_addr + SH_ADDRALIGN_AT (pu.elf, shdr, i)) & ++ - (int) SH_ADDRALIGN_AT (pu.elf, shdr, i)); + +- grub_seek (shdr[i].sh_offset); ++ grub_seek (SH_OFFSET_AT (pu.elf, shdr, i)); + +- sec_size = shdr[i].sh_size; ++ sec_size = SH_SIZE_AT (pu.elf, shdr, i); + + if (! (memcheck (cur_addr, sec_size) + && (grub_read ((char *) RAW_ADDR (cur_addr), +@@ -706,7 +710,7 @@ + break; + } + +- shdr[i].sh_addr = cur_addr; ++ SET_SH_ADDR_AT (pu.elf, shdr, i, cur_addr); + cur_addr += sec_size; + } + } +diff -Naur grub-0.97.orig/stage2/builtins.c grub-0.97.patched/stage2/builtins.c +--- grub-0.97.orig/stage2/builtins.c 2005-02-15 14:58:23.000000000 -0700 ++++ grub-0.97.patched/stage2/builtins.c 2006-09-25 14:59:16.000000000 -0600 +@@ -81,6 +81,7 @@ + /* Prototypes for allowing straightfoward calling of builtins functions + inside other functions. */ + static int configfile_func (char *arg, int flags); ++static void multi_boot_64bit (int entry_addr, int mbi); + + /* Initialize the data for builtins. */ + void +@@ -297,8 +298,11 @@ + break; + + case KERNEL_TYPE_MULTIBOOT: +- /* Multiboot */ +- multi_boot ((int) entry_addr, (int) &mbi); ++ ++ if (long_64bit_mode) ++ multi_boot_64bit((int) entry_addr, (int) &mbi); ++ else ++ multi_boot ((int) entry_addr, (int) &mbi); + break; + + default: +@@ -309,6 +313,73 @@ + return 0; + } + ++#define TABLE_BITS 0x7 /* user, r/w, present */ ++#define PAGE_BITS 0x87 /* not pat, not global, not dirty, not accessed, user, r/w, present */ ++ ++#define NOT_PRESENT_TABLE 0x6 ++#define NOT_PRESENT_PAGE 0x86 ++ ++ ++static void ++multi_boot_64bit (int entry_addr, int mbi) ++{ ++ unsigned *pml4 = PML4; ++ unsigned *pdpt0x000 = PDPT0x000; ++ unsigned *pd0x000_000 = PD0x000_000; ++ unsigned *pd0x000_001 = PD0x000_001; ++ unsigned *pd0x000_002 = PD0x000_002; ++ unsigned *pd0x000_003 = PD0x000_003; ++ int i; ++ unsigned long base; ++ ++ /* identity map 1st 4 GB */ ++ ++ for (i = 0; i < 512; i++) ++ { ++ pml4[i * 2 + 0] = NOT_PRESENT_TABLE; ++ pml4[i * 2 + 1] = 0; ++ ++ pdpt0x000[i * 2 + 0] = NOT_PRESENT_TABLE; ++ pdpt0x000[i * 2 + 1] = 0; ++ ++ pd0x000_000[i * 2 + 0] = NOT_PRESENT_PAGE; ++ pd0x000_000[i * 2 + 1] = 0; ++ pd0x000_001[i * 2 + 0] = NOT_PRESENT_PAGE; ++ pd0x000_001[i * 2 + 1] = 0; ++ pd0x000_002[i * 2 + 0] = NOT_PRESENT_PAGE; ++ pd0x000_002[i * 2 + 1] = 0; ++ pd0x000_003[i * 2 + 0] = NOT_PRESENT_PAGE; ++ pd0x000_003[i * 2 + 1] = 0; ++ } ++ ++ pml4[0x000 * 2 + 0] = PDPT0x000 + TABLE_BITS; ++ pml4[0x000 * 2 + 1] = 0; ++ ++ pdpt0x000[0x000 * 2 + 0] = PD0x000_000 + TABLE_BITS; ++ pdpt0x000[0x000 * 2 + 1] = 0; ++ pdpt0x000[0x001 * 2 + 0] = PD0x000_001 + TABLE_BITS; ++ pdpt0x000[0x001 * 2 + 1] = 0; ++ pdpt0x000[0x002 * 2 + 0] = PD0x000_002 + TABLE_BITS; ++ pdpt0x000[0x002 * 2 + 1] = 0; ++ pdpt0x000[0x003 * 2 + 0] = PD0x000_003 + TABLE_BITS; ++ pdpt0x000[0x003 * 2 + 1] = 0; ++ ++ for (i = 0, base = 0; i < 1005; i++, base += 0x200000) ++ { ++ pd0x000_000[i * 2 + 0] = base + PAGE_BITS; ++ pd0x000_000[i * 2 + 1] = 0; ++ pd0x000_001[i * 2 + 0] = base + (1 * 0x200 * 0x20000) + PAGE_BITS; ++ pd0x000_001[i * 2 + 1] = 0; ++ pd0x000_002[i * 2 + 0] = base + (2 * 0x200 * 0x20000) + PAGE_BITS; ++ pd0x000_002[i * 2 + 1] = 0; ++ pd0x000_003[i * 2 + 0] = base + (3 * 0x200 * 0x20000) + PAGE_BITS; ++ pd0x000_003[i * 2 + 1] = 0; ++ } ++ ++ multi_boot_64bit_doit (entry_addr, mbi); ++ /* NOTREACHED */ ++} ++ + static struct builtin builtin_boot = + { + "boot", +diff -Naur grub-0.97.orig/stage2/elf.h grub-0.97.patched/stage2/elf.h +--- grub-0.97.orig/stage2/elf.h 1969-12-31 17:00:00.000000000 -0700 ++++ grub-0.97.patched/stage2/elf.h 2006-08-25 21:58:37.000000000 -0600 +@@ -0,0 +1,79 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2001,2002,2006 Free Software Foundation, Inc. ++ * ++ * This program 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 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++ ++#include "i386-elf.h" ++#include "x86-64-elf.h" ++ ++ ++typedef union ++{ ++ unsigned char e_ident[EI_NIDENT]; ++ Elf32_Ehdr elf32; ++ Elf64_Ehdr elf64; ++} ++Elf_Ehdr; ++ ++ ++typedef union ++{ ++ Elf32_Phdr elf32; ++ Elf64_Phdr elf64; ++} ++Elf_Phdr; ++ ++ ++typedef union ++{ ++ Elf32_Shdr elf32; ++ Elf64_Shdr elf64; ++} ++Elf_Shdr; ++ ++ ++#define SIZEOF_ELF_EHDR(h) (h->e_ident[EI_CLASS] == ELFCLASS32 ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)) ++ ++#define E_ENTRY(h) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? h->elf32.e_entry : h->elf64.e_entry)) ++#define E_PHOFF(h) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? h->elf32.e_phoff : h->elf64.e_phoff)) ++#define E_PHNUM(h) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? h->elf32.e_phnum : h->elf64.e_phnum)) ++#define E_PHENTSIZE(h) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? h->elf32.e_phentsize : h->elf64.e_phentsize)) ++#define E_SHNUM(h) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? h->elf32.e_shnum : h->elf64.e_shnum)) ++#define E_SHENTSIZE(h) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? h->elf32.e_shentsize : h->elf64.e_shentsize)) ++#define E_SHSTRNDX(h) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? h->elf32.e_shstrndx : h->elf64.e_shstrndx)) ++#define E_SHOFF(h) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? h->elf32.e_shoff : h->elf64.e_shoff)) ++ ++#define P_TYPE(h, p) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? p->elf32.p_type : p->elf64.p_type)) ++#define P_OFFSET(h, p) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? p->elf32.p_offset : p->elf64.p_offset)) ++#define P_PADDR(h, p) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? p->elf32.p_paddr : p->elf64.p_paddr)) ++#define P_MEMSZ(h, p) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? p->elf32.p_memsz : p->elf64.p_memsz)) ++#define P_VADDR(h, p) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? p->elf32.p_vaddr : p->elf64.p_vaddr)) ++#define P_FILESZ(h, p) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? p->elf32.p_filesz : p->elf64.p_filesz)) ++ ++#define SH_ADDR_AT(h, sh, i) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? ((&(sh->elf32))[i]).sh_addr : ((&(sh->elf64))[i]).sh_addr)) ++#define SH_SIZE_AT(h, sh, i) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? ((&(sh->elf32))[i]).sh_size : ((&(sh->elf64))[i]).sh_size)) ++#define SH_ADDRALIGN_AT(h, sh, i) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? ((&(sh->elf32))[i]).sh_addralign : ((&(sh->elf64))[i]).sh_addralign)) ++#define SH_OFFSET_AT(h, sh, i) ((unsigned) (h->e_ident[EI_CLASS] == ELFCLASS32 ? ((&(sh->elf32))[i]).sh_offset : ((&(sh->elf64))[i]).sh_offset)) ++ ++#define SET_SH_ADDR_AT(h, sh, i, v) \ ++ { \ ++ if (h->e_ident[EI_CLASS] == ELFCLASS32) \ ++ ((&(sh->elf32))[i]).sh_addr = v; \ ++ else \ ++ ((&(sh->elf64))[i]).sh_addr = v; \ ++ } +diff -Naur grub-0.97.orig/stage2/shared.h grub-0.97.patched/stage2/shared.h +--- grub-0.97.orig/stage2/shared.h 2004-06-19 10:40:09.000000000 -0600 ++++ grub-0.97.patched/stage2/shared.h 2006-09-25 14:54:53.000000000 -0600 +@@ -70,6 +70,13 @@ + + #define BOOT_PART_TABLE RAW_ADDR (0x07be) + ++#define PML4 0x70000 ++#define PDPT0x000 0x71000 ++#define PD0x000_000 0x72000 ++#define PD0x000_001 0x73000 ++#define PD0x000_002 0x74000 ++#define PD0x000_003 0x75000 ++ + /* + * BIOS disk defines + */ +@@ -692,6 +699,8 @@ + + extern entry_func entry_addr; + ++extern unsigned long_64bit_mode; ++ + /* Enter the stage1.5/stage2 C code after the stack is set up. */ + void cmain (void); + +@@ -739,6 +748,9 @@ + /* booting a multiboot executable */ + void multi_boot (int start, int mb_info) __attribute__ ((noreturn)); + ++/* boot into 64-bit long mode */ ++void multi_boot_64bit_doit (int start, int mb_info) __attribute__ ((noreturn)); ++ + /* If LINEAR is nonzero, then set the Intel processor to linear mode. + Otherwise, bit 20 of all memory accesses is always forced to zero, + causing a wraparound effect for bugwards compatibility with the +diff -Naur grub-0.97.orig/stage2/x86-64-elf.h grub-0.97.patched/stage2/x86-64-elf.h +--- grub-0.97.orig/stage2/x86-64-elf.h 1969-12-31 17:00:00.000000000 -0700 ++++ grub-0.97.patched/stage2/x86-64-elf.h 2006-08-26 21:45:22.000000000 -0600 +@@ -0,0 +1,86 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2001,2002,2006 Free Software Foundation, Inc. ++ * ++ * This program 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 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++ ++typedef unsigned short Elf64_Half; ++typedef unsigned long Elf64_Word; ++typedef unsigned long long Elf64_Off; ++typedef unsigned long long Elf64_Addr; ++typedef unsigned long long Elf64_Xword; ++ ++ ++typedef struct ++{ ++ unsigned char e_ident[EI_NIDENT]; /* basic identification block */ ++ Elf64_Half e_type; /* file types */ ++ Elf64_Half e_machine; /* machine types */ ++ Elf64_Word e_version; /* use same as "EI_VERSION" above */ ++ Elf64_Addr e_entry; /* entry point of the program */ ++ Elf64_Off e_phoff; /* program header table file offset */ ++ Elf64_Off e_shoff; /* section header table file offset */ ++ Elf64_Word e_flags; /* flags */ ++ Elf64_Half e_ehsize; /* elf header size in bytes */ ++ Elf64_Half e_phentsize; /* program header entry size */ ++ Elf64_Half e_phnum; /* number of entries in program header */ ++ Elf64_Half e_shentsize; /* section header entry size */ ++ Elf64_Half e_shnum; /* number of entries in section header */ ++ Elf64_Half e_shstrndx; /* section header table index */ ++} ++Elf64_Ehdr; ++ ++ ++typedef struct ++{ ++ Elf64_Word p_type; ++ Elf64_Word p_flags; ++ Elf64_Off p_offset; ++ Elf64_Addr p_vaddr; ++ Elf64_Addr p_paddr; ++ Elf64_Xword p_filesz; ++ Elf64_Xword p_memsz; ++ Elf64_Xword p_align; ++} ++Elf64_Phdr; ++ ++ ++typedef struct ++{ ++ Elf64_Word sh_name; /* Section name (string tbl index) */ ++ Elf64_Word sh_type; /* Section type */ ++ Elf64_Xword sh_flags; /* Section flags */ ++ Elf64_Addr sh_addr; /* Section virtual addr at execution */ ++ Elf64_Off sh_offset; /* Section file offset */ ++ Elf64_Xword sh_size; /* Section size in bytes */ ++ Elf64_Word sh_link; /* Link to another section */ ++ Elf64_Word sh_info; /* Additional section information */ ++ Elf64_Xword sh_addralign; /* Section alignment */ ++ Elf64_Xword sh_entsize; /* Entry size if section holds table */ ++} ++Elf64_Shdr; ++ ++#define ELFCLASS64 2 ++ ++#define EM_X86_64 0x3e ++ ++#define BOOTABLE_X86_64_ELF(h) \ ++ ((h.e_ident[EI_MAG0] == ELFMAG0) & (h.e_ident[EI_MAG1] == ELFMAG1) \ ++ & (h.e_ident[EI_MAG2] == ELFMAG2) & (h.e_ident[EI_MAG3] == ELFMAG3) \ ++ & (h.e_ident[EI_CLASS] == ELFCLASS64) & (h.e_ident[EI_DATA] == ELFDATA2LSB) \ ++ & (h.e_ident[EI_VERSION] == EV_CURRENT) & (h.e_type == ET_EXEC) \ ++ & (h.e_machine == EM_X86_64) & (h.e_version == EV_CURRENT)) |