qemu_ram_free: Implement it
[qemu/kraxel.git] / pc-bios / optionrom / linuxboot.S
blobc10936344dd887106cd28e24357cd9055d43a759
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  */
23 #include "optionrom.h"
25 BOOT_ROM_START
27 run_linuxboot:
29         cli
30         cld
32         jmp             copy_kernel
33 boot_kernel:
35         read_fw         FW_CFG_SETUP_ADDR
37         mov             %eax, %ebx
38         shr             $4, %ebx
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
47         /* CX = CS we want to jump to */
48         add             $0x20, %bx
49         mov             %bx, %cx
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
59         /* Build indirect lret descriptor */
60         pushw           %cx             /* CS */
61         xor             %ax, %ax
62         pushw           %ax             /* IP = 0 */
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
72         /* Jump to Linux */
73         lret
76 copy_kernel:
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. */
82         /* Reserve space on the stack for our GDT descriptor. */
83         mov             %esp, %ebp
84         sub             $16, %esp
86         /* Now create the GDT descriptor */
87         movw            $((3 * 8) - 1), -16(%bp)
88         mov             %cs, %eax
89         movzwl          %ax, %eax
90         shl             $4, %eax
91         addl            $gdt, %eax
92         movl            %eax, -14(%bp)
94         /* And load the GDT */
95         data32 lgdt     -16(%bp)
96         mov             %ebp, %esp
98         /* Get us to protected mode now */
99         mov             $1, %eax
100         mov             %eax, %cr0
102         /* So we can set ES to a 32-bit segment */
103         mov             $0x10, %eax
104         mov             %eax, %es
106         /* We're now running in 16-bit CS, but 32-bit ES! */
108         /* Load kernel and initrd */
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)
114         /* And now jump into Linux! */
115         mov             $0, %eax
116         mov             %eax, %cr0
118         /* ES = CS */
119         mov             %cs, %ax
120         mov             %ax, %es
122         jmp             boot_kernel
124 /* Variables */
126 .align 4, 0
127 gdt:
128         /* 0x00 */
129 .byte   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
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
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
137 BOOT_ROM_END