Browse Source

Merge branch 'pxerom-pmm'

tags/v0.9.4
Michael Brown 16 years ago
parent
commit
08b19abf94

+ 265
- 136
src/arch/i386/prefix/libprefix.S View File

17
  *
17
  *
18
  */
18
  */
19
 
19
 
20
+	.arch i386
21
+	.section ".prefix.lib", "awx", @progbits
22
+	.section ".data16", "aw", @progbits
23
+
20
 /**
24
 /**
21
  * High memory temporary load address
25
  * High memory temporary load address
22
  *
26
  *
27
  * We use the start of an even megabyte so that we don't have to worry
31
  * We use the start of an even megabyte so that we don't have to worry
28
  * about the current state of the A20 line.
32
  * about the current state of the A20 line.
29
  *
33
  *
30
- * We use 4MB rather than 2MB because there is at least one commercial
31
- * PXE ROM ("Broadcom UNDI, PXE-2.1 (build 082) v2.0.4") which stores
32
- * data required by the UNDI ROM loader (yes, the ROM loader; that's
33
- * the component which should be impossible to damage short of
34
- * screwing with the MMU) around the 2MB mark.  Sadly, this is not a
35
- * joke.
36
- *
34
+ * We use 4MB rather than 2MB because some PXE stack / PMM BIOS
35
+ * combinations are known to place data required by other UNDI ROMs
36
+ * loader around the 2MB mark.
37
  */
37
  */
38
-#define HIGHMEM_LOADPOINT ( 4 << 20 )
38
+	.globl	HIGHMEM_LOADPOINT
39
+	.equ	HIGHMEM_LOADPOINT, ( 4 << 20 )
39
 
40
 
40
 /* Image compression enabled */
41
 /* Image compression enabled */
41
 #define COMPRESS 1
42
 #define COMPRESS 1
42
 
43
 
43
 #define CR0_PE 1
44
 #define CR0_PE 1
44
 
45
 
45
-	.arch i386
46
-	.section ".prefix.lib", "awx", @progbits
47
-	.section ".data16", "aw", @progbits
46
+/*****************************************************************************
47
+ * Utility function: print character (with LF -> LF,CR translation)
48
+ *
49
+ * Parameters:
50
+ *   %al : character to print
51
+ * Returns:
52
+ *   Nothing
53
+ * Corrupts:
54
+ *   %ax
55
+ *****************************************************************************
56
+ */
57
+	.section ".prefix.lib"
58
+	.code16
59
+	.globl	print_character
60
+print_character:
61
+	/* Preserve registers */
62
+	pushw	%bx
63
+	pushw	%bp
64
+	/* Print character */
65
+	movw	$0x0007, %bx		/* page 0, attribute 7 (normal) */
66
+	movb	$0x0e, %ah		/* write char, tty mode */
67
+	cmpb	$0x0a, %al		/* '\n'? */
68
+	jne	1f
69
+	int	$0x10
70
+	movb	$0x0d, %al
71
+1:	int	$0x10
72
+	/* Restore registers and return */
73
+	popw	%bp
74
+	popw	%bx
75
+	ret
76
+	.size	print_character, . - print_character
77
+
78
+/*****************************************************************************
79
+ * Utility function: print a NUL-terminated string
80
+ *
81
+ * Parameters:
82
+ *   %ds:si : string to print
83
+ * Returns:
84
+ *   %ds:si : character after terminating NUL
85
+ *****************************************************************************
86
+ */
87
+	.section ".prefix.lib"
88
+	.code16
89
+	.globl	print_message
90
+print_message:
91
+	/* Preserve registers */
92
+	pushw	%ax
93
+	/* Print string */
94
+1: 	lodsb
95
+	testb	%al, %al
96
+	je	2f
97
+	call	print_character
98
+	jmp	1b
99
+2:	/* Restore registers and return */
100
+	popw	%ax
101
+	ret
102
+	.size	print_message, . - print_message
103
+
104
+/*****************************************************************************
105
+ * Utility functions: print hex digit/byte/word/dword
106
+ *
107
+ * Parameters:
108
+ *   %al (low nibble) : digit to print
109
+ *   %al : byte to print
110
+ *   %ax : word to print
111
+ *   %eax : dword to print
112
+ * Returns:
113
+ *   Nothing
114
+ *****************************************************************************
115
+ */
116
+	.section ".prefix.lib"
117
+	.code16
118
+	.globl	print_hex_dword
119
+print_hex_dword:
120
+	rorl	$16, %eax
121
+	call	print_hex_word
122
+	rorl	$16, %eax
123
+	/* Fall through */
124
+	.size	print_hex_dword, . - print_hex_dword
125
+	.globl	print_hex_word
126
+print_hex_word:
127
+	xchgb	%al, %ah
128
+	call	print_hex_byte
129
+	xchgb	%al, %ah
130
+	/* Fall through */
131
+	.size	print_hex_word, . - print_hex_word
132
+	.globl	print_hex_byte
133
+print_hex_byte:
134
+	rorb	$4, %al
135
+	call	print_hex_nibble
136
+	rorb	$4, %al
137
+	/* Fall through */
138
+	.size	print_hex_byte, . - print_hex_byte
139
+	.globl	print_hex_nibble
140
+print_hex_nibble:
141
+	/* Preserve registers */
142
+	pushw	%ax
143
+	/* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */
144
+	andb	$0x0f, %al
145
+	cmpb	$10, %al
146
+	sbbb	$0x69, %al
147
+	das
148
+	call	print_character
149
+	/* Restore registers and return */
150
+	popw	%ax
151
+	ret
152
+	.size	print_hex_nibble, . - print_hex_nibble
48
 
153
 
49
 /****************************************************************************
154
 /****************************************************************************
50
  * pm_call (real-mode near call)
155
  * pm_call (real-mode near call)
70
 #ifndef KEEP_IT_REAL
175
 #ifndef KEEP_IT_REAL
71
 
176
 
72
 	/* GDT for protected-mode calls */
177
 	/* GDT for protected-mode calls */
73
-	.section ".data16"
178
+	.section ".prefix.lib"
74
 	.align 16
179
 	.align 16
180
+pm_call_vars:
75
 gdt:
181
 gdt:
76
 gdt_limit:		.word gdt_length - 1
182
 gdt_limit:		.word gdt_length - 1
77
 gdt_base:		.long 0
183
 gdt_base:		.long 0
78
 			.word 0 /* padding */
184
 			.word 0 /* padding */
79
-pm_cs:		/* 16-bit protected-mode code segment */
185
+pm_cs:		/* 16-bit protected-mode code segment */	
80
 	.equ    PM_CS, pm_cs - gdt
186
 	.equ    PM_CS, pm_cs - gdt
81
 	.word   0xffff, 0
187
 	.word   0xffff, 0
82
 	.byte   0, 0x9b, 0x00, 0
188
 	.byte   0, 0x9b, 0x00, 0
92
 	.equ	gdt_length, . - gdt
198
 	.equ	gdt_length, . - gdt
93
 	.size	gdt, . - gdt
199
 	.size	gdt, . - gdt
94
 
200
 
95
-	.section ".data16"
201
+	.section ".prefix.lib"
96
 	.align 16
202
 	.align 16
97
 pm_saved_gdt:	
203
 pm_saved_gdt:	
98
 	.long	0, 0
204
 	.long	0, 0
99
 	.size	pm_saved_gdt, . - pm_saved_gdt
205
 	.size	pm_saved_gdt, . - pm_saved_gdt
100
 
206
 
207
+	.equ	pm_call_vars_size, . - pm_call_vars
208
+#define PM_CALL_VAR(x) ( -pm_call_vars_size + ( (x) - pm_call_vars ) )
209
+
101
 	.section ".prefix.lib"
210
 	.section ".prefix.lib"
102
 	.code16
211
 	.code16
103
 pm_call:
212
 pm_call:
104
-	/* Preserve registers, flags, GDT, and RM return point */
213
+	/* Preserve registers, flags, and RM return point */
214
+	pushw	%bp
215
+	movw	%sp, %bp
216
+	subw	$pm_call_vars_size, %sp
217
+	andw	$0xfff0, %sp
105
 	pushfl
218
 	pushfl
106
-	sgdt	pm_saved_gdt
107
 	pushw	%gs
219
 	pushw	%gs
108
 	pushw	%fs
220
 	pushw	%fs
109
 	pushw	%es
221
 	pushw	%es
112
 	pushw	%cs
224
 	pushw	%cs
113
 	pushw	$99f
225
 	pushw	$99f
114
 
226
 
227
+	/* Set up local variable block, and preserve GDT */
228
+	pushw	%cx
229
+	pushw	%si
230
+	pushw	%di
231
+	pushw	%ss
232
+	popw	%es
233
+	movw	$pm_call_vars, %si
234
+	leaw	PM_CALL_VAR(pm_call_vars)(%bp), %di
235
+	movw	$pm_call_vars_size, %cx
236
+	cs rep movsb
237
+	popw	%di
238
+	popw	%si
239
+	popw	%cx
240
+	sgdt	PM_CALL_VAR(pm_saved_gdt)(%bp)
241
+
115
 	/* Set up GDT bases */
242
 	/* Set up GDT bases */
116
 	pushl	%eax
243
 	pushl	%eax
117
-	pushw	%bx
244
+	pushl	%edi
118
 	xorl	%eax, %eax
245
 	xorl	%eax, %eax
119
-	movw	%ds, %ax
246
+	movw	%ss, %ax
120
 	shll	$4, %eax
247
 	shll	$4, %eax
121
-	addl	$gdt, %eax
122
-	movl	%eax, gdt_base
248
+	movzwl	%bp, %edi
249
+	leal	PM_CALL_VAR(gdt)(%eax, %edi), %eax
250
+	movl	%eax, PM_CALL_VAR(gdt_base)(%bp)
123
 	movw	%cs, %ax
251
 	movw	%cs, %ax
124
-	movw	$pm_cs, %bx
252
+	movw	$PM_CALL_VAR(pm_cs), %di
125
 	call	set_seg_base
253
 	call	set_seg_base
126
 	movw	%ss, %ax
254
 	movw	%ss, %ax
127
-	movw	$pm_ss, %bx
255
+	movw	$PM_CALL_VAR(pm_ss), %di
128
 	call	set_seg_base
256
 	call	set_seg_base
129
-	popw	%bx
257
+	popl	%edi
130
 	popl	%eax
258
 	popl	%eax
131
 
259
 
132
 	/* Switch CPU to protected mode and load up segment registers */
260
 	/* Switch CPU to protected mode and load up segment registers */
133
 	pushl	%eax
261
 	pushl	%eax
134
 	cli
262
 	cli
135
-	lgdt	gdt
263
+	lgdt	PM_CALL_VAR(gdt)(%bp)
136
 	movl	%cr0, %eax
264
 	movl	%cr0, %eax
137
 	orb	$CR0_PE, %al
265
 	orb	$CR0_PE, %al
138
 	movl	%eax, %cr0
266
 	movl	%eax, %cr0
168
 	popw	%es
296
 	popw	%es
169
 	popw	%fs
297
 	popw	%fs
170
 	popw	%gs
298
 	popw	%gs
171
-	lgdt	pm_saved_gdt
299
+	lgdt	PM_CALL_VAR(pm_saved_gdt)(%bp)
172
 	popfl
300
 	popfl
173
-
301
+	movw	%bp, %sp
302
+	popw	%bp
174
 	ret
303
 	ret
175
 	.size pm_call, . - pm_call
304
 	.size pm_call, . - pm_call
176
 
305
 
177
 set_seg_base:
306
 set_seg_base:
178
 	rolw	$4, %ax
307
 	rolw	$4, %ax
179
-	movw	%ax, 2(%bx)
180
-	andw	$0xfff0, 2(%bx)
181
-	movb	%al, 4(%bx)
182
-	andb	$0x0f, 4(%bx)
308
+	movw	%ax, 2(%bp,%di)
309
+	andw	$0xfff0, 2(%bp,%di)
310
+	movb	%al, 4(%bp,%di)
311
+	andb	$0x0f, 4(%bp,%di)
183
 	ret
312
 	ret
184
 	.size set_seg_base, . - set_seg_base
313
 	.size set_seg_base, . - set_seg_base
185
 
314
 
196
  *   %ecx : length
325
  *   %ecx : length
197
  * Returns:
326
  * Returns:
198
  *   %ds:esi : next source address
327
  *   %ds:esi : next source address
199
- *   %ds:esi : next destination address
328
+ *   %es:edi : next destination address
200
  * Corrupts:
329
  * Corrupts:
201
  *   None
330
  *   None
202
  ****************************************************************************
331
  ****************************************************************************
211
 	.size copy_bytes, . - copy_bytes
340
 	.size copy_bytes, . - copy_bytes
212
 
341
 
213
 /****************************************************************************
342
 /****************************************************************************
214
- * install_block (real-mode or 16-bit protected-mode near call)
343
+ * install_block (real-mode near call)
215
  *
344
  *
216
  * Install block to specified address
345
  * Install block to specified address
217
  *
346
  *
218
  * Parameters:
347
  * Parameters:
219
- *   %ds:esi : source address (must be a multiple of 16)
220
- *   %es:edi : destination address
348
+ *   %esi : source physical address (must be a multiple of 16)
349
+ *   %edi : destination physical address (must be a multiple of 16)
221
  *   %ecx : length of (decompressed) data
350
  *   %ecx : length of (decompressed) data
222
  *   %edx : total length of block (including any uninitialised data portion)
351
  *   %edx : total length of block (including any uninitialised data portion)
223
  * Returns:
352
  * Returns:
224
- *   %ds:esi : next source address (will be a multiple of 16)
353
+ *   %esi : next source physical address (will be a multiple of 16)
225
  * Corrupts:
354
  * Corrupts:
226
- *   %edi, %ecx, %edx
355
+ *   none
227
  ****************************************************************************
356
  ****************************************************************************
228
  */
357
  */
229
 	.section ".prefix.lib"
358
 	.section ".prefix.lib"
230
 	.code16
359
 	.code16
231
 install_block:
360
 install_block:
361
+	
362
+#ifdef KEEP_IT_REAL
363
+
364
+	/* Preserve registers */
365
+	pushw	%ds
366
+	pushw	%es
367
+	pushl	%ecx
368
+	pushl	%edi
369
+	
370
+	/* Convert %esi and %edi to segment registers */
371
+	shrl	$4, %esi
372
+	movw	%si, %ds
373
+	xorw	%si, %si
374
+	shrl	$4, %edi
375
+	movw	%di, %es
376
+	xorw	%di, %di
377
+
378
+#else /* KEEP_IT_REAL */
379
+
380
+	/* Call self in protected mode */
381
+	pushw	%ax
382
+	movw	$1f, %ax
383
+	call	pm_call
384
+	popw	%ax
385
+	ret
386
+1:
387
+	/* Preserve registers */
388
+	pushl	%ecx
389
+	pushl	%edi
390
+	
391
+#endif /* KEEP_IT_REAL */
392
+
393
+	
232
 #if COMPRESS
394
 #if COMPRESS
233
 	/* Decompress source to destination */
395
 	/* Decompress source to destination */
234
 	call	decompress16
396
 	call	decompress16
249
 	addl	$0xf, %esi
411
 	addl	$0xf, %esi
250
 	andl	$~0xf, %esi
412
 	andl	$~0xf, %esi
251
 
413
 
414
+
415
+#ifdef KEEP_IT_REAL
416
+
417
+	/* Convert %ds:esi back to a physical address */
418
+	movzwl	%ds, %cx
419
+	shll	$4, %ecx
420
+	addl	%ecx, %esi
421
+
422
+	/* Restore registers */
423
+	popl	%edi
424
+	popl	%ecx
425
+	popw	%es
426
+	popw	%ds
427
+
428
+#else /* KEEP_IT_REAL */
429
+
430
+	/* Restore registers */
431
+	popl	%edi
432
+	popl	%ecx
433
+
434
+#endif
435
+
252
 	ret
436
 	ret
253
 	.size install_block, . - install_block
437
 	.size install_block, . - install_block
254
 	
438
 	
270
  */
454
  */
271
 	.section ".prefix.lib"
455
 	.section ".prefix.lib"
272
 	.code16
456
 	.code16
457
+	.globl	alloc_basemem
273
 alloc_basemem:
458
 alloc_basemem:
274
 	/* FBMS => %ax as segment address */
459
 	/* FBMS => %ax as segment address */
275
 	movw	$0x40, %ax
460
 	movw	$0x40, %ax
296
 	.size alloc_basemem, . - alloc_basemem
481
 	.size alloc_basemem, . - alloc_basemem
297
 
482
 
298
 /****************************************************************************
483
 /****************************************************************************
299
- * install_basemem (real-mode near call)
484
+ * install (real-mode near call)
300
  *
485
  *
301
- * Install source block into base memory
486
+ * Install all text and data segments.
302
  *
487
  *
303
  * Parameters:
488
  * Parameters:
304
- *   %esi : source physical address (must be a multiple of 16)
305
- *   %es : destination segment address
306
- *   %cx : length of (decompressed) data
307
- *   %dx : total length of block (including any uninitialised data portion)
489
+ *   none
308
  * Returns:
490
  * Returns:
309
- *   %esi : next source physical address (will be a multiple of 16)
491
+ *   %ax  : .text16 segment address
492
+ *   %bx  : .data16 segment address
310
  * Corrupts:
493
  * Corrupts:
311
- *   %edi, %ecx, %edx
494
+ *   none
312
  ****************************************************************************
495
  ****************************************************************************
313
  */
496
  */
314
 	.section ".prefix.lib"
497
 	.section ".prefix.lib"
315
 	.code16
498
 	.code16
316
-install_basemem:
499
+	.globl install
500
+install:
317
 	/* Preserve registers */
501
 	/* Preserve registers */
318
-	pushw	%ds
319
-
320
-	/* Preserve original %esi */
321
 	pushl	%esi
502
 	pushl	%esi
322
-
323
-	/* Install to specified address */
324
-	shrl	$4, %esi
325
-	movw	%si, %ds
326
-	xorw	%si, %si
327
-	xorl	%edi, %edi
328
-	movzwl	%cx, %ecx
329
-	movzwl	%dx, %edx
330
-	call	install_block
331
-
332
-	/* Fix up %esi for return */
333
-	popl	%ecx
334
-	addl	%ecx, %esi
335
-
336
-	/* Restore registers */
337
-	popw	%ds
503
+	pushl	%edi
504
+	/* Allocate space for .text16 and .data16 */
505
+	call	alloc_basemem
506
+	/* Image source = %cs:0000 */
507
+	xorl	%esi, %esi
508
+	/* Image destination = HIGHMEM_LOADPOINT */
509
+	movl	$HIGHMEM_LOADPOINT, %edi
510
+	/* Install text and data segments */
511
+	call	install_prealloc
512
+	/* Restore registers and return */
513
+	popl	%edi
514
+	popl	%esi
338
 	ret
515
 	ret
339
-	.size install_basemem, . - install_basemem
340
-
341
-/****************************************************************************
342
- * install_highmem (real-mode near call)
343
- *
344
- * Install source block into high memory
345
- *
346
- * Parameters:
347
- *   %esi : source physical address (must be a multiple of 16)
348
- *   %edi : destination physical address
349
- *   %ecx : length of (decompressed) data
350
- *   %edx : total length of block (including any uninitialised data portion)
351
- * Returns:
352
- *   %esi : next source physical address (will be a multiple of 16)
353
- * Corrupts:
354
- *   %edi, %ecx, %edx
355
- ****************************************************************************
356
- */
357
-
358
-#ifndef KEEP_IT_REAL
359
-
360
-	.section ".prefix.lib"
361
-	.code16
362
-install_highmem:
363
-	/* Preserve registers */
364
-	pushw	%ax
365
-
366
-	/* Install to specified address */
367
-	movw	$install_block, %ax
368
-	call	pm_call
516
+	.size install, . - install
369
 
517
 
370
-	/* Restore registers */
371
-	popw	%ax
372
-	ret
373
-	.size install_highmem, . - install_highmem
374
-	
375
-#endif /* KEEP_IT_REAL */
376
-	
377
 /****************************************************************************
518
 /****************************************************************************
378
- * install (real-mode near call)
379
  * install_prealloc (real-mode near call)
519
  * install_prealloc (real-mode near call)
380
  *
520
  *
381
  * Install all text and data segments.
521
  * Install all text and data segments.
382
  *
522
  *
383
  * Parameters:
523
  * Parameters:
384
- *   %ax : .text16 segment address (install_prealloc only)
385
- *   %bx : .data16 segment address (install_prealloc only)
386
- * Returns:
387
- *   %ax : .text16 segment address
388
- *   %bx : .data16 segment address
389
- *   %edi : .text physical address (if applicable)
524
+ *   %ax  : .text16 segment address
525
+ *   %bx  : .data16 segment address
526
+ *   %esi : Image source physical address (or zero for %cs:0000)
527
+ *   %edi : Decompression temporary area physical address
390
  * Corrupts:
528
  * Corrupts:
391
  *   none
529
  *   none
392
  ****************************************************************************
530
  ****************************************************************************
393
  */
531
  */
394
 	.section ".prefix.lib"
532
 	.section ".prefix.lib"
395
 	.code16
533
 	.code16
396
-	.globl install
397
-install:
398
-	/* Allocate space for .text16 and .data16 */
399
-	call	alloc_basemem
400
-	.size install, . - install
401
 	.globl install_prealloc
534
 	.globl install_prealloc
402
 install_prealloc:
535
 install_prealloc:
403
 	/* Save registers */
536
 	/* Save registers */
537
+	pushal
404
 	pushw	%ds
538
 	pushw	%ds
405
 	pushw	%es
539
 	pushw	%es
406
-	pushl	%esi
407
-	pushl	%ecx
408
-	pushl	%edx
409
 
540
 
410
 	/* Sanity: clear the direction flag asap */
541
 	/* Sanity: clear the direction flag asap */
411
 	cld
542
 	cld
412
 
543
 
413
 	/* Calculate physical address of payload (i.e. first source) */
544
 	/* Calculate physical address of payload (i.e. first source) */
414
-	xorl	%esi, %esi
545
+	testl	%esi, %esi
546
+	jnz	1f
415
 	movw	%cs, %si
547
 	movw	%cs, %si
416
 	shll	$4, %esi
548
 	shll	$4, %esi
417
-	addl	$_payload_offset, %esi
418
-
419
-	/* Install .text16 */
420
-	movw	%ax, %es
421
-	movw	$_text16_size, %cx
422
-	movw	%cx, %dx
423
-	call	install_basemem
549
+1:	addl	$_payload_offset, %esi
424
 
550
 
425
-	/* Install .data16 */
426
-	movw	%bx, %es
427
-	movw	$_data16_progbits_size, %cx
428
-	movw	$_data16_size, %dx
429
-	call	install_basemem
551
+	/* Install .text16 and .data16 */
552
+	pushl	%edi
553
+	movzwl	%ax, %edi
554
+	shll	$4, %edi
555
+	movl	$_text16_size, %ecx
556
+	movl	%ecx, %edx
557
+	call	install_block		/* .text16 */
558
+	movzwl	%bx, %edi
559
+	shll	$4, %edi
560
+	movl	$_data16_progbits_size, %ecx
561
+	movl	$_data16_size, %edx
562
+	call	install_block		/* .data16 */
563
+	popl	%edi
430
 
564
 
431
 	/* Set up %ds for access to .data16 */
565
 	/* Set up %ds for access to .data16 */
432
 	movw	%bx, %ds
566
 	movw	%bx, %ds
440
 	 * prior to reading the E820 memory map and relocating
574
 	 * prior to reading the E820 memory map and relocating
441
 	 * properly.
575
 	 * properly.
442
 	 */
576
 	 */
443
-	movl	$HIGHMEM_LOADPOINT, %edi
444
 	movl	$_textdata_progbits_size, %ecx
577
 	movl	$_textdata_progbits_size, %ecx
445
 	movl	$_textdata_size, %edx
578
 	movl	$_textdata_size, %edx
446
-	pushl	%edi
447
-	call	install_highmem
448
-	popl	%edi
579
+	call	install_block
449
 
580
 
450
 	/* Initialise librm at current location */
581
 	/* Initialise librm at current location */
451
 	movw	%ax, (init_librm_vector+2)
582
 	movw	%ax, (init_librm_vector+2)
473
 
604
 
474
 #endif
605
 #endif
475
 	/* Restore registers */
606
 	/* Restore registers */
476
-	popl	%edx
477
-	popl	%ecx
478
-	popl	%esi
479
 	popw	%es
607
 	popw	%es
480
 	popw	%ds
608
 	popw	%ds
609
+	popal
481
 	ret
610
 	ret
482
 	.size install_prealloc, . - install_prealloc
611
 	.size install_prealloc, . - install_prealloc
483
 
612
 

+ 0
- 106
src/arch/i386/prefix/pxeprefix.S View File

320
 finished:
320
 finished:
321
 	jmp	run_etherboot
321
 	jmp	run_etherboot
322
 
322
 
323
-/*****************************************************************************
324
- * Subroutine: print character (with LF -> LF,CR translation)
325
- *
326
- * Parameters:
327
- *   %al : character to print
328
- * Returns:
329
- *   Nothing
330
- *****************************************************************************
331
- */
332
-print_character:
333
-	/* Preserve registers */
334
-	pushw	%ax
335
-	pushw	%bx
336
-	pushw	%bp
337
-	/* Print character */
338
-	movw	$0x0007, %bx		/* page 0, attribute 7 (normal) */
339
-	movb	$0x0e, %ah		/* write char, tty mode */
340
-	cmpb	$0x0a, %al		/* '\n'? */
341
-	jne	1f
342
-	int	$0x10
343
-	movb	$0x0d, %al
344
-1:	int	$0x10
345
-	/* Restore registers and return */
346
-	popw	%bp
347
-	popw	%bx
348
-	popw	%ax
349
-	ret
350
-	
351
-/*****************************************************************************
352
- * Subroutine: print a NUL-terminated string
353
- *
354
- * Parameters:
355
- *   %ds:%si : string to print
356
- * Returns:
357
- *   Nothing
358
- *****************************************************************************
359
- */	
360
-print_message:
361
-	/* Preserve registers */
362
-	pushw	%ax
363
-	pushw	%si
364
-	/* Print string */
365
-1: 	lodsb
366
-	testb	%al, %al
367
-	je	2f
368
-	call	print_character
369
-	jmp	1b
370
-2:	/* Restore registers and return */
371
-	popw	%si
372
-	popw	%ax
373
-	ret
374
-
375
-/*****************************************************************************
376
- * Subroutine: print hex digit
377
- *
378
- * Parameters:
379
- *   %al (low nibble) : digit to print
380
- * Returns:
381
- *   Nothing
382
- *****************************************************************************
383
- */
384
-print_hex_nibble:
385
-	/* Preserve registers */
386
-	pushw	%ax
387
-	/* Print digit (technique by Norbert Juffa <norbert.juffa@amd.com> */
388
-	andb	$0x0f, %al
389
-	cmpb	$10, %al
390
-	sbbb	$0x69, %al
391
-	das
392
-	call	print_character
393
-	/* Restore registers and return */
394
-	popw	%ax
395
-	ret	
396
-
397
-/*****************************************************************************
398
- * Subroutine: print hex byte
399
- *
400
- * Parameters:
401
- *   %al : byte to print
402
- * Returns:
403
- *   Nothing
404
- *****************************************************************************
405
- */
406
-print_hex_byte:
407
-	rorb	$4, %al
408
-	call	print_hex_nibble
409
-	rorb	$4, %al
410
-	call	print_hex_nibble
411
-	ret
412
-
413
-/*****************************************************************************
414
- * Subroutine: print hex word
415
- *
416
- * Parameters:
417
- *   %ax : word to print
418
- * Returns:
419
- *   Nothing
420
- *****************************************************************************
421
- */
422
-print_hex_word:
423
-	xchgb	%al, %ah
424
-	call	print_hex_byte
425
-	xchgb	%al, %ah
426
-	call	print_hex_byte
427
-	ret
428
-
429
 /*****************************************************************************
323
 /*****************************************************************************
430
  * Subroutine: print segment:offset address
324
  * Subroutine: print segment:offset address
431
  *
325
  *

+ 215
- 63
src/arch/i386/prefix/romprefix.S View File

6
  * table so using a noticeable amount of stack space is a no-no.
6
  * table so using a noticeable amount of stack space is a no-no.
7
  */
7
  */
8
 
8
 
9
+#define PNP_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'n' << 16 ) + ( 'P' << 24 ) )
10
+#define PMM_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'M' << 16 ) + ( 'M' << 24 ) )
11
+#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
12
+#define PNP_GET_BBS_VERSION 0x60
13
+
9
 	.text
14
 	.text
10
 	.code16
15
 	.code16
11
 	.arch i386
16
 	.arch i386
15
 romheader:
20
 romheader:
16
 	.word	0xAA55			/* BIOS extension signature */
21
 	.word	0xAA55			/* BIOS extension signature */
17
 romheader_size:	.byte _load_size_sect	/* Size in 512-byte blocks */
22
 romheader_size:	.byte _load_size_sect	/* Size in 512-byte blocks */
18
-	jmp	init_vector		/* Initialisation vector */
23
+	jmp	init			/* Initialisation vector */
24
+checksum:
25
+	.byte	0
19
 	.org	0x16
26
 	.org	0x16
20
 	.word	undiheader
27
 	.word	undiheader
21
 	.org	0x18
28
 	.org	0x18
72
 	.byte	0x54			/* Device indicator */
79
 	.byte	0x54			/* Device indicator */
73
 	.word	0x0000			/* Boot connection vector */
80
 	.word	0x0000			/* Boot connection vector */
74
 	.word	0x0000			/* Disconnect vector */
81
 	.word	0x0000			/* Disconnect vector */
75
-	.word	exec_vector		/* Boot execution vector */
82
+	.word	bev_entry		/* Boot execution vector */
76
 	.word	0x0000			/* Reserved */
83
 	.word	0x0000			/* Reserved */
77
 	.word	0x0000			/* Static resource information vector*/
84
 	.word	0x0000			/* Static resource information vector*/
78
 	.equ pnpheader_len, . - pnpheader
85
 	.equ pnpheader_len, . - pnpheader
98
 	.equ undiheader_len, . - undiheader
105
 	.equ undiheader_len, . - undiheader
99
 	.size undiheader, . - undiheader
106
 	.size undiheader, . - undiheader
100
 
107
 
101
-/* Initialisation vector
108
+/* Initialisation (called once during POST)
102
  *
109
  *
103
  * Determine whether or not this is a PnP system via a signature
110
  * Determine whether or not this is a PnP system via a signature
104
  * check.  If it is PnP, return to the PnP BIOS indicating that we are
111
  * check.  If it is PnP, return to the PnP BIOS indicating that we are
105
  * a boot-capable device; the BIOS will call our boot execution vector
112
  * a boot-capable device; the BIOS will call our boot execution vector
106
  * if it wants to boot us.  If it is not PnP, hook INT 19.
113
  * if it wants to boot us.  If it is not PnP, hook INT 19.
107
  */
114
  */
108
-init_vector:
109
-	pushw	%si
110
-	cmpw	$'$'+'P'*256, %es:0(%di)
111
-	jne	notpnp
112
-	cmpw	$'n'+'P'*256, %es:2(%di)
113
-	jne	notpnp
114
-ispnp:
115
-	movw	$ispnp_message, %si
116
-	jmp	99f
117
-notpnp:
115
+init:
116
+	/* Preserve registers, clear direction flag, set %ds=%cs */
117
+	pushaw
118
 	pushw	%ds
118
 	pushw	%ds
119
-	pushw	$0
120
-	popw	%ds
119
+	pushw	%es
120
+	cld
121
 	pushw	%cs
121
 	pushw	%cs
122
-	pushw	$exec_vector
123
-	popl	( 0x19 * 4 )
124
 	popw	%ds
122
 	popw	%ds
125
-	movw	$notpnp_message, %si
126
-99:
123
+	/* Print message as early as possible */
124
+	movw	$init_message, %si
125
+	call	print_message
126
+	/* Check for PnP BIOS */
127
+	testw	$0x0f, %di	/* PnP signature must be aligned - bochs    */
128
+	jnz	hook_int19	/* uses unalignment to indicate 'fake' PnP. */
129
+	cmpl	$PNP_SIGNATURE, %es:0(%di)
130
+	jne	hook_int19
131
+	/* Is PnP: print PnP message */
132
+	movw	$init_message_pnp, %si
133
+	call	print_message
134
+	xchgw	%bx, %bx
135
+	/* Check for BBS */
136
+	pushw	%es:0x1b(%di)	/* Real-mode data segment */
137
+	pushw	%ds		/* &(bbs_version) */
138
+	pushw	$bbs_version
139
+	pushw	$PNP_GET_BBS_VERSION
140
+	lcall	*%es:0xd(%di)
141
+	addw	$8, %sp
142
+	testw	%ax, %ax
143
+	jne	hook_int19
144
+	movw	$init_message_bbs, %si
145
+	call	print_message
146
+	jmp	hook_bbs
147
+	/* Not BBS-compliant - must hook INT 19 */
148
+hook_int19:
149
+	movw	$init_message_int19, %si
150
+	call	print_message
151
+	xorw	%ax, %ax
152
+	movw	%ax, %es
153
+	pushw	%cs
154
+	pushw	$int19_entry
155
+	popl	%es:( 0x19 * 4 )
156
+hook_bbs:
157
+	/* Check for PMM */
158
+	movw	$( 0xe000 - 1 ), %di
159
+pmm_scan:
160
+	incw	%di
161
+	jz	no_pmm
162
+	movw	%di, %es
163
+	cmpl	$PMM_SIGNATURE, %es:0
164
+	jne	pmm_scan
165
+	xorw	%bx, %bx
166
+	xorw	%si, %si
167
+	movzbw	%es:5, %cx
168
+1:	es lodsb
169
+	addb	%al, %bl
170
+	loop	1b
171
+	jnz	pmm_scan
172
+	/* PMM found: print PMM message */
173
+	movw	$init_message_pmm, %si
127
 	call	print_message
174
 	call	print_message
175
+	/* Try to allocate 2MB block via PMM */
176
+	pushw	$0x0006		/* Aligned, extended memory */
177
+	pushl	$0xffffffff	/* No handle */
178
+	pushl	$( 0x00200000 / 16 ) /* 2MB in paragraphs */
179
+	pushw	$0x0000		/* pmmAllocate */
180
+	lcall	*%es:7
181
+	addw	$12, %sp
182
+	testw	%dx, %dx	/* %ax==0 even on success, since align=2MB */
183
+	jnz	gotpmm
184
+	movw	$init_message_pmm_failed, %si
185
+	call	print_message
186
+	jmp	no_pmm
187
+gotpmm:	/* PMM allocation succeeded: copy ROM to PMM block */
188
+	pushal			/* PMM presence implies 1kB stack */
189
+	movw	%ax, %es	/* %ax=0 already - see above */
190
+	pushw	%dx
191
+	pushw	%ax
192
+	popl	%edi
193
+	movl	%edi, image_source
194
+	xorl	%esi, %esi
195
+	movzbl	romheader_size, %ecx
196
+	shll	$9, %ecx
197
+	addr32 rep movsb	/* PMM presence implies flat real mode */
198
+	movl	%edi, decompress_to
199
+	/* Shrink ROM and update checksum */
200
+	xorw	%bx, %bx
201
+	xorw	%si, %si
202
+	movw	$_prefix_size_sect, %cx
203
+	movb	%cl, romheader_size
204
+	shlw	$9, %cx
205
+1:	lodsb
206
+	addb	%al, %bl
207
+	loop	1b
208
+	subb	%bl, checksum
209
+	popal
210
+no_pmm:
211
+	/* Print CRLF to terminate messages */
212
+	movw	$'\n', %ax
213
+	call	print_character
214
+	/* Restore registers */
215
+	popw	%es
216
+	popw	%ds
217
+	popaw
218
+	/* Indicate boot capability to PnP BIOS, if present */
128
 	movw	$0x20, %ax
219
 	movw	$0x20, %ax
129
-	popw	%si
130
 	lret
220
 	lret
131
-	.size init_vector, . - init_vector
132
-
133
-ispnp_message:
134
-	.asciz	"gPXE detected PnP BIOS\r\n"
135
-	.size ispnp_message, . - ispnp_message
136
-notpnp_message:
137
-	.asciz	"gPXE detected non-PnP BIOS\r\n"
138
-	.size notpnp_message, . - notpnp_message
139
-
140
-/* Boot execution vector
141
- *pciheader_size
142
- * Called by the PnP BIOS when it wants to boot us, or via the hooked
143
- * INT 19 if we detected a non-PnP BIOS.
144
- */	
145
-exec_vector:
146
-	/* Obtain a reasonably-sized stack */
221
+	.size init, . - init
222
+
223
+init_message:
224
+	.asciz	"gPXE (http://etherboot.org) -"
225
+	.size	init_message, . - init_message
226
+init_message_pnp:
227
+	.asciz	" PnP"
228
+	.size init_message_pnp, . - init_message_pnp
229
+init_message_bbs:
230
+	.asciz	" BBS"
231
+	.size init_message_bbs, . - init_message_bbs
232
+init_message_pmm:
233
+	.asciz	" PMM"
234
+	.size init_message_pmm, . - init_message_pmm
235
+init_message_pmm_failed:
236
+	.asciz	"(failed)"
237
+	.size init_message_pmm_failed, . - init_message_pmm_failed
238
+init_message_int19:
239
+	.asciz	" INT19"
240
+	.size init_message_int19, . - init_message_int19
241
+
242
+/* ROM image location
243
+ *
244
+ * May be either within option ROM space, or within PMM-allocated block.
245
+ */
246
+image_source:
247
+	.long	0
248
+	.size	image_source, . - image_source
249
+
250
+/* Temporary decompression area
251
+ *
252
+ * May be either at HIGHMEM_LOADPOINT, or within PMM-allocated block.
253
+ */
254
+decompress_to:
255
+	.long	HIGHMEM_LOADPOINT
256
+	.size	decompress_to, . - decompress_to
257
+
258
+/* BBS version
259
+ *
260
+ * Filled in by BBS BIOS.  We ignore the value.
261
+ */
262
+bbs_version:
263
+	.word	0
264
+
265
+/* Boot Execution Vector entry point
266
+ *
267
+ * Called by the PnP BIOS when it wants to boot us.
268
+ */
269
+bev_entry:
270
+	pushw	%cs
271
+	call	exec
272
+	lret
273
+	.size	bev_entry, . - bev_entry
274
+
275
+/* INT19 entry point
276
+ *
277
+ * Called via the hooked INT 19 if we detected a non-PnP BIOS.
278
+ */
279
+int19_entry:
280
+	pushw	%cs
281
+	call	exec
282
+	/* No real way to return from INT19 */
283
+	int	$0x18
284
+	.size	int19_entry, . - int19_entry
285
+
286
+/* Execute as a boot device
287
+ *
288
+ */
289
+exec:	/* Set %ds = %cs */
290
+	pushw	%cs
291
+	popw	%ds
292
+
293
+	/* Print message as soon as possible */
294
+	movw	$exec_message, %si
295
+	call	print_message
296
+
297
+	/* Store magic word on BIOS stack and remember BIOS %ss:sp */
298
+	pushl	$STACK_MAGIC
299
+	movw	%ss, %dx
300
+	movw	%sp, %bp
301
+
302
+	/* Obtain a reasonably-sized temporary stack */
147
 	xorw	%ax, %ax
303
 	xorw	%ax, %ax
148
 	movw	%ax, %ss
304
 	movw	%ax, %ss
149
 	movw	$0x7c00, %sp
305
 	movw	$0x7c00, %sp
150
-	
151
-	movw	$exec_message, %si
152
-	call	print_message
153
 
306
 
154
-	call	install
307
+	/* Install gPXE */
308
+	movl	image_source, %esi
309
+	movl	decompress_to, %edi
310
+	call	alloc_basemem
311
+	call	install_prealloc
155
 
312
 
156
 	/* Set up real-mode stack */
313
 	/* Set up real-mode stack */
157
 	movw	%bx, %ss
314
 	movw	%bx, %ss
162
 	pushw	$1f
319
 	pushw	$1f
163
 	lret
320
 	lret
164
 	.section ".text16", "awx", @progbits
321
 	.section ".text16", "awx", @progbits
165
-1:
322
+1:	/* Call main() */
166
 	pushl	$main
323
 	pushl	$main
167
 	pushw	%cs
324
 	pushw	%cs
168
 	call	prot_call
325
 	call	prot_call
169
-	popl	%eax /* discard */
326
+	/* No need to clean up stack; we are about to reload %ss:sp */
327
+	
328
+	/* Restore BIOS stack */
329
+	movw	%dx, %ss
330
+	movw	%bp, %sp
170
 
331
 
171
-	/* Boot next device */
332
+	/* Check magic word on BIOS stack */
333
+	popl	%eax
334
+	cmpl	$STACK_MAGIC, %eax
335
+	jne	1f
336
+	/* BIOS stack OK: return to caller */
337
+	lret
338
+1:	/* BIOS stack corrupt: use INT 18 */
172
 	int	$0x18
339
 	int	$0x18
173
 	.previous
340
 	.previous
174
 
341
 
175
 exec_message:
342
 exec_message:
176
-	.asciz	"gPXE starting boot\r\n"
343
+	.asciz	"gPXE starting boot\n"
177
 	.size exec_message, . - exec_message
344
 	.size exec_message, . - exec_message
178
 
345
 
179
 /* UNDI loader
346
 /* UNDI loader
182
  */
349
  */
183
 undiloader:
350
 undiloader:
184
 	/* Save registers */
351
 	/* Save registers */
352
+	pushl	%esi
185
 	pushl	%edi
353
 	pushl	%edi
186
 	pushw	%es
354
 	pushw	%es
187
 	pushw	%bx
355
 	pushw	%bx
193
 	pushw	%di
361
 	pushw	%di
194
 	movw	%es:12(%di), %bx
362
 	movw	%es:12(%di), %bx
195
 	movw	%es:14(%di), %ax
363
 	movw	%es:14(%di), %ax
364
+	movl	%cs:image_source, %esi
365
+	movl	%cs:decompress_to, %edi
196
 	call	install_prealloc
366
 	call	install_prealloc
197
 	popw	%di
367
 	popw	%di
198
 	/* Call UNDI loader C code */
368
 	/* Call UNDI loader C code */
208
 	popw	%bx
378
 	popw	%bx
209
 	popw	%es
379
 	popw	%es
210
 	popl	%edi
380
 	popl	%edi
381
+	popl	%esi
211
 	lret
382
 	lret
212
 	.size undiloader, . - undiloader
383
 	.size undiloader, . - undiloader
213
-				
214
-/* Utility function: print string
215
- */
216
-print_message:
217
-	pushw	%ax
218
-	pushw	%bx
219
-	pushw	%bp
220
-	movw    $0x0007, %bx
221
-1:	cs lodsb
222
-	testb	%al, %al
223
-	je	2f
224
-	movb    $0x0e, %ah              /* write char, tty mode */
225
-	int     $0x10
226
-	jmp	1b
227
-2:	popw	%bp
228
-	popw	%bx
229
-	popw	%ax
230
-	ret
231
-	.size print_message, . - print_message

+ 2
- 0
src/arch/i386/scripts/i386.lds View File

257
     /*
257
     /*
258
      * Values calculated to save code from doing it
258
      * Values calculated to save code from doing it
259
      */
259
      */
260
+    _prefix_size_pgh	= ( ( _prefix_size + 15 ) / 16 );
261
+    _prefix_size_sect	= ( ( _prefix_size + 511 ) / 512 );
260
     _text16_size_pgh	= ( ( _text16_size + 15 ) / 16 );
262
     _text16_size_pgh	= ( ( _text16_size + 15 ) / 16 );
261
     _data16_size_pgh	= ( ( _data16_size + 15 ) / 16 );
263
     _data16_size_pgh	= ( ( _data16_size + 15 ) / 16 );
262
 
264
 

Loading…
Cancel
Save