2 * This file is part of the coreboot project.
4 * Copyright (C) 1999 Ronald G. Minnich
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <arch/rom_segs.h>
25 /* Save the BIST result. */
28 /* thanks to kmliu@sis.com.tw for this TLB fix */
29 /* IMMEDIATELY invalidate the translation lookaside buffer (TLB) before
30 * executing any further code. Even though paging is disabled we
31 * could still get false address translations due to the TLB if we
32 * didn't invalidate it.
35 movl %eax, %cr3 /* Invalidate TLB. */
37 /* Switch to protected mode. */
39 /* NOTE: With GNU assembler version 2.15.94.0.2.2 (i386-redhat-linux)
40 * using BFD version 2.15.94.0.2.2 20041220 this works fine without all
41 * the ld hackery and other things. So leave it as is with this comment.
44 data32 lgdt %cs:gdtptr
47 andl $0x7FFAFFD1, %eax /* PG, AM, WP, NE, TS, EM, MP = 0 */
48 orl $0x60000001, %eax /* CD, NW, PE = 1 */
51 /* Restore BIST result. */
55 /* Now we are in protected mode. Jump to a 32 bit code segment. */
56 data32 ljmp $ROM_CODE_SEG, $protected_stage0
58 /* I am leaving this weird jump in here in the event that future gas
59 * bugs force it to be used.
63 /* ljmp $ROM_CODE_SEG, $protected_stage0 */
70 .word gdt16xend - gdt16x -1 /* Compute the table limit. */
74 /* selgdt 0x08, flat code segment */
76 .byte 0x00, 0x9b, 0xcf, 0x00
78 /* selgdt 0x10, flat data segment */
80 .byte 0x00, 0x93, 0xcf, 0x00
83 /* From now on we are 32 bit. */
86 /* We have two gdts where we could have one. That is ok.
88 * Let's not worry about this -- optimizing gdt is pointless since
89 * we're only in it for a little bit.
91 * Btw. note the trick below: The GDT points to ITSELF, and the first
92 * good descriptor is at offset 8. So you word-align the table, and
93 * then because you chose 8, you get a nice 64-bit aligned GDT entry,
94 * which is good as this is the size of the entry.
95 * Just in case you ever wonder why people do this.
100 gdt_limit = gdt_end - gdt - 1 /* Compute the table limit. */
104 .word gdt_end - gdt -1 /* Compute the table limit. */
105 .long gdt /* We know the offset. */
108 /* selgdt 0x08, flat code segment */
110 .byte 0x00, 0x9b, 0xcf, 0x00
112 /* selgdt 0x10, flat data segment */
114 .byte 0x00, 0x93, 0xcf, 0x00
121 * RVECTOR: Size of reset vector, default is 0x10.
122 * RESRVED: Size of vpd code, default is 0xf0.
123 * BOOTBLK: Size of bootblock code, default is 0x1f00 (8k-256b).
126 SEGMENT_SIZE = 0x10000
129 /* Due to YET ANOTHER BUG in GNU bintools, you can NOT have a code16 here.
130 * I think we should leave it this way forever, as the bugs come and
131 * go -- and come again.
134 * .section ".rom.text"
136 .section ".reset", "ax"
139 /* GNU bintools bugs again. This jumps to stage0 - 2. Sigh. */
142 .int _stage0 - ( . + 2 )
144 /* Note: The above jump is hand coded to work around bugs in binutils.
145 * 5 bytes are used for a 3 byte instruction. This works because x86
146 * is little endian and allows us to use supported 32 bit relocations
147 * instead of the weird 16 bit relocations that binutils does not
148 * handle consistenly between versions because they are used so rarely.