Browse Source

[pxeprefix] Add .kkpxe image type and ability to return via PXE stack

Certain combinations of PXE stack and BIOS result in a broken INT 18
call, which will leave the system displaying a "PRESS ANY KEY TO
REBOOT" message instead of proceeding to the next boot device.  On
these systems, returning via the PXE stack is the only way to continue
to the next boot device.  Returning via the PXE stack works only if we
haven't already blown away the PXE base code in pxeprefix.S.

In most circumstances, we do want to blow away the PXE base code.
Base memory is a limited resource, and it is desirable to reclaim as
much as possible.  When we perform an iSCSI boot, we need to place the
iBFT above the 512kB mark, because otherwise it may not be detected by
the loaded OS; this may not be possible if the PXE base code is still
occupying that memory.

Introduce a new prefix type .kkpxe which will preserve both the PXE
base code and the UNDI driver (as compared to .kpxe, which preserves
the UNDI driver but uninstalls the PXE base code).  This prefix type
can be used on systems that are known to experience the specific
problem of INT 18 being broken, or in builds (such as gpxelinux.0) for
which it is particularly important to know that returning to the BIOS
will work.

Written by H. Peter Anvin <hpa@zytor.com> and Stefan Hajnoczi
<stefanha@gmail.com>, minor structural alterations by Michael Brown
<mcb30@etherboot.org>.
tags/v0.9.7
Michael Brown 16 years ago
parent
commit
b5577553e5

+ 1
- 0
src/arch/i386/Makefile.pcbios View File

13
 MEDIA		+= rom
13
 MEDIA		+= rom
14
 MEDIA		+= pxe
14
 MEDIA		+= pxe
15
 MEDIA		+= kpxe
15
 MEDIA		+= kpxe
16
+MEDIA		+= kkpxe
16
 MEDIA		+= elf
17
 MEDIA		+= elf
17
 MEDIA		+= elfd
18
 MEDIA		+= elfd
18
 MEDIA		+= lmelf
19
 MEDIA		+= lmelf

+ 35
- 22
src/arch/i386/drivers/net/undinet.c View File

669
 	undi->flags |= UNDI_FL_STARTED;
669
 	undi->flags |= UNDI_FL_STARTED;
670
 
670
 
671
 	/* Bring up UNDI stack */
671
 	/* Bring up UNDI stack */
672
-	memset ( &undi_startup, 0, sizeof ( undi_startup ) );
673
-	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_STARTUP, &undi_startup,
674
-				   sizeof ( undi_startup ) ) ) != 0 )
675
-		goto err_undi_startup;
676
-	memset ( &undi_initialize, 0, sizeof ( undi_initialize ) );
677
-	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_INITIALIZE,
678
-				   &undi_initialize,
679
-				   sizeof ( undi_initialize ) ) ) != 0 )
680
-		goto err_undi_initialize;
672
+	if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) {
673
+		memset ( &undi_startup, 0, sizeof ( undi_startup ) );
674
+		if ( ( rc = undinet_call ( undinic, PXENV_UNDI_STARTUP,
675
+					   &undi_startup,
676
+					   sizeof ( undi_startup ) ) ) != 0 )
677
+			goto err_undi_startup;
678
+		memset ( &undi_initialize, 0, sizeof ( undi_initialize ) );
679
+		if ( ( rc = undinet_call ( undinic, PXENV_UNDI_INITIALIZE,
680
+					   &undi_initialize,
681
+					   sizeof ( undi_initialize ))) != 0 )
682
+			goto err_undi_initialize;
683
+	}
684
+	undi->flags |= UNDI_FL_INITIALIZED;
681
 
685
 
682
 	/* Get device information */
686
 	/* Get device information */
683
 	memset ( &undi_info, 0, sizeof ( undi_info ) );
687
 	memset ( &undi_info, 0, sizeof ( undi_info ) );
731
 	memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
735
 	memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
732
 	undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
736
 	undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
733
 		       sizeof ( undi_cleanup ) );
737
 		       sizeof ( undi_cleanup ) );
738
+	undi->flags &= ~UNDI_FL_INITIALIZED;
734
  err_undi_startup:
739
  err_undi_startup:
735
 	/* Unhook UNDI stack */
740
 	/* Unhook UNDI stack */
736
 	memset ( &stop_undi, 0, sizeof ( stop_undi ) );
741
 	memset ( &stop_undi, 0, sizeof ( stop_undi ) );
737
 	undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
742
 	undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
738
 		       sizeof ( stop_undi ) );
743
 		       sizeof ( stop_undi ) );
744
+	undi->flags &= ~UNDI_FL_STARTED;
739
  err_start_undi:
745
  err_start_undi:
740
 	netdev_nullify ( netdev );
746
 	netdev_nullify ( netdev );
741
 	netdev_put ( netdev );
747
 	netdev_put ( netdev );
758
 	/* Unregister net device */
764
 	/* Unregister net device */
759
 	unregister_netdev ( netdev );
765
 	unregister_netdev ( netdev );
760
 
766
 
761
-	/* Shut down UNDI stack */
762
-	memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
763
-	undinet_call ( undinic, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
764
-		       sizeof ( undi_shutdown ) );
765
-	memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
766
-	undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
767
-		       sizeof ( undi_cleanup ) );
768
-
769
-	/* Unhook UNDI stack */
770
-	memset ( &stop_undi, 0, sizeof ( stop_undi ) );
771
-	undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
772
-		       sizeof ( stop_undi ) );
773
-	undi->flags &= ~UNDI_FL_STARTED;
767
+	/* If we are preparing for an OS boot, or if we cannot exit
768
+	 * via the PXE stack, then shut down the PXE stack.
769
+	 */
770
+	if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
771
+
772
+		/* Shut down UNDI stack */
773
+		memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
774
+		undinet_call ( undinic, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
775
+			       sizeof ( undi_shutdown ) );
776
+		memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
777
+		undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
778
+			       sizeof ( undi_cleanup ) );
779
+		undi->flags &= ~UNDI_FL_INITIALIZED;
780
+
781
+		/* Unhook UNDI stack */
782
+		memset ( &stop_undi, 0, sizeof ( stop_undi ) );
783
+		undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
784
+			       sizeof ( stop_undi ) );
785
+		undi->flags &= ~UNDI_FL_STARTED;
786
+	}
774
 
787
 
775
 	/* Clear entry point */
788
 	/* Clear entry point */
776
 	memset ( &undinet_entry_point, 0, sizeof ( undinet_entry_point ) );
789
 	memset ( &undinet_entry_point, 0, sizeof ( undinet_entry_point ) );

+ 18
- 0
src/arch/i386/drivers/net/undionly.c View File

20
 #include <stdlib.h>
20
 #include <stdlib.h>
21
 #include <string.h>
21
 #include <string.h>
22
 #include <gpxe/device.h>
22
 #include <gpxe/device.h>
23
+#include <gpxe/init.h>
23
 #include <undi.h>
24
 #include <undi.h>
24
 #include <undinet.h>
25
 #include <undinet.h>
25
 #include <undipreload.h>
26
 #include <undipreload.h>
107
 	.dev = { .name = "UNDI" },
108
 	.dev = { .name = "UNDI" },
108
 	.driver = &undi_root_driver,
109
 	.driver = &undi_root_driver,
109
 };
110
 };
111
+
112
+/**
113
+ * Prepare for exit
114
+ *
115
+ * @v flags		Shutdown flags
116
+ */
117
+static void undionly_shutdown ( int flags ) {
118
+	/* If we are shutting down to boot an OS, clear the "keep PXE
119
+	 * stack" flag.
120
+	 */
121
+	if ( flags & SHUTDOWN_BOOT )
122
+		preloaded_undi.flags &= ~UNDI_FL_KEEP_ALL;
123
+}
124
+
125
+struct startup_fn startup_undionly __startup_fn ( STARTUP_LATE ) = {
126
+	.shutdown = undionly_shutdown,
127
+};

+ 6
- 0
src/arch/i386/include/undi.h View File

95
 /** UNDI flag: START_UNDI has been called */
95
 /** UNDI flag: START_UNDI has been called */
96
 #define UNDI_FL_STARTED 0x0001
96
 #define UNDI_FL_STARTED 0x0001
97
 
97
 
98
+/** UNDI flag: UNDI_STARTUP and UNDI_INITIALIZE have been called */
99
+#define UNDI_FL_INITIALIZED 0x0002
100
+
101
+/** UNDI flag: keep stack resident */
102
+#define UNDI_FL_KEEP_ALL 0x0004
103
+
98
 #endif /* _UNDI_H */
104
 #endif /* _UNDI_H */

+ 8
- 0
src/arch/i386/prefix/kkpxeprefix.S View File

1
+/*****************************************************************************
2
+ * PXE prefix that keeps the whole PXE stack present
3
+ *****************************************************************************
4
+ */
5
+
6
+#define PXELOADER_KEEP_UNDI
7
+#define PXELOADER_KEEP_PXE
8
+#include "pxeprefix.S"

+ 62
- 17
src/arch/i386/prefix/pxeprefix.S View File

10
 
10
 
11
 #include <undi.h>
11
 #include <undi.h>
12
 
12
 
13
+#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
14
+
13
 /*****************************************************************************
15
 /*****************************************************************************
14
  * Entry point:	set operating context, print welcome message
16
  * Entry point:	set operating context, print welcome message
15
  *****************************************************************************
17
  *****************************************************************************
16
  */
18
  */
17
 	.section ".prefix", "ax", @progbits
19
 	.section ".prefix", "ax", @progbits
18
-	/* Set up our non-stack segment registers */
19
 	jmp	$0x7c0, $1f
20
 	jmp	$0x7c0, $1f
20
-1:	movw	%cs, %ax
21
+1:
22
+	/* Preserve registers for possible return to PXE */
23
+	pushfl
24
+	pushal
25
+	pushw	%gs
26
+	pushw	%fs
27
+	pushw	%es
28
+	pushw	%ds
29
+
30
+	/* Store magic word on PXE stack and remember PXE %ss:esp */
31
+	pushl	$STACK_MAGIC
32
+	movw	%ss, %cs:pxe_ss
33
+	movl	%esp, %cs:pxe_esp
34
+	movw	%sp, %bp
35
+	movl	(10*4+4*2+4)(%bp),%ebp	/* !PXE address */
36
+
37
+	/* Set up %ds */
38
+	movw	%cs, %ax
21
 	movw	%ax, %ds
39
 	movw	%ax, %ds
22
-	movw	$0x40, %ax		/* BIOS data segment access */
23
-	movw	%ax, %fs
24
 	/* Record PXENV+ and !PXE nominal addresses */
40
 	/* Record PXENV+ and !PXE nominal addresses */
25
-	movw	%es, %ax		/* PXENV+ address */
26
-	movw	%ax, pxenv_segment
41
+	movw	%es, pxenv_segment	/* PXENV+ address */
27
 	movw	%bx, pxenv_offset
42
 	movw	%bx, pxenv_offset
28
-	popl	%eax			/* Discard return address */
29
-	popl	ppxe_segoff		/* !PXE address */
43
+	movl	%ebp, ppxe_segoff	/* !PXE address */
44
+	/* Set up %es and %fs */
45
+	movw	%ax, %es
46
+	movw	$0x40, %ax		/* BIOS data segment access */
47
+	movw	%ax, %fs
30
 	/* Set up stack just below 0x7c00 */
48
 	/* Set up stack just below 0x7c00 */
31
 	xorw	%ax, %ax
49
 	xorw	%ax, %ax
32
 	movw	%ax, %ss
50
 	movw	%ax, %ss
33
-	movw	$0x7c00, %sp
51
+	movl	$0x7c00, %esp
34
 	/* Clear direction flag, for the sake of sanity */
52
 	/* Clear direction flag, for the sake of sanity */
35
 	cld
53
 	cld
36
 	/* Print welcome message */
54
 	/* Print welcome message */
249
  * Leave NIC in a safe state
267
  * Leave NIC in a safe state
250
  *****************************************************************************
268
  *****************************************************************************
251
  */
269
  */
270
+#ifndef PXELOADER_KEEP_PXE
252
 shutdown_nic:
271
 shutdown_nic:
253
 	/* Issue PXENV_UNDI_SHUTDOWN */
272
 	/* Issue PXENV_UNDI_SHUTDOWN */
254
 	movw	$PXENV_UNDI_SHUTDOWN, %bx
273
 	movw	$PXENV_UNDI_SHUTDOWN, %bx
256
 	jnc	1f
275
 	jnc	1f
257
 	call	print_pxe_error
276
 	call	print_pxe_error
258
 1:
277
 1:
259
-
260
-/*****************************************************************************
261
- * Unload PXE base code
262
- *****************************************************************************
263
- */	
264
 unload_base_code:
278
 unload_base_code:
265
 	/* Issue PXENV_UNLOAD_STACK */
279
 	/* Issue PXENV_UNLOAD_STACK */
266
 	movw	$PXENV_UNLOAD_STACK, %bx
280
 	movw	$PXENV_UNLOAD_STACK, %bx
273
 	movw	%fs:(0x13), %bx
287
 	movw	%fs:(0x13), %bx
274
 	call	free_basemem
288
 	call	free_basemem
275
 99:
289
 99:
290
+	andw	$~( UNDI_FL_INITIALIZED | UNDI_FL_KEEP_ALL ), flags
291
+#endif /* PXELOADER_KEEP_PXE */
276
 
292
 
277
 /*****************************************************************************
293
 /*****************************************************************************
278
  * Unload UNDI driver
294
  * Unload UNDI driver
511
  * PXE data structures
527
  * PXE data structures
512
  *****************************************************************************
528
  *****************************************************************************
513
  */
529
  */
530
+	.section ".prefix.data"
531
+
532
+pxe_ss:			.word 0
533
+pxe_esp:		.long 0
514
 
534
 
515
 pxe_parameter_structure: .fill 20
535
 pxe_parameter_structure: .fill 20
516
 
536
 
547
 
567
 
548
 pci_vendor:		.word 0
568
 pci_vendor:		.word 0
549
 pci_device:		.word 0
569
 pci_device:		.word 0
550
-flags:			.word UNDI_FL_STARTED
570
+flags:
571
+	.word ( UNDI_FL_INITIALIZED | UNDI_FL_STARTED | UNDI_FL_KEEP_ALL )
551
 
572
 
552
 	.equ undi_device_size, ( . - undi_device )
573
 	.equ undi_device_size, ( . - undi_device )
553
 
574
 
554
 /*****************************************************************************
575
 /*****************************************************************************
555
  * Run gPXE main code
576
  * Run gPXE main code
556
  *****************************************************************************
577
  *****************************************************************************
557
- */	
578
+ */
579
+	.section ".prefix"
558
 run_gpxe:
580
 run_gpxe:
559
 	/* Install gPXE */
581
 	/* Install gPXE */
560
 	call	install
582
 	call	install
572
 	rep movsb
594
 	rep movsb
573
 #endif
595
 #endif
574
 
596
 
597
+	/* Retrieve PXE %ss:esp */
598
+	movw	pxe_ss,	%di
599
+	movl	pxe_esp, %ebp
600
+
575
 	/* Jump to .text16 segment with %ds pointing to .data16 */
601
 	/* Jump to .text16 segment with %ds pointing to .data16 */
576
 	movw	%bx, %ds
602
 	movw	%bx, %ds
577
 	pushw	%ax
603
 	pushw	%ax
588
 	/* Uninstall gPXE */
614
 	/* Uninstall gPXE */
589
 	call	uninstall
615
 	call	uninstall
590
 
616
 
591
-	/* Boot next device */
617
+	/* Restore PXE stack */
618
+	movw	%di, %ss
619
+	movl	%ebp, %esp
620
+
621
+	/* Check PXE stack magic */
622
+	popl	%eax
623
+	cmpl	$STACK_MAGIC, %eax
624
+	jne	1f
625
+
626
+	/* PXE stack OK: return to caller */
627
+	popw	%ds
628
+	popw	%es
629
+	popw	%fs
630
+	popw	%gs
631
+	popal
632
+	popfl
633
+	xorw	%ax, %ax	/* Return success */
634
+	lret
635
+
636
+1:	/* PXE stack corrupt or removed: use INT 18 */
592
 	int	$0x18
637
 	int	$0x18
593
 	.previous
638
 	.previous

+ 1
- 0
src/include/gpxe/init.h View File

63
 
63
 
64
 #define STARTUP_EARLY	01	/**< Early startup */
64
 #define STARTUP_EARLY	01	/**< Early startup */
65
 #define STARTUP_NORMAL	02	/**< Normal startup */
65
 #define STARTUP_NORMAL	02	/**< Normal startup */
66
+#define STARTUP_LATE	03	/**< Late startup */
66
 
67
 
67
 /** @} */
68
 /** @} */
68
 
69
 

Loading…
Cancel
Save