summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/i386/Makefile.pcbios1
-rw-r--r--src/arch/i386/include/pxe_api.h6
-rw-r--r--src/arch/i386/interface/pxe/pxe_exit_hook.c60
-rw-r--r--src/arch/i386/interface/pxe/pxe_file.c70
-rw-r--r--src/arch/i386/prefix/kkkpxeprefix.S19
-rw-r--r--src/arch/i386/prefix/pxeprefix.S15
6 files changed, 118 insertions, 53 deletions
diff --git a/src/arch/i386/Makefile.pcbios b/src/arch/i386/Makefile.pcbios
index 258c5d7d8..e1b226f5a 100644
--- a/src/arch/i386/Makefile.pcbios
+++ b/src/arch/i386/Makefile.pcbios
@@ -19,6 +19,7 @@ MEDIA += mrom
MEDIA += pxe
MEDIA += kpxe
MEDIA += kkpxe
+MEDIA += kkkpxe
MEDIA += lkrn
MEDIA += dsk
MEDIA += nbi
diff --git a/src/arch/i386/include/pxe_api.h b/src/arch/i386/include/pxe_api.h
index f40138467..d01c262d2 100644
--- a/src/arch/i386/include/pxe_api.h
+++ b/src/arch/i386/include/pxe_api.h
@@ -1511,6 +1511,12 @@ typedef struct s_PXENV_UNDI_ISR PXENV_UNDI_ISR_t;
* @{
*/
+/** Minimum possible opcode used within PXE FILE API */
+#define PXENV_FILE_MIN 0x00e0
+
+/** Minimum possible opcode used within PXE FILE API */
+#define PXENV_FILE_MAX 0x00ef
+
/** @defgroup pxenv_file_open PXENV_FILE_OPEN
*
* FILE OPEN
diff --git a/src/arch/i386/interface/pxe/pxe_exit_hook.c b/src/arch/i386/interface/pxe/pxe_exit_hook.c
new file mode 100644
index 000000000..507229d86
--- /dev/null
+++ b/src/arch/i386/interface/pxe/pxe_exit_hook.c
@@ -0,0 +1,60 @@
+/** @file
+ *
+ * PXE exit hook
+ *
+ */
+
+/*
+ * Copyright (C) 2010 Shao Miller <shao.miller@yrdsb.edu.on.ca>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <realmode.h>
+#include <pxe.h>
+
+/** PXE exit hook */
+extern segoff_t __data16 ( pxe_exit_hook );
+#define pxe_exit_hook __use_data16 ( pxe_exit_hook )
+
+/**
+ * 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
+ *
+ */
+static PXENV_EXIT_t
+pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK *file_exit_hook ) {
+ DBG ( "PXENV_FILE_EXIT_HOOK" );
+
+ /* 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;
+}
+
+/** PXE file API */
+struct pxe_api_call pxe_file_api_exit_hook __pxe_api_call =
+ PXE_API_CALL ( PXENV_FILE_EXIT_HOOK, pxenv_file_exit_hook,
+ struct s_PXENV_FILE_EXIT_HOOK );
diff --git a/src/arch/i386/interface/pxe/pxe_file.c b/src/arch/i386/interface/pxe/pxe_file.c
index de1cd9be4..7daaf919a 100644
--- a/src/arch/i386/interface/pxe/pxe_file.c
+++ b/src/arch/i386/interface/pxe/pxe_file.c
@@ -16,8 +16,6 @@
/*
* 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
@@ -234,9 +232,6 @@ static 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
*
@@ -253,57 +248,40 @@ segoff_t __data16 ( pxe_exit_hook ) = { 0, 0 };
*/
static PXENV_EXIT_t
pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_check ) {
+ struct pxe_api_call *call;
+ unsigned int mask = 0;
+ unsigned int offset;
+
DBG ( "PXENV_FILE_API_CHECK" );
+ /* Check for magic value */
if ( file_api_check->Magic != 0x91d447b2 ) {
file_api_check->Status = PXENV_STATUS_BAD_FUNC;
return PXENV_EXIT_FAILURE;
- } else if ( file_api_check->Size <
- sizeof(struct s_PXENV_FILE_API_CHECK) ) {
+ }
+
+ /* Check for required parameter size */
+ if ( file_api_check->Size < sizeof ( *file_api_check ) ) {
file_api_check->Status = PXENV_STATUS_OUT_OF_RESOURCES;
return PXENV_EXIT_FAILURE;
- } else {
- file_api_check->Status = PXENV_STATUS_SUCCESS;
- file_api_check->Size = sizeof(struct s_PXENV_FILE_API_CHECK);
- file_api_check->Magic = 0xe9c17b20;
- file_api_check->Provider = 0x45585067; /* "iPXE" */
- 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
- *
- */
-static 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;
+ /* Determine supported calls */
+ for_each_table_entry ( call, PXE_API_CALLS ) {
+ offset = ( call->opcode - PXENV_FILE_MIN );
+ if ( offset <= ( PXENV_FILE_MAX - PXENV_FILE_MIN ) )
+ mask |= ( 1 << offset );
}
- DBG ( " not NBP" );
- file_exit_hook->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
+ /* Fill in parameters */
+ file_api_check->Size = sizeof ( *file_api_check );
+ file_api_check->Magic = 0xe9c17b20;
+ file_api_check->Provider = 0x45585067; /* "iPXE" */
+ file_api_check->APIMask = mask;
+ file_api_check->Flags = 0; /* None defined */
+
+ file_api_check->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
}
/** PXE file API */
@@ -322,6 +300,4 @@ struct pxe_api_call pxe_file_api[] __pxe_api_call = {
struct s_PXENV_FILE_EXEC ),
PXE_API_CALL ( PXENV_FILE_API_CHECK, pxenv_file_api_check,
struct s_PXENV_FILE_API_CHECK ),
- PXE_API_CALL ( PXENV_FILE_EXIT_HOOK, pxenv_file_exit_hook,
- struct s_PXENV_FILE_EXIT_HOOK ),
};
diff --git a/src/arch/i386/prefix/kkkpxeprefix.S b/src/arch/i386/prefix/kkkpxeprefix.S
new file mode 100644
index 000000000..27ed231e7
--- /dev/null
+++ b/src/arch/i386/prefix/kkkpxeprefix.S
@@ -0,0 +1,19 @@
+/*****************************************************************************
+ * PXE prefix that keeps the whole PXE stack present and provides an exit hook
+ *
+ * This prefix is essentially intended solely for the case of ipxelinux.0
+ *****************************************************************************
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+/* Since we have the whole stack, we can use cached DHCP information */
+REQUIRE_OBJECT ( pxeparent_dhcp )
+
+/* Provide the PXENV_FILE_EXIT_HOOK API call */
+REQUIRE_OBJECT ( pxe_exit_hook )
+
+#define PXELOADER_KEEP_UNDI
+#define PXELOADER_KEEP_PXE
+#define _pxe_start _kkkpxe_start
+#include "pxeprefix.S"
diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S
index b7468cdf0..f59e347ad 100644
--- a/src/arch/i386/prefix/pxeprefix.S
+++ b/src/arch/i386/prefix/pxeprefix.S
@@ -721,11 +721,7 @@ run_ipxe:
.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
+ movw %cs, ( pxe_exit_hook + 2 )
/* Run main program */
pushl $main
@@ -743,7 +739,14 @@ run_ipxe:
/* Jump to hook if applicable */
ljmpw *pxe_exit_hook
-2: /* Check PXE stack magic */
+ .section ".data16", "aw", @progbits
+ .globl pxe_exit_hook
+pxe_exit_hook:
+ .word exit_ipxe, 0
+ .previous
+
+exit_ipxe:
+ /* Check PXE stack magic */
popl %eax
cmpl $STACK_MAGIC, %eax
jne 1f