blob: 2c0950e3992be298424a0c7bce360849769523bb [file] [log] [blame]
Rudolf Marek33cafe52009-04-13 18:07:02 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz>
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +00005 * Copyright (C) 2009 coresystems GmbH
Rudolf Marek33cafe52009-04-13 18:07:02 +00006 *
7 * This program is free software; you can redistribute it and/or modify
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +00008 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
Rudolf Marek33cafe52009-04-13 18:07:02 +000010 *
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.
Rudolf Marek33cafe52009-04-13 18:07:02 +000015 */
Rudolf Marek33cafe52009-04-13 18:07:02 +000016
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000017#define WAKEUP_BASE 0x600
18#define RELOCATED(x) (x - __wakeup + WAKEUP_BASE)
19
20/* CR0 bits */
21#define PE (1 << 0)
22
Stefan Reinauer96938852015-06-18 01:23:48 -070023#ifdef __x86_64__
24 .code64
25#else
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000026 .code32
Stefan Reinauer96938852015-06-18 01:23:48 -070027#endif
28
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000029 .globl __wakeup
30__wakeup:
Stefan Reinauerac901e62015-07-31 16:46:28 -070031#ifdef __x86_64__
32 .intel_syntax noprefix
33 xor rax,rax
34 mov ax, ss
35 push rax
36 mov rax, rsp
37 add rax, 8
38 push rax
39 pushfq
40 push 0x10
41 lea rax,[rip+3]
42 push rax
43 iretq
44
45 .code32
46
47 /* disable paging */
48 mov eax, cr0
49 btc eax, 31
50 mov cr0, eax
51
52 /* disable long mode */
53 mov ecx, 0xC0000080
54 rdmsr
55 btc eax, 8
56 wrmsr
57 .att_syntax prefix
58#endif
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000059 /* First prepare the jmp to the resume vector */
60 mov 0x4(%esp), %eax /* vector */
Rudolf Marek33cafe52009-04-13 18:07:02 +000061 /* last 4 bits of linear addr are taken as offset */
62 andw $0x0f, %ax
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000063 movw %ax, (__wakeup_offset)
Rudolf Marek33cafe52009-04-13 18:07:02 +000064 mov 0x4(%esp), %eax
65 /* the rest is taken as segment */
66 shr $4, %eax
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000067 movw %ax, (__wakeup_segment)
68
69 /* Then overwrite coreboot with our backed up memory */
Stefan Reinauer8acbc2a2011-11-17 13:03:38 -080070 cld
71 movl 8(%esp), %esi
72 movl 12(%esp), %edi
73 movl 16(%esp), %ecx
74 shrl $2, %ecx
75 rep movsl
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000076
77 /* Activate the right segment descriptor real mode. */
78 ljmp $0x28, $RELOCATED(1f)
791:
80.code16
81 /* 16 bit code from here on... */
82
83 /* Load the segment registers w/ properly configured
84 * segment descriptors. They will retain these
85 * configurations (limits, writability, etc.) once
86 * protected mode is turned off.
87 */
88 mov $0x30, %ax
Stefan Reinauer14e22772010-04-27 06:56:47 +000089 mov %ax, %ds
90 mov %ax, %es
91 mov %ax, %fs
92 mov %ax, %gs
93 mov %ax, %ss
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000094
95 /* Turn off protection */
Rudolf Marek33cafe52009-04-13 18:07:02 +000096 movl %cr0, %eax
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000097 andl $~PE, %eax
Rudolf Marek33cafe52009-04-13 18:07:02 +000098 movl %eax, %cr0
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +000099
100 /* Now really going into real mode */
101 ljmp $0, $RELOCATED(1f)
1021:
Rudolf Marek33cafe52009-04-13 18:07:02 +0000103 movw $0x0, %ax
104 movw %ax, %ds
105 movw %ax, %es
106 movw %ax, %ss
107 movw %ax, %fs
108 movw %ax, %gs
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000109
110 /* This is a FAR JMP to the OS waking vector. The C code changed
111 * the address to be correct.
112 */
Rudolf Marek33cafe52009-04-13 18:07:02 +0000113 .byte 0xea
Rudolf Marek33cafe52009-04-13 18:07:02 +0000114
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000115__wakeup_offset = RELOCATED(.)
116 .word 0x0000
Rudolf Marek33cafe52009-04-13 18:07:02 +0000117
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000118__wakeup_segment = RELOCATED(.)
119 .word 0x0000
Rudolf Marek33cafe52009-04-13 18:07:02 +0000120
Stefan Reinauerc0ac7e92009-11-10 22:17:15 +0000121 .globl __wakeup_size
Aaron Durbina146d582013-02-08 16:56:51 -0600122__wakeup_size:
123 .long . - __wakeup