aboutsummaryrefslogtreecommitdiffstats
path: root/gpxe/src/interface
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-09-07 22:41:29 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-09-07 22:41:29 -0700
commitc14f98ab23dbc912aa9db26d86434a4d2bd80a5f (patch)
treea0b1d6fd48ad30f8af19a88d11a8f4e61cebf52f /gpxe/src/interface
parent3506d7fb195922b04c941650b1512440bdcc89e4 (diff)
downloadsyslinux.git-c14f98ab23dbc912aa9db26d86434a4d2bd80a5f.tar.gz
syslinux.git-c14f98ab23dbc912aa9db26d86434a4d2bd80a5f.tar.xz
syslinux.git-c14f98ab23dbc912aa9db26d86434a4d2bd80a5f.zip
gPXE: update gPXE to current git
Update gPXE to current git. gpxe-for-syslinux e3ef2094cfa26f874c5f8dbd687eb311830efcf0 gpxe main tree 8223084afc206000312611a3fcfa30a28500d1a3
Diffstat (limited to 'gpxe/src/interface')
-rw-r--r--gpxe/src/interface/pxe/pxe_loader.c6
-rw-r--r--gpxe/src/interface/pxe/pxe_preboot.c5
-rw-r--r--gpxe/src/interface/pxe/pxe_udp.c21
-rw-r--r--gpxe/src/interface/pxe/pxe_undi.c96
4 files changed, 100 insertions, 28 deletions
diff --git a/gpxe/src/interface/pxe/pxe_loader.c b/gpxe/src/interface/pxe/pxe_loader.c
index 708d203a..f815bc25 100644
--- a/gpxe/src/interface/pxe/pxe_loader.c
+++ b/gpxe/src/interface/pxe/pxe_loader.c
@@ -42,11 +42,9 @@ PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader ) {
/* Fill in UNDI loader structure */
undi_loader->PXEptr.segment = rm_cs;
- undi_loader->PXEptr.offset =
- ( ( unsigned ) & __from_text16 ( ppxe ) );
+ undi_loader->PXEptr.offset = __from_text16 ( &ppxe );
undi_loader->PXENVptr.segment = rm_cs;
- undi_loader->PXENVptr.offset =
- ( ( unsigned ) & __from_text16 ( pxenv ) );
+ undi_loader->PXENVptr.offset = __from_text16 ( &pxenv );
undi_loader->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
diff --git a/gpxe/src/interface/pxe/pxe_preboot.c b/gpxe/src/interface/pxe/pxe_preboot.c
index 302953eb..8220d1f2 100644
--- a/gpxe/src/interface/pxe/pxe_preboot.c
+++ b/gpxe/src/interface/pxe/pxe_preboot.c
@@ -196,8 +196,7 @@ PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO
* fill it in.
*/
get_cached_info->Buffer.segment = rm_ds;
- get_cached_info->Buffer.offset =
- ( unsigned ) ( __from_data16 ( info ) );
+ get_cached_info->Buffer.offset = __from_data16 ( info );
get_cached_info->BufferSize = sizeof ( *info );
DBG ( " returning %04x:%04x+%04x['%x']",
get_cached_info->Buffer.segment,
@@ -319,7 +318,7 @@ PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ) {
pxe_set_netdev ( NULL );
/* Prepare for unload */
- shutdown();
+ shutdown ( SHUTDOWN_BOOT );
stop_undi->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
diff --git a/gpxe/src/interface/pxe/pxe_udp.c b/gpxe/src/interface/pxe/pxe_udp.c
index 40c2b2e5..033b1ad9 100644
--- a/gpxe/src/interface/pxe/pxe_udp.c
+++ b/gpxe/src/interface/pxe/pxe_udp.c
@@ -166,6 +166,7 @@ PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) {
/* Record source IP address */
pxe_udp.local.sin_addr.s_addr = pxenv_udp_open->src_ip;
+ DBG ( " %s", inet_ntoa ( pxe_udp.local.sin_addr ) );
/* Open promiscuous UDP connection */
xfer_close ( &pxe_udp.xfer, 0 );
@@ -255,6 +256,7 @@ PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
struct xfer_metadata meta = {
.src = ( struct sockaddr * ) &pxe_udp.local,
.dest = ( struct sockaddr * ) &dest,
+ .netdev = pxe_netdev,
};
size_t len;
struct io_buffer *iobuf;
@@ -354,8 +356,10 @@ PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
*
*/
PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
- struct in_addr dest_ip = { .s_addr = pxenv_udp_read->dest_ip };
- uint16_t d_port = pxenv_udp_read->d_port;
+ struct in_addr dest_ip_wanted = { .s_addr = pxenv_udp_read->dest_ip };
+ struct in_addr dest_ip;
+ uint16_t d_port_wanted = pxenv_udp_read->d_port;
+ uint16_t d_port;
DBG ( "PXENV_UDP_READ" );
@@ -367,12 +371,21 @@ PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
pxe_udp.pxenv_udp_read = NULL;
goto no_packet;
}
+ dest_ip.s_addr = pxenv_udp_read->dest_ip;
+ d_port = pxenv_udp_read->d_port;
/* Filter on destination address and/or port */
- if ( dest_ip.s_addr && ( dest_ip.s_addr != pxenv_udp_read->dest_ip ) )
+ if ( dest_ip_wanted.s_addr &&
+ ( dest_ip_wanted.s_addr != dest_ip.s_addr ) ) {
+ DBG ( " wrong IP %s", inet_ntoa ( dest_ip ) );
+ DBG ( " (wanted %s)", inet_ntoa ( dest_ip_wanted ) );
goto no_packet;
- if ( d_port && ( d_port != pxenv_udp_read->d_port ) )
+ }
+ if ( d_port_wanted && ( d_port_wanted != d_port ) ) {
+ DBG ( " wrong port %d ", htons ( d_port ) );
+ DBG ( " (wanted %d)", htons ( d_port_wanted ) );
goto no_packet;
+ }
DBG ( " %04x:%04x+%x %s:", pxenv_udp_read->buffer.segment,
pxenv_udp_read->buffer.offset, pxenv_udp_read->buffer_size,
diff --git a/gpxe/src/interface/pxe/pxe_undi.c b/gpxe/src/interface/pxe/pxe_undi.c
index 76b55df9..5d06f2d8 100644
--- a/gpxe/src/interface/pxe/pxe_undi.c
+++ b/gpxe/src/interface/pxe/pxe_undi.c
@@ -221,7 +221,7 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
return PXENV_EXIT_FAILURE;
}
- DBG ( " %s", ( net_protocol ? net_protocol->name : "UNKNOWN" ) );
+ DBG ( " %s", ( net_protocol ? net_protocol->name : "RAW" ) );
/* Calculate total packet length */
copy_from_real ( &tbd, undi_transmit->TBD.segment,
@@ -251,11 +251,9 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
datablk->TDDataLen );
}
- /* Transmit packet */
- if ( net_protocol == NULL ) {
- /* Link-layer header already present */
- rc = netdev_tx ( pxe_netdev, iobuf );
- } else {
+ /* Add link-layer header, if required to do so */
+ if ( net_protocol != NULL ) {
+
/* Calculate destination address */
if ( undi_transmit->XmitFlag == XMT_DESTADDR ) {
copy_from_real ( destaddr,
@@ -264,16 +262,31 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
pxe_netdev->ll_protocol->ll_addr_len );
ll_dest = destaddr;
} else {
+ DBG ( " BCAST" );
ll_dest = pxe_netdev->ll_protocol->ll_broadcast;
}
- rc = net_tx ( iobuf, pxe_netdev, net_protocol, ll_dest );
+
+ /* Add link-layer header */
+ if ( ( rc = pxe_netdev->ll_protocol->push ( iobuf, pxe_netdev,
+ net_protocol,
+ ll_dest )) != 0 ){
+ free_iob ( iobuf );
+ undi_transmit->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+ }
+
+ /* Transmit packet */
+ if ( ( rc = netdev_tx ( pxe_netdev, iobuf ) ) != 0 ) {
+ undi_transmit->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
}
/* Flag transmission as in-progress */
undi_tx_count++;
- undi_transmit->Status = PXENV_STATUS ( rc );
- return ( ( rc == 0 ) ? PXENV_EXIT_SUCCESS : PXENV_EXIT_FAILURE );
+ undi_transmit->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
}
/* PXENV_UNDI_SET_MCAST_ADDRESS
@@ -531,6 +544,13 @@ PXENV_EXIT_t pxenv_undi_get_state ( struct s_PXENV_UNDI_GET_STATE
PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
struct io_buffer *iobuf;
size_t len;
+ struct ll_protocol *ll_protocol;
+ const void *ll_source;
+ uint16_t net_proto;
+ size_t ll_hlen;
+ struct net_protocol *net_protocol;
+ unsigned int prottype;
+ int rc;
DBG ( "PXENV_UNDI_ISR" );
@@ -559,13 +579,25 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS;
break;
case PXENV_UNDI_ISR_IN_PROCESS :
+ DBG ( " PROCESS" );
+ /* Fall through */
case PXENV_UNDI_ISR_IN_GET_NEXT :
- DBG ( " PROCESS/GET_NEXT" );
+ DBG ( " GET_NEXT" );
+
+ /* Some dumb NBPs (e.g. emBoot's winBoot/i) never call
+ * PXENV_UNDI_ISR with FuncFlag=PXENV_UNDI_ISR_START;
+ * they just sit in a tight polling loop merrily
+ * violating the PXE spec with repeated calls to
+ * PXENV_UNDI_ISR_IN_PROCESS. Force extra polls to
+ * cope with these out-of-spec clients.
+ */
+ netdev_poll ( pxe_netdev );
/* If we have not yet marked a TX as complete, and the
* netdev TX queue is empty, report the TX completion.
*/
if ( undi_tx_count && list_empty ( &pxe_netdev->tx_queue ) ) {
+ DBG ( " TXC" );
undi_tx_count--;
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_TRANSMIT;
break;
@@ -574,6 +606,7 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
/* Remove first packet from netdev RX queue */
iobuf = netdev_rx_dequeue ( pxe_netdev );
if ( ! iobuf ) {
+ DBG ( " DONE" );
/* No more packets remaining */
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
/* Re-enable interrupts */
@@ -583,24 +616,53 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
/* Copy packet to base memory buffer */
len = iob_len ( iobuf );
- DBG ( " RECEIVE %zd", len );
+ DBG ( " RX %zd", len );
if ( len > sizeof ( basemem_packet ) ) {
/* Should never happen */
len = sizeof ( basemem_packet );
}
memcpy ( basemem_packet, iobuf->data, len );
+ /* Strip link-layer header */
+ ll_protocol = pxe_netdev->ll_protocol;
+ if ( ( rc = ll_protocol->pull ( iobuf, pxe_netdev,
+ &net_proto,
+ &ll_source ) ) != 0 ) {
+ /* Assume unknown net_proto and no ll_source */
+ net_proto = 0;
+ ll_source = NULL;
+ }
+ ll_hlen = ( len - iob_len ( iobuf ) );
+
+ /* Determine network-layer protocol */
+ switch ( net_proto ) {
+ case htons ( ETH_P_IP ):
+ net_protocol = &ipv4_protocol;
+ prottype = P_IP;
+ break;
+ case htons ( ETH_P_ARP ):
+ net_protocol = &arp_protocol;
+ prottype = P_ARP;
+ break;
+ case htons ( ETH_P_RARP ):
+ net_protocol = &rarp_protocol;
+ prottype = P_RARP;
+ break;
+ default:
+ net_protocol = NULL;
+ prottype = P_UNKNOWN;
+ break;
+ }
+ DBG ( " %s", ( net_protocol ? net_protocol->name : "RAW" ) );
+
/* Fill in UNDI_ISR structure */
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_RECEIVE;
undi_isr->BufferLength = len;
undi_isr->FrameLength = len;
- undi_isr->FrameHeaderLength =
- pxe_netdev->ll_protocol->ll_header_len;
+ undi_isr->FrameHeaderLength = ll_hlen;
undi_isr->Frame.segment = rm_ds;
- undi_isr->Frame.offset =
- ( ( unsigned ) & __from_data16 ( basemem_packet ) );
- /* Probably ought to fill in packet type */
- undi_isr->ProtType = P_UNKNOWN;
+ undi_isr->Frame.offset = __from_data16 ( basemem_packet );
+ undi_isr->ProtType = prottype;
undi_isr->PktType = XMT_DESTADDR;
/* Free packet */