]>
Commit | Line | Data |
---|---|---|
57a46d05 AG |
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 <agraf@suse.de> | |
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 | ||
36ecd7c0 PB |
82 | /* Reserve space on the stack for our GDT descriptor. */ |
83 | mov %esp, %ebp | |
84 | sub $16, %esp | |
57a46d05 AG |
85 | |
86 | /* Now create the GDT descriptor */ | |
36ecd7c0 | 87 | movw $((3 * 8) - 1), -16(%bp) |
57a46d05 | 88 | mov %cs, %eax |
d0652aa8 | 89 | movzwl %ax, %eax |
57a46d05 | 90 | shl $4, %eax |
d0652aa8 AK |
91 | addl $gdt, %eax |
92 | movl %eax, -14(%bp) | |
57a46d05 AG |
93 | |
94 | /* And load the GDT */ | |
36ecd7c0 PB |
95 | data32 lgdt -16(%bp) |
96 | mov %ebp, %esp | |
57a46d05 AG |
97 | |
98 | /* Get us to protected mode now */ | |
99 | mov $1, %eax | |
100 | mov %eax, %cr0 | |
101 | ||
dc61b0dc | 102 | /* So we can set ES to a 32-bit segment */ |
57a46d05 | 103 | mov $0x10, %eax |
dc61b0dc | 104 | mov %eax, %es |
57a46d05 | 105 | |
dc61b0dc | 106 | /* We're now running in 16-bit CS, but 32-bit ES! */ |
57a46d05 AG |
107 | |
108 | /* Load kernel and initrd */ | |
590bf491 AG |
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) | |
57a46d05 AG |
113 | |
114 | /* And now jump into Linux! */ | |
115 | mov $0, %eax | |
116 | mov %eax, %cr0 | |
117 | ||
dc61b0dc | 118 | /* ES = CS */ |
57a46d05 | 119 | mov %cs, %ax |
dc61b0dc | 120 | mov %ax, %es |
57a46d05 AG |
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 |