Friday, October 2, 2009

To Compile GRUB with GFXBOOT and SLIC patch

I use GRUB 0.97 to boot multiple operating systems on my computer. While I was searching Yahoo! China, I found a patch called loadslic.patch. I wanted to use MinGW to compile GRUB with GFXBOOT and SLIC patch. But I received an error saying “GRUB requires a working absolute objcopy; upgrade your binutils.” So I switched to Linux and compiled GRUB. Below I show how I did it.




  1. I prepared my compiler environment by installing GCC 3.4. Then I downloaded the following files:





  2. Unpack the GRUB 0.97 source.


    tar xzvf grub-0.97.tar.gz
    cd grub-0.97


  3. Apply various patches.


    patch -p1 -l < ../040_all_grub-0.96-nxstack.patch
    patch -p1 -l < ../05-grub-0.97-initrdaddr.diff
    patch -p1 -l < ../i2o.patch
    patch -p1 -l < ../intelmac.patch
    patch -p1 -l < ../more-raid.patch
    patch -p1 -l < ../special-devices.patch
    patch -p1 -l < ../grub-0.97-pure64-1.patch


  4. Apply the GFXBOOT patch.


    cd ..
    tar xjvf gfxboot-4.1.19.tar.bz2
    cd ../grub-0.97
    patch -p0 -l < ../gfxboot-4.1.19/patches/grub-0.97.diff



  5. Apply the following patch which adds a feature to load an OEM SLIC table for Windows activation. I found this patch through Yahoo! China. Save it as loadslic.patch.


    --- grub-0.97/stage2/builtins.c 2005-02-16 05:58:23.000000000 +0800
    +++ grub-0.97.new/stage2/builtins.c 2009-08-11 22:37:26.000000000 +0800
    @@ -48,6 +48,7 @@
    #ifdef USE_MD5_PASSWORDS
    # include <md5.h>
    #endif
    +#include <defs.h>

    /* The type of kernel loaded. */
    kernel_t kernel_type;
    @@ -397,6 +398,180 @@
    "Print the contents of the file FILE."
    };

    +
    +/*
    + * Add by yangrz, 2009-08-11
    + */
    +#define SLIC_LENGTH 0x176
    +
    +typedef struct acpi_rsdp {
    + char signature[8]; /* RSDP signature "RSD PTR" */
    + u_char checksum; /* checksum of the first 20 bytes */
    + char oem_id[6]; /* OEM ID, "LXBIOS" */
    + u_char revision; /* 0 for APCI 1.0, 2 for ACPI 2.0 */
    + u_int rsdt_address; /* physical address of RSDT */
    + u_int length; /* total length of RSDP (including extended part) */
    + unsigned long long xsdt_address; /* physical address of XSDT */
    + u_char ext_checksum; /* chechsum of whole table */
    + u_char reserved[3];
    +} __attribute__((packed)) acpi_rsdp_t;
    +
    +typedef struct acpi_table_header /* ACPI common table header */
    +{
    + char signature [4]; /* ACPI signature (4 ASCII characters) */\
    + u_int length; /* Length of table, in bytes, including header */\
    + u_char revision; /* ACPI Specification minor version # */\
    + u_char checksum; /* To make sum of entire table == 0 */\
    + char oem_id [6]; /* OEM identification */\
    + char oem_table_id [8]; /* OEM table identification */\
    + u_int oem_revision; /* OEM revision number */\
    + char asl_compiler_id [4]; /* ASL compiler vendor ID */\
    + u_int asl_compiler_revision; /* ASL compiler revision number */
    +} __attribute__ ((packed)) acpi_header_t;
    +
    +/* RSDT */
    +typedef struct acpi_rsdt {
    + struct acpi_table_header header;
    + /* MCONFIG, HPET, FADT, SRAT, SLIT, MADT(APIC), SSDT, SSDTX, and SSDT for CPU pstate*/
    + u_int entry[1];
    +} __attribute__ ((packed)) acpi_rsdt_t;
    +
    +static u_char
    +acpi_checksum(u_char *table, u_int length)
    +{
    + u_char ret=0;
    + while (length--)
    + {
    + ret += *table;
    + table++;
    + }
    + return -ret;
    +}
    +
    +static acpi_rsdp_t *
    +acpi_find_rsdp(void)
    +{
    + acpi_rsdp_t *rsdp;
    +
    + //TODO: also search EBDA
    + for ( rsdp = (acpi_rsdp_t *)(RAW_ADDR(0xe0000));
    + rsdp < (acpi_rsdp_t *)(RAW_ADDR(0xfffff - 0x16));
    + rsdp = (acpi_rsdp_t *)((unsigned char *)rsdp + 16) )
    + {
    + if ( memcmp(rsdp->signature, "RSD PTR ", 8) == 0
    + && acpi_checksum((u_char *)rsdp, rsdp->length) == 0 )
    + {
    + return rsdp;
    + }
    + }
    +
    + return NULL;
    +}
    +
    +static acpi_header_t *
    +acpi_find_slic(acpi_rsdp_t *rsdp)
    +{
    + int i;
    + acpi_rsdt_t *rsdt;
    + acpi_header_t *slic;
    +
    + rsdt = (acpi_rsdt_t *)(rsdp->rsdt_address);
    + for ( i = 0;
    + i < (rsdt->header.length - sizeof(acpi_header_t))/4;
    + i++)
    + {
    + slic = (acpi_header_t *)(RAW_ADDR(rsdt->entry[i]));
    + if ( slic != NULL && memcmp(slic->signature, "SLIC", 4) == 0 )
    + {
    + return slic;
    + }
    + }
    +
    + return NULL;
    +}
    +
    +/*
    + * return value : success 0
    + * fail 1
    + */
    +static int
    +acpi_copy_memory(char *target, char *source, int len)
    +{
    + int i;
    +
    + for ( i = 0; i < len; i++ )
    + {
    + target[i] = source[i];
    + }
    + /* check data */
    + if ( memcmp(target, source, len) != 0 )
    + {
    + printf("modify memory fail: maybe address 0x%x write protect\n",
    + target);
    + return 1;
    + }
    + return 0;
    +}
    +
    +static int
    +acpi_add_slic(char *arg, int flags)
    +{
    + char *file = arg;
    + acpi_rsdp_t *rsdp;
    + acpi_header_t *slic;
    + char buf[SLIC_LENGTH];
    +
    + rsdp = acpi_find_rsdp();
    + if ( rsdp == NULL )
    + {
    + grub_printf("can not find rsdp\n");
    + return 1;
    + }
    + slic = acpi_find_slic(rsdp);
    + if ( slic == NULL )
    + {
    + grub_printf("can not find slic\n");
    + return 1;
    + }
    +
    + if ( slic->length != SLIC_LENGTH )
    + {
    + return 1;
    + }
    +
    + if ( !grub_open(file) )
    + {
    + printf("grub open %s fail\n", file);
    + return 1;
    + }
    + if ( grub_read (buf, SLIC_LENGTH) != SLIC_LENGTH )
    + {
    + printf("grub read fail\n");
    + grub_close();
    + return 1;
    + }
    + grub_close();
    +
    + if ( acpi_copy_memory((char *)slic, buf, SLIC_LENGTH) )
    + {
    + errnum = ERR_WONT_FIT;
    + return 1;
    + }
    +
    + errnum = ERR_NONE;
    + return 0;
    +}
    +
    +static struct builtin builtin_load_slic =
    +{
    + "loadslic",
    + acpi_add_slic,
    + BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
    + "loadslic FILE",
    + "load acpi slic form file"
    +};
    +/* end yangrz add */
    +

    /* chainloader */
    static int
    @@ -4835,6 +5010,8 @@
    &builtin_install,
    &builtin_ioprobe,
    &builtin_kernel,
    + /* Add by yangrz, 2009-08-08 */
    + &builtin_load_slic,
    &builtin_lock,
    &builtin_makeactive,
    &builtin_map,

    Apply this patch as follows:


    patch -p1 -l < ../loadslic.patch


  6. Compile GRUB.


    ./configure --prefix=/usr
    make
    make install

    The following files are installed:


    /usr/bin/mbchk
    /usr/info/multiboot.info
    /usr/lib/grub/i386-pc
    /usr/man/man1/mbchk.1
    /usr/man/man8/grub.8
    /usr/man/man8/grub-install.8
    /usr/man/man8/grub-md5-crypt.8
    /usr/man/man8/grub-terminfo.8
    /usr/sbin/grub
    /usr/sbin/grub-install
    /usr/sbin/grub-md5-crypt
    /usr/sbin/grub-set-default
    /usr/sbin/grub-terminfo

    To get my GRUB binaries, read this post.





Using GRUB to load SLIC


Note that the SLIC patch for GRUB only works on computers with BIOS that actually contain a SLIC table. To load SLIC with the patched GRUB, use the loadslic command at the GRUB prompt or in the menu.lst configuration file. For example, a menu.lst may contain a section like the following:


# GRUB Boot Menu
hiddenmenu

# By default, boot Windows Vista
default 0
timeout 0

# Boot Windows Vista Home Premium
title Windows Vista Home Premium
unhide (hd0,0)
hide (hd0,1)
loadslic (hd0,5)/boot/grub/slic.bin
chainloader (hd0,0)+1


For old computers with non-SLP BIOS, read this post.

No comments:

Post a Comment

About This Blog

KBlog logo This blog is about current events and issues concerning general population. Thanks for visiting the blog and posting your comments.

© Contents by KBlog

© Blogger template by Emporium Digital 2008

Followers

Total Pageviews

icon
Powered By Blogger