root / pc-bios / optionrom / multiboot.S @ 75b9f690
History | View | Annotate | Download (4.1 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, see <http://www.gnu.org/licenses/>. |
16 |
* |
17 |
* Copyright Novell Inc, 2009 |
18 |
* Authors: Alexander Graf <agraf@suse.de> |
19 |
*/ |
20 |
|
21 |
#include "optionrom.h" |
22 |
|
23 |
#define BOOT_ROM_PRODUCT "multiboot loader" |
24 |
|
25 |
#define MULTIBOOT_MAGIC 0x2badb002 |
26 |
|
27 |
#define GS_PROT_JUMP 0 |
28 |
#define GS_GDT_DESC 6 |
29 |
|
30 |
|
31 |
BOOT_ROM_START |
32 |
|
33 |
run_multiboot: |
34 |
|
35 |
cli |
36 |
cld |
37 |
|
38 |
mov %cs, %eax |
39 |
shl $0x4, %eax |
40 |
|
41 |
/* set up a long jump descriptor that is PC relative */ |
42 |
|
43 |
/* move stack memory to %gs */ |
44 |
mov %ss, %ecx |
45 |
shl $0x4, %ecx |
46 |
mov %esp, %ebx |
47 |
add %ebx, %ecx |
48 |
sub $0x20, %ecx |
49 |
sub $0x30, %esp |
50 |
shr $0x4, %ecx |
51 |
mov %cx, %gs |
52 |
|
53 |
/* now push the indirect jump decriptor there */ |
54 |
mov (prot_jump), %ebx |
55 |
add %eax, %ebx |
56 |
movl %ebx, %gs:GS_PROT_JUMP |
57 |
mov $8, %bx |
58 |
movw %bx, %gs:GS_PROT_JUMP + 4 |
59 |
|
60 |
/* fix the gdt descriptor to be PC relative */ |
61 |
movw (gdt_desc), %bx |
62 |
movw %bx, %gs:GS_GDT_DESC |
63 |
movl (gdt_desc+2), %ebx |
64 |
add %eax, %ebx |
65 |
movl %ebx, %gs:GS_GDT_DESC + 2 |
66 |
|
67 |
xor %eax, %eax |
68 |
mov %eax, %es |
69 |
|
70 |
/* Read the bootinfo struct into RAM */ |
71 |
read_fw_blob(FW_CFG_INITRD) |
72 |
|
73 |
/* FS = bootinfo_struct */ |
74 |
read_fw FW_CFG_INITRD_ADDR |
75 |
shr $4, %eax |
76 |
mov %ax, %fs |
77 |
|
78 |
/* ES = mmap_addr */ |
79 |
mov %fs:48, %eax |
80 |
shr $4, %eax |
81 |
mov %ax, %es |
82 |
|
83 |
/* Initialize multiboot mmap structs using int 0x15(e820) */ |
84 |
xor %ebx, %ebx |
85 |
/* mmap start after first size */ |
86 |
movl $4, %edi |
87 |
|
88 |
mmap_loop: |
89 |
/* entry size (mmap struct) & max buffer size (int15) */ |
90 |
movl $20, %ecx |
91 |
/* store entry size */ |
92 |
/* old as(1) doesn't like this insn so emit the bytes instead: |
93 |
movl %ecx, %es:-4(%edi) |
94 |
*/ |
95 |
.dc.b 0x26,0x67,0x66,0x89,0x4f,0xfc |
96 |
/* e820 */ |
97 |
movl $0x0000e820, %eax |
98 |
/* 'SMAP' magic */ |
99 |
movl $0x534d4150, %edx |
100 |
int $0x15 |
101 |
|
102 |
mmap_check_entry: |
103 |
/* last entry? then we're done */ |
104 |
jb mmap_done |
105 |
and %bx, %bx |
106 |
jz mmap_done |
107 |
/* valid entry, so let's loop on */ |
108 |
|
109 |
mmap_store_entry: |
110 |
/* %ax = entry_number * 24 */ |
111 |
mov $24, %ax |
112 |
mul %bx |
113 |
mov %ax, %di |
114 |
movw %di, %fs:0x2c |
115 |
/* %di = 4 + (entry_number * 24) */ |
116 |
add $4, %di |
117 |
jmp mmap_loop |
118 |
|
119 |
mmap_done: |
120 |
real_to_prot: |
121 |
/* Load the GDT before going into protected mode */ |
122 |
lgdt: |
123 |
data32 lgdt %gs:GS_GDT_DESC |
124 |
|
125 |
/* get us to protected mode now */ |
126 |
movl $1, %eax |
127 |
movl %eax, %cr0 |
128 |
|
129 |
/* the LJMP sets CS for us and gets us to 32-bit */ |
130 |
ljmp: |
131 |
data32 ljmp *%gs:GS_PROT_JUMP |
132 |
|
133 |
prot_mode: |
134 |
.code32 |
135 |
|
136 |
/* initialize all other segments */ |
137 |
movl $0x10, %eax |
138 |
movl %eax, %ss |
139 |
movl %eax, %ds |
140 |
movl %eax, %es |
141 |
movl %eax, %fs |
142 |
movl %eax, %gs |
143 |
|
144 |
/* Read the kernel and modules into RAM */ |
145 |
read_fw_blob(FW_CFG_KERNEL) |
146 |
|
147 |
/* Jump off to the kernel */ |
148 |
read_fw FW_CFG_KERNEL_ENTRY |
149 |
mov %eax, %ecx |
150 |
|
151 |
/* EBX contains a pointer to the bootinfo struct */ |
152 |
read_fw FW_CFG_INITRD_ADDR |
153 |
movl %eax, %ebx |
154 |
|
155 |
/* EAX has to contain the magic */ |
156 |
movl $MULTIBOOT_MAGIC, %eax |
157 |
ljmp2: |
158 |
jmp *%ecx |
159 |
|
160 |
/* Variables */ |
161 |
.align 4, 0 |
162 |
prot_jump: .long prot_mode |
163 |
.short 8 |
164 |
|
165 |
.align 4, 0 |
166 |
gdt: |
167 |
/* 0x00 */ |
168 |
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
169 |
|
170 |
/* 0x08: code segment (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k) */ |
171 |
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00 |
172 |
|
173 |
/* 0x10: data segment (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k) */ |
174 |
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00 |
175 |
|
176 |
/* 0x18: code segment (base=0, limit=0x0ffff, type=16bit code exec/read/conf, DPL=0, 1b) */ |
177 |
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00 |
178 |
|
179 |
/* 0x20: data segment (base=0, limit=0x0ffff, type=16bit data read/write, DPL=0, 1b) */ |
180 |
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00 |
181 |
|
182 |
gdt_desc: |
183 |
.short (5 * 8) - 1 |
184 |
.long gdt |
185 |
|
186 |
BOOT_ROM_END |