Browse Source

[pxe] Introduce PXE exit hook for NBP chaining

It might be the case that we wish to chain to an NBP without
being "in the way".  We now implement a hook in our exit path
for gPXE *.*pxe build targets.  The hook is a pointer to a
SEG16:OFF16 which we try to jump to during exit.  By default,
this pointer results in the usual exit path.

We also implement the "pxenv_file_exit_hook" PXE API routine
to allow the user to specify an alternate SEG16:OFF16 to jump
to during exit.

Unfortunately, this additional PXE extension has a cost
in code size.  Fortunately, a look at the size difference
for a gPXE .rom build target shows zero size difference
after compression.

The routine is documented in doc/pxe_extensions as follows:

FILE EXIT HOOK

Op-Code:	PXENV_FILE_EXIT_HOOK (00e7h)

Input:	Far pointer to a t_PXENV_FILE_EXIT_HOOK parameter
		structure that has been initialized by the caller.

Output:	PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be
		returned in AX.  The Status field in the parameter
		structure must be set to one of the values represented
		by the PXENV_STATUS_xxx constants.

Description:Modify the exit path to jump to the specified code.
		Only valid for pxeprefix-based builds.

typedef struct s_PXENV_FILE_EXIT_HOOK {
        PXENV_STATUS_t Status;
        SEGOFF16_t Hook;
} t_PXENV_FILE_EXIT_HOOK;

Set before calling API service:

Hook:	The SEG16:OFF16 of the code to jump to.

Returned from API service:

Status:	See PXENV_STATUS_xxx constants.

Requested-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Shao Miller <shao.miller@yrdsb.edu.on.ca>
Signed-off-by: Marty Connor <mdc@etherboot.org>
tags/v1.0.0-rc1
Shao Miller 15 years ago
parent
commit
112a3f2de2

+ 1
- 0
src/arch/i386/include/pxe.h View File

@@ -67,6 +67,7 @@ union u_PXENV_ANY {
67 67
 	struct s_PXENV_GET_FILE_SIZE		get_file_size;
68 68
 	struct s_PXENV_FILE_EXEC		file_exec;
69 69
 	struct s_PXENV_FILE_API_CHECK		file_api_check;
70
+	struct s_PXENV_FILE_EXIT_HOOK		file_exit_hook;
70 71
 };
71 72
 
72 73
 typedef union u_PXENV_ANY PXENV_ANY_t;

+ 22
- 0
src/arch/i386/include/pxe_api.h View File

@@ -1778,6 +1778,28 @@ extern PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_a
1778 1778
 
1779 1779
 /** @} */ /* pxenv_file_api_check */
1780 1780
 
1781
+/** @defgroup pxenv_file_exit_hook PXENV_FILE_EXIT_HOOK
1782
+ *
1783
+ * FILE EXIT HOOK
1784
+ *
1785
+ * @{
1786
+ */
1787
+
1788
+/** PXE API function code for pxenv_file_exit_hook() */
1789
+#define PXENV_FILE_EXIT_HOOK			0x00e7
1790
+
1791
+/** Parameter block for pxenv_file_exit_hook() */
1792
+struct s_PXENV_FILE_EXIT_HOOK {
1793
+	PXENV_STATUS_t Status;		/**< PXE status code */
1794
+	SEGOFF16_t Hook;		/**< SEG16:OFF16 to jump to */
1795
+} PACKED;
1796
+
1797
+typedef struct s_PXENV_FILE_EXIT_HOOK PXENV_FILE_EXIT_HOOK_t;
1798
+
1799
+extern PXENV_EXIT_t pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK *file_exit_hook );
1800
+
1801
+/** @} */ /* pxenv_file_exit_hook */
1802
+
1781 1803
 /** @} */ /* pxe_file_api */
1782 1804
 
1783 1805
 /** @defgroup pxe_loader_api PXE Loader API

+ 5
- 0
src/arch/i386/interface/pxe/pxe_call.c View File

@@ -104,6 +104,7 @@ union pxenv_call {
104 104
 	PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * );
105 105
 	PXENV_EXIT_t ( * file_exec ) ( struct s_PXENV_FILE_EXEC * );
106 106
 	PXENV_EXIT_t ( * file_api_check ) ( struct s_PXENV_FILE_API_CHECK * );
107
+	PXENV_EXIT_t ( * file_exit_hook ) ( struct s_PXENV_FILE_EXIT_HOOK * );
107 108
 };
108 109
 
109 110
 /**
@@ -310,6 +311,10 @@ __asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) {
310 311
 		pxenv_call.file_api_check = pxenv_file_api_check;
311 312
 		param_len = sizeof ( pxenv_any.file_api_check );
312 313
 		break;
314
+	case PXENV_FILE_EXIT_HOOK:
315
+		pxenv_call.file_exit_hook = pxenv_file_exit_hook;
316
+		param_len = sizeof ( pxenv_any.file_exit_hook );
317
+		break;
313 318
 	default:
314 319
 		DBG ( "PXENV_UNKNOWN_%hx", opcode );
315 320
 		pxenv_call.unknown = pxenv_unknown;

+ 40
- 0
src/arch/i386/interface/pxe/pxe_file.c View File

@@ -12,9 +12,12 @@
12 12
 #include <gpxe/posix_io.h>
13 13
 #include <gpxe/features.h>
14 14
 #include <pxe.h>
15
+#include <realmode.h>
15 16
 
16 17
 /*
17 18
  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
19
+ * Portions (C) 2010 Shao Miller <shao.miller@yrdsb.edu.on.ca>.
20
+ *              [PXE exit hook logic]
18 21
  *
19 22
  * This program is free software; you can redistribute it and/or
20 23
  * modify it under the terms of the GNU General Public License as
@@ -230,6 +233,9 @@ PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) {
230 233
 	return PXENV_EXIT_SUCCESS;
231 234
 }
232 235
 
236
+segoff_t __data16 ( pxe_exit_hook ) = { 0, 0 };
237
+#define pxe_exit_hook __use_data16 ( pxe_exit_hook )
238
+
233 239
 /**
234 240
  * FILE API CHECK
235 241
  *
@@ -260,7 +266,41 @@ PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_chec
260 266
 		file_api_check->Magic    = 0xe9c17b20;
261 267
 		file_api_check->Provider = 0x45585067; /* "gPXE" */
262 268
 		file_api_check->APIMask  = 0x0000007f; /* Functions e0-e6 */
269
+		/* Check to see if we have a PXE exit hook */
270
+		if ( pxe_exit_hook.segment | pxe_exit_hook.offset )
271
+			/* Function e7, also */
272
+			file_api_check->APIMask |= 0x00000080;
263 273
 		file_api_check->Flags    = 0;	       /* None defined */
264 274
 		return PXENV_EXIT_SUCCESS;
265 275
 	}
266 276
 }
277
+
278
+/**
279
+ * FILE EXIT HOOK
280
+ *
281
+ * @v file_exit_hook			Pointer to a struct
282
+ *					s_PXENV_FILE_EXIT_HOOK
283
+ * @v s_PXENV_FILE_EXIT_HOOK::Hook	SEG16:OFF16 to jump to
284
+ * @ret #PXENV_EXIT_SUCCESS		Successfully set hook
285
+ * @ret #PXENV_EXIT_FAILURE		We're not an NBP build
286
+ * @ret s_PXENV_FILE_EXIT_HOOK::Status	PXE status code
287
+ *
288
+ */
289
+PXENV_EXIT_t pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK
290
+					*file_exit_hook ) {
291
+	DBG ( "PXENV_FILE_EXIT_HOOK" );
292
+
293
+	/* Check to see if we have a PXE exit hook */
294
+	if ( pxe_exit_hook.segment | pxe_exit_hook.offset ) {
295
+		/* We'll jump to the specified SEG16:OFF16 during exit */
296
+		pxe_exit_hook.segment = file_exit_hook->Hook.segment;
297
+		pxe_exit_hook.offset = file_exit_hook->Hook.offset;
298
+		file_exit_hook->Status = PXENV_STATUS_SUCCESS;
299
+		return PXENV_EXIT_SUCCESS;
300
+	}
301
+
302
+	DBG ( " not NBP" );
303
+	file_exit_hook->Status = PXENV_STATUS_UNSUPPORTED;
304
+	return PXENV_EXIT_FAILURE;
305
+}
306
+

+ 11
- 1
src/arch/i386/prefix/pxeprefix.S View File

@@ -718,6 +718,13 @@ run_gpxe:
718 718
 	lret
719 719
 	.section ".text16", "ax", @progbits
720 720
 1:
721
+	/* Update the exit hook */
722
+	movw	%cs,pxe_exit_hook+2
723
+	push	%ax
724
+	mov	$2f,%ax
725
+	mov	%ax,pxe_exit_hook
726
+	pop	%ax
727
+
721 728
 	/* Run main program */
722 729
 	pushl	$main
723 730
 	pushw	%cs
@@ -731,7 +738,10 @@ run_gpxe:
731 738
 	movw	%di, %ss
732 739
 	movl	%ebp, %esp
733 740
 
734
-	/* Check PXE stack magic */
741
+	/* Jump to hook if applicable */
742
+	ljmpw	*pxe_exit_hook
743
+
744
+2:	/* Check PXE stack magic */
735 745
 	popl	%eax
736 746
 	cmpl	$STACK_MAGIC, %eax
737 747
 	jne	1f

+ 33
- 0
src/doc/pxe_extensions View File

@@ -277,3 +277,36 @@ Provider:	Set to 0x45585067 ("gPXE").  Another implementation of this
277 277
 APIMask:	Bitmask of supported API functions (one bit for each function
278 278
 		in the range 00e0h to 00ffh).
279 279
 Flags:		Set to zero, reserved for future use.
280
+
281
+
282
+
283
+
284
+FILE EXIT HOOK
285
+
286
+Op-Code:	PXENV_FILE_EXIT_HOOK (00e7h)
287
+
288
+Input:		Far pointer to a t_PXENV_FILE_EXIT_HOOK parameter
289
+		structure that has been initialized by the caller.
290
+
291
+Output:		PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be
292
+		returned in AX.  The Status field in the parameter
293
+		structure must be set to one of the values represented
294
+		by the PXENV_STATUS_xxx constants.
295
+
296
+Description:	Modify the exit path to jump to the specified code.
297
+		Only valid for pxeprefix-based builds.
298
+
299
+typedef struct s_PXENV_FILE_EXIT_HOOK {
300
+        PXENV_STATUS_t Status;
301
+        SEGOFF16_t Hook;
302
+} t_PXENV_FILE_EXIT_HOOK;
303
+
304
+
305
+Set before calling API service:
306
+
307
+Hook:		The SEG16:OFF16 of the code to jump to.
308
+
309
+
310
+Returned from API service:
311
+
312
+Status:		See PXENV_STATUS_xxx constants.

Loading…
Cancel
Save