summaryrefslogtreecommitdiffstats
path: root/grub-core/boot/i386/pc/lnxboot.S
blob: 2dda0e06b4391f5f35d293683f047cfdc6c59665 (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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/* -*-Asm-*- */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2007,2008,2009  Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <config.h>
#include <grub/symbol.h>
#include <grub/machine/boot.h>
#include <grub/machine/kernel.h>
#include <multiboot.h>

        .file   "lnxboot.S"

#define CODE_ADDR	0x6000
#define CODE_SECTORS	1
#define DATA_ADDR	((GRUB_BOOT_MACHINE_KERNEL_ADDR) + 0x200)

#define BLCK_LENG	0x4000

	.text

        .code16

        .globl  start, _start

data_start:
	xorl	%ebp, %ebp
	jmp	LOCAL(linux_next)

	.org 0x1F1

setup_sects:
	.byte	CODE_SECTORS
root_flags:
	.word	0
syssize:
	.word	0
swap_dev:
	.word	0
ram_size:
	.word	0
vid_mode:
	.word	0
root_dev:
	.word	0
boot_flag:
	.word	0xAA55

start:
_start:

	jmp LOCAL(linux_init)

	.ascii	"HdrS"			/* Header signature.  */
	.word	0x0203			/* Header version number.  */

realmode_swtch:
	.word	0, 0			/* default_switch, SETUPSEG.  */
start_sys_seg:
	.word	0x1000			/* Obsolete.  */
version_ptr:
	.word	0			/* Version string ptr.  */
type_of_loader:
	.byte	0			/* Filled in by boot loader.  */
loadflags:
	.byte	1			/* Please load high.  */
setup_move_size:
	.word	0			/* Unused.  */
code32_start:
	.long	0x100000		/* 32-bit start address.  */
ramdisk_image:
	.long	0			/* Loaded ramdisk image address.  */
ramdisk_size:
	.long	0			/* Size of loaded ramdisk.  */
bootsect_kludge:
	.word	0, 0
heap_end_ptr:
	.word	0
pad1:
	.word	0
cmd_line_ptr:
	.long	0			/* Command line.  */
ramdisk_max:
	.long	0xffffffff		/* Highest allowed ramdisk address.  */

gdt:
	.long	0, 0, 0, 0		/* Must be zero.  */
	.word	0xffff			/* 64 K segment size.  */
gdt_src1:
	.byte	0, 0 ,0			/* Low 24 bits of source address.  */
	.byte	0x93			/* Access rights.  */
	.byte	0			/* Extended access rights.  */
gdt_src2:
	.byte	0			/* High 8 bits of source address.  */
	.word	0xffff			/* 64 K segment size.  */
gdt_dst1:
	.byte	0, 0, 0			/* Low 24 bits of target address.  */
	.byte	0x93			/* Access rights.  */
	.byte	0			/* Extended access rights.  */
gdt_dst2:
	.byte	0			/* High 8 bits of source address.  */
	.long	0, 0, 0, 0		/* More space for the BIOS.  */

reg_edx:
	.byte	0x80, 0, 0xFF, 0xFF

data_leng:
	.long	0

LOCAL(linux_init):
	movw	%cs:(reg_edx - start), %dx
	movl	%cs:(code32_start - start), %ebp

LOCAL(linux_next):

	call	LOCAL(normalize)

LOCAL(normalize):
	popw	%bx
	subw	$(LOCAL(normalize) - start), %bx
	shrw	$4, %bx
	movw	%cs, %ax
	addw	%bx, %ax
	pushw	%ax
	pushw	$(real_code - start)
	lret				/* Jump to real_code.  */

real_code:
	subw	$0x20, %ax
	movw	%ax, %ds
	movw	(setup_sects - data_start), %cx
	shlw	$7, %cx

	/* Setup stack.  */

	xorw	%si, %si
	movw	%si, %ss
	movw	$(CODE_ADDR), %sp

	/* Move itself to 0:CODE_ADDR.  */

	cld
	movw	%cs, %ax
	movw	%ax, %ds
	movw	$(CODE_ADDR >> 4), %ax
	movw	%ax, %es
	movw	%si, %di

	rep
	movsl
	ljmp	$(CODE_ADDR >> 4), $(real_code_2  - start)

real_code_2:

	xchgl	%ebp, %esi
	orl	%esi, %esi
	jnz	1f
	movw	%ds, %si
	shll	$4, %esi
	addl	%ebp, %esi
1:

	pushw	%es
	popw	%ds

	movl	$0x1000, %ecx
	addl	$0x200, %esi
	movl	$DATA_ADDR, %edi

	call	LOCAL(move_memory)

	/* Check for multiboot signature.  */
	movl	$DATA_ADDR, %edi
3:
	movl	%ss:(%edi), %eax
	cmpl	$MULTIBOOT_HEADER_MAGIC, %eax
	jz	1f
	addl	$4, %edi
	cmpl	$(DATA_ADDR + 0x1000), %edi
	jne     3b

	movl	(ramdisk_image - start), %esi
	movl	(ramdisk_size - start), %ecx
	movl	$(DATA_ADDR - 0x200), %edi
	jmp	2f

1:

	movl	$(DATA_ADDR + 0x1000), %edi
	movl	%ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx
	addl	$GRUB_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE, %ecx

2:
	call	LOCAL(move_memory)

	movb	%dh, %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 2)
	movb	(reg_edx + 2 - start), %dh
	movb	%dh, %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 1)

	movb	$0xFF, %dh

	ljmp	$(DATA_ADDR >> 4), $0

/*
 * Parameters:
 *   esi: source address
 *   edi: target address
 *   ecx: number of bytes
 */

LOCAL(move_memory):
	incl	%ecx
	andb	$0xFE, %cl
	pushw	%dx
1:
	pushl	%esi
	pushl	%edi
	pushl	%ecx
	cmpl	$BLCK_LENG, %ecx
	jbe	2f
	movl	$BLCK_LENG, %ecx
2:
	pushl	%ecx

	movl	%esi, %eax
	movw	%si, (gdt_src1 - start)
	shrl	$16, %eax
	movb	%al, (gdt_src1 + 2 - start)
	movb	%ah, (gdt_src2 - start)

	movl	%edi, %eax
	movw	%di, (gdt_dst1 - start)
	shrl	$16, %eax
	movb	%al, (gdt_dst1 + 2 - start)
	movb	%ah, (gdt_dst2 - start)

	movw	$(gdt - start), %si
	movb	$0x87, %ah
	shrw	$1, %cx

	int	$0x15

	popl	%eax
	popl	%ecx
	popl	%edi
	popl	%esi

	jnc	2f
	movw	$(err_int15_msg - start), %si
	jmp	LOCAL(fail)

2:

	addl	%eax, %esi
	addl	%eax, %edi
	subl	%eax, %ecx
	jnz	1b


	popw	%dx
	ret

/*
 * Parameters:
 *   si: message
 */

LOCAL(fail):
	movb	$0x0e, %ah
	xorw	%bx, %bx
1:
	lodsb	(%si), %al
	int	$0x10
	cmpb	$0, %al
	jne	1b
1:	jmp	1b

err_int15_msg:
	.ascii	"move memory fails\0"

	.org (CODE_SECTORS * 512 + 512)