Browse Source

[prefix] Cope with image source addresses outside base memory

When PMM is used, the gPXE image source will no longer be in base memory.
Decompression of .text16 and .data16 can therefore no longer be done in
real mode.
tags/v0.9.4
Michael Brown 16 years ago
parent
commit
3bf7105cab
1 changed files with 114 additions and 121 deletions
  1. 114
    121
      src/arch/i386/prefix/libprefix.S

+ 114
- 121
src/arch/i386/prefix/libprefix.S View File

175
 #ifndef KEEP_IT_REAL
175
 #ifndef KEEP_IT_REAL
176
 
176
 
177
 	/* GDT for protected-mode calls */
177
 	/* GDT for protected-mode calls */
178
-	.section ".data16"
178
+	.section ".prefix.lib"
179
 	.align 16
179
 	.align 16
180
+pm_call_vars:
180
 gdt:
181
 gdt:
181
 gdt_limit:		.word gdt_length - 1
182
 gdt_limit:		.word gdt_length - 1
182
 gdt_base:		.long 0
183
 gdt_base:		.long 0
183
 			.word 0 /* padding */
184
 			.word 0 /* padding */
184
-pm_cs:		/* 16-bit protected-mode code segment */
185
+pm_cs:		/* 16-bit protected-mode code segment */	
185
 	.equ    PM_CS, pm_cs - gdt
186
 	.equ    PM_CS, pm_cs - gdt
186
 	.word   0xffff, 0
187
 	.word   0xffff, 0
187
 	.byte   0, 0x9b, 0x00, 0
188
 	.byte   0, 0x9b, 0x00, 0
197
 	.equ	gdt_length, . - gdt
198
 	.equ	gdt_length, . - gdt
198
 	.size	gdt, . - gdt
199
 	.size	gdt, . - gdt
199
 
200
 
200
-	.section ".data16"
201
+	.section ".prefix.lib"
201
 	.align 16
202
 	.align 16
202
 pm_saved_gdt:	
203
 pm_saved_gdt:	
203
 	.long	0, 0
204
 	.long	0, 0
204
 	.size	pm_saved_gdt, . - pm_saved_gdt
205
 	.size	pm_saved_gdt, . - pm_saved_gdt
205
 
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
+
206
 	.section ".prefix.lib"
210
 	.section ".prefix.lib"
207
 	.code16
211
 	.code16
208
 pm_call:
212
 pm_call:
209
-	/* 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
210
 	pushfl
218
 	pushfl
211
-	sgdt	pm_saved_gdt
212
 	pushw	%gs
219
 	pushw	%gs
213
 	pushw	%fs
220
 	pushw	%fs
214
 	pushw	%es
221
 	pushw	%es
217
 	pushw	%cs
224
 	pushw	%cs
218
 	pushw	$99f
225
 	pushw	$99f
219
 
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
+
220
 	/* Set up GDT bases */
242
 	/* Set up GDT bases */
221
 	pushl	%eax
243
 	pushl	%eax
222
-	pushw	%bx
244
+	pushl	%edi
223
 	xorl	%eax, %eax
245
 	xorl	%eax, %eax
224
-	movw	%ds, %ax
246
+	movw	%ss, %ax
225
 	shll	$4, %eax
247
 	shll	$4, %eax
226
-	addl	$gdt, %eax
227
-	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)
228
 	movw	%cs, %ax
251
 	movw	%cs, %ax
229
-	movw	$pm_cs, %bx
252
+	movw	$PM_CALL_VAR(pm_cs), %di
230
 	call	set_seg_base
253
 	call	set_seg_base
231
 	movw	%ss, %ax
254
 	movw	%ss, %ax
232
-	movw	$pm_ss, %bx
255
+	movw	$PM_CALL_VAR(pm_ss), %di
233
 	call	set_seg_base
256
 	call	set_seg_base
234
-	popw	%bx
257
+	popl	%edi
235
 	popl	%eax
258
 	popl	%eax
236
 
259
 
237
 	/* Switch CPU to protected mode and load up segment registers */
260
 	/* Switch CPU to protected mode and load up segment registers */
238
 	pushl	%eax
261
 	pushl	%eax
239
 	cli
262
 	cli
240
-	lgdt	gdt
263
+	lgdt	PM_CALL_VAR(gdt)(%bp)
241
 	movl	%cr0, %eax
264
 	movl	%cr0, %eax
242
 	orb	$CR0_PE, %al
265
 	orb	$CR0_PE, %al
243
 	movl	%eax, %cr0
266
 	movl	%eax, %cr0
273
 	popw	%es
296
 	popw	%es
274
 	popw	%fs
297
 	popw	%fs
275
 	popw	%gs
298
 	popw	%gs
276
-	lgdt	pm_saved_gdt
299
+	lgdt	PM_CALL_VAR(pm_saved_gdt)(%bp)
277
 	popfl
300
 	popfl
278
-
301
+	movw	%bp, %sp
302
+	popw	%bp
279
 	ret
303
 	ret
280
 	.size pm_call, . - pm_call
304
 	.size pm_call, . - pm_call
281
 
305
 
282
 set_seg_base:
306
 set_seg_base:
283
 	rolw	$4, %ax
307
 	rolw	$4, %ax
284
-	movw	%ax, 2(%bx)
285
-	andw	$0xfff0, 2(%bx)
286
-	movb	%al, 4(%bx)
287
-	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)
288
 	ret
312
 	ret
289
 	.size set_seg_base, . - set_seg_base
313
 	.size set_seg_base, . - set_seg_base
290
 
314
 
301
  *   %ecx : length
325
  *   %ecx : length
302
  * Returns:
326
  * Returns:
303
  *   %ds:esi : next source address
327
  *   %ds:esi : next source address
304
- *   %ds:esi : next destination address
328
+ *   %es:edi : next destination address
305
  * Corrupts:
329
  * Corrupts:
306
  *   None
330
  *   None
307
  ****************************************************************************
331
  ****************************************************************************
316
 	.size copy_bytes, . - copy_bytes
340
 	.size copy_bytes, . - copy_bytes
317
 
341
 
318
 /****************************************************************************
342
 /****************************************************************************
319
- * install_block (real-mode or 16-bit protected-mode near call)
343
+ * install_block (real-mode near call)
320
  *
344
  *
321
  * Install block to specified address
345
  * Install block to specified address
322
  *
346
  *
323
  * Parameters:
347
  * Parameters:
324
- *   %ds:esi : source address (must be a multiple of 16)
325
- *   %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)
326
  *   %ecx : length of (decompressed) data
350
  *   %ecx : length of (decompressed) data
327
  *   %edx : total length of block (including any uninitialised data portion)
351
  *   %edx : total length of block (including any uninitialised data portion)
328
  * Returns:
352
  * Returns:
329
- *   %ds:esi : next source address (will be a multiple of 16)
353
+ *   %esi : next source physical address (will be a multiple of 16)
330
  * Corrupts:
354
  * Corrupts:
331
- *   %ecx, %edx
355
+ *   none
332
  ****************************************************************************
356
  ****************************************************************************
333
  */
357
  */
334
 	.section ".prefix.lib"
358
 	.section ".prefix.lib"
335
 	.code16
359
 	.code16
336
 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:
337
 	/* Preserve registers */
387
 	/* Preserve registers */
388
+	pushl	%ecx
338
 	pushl	%edi
389
 	pushl	%edi
339
 	
390
 	
391
+#endif /* KEEP_IT_REAL */
392
+
393
+	
340
 #if COMPRESS
394
 #if COMPRESS
341
 	/* Decompress source to destination */
395
 	/* Decompress source to destination */
342
 	call	decompress16
396
 	call	decompress16
357
 	addl	$0xf, %esi
411
 	addl	$0xf, %esi
358
 	andl	$~0xf, %esi
412
 	andl	$~0xf, %esi
359
 
413
 
360
-	/* Restore registers and return */
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 */
361
 	popl	%edi
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
+
362
 	ret
436
 	ret
363
 	.size install_block, . - install_block
437
 	.size install_block, . - install_block
364
 	
438
 	
406
 	ret
480
 	ret
407
 	.size alloc_basemem, . - alloc_basemem
481
 	.size alloc_basemem, . - alloc_basemem
408
 
482
 
409
-/****************************************************************************
410
- * install_basemem (real-mode near call)
411
- *
412
- * Install source block into base memory
413
- *
414
- * Parameters:
415
- *   %esi : source physical address (must be a multiple of 16)
416
- *   %es : destination segment address
417
- *   %cx : length of (decompressed) data
418
- *   %dx : total length of block (including any uninitialised data portion)
419
- * Returns:
420
- *   %esi : next source physical address (will be a multiple of 16)
421
- * Corrupts:
422
- *   %ecx, %edx
423
- ****************************************************************************
424
- */
425
-	.section ".prefix.lib"
426
-	.code16
427
-install_basemem:
428
-	/* Preserve registers */
429
-	pushl	%edi
430
-	pushw	%ds
431
-
432
-	/* Preserve original %esi */
433
-	pushl	%esi
434
-
435
-	/* Install to specified address */
436
-	shrl	$4, %esi
437
-	movw	%si, %ds
438
-	xorw	%si, %si
439
-	xorl	%edi, %edi
440
-	movzwl	%cx, %ecx
441
-	movzwl	%dx, %edx
442
-	call	install_block
443
-
444
-	/* Fix up %esi for return */
445
-	popl	%ecx
446
-	addl	%ecx, %esi
447
-
448
-	/* Restore registers */
449
-	popw	%ds
450
-	popl	%edi
451
-	ret
452
-	.size install_basemem, . - install_basemem
453
-
454
-/****************************************************************************
455
- * install_highmem (real-mode near call)
456
- *
457
- * Install source block into high memory
458
- *
459
- * Parameters:
460
- *   %esi : source physical address (must be a multiple of 16)
461
- *   %edi : destination physical address
462
- *   %ecx : length of (decompressed) data
463
- *   %edx : total length of block (including any uninitialised data portion)
464
- * Returns:
465
- *   %esi : next source physical address (will be a multiple of 16)
466
- * Corrupts:
467
- *   %ecx, %edx
468
- ****************************************************************************
469
- */
470
-
471
-#ifndef KEEP_IT_REAL
472
-
473
-	.section ".prefix.lib"
474
-	.code16
475
-install_highmem:
476
-	/* Preserve registers */
477
-	pushw	%ax
478
-
479
-	/* Install to specified address */
480
-	movw	$install_block, %ax
481
-	call	pm_call
482
-
483
-	/* Restore registers */
484
-	popw	%ax
485
-	ret
486
-	.size install_highmem, . - install_highmem
487
-	
488
-#endif /* KEEP_IT_REAL */
489
-	
490
 /****************************************************************************
483
 /****************************************************************************
491
  * install (real-mode near call)
484
  * install (real-mode near call)
492
  *
485
  *
555
 	shll	$4, %esi
548
 	shll	$4, %esi
556
 1:	addl	$_payload_offset, %esi
549
 1:	addl	$_payload_offset, %esi
557
 
550
 
558
-	/* Install .text16 */
559
-	movw	%ax, %es
560
-	movw	$_text16_size, %cx
561
-	movw	%cx, %dx
562
-	call	install_basemem
563
-
564
-	/* Install .data16 */
565
-	movw	%bx, %es
566
-	movw	$_data16_progbits_size, %cx
567
-	movw	$_data16_size, %dx
568
-	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
569
 
564
 
570
 	/* Set up %ds for access to .data16 */
565
 	/* Set up %ds for access to .data16 */
571
 	movw	%bx, %ds
566
 	movw	%bx, %ds
581
 	 */
576
 	 */
582
 	movl	$_textdata_progbits_size, %ecx
577
 	movl	$_textdata_progbits_size, %ecx
583
 	movl	$_textdata_size, %edx
578
 	movl	$_textdata_size, %edx
584
-	pushl	%edi
585
-	call	install_highmem
586
-	popl	%edi
579
+	call	install_block
587
 
580
 
588
 	/* Initialise librm at current location */
581
 	/* Initialise librm at current location */
589
 	movw	%ax, (init_librm_vector+2)
582
 	movw	%ax, (init_librm_vector+2)

Loading…
Cancel
Save