summaryrefslogtreecommitdiffstats
path: root/extra/source/grub
diff options
context:
space:
mode:
Diffstat (limited to 'extra/source/grub')
-rw-r--r--extra/source/grub/grub-0.97-x86_64.patch809
-rwxr-xr-xextra/source/grub/grub.SlackBuild121
-rw-r--r--extra/source/grub/grub_support_256byte_inode.patch94
-rw-r--r--extra/source/grub/grubconfig_localefix.patch32
-rw-r--r--extra/source/grub/slack-desc19
5 files changed, 1075 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 000000000..480e38fce
--- /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))
diff --git a/extra/source/grub/grub.SlackBuild b/extra/source/grub/grub.SlackBuild
new file mode 100755
index 000000000..417cb6364
--- /dev/null
+++ b/extra/source/grub/grub.SlackBuild
@@ -0,0 +1,121 @@
+#!/bin/sh
+
+# Copyright 2009 Patrick J. Volkerding, Sebeka, MN, USA
+# All rights reserved.
+#
+# Redistribution and use of this script, with or without modification, is
+# permitted provided that the following conditions are met:
+#
+# 1. Redistributions of this script must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+VERSION=0.97
+GCVER=1.28
+ARCH=${ARCH:-x86_64}
+BUILD=7
+
+NUMJOBS=${NUMJOBS:-" -j7 "}
+
+if [ "$ARCH" = "i486" ]; then
+ SLKCFLAGS="-O2 -march=i486 -mtune=i686"
+elif [ "$ARCH" = "s390" ]; then
+ SLKCFLAGS="-O2"
+elif [ "$ARCH" = "x86_64" ]; then
+ SLKCFLAGS="-O2"
+fi
+
+CWD=$(pwd)
+TMP=${TMP:-/tmp}
+PKG=$TMP/package-grub
+
+rm -rf $PKG
+mkdir -p $PKG $TMP
+cd $TMP
+rm -rf grub-$VERSION
+tar xvf $CWD/grub-$VERSION.tar.gz || exit 1
+cd grub-$VERSION || exit 1
+
+# This is needed for the optional (but now default) increase in
+# inode size from 128 to 256 bytes with ext2 and ext3:
+zcat $CWD/grub_support_256byte_inode.patch.gz | patch -p1 --verbose || exit 1
+
+zcat $CWD/grub-0.97-x86_64.patch.gz | patch -p1 || exit 1
+
+chown -R root:root .
+find . \
+ \( -perm 777 -o -perm 775 -o -perm 711 -o -perm 555 -o -perm 511 \) \
+ -exec chmod 755 {} \; -o \
+ \( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
+ -exec chmod 644 {} \;
+
+CFLAGS="$SLKCFLAGS" \
+./configure \
+ --prefix=/usr \
+ --infodir=/usr/info \
+ --mandir=/usr/man
+
+make $NUMJOBS || make || exit 1
+make install DESTDIR=$PKG || exit 1
+
+find $PKG | xargs file | grep -e "executable" -e "shared object" \
+ | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
+
+# Compress and if needed symlink the man pages:
+if [ -d $PKG/usr/man ]; then
+ ( cd $PKG/usr/man
+ for manpagedir in $(find . -type d -name "man*") ; do
+ ( cd $manpagedir
+ for eachpage in $( find . -type l -maxdepth 1) ; do
+ ln -s $( readlink $eachpage ).gz $eachpage.gz
+ rm $eachpage
+ done
+ gzip -9 *.?
+ )
+ done
+ )
+fi
+
+# Compress info pages and purge "dir" file from the package:
+if [ -d $PKG/usr/info ]; then
+ ( cd $PKG/usr/info
+ rm -f dir
+ gzip -9 *
+ )
+fi
+
+mkdir -p $PKG/usr/doc/grub-$VERSION
+cp -a \
+ AUTHORS BUGS COPYING INSTALL MAINTENANCE NEWS README THANKS TODO \
+ $PKG/usr/doc/grub-$VERSION
+
+mkdir -p $PKG/install
+cat $CWD/slack-desc > $PKG/install/slack-desc
+
+# Add Kent's grubconfig tool:
+cd $TMP
+rm -rf grubconfig-$GCVER
+tar xf $CWD/grubconfig-${GCVER}.tar.gz || exit 1
+cd grubconfig-$GCVER || exit 1
+zcat $CWD/grubconfig_localefix.patch.gz | patch || exit 1
+chown -R root:root .
+chmod 644 README
+chmod 755 grubconfig
+mkdir -p $PKG/usr/doc/grubconfig-${GCVER}
+cp -a README $PKG/usr/doc/grubconfig-${GCVER}
+cp -a grubconfig $PKG/usr/sbin/grubconfig
+
+cd $PKG
+/sbin/makepkg -l y -c n $TMP/grub-$VERSION-$ARCH-$BUILD.txz
+
diff --git a/extra/source/grub/grub_support_256byte_inode.patch b/extra/source/grub/grub_support_256byte_inode.patch
new file mode 100644
index 000000000..bef3bc18e
--- /dev/null
+++ b/extra/source/grub/grub_support_256byte_inode.patch
@@ -0,0 +1,94 @@
+diff -Nrup a/stage2/fsys_ext2fs.c b/stage2/fsys_ext2fs.c
+--- a/stage2/fsys_ext2fs.c 2004-08-08 20:19:18.000000000 +0200
++++ b/stage2/fsys_ext2fs.c 2008-01-30 14:27:20.000000000 +0100
+@@ -79,7 +79,52 @@ struct ext2_super_block
+ __u32 s_rev_level; /* Revision level */
+ __u16 s_def_resuid; /* Default uid for reserved blocks */
+ __u16 s_def_resgid; /* Default gid for reserved blocks */
+- __u32 s_reserved[235]; /* Padding to the end of the block */
++ /*
++ * These fields are for EXT2_DYNAMIC_REV superblocks only.
++ *
++ * Note: the difference between the compatible feature set and
++ * the incompatible feature set is that if there is a bit set
++ * in the incompatible feature set that the kernel doesn't
++ * know about, it should refuse to mount the filesystem.
++ *
++ * e2fsck's requirements are more strict; if it doesn't know
++ * about a feature in either the compatible or incompatible
++ * feature set, it must abort and not try to meddle with
++ * things it doesn't understand...
++ */
++ __u32 s_first_ino; /* First non-reserved inode */
++ __u16 s_inode_size; /* size of inode structure */
++ __u16 s_block_group_nr; /* block group # of this superblock */
++ __u32 s_feature_compat; /* compatible feature set */
++ __u32 s_feature_incompat; /* incompatible feature set */
++ __u32 s_feature_ro_compat; /* readonly-compatible feature set */
++ __u8 s_uuid[16]; /* 128-bit uuid for volume */
++ char s_volume_name[16]; /* volume name */
++ char s_last_mounted[64]; /* directory where last mounted */
++ __u32 s_algorithm_usage_bitmap; /* For compression */
++ /*
++ * Performance hints. Directory preallocation should only
++ * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
++ */
++ __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
++ __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
++ __u16 s_reserved_gdt_blocks;/* Per group table for online growth */
++ /*
++ * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
++ */
++ __u8 s_journal_uuid[16]; /* uuid of journal superblock */
++ __u32 s_journal_inum; /* inode number of journal file */
++ __u32 s_journal_dev; /* device number of journal file */
++ __u32 s_last_orphan; /* start of list of inodes to delete */
++ __u32 s_hash_seed[4]; /* HTREE hash seed */
++ __u8 s_def_hash_version; /* Default hash version to use */
++ __u8 s_jnl_backup_type; /* Default type of journal backup */
++ __u16 s_reserved_word_pad;
++ __u32 s_default_mount_opts;
++ __u32 s_first_meta_bg; /* First metablock group */
++ __u32 s_mkfs_time; /* When the filesystem was created */
++ __u32 s_jnl_blocks[17]; /* Backup of the journal inode */
++ __u32 s_reserved[172]; /* Padding to the end of the block */
+ };
+
+ struct ext2_group_desc
+@@ -218,6 +263,9 @@ struct ext2_dir_entry
+ #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
+ #define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s)))
+
++#define EXT2_INODE_SIZE(s) (SUPERBLOCK->s_inode_size)
++#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
++
+ /* linux/ext2_fs.h */
+ #define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
+ /* kind of from ext2/super.c */
+@@ -553,7 +601,7 @@ ext2fs_dir (char *dirname)
+ gdp = GROUP_DESC;
+ ino_blk = gdp[desc].bg_inode_table +
+ (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
+- >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
++ >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));
+ #ifdef E2DEBUG
+ printf ("inode table fsblock=%d\n", ino_blk);
+ #endif /* E2DEBUG */
+@@ -565,13 +613,12 @@ ext2fs_dir (char *dirname)
+ /* reset indirect blocks! */
+ mapblock2 = mapblock1 = -1;
+
+- raw_inode = INODE +
+- ((current_ino - 1)
+- & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
++ raw_inode = (struct ext2_inode *)((char *)INODE +
++ ((current_ino - 1) & (EXT2_INODES_PER_BLOCK (SUPERBLOCK) - 1)) *
++ EXT2_INODE_SIZE (SUPERBLOCK));
+ #ifdef E2DEBUG
+ printf ("ipb=%d, sizeof(inode)=%d\n",
+- (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
+- sizeof (struct ext2_inode));
++ EXT2_INODES_PER_BLOCK (SUPERBLOCK), EXT2_INODE_SIZE (SUPERBLOCK));
+ printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode);
+ printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
+ for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode;
diff --git a/extra/source/grub/grubconfig_localefix.patch b/extra/source/grub/grubconfig_localefix.patch
new file mode 100644
index 000000000..6c1d4e9f9
--- /dev/null
+++ b/extra/source/grub/grubconfig_localefix.patch
@@ -0,0 +1,32 @@
+--- /usr/sbin/grubconfig 2006-03-24 09:28:41.000000000 +0100
++++ _developpement/debug/grubconfig 2007-05-12 16:51:57.000000000 +0200
+@@ -53,6 +53,10 @@
+ rm -rf $TMP $BOOT_TMP
+ mkdir -p $TMP $BOOT_TMP
+
++# We need to ensure the output is in english in order to match the devices
++# with fdisk.
++export LC_ALL=C
++
+ PATH=$PATH:/bin:/usr/bin:/sbin:/usr/sbin
+
+ # Menu to check if we want to use VESA framebuffer support:
+@@ -475,7 +479,8 @@
+ chmod 644 $BOOT/grub/$grub_config
+ message=yes
+ installcolor;
+- umount $BOOT_TMP 2>$TMP/null && rmdir $BOOT_TMP
++ umount $BOOT_TMP 2> $TMP/null
++ rmdir $BOOT_TMP 2> $TMP/null
+ rm -rf $TMP
+ }
+
+@@ -1004,8 +1009,6 @@
+ KILL=NO
+ fi
+ simplegrub
+- umount $BOOT_TMP 2>$TMP/null
+- rm -rf $TMP $BOOT_TMP
+ chroot_umount
+ exit
+ fi
diff --git a/extra/source/grub/slack-desc b/extra/source/grub/slack-desc
new file mode 100644
index 000000000..f3bead79e
--- /dev/null
+++ b/extra/source/grub/slack-desc
@@ -0,0 +1,19 @@
+# HOW TO EDIT THIS FILE:
+# The "handy ruler" below makes it easier to edit a package description. Line
+# up the first '|' above the ':' following the base package name, and the '|'
+# on the right side marks the last column you can put a character in. You must
+# make exactly 11 lines for the formatting to be correct. It's also
+# customary to leave one space after the ':'.
+
+ |-----handy-ruler------------------------------------------------------|
+grub: grub (GNU GRUB Legacy bootloader)
+grub:
+grub: This is the legacy (0.9x) version of GNU GRUB, the GRand Unified
+grub: Bootloader. GRUB is an alternative to other familiar bootloaders
+grub: such as LILO. Unlike LILO, it loads a kernel through direct file-
+grub: system support rather than a block list so it does not need to be
+grub: updated if a new kernel is installed.
+grub:
+grub: Also included is Kent Robotti's 'grubconfig' tool (similar to the
+grub: Slackware 'liloconfig' setup tool).
+grub: