Skip to content

Commit

Permalink
[pxe] Introduce PXE exit hook for NBP chaining
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Shao Miller authored and Marty Connor committed Jan 24, 2010
1 parent 5efc2fc commit 112a3f2
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/arch/i386/include/pxe.h
Expand Up @@ -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;
Expand Down
22 changes: 22 additions & 0 deletions src/arch/i386/include/pxe_api.h
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/arch/i386/interface/pxe/pxe_call.c
Expand Up @@ -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 * );
};

/**
Expand Down Expand Up @@ -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;
Expand Down
40 changes: 40 additions & 0 deletions src/arch/i386/interface/pxe/pxe_file.c
Expand Up @@ -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
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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;
}

12 changes: 11 additions & 1 deletion src/arch/i386/prefix/pxeprefix.S
Expand Up @@ -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
Expand All @@ -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
Expand Down
33 changes: 33 additions & 0 deletions src/doc/pxe_extensions
Expand Up @@ -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.

0 comments on commit 112a3f2

Please sign in to comment.