Statistics
| Branch: | Revision:

root / pc-bios / optionrom / linuxboot.S @ 590bf491

History | View | Annotate | Download (2.9 kB)

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

    
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
	movzwl		%ax, %eax
90
	shl		$4, %eax
91
	addl		$gdt, %eax
92
	movl		%eax, -14(%bp)
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 */
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)
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