summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/arch/i386/prefix/lkrnprefix.S
blob: 64135e14b9e129ca07efbde8001eda01441f3aa3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

#define BZI_LOAD_HIGH_ADDR 0x100000

	.text
	.arch i386
	.code16
	.section ".prefix", "ax", @progbits
	.globl	_lkrn_start
_lkrn_start:

/*****************************************************************************
 *
 * Kernel header
 *
 * We place our prefix (i.e. our .prefix and .text16.early sections)
 * within the bzImage real-mode portion which gets loaded at
 * 1000:0000, and our payload (i.e. everything else) within the
 * bzImage protected-mode portion which gets loaded at 0x100000
 * upwards.
 *
 */

	.org	0x1f1
setup_sects:
	.byte	-1 /* Allow for initial "boot sector" */
	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
	.ascii	"ADHL"
	.long	setup_sects
	.long	512
	.long	0
	.previous
root_flags:
	.word	0
syssize:
	.long	0
	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
	.ascii	"ADPL"
	.long	syssize
	.long	16
	.long	0
	.previous
ram_size:
	.word	0
vid_mode:
	.word	0
root_dev:
	.word	0
boot_flag:
	.word	0xaa55
jump:
	/* Manually specify a two-byte jmp instruction here rather
	 * than leaving it up to the assembler.
	 */
	.byte	0xeb, ( setup - header )
header:
	.byte	'H', 'd', 'r', 'S'
version:
	.word	0x0207 /* 2.07 */
realmode_swtch:
	.long	0
start_sys:
	.word	0
kernel_version:
	.word	version_string - 0x200
type_of_loader:
	.byte	0
loadflags:
	.byte	0x01 /* LOADED_HIGH */
setup_move_size:
	.word	0
code32_start:
	.long	0
ramdisk_image:
	.long	0
ramdisk_size:
	.long	0
bootsect_kludge:
	.long	0
heap_end_ptr:
	.word	0
ext_loader_ver:
	.byte	0
ext_loader_type:
	.byte	0
cmd_line_ptr:
	.long	0
initrd_addr_max:
	.long	0xffffffff
kernel_alignment:
	.long	0
relocatable_kernel:
	.byte	0
min_alignment:
	.byte	0
xloadflags:
	.word	0
cmdline_size:
	.long	0x7ff
hardware_subarch:
	.long	0
hardware_subarch_data:
	.byte	0, 0, 0, 0, 0, 0, 0, 0

version_string:
	.asciz	VERSION

/*****************************************************************************
 *
 * Setup code
 *
 */

setup:
	/* Fix up code segment */
	pushw	%ds
	pushw	$1f
	lret
1:
	/* Set up stack just below 0x7c00 and clear direction flag */
	xorw	%ax, %ax
	movw	%ax, %ss
	movw	$0x7c00, %sp
	cld

	/* Retrieve command-line pointer */
	movl	cmd_line_ptr, %edx
	testl	%edx, %edx
	jz	no_cmd_line

	/* Set up %es:%di to point to command line */
	movl	%edx, %edi
	andl	$0xf, %edi
	rorl	$4, %edx
	movw	%dx, %es

	/* Find length of command line */
	pushw	%di
	movw	$0xffff, %cx
	repnz scasb
	notw	%cx
	popw	%si

	/* Make space for command line on stack */
	movw	%sp, %di
	subw	%cx, %di
	andw	$~0xf, %di
	movw	%di, %sp

	/* Copy command line to stack */
	pushw	%ds
	pushw	%es
	popw	%ds
	pushw	%ss
	popw	%es
	rep movsb
	popw	%ds

	/* Store new command-line pointer */
	movzwl	%sp, %edx
no_cmd_line:

	/* Calculate maximum relocation address */
	movl	ramdisk_image, %ebp
	testl	%ebp, %ebp
	jnz	1f
	orl	$0xffffffff, %ebp /* Allow arbitrary relocation if no initrd */
1:
	/* Install iPXE */
	call	alloc_basemem
	xorl	%esi, %esi
	xorl	%edi, %edi
	call	install_prealloc

	/* Set up real-mode stack */
	movw	%bx, %ss
	movw	$_estack16, %sp

	/* Jump to .text16 segment */
	pushw	%ax
	pushw	$1f
	lret
	.section ".text16", "awx", @progbits
1:
	/* Retrieve initrd pointer and size */
	movl	ramdisk_image, %ebp
	movl	ramdisk_size, %ecx

	/* Set up %ds for access to .data16 */
	movw	%bx, %ds

	/* Store command-line pointer */
	movl	%edx, cmdline_phys

	/* Store initrd pointer and size */
	movl	%ebp, initrd_phys
	movl	%ecx, initrd_len

	/* Run iPXE */
	pushl	$main
	pushw	%cs
	call	prot_call
	popl	%ecx /* discard */

	/* Uninstall iPXE */
	call	uninstall

	/* Boot next device */
	int $0x18

/*****************************************************************************
 *
 * Open payload (called by libprefix)
 *
 * Parameters:
 *   %ds:0000 : Prefix
 *   %esi : Buffer for copy of image source (or zero if no buffer available)
 *   %ecx : Expected offset within buffer of first payload block
 * Returns:
 *   %esi : Valid image source address (buffered or unbuffered)
 *   %ecx : Actual offset within buffer of first payload block
 *   CF set on error
 */

	.section ".text16.early", "awx", @progbits
	.globl	open_payload
open_payload:

	/* Our payload will always end up at BZI_LOAD_HIGH_ADDR */
	movl	$BZI_LOAD_HIGH_ADDR, %esi
	xorl	%ecx, %ecx
	lret

	/* Payload must be aligned to a whole number of setup sectors */
	.globl	_payload_align
	.equ	_payload_align, 512