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.
- I prepared my compiler environment by installing GCC 3.4. Then I downloaded the following files: - grub-0.97.tar.gz
- gfxboot-4.1.19.tar.bz2
- There are additional patches in this ArchLinux page.
 
- grub-0.97.tar.gz
- Unpack the GRUB 0.97 source. - tar xzvf grub-0.97.tar.gz 
 cd grub-0.97
- 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
- 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
- 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 
- 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