mirror of
https://github.com/ipxe/ipxe
synced 2025-12-15 00:12:19 +03:00
[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>
This commit is contained in:
committed by
Marty Connor
parent
5efc2fcb60
commit
112a3f2de2
@@ -67,6 +67,7 @@ union u_PXENV_ANY {
|
|||||||
struct s_PXENV_GET_FILE_SIZE get_file_size;
|
struct s_PXENV_GET_FILE_SIZE get_file_size;
|
||||||
struct s_PXENV_FILE_EXEC file_exec;
|
struct s_PXENV_FILE_EXEC file_exec;
|
||||||
struct s_PXENV_FILE_API_CHECK file_api_check;
|
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;
|
typedef union u_PXENV_ANY PXENV_ANY_t;
|
||||||
|
|||||||
@@ -1778,6 +1778,28 @@ extern PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_a
|
|||||||
|
|
||||||
/** @} */ /* pxenv_file_api_check */
|
/** @} */ /* 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 */
|
/** @} */ /* pxe_file_api */
|
||||||
|
|
||||||
/** @defgroup pxe_loader_api PXE Loader API
|
/** @defgroup pxe_loader_api PXE Loader API
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ union pxenv_call {
|
|||||||
PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * );
|
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_exec ) ( struct s_PXENV_FILE_EXEC * );
|
||||||
PXENV_EXIT_t ( * file_api_check ) ( struct s_PXENV_FILE_API_CHECK * );
|
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;
|
pxenv_call.file_api_check = pxenv_file_api_check;
|
||||||
param_len = sizeof ( pxenv_any.file_api_check );
|
param_len = sizeof ( pxenv_any.file_api_check );
|
||||||
break;
|
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:
|
default:
|
||||||
DBG ( "PXENV_UNKNOWN_%hx", opcode );
|
DBG ( "PXENV_UNKNOWN_%hx", opcode );
|
||||||
pxenv_call.unknown = pxenv_unknown;
|
pxenv_call.unknown = pxenv_unknown;
|
||||||
|
|||||||
@@ -12,9 +12,12 @@
|
|||||||
#include <gpxe/posix_io.h>
|
#include <gpxe/posix_io.h>
|
||||||
#include <gpxe/features.h>
|
#include <gpxe/features.h>
|
||||||
#include <pxe.h>
|
#include <pxe.h>
|
||||||
|
#include <realmode.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* 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;
|
return PXENV_EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
segoff_t __data16 ( pxe_exit_hook ) = { 0, 0 };
|
||||||
|
#define pxe_exit_hook __use_data16 ( pxe_exit_hook )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FILE API CHECK
|
* 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->Magic = 0xe9c17b20;
|
||||||
file_api_check->Provider = 0x45585067; /* "gPXE" */
|
file_api_check->Provider = 0x45585067; /* "gPXE" */
|
||||||
file_api_check->APIMask = 0x0000007f; /* Functions e0-e6 */
|
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 */
|
file_api_check->Flags = 0; /* None defined */
|
||||||
return PXENV_EXIT_SUCCESS;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -718,6 +718,13 @@ run_gpxe:
|
|||||||
lret
|
lret
|
||||||
.section ".text16", "ax", @progbits
|
.section ".text16", "ax", @progbits
|
||||||
1:
|
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 */
|
/* Run main program */
|
||||||
pushl $main
|
pushl $main
|
||||||
pushw %cs
|
pushw %cs
|
||||||
@@ -731,7 +738,10 @@ run_gpxe:
|
|||||||
movw %di, %ss
|
movw %di, %ss
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
|
|
||||||
/* Check PXE stack magic */
|
/* Jump to hook if applicable */
|
||||||
|
ljmpw *pxe_exit_hook
|
||||||
|
|
||||||
|
2: /* Check PXE stack magic */
|
||||||
popl %eax
|
popl %eax
|
||||||
cmpl $STACK_MAGIC, %eax
|
cmpl $STACK_MAGIC, %eax
|
||||||
jne 1f
|
jne 1f
|
||||||
|
|||||||
@@ -277,3 +277,36 @@ Provider: Set to 0x45585067 ("gPXE"). Another implementation of this
|
|||||||
APIMask: Bitmask of supported API functions (one bit for each function
|
APIMask: Bitmask of supported API functions (one bit for each function
|
||||||
in the range 00e0h to 00ffh).
|
in the range 00e0h to 00ffh).
|
||||||
Flags: Set to zero, reserved for future use.
|
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.
|
||||||
|
|||||||
Reference in New Issue
Block a user