File: early_init.S

package info (click to toggle)
faumachine 20100527-2
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 53,836 kB
  • ctags: 20,552
  • sloc: ansic: 179,550; asm: 3,645; makefile: 3,611; perl: 2,103; sh: 1,529; python: 600; xml: 563; lex: 210; vhdl: 204
file content (315 lines) | stat: -rw-r--r-- 7,001 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/*
 * $Id: early_init.S,v 1.5 2009-07-29 07:15:36 vrsieh Exp $ 
 *
 * Copyright (C) 2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

/* FIXME */
#define HACK_FOR_KVM_INTEL	1

#include "build_config.h"
#include "libsys.h"
#include "compiler.h"

#define PCI_ADDR(bus, dev, func) \
        (((bus) << 16) | ((dev) << 11) | ((func) << 8))
#define PCICONF_ADDR    0x0cf8
#define PCICONF_DATA    0x0cfc


#ifdef INIT_EARLY
	.section .text.reset, "ax"
	/* .org 0xfffffff0 */
	.code16
_C_LABEL(bios_entry): .globl _C_LABEL(bios_entry)
	jmp early_init_entry

	.section .text
	.code16gcc
early_init_entry: .globl early_init_entry
	/*
	 * test warm reset
	 */
	movb $0x0f, %al /* read reset type */
	outb %al, $0x70
	inb $0x71, %al
	cmp $0x05, %al
	jnz start_init
	movb $0x0f, %al /* set reset type to default value */
	outb %al, $0x70
	movb $0x00, %al
	outb %al, $0x71

	ljmpw *(0x0467)

start_init:
	/*
	 * Switch to protected mode.
	 */
	movl $init_gdt, %eax
	andl $0xffff, %eax
	lgdtl %cs:(%eax)

	movl %cr0, %eax
	orl $1, %eax
	movl %eax, %cr0

	movw $16, %ax
	movw %ax, %ds
	movw %ax, %es

	/* Ugly -- FIXME */
	ljmpw $8, $(start_init2 - early_init_entry + 0xf000)

	// .code32
start_init2:
	/*
	 * Enable 1Mbyte BIOS.
	 */
	movl $PCI_ADDR(0, 7, 0) | 0x80000000 | 0x4c, %eax
	movw $PCICONF_ADDR, %dx
	outl %eax, %dx
	movw $PCICONF_DATA + 2, %dx
	inw %dx
	orw $(1 << 9) | (1 << 7) | (1 << 6), %ax
	outw %ax, %dx

	/*
	 * Init Memory
	 *
	 * See 82443BX Host Bridge Datasheet.
	 */
	movw $0, %cx    /* Counter for 8 registers to set. */
	movl $0, %esi   /* Up to that limit memory is found. */
	movl $0, %edi   /* Up to that limit memory is tested. */

mem_init_loop:
	/* Set register of host bridge to support as much memory as */
	/* possible (0x80 * 8 MByte) to be able to access/test it... */
	/* reg(0x60 + %cx) <= 0x80 */
	movl $PCI_ADDR(0, 0, 0) | 0x80000000 | 0x60, %eax
	orb %cl, %al
	andb $0xfc, %al
	movw $PCICONF_ADDR, %dx
	outl %eax, %dx
	movw %cx, %dx
	andw $0x03, %dx
	orw $PCICONF_DATA, %dx
	movb $0x80, %al
	outb %al, %dx

mem_init_test:
	movb $0x00, (%edi)
	cmpb $0x00, (%edi)
	jne mem_end_found
	movb $0xff, (%edi)
	cmpb $0xff, (%edi)
	jne mem_end_found
	movb $0x55, (%edi)
	cmpb $0x55, (%edi)
	jne mem_end_found
	movb $0xaa, (%edi)
	cmpb $0xaa, (%edi)
	jne mem_end_found

	addl $8*1024*1024, %edi

	movb $0x00, (%esi)
	movb $0xff, (%edi)
	cmpb $0x00, (%esi)
	je mem_init_test

mem_end_found:
	movl %edi, %eax
	shrl $23, %eax

	/* PCICONF_ADDR already set. */
	/* %dx already set. */
	outb %al, %dx

	movl %edi, %esi
	addw $1, %cx
	cmpw $8, %cx
	jne mem_init_loop

	/*
	 * Copy BIOS INIT data to "vma_init_rm_data".
	 */
	movl $evma_init_rm_data, %ecx
	subl $vma_init_rm_data, %ecx
	movl $vma_init_rm_data, %edi
	movl $lma_init_rm_data, %esi
	rep movsb %ds:(%esi), %es:(%edi)

	/*
	 * Clear BIOS INIT bss at "vma_init_rm_bss".
	 */
	movl $evma_init_rm_bss, %ecx
	subl $vma_init_rm_bss, %ecx
	movl $vma_init_rm_bss, %edi
	movb $0, %al
	rep stosb %es:(%edi)

	/*
	 * Copy BIOS INIT part to 0x10000.
	 */
	movl $evma_init_rm, %ecx
	subl $vma_init_rm, %ecx
	movl $vma_init_rm, %edi
	movl $lma_init_rm, %esi
	rep movsb %ds:(%esi), %es:(%edi)

#ifdef CONFIG_SMI_SUPPORT
	/*
	 * Copy BIOS SMM redirect part to 0x38000.
	 */
	movl $evma_smi_redirect, %ecx
	subl $vma_smi_redirect, %ecx
	movl $vma_smi_redirect, %edi
	movl $lma_smi_redirect, %esi
	rep movsb %ds:(%esi), %es:(%edi)

	/*
	 * Open SMM space to be able to copy SMM part of BIOS to 0xa8000.
	 */
	movl $PCI_ADDR(0, 0, 0) | 0x80000000 | 0x70, %eax
	movw $PCICONF_ADDR, %dx
	outl %eax, %dx
	movw $PCICONF_DATA + 2, %dx
	movb $(1 << 6) | (1 << 3), %al
	outb %al, %dx

	/*
	 * Copy BIOS SMM part to 0xa8000.
	 */
	movl $evma_smi, %ecx
	subl $vma_smi, %ecx
	movl $vma_smi, %edi
	movl $lma_smi, %esi
	rep movsb %ds:(%esi), %es:(%edi)

	/*
	 * Lock SMM space.
	 */
	movl $PCI_ADDR(0, 0, 0) | 0x80000000 | 0x70, %eax
	movw $PCICONF_ADDR, %dx
	outl %eax, %dx
	movw $PCICONF_DATA + 2, %dx
	movb $(1 << 4) | (1 << 3), %al
	outb %al, %dx
#endif /* CONFIG_SMI_SUPPORT */

	/*
	 * Set PAM registers to be able to copy RUNTIME part of
	 * BIOS to 0xe0000-0xfffff.
	 */
	movl $PCI_ADDR(0, 0, 0) | 0x80000000 | 0x58, %eax
	movw $PCICONF_ADDR, %dx
	outl %eax, %dx
	movw $PCICONF_DATA, %dx
	movl $0x00003000, %eax
	outl %eax, %dx

	/*
	 * Set PAM registers to be able to copy RUNTIME part of
	 * BIOS to 0xe0000-0xfffff.
	 */
	movl $PCI_ADDR(0, 0, 0) | 0x80000000 | 0x58, %eax
	movw $PCICONF_ADDR, %dx
	outl %eax, %dx
	movw $PCICONF_DATA, %dx
	movl $0x00003000, %eax
	outl %eax, %dx
	movl $PCI_ADDR(0, 0, 0) | 0x80000000 | 0x5c, %eax
	movw $PCICONF_ADDR, %dx
	outl %eax, %dx
	movw $PCICONF_DATA, %dx
	movl $0x33330000, %eax
	outl %eax, %dx

	/*
	 * Copy BIOS RUNTIME part to 0xe0000-0xfffff.
	 */
	movl $evma_rt_legacy, %ecx
	subl $vma_rt_legacy, %ecx
	movl $vma_rt_legacy, %edi
	movl $lma_rt_legacy, %esi
	rep movsb %ds:(%esi), %es:(%edi)

	/*
	 * Set PAM registers to make BIOS RUNTIME part read-only.
	 */
	movl $PCI_ADDR(0, 0, 0) | 0x80000000 | 0x58, %eax
	movw $PCICONF_ADDR, %dx
	outl %eax, %dx
	movw $PCICONF_DATA, %dx
	inl %dx, %eax
	andl $0xfffffbff, %eax  /* WE bit of range 0xf0000-0xfffff. */
	outl %eax, %dx
	movl $PCI_ADDR(0, 0, 0) | 0x80000000 | 0x5c, %eax
	movw $PCICONF_ADDR, %dx
	outl %eax, %dx
	movw $PCICONF_DATA, %dx
	inl %dx, %eax
	andl $0xbbbbffff, %eax  /* WE bits of range 0xe0000-0xeffff. */
	outl %eax, %dx

	/*
	 * Switch back to real-mode.
	 */
#ifdef HACK_FOR_KVM_INTEL
	movw $0xfffe, %dx
	movb $42, %al
	outb %al, %dx
#endif
	movl %cr0, %eax
	andl $~1, %eax
	movl %eax, %cr0

	/*
	 * Jump to INIT part of BIOS.
	 * This changes %cs segment.
	 */
	ex_ljmp init_rm_bsp

	.section .rodata
init_gdt:
	/* Null descriptor/GDT descriptor */
	.word 3 * 8 - 1
	.long init_gdt
	.word 0

	/* Code descriptor */
	.word 0xffff		/* Limit 15:0 */
	.word 0x0000		/* Base 15:0 */
	.word (1 << 15)		/* Present */ \
	    | (0 << 13)		/* DPL */ \
	    | (1 << 12)		/* Code/Data */ \
	    | (0xb << 8)	/* Code+Accessed */ \
	    | 0xff		/* Base 23:16 */
	.word (0xff << (24-16))	/* Base 31:24 */ \
	    | (1 << (23-16))	/* Granularity */ \
	    | (0 << (22-16))	/* 16bit Code */ \
	    | (0 << (21-16))	/* Unused */ \
	    | (0 << (20-16))	/* Available */ \
	    | (0xf << (16-16))	/* Limit 19:16 */

	/* Data descriptor */
	.word 0xffff		/* Limit 15:0 */
	.word 0x0000		/* Base 15:0 */
	.word (1 << 15)		/* Present */ \
	    | (0 << 13)		/* DPL */ \
	    | (1 << 12)		/* Code/Data */ \
	    | (0x3 << 8)	/* Data+Accessed */ \
	    | 0x00		/* Base 23:16 */
	.word (0x00 << (24-16))	/* Base 31:24 */ \
	    | (1 << (23-16))	/* Granularity */ \
	    | (0 << (22-16))	/* 16bit Data */ \
	    | (0 << (21-16))	/* Unused */ \
	    | (0 << (20-16))	/* Available */ \
	    | (0xf << (16-16))	/* Limit 19:16 */

#endif /* INIT_EARLY */