diff options
author | Shao Miller <shao.miller@yrdsb.edu.on.ca> | 2010-01-23 22:12:27 -0500 |
---|---|---|
committer | Marty Connor <mdc@etherboot.org> | 2010-01-24 07:54:42 -0500 |
commit | 112a3f2de281a2afb23ced2082d555720de7c9b0 (patch) | |
tree | 50f91813ae58ed102fa4b7a47bd9f90f9d99732c | |
parent | 5efc2fcb602864e82de2cd7414e3828f589034e5 (diff) | |
download | ipxe-112a3f2de281a2afb23ced2082d555720de7c9b0.tar.gz |
[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.h | 1 | ||||
-rw-r--r-- | src/arch/i386/include/pxe_api.h | 22 | ||||
-rw-r--r-- | src/arch/i386/interface/pxe/pxe_call.c | 5 | ||||
-rw-r--r-- | src/arch/i386/interface/pxe/pxe_file.c | 40 | ||||
-rw-r--r-- | src/arch/i386/prefix/pxeprefix.S | 12 | ||||
-rw-r--r-- | src/doc/pxe_extensions | 33 |
6 files changed, 112 insertions, 1 deletions
diff --git a/src/arch/i386/include/pxe.h b/src/arch/i386/include/pxe.h index b0cabef0d..041ee7bab 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 ba0dbdc0a..92f046f79 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 a50d6437e..66a9b1e21 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 552a1a128..8d832123c 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 b541e4bb5..e728c4829 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 92269cfc5..8ff14a95b 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. |