|
|
1.1 root 1: /*
2: * Linux Boot 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: * Based on code in hw/pc.c.
21: */
22:
23: #include "optionrom.h"
24:
25: BOOT_ROM_START
26:
27: run_linuxboot:
28:
29: cli
30: cld
31:
32: jmp copy_kernel
33: boot_kernel:
34:
35: read_fw FW_CFG_SETUP_ADDR
36:
37: mov %eax, %ebx
38: shr $4, %ebx
39:
40: /* All segments contain real_addr */
41: mov %bx, %ds
42: mov %bx, %es
43: mov %bx, %fs
44: mov %bx, %gs
45: mov %bx, %ss
46:
47: /* CX = CS we want to jump to */
48: add $0x20, %bx
49: mov %bx, %cx
50:
51: /* SP = cmdline_addr-real_addr-16 */
52: read_fw FW_CFG_CMDLINE_ADDR
53: mov %eax, %ebx
54: read_fw FW_CFG_SETUP_ADDR
55: sub %eax, %ebx
56: sub $16, %ebx
57: mov %ebx, %esp
58:
59: /* Build indirect lret descriptor */
60: pushw %cx /* CS */
61: xor %ax, %ax
62: pushw %ax /* IP = 0 */
63:
64: /* Clear registers */
65: xor %eax, %eax
66: xor %ebx, %ebx
67: xor %ecx, %ecx
68: xor %edx, %edx
69: xor %edi, %edi
70: xor %ebp, %ebp
71:
72: /* Jump to Linux */
73: lret
74:
75:
76: copy_kernel:
77:
78: /* We need to load the kernel into memory we can't access in 16 bit
79: mode, so let's get into 32 bit mode, write the kernel and jump
80: back again. */
81:
82: /* Reserve space on the stack for our GDT descriptor. */
83: mov %esp, %ebp
84: sub $16, %esp
85:
86: /* Now create the GDT descriptor */
87: movw $((3 * 8) - 1), -16(%bp)
88: mov %cs, %eax
89: shl $4, %eax
90: addl $gdt, %ebx
91: movl %ebx, -14(%bp)
92:
93: /* And load the GDT */
94: data32 lgdt -16(%bp)
95: mov %ebp, %esp
96:
97: /* Get us to protected mode now */
98: mov $1, %eax
99: mov %eax, %cr0
100:
101: /* So we can set ES to a 32-bit segment */
102: mov $0x10, %eax
103: mov %eax, %es
104:
105: /* We're now running in 16-bit CS, but 32-bit ES! */
106:
107: /* Load kernel and initrd */
108: read_fw_blob(FW_CFG_KERNEL)
109: read_fw_blob(FW_CFG_INITRD)
110: read_fw_blob(FW_CFG_CMDLINE)
111: read_fw_blob(FW_CFG_SETUP)
112:
113: /* And now jump into Linux! */
114: mov $0, %eax
115: mov %eax, %cr0
116:
117: /* ES = CS */
118: mov %cs, %ax
119: mov %ax, %es
120:
121: jmp boot_kernel
122:
123: /* Variables */
124:
125: .align 4, 0
126: gdt:
127: /* 0x00 */
128: .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
129:
130: /* 0x08: code segment (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k) */
131: .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00
132:
133: /* 0x10: data segment (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k) */
134: .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00
135:
136: BOOT_ROM_END
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.