浏览代码

[romprefix] If we hook INT 19, prompt before attempting boot

On non-BBS systems we hook INT 19, since there is no other way we can
guarantee gaining control of the flow of execution.  If we end up
doing this, prompt the user before attempting boot, since forcibly
capturing INT 19 is rather antisocial.
tags/v0.9.4
Michael Brown 15 年前
父节点
当前提交
9d44a06188
共有 1 个文件被更改,包括 107 次插入44 次删除
  1. 107
    44
      src/arch/i386/prefix/romprefix.S

+ 107
- 44
src/arch/i386/prefix/romprefix.S 查看文件

@@ -145,8 +145,6 @@ init:
145 145
 	cld
146 146
 	pushw	%cs
147 147
 	popw	%ds
148
-	pushw	$0x40
149
-	popw	%fs
150 148
 
151 149
 	/* Shuffle some registers around.  We need %di available for
152 150
 	 * the print_xxx functions, and in a register that's
@@ -317,46 +315,17 @@ no_pmm:
317 315
 	movw	$init_message_prompt, %si
318 316
 	xorw	%di, %di
319 317
 	call	print_message
320
-	/* Empty the keyboard buffer before waiting for input */
321
-empty_keyboard_buffer:
322
-	movb	$0x01, %ah
323
-	int	$0x16
324
-	jz	1f
325
-	xorw	%ax, %ax
326
-	int	$0x16
327
-	jmp	empty_keyboard_buffer
328
-1:	/* Wait for up to 3s for a key press */
329
-	movw	$(18 * 3), %cx	/* Approx 3s worth of timer ticks */
330
-wait_for_key:
331
-	decw	%cx
332
-	jz	no_key_pressed
333
-	/* Wait for timer tick to be updated */
334
-	movl	%fs:(0x6c), %eax
335
-1:	pushf
336
-	sti
337
-	hlt
338
-	popf
339
-	cmpl	%fs:(0x6c), %eax
340
-	je	1b
341
-	/* Check to see if a key was pressed */
342
-	movb	$0x01, %ah
343
-	int	$0x16
344
-	jz	wait_for_key
345
-	/* Check to see if key was Ctrl-B */
346
-	cmpb	$0x02, %al
347
-	je	1f
348
-	/* Key was not Ctrl-B: remove from buffer and stop waiting */
349
-	xorw	%ax, %ax
350
-	int	$0x16
351
-	jmp	no_key_pressed
352
-1:	/* Key was Ctrl-B: leave in keyboard buffer and invoke gPXE.
353
-	 * The keypress will be picked up by the initial shell
354
-	 * prompt, and we will drop into a shell.
318
+	/* Wait for Ctrl-B */
319
+	movw	$0xff02, %bx
320
+	call	wait_for_key
321
+	jnz	1f
322
+	/* Ctrl-B was pressed: invoke gPXE.  The keypress will be
323
+	 * picked up by the initial shell prompt, and we will drop
324
+	 * into a shell.
355 325
 	 */
356 326
 	pushw	%cs
357 327
 	call	exec
358
-no_key_pressed:
359
-
328
+1:
360 329
 	/* Print blank lines to terminate messages */
361 330
 	movw	$init_message_end, %si
362 331
 	xorw	%di, %di
@@ -436,24 +405,54 @@ bev_entry:
436 405
 /* INT19 entry point
437 406
  *
438 407
  * Called via the hooked INT 19 if we detected a non-PnP BIOS.  We
439
- * attempt to return via the original INT 19 vector (if we were able to
440
- * store it).
408
+ * attempt to return via the original INT 19 vector (if we were able
409
+ * to store it).
441 410
  */
442 411
 int19_entry:
443 412
 	pushw	%cs
413
+	popw	%ds
414
+	/* Prompt user to press B to boot */
415
+	movw	$int19_message_prompt, %si
416
+	xorw	%di, %di
417
+	call	print_message
418
+	movw	$prodstr, %si
419
+	call	print_message
420
+	movw	$int19_message_dots, %si
421
+	call	print_message
422
+	movw	$0xdf42, %bx
423
+	call	wait_for_key
424
+	jnz	1f
425
+	/* Leave keypress in buffer and start gPXE.  The keypress will
426
+	 * cause the usual initial Ctrl-B prompt to be skipped.
427
+	 */
428
+	pushw	%cs
444 429
 	call	exec
430
+1:	/* Print blank lines to terminate messages */
431
+	movw	$int19_message_end, %si
432
+	xorw	%di, %di
433
+	call	print_message
434
+	/* Try to call original INT 19 vector */
445 435
 	movl	%cs:orig_int19, %eax
446 436
 	testl	%eax, %eax
447
-	je	1f
448
-	/* Chain to original INT 19 vector */
437
+	je	2f
449 438
 	ljmp	*%cs:orig_int19
450
-1:	/* No chained vector: issue INT 18 as a last resort */
439
+2:	/* No chained vector: issue INT 18 as a last resort */
451 440
 	int	$0x18
452 441
 	.size	int19_entry, . - int19_entry
453 442
 orig_int19:
454 443
 	.long	0
455 444
 	.size	orig_int19, . - orig_int19
456 445
 
446
+int19_message_prompt:
447
+	.asciz	"Press B to boot from "
448
+	.size	int19_message_prompt, . - int19_message_prompt
449
+int19_message_dots:
450
+	.asciz	"..."
451
+	.size	int19_message_dots, . - int19_message_dots
452
+int19_message_end:
453
+	.asciz	"\n\n\n"
454
+	.size	int19_message_end, . - int19_message_end
455
+	
457 456
 /* Execute as a boot device
458 457
  *
459 458
  */
@@ -560,3 +559,67 @@ undiloader:
560 559
 	popl	%esi
561 560
 	lret
562 561
 	.size undiloader, . - undiloader
562
+
563
+/* Wait for key press specified by %bl (masked by %bh)
564
+ *
565
+ * Used by init and INT19 code when prompting user.  If the specified
566
+ * key is pressed, it is left in the keyboard buffer.
567
+ *
568
+ * Returns with ZF set iff specified key is pressed.
569
+ */
570
+wait_for_key:
571
+	/* Preserve registers */
572
+	pushw	%cx
573
+	pushw	%ax
574
+1:	/* Empty the keyboard buffer before waiting for input */
575
+	movb	$0x01, %ah
576
+	int	$0x16
577
+	jz	2f
578
+	xorw	%ax, %ax
579
+	int	$0x16
580
+	jmp	1b
581
+2:	/* Wait for up to 5s for a key press */
582
+	movw	$(18 * 5), %cx	/* Approx 5s worth of timer ticks */
583
+3:	decw	%cx
584
+	js	99f		/* Exit with ZF clear */
585
+	/* Wait for timer tick to be updated */
586
+	call	wait_for_tick
587
+	/* Check to see if a key was pressed */
588
+	movb	$0x01, %ah
589
+	int	$0x16
590
+	jz	3b
591
+	/* Check to see if key was the specified key */
592
+	andb	%bh, %al
593
+	cmpb	%al, %bl
594
+	je	99f		/* Exit with ZF set */
595
+	/* Not the specified key: remove from buffer and stop waiting */
596
+	pushfw
597
+	xorw	%ax, %ax
598
+	int	$0x16
599
+	popfw			/* Exit with ZF clear */
600
+99:	/* Restore registers and return */
601
+	popw	%ax
602
+	popw	%cx
603
+	ret
604
+	.size wait_for_key, . - wait_for_key
605
+
606
+/* Wait for timer tick
607
+ *
608
+ * Used by wait_for_key
609
+ */
610
+wait_for_tick:
611
+	pushl	%eax
612
+	pushw	%fs
613
+	movw	$0x40, %ax
614
+	movw	%ax, %fs
615
+	movl	%fs:(0x6c), %eax
616
+1:	pushf
617
+	sti
618
+	hlt
619
+	popf
620
+	cmpl	%fs:(0x6c), %eax
621
+	je	1b
622
+	popw	%fs
623
+	popl	%eax
624
+	ret
625
+	.size wait_for_tick, . - wait_for_tick

正在加载...
取消
保存