[coreboot] [v2] r4101 - in trunk/coreboot-v2/src/arch/i386: boot include/arch

svn at coreboot.org svn at coreboot.org
Mon Apr 13 20:07:02 CEST 2009


Author: ruik
Date: 2009-04-13 20:07:02 +0200 (Mon, 13 Apr 2009)
New Revision: 4101

Added:
   trunk/coreboot-v2/src/arch/i386/boot/wakeup.S
Modified:
   trunk/coreboot-v2/src/arch/i386/boot/Config.lb
   trunk/coreboot-v2/src/arch/i386/boot/acpi.c
   trunk/coreboot-v2/src/arch/i386/include/arch/acpi.h
Log:
Following patch implements ACPI resume support for coreboot. The hardware main
hook will come in separate patch perhaps.

Signed-off-by: Rudolf Marek <r.marek at assembler.cz>
Acked-by: Peter Stuge <peter at stuge.se>



Modified: trunk/coreboot-v2/src/arch/i386/boot/Config.lb
===================================================================
--- trunk/coreboot-v2/src/arch/i386/boot/Config.lb	2009-04-13 18:00:09 UTC (rev 4100)
+++ trunk/coreboot-v2/src/arch/i386/boot/Config.lb	2009-04-13 18:07:02 UTC (rev 4101)
@@ -14,4 +14,7 @@
 if HAVE_ACPI_TABLES
 object acpi.o
 object acpigen.o
+if HAVE_ACPI_RESUME
+object wakeup.S
 end
+end

Modified: trunk/coreboot-v2/src/arch/i386/boot/acpi.c
===================================================================
--- trunk/coreboot-v2/src/arch/i386/boot/acpi.c	2009-04-13 18:00:09 UTC (rev 4100)
+++ trunk/coreboot-v2/src/arch/i386/boot/acpi.c	2009-04-13 18:07:02 UTC (rev 4101)
@@ -27,6 +27,11 @@
 #include <arch/acpigen.h>
 #include <device/pci.h>
 
+#if HAVE_ACPI_RESUME == 1
+/* this is to be filled by SB code - startup value what was found */
+u8 acpi_slp_type;
+#endif
+
 u8 acpi_checksum(u8 *table, u32 length)
 {
 	u8 ret=0;
@@ -323,12 +328,12 @@
 	
 	header->checksum	= acpi_checksum((void *)hpet, sizeof(acpi_hpet_t));
 }
-
 void acpi_create_facs(acpi_facs_t *facs)
 {
+	
 	memset( (void *)facs,0, sizeof(acpi_facs_t));
 
-	memcpy(facs->signature,"FACS",4);
+	memcpy(facs->signature, FACS_NAME, 4);
 	facs->length = sizeof(acpi_facs_t);
 	facs->hardware_signature = 0;
 	facs->firmware_waking_vector = 0;
@@ -365,11 +370,114 @@
 {
 	memcpy(rsdp->signature, RSDP_SIG, 8);
 	memcpy(rsdp->oem_id, OEM_ID, 6);
-	
 	rsdp->length		= sizeof(acpi_rsdp_t);
 	rsdp->rsdt_address	= (u32)rsdt;
+	rsdp->revision		= 2;
 	rsdp->checksum		= acpi_checksum((void *)rsdp, 20);
 	rsdp->ext_checksum	= acpi_checksum((void *)rsdp, sizeof(acpi_rsdp_t));
 }
 
+#if HAVE_ACPI_RESUME == 1
 
+int acpi_get_sleep_type(void)
+{
+	return acpi_slp_type;
+}
+
+int acpi_is_wakeup(void)
+{
+	return (acpi_slp_type == 3);
+}
+
+static acpi_rsdp_t *valid_rsdp(acpi_rsdp_t *rsdp)
+{
+	if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0)
+		return NULL;
+
+	printk_debug("Looking on %p for valid checksum\n", rsdp);
+
+	if (acpi_checksum((void *)rsdp, 20) != 0)
+		return NULL;
+	printk_debug("Checksum 1 passed\n");
+
+	if ((rsdp->revision > 1) && (acpi_checksum((void *)rsdp,
+						rsdp->length) != 0))
+		return NULL;
+
+	printk_debug("Checksum 2 passed all OK\n");
+
+	return rsdp;
+}
+
+static acpi_rsdp_t *rsdp;
+
+void *acpi_get_wakeup_rsdp(void)
+{
+	return rsdp;
+}
+
+void *acpi_find_wakeup_vector(void)
+{
+	char *p, *end;
+
+	acpi_rsdt_t *rsdt;
+	acpi_facs_t *facs;
+	acpi_fadt_t *fadt;
+	void  *wake_vec;
+	int i;
+
+	rsdp = NULL;
+
+	if (!acpi_is_wakeup())
+		return NULL;
+
+	printk_debug("Trying to find the wakeup vector ...\n");
+
+	/* find RSDP */
+	for (p = (char *) 0xe0000; p <  (char *) 0xfffff; p+=16) {
+		if ((rsdp = valid_rsdp((acpi_rsdp_t *) p)))
+			break;
+	}
+
+	if (rsdp == NULL)
+		return NULL;
+
+	printk_debug("RSDP found at %p\n", rsdp);
+	rsdt = (acpi_rsdt_t *) rsdp->rsdt_address;
+	
+	end = (char *) rsdt + rsdt->header.length;
+	printk_debug("RSDT found at %p ends at %p\n", rsdt, end);
+
+	for (i = 0; ((char *) &rsdt->entry[i]) < end; i++) {
+		fadt = (acpi_fadt_t *) rsdt->entry[i];
+		if (strncmp((char *)fadt, FADT_NAME, sizeof(FADT_NAME) - 1) == 0)
+			break;
+		fadt = NULL;
+	}
+
+	if (fadt == NULL)
+		return NULL;
+
+	printk_debug("FADT found at %p\n", fadt);
+	facs = fadt->firmware_ctrl;
+
+	if (facs == NULL)
+		return NULL;
+
+	printk_debug("FACS found at %p\n", facs);
+	wake_vec = (void *) facs->firmware_waking_vector;
+	printk_debug("OS waking vector is %p\n", wake_vec);
+	return wake_vec;
+}
+
+extern char *lowmem_backup;
+extern char *lowmem_backup_ptr;
+extern int lowmem_backup_size;
+
+void acpi_jump_to_wakeup(void *vector)
+{
+	/* 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);
+}
+#endif

Added: trunk/coreboot-v2/src/arch/i386/boot/wakeup.S
===================================================================
--- trunk/coreboot-v2/src/arch/i386/boot/wakeup.S	                        (rev 0)
+++ trunk/coreboot-v2/src/arch/i386/boot/wakeup.S	2009-04-13 18:07:02 UTC (rev 4101)
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 Rudolf Marek <r.marek at assembler.cz>
+ *
+ * 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.
+ *
+ * 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
+ */
+	.text
+	.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
+	/* last 4 bits of linear addr are taken as offset */
+	andw	$0x0f, %ax
+	movw	%ax, (jmp_off)
+	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 */
+	movl	%cr0, %eax
+	andb	$0xfe,%al
+	movl	%eax, %cr0
+	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 */
+	.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 */
+
+	 .data
+
+	/* 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
+
+	/* 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

Modified: trunk/coreboot-v2/src/arch/i386/include/arch/acpi.h
===================================================================
--- trunk/coreboot-v2/src/arch/i386/include/arch/acpi.h	2009-04-13 18:00:09 UTC (rev 4100)
+++ trunk/coreboot-v2/src/arch/i386/include/arch/acpi.h	2009-04-13 18:07:02 UTC (rev 4101)
@@ -16,6 +16,9 @@
 #if HAVE_ACPI_TABLES==1
 
 #include <stdint.h>
+ 
+/* 0 = S0, 1 = S1 ...*/
+extern u8 acpi_slp_type;
 
 #define RSDP_SIG              "RSD PTR "  /* RSDT Pointer signature */
 #define RSDP_NAME             "RSDP"
@@ -27,6 +30,8 @@
 #define SRAT_NAME             "SRAT"
 #define SLIT_NAME	      "SLIT"
 #define SSDT_NAME	      "SSDT"
+#define FACS_NAME	      "FACS"
+#define FADT_NAME	      "FACP"
 
 #define RSDT_TABLE            "RSDT    "
 #define HPET_TABLE            "AMD64   "
@@ -328,6 +333,10 @@
 
 void acpi_write_rsdt(acpi_rsdt_t *rsdt);
 void acpi_write_rsdp(acpi_rsdp_t *rsdp, acpi_rsdt_t *rsdt);
+void *acpi_find_wakeup_vector(void);
+void *acpi_get_wakeup_rsdp(void);
+extern void acpi_jmp_to_realm_wakeup(u32 linear_addr);
+void acpi_jump_to_wakeup(void *wakeup_addr);
 
 unsigned long acpi_add_ssdt_pstates(acpi_rsdt_t *rsdt, unsigned long current);
 





More information about the coreboot mailing list