Patchwork ACPI updates + S3 Resume without hole at 31MB

login
register
about
Submitter Stefan Reinauer
Date 2009-10-26 17:27:37
Message ID <4AE5DC09.9030604@coresystems.de>
Download mbox | patch
Permalink /patch/491/
State Accepted
Commit r4932
Headers show

Comments

Stefan Reinauer - 2009-10-26 17:27:37
See patch. This works nicely on two i945 machines I have here
(unfortunately not the Kontron 986lcd-m due to some other reason)
Probably needs some fixing for the AMD board that Rudolf got running
with Resume. Rudolf, can you jump in, I don't have that hardware..

Stefan
* Simplify acpi_add_table
* fix some comments
* Simplify ACPI wakeup code and make it work without a memory hole
* Add resume entries to global GDT so we don't need our own for resume.
* add ECDT description to acpi.h for anyone who might need it ;-)
* remove rather stupid math to get the right number of MAX_ACPI_TABLES
  and just define a reasonable maximum for now.

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Rudolf Marek - 2009-10-27 22:36:10
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

I have some questions:

1) is 0x600 as base for lowmem trampoline safe? it always makes me wonder, this
was the reason why I did the realmode code which runs above 1MB ;) Maybe we can
have that too and only copy the trampoline to the highmem save area and execute
it there. This would mean all memory bellow 1MB is untouched.

2)

You seem to follow different way how to detect S3.

I had in the code for all boards (like memory controller init)

ifdef ACPI_IS_WAKEUP_EARLY
<------>int suspend = acpi_is_wakeup_early();
#else
<------>int suspend = 0;
#endif


And for per chipset CAR code  I defined a function which is doing it:

define ACPI_IS_WAKEUP_EARLY 1

int acpi_is_wakeup_early(void) {
device_t dev;
u16 tmp;
print_debug("IN TEST WAKEUP\n");
...


And for the normal ram stage there is:

/* this is to be filled by SB code - startup value what was found */

u8 acpi_slp_type = 0;

int acpi_is_wakeup(void)
{
<------>return (acpi_slp_type == 3);
}

Which is backup what was the sleep type. I think this is how you deal with that
using the scratchpads.

3) I think your SMM code corrupts lowmem, or I have not seen any backup of that
mem? Maybe I'm wrong?

4) Changes to the stack

I think you changed the stack to some other place, not sure how to change that
for K8 CAR? Also there is an remaining issue if CAR gets flushed to memory or
not. I think Carl-Daniel had some patch for this.

5) Don't understand much the cbmem_reinit((u64)high_ram_base)) in CAR code, you
seem to take the TOM from PCI reg but this gets more complicated for UMA, I dont
know how to do that for K8. Partially because the high_ram_base gets dynamically
 lowered in K8M890 resource code :/ In other words there is no easy way for me
to find it in memory. Except some hacks like make the cbmem look like some
proprietary ACPI table and walk acpi tables as for we do for resume but in car
stage just to find out where the tables are...

I think only issue #5 is a real problem.

Rudolf
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkrnddoACgkQ3J9wPJqZRNX5egCfaEQUqTwRoV9yd6qsb8qvbH8K
THEAoKEutUPq2mxJTBJY18m2mw+Dmtrl
=XC3U
-----END PGP SIGNATURE-----
Stefan Reinauer - 2009-10-28 09:51:59
Rudolf Marek wrote:
> Hi,
>
> I have some questions:
>
> 1) is 0x600 as base for lowmem trampoline safe? it always makes me
> wonder, this
> was the reason why I did the realmode code which runs above 1MB ;)
> Maybe we can
> have that too and only copy the trampoline to the highmem save area
> and execute
> it there. This would mean all memory bellow 1MB is untouched.

It should be safe. The lower 4kb are supposed to be untouched by the OS,
according to some information I found, including an old mail of yours on
S3 Resume.

> 2)
>
> You seem to follow different way how to detect S3.
>
Not sure I can follow. I didn't change that part of your code

> I had in the code for all boards (like memory controller init)
>
> ifdef ACPI_IS_WAKEUP_EARLY
> <------>int suspend = acpi_is_wakeup_early();
> #else
> <------>int suspend = 0;
> #endif
>
>
> And for per chipset CAR code  I defined a function which is doing it:
>
> define ACPI_IS_WAKEUP_EARLY 1
>
> int acpi_is_wakeup_early(void) {
> device_t dev;
> u16 tmp;
> print_debug("IN TEST WAKEUP\n");
> ...
>
Since I only use the value in auto.c I did not put this into a one line
function called externally. If that is what you suggest, we can easily
do that, though.

> And for the normal ram stage there is:
>
> /* this is to be filled by SB code - startup value what was found */
>
> u8 acpi_slp_type = 0;
>
> int acpi_is_wakeup(void)
> {
> <------>return (acpi_slp_type == 3);
> }
>
> Which is backup what was the sleep type. I think this is how you deal
> with that
> using the scratchpads.

Yes, I am using your mechanism here. But since it's not safe to leave
the value in PM1_CNT (at least on i945), I had to move it somewhere
else. SKPAD seemed like a good place to get it over to stage 2.


>
> 3) I think your SMM code corrupts lowmem, or I have not seen any
> backup of that
> mem? Maybe I'm wrong?
No, that is true... 0x38000 + size of SMM relocator is wiped out.


> 4) Changes to the stack
>
> I think you changed the stack to some other place, not sure how to
> change that
> for K8 CAR? Also there is an remaining issue if CAR gets flushed to
> memory or
> not. I think Carl-Daniel had some patch for this.

On i945 the cache as ram area is not backed by RAM, so the copy trickery
from K8 does not work here.

Stack setup is more than fishy on most platforms, but that's pretty
unrelated to my ACPI resume patch.

What patch are you referring to?

> 5) Don't understand much the cbmem_reinit((u64)high_ram_base)) in CAR
> code, you
> seem to take the TOM from PCI reg but this gets more complicated for
> UMA, I dont
> know how to do that for K8. Partially because the high_ram_base gets
> dynamically
>  lowered in K8M890 resource code :/ In other words there is no easy
> way for me
> to find it in memory.
Very ugly. Maybe we can fix the K8M890 resource code? What factors
influence the high_ram_base on that chipset? How early can we determine
them?

> Except some hacks like make the cbmem look like some
> proprietary ACPI table and walk acpi tables as for we do for resume
> but in car
> stage just to find out where the tables are...
Speaking of hacks, we could remember the CBMEM base address in the low
4KB so we can find them again...



Stefan
Rudolf Marek - 2009-10-28 22:42:13
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Stefan,


>> 1) is 0x600 as base for lowmem trampoline safe? it always makes me
>> wonder, this
>> was the reason why I did the realmode code which runs above 1MB ;)
>> Maybe we can
>> have that too and only copy the trampoline to the highmem save area
>> and execute
>> it there. This would mean all memory bellow 1MB is untouched.
> 
> It should be safe. The lower 4kb are supposed to be untouched by the OS,
> according to some information I found, including an old mail of yours on
> S3 Resume.

Aha, I think we could rework this and have the trampoline in CBMEM, because the
trick to run realmode code over 1MB would work too.


> 
>> 2)
> Since I only use the value in auto.c I did not put this into a one line
> function called externally. If that is what you suggest, we can easily
> do that, though.

Yes this is just for code to look same...


>> 3) I think your SMM code corrupts lowmem, or I have not seen any
>> backup of that
>> mem? Maybe I'm wrong?

> No, that is true... 0x38000 + size of SMM relocator is wiped out.

OK ;)


>> 4) Changes to the stack
>>
> 
> What patch are you referring to?

Well I think the previous one for CBMEM if I recall correctly or the ICH7
updates stuff.

>> 5) Don't understand much the cbmem_reinit((u64)high_ram_base)) in CAR

> Very ugly. Maybe we can fix the K8M890 resource code? What factors
> influence the high_ram_base on that chipset? How early can we determine
> them?

Yes I tried to fixed it with separate patch.

>> Except some hacks like make the cbmem look like some
>> proprietary ACPI table and walk acpi tables as for we do for resume
>> but in car
>> stage just to find out where the tables are...

> Speaking of hacks, we could remember the CBMEM base address in the low
> 4KB so we can find them again...

Yes I tried that I used 0:4F0 for the PRT which is some 'user data area'. I'm
having trouble with CBMEM refusing me to create the ACPI RESUME table. However
the bits I have rewritten to use the 0:4F0 trampoline are OK.

Rudolf
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkroxGYACgkQ3J9wPJqZRNVO5wCeKH96JfOLZep/VEmLnGl4S6Tk
aCMAnA/C/qXvGo/qiBPFwe1qeS3rY//y
=25u2
-----END PGP SIGNATURE-----
Stefan Reinauer - 2009-10-29 18:57:21
Rudolf Marek wrote:
> Yes I tried that I used 0:4F0 for the PRT which is some 'user data
> area'. I'm
> having trouble with CBMEM refusing me to create the ACPI RESUME table.
> However
> the bits I have rewritten to use the 0:4F0 trampoline are OK.
The high tables area needs to grow from 64KB to 1MB in order for the
ACPI RESUME table to fit...

Stefan
Stefan Reinauer - 2009-11-04 18:04:29
Stefan Reinauer wrote:
> See patch. This works nicely on two i945 machines I have here
> (unfortunately not the Kontron 986lcd-m due to some other reason)
> Probably needs some fixing for the AMD board that Rudolf got running
> with Resume. Rudolf, can you jump in, I don't have that hardware..
>
> Stefan
>   

> * Simplify acpi_add_table
> * fix some comments
> * Simplify ACPI wakeup code and make it work without a memory hole
> * Add resume entries to global GDT so we don't need our own for resume.
> * add ECDT description to acpi.h for anyone who might need it  ;-) 
> * remove rather stupid math to get the right number of MAX_ACPI_TABLES
>   and just define a reasonable maximum for now.
>
> Signed-off-by: Stefan Reinauer <stepan@coresystems.de>


ping?
Rudolf Marek - 2009-11-04 22:04:14
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi

Sorry I tried to get it working on K8 but got distracted by the network support
for SerialICE and network console for coreboot ;)

I think I can Acked-by: Rudolf Marek <r.marek@assembler.cz> Although I would
prefer to have the wakeup trampoline located in the cbmem area. The trick to run
in real mode higher than 1MB would work too and make things safer.

Rudolf
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkrx+l4ACgkQ3J9wPJqZRNX1nwCghMM2i01//qn+1h0DiCbHPYAN
3OsAoOHkKkfOQ7nza70OSi8OI05gQxSL
=cv2a
-----END PGP SIGNATURE-----
Joseph Smith - 2009-11-04 22:24:39
On Wed, 04 Nov 2009 23:04:14 +0100, Rudolf Marek <r.marek@assembler.cz>
wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Hi
> 
> Sorry I tried to get it working on K8 but got distracted by the network
> support
> for SerialICE and network console for coreboot ;)
> 
Sorry to get off subject, but what is this all about, do tell :-)
Stefan Reinauer - 2009-11-10 22:18:35
Rudolf Marek wrote:
> Hi
>
> Sorry I tried to get it working on K8 but got distracted by the
> network support
> for SerialICE and network console for coreboot ;)
How's that going?
> I think I can Acked-by: Rudolf Marek <r.marek@assembler.cz> 

Thanks, r4932

> Although I would
> prefer to have the wakeup trampoline located in the cbmem area. The
> trick to run
> in real mode higher than 1MB would work too and make things safer.

Ok, I'll put that on my stack... If you can come up with a solution
quicker, please do..

Stefan

Patch

Index: src/arch/i386/boot/acpi.c
===================================================================
--- src/arch/i386/boot/acpi.c	(revision 4861)
+++ src/arch/i386/boot/acpi.c	(working copy)
@@ -18,7 +18,8 @@ 
  *   write_acpi_tables()
  *   acpi_dump_apics()
  *   
- * See AMD Solo, Island Aruma or Via Epia-M port for more details.
+ * See Kontron 986LCD-M port for a good example of an ACPI implementation
+ * in coreboot.
  */
 
 #include <console/console.h>
@@ -26,6 +27,7 @@ 
 #include <arch/acpi.h>
 #include <arch/acpigen.h>
 #include <device/pci.h>
+#include <cbmem.h>
 
 u8 acpi_checksum(u8 *table, u32 length)
 {
@@ -37,54 +39,67 @@ 
 	return -ret;
 }
 
-/*
- * add an acpi table to rsdt structure, and recalculate checksum
+/**
+ * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length and checksum
  */
 
 void acpi_add_table(acpi_rsdp_t *rsdp, void *table)
 {
-	int i;
+	int i, entries_num;
 	acpi_rsdt_t *rsdt;
 	acpi_xsdt_t *xsdt = NULL;
 
+	/* The RSDT is mandatory ... */
 	rsdt = (acpi_rsdt_t *)rsdp->rsdt_address;
+
+	/* ... while the XSDT is not */
 	if (rsdp->xsdt_address) {
 		xsdt = (acpi_xsdt_t *)((u32)rsdp->xsdt_address);
 	}
 	
-	int entries_num = ARRAY_SIZE(rsdt->entry);
+	/* This should always be MAX_ACPI_TABLES */
+	entries_num = ARRAY_SIZE(rsdt->entry);
 	
-	for (i=0; i<entries_num; i++) {
-		if(rsdt->entry[i]==0) {
-			rsdt->entry[i]=(u32)table;
-			/* fix length to stop kernel whining about invalid entries */
-			rsdt->header.length = sizeof(acpi_header_t) + (sizeof(u32) * (i+1));
-			/* fix checksum */
-			/* hope this won't get optimized away */
-			rsdt->header.checksum=0;
-			rsdt->header.checksum=acpi_checksum((u8 *)rsdt,
-					rsdt->header.length);
+	for (i = 0; i < entries_num; i++) {
+		if(rsdt->entry[i] == 0)
+			break;
+	}
 
-			/* And now the same thing for the XSDT. We use the same
-			 * index as we want the XSDT and RSDT to always be in
-			 * sync in coreboot.
-			 */
-			if (xsdt) {
-				xsdt->entry[i]=(u64)(u32)table;
-				xsdt->header.length = sizeof(acpi_header_t) +
-					(sizeof(u64) * (i+1));
-				xsdt->header.checksum=0;
-				xsdt->header.checksum=acpi_checksum((u8 *)xsdt,
-						xsdt->header.length);
-			}
-			
-			printk_debug("ACPI: added table %d/%d Length now %d\n",
-					i+1, entries_num, rsdt->header.length);
-			return;
-		}
+	if (i >= entries_num) {
+		printk_err("ACPI: Error: Could not add ACPI table, too many tables.\n");
+		return;
 	}
 
-	printk_err("ACPI: Error: Could not add ACPI table, too many tables.\n");
+	/* Add table to the RSDT */
+	rsdt->entry[i] = (u32)table;
+
+	/* Fix RSDT length or the kernel will assume invalid entries */
+	rsdt->header.length = sizeof(acpi_header_t) + (sizeof(u32) * (i+1));
+
+	/* Re-calculate checksum */
+	rsdt->header.checksum = 0; /* Hope this won't get optimized away */
+	rsdt->header.checksum = acpi_checksum((u8 *)rsdt,
+			rsdt->header.length);
+
+	/* And now the same thing for the XSDT. We use the same index as for
+	 * now we want the XSDT and RSDT to always be in sync in coreboot.
+	 */
+	if (xsdt) {
+		/* Add table to the XSDT */
+		xsdt->entry[i]=(u64)(u32)table;
+
+		/* Fix XSDT length */
+		xsdt->header.length = sizeof(acpi_header_t) +
+			(sizeof(u64) * (i+1));
+
+		/* Re-calculate checksum */
+		xsdt->header.checksum=0;
+		xsdt->header.checksum=acpi_checksum((u8 *)xsdt,
+				xsdt->header.length);
+	}
+
+	printk_debug("ACPI: added table %d/%d Length now %d\n",
+			i+1, entries_num, rsdt->header.length);
 }
 
 int acpi_create_mcfg_mmconfig(acpi_mcfg_mmconfig_t *mmconfig, u32 base, u16 seg_nr, u8 start, u8 end)
@@ -222,7 +237,8 @@ 
 }
 
 /* this can be overriden by platform ACPI setup code,
-   if it calls acpi_create_ssdt_generator */
+ * if it calls acpi_create_ssdt_generator
+ */
 unsigned long __attribute__((weak)) acpi_fill_ssdt_generator(unsigned long current,
 						    const char *oem_table_id) {
 	return current;
@@ -559,10 +575,29 @@ 
 extern char *lowmem_backup_ptr;
 extern int lowmem_backup_size;
 
+#define WAKEUP_BASE		0x600
+
+void (*acpi_do_wakeup)(u32 vector, u32 backup_source, u32 backup_target, u32
+		backup_size) __attribute__((regparm(0))) = (void *)WAKEUP_BASE;
+
+extern unsigned char __wakeup, __wakeup_size;
+
 void acpi_jump_to_wakeup(void *vector)
 {
+	u32 acpi_backup_memory = (u32) cbmem_find(CBMEM_ID_RESUME);
+
+	if (!acpi_backup_memory) {
+		printk(BIOS_WARNING, "ACPI: Backup memory missing. No S3 Resume.\n");
+		return;
+	}
+
+	// FIXME this should go into the ACPI backup memory, too. No pork saussages.
 	/* just restore the SMP trampoline and continue with wakeup on assembly level */
 	memcpy(lowmem_backup_ptr, lowmem_backup, lowmem_backup_size);
-	acpi_jmp_to_realm_wakeup((u32) vector);
+
+	/* copy wakeup trampoline in place */
+	memcpy(WAKEUP_BASE, &__wakeup, &__wakeup_size);
+
+	acpi_do_wakeup((u32)vector, acpi_backup_memory, CONFIG_RAMBASE, HIGH_MEMORY_SAVE);
 }
 #endif
Index: src/arch/i386/boot/wakeup.S
===================================================================
--- src/arch/i386/boot/wakeup.S	(revision 4861)
+++ src/arch/i386/boot/wakeup.S	(working copy)
@@ -2,10 +2,11 @@ 
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz>
+ * Copyright (C) 2009 coresystems GmbH
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License v2 as published by
- * the Free Software Foundation.
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,76 +17,89 @@ 
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
-	.text
+
+#define WAKEUP_BASE		0x600
+#define RELOCATED(x)	(x - __wakeup + WAKEUP_BASE)
+
+/* CR0 bits */
+#define PE		(1 << 0)
+
 	.code32
-	.globl acpi_jmp_to_realm_wakeup
-	/* This function does the PM -> RM switch, but
-	it can run >1MB even in real mode */
-
-acpi_jmp_to_realm_wakeup:
-	mov	0x4(%esp), %eax
+	.globl __wakeup
+__wakeup:
+	/* First prepare the jmp to the resume vector */
+	mov	0x4(%esp), %eax	/* vector */
 	/* last 4 bits of linear addr are taken as offset */
 	andw	$0x0f, %ax
-	movw	%ax, (jmp_off)
+	movw	%ax, (__wakeup_offset)
 	mov	0x4(%esp), %eax
 	/* the rest is taken as segment */
 	shr	$4, %eax
-	movw	%ax, (jmp_seg)
-	lgdt	gdtaddr_wakeup
-	movl	$0x008,%eax
-	mov	%eax,%ds
-	movl	%eax,%es
-	movl	%eax,%ss
-	movl	%eax,%fs
-	movl	%eax,%gs
-	ljmp $0x0010,$reload_cs
-        .code16gcc
-reload_cs:
-	/* switch off PE */
+	movw	%ax, (__wakeup_segment)
+
+	/* Then overwrite coreboot with our backed up memory */
+	movl 8(%esp), %esi
+	movl 12(%esp), %edi
+	movl 16(%esp), %ecx
+	shrl	$4, %ecx
+1:
+	movl	0(%esi),%eax
+	movl	4(%esi),%edx
+	movl	8(%esi),%ebx
+	movl	12(%esi),%ebp
+	addl	$16,%esi
+	subl	$1,%ecx
+	movl	%eax,0(%edi)
+	movl	%edx,4(%edi)
+	movl	%ebx,8(%edi)
+	movl	%ebp,12(%edi)
+	leal	16(%edi),%edi
+	jne	1b
+
+	/* Activate the right segment descriptor real mode. */
+	ljmp	$0x28, $RELOCATED(1f)
+1:
+.code16
+	/* 16 bit code from here on... */
+
+	/* Load the segment registers w/ properly configured
+	 * segment descriptors. They will retain these
+	 * configurations (limits, writability, etc.) once
+	 * protected mode is turned off.
+	 */
+	mov	$0x30, %ax
+	mov	%ax, %ds       
+	mov	%ax, %es       
+	mov	%ax, %fs       
+	mov	%ax, %gs       
+	mov	%ax, %ss       
+
+	/* Turn off protection */
 	movl	%cr0, %eax
-	andb	$0xfe,%al
+	andl	$~PE, %eax
 	movl	%eax, %cr0
-	ljmpl $0x0, $cpu_flushed
-cpu_flushed:
+
+	/* Now really going into real mode */
+	ljmp	$0, $RELOCATED(1f)
+1:
 	movw	$0x0, %ax
 	movw	%ax, %ds
 	movw	%ax, %es
 	movw	%ax, %ss
 	movw	%ax, %fs
 	movw	%ax, %gs
-	/* far jump to OS waking vector. The linear addr is changed to SEG and OFFSET
-	   check ACPI specs or above code for details */
+
+	/* This is a FAR JMP to the OS waking vector. The C code changed
+	 * the address to be correct.
+	 */
 	.byte 0xea
-jmp_off:
-	.word 0
-jmp_seg:
-	.word 0
 
-.code32
-gdt_wakeup_limit = gdt_wakeup_end - gdt_wakeup - 1	/* compute the table limit */
-	gdtaddr_wakeup:
-	.word   gdt_wakeup_limit	/* the table limit */
-	.long   gdt_wakeup             /* we know the offset */
+__wakeup_offset = RELOCATED(.)
+	.word 0x0000
 
-	 .data
+__wakeup_segment = RELOCATED(.)
+	.word 0x0000
 
-	/* This is the gdt for GCC part of coreboot.
-	 * It is different from the gdt in ROMCC/ASM part of coreboot
-	 * which is defined in entry32.inc */
-gdt_wakeup:
-	/* selgdt 0, unused */
-	.word	0x0000, 0x0000		/* dummy */
-	.byte	0x00, 0x00, 0x00, 0x00
+	.globl __wakeup_size
+__wakeup_size = ( . - __wakeup)
 
-	/* selgdt 8, flat data segment 16bit */
-	.word	0x0000, 0x0000		/* dummy */
-	.byte	0x00, 0x93, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */	
-
-	/* selgdt 0x10, flat code segment 16bit */ 
-	.word	0xffff, 0x0000		
-	.byte	0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */	
-
-gdt_wakeup_end:
-
-	.previous
-.code32
Index: src/arch/i386/include/arch/acpi.h
===================================================================
--- src/arch/i386/include/arch/acpi.h	(revision 4861)
+++ src/arch/i386/include/arch/acpi.h	(working copy)
@@ -1,16 +1,27 @@ 
 /*
  * coreboot ACPI Support - headers and defines.
- * 
+ *
  * written by Stefan Reinauer <stepan@coresystems.de>
  * Copyright (C) 2004 SUSE LINUX AG
+ * Copyright (C) 2004 Nick Barker
  * Copyright (C) 2008-2009 coresystems GmbH
  *
- * The ACPI table structs are based on the Linux kernel sources.
- * ACPI FADT & FACS added by Nick Barker <nick.barker9@btinternet.com>
- * those parts (C) 2004 Nick Barker
+ * 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; version 2 of
+ * the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
  */
 
-
 #ifndef __ASM_ACPI_H
 #define __ASM_ACPI_H
 
@@ -48,6 +59,12 @@ 
 	u32 addrh;
 } __attribute__ ((packed)) acpi_addr_t;
 
+#define ACPI_ADDRESS_SPACE_MEMORY	   0
+#define ACPI_ADDRESS_SPACE_IO		   1
+#define ACPI_ADDRESS_SPACE_PCI		   2
+#define ACPI_ADDRESS_SPACE_FIXED	0x7f
+
+
 /* Generic ACPI Header, provided by (almost) all tables */
 
 typedef struct acpi_table_header         /* ACPI common table header */
@@ -63,13 +80,9 @@ 
 	u32  asl_compiler_revision;  /* ASL compiler revision number */
 } __attribute__ ((packed)) acpi_header_t;
 
-/* FIXME: This is very fragile:
- * MCONFIG, HPET, FADT, SRAT, SLIT, MADT(APIC), SSDT, SSDTX, and SSDT for CPU
- * pstate
- */
+/* A maximum number of 32 ACPI tables ought to be enough for now */
+#define MAX_ACPI_TABLES 32
 
-#define MAX_ACPI_TABLES (7 + CONFIG_ACPI_SSDTX_NUM + CONFIG_MAX_CPUS)
-
 /* RSDT */
 typedef struct acpi_rsdt {
 	struct acpi_table_header header;
@@ -330,6 +343,16 @@ 
 //
 #define ACPI_FACS_S4BIOS_F	(1 << 0)
 
+typedef struct acpi_ecdt {
+	struct acpi_table_header header;
+	struct acpi_gen_regaddr ec_control;
+	struct acpi_gen_regaddr ec_data;
+	u32 uid;
+	u8 gpe_bit;
+	u8 ec_id[];
+} __attribute__ ((packed)) acpi_ecdt_t;
+
+
 /* These are implemented by the target port */
 unsigned long write_acpi_tables(unsigned long addr);
 unsigned long acpi_fill_madt(unsigned long current);
@@ -382,7 +405,7 @@ 
 void suspend_resume(void);
 void *acpi_find_wakeup_vector(void);
 void *acpi_get_wakeup_rsdp(void);
-void acpi_jmp_to_realm_wakeup(u32 linear_addr);
+void acpi_jmp_to_realm_wakeup(u32 linear_addr) __attribute__((regparm(0)));
 void acpi_jump_to_wakeup(void *wakeup_addr);
 
 int acpi_get_sleep_type(void);
Index: src/arch/i386/lib/c_start.S
===================================================================
--- src/arch/i386/lib/c_start.S	(revision 4861)
+++ src/arch/i386/lib/c_start.S	(working copy)
@@ -253,7 +253,16 @@ 
 
 	/* This is the gdt for GCC part of coreboot.
 	 * It is different from the gdt in ROMCC/ASM part of coreboot
-	 * which is defined in entry32.inc */ /* BUT WHY?? */
+	 * which is defined in entry32.inc
+	 *
+	 * When the machine is initially started, we use a very simple
+	 * gdt from rom (that in entry32.inc) which only contains those
+	 * entries we need for protected mode.
+	 *
+	 * When we're executing code from RAM, we want to do more complex
+	 * stuff, like initializing PCI option roms in real mode, or doing
+	 * a resume from a suspend to ram. 
+	 */
 gdt:
 	/* selgdt 0, unused */
 	.word	0x0000, 0x0000		/* dummy */
@@ -275,6 +284,8 @@ 
 	.word	0x0000, 0x0000		/* dummy */
 	.byte	0x00, 0x00, 0x00, 0x00
 
+	/* The next two entries are used for executing VGA option ROMs */
+
 	/* selgdt 0x28 16-bit 64k code at 0x00000000 */
 	.word   0xffff, 0x0000
 	.byte   0, 0x9a, 0, 0
@@ -282,6 +293,16 @@ 
 	/* selgdt 0x30 16-bit 64k data at 0x00000000 */
 	.word   0xffff, 0x0000
 	.byte   0, 0x92, 0, 0
+
+	/* The next two entries are used for ACPI S3 RESUME */
+
+	/* selgdt 0x38, flat data segment 16bit */
+	.word	0x0000, 0x0000		/* dummy */
+	.byte	0x00, 0x93, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */	
+
+	/* selgdt 0x40, flat code segment 16bit */ 
+	.word	0xffff, 0x0000		
+	.byte	0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */	
 gdt_end:
 
 idtarg: