|
|
1.1 root 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 <[email protected]>
19: */
20:
21: #define NO_QEMU_PROTOS
22: #include "../../hw/fw_cfg.h"
23:
24: #define BIOS_CFG_IOPORT_CFG 0x510
25: #define BIOS_CFG_IOPORT_DATA 0x511
26:
27: #define MULTIBOOT_MAGIC 0x2badb002
28:
29: /* Read a variable from the fw_cfg device.
30: Clobbers: %edx
31: Out: %eax */
32: .macro read_fw VAR
33: mov $\VAR, %ax
34: mov $BIOS_CFG_IOPORT_CFG, %dx
35: outw %ax, (%dx)
36: mov $BIOS_CFG_IOPORT_DATA, %dx
37: inb (%dx), %al
38: shl $8, %eax
39: inb (%dx), %al
40: shl $8, %eax
41: inb (%dx), %al
42: shl $8, %eax
43: inb (%dx), %al
44: bswap %eax
45: .endm
46:
47: .code16
48: .text
49: .global _start
50: _start:
51: .short 0xaa55
52: .byte 1 /* (_end - _start) / 512 */
53: push %eax
54: push %ds
55:
56: /* setup ds so we can access the IVT */
57: xor %ax, %ax
58: mov %ax, %ds
59:
60: /* save old int 19 */
61: mov (0x19*4), %eax
62: mov %eax, %cs:old_int19
63:
64: /* install our int 19 handler */
65: movw $int19_handler, (0x19*4)
66: mov %cs, (0x19*4+2)
67:
68: pop %ds
69: pop %eax
70: lret
71:
72: int19_handler:
73: /* DS = CS */
74: movw %cs, %ax
75: movw %ax, %ds
76:
77: /* fall through */
78:
79: run_multiboot:
80:
81: cli
82: cld
83:
84: mov %cs, %eax
85: shl $0x4, %eax
86:
87: /* fix the gdt descriptor to be PC relative */
88: mov (gdt_desc+2), %ebx
89: add %eax, %ebx
90: mov %ebx, (gdt_desc+2)
91:
92: /* fix the prot mode indirect jump to be PC relative */
93: mov (prot_jump), %ebx
94: add %eax, %ebx
95: mov %ebx, (prot_jump)
96:
97: /* FS = bootinfo_struct */
98: read_fw FW_CFG_INITRD_ADDR
99: shr $4, %eax
100: mov %ax, %fs
101:
102: /* ES = mmap_addr */
103: read_fw FW_CFG_INITRD_SIZE
104: shr $4, %eax
105: mov %ax, %es
106:
107: /* Initialize multiboot mmap structs using int 0x15(e820) */
108: xor %ebx, %ebx
109: /* mmap start after first size */
110: movl $4, %edi
111:
112: mmap_loop:
113: /* entry size (mmap struct) & max buffer size (int15) */
114: movl $20, %ecx
115: /* store entry size */
116: movl %ecx, %es:-4(%edi)
117: /* e820 */
118: movl $0x0000e820, %eax
119: /* 'SMAP' magic */
120: movl $0x534d4150, %edx
121: int $0x15
122:
123: mmap_check_entry:
124: /* last entry? then we're done */
125: jb mmap_done
126: and %bx, %bx
127: jz mmap_done
128: /* valid entry, so let's loop on */
129:
130: mmap_store_entry:
131: /* %ax = entry_number * 24 */
132: mov $24, %ax
133: mul %bx
134: mov %ax, %di
135: movw %di, %fs:0x2c
136: /* %di = 4 + (entry_number * 24) */
137: add $4, %di
138: jmp mmap_loop
139:
140: mmap_done:
141: real_to_prot:
142: /* Load the GDT before going into protected mode */
143: lgdt:
144: data32 lgdt %cs:gdt_desc
145:
146: /* get us to protected mode now */
147: movl $1, %eax
148: movl %eax, %cr0
149:
150: /* the LJMP sets CS for us and gets us to 32-bit */
151: ljmp:
152: data32 ljmp *%cs:prot_jump
153:
154: prot_mode:
155: .code32
156:
157: /* initialize all other segments */
158: movl $0x10, %eax
159: movl %eax, %ss
160: movl %eax, %ds
161: movl %eax, %es
162: movl %eax, %fs
163: movl %eax, %gs
164:
165: /* Jump off to the kernel */
166: read_fw FW_CFG_KERNEL_ADDR
167: mov %eax, %ecx
168:
169: /* EBX contains a pointer to the bootinfo struct */
170: read_fw FW_CFG_INITRD_ADDR
171: movl %eax, %ebx
172:
173: /* EAX has to contain the magic */
174: movl $MULTIBOOT_MAGIC, %eax
175: ljmp2:
176: jmp *%ecx
177:
178: /* Variables */
179: .align 4, 0
180: old_int19: .long 0
181:
182: prot_jump: .long prot_mode
183: .short 8
184:
185: .align 4, 0
186: gdt:
187: /* 0x00 */
188: .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
189:
190: /* 0x08: code segment (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k) */
191: .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00
192:
193: /* 0x10: data segment (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k) */
194: .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00
195:
196: /* 0x18: code segment (base=0, limit=0x0ffff, type=16bit code exec/read/conf, DPL=0, 1b) */
197: .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00
198:
199: /* 0x20: data segment (base=0, limit=0x0ffff, type=16bit data read/write, DPL=0, 1b) */
200: .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00
201:
202: gdt_desc:
203: .short (5 * 8) - 1
204: .long gdt
205:
206: .align 512, 0
207: _end:
208:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.