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.97Apply 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.patchApply 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.diffApply 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 installThe 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-terminfoTo 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