summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/arch/i386/interface/pxe/pxe_call.c5
-rw-r--r--src/include/pxe.h1
-rw-r--r--src/include/pxe_api.h22
-rw-r--r--src/interface/pxe/pxe_file.c40
4 files changed, 67 insertions, 1 deletions
diff --git a/src/arch/i386/interface/pxe/pxe_call.c b/src/arch/i386/interface/pxe/pxe_call.c
index 8f1dd0a2..b9c21ce5 100644
--- a/src/arch/i386/interface/pxe/pxe_call.c
+++ b/src/arch/i386/interface/pxe/pxe_call.c
@@ -96,6 +96,7 @@ union pxenv_call {
PXENV_EXIT_t ( * file_select ) ( struct s_PXENV_FILE_SELECT * );
PXENV_EXIT_t ( * file_read ) ( struct s_PXENV_FILE_READ * );
PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * );
+ PXENV_EXIT_t ( * file_exec ) ( struct s_PXENV_FILE_EXEC * );
};
/**
@@ -294,6 +295,10 @@ __cdecl void pxe_api_call ( struct i386_all_regs *ix86 ) {
pxenv_call.get_file_size = pxenv_get_file_size;
param_len = sizeof ( pxenv_any.get_file_size );
break;
+ case PXENV_FILE_EXEC:
+ pxenv_call.file_exec = pxenv_file_exec;
+ param_len = sizeof ( pxenv_any.file_exec );
+ break;
default:
DBG ( "PXENV_UNKNOWN_%hx", opcode );
pxenv_call.unknown = pxenv_unknown;
diff --git a/src/include/pxe.h b/src/include/pxe.h
index f17d8f77..8b3ca14c 100644
--- a/src/include/pxe.h
+++ b/src/include/pxe.h
@@ -63,6 +63,7 @@ union u_PXENV_ANY {
struct s_PXENV_FILE_SELECT file_select;
struct s_PXENV_FILE_READ file_read;
struct s_PXENV_GET_FILE_SIZE get_file_size;
+ struct s_PXENV_FILE_EXEC file_exec;
};
typedef union u_PXENV_ANY PXENV_ANY_t;
diff --git a/src/include/pxe_api.h b/src/include/pxe_api.h
index 8dc1607a..53708ed4 100644
--- a/src/include/pxe_api.h
+++ b/src/include/pxe_api.h
@@ -1684,6 +1684,28 @@ extern PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE
/** @} */ /* pxenv_get_file_size */
+/** @defgroup pxenv_file_exec PXENV_FILE_EXEC
+ *
+ * FILE EXEC
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_exec() */
+#define PXENV_FILE_EXEC 0x00e5
+
+/** Parameter block for pxenv_file_exec() */
+struct s_PXENV_FILE_EXEC {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ SEGOFF16_t Command; /**< Command to execute */
+} PACKED;
+
+typedef struct s_PXENV_FILE_EXEC PXENV_FILE_EXEC_t;
+
+extern PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec );
+
+/** @} */ /* pxenv_file_exec */
+
/** @} */ /* pxe_file_api */
/** @defgroup pxe_loader_api PXE Loader API
diff --git a/src/interface/pxe/pxe_file.c b/src/interface/pxe/pxe_file.c
index 01dac8f7..718f5e38 100644
--- a/src/interface/pxe/pxe_file.c
+++ b/src/interface/pxe/pxe_file.c
@@ -31,7 +31,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 1 );
+FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 2 );
/**
* FILE OPEN
@@ -189,3 +189,41 @@ PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE
get_file_size->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
}
+
+/**
+ * FILE EXEC
+ *
+ * @v file_exec Pointer to a struct s_PXENV_FILE_EXEC
+ * @v s_PXENV_FILE_EXEC::Command Command to execute
+ * @ret #PXENV_EXIT_SUCCESS Command was executed successfully
+ * @ret #PXENV_EXIT_FAILURE Command was not executed successfully
+ * @ret s_PXENV_FILE_EXEC::Status PXE status code
+ *
+ */
+PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) {
+ userptr_t command;
+ size_t command_len;
+ int rc;
+
+ DBG ( "PXENV_FILE_EXEC" );
+
+ /* Copy name from external program, and exec it */
+ command = real_to_user ( file_exec->Command.segment,
+ file_exec->Command.offset );
+ command_len = strlen_user ( command, 0 );
+ {
+ char command_string[ command_len + 1 ];
+
+ copy_from_user ( command_string, command, 0,
+ sizeof ( command_string ) );
+ DBG ( " %s", command_string );
+
+ if ( ( rc = system ( command_string ) ) != 0 ) {
+ file_exec->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+ }
+
+ file_exec->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+}