Statistics
| Branch: | Revision:

root / pc-bios / optionrom / multiboot.S @ 8676188b

History | View | Annotate | Download (4.3 kB)

1
/*
2
 * Multiboot Option ROM
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 2 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
 *
18
 * Copyright Novell Inc, 2009
19
 *   Authors: Alexander Graf <agraf@suse.de>
20
 */
21

    
22
#define NO_QEMU_PROTOS
23
#include "../../hw/fw_cfg.h"
24

    
25
#define BIOS_CFG_IOPORT_CFG	0x510
26
#define BIOS_CFG_IOPORT_DATA	0x511
27

    
28
#define MULTIBOOT_MAGIC		0x2badb002
29

    
30
/* Read a variable from the fw_cfg device.
31
   Clobbers:	%edx
32
   Out:		%eax */
33
.macro read_fw VAR
34
	mov		$\VAR, %ax
35
	mov		$BIOS_CFG_IOPORT_CFG, %dx
36
	outw		%ax, (%dx)
37
	mov		$BIOS_CFG_IOPORT_DATA, %dx
38
	inb		(%dx), %al
39
	shl		$8, %eax
40
	inb		(%dx), %al
41
	shl		$8, %eax
42
	inb		(%dx), %al
43
	shl		$8, %eax
44
	inb		(%dx), %al
45
	bswap		%eax
46
.endm
47

    
48
.code16
49
.text
50
	.global 	_start
51
_start:
52
	.short		0xaa55
53
	.byte		1 /* (_end - _start) / 512 */
54
	push		%eax
55
	push		%ds
56

    
57
	/* setup ds so we can access the IVT */
58
	xor		%ax, %ax
59
	mov		%ax, %ds
60

    
61
	/* save old int 19 */
62
	mov		(0x19*4), %eax
63
	mov		%eax, %cs:old_int19
64

    
65
	/* install our int 19 handler */
66
	movw		$int19_handler, (0x19*4)
67
	mov		%cs, (0x19*4+2)
68

    
69
	pop		%ds
70
	pop		%eax
71
	lret
72

    
73
int19_handler:
74
	/* DS = CS */
75
	movw		%cs, %ax
76
	movw		%ax, %ds
77

    
78
	/* fall through */
79

    
80
run_multiboot:
81

    
82
	cli
83
	cld
84

    
85
	mov		%cs, %eax
86
	shl		$0x4, %eax
87

    
88
	/* fix the gdt descriptor to be PC relative */
89
	mov		(gdt_desc+2), %ebx
90
	add		%eax, %ebx
91
	mov		%ebx, (gdt_desc+2)
92

    
93
	/* fix the prot mode indirect jump to be PC relative */
94
	mov		(prot_jump), %ebx
95
	add		%eax, %ebx
96
	mov		%ebx, (prot_jump)
97

    
98
	/* FS = bootinfo_struct */
99
	read_fw		FW_CFG_INITRD_ADDR
100
	shr		$4, %eax
101
	mov		%ax, %fs
102

    
103
	/* ES = mmap_addr */
104
	read_fw		FW_CFG_INITRD_SIZE
105
	shr		$4, %eax
106
	mov		%ax, %es
107

    
108
	/* Initialize multiboot mmap structs using int 0x15(e820) */
109
	xor		%ebx, %ebx
110
	/* mmap start after first size */
111
	movl		$4, %edi
112

    
113
mmap_loop:
114
	/* entry size (mmap struct) & max buffer size (int15) */
115
	movl		$20, %ecx
116
	/* store entry size */
117
	movl		%ecx, %es:-4(%edi)
118
	/* e820 */
119
	movl		$0x0000e820, %eax
120
	/* 'SMAP' magic */
121
	movl		$0x534d4150, %edx
122
	int		$0x15
123

    
124
mmap_check_entry:
125
	/* last entry? then we're done */
126
	jb		mmap_done
127
	and		%bx, %bx
128
	jz		mmap_done
129
	/* valid entry, so let's loop on */
130

    
131
mmap_store_entry:
132
	/* %ax = entry_number * 24 */
133
	mov		$24, %ax
134
	mul		%bx
135
	mov		%ax, %di
136
	movw		%di, %fs:0x2c
137
	/* %di = 4 + (entry_number * 24) */
138
	add		$4, %di
139
	jmp		mmap_loop
140

    
141
mmap_done:
142
real_to_prot:
143
	/* Load the GDT before going into protected mode */
144
lgdt:
145
	data32 lgdt	%cs:gdt_desc
146

    
147
	/* get us to protected mode now */
148
	movl		$1, %eax
149
	movl		%eax, %cr0
150

    
151
	/* the LJMP sets CS for us and gets us to 32-bit */
152
ljmp:
153
	data32 ljmp	*%cs:prot_jump
154

    
155
prot_mode:
156
.code32
157

    
158
	/* initialize all other segments */
159
	movl		$0x10, %eax
160
	movl		%eax, %ss
161
	movl		%eax, %ds
162
	movl		%eax, %es
163
	movl		%eax, %fs
164
	movl		%eax, %gs
165

    
166
	/* Jump off to the kernel */
167
	read_fw		FW_CFG_KERNEL_ADDR
168
	mov		%eax, %ecx
169

    
170
	/* EBX contains a pointer to the bootinfo struct */
171
	read_fw		FW_CFG_INITRD_ADDR
172
	movl		%eax, %ebx
173

    
174
	/* EAX has to contain the magic */
175
	movl		$MULTIBOOT_MAGIC, %eax
176
ljmp2:
177
	jmp		*%ecx
178

    
179
/* Variables */
180
.align 4, 0
181
old_int19:	.long 0
182

    
183
prot_jump:	.long prot_mode
184
		.short 8
185

    
186
.align 4, 0
187
gdt:
188
	/* 0x00 */
189
.byte	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
190

    
191
	/* 0x08: code segment (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k) */
192
.byte	0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00
193

    
194
	/* 0x10: data segment (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k) */
195
.byte	0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00
196

    
197
	/* 0x18: code segment (base=0, limit=0x0ffff, type=16bit code exec/read/conf, DPL=0, 1b) */
198
.byte	0xff, 0xff, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00
199

    
200
	/* 0x20: data segment (base=0, limit=0x0ffff, type=16bit data read/write, DPL=0, 1b) */
201
.byte	0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00
202

    
203
gdt_desc:
204
.short	(5 * 8) - 1
205
.long	gdt
206

    
207
.align 512, 0
208
_end:
209