--- linux-2.6.1.orig/drivers/acpi/Kconfig	2004-01-09 08:00:12.000000000 +0100
+++ linux-2.6.1/drivers/acpi/Kconfig	2004-01-19 20:47:09.000000000 +0100
@@ -263,5 +263,19 @@
 	  particular, many Toshiba laptops require this for correct operation
 	  of the AC module.
 
+config ACPI_INITRD
+	bool "Read DSDT from initrd"
+	depends on ACPI && BLK_DEV_INITRD
+	default y
+	help
+	  The DSDT (Differentiated System Description Table) often needs to be
+	  overridden because of broken BIOS implementations. If you want to use
+	  a customized DSDT, please use the mkinitrd tool (mkinitrd package) to 
+	  attach the  DSDT to the initrd) or see http://gaugusch.at/kernel.shtml 
+	  for instructions on using an existing initrd with ACPI. If there is no 
+	  one found in the initrd, the DSDT from the BIOS is used. Even you do not 
+	  need a new one at the moment, you may want to use a better implemented 
+	  DSDT later. It is save to say yes here
+
 endmenu
 
--- linux-2.6.1.orig/drivers/acpi/osl.c	2004-01-09 07:59:56.000000000 +0100
+++ linux-2.6.1/drivers/acpi/osl.c	2004-01-19 20:47:09.000000000 +0100
@@ -34,12 +34,14 @@
 #include <linux/interrupt.h>
 #include <linux/kmod.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <linux/workqueue.h>
 #include <linux/nmi.h>
 #include <acpi/acpi.h>
 #include <asm/io.h>
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
+#include <linux/vmalloc.h>
 
 #include <linux/efi.h>
 
@@ -226,11 +228,32 @@
 acpi_os_table_override (struct acpi_table_header *existing_table,
 			struct acpi_table_header **new_table)
 {
-	if (!existing_table || !new_table)
-		return AE_BAD_PARAMETER;
-
-	*new_table = NULL;
-	return AE_OK;
+ #ifdef CONFIG_ACPI_INITRD
+	extern char* dsdt_start;
+ #endif
+         if (!existing_table || !new_table)
+                 return AE_BAD_PARAMETER;
+  
+  #ifdef CONFIG_ACPI_INITRD
+	if(memcmp(existing_table, "DSDT", 4)){
+		*new_table = NULL;
+		return AE_OK;
+	}
+	// dsdt_start has been kmalloced in /init/initram.c
+	// where should it be freed ?!? 
+	if (dsdt_start != NULL){
+	 	printk(KERN_INFO "ACPI: Using customized DSDT\n");
+		*new_table = (struct acpi_table_header*)dsdt_start;
+		return AE_OK;
+	 }
+	 else{
+                *new_table = NULL;
+		return AE_OK;
+	 }
+ #else
+         *new_table = NULL;
+ #endif
+         return AE_OK;
 }
 
 static irqreturn_t
--- linux-2.6.1.orig/drivers/acpi/tables/tbget.c	2004-01-09 07:59:45.000000000 +0100
+++ linux-2.6.1/drivers/acpi/tables/tbget.c	2004-01-19 20:47:09.000000000 +0100
@@ -45,6 +45,9 @@
 #include <acpi/acpi.h>
 #include <acpi/actables.h>
 
+#ifdef CONFIG_ACPI_INITRD
+     extern unsigned char *dsdt_start;
+#endif
 
 #define _COMPONENT          ACPI_TABLES
 	 ACPI_MODULE_NAME    ("tbget")
@@ -285,8 +288,13 @@
 			acpi_format_exception (status)));
 		return_ACPI_STATUS (status);
 	}
-
 	/* Copy the table info */
+#ifdef CONFIG_ACPI_INITRD
+	if (dsdt_start) {
+		vfree(dsdt_start);
+		dsdt_start = NULL;
+	}
+#endif
 
 	ACPI_REPORT_INFO (("Table [%4.4s] replaced by host OS\n",
 		table_info->pointer->signature));
--- linux-2.6.1.orig/include/linux/initrd.h	2004-01-09 08:00:04.000000000 +0100
+++ linux-2.6.1/include/linux/initrd.h	2004-01-19 20:47:09.000000000 +0100
@@ -15,6 +15,7 @@
 
 /* free_initrd_mem always gets called with the next two as arguments.. */
 extern unsigned long initrd_start, initrd_end;
+extern unsigned char *dsdt_start;
 extern void free_initrd_mem(unsigned long, unsigned long);
 
 extern unsigned int real_root_dev;
diff -ruN linux-2.6.1.orig/init/initramfs.c linux-2.6.1/init/initramfs.c
--- linux-2.6.1.orig/init/initramfs.c	2004-01-09 07:59:07.000000000 +0100
+++ linux-2.6.1/init/initramfs.c	2004-01-19 20:47:09.000000000 +0100
@@ -7,8 +7,14 @@
 #include <linux/unistd.h>
 #include <linux/delay.h>
 #include <linux/string.h>
+#include <linux/vmalloc.h>
+
+#ifdef CONFIG_ACPI_INITRD
+	unsigned char *dsdt_start;
+#endif
 
 static __initdata char *message;
+
 static void __init error(char *x)
 {
 	if (!message)
@@ -481,22 +487,80 @@
 {
 	char *err = unpack_to_rootfs(&__initramfs_start,
 			 &__initramfs_end - &__initramfs_start, 0);
+#ifdef CONFIG_ACPI_INITRD
+	unsigned char start_signature[] = "INITRDDSDT123DSDT123";
+	unsigned char end_signature[] =   "INITRDDSDT321DSDT321";
+	unsigned char *data = (unsigned char*) initrd_start;
+	unsigned char *dsdt_start_tmp = NULL;
+	unsigned char *initrd_end_tmp = NULL;
+#endif
 	if (err)
 		panic(err);
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start) {
 		int fd;
+		
+		
 		printk(KERN_INFO "checking if image is initramfs...");
 		err = unpack_to_rootfs((char *)initrd_start,
-			initrd_end - initrd_start, 1);
+			       initrd_end - initrd_start, 1);
 		if (!err) {
 			printk(" it is\n");
 			unpack_to_rootfs((char *)initrd_start,
-				initrd_end - initrd_start, 0);
+				 initrd_end - initrd_start, 0);
 			free_initrd_mem(initrd_start, initrd_end);
 			return;
 		}
 		printk("it isn't (%s); looks like an initrd\n", err);
+		
+#ifdef CONFIG_ACPI_INITRD
+		dsdt_start = NULL;
+		
+		printk(KERN_INFO "ACPI: Looking for DSDT in initrd ...");
+		 /* don't scan above end, do not modify initrd borders */
+		initrd_end_tmp=(unsigned char*)initrd_end-sizeof(end_signature);
+
+		if ((initrd_end_tmp-(unsigned char*)initrd_start) > 4 && 
+			!memcmp((unsigned char*)initrd_start, "DSDT", 4)) {
+			/* found DSDT at start of initrd */
+			dsdt_start_tmp=(unsigned char*)initrd_start; 
+		}
+		else { /* searching for start signature in initrd */
+			for (data=(unsigned char*)initrd_start; 
+				data < (unsigned char*)initrd_end_tmp ; ++data) {
+				
+				if (!memcmp(data, start_signature, 
+					sizeof(start_signature)-1)) {
+					printk(" found (at offset %u)!\n", 
+						data+sizeof(start_signature)-
+						(unsigned char*)initrd_start);
+					dsdt_start_tmp = data+sizeof(start_signature);
+					break;
+				}
+			}
+		}
+		// check if head of dsdt is valid
+		if (dsdt_start_tmp != NULL && !memcmp(dsdt_start_tmp, "DSDT", 4)) {
+			// searching for end signature in initrd
+			for (data += sizeof(end_signature); 
+				data <= (unsigned char*)initrd_end; data++){  
+				if (!memcmp(data, end_signature, 
+					sizeof(end_signature)-1)){
+					break;
+				}
+			}
+			printk (" found customized DSDT with %u bytes!\n", data-dsdt_start_tmp);
+			// DSDT could be about 10-200kb, maybe more? 
+			// could kmalloc be used ?
+			// am I allowed to use vmalloc ?
+			dsdt_start = vmalloc(data-dsdt_start_tmp+1);
+			memcpy(dsdt_start, dsdt_start_tmp, data-dsdt_start_tmp);
+		}
+		else{
+			printk(" not found!\n");
+		}
+#endif 
+		
 		fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 700);
 		if (fd >= 0) {
 			sys_write(fd, (char *)initrd_start,

