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 movl 8(%esp), %esi 42 movl 12(%esp), %edi 43 movl 16(%esp), %ecx 44 shrl $4, %ecx 451: 46 movl 0(%esi),%eax 47 movl 4(%esi),%edx 48 movl 8(%esi),%ebx 49 movl 12(%esi),%ebp 50 addl $16,%esi 51 subl $1,%ecx 52 movl %eax,0(%edi) 53 movl %edx,4(%edi) 54 movl %ebx,8(%edi) 55 movl %ebp,12(%edi) 56 leal 16(%edi),%edi 57 jne 1b 58 59 /* Activate the right segment descriptor real mode. */ 60 ljmp $0x28, $RELOCATED(1f) 611: 62.code16 63 /* 16 bit code from here on... */ 64 65 /* Load the segment registers w/ properly configured 66 * segment descriptors. They will retain these 67 * configurations (limits, writability, etc.) once 68 * protected mode is turned off. 69 */ 70 mov $0x30, %ax 71 mov %ax, %ds 72 mov %ax, %es 73 mov %ax, %fs 74 mov %ax, %gs 75 mov %ax, %ss 76 77 /* Turn off protection */ 78 movl %cr0, %eax 79 andl $~PE, %eax 80 movl %eax, %cr0 81 82 /* Now really going into real mode */ 83 ljmp $0, $RELOCATED(1f) 841: 85 movw $0x0, %ax 86 movw %ax, %ds 87 movw %ax, %es 88 movw %ax, %ss 89 movw %ax, %fs 90 movw %ax, %gs 91 92 /* This is a FAR JMP to the OS waking vector. The C code changed 93 * the address to be correct. 94 */ 95 .byte 0xea 96 97__wakeup_offset = RELOCATED(.) 98 .word 0x0000 99 100__wakeup_segment = RELOCATED(.) 101 .word 0x0000 102 103 .globl __wakeup_size 104__wakeup_size = ( . - __wakeup) 105 106

