Merge branch 'xl0-timer'
authorMichael Brown <mcb30@etherboot.org>
Mon, 10 Mar 2008 13:02:53 +0000 (13:02 +0000)
committerMichael Brown <mcb30@etherboot.org>
Mon, 10 Mar 2008 13:02:53 +0000 (13:02 +0000)
12 files changed:
src/arch/i386/interface/pxe/pxe_call.c
src/config.h
src/core/config.c
src/drivers/net/tg3.c
src/hci/commands/sanboot_cmd.c [new file with mode: 0644]
src/include/pxe.h
src/include/pxe_api.h
src/include/usr/autoboot.h
src/interface/pxe/pxe_file.c
src/interface/pxe/pxe_preboot.c
src/usr/autoboot.c
src/util/parserom.pl

index 8f1dd0a..b9c21ce 100644 (file)
@@ -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;
index 67fdd64..e004f23 100644 (file)
 #define        ROUTE_CMD               /* Routing table management commands */
 #define IMAGE_CMD              /* Image management commands */
 #define DHCP_CMD               /* DHCP management commands */
+#define SANBOOT_CMD            /* SAN boot commands */
 
 /* @END general.h */ 
 
index 94fd0b8..24db355 100644 (file)
@@ -186,6 +186,9 @@ REQUIRE_OBJECT ( image_cmd );
 #ifdef DHCP_CMD
 REQUIRE_OBJECT ( dhcp_cmd );
 #endif
+#ifdef SANBOOT_CMD
+REQUIRE_OBJECT ( sanboot_cmd );
+#endif
 
 /*
  * Drag in miscellaneous objects
index 57b9df1..2aa072b 100644 (file)
@@ -3383,6 +3383,7 @@ PCI_ROM(0x173b, 0x03e8, "tg3-ac1000",      "Altima AC1000"),
 PCI_ROM(0x173b, 0x03e9, "tg3-ac1001",      "Altima AC1001"),
 PCI_ROM(0x173b, 0x03ea, "tg3-ac9100",      "Altima AC9100"),
 PCI_ROM(0x173b, 0x03eb, "tg3-ac1003",      "Altima AC1003"),
+PCI_ROM(0x0e11, 0x00ca, "tg3-hp",         "HP Tigon 3"),
 };
 
 PCI_DRIVER ( tg3_driver, tg3_nics, PCI_NO_CLASS );
diff --git a/src/hci/commands/sanboot_cmd.c b/src/hci/commands/sanboot_cmd.c
new file mode 100644 (file)
index 0000000..d5bbfb8
--- /dev/null
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <gpxe/command.h>
+#include <usr/autoboot.h>
+
+/**
+ * "sanboot" command syntax message
+ *
+ * @v argv             Argument list
+ */
+static void sanboot_syntax ( char **argv ) {
+       printf ( "Usage:\n"
+                "  %s <root-path>\n"
+                "\n"
+                "Boot from SAN target\n",
+                argv[0] );
+}
+
+/**
+ * The "sanboot" command
+ *
+ * @v argc             Argument count
+ * @v argv             Argument list
+ * @ret rc             Exit code
+ */
+static int sanboot_exec ( int argc, char **argv ) {
+       static struct option longopts[] = {
+               { "help", 0, NULL, 'h' },
+               { NULL, 0, NULL, 0 },
+       };
+       const char *root_path = NULL;
+       int c;
+       int rc;
+
+       /* Parse options */
+       while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
+               switch ( c ) {
+               case 'h':
+                       /* Display help text */
+               default:
+                       /* Unrecognised/invalid option */
+                       sanboot_syntax ( argv );
+                       return 1;
+               }
+       }
+
+       /* Need exactly one image name remaining after the options */
+       if ( optind != ( argc - 1 ) ) {
+               sanboot_syntax ( argv );
+               return 1;
+       }
+       root_path = argv[optind];
+
+       /* Boot from root path */
+       if ( ( rc = boot_root_path ( root_path ) ) != 0 ) {
+               printf ( "Could not boot from %s: %s\n",
+                        root_path, strerror ( rc ) );
+               return 1;
+       }
+
+       return 0;
+}
+
+struct command sanboot_command __command = {
+       .name = "sanboot",
+       .exec = sanboot_exec,
+};
index f17d8f7..8b3ca14 100644 (file)
@@ -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;
index 8dc1607..53708ed 100644 (file)
@@ -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
index 4ddeb5b..b451a8c 100644 (file)
@@ -8,5 +8,6 @@
  */
 
 extern void autoboot ( void );
+extern int boot_root_path ( const char *root_path );
 
 #endif /* _USR_AUTOBOOT_H */
index 01dac8f..718f5e3 100644 (file)
@@ -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;
+}
index 53ece3c..2d6f135 100644 (file)
@@ -51,8 +51,18 @@ enum pxe_cached_info_indices {
 /** A cached DHCP packet */
 union pxe_cached_info {
        struct dhcphdr dhcphdr;
-       char raw[ETH_FRAME_LEN];
-};
+       /* This buffer must be *exactly* the size of a BOOTPLAYER_t
+        * structure, otherwise WinPE will die horribly.  It takes the
+        * size of *our* buffer and feeds it in to us as the size of
+        * one of *its* buffers.  If our buffer is larger than it
+        * expects, we therefore end up overwriting part of its data
+        * segment, since it tells us to do so.  (D'oh!)
+        *
+        * Note that a BOOTPLAYER_t is not necessarily large enough to
+        * hold a DHCP packet; this is a flaw in the PXE spec.
+        */
+       BOOTPLAYER_t packet;
+} __attribute__ (( packed ));
 
 /* The case in which the caller doesn't supply a buffer is really
  * awkward to support given that we have multiple sources of options,
index c3b07e9..b84bd7b 100644 (file)
@@ -108,7 +108,7 @@ static int boot_filename ( const char *filename ) {
  * @v root_path                Root path
  * @ret rc             Return status code
  */
-static int boot_root_path ( const char *root_path ) {
+int boot_root_path ( const char *root_path ) {
 
        /* Quick hack */
        if ( strncmp ( root_path, "iscsi:", 6 ) == 0 ) {
index ace8ec9..3d41b54 100644 (file)
@@ -49,7 +49,7 @@ while ( <DRV> ) {
        \)/x ) {
     ( my $vendor, my $device, my $image, my $desc ) = ( lc $1, lc $2, $3, $4 );
     rom ( "pci", $image, $desc, $vendor, $device );
-    rom ( "pci", lc "pci_${vendor}_${device}", $desc, $vendor, $device );
+    rom ( "pci", lc "${vendor}${device}", $desc, $vendor, $device );
   } elsif ( /^\s*ISA_ROM\s*\(
              \s*\"([^\"]*)\"\s*,  # Image
              \s*\"([^\"]*)\"\s*   # Description