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
 	struct s_PXENV_GET_FILE_SIZE		get_file_size;
67
 	struct s_PXENV_GET_FILE_SIZE		get_file_size;
68
 	struct s_PXENV_FILE_EXEC		file_exec;
68
 	struct s_PXENV_FILE_EXEC		file_exec;
69
 	struct s_PXENV_FILE_API_CHECK		file_api_check;
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
 typedef union u_PXENV_ANY PXENV_ANY_t;
73
 typedef union u_PXENV_ANY PXENV_ANY_t;

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

1778
 
1778
 
1779
 /** @} */ /* pxenv_file_api_check */
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
 /** @} */ /* pxe_file_api */
1803
 /** @} */ /* pxe_file_api */
1782
 
1804
 
1783
 /** @defgroup pxe_loader_api PXE Loader API
1805
 /** @defgroup pxe_loader_api PXE Loader API

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

104
 	PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * );
104
 	PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * );
105
 	PXENV_EXIT_t ( * file_exec ) ( struct s_PXENV_FILE_EXEC * );
105
 	PXENV_EXIT_t ( * file_exec ) ( struct s_PXENV_FILE_EXEC * );
106
 	PXENV_EXIT_t ( * file_api_check ) ( struct s_PXENV_FILE_API_CHECK * );
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
 		pxenv_call.file_api_check = pxenv_file_api_check;
311
 		pxenv_call.file_api_check = pxenv_file_api_check;
311
 		param_len = sizeof ( pxenv_any.file_api_check );
312
 		param_len = sizeof ( pxenv_any.file_api_check );
312
 		break;
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
 	default:
318
 	default:
314
 		DBG ( "PXENV_UNKNOWN_%hx", opcode );
319
 		DBG ( "PXENV_UNKNOWN_%hx", opcode );
315
 		pxenv_call.unknown = pxenv_unknown;
320
 		pxenv_call.unknown = pxenv_unknown;

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

12
 #include <gpxe/posix_io.h>
12
 #include <gpxe/posix_io.h>
13
 #include <gpxe/features.h>
13
 #include <gpxe/features.h>
14
 #include <pxe.h>
14
 #include <pxe.h>
15
+#include <realmode.h>
15
 
16
 
16
 /*
17
 /*
17
  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
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
  * This program is free software; you can redistribute it and/or
22
  * This program is free software; you can redistribute it and/or
20
  * modify it under the terms of the GNU General Public License as
23
  * modify it under the terms of the GNU General Public License as
230
 	return PXENV_EXIT_SUCCESS;
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
  * FILE API CHECK
240
  * FILE API CHECK
235
  *
241
  *
260
 		file_api_check->Magic    = 0xe9c17b20;
266
 		file_api_check->Magic    = 0xe9c17b20;
261
 		file_api_check->Provider = 0x45585067; /* "gPXE" */
267
 		file_api_check->Provider = 0x45585067; /* "gPXE" */
262
 		file_api_check->APIMask  = 0x0000007f; /* Functions e0-e6 */
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
 		file_api_check->Flags    = 0;	       /* None defined */
273
 		file_api_check->Flags    = 0;	       /* None defined */
264
 		return PXENV_EXIT_SUCCESS;
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
 	lret
718
 	lret
719
 	.section ".text16", "ax", @progbits
719
 	.section ".text16", "ax", @progbits
720
 1:
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
 	/* Run main program */
728
 	/* Run main program */
722
 	pushl	$main
729
 	pushl	$main
723
 	pushw	%cs
730
 	pushw	%cs
731
 	movw	%di, %ss
738
 	movw	%di, %ss
732
 	movl	%ebp, %esp
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
 	popl	%eax
745
 	popl	%eax
736
 	cmpl	$STACK_MAGIC, %eax
746
 	cmpl	$STACK_MAGIC, %eax
737
 	jne	1f
747
 	jne	1f

+ 33
- 0
src/doc/pxe_extensions View File

277
 APIMask:	Bitmask of supported API functions (one bit for each function
277
 APIMask:	Bitmask of supported API functions (one bit for each function
278
 		in the range 00e0h to 00ffh).
278
 		in the range 00e0h to 00ffh).
279
 Flags:		Set to zero, reserved for future use.
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