|
|
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
1.1.1.2 root 89: movzwl %ax, %eax
1.1 root 90: shl $4, %eax
1.1.1.2 root 91: addl $gdt, %eax
92: movl %eax, -14(%bp)
1.1 root 93:
94: /* And load the GDT */
95: data32 lgdt -16(%bp)
96: mov %ebp, %esp
97:
98: /* Get us to protected mode now */
99: mov $1, %eax
100: mov %eax, %cr0
101:
102: /* So we can set ES to a 32-bit segment */
103: mov $0x10, %eax
104: mov %eax, %es
105:
106: /* We're now running in 16-bit CS, but 32-bit ES! */
107:
108: /* Load kernel and initrd */
1.1.1.3 ! root 109: read_fw_blob_addr32(FW_CFG_KERNEL)
! 110: read_fw_blob_addr32(FW_CFG_INITRD)
! 111: read_fw_blob_addr32(FW_CFG_CMDLINE)
! 112: read_fw_blob_addr32(FW_CFG_SETUP)
1.1 root 113:
114: /* And now jump into Linux! */
115: mov $0, %eax
116: mov %eax, %cr0
117:
118: /* ES = CS */
119: mov %cs, %ax
120: mov %ax, %es
121:
122: jmp boot_kernel
123:
124: /* Variables */
125:
126: .align 4, 0
127: gdt:
128: /* 0x00 */
129: .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
130:
131: /* 0x08: code segment (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k) */
132: .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00
133:
134: /* 0x10: data segment (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k) */
135: .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00
136:
137: BOOT_ROM_END
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.