summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShao Miller2010-01-24 04:12:27 +0100
committerMarty Connor2010-01-24 13:54:42 +0100
commit112a3f2de281a2afb23ced2082d555720de7c9b0 (patch)
tree50f91813ae58ed102fa4b7a47bd9f90f9d99732c
parent[dhcp] Keep multiple DHCP offers received, and use them intelligently (diff)
downloadipxe-112a3f2de281a2afb23ced2082d555720de7c9b0.tar.gz
ipxe-112a3f2de281a2afb23ced2082d555720de7c9b0.tar.xz
ipxe-112a3f2de281a2afb23ced2082d555720de7c9b0.zip
[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>
-rw-r--r--src/arch/i386/include/pxe.h1
-rw-r--r--src/arch/i386/include/pxe_api.h22
-rw-r--r--src/arch/i386/interface/pxe/pxe_call.c5
-rw-r--r--src/arch/i386/interface/pxe/pxe_file.c40
-rw-r--r--src/arch/i386/prefix/pxeprefix.S12
-rw-r--r--src/doc/pxe_extensions33
6 files changed, 112 insertions, 1 deletions
diff --git a/src/arch/i386/include/pxe.h b/src/arch/i386/include/pxe.h
index b0cabef0..041ee7ba 100644
--- a/src/arch/i386/include/pxe.h
+++ b/src/arch/i386/include/pxe.h
@@ -67,6 +67,7 @@ union u_PXENV_ANY {
struct s_PXENV_GET_FILE_SIZE get_file_size;
struct s_PXENV_FILE_EXEC file_exec;
struct s_PXENV_FILE_API_CHECK file_api_check;
+ struct s_PXENV_FILE_EXIT_HOOK file_exit_hook;
};
typedef union u_PXENV_ANY PXENV_ANY_t;
diff --git a/src/arch/i386/include/pxe_api.h b/src/arch/i386/include/pxe_api.h
index ba0dbdc0..92f046f7 100644
--- a/src/arch/i386/include/pxe_api.h
+++ b/src/arch/i386/include/pxe_api.h
@@ -1778,6 +1778,28 @@ extern PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_a
/** @} */ /* pxenv_file_api_check */
+/** @defgroup pxenv_file_exit_hook PXENV_FILE_EXIT_HOOK
+ *
+ * FILE EXIT HOOK
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_exit_hook() */
+#define PXENV_FILE_EXIT_HOOK 0x00e7
+
+/** Parameter block for pxenv_file_exit_hook() */
+struct s_PXENV_FILE_EXIT_HOOK {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ SEGOFF16_t Hook; /**< SEG16:OFF16 to jump to */
+} PACKED;
+
+typedef struct s_PXENV_FILE_EXIT_HOOK PXENV_FILE_EXIT_HOOK_t;
+
+extern PXENV_EXIT_t pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK *file_exit_hook );
+
+/** @} */ /* pxenv_file_exit_hook */
+
/** @} */ /* pxe_file_api */
/** @defgroup pxe_loader_api PXE Loader API
diff --git a/src/arch/i386/interface/pxe/pxe_call.c b/src/arch/i386/interface/pxe/pxe_call.c
index a50d6437..66a9b1e2 100644
--- a/src/arch/i386/interface/pxe/pxe_call.c
+++ b/src/arch/i386/interface/pxe/pxe_call.c
@@ -104,6 +104,7 @@ union pxenv_call {
PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * );
PXENV_EXIT_t ( * file_exec ) ( struct s_PXENV_FILE_EXEC * );
PXENV_EXIT_t ( * file_api_check ) ( struct s_PXENV_FILE_API_CHECK * );
+ PXENV_EXIT_t ( * file_exit_hook ) ( struct s_PXENV_FILE_EXIT_HOOK * );
};
/**
@@ -310,6 +311,10 @@ __asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) {
pxenv_call.file_api_check = pxenv_file_api_check;
param_len = sizeof ( pxenv_any.file_api_check );
break;
+ case PXENV_FILE_EXIT_HOOK:
+ pxenv_call.file_exit_hook = pxenv_file_exit_hook;
+ param_len = sizeof ( pxenv_any.file_exit_hook );
+ break;
default:
DBG ( "PXENV_UNKNOWN_%hx", opcode );
pxenv_call.unknown = pxenv_unknown;
diff --git a/src/arch/i386/interface/pxe/pxe_file.c b/src/arch/i386/interface/pxe/pxe_file.c
index 552a1a12..8d832123 100644
--- a/src/arch/i386/interface/pxe/pxe_file.c
+++ b/src/arch/i386/interface/pxe/pxe_file.c
@@ -12,9 +12,12 @@
#include <gpxe/posix_io.h>
#include <gpxe/features.h>
#include <pxe.h>
+#include <realmode.h>
/*
* Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ * Portions (C) 2010 Shao Miller <shao.miller@yrdsb.edu.on.ca>.
+ * [PXE exit hook logic]
*
* This program is free software; you can redistribute it and/or
* 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 ) {
return PXENV_EXIT_SUCCESS;
}
+segoff_t __data16 ( pxe_exit_hook ) = { 0, 0 };
+#define pxe_exit_hook __use_data16 ( pxe_exit_hook )
+
/**
* FILE API CHECK
*
@@ -260,7 +266,41 @@ PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_chec
file_api_check->Magic = 0xe9c17b20;
file_api_check->Provider = 0x45585067; /* "gPXE" */
file_api_check->APIMask = 0x0000007f; /* Functions e0-e6 */
+ /* Check to see if we have a PXE exit hook */
+ if ( pxe_exit_hook.segment | pxe_exit_hook.offset )
+ /* Function e7, also */
+ file_api_check->APIMask |= 0x00000080;
file_api_check->Flags = 0; /* None defined */
return PXENV_EXIT_SUCCESS;
}
}
+
+/**
+ * FILE EXIT HOOK
+ *
+ * @v file_exit_hook Pointer to a struct
+ * s_PXENV_FILE_EXIT_HOOK
+ * @v s_PXENV_FILE_EXIT_HOOK::Hook SEG16:OFF16 to jump to
+ * @ret #PXENV_EXIT_SUCCESS Successfully set hook
+ * @ret #PXENV_EXIT_FAILURE We're not an NBP build
+ * @ret s_PXENV_FILE_EXIT_HOOK::Status PXE status code
+ *
+ */
+PXENV_EXIT_t pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK
+ *file_exit_hook ) {
+ DBG ( "PXENV_FILE_EXIT_HOOK" );
+
+ /* Check to see if we have a PXE exit hook */
+ if ( pxe_exit_hook.segment | pxe_exit_hook.offset ) {
+ /* We'll jump to the specified SEG16:OFF16 during exit */
+ pxe_exit_hook.segment = file_exit_hook->Hook.segment;
+ pxe_exit_hook.offset = file_exit_hook->Hook.offset;
+ file_exit_hook->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+ }
+
+ DBG ( " not NBP" );
+ file_exit_hook->Status = PXENV_STATUS_UNSUPPORTED;
+ return PXENV_EXIT_FAILURE;
+}
+
diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S
index b541e4bb..e728c482 100644
--- a/src/arch/i386/prefix/pxeprefix.S
+++ b/src/arch/i386/prefix/pxeprefix.S
@@ -718,6 +718,13 @@ run_gpxe:
lret
.section ".text16", "ax", @progbits
1:
+ /* Update the exit hook */
+ movw %cs,pxe_exit_hook+2
+ push %ax
+ mov $2f,%ax
+ mov %ax,pxe_exit_hook
+ pop %ax
+
/* Run main program */
pushl $main
pushw %cs
@@ -731,7 +738,10 @@ run_gpxe:
movw %di, %ss
movl %ebp, %esp
- /* Check PXE stack magic */
+ /* Jump to hook if applicable */
+ ljmpw *pxe_exit_hook
+
+2: /* Check PXE stack magic */
popl %eax
cmpl $STACK_MAGIC, %eax
jne 1f
diff --git a/src/doc/pxe_extensions b/src/doc/pxe_extensions
index 92269cfc..8ff14a95 100644
--- a/src/doc/pxe_extensions
+++ b/src/doc/pxe_extensions
@@ -277,3 +277,36 @@ Provider: Set to 0x45585067 ("gPXE"). Another implementation of this
APIMask: Bitmask of supported API functions (one bit for each function
in the range 00e0h to 00ffh).
Flags: Set to zero, reserved for future use.
+
+
+
+
+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.