Bladeren bron

[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 jaren geleden
bovenliggende
commit
3bf7105cab
1 gewijzigde bestanden met toevoegingen van 114 en 121 verwijderingen
  1. 114
    121
      src/arch/i386/prefix/libprefix.S

+ 114
- 121
src/arch/i386/prefix/libprefix.S Bestand weergeven

@@ -175,13 +175,14 @@ print_hex_nibble:
175 175
 #ifndef KEEP_IT_REAL
176 176
 
177 177
 	/* GDT for protected-mode calls */
178
-	.section ".data16"
178
+	.section ".prefix.lib"
179 179
 	.align 16
180
+pm_call_vars:
180 181
 gdt:
181 182
 gdt_limit:		.word gdt_length - 1
182 183
 gdt_base:		.long 0
183 184
 			.word 0 /* padding */
184
-pm_cs:		/* 16-bit protected-mode code segment */
185
+pm_cs:		/* 16-bit protected-mode code segment */	
185 186
 	.equ    PM_CS, pm_cs - gdt
186 187
 	.word   0xffff, 0
187 188
 	.byte   0, 0x9b, 0x00, 0
@@ -197,18 +198,24 @@ gdt_end:
197 198
 	.equ	gdt_length, . - gdt
198 199
 	.size	gdt, . - gdt
199 200
 
200
-	.section ".data16"
201
+	.section ".prefix.lib"
201 202
 	.align 16
202 203
 pm_saved_gdt:	
203 204
 	.long	0, 0
204 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 210
 	.section ".prefix.lib"
207 211
 	.code16
208 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 218
 	pushfl
211
-	sgdt	pm_saved_gdt
212 219
 	pushw	%gs
213 220
 	pushw	%fs
214 221
 	pushw	%es
@@ -217,27 +224,43 @@ pm_call:
217 224
 	pushw	%cs
218 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 242
 	/* Set up GDT bases */
221 243
 	pushl	%eax
222
-	pushw	%bx
244
+	pushl	%edi
223 245
 	xorl	%eax, %eax
224
-	movw	%ds, %ax
246
+	movw	%ss, %ax
225 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 251
 	movw	%cs, %ax
229
-	movw	$pm_cs, %bx
252
+	movw	$PM_CALL_VAR(pm_cs), %di
230 253
 	call	set_seg_base
231 254
 	movw	%ss, %ax
232
-	movw	$pm_ss, %bx
255
+	movw	$PM_CALL_VAR(pm_ss), %di
233 256
 	call	set_seg_base
234
-	popw	%bx
257
+	popl	%edi
235 258
 	popl	%eax
236 259
 
237 260
 	/* Switch CPU to protected mode and load up segment registers */
238 261
 	pushl	%eax
239 262
 	cli
240
-	lgdt	gdt
263
+	lgdt	PM_CALL_VAR(gdt)(%bp)
241 264
 	movl	%cr0, %eax
242 265
 	orb	$CR0_PE, %al
243 266
 	movl	%eax, %cr0
@@ -273,18 +296,19 @@ pm_call:
273 296
 	popw	%es
274 297
 	popw	%fs
275 298
 	popw	%gs
276
-	lgdt	pm_saved_gdt
299
+	lgdt	PM_CALL_VAR(pm_saved_gdt)(%bp)
277 300
 	popfl
278
-
301
+	movw	%bp, %sp
302
+	popw	%bp
279 303
 	ret
280 304
 	.size pm_call, . - pm_call
281 305
 
282 306
 set_seg_base:
283 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 312
 	ret
289 313
 	.size set_seg_base, . - set_seg_base
290 314
 
@@ -301,7 +325,7 @@ set_seg_base:
301 325
  *   %ecx : length
302 326
  * Returns:
303 327
  *   %ds:esi : next source address
304
- *   %ds:esi : next destination address
328
+ *   %es:edi : next destination address
305 329
  * Corrupts:
306 330
  *   None
307 331
  ****************************************************************************
@@ -316,27 +340,57 @@ copy_bytes:
316 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 345
  * Install block to specified address
322 346
  *
323 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 350
  *   %ecx : length of (decompressed) data
327 351
  *   %edx : total length of block (including any uninitialised data portion)
328 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 354
  * Corrupts:
331
- *   %ecx, %edx
355
+ *   none
332 356
  ****************************************************************************
333 357
  */
334 358
 	.section ".prefix.lib"
335 359
 	.code16
336 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 387
 	/* Preserve registers */
388
+	pushl	%ecx
338 389
 	pushl	%edi
339 390
 	
391
+#endif /* KEEP_IT_REAL */
392
+
393
+	
340 394
 #if COMPRESS
341 395
 	/* Decompress source to destination */
342 396
 	call	decompress16
@@ -357,8 +411,28 @@ install_block:
357 411
 	addl	$0xf, %esi
358 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 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 436
 	ret
363 437
 	.size install_block, . - install_block
364 438
 	
@@ -406,87 +480,6 @@ alloc_basemem:
406 480
 	ret
407 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 484
  * install (real-mode near call)
492 485
  *
@@ -555,17 +548,19 @@ install_prealloc:
555 548
 	shll	$4, %esi
556 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 565
 	/* Set up %ds for access to .data16 */
571 566
 	movw	%bx, %ds
@@ -581,9 +576,7 @@ install_prealloc:
581 576
 	 */
582 577
 	movl	$_textdata_progbits_size, %ecx
583 578
 	movl	$_textdata_size, %edx
584
-	pushl	%edi
585
-	call	install_highmem
586
-	popl	%edi
579
+	call	install_block
587 580
 
588 581
 	/* Initialise librm at current location */
589 582
 	movw	%ax, (init_librm_vector+2)

Laden…
Annuleren
Opslaan