use movsl for copying resume memory back
[coreboot.git] / src / arch / x86 / boot / wakeup.S
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz>
5  * Copyright (C) 2009 coresystems GmbH
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 2 of the License.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #define WAKEUP_BASE             0x600
22 #define RELOCATED(x)    (x - __wakeup + WAKEUP_BASE)
23
24 /* CR0 bits */
25 #define PE              (1 << 0)
26
27         .code32
28         .globl __wakeup
29 __wakeup:
30         /* First prepare the jmp to the resume vector */
31         mov     0x4(%esp), %eax /* vector */
32         /* last 4 bits of linear addr are taken as offset */
33         andw    $0x0f, %ax
34         movw    %ax, (__wakeup_offset)
35         mov     0x4(%esp), %eax
36         /* the rest is taken as segment */
37         shr     $4, %eax
38         movw    %ax, (__wakeup_segment)
39
40         /* Then overwrite coreboot with our backed up memory */
41         cld
42         movl    8(%esp), %esi
43         movl    12(%esp), %edi
44         movl    16(%esp), %ecx
45         shrl    $2, %ecx
46         rep     movsl
47
48         /* Activate the right segment descriptor real mode. */
49         ljmp    $0x28, $RELOCATED(1f)
50 1:
51 .code16
52         /* 16 bit code from here on... */
53
54         /* Load the segment registers w/ properly configured
55          * segment descriptors. They will retain these
56          * configurations (limits, writability, etc.) once
57          * protected mode is turned off.
58          */
59         mov     $0x30, %ax
60         mov     %ax, %ds
61         mov     %ax, %es
62         mov     %ax, %fs
63         mov     %ax, %gs
64         mov     %ax, %ss
65
66         /* Turn off protection */
67         movl    %cr0, %eax
68         andl    $~PE, %eax
69         movl    %eax, %cr0
70
71         /* Now really going into real mode */
72         ljmp    $0, $RELOCATED(1f)
73 1:
74         movw    $0x0, %ax
75         movw    %ax, %ds
76         movw    %ax, %es
77         movw    %ax, %ss
78         movw    %ax, %fs
79         movw    %ax, %gs
80
81         /* This is a FAR JMP to the OS waking vector. The C code changed
82          * the address to be correct.
83          */
84         .byte 0xea
85
86 __wakeup_offset = RELOCATED(.)
87         .word 0x0000
88
89 __wakeup_segment = RELOCATED(.)
90         .word 0x0000
91
92         .globl __wakeup_size
93 __wakeup_size = ( . - __wakeup)
94