Add PXE FILE API.
authorMichael Brown <mcb30@etherboot.org>
Sat, 4 Aug 2007 00:23:37 +0000 (01:23 +0100)
committerMichael Brown <mcb30@etherboot.org>
Sat, 4 Aug 2007 00:23:37 +0000 (01:23 +0100)
src/arch/i386/interface/pxe/pxe_call.c
src/include/pxe.h
src/include/pxe_api.h
src/interface/pxe/pxe_file.c [new file with mode: 0644]

index 1c1b506..8f1dd0a 100644 (file)
@@ -91,6 +91,11 @@ union pxenv_call {
                        ( struct s_PXENV_UNDI_GET_IFACE_INFO * );
        PXENV_EXIT_t ( * undi_get_state ) ( struct s_PXENV_UNDI_GET_STATE * );
        PXENV_EXIT_t ( * undi_isr ) ( struct s_PXENV_UNDI_ISR * );
+       PXENV_EXIT_t ( * file_open ) ( struct s_PXENV_FILE_OPEN * );
+       PXENV_EXIT_t ( * file_close ) ( struct s_PXENV_FILE_CLOSE * );
+       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 * );
 };
 
 /**
@@ -269,6 +274,26 @@ __cdecl void pxe_api_call ( struct i386_all_regs *ix86 ) {
                pxenv_call.undi_isr = pxenv_undi_isr;
                param_len = sizeof ( pxenv_any.undi_isr );
                break;
+       case PXENV_FILE_OPEN:
+               pxenv_call.file_open = pxenv_file_open;
+               param_len = sizeof ( pxenv_any.file_open );
+               break;
+       case PXENV_FILE_CLOSE:
+               pxenv_call.file_close = pxenv_file_close;
+               param_len = sizeof ( pxenv_any.file_close );
+               break;
+       case PXENV_FILE_SELECT:
+               pxenv_call.file_select = pxenv_file_select;
+               param_len = sizeof ( pxenv_any.file_select );
+               break;
+       case PXENV_FILE_READ:
+               pxenv_call.file_read = pxenv_file_read;
+               param_len = sizeof ( pxenv_any.file_read );
+               break;
+       case PXENV_GET_FILE_SIZE:
+               pxenv_call.get_file_size = pxenv_get_file_size;
+               param_len = sizeof ( pxenv_any.get_file_size );
+               break;
        default:
                DBG ( "PXENV_UNKNOWN_%hx", opcode );
                pxenv_call.unknown = pxenv_unknown;
index 301bb10..ecb664d 100644 (file)
@@ -58,6 +58,11 @@ union u_PXENV_ANY {
        struct s_PXENV_UNDI_GET_IFACE_INFO      undi_get_iface_info;
        struct s_PXENV_UNDI_GET_STATE           undi_get_state;
        struct s_PXENV_UNDI_ISR                 undi_isr;
+       struct s_PXENV_FILE_OPEN                file_open;
+       struct s_PXENV_FILE_CLOSE               file_close;
+       struct s_PXENV_FILE_SELECT              file_select;
+       struct s_PXENV_FILE_READ                file_read;
+       struct s_PXENV_GET_FILE_SIZE            get_file_size;
 };
 
 typedef union u_PXENV_ANY PXENV_ANY_t;
index e644132..8dc1607 100644 (file)
@@ -1555,6 +1555,137 @@ extern PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr );
 
 /** @} */ /* pxe_undi_api */
 
+/** @defgroup pxe_file_api PXE FILE API
+ *
+ * POSIX-like file operations
+ *
+ * @{
+ */
+
+/** @defgroup pxenv_file_open PXENV_FILE_OPEN
+ *
+ * FILE OPEN
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_open() */
+#define PXENV_FILE_OPEN                        0x00e0
+
+/** Parameter block for pxenv_file_open() */
+struct s_PXENV_FILE_OPEN {
+       PXENV_STATUS_t Status;          /**< PXE status code */
+       UINT16_t FileHandle;            /**< File handle */
+       SEGOFF16_t FileName;            /**< File URL */
+       UINT32_t Reserved;              /**< Reserved */
+} PACKED;
+
+typedef struct s_PXENV_FILE_OPEN PXENV_FILE_OPEN_t;
+
+extern PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open );
+
+/** @} */ /* pxenv_file_open */
+
+/** @defgroup pxenv_file_close PXENV_FILE_CLOSE
+ *
+ * FILE CLOSE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_close() */
+#define PXENV_FILE_CLOSE               0x00e1
+
+/** Parameter block for pxenv_file_close() */
+struct s_PXENV_FILE_CLOSE {
+       PXENV_STATUS_t Status;          /**< PXE status code */
+       UINT16_t FileHandle;            /**< File handle */
+} PACKED;
+
+typedef struct s_PXENV_FILE_CLOSE PXENV_FILE_CLOSE_t;
+
+extern PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE
+                                      *file_close );
+
+/** @} */ /* pxenv_file_close */
+
+/** @defgroup pxenv_file_select PXENV_FILE_SELECT
+ *
+ * FILE SELECT
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_select() */
+#define PXENV_FILE_SELECT              0x00e2
+
+/** File is ready for reading */
+#define RDY_READ                       0x0001
+
+/** Parameter block for pxenv_file_select() */
+struct s_PXENV_FILE_SELECT {
+       PXENV_STATUS_t Status;          /**< PXE status code */
+       UINT16_t FileHandle;            /**< File handle */
+       UINT16_t Ready;                 /**< Indication of readiness */
+} PACKED;
+
+typedef struct s_PXENV_FILE_SELECT PXENV_FILE_SELECT_t;
+
+extern PXENV_EXIT_t pxenv_file_select ( struct s_PXENV_FILE_SELECT
+                                       *file_select );
+
+/** @} */ /* pxenv_file_select */
+
+/** @defgroup pxenv_file_read PXENV_FILE_READ
+ *
+ * FILE READ
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_read() */
+#define PXENV_FILE_READ                0x00e3
+
+/** Parameter block for pxenv_file_read() */
+struct s_PXENV_FILE_READ {
+       PXENV_STATUS_t Status;          /**< PXE status code */
+       UINT16_t FileHandle;            /**< File handle */
+       UINT16_t BufferSize;            /**< Data buffer size */
+       SEGOFF16_t Buffer;              /**< Data buffer */
+} PACKED;
+
+typedef struct s_PXENV_FILE_READ PXENV_FILE_READ_t;
+
+extern PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read );
+
+/** @} */ /* pxenv_file_read */
+
+/** @defgroup pxenv_get_file_size PXENV_GET_FILE_SIZE
+ *
+ * GET FILE SIZE
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_get_file_size() */
+#define PXENV_GET_FILE_SIZE            0x00e4
+
+/** Parameter block for pxenv_get_file_size() */
+struct s_PXENV_GET_FILE_SIZE {
+       PXENV_STATUS_t Status;          /**< PXE status code */
+       UINT16_t FileHandle;            /**< File handle */
+       UINT32_t FileSize;              /**< File size */
+} PACKED;
+
+typedef struct s_PXENV_GET_FILE_SIZE PXENV_GET_FILE_SIZE_t;
+
+extern PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE
+                                         *get_file_size );
+
+/** @} */ /* pxenv_get_file_size */
+
+/** @} */ /* pxe_file_api */
+
 /** @defgroup pxe_loader_api PXE Loader API
  *
  * The UNDI ROM loader API
diff --git a/src/interface/pxe/pxe_file.c b/src/interface/pxe/pxe_file.c
new file mode 100644 (file)
index 0000000..01dac8f
--- /dev/null
@@ -0,0 +1,191 @@
+/** @file
+ *
+ * PXE FILE API
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/posix_io.h>
+#include <gpxe/features.h>
+#include <pxe.h>
+
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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.
+ */
+
+FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 1 );
+
+/**
+ * FILE OPEN
+ *
+ * @v file_open                                Pointer to a struct s_PXENV_FILE_OPEN
+ * @v s_PXENV_FILE_OPEN::FileName      URL of file to open
+ * @ret #PXENV_EXIT_SUCCESS            File was opened
+ * @ret #PXENV_EXIT_FAILURE            File was not opened
+ * @ret s_PXENV_FILE_OPEN::Status      PXE status code
+ * @ret s_PXENV_FILE_OPEN::FileHandle  Handle of opened file
+ *
+ */
+PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ) {
+       userptr_t filename;
+       size_t filename_len;
+       int fd;
+
+       DBG ( "PXENV_FILE_OPEN" );
+
+       /* Copy name from external program, and open it */
+       filename = real_to_user ( file_open->FileName.segment,
+                             file_open->FileName.offset );
+       filename_len = strlen_user ( filename, 0 );
+       {
+               char uri_string[ filename_len + 1 ];
+
+               copy_from_user ( uri_string, filename, 0,
+                                sizeof ( uri_string ) );
+               DBG ( " %s", uri_string );
+               fd = open ( uri_string );
+       }
+
+       if ( fd < 0 ) {
+               file_open->Status = PXENV_STATUS ( fd );
+               return PXENV_EXIT_FAILURE;
+       }
+
+       DBG ( " as file %d", fd );
+
+       file_open->FileHandle = fd;
+       file_open->Status = PXENV_STATUS_SUCCESS;
+       return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * FILE CLOSE
+ *
+ * @v file_close                       Pointer to a struct s_PXENV_FILE_CLOSE
+ * @v s_PXENV_FILE_CLOSE::FileHandle   File handle
+ * @ret #PXENV_EXIT_SUCCESS            File was closed
+ * @ret #PXENV_EXIT_FAILURE            File was not closed
+ * @ret s_PXENV_FILE_CLOSE::Status     PXE status code
+ *
+ */
+PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE *file_close ) {
+
+       DBG ( "PXENV_FILE_CLOSE %d", file_close->FileHandle );
+
+       close ( file_close->FileHandle );
+       file_close->Status = PXENV_STATUS_SUCCESS;
+       return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * FILE SELECT
+ *
+ * @v file_select                      Pointer to a struct s_PXENV_FILE_SELECT
+ * @v s_PXENV_FILE_SELECT::FileHandle  File handle
+ * @ret #PXENV_EXIT_SUCCESS            File has been checked for readiness
+ * @ret #PXENV_EXIT_FAILURE            File has not been checked for readiness
+ * @ret s_PXENV_FILE_SELECT::Status    PXE status code
+ * @ret s_PXENV_FILE_SELECT::Ready     Indication of readiness
+ *
+ */
+PXENV_EXIT_t pxenv_file_select ( struct s_PXENV_FILE_SELECT *file_select ) {
+       fd_set fdset;
+       int ready;
+
+       DBG ( "PXENV_FILE_SELECT %d", file_select->FileHandle );
+
+       FD_ZERO ( &fdset );
+       FD_SET ( file_select->FileHandle, &fdset );
+       if ( ( ready = select ( &fdset, 0 ) ) < 0 ) {
+               file_select->Status = PXENV_STATUS ( ready );
+               return PXENV_EXIT_FAILURE;
+       }
+
+       file_select->Ready = ( ready ? RDY_READ : 0 );
+       file_select->Status = PXENV_STATUS_SUCCESS;
+       return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * FILE READ
+ *
+ * @v file_read                                Pointer to a struct s_PXENV_FILE_READ
+ * @v s_PXENV_FILE_READ::FileHandle    File handle
+ * @v s_PXENV_FILE_READ::BufferSize    Size of data buffer
+ * @v s_PXENV_FILE_READ::Buffer                Data buffer
+ * @ret #PXENV_EXIT_SUCCESS            Data has been read from file
+ * @ret #PXENV_EXIT_FAILURE            Data has not been read from file
+ * @ret s_PXENV_FILE_READ::Status      PXE status code
+ * @ret s_PXENV_FILE_READ::Ready       Indication of readiness
+ * @ret s_PXENV_FILE_READ::BufferSize  Length of data read
+ *
+ */
+PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ) {
+       userptr_t buffer;
+       ssize_t len;
+
+       DBG ( "PXENV_FILE_READ %d to %04x:%04x+%04x", file_read->FileHandle,
+             file_read->Buffer.segment, file_read->Buffer.offset,
+             file_read->BufferSize );
+
+       buffer = real_to_user ( file_read->Buffer.segment,
+                               file_read->Buffer.offset );
+       if ( ( len = read_user ( file_read->FileHandle, buffer, 0,
+                               file_read->BufferSize ) ) < 0 ) {
+               file_read->Status = PXENV_STATUS ( len );
+               return PXENV_EXIT_FAILURE;
+       }
+
+       DBG ( " read %04zx", ( ( size_t ) len ) );
+
+       file_read->BufferSize = len;
+       file_read->Status = PXENV_STATUS_SUCCESS;
+       return PXENV_EXIT_SUCCESS;
+}
+
+/**
+ * GET FILE SIZE
+ *
+ * @v get_file_size                    Pointer to a struct s_PXENV_GET_FILE_SIZE
+ * @v s_PXENV_GET_FILE_SIZE::FileHandle        File handle
+ * @ret #PXENV_EXIT_SUCCESS            File size has been determined
+ * @ret #PXENV_EXIT_FAILURE            File size has not been determined
+ * @ret s_PXENV_GET_FILE_SIZE::Status  PXE status code
+ * @ret s_PXENV_GET_FILE_SIZE::FileSize        Size of file
+ */
+PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE
+                                  *get_file_size ) {
+       ssize_t filesize;
+
+       DBG ( "PXENV_GET_FILE_SIZE %d", get_file_size->FileHandle );
+
+       filesize = fsize ( get_file_size->FileHandle );
+       if ( filesize < 0 ) {
+               get_file_size->Status = PXENV_STATUS ( filesize );
+               return PXENV_EXIT_FAILURE;
+       }
+
+       DBG ( " is %zd", ( ( size_t ) filesize ) );
+
+       get_file_size->FileSize = filesize;
+       get_file_size->Status = PXENV_STATUS_SUCCESS;
+       return PXENV_EXIT_SUCCESS;
+}