Statistics
| Branch: | Revision:

root / pc-bios / optionrom / linuxboot.S @ 75b9f690

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
#define BOOT_ROM_PRODUCT "Linux loader"
26

    
27
BOOT_ROM_START
28

    
29
run_linuxboot:
30

    
31
	cli
32
	cld
33

    
34
	jmp		copy_kernel
35
boot_kernel:
36

    
37
	read_fw		FW_CFG_SETUP_ADDR
38

    
39
	mov		%eax, %ebx
40
	shr		$4, %ebx
41

    
42
	/* All segments contain real_addr */
43
	mov		%bx, %ds
44
	mov		%bx, %es
45
	mov		%bx, %fs
46
	mov		%bx, %gs
47
	mov		%bx, %ss
48

    
49
	/* CX = CS we want to jump to */
50
	add		$0x20, %bx
51
	mov		%bx, %cx
52

    
53
	/* SP = cmdline_addr-real_addr-16 */
54
	read_fw		FW_CFG_CMDLINE_ADDR
55
	mov		%eax, %ebx
56
	read_fw		FW_CFG_SETUP_ADDR
57
	sub		%eax, %ebx
58
	sub		$16, %ebx
59
	mov		%ebx, %esp
60

    
61
	/* Build indirect lret descriptor */
62
	pushw		%cx		/* CS */
63
	xor		%ax, %ax
64
	pushw		%ax		/* IP = 0 */
65

    
66
	/* Clear registers */
67
	xor		%eax, %eax
68
	xor		%ebx, %ebx
69
	xor		%ecx, %ecx
70
	xor		%edx, %edx
71
	xor		%edi, %edi
72
	xor		%ebp, %ebp
73

    
74
	/* Jump to Linux */
75
	lret
76

    
77

    
78
copy_kernel:
79

    
80
	/* We need to load the kernel into memory we can't access in 16 bit
81
	   mode, so let's get into 32 bit mode, write the kernel and jump
82
	   back again. */
83

    
84
	/* Reserve space on the stack for our GDT descriptor. */
85
	mov		%esp, %ebp
86
	sub		$16, %esp
87

    
88
	/* Now create the GDT descriptor */
89
	movw		$((3 * 8) - 1), -16(%bp)
90
	mov		%cs, %eax
91
	movzwl		%ax, %eax
92
	shl		$4, %eax
93
	addl		$gdt, %eax
94
	movl		%eax, -14(%bp)
95

    
96
	/* And load the GDT */
97
	data32 lgdt	-16(%bp)
98
	mov		%ebp, %esp
99

    
100
	/* Get us to protected mode now */
101
	mov		$1, %eax
102
	mov		%eax, %cr0
103

    
104
	/* So we can set ES to a 32-bit segment */
105
	mov		$0x10, %eax
106
	mov		%eax, %es
107

    
108
	/* We're now running in 16-bit CS, but 32-bit ES! */
109

    
110
	/* Load kernel and initrd */
111
	read_fw_blob_addr32(FW_CFG_KERNEL)
112
	read_fw_blob_addr32(FW_CFG_INITRD)
113
	read_fw_blob_addr32(FW_CFG_CMDLINE)
114
	read_fw_blob_addr32(FW_CFG_SETUP)
115

    
116
	/* And now jump into Linux! */
117
	mov		$0, %eax
118
	mov		%eax, %cr0
119

    
120
	/* ES = CS */
121
	mov		%cs, %ax
122
	mov		%ax, %es
123

    
124
	jmp		boot_kernel
125

    
126
/* Variables */
127

    
128
.align 4, 0
129
gdt:
130
	/* 0x00 */
131
.byte	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
132

    
133
	/* 0x08: code segment (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k) */
134
.byte	0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00
135

    
136
	/* 0x10: data segment (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k) */
137
.byte	0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00
138

    
139
BOOT_ROM_END