2
0
mirror of https://github.com/xcat2/xcat-dep.git synced 2024-11-23 01:51:54 +00:00

-Add several patches from gPXE git tree (all of this checkin is from gPXE git tree)

-Add workaround for use of Etherboot UNDI stack from git tree
-Add workaround for UNDI drivers that do not call the undi open call before attempting to use defive from git tree
-Change ProxyDHCP broadcast to go to port 67 (from git tree)
-Enable use of DHCP options when BOOTP fields are not present
-Report UNDI device to driver as a more standard interface type
-Workaround malformed OACK packets sent by certain PXE servers
-Avoid a spurious IRQ
-Add fix for e1000 driver
-Have the UNDI stack report UNDI capabilities
-Fix some places where interrupt handlers did not use iret to return
This commit is contained in:
jbjohnso 2009-08-22 02:03:07 +00:00
parent dd6aed9f5f
commit a60d90375d
10 changed files with 498 additions and 0 deletions

View File

@ -0,0 +1,12 @@
diff -urN gpxe-0.9.7/src/arch/i386/interface/pxe/pxe_undi.c gpxe-0.9.7-8021ifacetype/src/arch/i386/interface/pxe/pxe_undi.c
--- gpxe-0.9.7/src/arch/i386/interface/pxe/pxe_undi.c 2009-08-21 20:54:12.000000000 -0400
+++ gpxe-0.9.7-8021ifacetype/src/arch/i386/interface/pxe/pxe_undi.c 2009-08-21 20:53:53.000000000 -0400
@@ -517,7 +517,7 @@
* Most PXE stacks seem to take this approach.
*/
snprintf ( ( char * ) undi_get_iface_info->IfaceType,
- sizeof ( undi_get_iface_info->IfaceType ), "gPXE" );
+ sizeof ( undi_get_iface_info->IfaceType ), "DIX+802.3" );
undi_get_iface_info->LinkSpeed = 10000000; /* 10 Mbps */
undi_get_iface_info->ServiceFlags =
( SUPPORTED_BROADCAST | SUPPORTED_MULTICAST |

View File

@ -0,0 +1,21 @@
diff -urN gpxe-0.9.7/src/arch/i386/interface/pxe/pxe_undi.c gpxe-0.9.7-avoidspuriousirq/src/arch/i386/interface/pxe/pxe_undi.c
--- gpxe-0.9.7/src/arch/i386/interface/pxe/pxe_undi.c 2009-08-21 21:00:26.000000000 -0400
+++ gpxe-0.9.7-avoidspuriousirq/src/arch/i386/interface/pxe/pxe_undi.c 2009-08-21 20:59:51.000000000 -0400
@@ -277,14 +277,15 @@
}
}
+ /* Flag transmission as in-progress */
+ undi_tx_count++;
/* Transmit packet */
if ( ( rc = netdev_tx ( pxe_netdev, iobuf ) ) != 0 ) {
+ undi_tx_count--;
undi_transmit->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
}
- /* Flag transmission as in-progress */
- undi_tx_count++;
undi_transmit->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;

View File

@ -0,0 +1,33 @@
diff -urN gpxe-0.9.7/src/net/dhcppkt.c gpxe-0.9.7-bootptodhcpfailover/src/net/dhcppkt.c
--- gpxe-0.9.7/src/net/dhcppkt.c 2009-03-01 21:23:42.000000000 -0500
+++ gpxe-0.9.7-bootptodhcpfailover/src/net/dhcppkt.c 2009-08-21 21:49:52.000000000 -0400
@@ -155,6 +155,8 @@
memset ( field_data, 0, field->len );
memcpy ( dhcp_packet_field ( dhcppkt->dhcphdr, field ),
data, len );
+ /* Erase any equivalent option from the options block */
+ dhcpopt_store ( &dhcppkt->options, tag, NULL, 0 );
return 0;
}
@@ -181,14 +183,16 @@
void *data, size_t len ) {
struct dhcp_packet_field *field;
void *field_data;
- size_t field_len;
+ size_t field_len = 0;
- /* If this is a special field, return it */
+ /* Identify special field, if any */
if ( ( field = find_dhcp_packet_field ( tag ) ) != NULL ) {
field_data = dhcp_packet_field ( dhcppkt->dhcphdr, field );
field_len = field->used_len ( field_data, field->len );
- if ( ! field_len )
- return -ENOENT;
+ }
+
+ /* Return special field, if it exists and is populated */
+ if ( field_len ) {
if ( len > field_len )
len = field_len;
memcpy ( data, field_data, len );

View File

@ -0,0 +1,11 @@
diff -urN gpxe-0.9.7/src/drivers/net/e1000/e1000.c gpxe-0.9.7-e1000fix/src/drivers/net/e1000/e1000.c
--- gpxe-0.9.7/src/drivers/net/e1000/e1000.c 2009-03-01 21:23:42.000000000 -0500
+++ gpxe-0.9.7-e1000fix/src/drivers/net/e1000/e1000.c 2009-08-21 21:13:59.000000000 -0400
@@ -586,6 +586,7 @@
/* Write new tail to NIC, making packet available for transmit
*/
+ wmb();
E1000_WRITE_REG ( hw, TDT, adapter->tx_tail );
return 0;

View File

@ -0,0 +1,126 @@
diff -urN gpxe-0.9.7/src/arch/i386/prefix/pxeprefix.S gpxe-0.9.7-etherbootworkaround/src/arch/i386/prefix/pxeprefix.S
--- gpxe-0.9.7/src/arch/i386/prefix/pxeprefix.S 2009-03-01 21:23:42.000000000 -0500
+++ gpxe-0.9.7-etherbootworkaround/src/arch/i386/prefix/pxeprefix.S 2009-08-21 20:36:55.000000000 -0400
@@ -1,8 +1,11 @@
#define PXENV_UNDI_SHUTDOWN 0x0005
#define PXENV_UNDI_GET_NIC_TYPE 0x0012
+#define PXENV_UNDI_GET_IFACE_INFO 0x0013
#define PXENV_STOP_UNDI 0x0015
#define PXENV_UNLOAD_STACK 0x0070
+#define PXE_HACK_EB54 0x0001
+
.text
.arch i386
.org 0
@@ -11,6 +14,8 @@
#include <undi.h>
#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
+#define EB_MAGIC_1 ( 'E' + ( 't' << 8 ) + ( 'h' << 16 ) + ( 'e' << 24 ) )
+#define EB_MAGIC_2 ( 'r' + ( 'b' << 8 ) + ( 'o' << 16 ) + ( 'o' << 24 ) )
/*****************************************************************************
* Entry point: set operating context, print welcome message
@@ -309,8 +314,6 @@
movw $10f, %si
call print_message
call print_pci_busdevfn
- movb $0x0a, %al
- call print_character
jmp 99f
.section ".prefix.data", "aw", @progbits
10: .asciz " UNDI device is PCI "
@@ -321,12 +324,47 @@
movw $10f, %si
call print_message
.section ".prefix.data", "aw", @progbits
-10: .asciz " Unable to determine UNDI physical device\n"
+10: .asciz " Unable to determine UNDI physical device"
.previous
99:
/*****************************************************************************
+ * Determine interface type
+ *****************************************************************************
+ */
+get_iface_type:
+ /* Issue PXENV_UNDI_GET_IFACE_INFO */
+ movw $PXENV_UNDI_GET_IFACE_INFO, %bx
+ call pxe_call
+ jnc 1f
+ call print_pxe_error
+ jmp 99f
+1: /* Print interface type */
+ movw $10f, %si
+ call print_message
+ leaw ( pxe_parameter_structure + 0x02 ), %si
+ call print_message
+ .section ".prefix.data", "aw", @progbits
+10: .asciz ", type "
+ .previous
+ /* Check for "Etherboot" interface type */
+ cmpl $EB_MAGIC_1, ( pxe_parameter_structure + 0x02 )
+ jne 99f
+ cmpl $EB_MAGIC_2, ( pxe_parameter_structure + 0x06 )
+ jne 99f
+ movw $10f, %si
+ call print_message
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " (workaround enabled)"
+ .previous
+ /* Flag Etherboot workarounds as required */
+ orw $PXE_HACK_EB54, pxe_hacks
+
+99: movb $0x0a, %al
+ call print_character
+
+/*****************************************************************************
* Leave NIC in a safe state
*****************************************************************************
*/
@@ -339,6 +377,14 @@
call print_pxe_error
1:
unload_base_code:
+ /* Etherboot treats PXENV_UNLOAD_STACK as PXENV_STOP_UNDI, so
+ * we must not issue this call if the underlying stack is
+ * Etherboot and we were not intending to issue a PXENV_STOP_UNDI.
+ */
+#ifdef PXELOADER_KEEP_UNDI
+ testw $PXE_HACK_EB54, pxe_hacks
+ jnz 99f
+#endif /* PXELOADER_KEEP_UNDI */
/* Issue PXENV_UNLOAD_STACK */
movw $PXENV_UNLOAD_STACK, %bx
call pxe_call
@@ -551,7 +597,9 @@
testw %ax, %ax
jz 1f
stc
-1: /* Restore registers and return */
+1: /* Clear direction flag, for the sake of sanity */
+ cld
+ /* Restore registers and return */
popw %es
popw %di
ret
@@ -595,7 +643,7 @@
pxe_esp: .long 0
pxe_ss: .word 0
-pxe_parameter_structure: .fill 20
+pxe_parameter_structure: .fill 64
undi_code_segoff:
undi_code_size: .word 0
@@ -605,6 +653,8 @@
undi_data_size: .word 0
undi_data_segment: .word 0
+pxe_hacks: .word 0
+
/* The following fields are part of a struct undi_device */
undi_device:

View File

@ -0,0 +1,111 @@
diff -urN gpxe-0.9.7/src/arch/i386/firmware/pcbios/e820mangler.S gpxe-0.9.7-iretfixes/src/arch/i386/firmware/pcbios/e820mangler.S
--- gpxe-0.9.7/src/arch/i386/firmware/pcbios/e820mangler.S 2009-03-01 21:23:42.000000000 -0500
+++ gpxe-0.9.7-iretfixes/src/arch/i386/firmware/pcbios/e820mangler.S 2009-08-21 21:28:41.000000000 -0400
@@ -490,6 +490,18 @@
.size get_mangled_e820, . - get_mangled_e820
/****************************************************************************
+ * Set/clear CF on the stack as appropriate, assumes stack is as it should
+ * be immediately before IRET
+ ****************************************************************************
+ */
+patch_cf:
+ pushw %bp
+ movw %sp, %bp
+ setc 8(%bp) /* Set/reset CF; clears PF, AF, ZF, SF */
+ popw %bp
+ ret
+
+/****************************************************************************
* INT 15,e820 handler
****************************************************************************
*/
@@ -500,7 +512,8 @@
popw %ds
call get_mangled_e820
popw %ds
- lret $2
+ call patch_cf
+ iret
.size int15_e820, . - int15_e820
/****************************************************************************
@@ -512,7 +525,7 @@
/* Call previous handler */
pushfw
lcall *%cs:int15_vector
- pushfw
+ call patch_cf
/* Edit result */
pushw %ds
pushw %cs:rm_ds
@@ -524,9 +537,7 @@
xchgw %ax, %cx
xchgw %bx, %dx
popw %ds
- /* Restore flags returned by previous handler and return */
- popfw
- lret $2
+ iret
.size int15_e801, . - int15_e801
/****************************************************************************
@@ -538,16 +549,14 @@
/* Call previous handler */
pushfw
lcall *%cs:int15_vector
- pushfw
+ call patch_cf
/* Edit result */
pushw %ds
pushw %cs:rm_ds
popw %ds
call patch_1m
popw %ds
- /* Restore flags returned by previous handler and return */
- popfw
- lret $2
+ iret
.size int15_88, . - int15_88
/****************************************************************************
diff -urN gpxe-0.9.7/src/arch/i386/firmware/pcbios/fakee820.c gpxe-0.9.7-iretfixes/src/arch/i386/firmware/pcbios/fakee820.c
--- gpxe-0.9.7/src/arch/i386/firmware/pcbios/fakee820.c 2009-03-01 21:23:42.000000000 -0500
+++ gpxe-0.9.7-iretfixes/src/arch/i386/firmware/pcbios/fakee820.c 2009-08-21 21:28:41.000000000 -0400
@@ -63,6 +63,8 @@
"cmpl $0x534d4150, %%edx\n\t"
"jne 99f\n\t"
"pushaw\n\t"
+ "movw %%sp, %%bp\n\t"
+ "andb $~0x01, 22(%%bp)\n\t" /* Clear return CF */
"leaw e820map(%%bx), %%si\n\t"
"cs rep movsb\n\t"
"popaw\n\t"
@@ -73,8 +75,7 @@
"xorl %%ebx,%%ebx\n\t"
"\n1:\n\t"
"popfw\n\t"
- "clc\n\t"
- "lret $2\n\t"
+ "iret\n\t"
"\n99:\n\t"
"popfw\n\t"
"ljmp *%%cs:real_int15_vector\n\t" )
diff -urN gpxe-0.9.7/src/arch/i386/interface/pxe/pxe_entry.S gpxe-0.9.7-iretfixes/src/arch/i386/interface/pxe/pxe_entry.S
--- gpxe-0.9.7/src/arch/i386/interface/pxe/pxe_entry.S 2009-03-01 21:23:42.000000000 -0500
+++ gpxe-0.9.7-iretfixes/src/arch/i386/interface/pxe/pxe_entry.S 2009-08-21 21:28:41.000000000 -0400
@@ -199,9 +199,12 @@
shll $4, %edx
addl $pxenv, %edx
movw $0x564e, %ax
+ pushw %bp
+ movw %sp, %bp
+ andb $~0x01, 8(%bp) /* Clear CF on return */
+ popw %bp
popfw
- clc
- lret $2
+ iret
1: /* INT 1A,other - pass through */
popfw
ljmp *%cs:pxe_int_1a_vector

View File

@ -0,0 +1,36 @@
diff -urN gpxe-0.9.7/src/arch/i386/interface/pxe/pxe_undi.c gpxe-0.9.7-noopenworkaround/src/arch/i386/interface/pxe/pxe_undi.c
--- gpxe-0.9.7/src/arch/i386/interface/pxe/pxe_undi.c 2009-08-21 21:05:12.000000000 -0400
+++ gpxe-0.9.7-noopenworkaround/src/arch/i386/interface/pxe/pxe_undi.c 2009-08-21 21:04:39.000000000 -0400
@@ -209,6 +209,12 @@
DBG ( "PXENV_UNDI_TRANSMIT" );
+ /* Forcibly enable interrupts at this point, to work around
+ * callers that never call PXENV_UNDI_OPEN before attempting
+ * to use the UNDI API.
+ */
+ netdev_irq ( pxe_netdev, 1 );
+
/* Identify network-layer protocol */
switch ( undi_transmit->Protocol ) {
case P_IP: net_protocol = &ipv4_protocol; break;
@@ -340,10 +346,17 @@
PXENV_EXIT_t
pxenv_undi_set_packet_filter ( struct s_PXENV_UNDI_SET_PACKET_FILTER
*undi_set_packet_filter ) {
+
DBG ( "PXENV_UNDI_SET_PACKET_FILTER" );
- undi_set_packet_filter->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
+ /* Pretend that we succeeded, otherwise the 3Com DOS UNDI
+ * driver refuses to load. (We ignore the filter value in the
+ * PXENV_UNDI_OPEN call anyway.)
+ */
+ DBG ( " %02x", undi_set_packet_filter->filter );
+ undi_set_packet_filter->Status = PXENV_STATUS_SUCCESS;
+
+ return PXENV_EXIT_SUCCESS;
}
/* PXENV_UNDI_GET_INFORMATION

View File

@ -0,0 +1,65 @@
diff -urN gpxe-0.9.7/src/net/udp/tftp.c gpxe-0.9.7-oackfix/src/net/udp/tftp.c
--- gpxe-0.9.7/src/net/udp/tftp.c 2009-03-01 21:23:42.000000000 -0500
+++ gpxe-0.9.7-oackfix/src/net/udp/tftp.c 2009-08-21 20:45:10.000000000 -0400
@@ -670,6 +670,7 @@
char *end = buf + len;
char *name;
char *value;
+ char *next;
int rc = 0;
/* Sanity check */
@@ -679,26 +680,41 @@
rc = -EINVAL;
goto done;
}
- if ( end[-1] != '\0' ) {
- DBGC ( tftp, "TFTP %p received OACK missing final NUL\n",
- tftp );
- rc = -EINVAL;
- goto done;
- }
/* Process each option in turn */
- name = oack->data;
- while ( name < end ) {
- value = ( name + strlen ( name ) + 1 );
+ for ( name = oack->data ; name < end ; name = next ) {
+
+ /* Parse option name and value
+ *
+ * We treat parsing errors as non-fatal, because there
+ * exists at least one TFTP server (IBM Tivoli PXE
+ * Server 5.1.0.3) that has been observed to send
+ * malformed OACKs containing trailing garbage bytes.
+ */
+ value = ( name + strnlen ( name, ( end - name ) ) + 1 );
+ if ( value > end ) {
+ DBGC ( tftp, "TFTP %p received OACK with malformed "
+ "option name:\n", tftp );
+ DBGC_HD ( tftp, oack, len );
+ break;
+ }
if ( value == end ) {
DBGC ( tftp, "TFTP %p received OACK missing value "
"for option \"%s\"\n", tftp, name );
- rc = -EINVAL;
- goto done;
+ DBGC_HD ( tftp, oack, len );
+ break;
}
+ next = ( value + strnlen ( value, ( end - value ) ) + 1 );
+ if ( next > end ) {
+ DBGC ( tftp, "TFTP %p received OACK with malformed "
+ "value for option \"%s\":\n", tftp, name );
+ DBGC_HD ( tftp, oack, len );
+ break;
+ }
+
+ /* Process option */
if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
goto done;
- name = ( value + strlen ( value ) + 1 );
}
/* Process tsize information, if available */

View File

@ -0,0 +1,39 @@
diff -urN gpxe-0.9.7/src/net/udp/dhcp.c gpxe-0.9.7-pdhcp67/src/net/udp/dhcp.c
--- gpxe-0.9.7/src/net/udp/dhcp.c 2009-08-21 21:33:52.000000000 -0400
+++ gpxe-0.9.7-pdhcp67/src/net/udp/dhcp.c 2009-08-21 21:33:13.000000000 -0400
@@ -668,8 +668,13 @@
struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
int rc;
+ /* Set server address */
+ peer->sin_addr = *(dhcp->pxe_attempt);
+ peer->sin_port = ( ( peer->sin_addr.s_addr == INADDR_BROADCAST ) ?
+ htons ( BOOTPS_PORT ) : htons ( PXE_PORT ) );
+
DBGC ( dhcp, "DHCP %p PXEBS REQUEST to %s:%d for type %d\n",
- dhcp, inet_ntoa ( *(dhcp->pxe_attempt) ), PXE_PORT,
+ dhcp, inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ),
ntohs ( dhcp->pxe_type ) );
/* Set boot menu item */
@@ -678,10 +683,6 @@
&menu_item, sizeof ( menu_item ) ) ) != 0 )
return rc;
- /* Set server address */
- peer->sin_addr = *(dhcp->pxe_attempt);
- peer->sin_port = htons ( PXE_PORT );
-
return 0;
}
@@ -741,7 +742,8 @@
DBGC ( dhcp, "\n" );
/* Filter out unacceptable responses */
- if ( peer->sin_port != htons ( PXE_PORT ) )
+ if ( ( peer->sin_port != htons ( BOOTPS_PORT ) ) &&
+ ( peer->sin_port != htons ( PXE_PORT ) ) )
return;
if ( msgtype != DHCPACK )
return;

View File

@ -0,0 +1,44 @@
diff -urN gpxe-0.9.7/src/arch/i386/include/pxe_api.h gpxe-0.9.7-undiserviceflags/src/arch/i386/include/pxe_api.h
--- gpxe-0.9.7/src/arch/i386/include/pxe_api.h 2009-03-01 21:23:42.000000000 -0500
+++ gpxe-0.9.7-undiserviceflags/src/arch/i386/include/pxe_api.h 2009-08-21 20:49:41.000000000 -0400
@@ -1415,6 +1415,25 @@
/** PXE API function code for pxenv_undi_get_iface_info() */
#define PXENV_UNDI_GET_IFACE_INFO 0x0013
+/** Broadcast supported */
+#define SUPPORTED_BROADCAST 0x0001
+/** Multicast supported */
+#define SUPPORTED_MULTICAST 0x0002
+/** Functional/group addressing supported */
+#define SUPPORTED_GROUP 0x0004
+/** Promiscuous mode supported */
+#define SUPPORTED_PROMISCUOUS 0x0008
+/** Software settable station address */
+#define SUPPORTED_SET_STATION_ADDRESS 0x0010
+/** InitiateDiagnostics supported */
+#define SUPPORTED_DIAGNOSTICS 0x0040
+/** Reset MAC supported */
+#define SUPPORTED_RESET 0x0400
+/** Open / Close Adapter supported */
+#define SUPPORTED_OPEN_CLOSE 0x0800
+/** Interrupt Request supported */
+#define SUPPORTED_IRQ 0x1000
+
/** Parameter block for pxenv_undi_get_iface_info() */
struct s_PXENV_UNDI_GET_IFACE_INFO {
PXENV_STATUS_t Status; /**< PXE status code */
diff -urN gpxe-0.9.7/src/arch/i386/interface/pxe/pxe_undi.c gpxe-0.9.7-undiserviceflags/src/arch/i386/interface/pxe/pxe_undi.c
--- gpxe-0.9.7/src/arch/i386/interface/pxe/pxe_undi.c 2009-03-01 21:23:42.000000000 -0500
+++ gpxe-0.9.7-undiserviceflags/src/arch/i386/interface/pxe/pxe_undi.c 2009-08-21 20:49:41.000000000 -0400
@@ -519,7 +519,10 @@
snprintf ( ( char * ) undi_get_iface_info->IfaceType,
sizeof ( undi_get_iface_info->IfaceType ), "gPXE" );
undi_get_iface_info->LinkSpeed = 10000000; /* 10 Mbps */
- undi_get_iface_info->ServiceFlags = 0;
+ undi_get_iface_info->ServiceFlags =
+ ( SUPPORTED_BROADCAST | SUPPORTED_MULTICAST |
+ SUPPORTED_SET_STATION_ADDRESS | SUPPORTED_RESET |
+ SUPPORTED_OPEN_CLOSE | SUPPORTED_IRQ );
memset ( undi_get_iface_info->Reserved, 0,
sizeof(undi_get_iface_info->Reserved) );