summaryrefslogtreecommitdiff
path: root/extra/source/grub/grub-0.97-x86_64.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extra/source/grub/grub-0.97-x86_64.patch')
-rw-r--r--extra/source/grub/grub-0.97-x86_64.patch809
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))