[syslinux:pathbased] pxe: centralize all the IP information and export it to modules

syslinux-bot for H. Peter Anvin hpa at linux.intel.com
Fri Jun 18 18:30:18 PDT 2010


Commit-ID:  42615d2c7eb2aeaea280891b80f1e76ac670fbf2
Gitweb:     http://syslinux.zytor.com/commit/42615d2c7eb2aeaea280891b80f1e76ac670fbf2
Author:     H. Peter Anvin <hpa at linux.intel.com>
AuthorDate: Fri, 18 Jun 2010 18:16:48 -0700
Committer:  H. Peter Anvin <hpa at linux.intel.com>
CommitDate: Fri, 18 Jun 2010 18:19:37 -0700

pxe: centralize all the IP information and export it to modules

It appears that there still are PXE stacks in the field which needs
the crutch of being pointed to the default gateway.  As such, put all
the IP information into a single memory structure and allow modules to
see it.

Signed-off-by: H. Peter Anvin <hpa at linux.intel.com>


---
 com32/include/syslinux/config.h |    9 ++++++++
 core/comboot.inc                |    4 ++-
 core/fs/pxe/dhcp_option.c       |   12 +++++-----
 core/fs/pxe/dnsresolv.c         |    5 ++-
 core/fs/pxe/idle.c              |    2 +-
 core/fs/pxe/pxe.c               |   42 ++++++++++++++++----------------------
 core/fs/pxe/pxe.h               |   29 +++++++++++++++++++++-----
 core/pxelinux.asm               |   14 ++++++++++--
 doc/comboot.txt                 |    8 +++++++
 9 files changed, 82 insertions(+), 43 deletions(-)

diff --git a/com32/include/syslinux/config.h b/com32/include/syslinux/config.h
index 868b0f1..60d8d23 100644
--- a/com32/include/syslinux/config.h
+++ b/com32/include/syslinux/config.h
@@ -54,6 +54,14 @@ struct syslinux_version {
     const char *copyright_string;
 };
 
+struct syslinux_ipinfo {
+    uint32_t ipver;
+    uint32_t myip;
+    uint32_t netmask;
+    uint32_t gateway;
+    uint32_t serverip;
+};
+
 extern __nocommon struct syslinux_version __syslinux_version;
 static inline const struct syslinux_version *syslinux_version(void)
 {
@@ -116,6 +124,7 @@ union syslinux_derivative_info {
 	uint32_t _eflags;
 	const void *pxenvptr;
 	const void *stack;
+	const struct syslinux_ipinfo *ipinfo;
     } pxe;			/* pxelinux */
     struct {
 	uint16_t _gs, _fs, _es, _ds;
diff --git a/core/comboot.inc b/core/comboot.inc
index 45b770f..0c9956a 100644
--- a/core/comboot.inc
+++ b/core/comboot.inc
@@ -580,8 +580,10 @@ comapi_derinfo:
 		mov P_SI,ax
 		mov ax,[InitStack+2]
 		mov P_FS,ax
-		mov eax,[MyIP]
+		mov eax,[IPInfo.MyIP]
 		mov P_ECX,eax
+		mov P_GS,0
+		mov P_DI,IPInfo
 %else
 		; Physical medium...
 
diff --git a/core/fs/pxe/dhcp_option.c b/core/fs/pxe/dhcp_option.c
index e18b605..39b5166 100644
--- a/core/fs/pxe/dhcp_option.c
+++ b/core/fs/pxe/dhcp_option.c
@@ -16,14 +16,14 @@ static void subnet_mask(void *data, int opt_len)
 {
     if (opt_len != 4)
 	return;
-    net_mask = *(uint32_t *)data;
+    IPInfo.netmask = *(uint32_t *)data;
 }
 
 static void router(void *data, int opt_len)
 {
     if (opt_len != 4)
 	return;
-    gate_way = *(uint32_t *)data;
+    IPInfo.gateway = *(uint32_t *)data;
 }
 
 static void dns_servers(void *data, int opt_len)
@@ -83,12 +83,12 @@ static void server(void *data, int opt_len)
     if (opt_len != 4)
 	return;
     
-    if (server_ip)
+    if (IPInfo.serverip)
         return;
     
     ip = *(uint32_t *)data;
     if (ip_ok(ip))
-        server_ip = ip;
+        IPInfo.serverip = ip;
 }
 
 static void client_identifier(void *data, int opt_len)
@@ -246,10 +246,10 @@ void parse_dhcp(int pkt_len)
 
     over_load = 0;
     if (ip_ok(dhcp->yip))
-        MyIP = dhcp->yip;
+        IPInfo.myip = dhcp->yip;
     
     if (ip_ok(dhcp->sip))
-        server_ip = dhcp->sip;
+        IPInfo.serverip = dhcp->sip;
     
     opt_len = (char *)dhcp + pkt_len - (char *)&dhcp->options;
     if (opt_len && (dhcp->option_magic == BOOTP_OPTION_MAGIC)) 
diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c
index df7f33c..ecee785 100644
--- a/core/fs/pxe/dnsresolv.c
+++ b/core/fs/pxe/dnsresolv.c
@@ -229,7 +229,7 @@ uint32_t dns_resolv(const char *name)
 	    continue;  /* just move on before runing the time out */
         udp_write.status      = 0;
         udp_write.ip          = srv;
-        udp_write.gw          = ((srv ^ MyIP) & net_mask) ? gate_way : 0;
+        udp_write.gw          = gateway(srv);
         udp_write.src_port    = local_port;
         udp_write.dst_port    = DNS_PORT;
         udp_write.buffer_size = p - DNSSendBuf;
@@ -242,7 +242,7 @@ uint32_t dns_resolv(const char *name)
 	while (1) {
             udp_read.status      = 0;
             udp_read.src_ip      = srv;
-            udp_read.dest_ip     = MyIP;
+            udp_read.dest_ip     = IPInfo.myip;
             udp_read.s_port      = DNS_PORT;
             udp_read.d_port      = local_port;
             udp_read.buffer_size = DNS_MAX_PACKET;
@@ -349,4 +349,5 @@ void pxe_dns_resolv(com32sys_t *regs)
     const char *name = MK_PTR(regs->ds, regs->esi.w[0]);
 
     regs->eax.l = dns_resolv(name);
+    printf("dnsresolv returns %08x\n", regs->eax.l);
 }
diff --git a/core/fs/pxe/idle.c b/core/fs/pxe/idle.c
index 0538b16..52a87c3 100644
--- a/core/fs/pxe/idle.c
+++ b/core/fs/pxe/idle.c
@@ -27,7 +27,7 @@ static int pxe_idle_poll(void)
     memset(&read_buf, 0, sizeof read_buf);
 
     read_buf.src_ip  = 0;	 /* Any destination */
-    read_buf.dest_ip = MyIP;
+    read_buf.dest_ip = IPInfo.myip;
     read_buf.s_port  = 0;	 /* Any source port */
     read_buf.d_port  = htons(9); /* Discard port (not used...) */
     read_buf.buffer_size = sizeof junk_pkt;
diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c
index 011ef29..ef2398b 100644
--- a/core/fs/pxe/pxe.c
+++ b/core/fs/pxe/pxe.c
@@ -9,10 +9,7 @@
 
 #define GPXE 1
 
-uint32_t server_ip = 0;            /* IP address of boot server */
-uint32_t net_mask = 0;             /* net_mask of this subnet */
-uint32_t gate_way = 0;             /* Default router */
-uint16_t real_base_mem;            /* Amount of DOS memory after freeing */
+static uint16_t real_base_mem;	   /* Amount of DOS memory after freeing */
 
 uint8_t MAC[MAC_MAX];		   /* Actual MAC address */
 uint8_t MAC_len;                   /* MAC address len */
@@ -297,7 +294,7 @@ static void tftp_error(struct inode *inode, uint16_t errnum,
     udp_write.src_port    = socket->tftp_localport;
     udp_write.dst_port    = socket->tftp_remoteport;
     udp_write.ip          = socket->tftp_remoteip;
-    udp_write.gw          = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0;
+    udp_write.gw          = gateway(udp_write.ip);
     udp_write.buffer      = FAR_PTR(&err_buf);
     udp_write.buffer_size = 4 + len + 1;
 
@@ -326,7 +323,7 @@ static void ack_packet(struct inode *inode, uint16_t ack_num)
     udp_write.src_port    = socket->tftp_localport;
     udp_write.dst_port    = socket->tftp_remoteport;
     udp_write.ip          = socket->tftp_remoteip;
-    udp_write.gw          = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0;
+    udp_write.gw          = gateway(udp_write.ip);
     udp_write.buffer      = FAR_PTR(ack_packet_buf);
     udp_write.buffer_size = 4;
 
@@ -513,7 +510,7 @@ static void fill_buffer(struct inode *inode)
         udp_read.buffer      = FAR_PTR(packet_buf);
         udp_read.buffer_size = PKTBUF_SIZE;
         udp_read.src_ip      = socket->tftp_remoteip;
-        udp_read.dest_ip     = MyIP;
+        udp_read.dest_ip     = IPInfo.myip;
         udp_read.s_port      = socket->tftp_remoteport;
         udp_read.d_port      = socket->tftp_localport;
         err = pxe_call(PXENV_UDP_READ, &udp_read);
@@ -688,12 +685,12 @@ static void pxe_searchdir(const char *filename, struct file *file)
     case PXE_RELATIVE:		/* Really shouldn't happen... */
     case PXE_URL:
 	buf = stpcpy(buf, filename);
-	ip = server_ip;		/* Default server */
+	ip = IPInfo.serverip;	/* Default server */
 	break;
 
     case PXE_HOMESERVER:
 	buf = stpcpy(buf, filename+2);
-	ip = server_ip;
+	ip = IPInfo.serverip;
 	break;
 
     case PXE_TFTP:
@@ -781,7 +778,7 @@ sendreq:
     tid = socket->tftp_localport;   /* TID(local port No) */
     udp_write.buffer    = FAR_PTR(rrq_packet_buf);
     udp_write.ip        = ip;
-    udp_write.gw        = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0;
+    udp_write.gw        = gateway(udp_write.ip);
     udp_write.src_port  = tid;
     udp_write.dst_port  = server_port;
     udp_write.buffer_size = buf - rrq_packet_buf;
@@ -794,7 +791,7 @@ wait_pkt:
         buf                  = packet_buf;
         udp_read.buffer      = FAR_PTR(buf);
         udp_read.buffer_size = PKTBUF_SIZE;
-        udp_read.dest_ip     = MyIP;
+        udp_read.dest_ip     = IPInfo.myip;
         udp_read.d_port      = tid;
         err = pxe_call(PXENV_UDP_READ, &udp_read);
         if (err) {
@@ -1107,7 +1104,7 @@ static int pxe_load_config(void)
         return 0;
 
     /* Nope, try hexadecimal IP prefixes... */
-    uchexbytes(config_file, (uint8_t *)&MyIP, 4);     /* Convet to hex string */
+    uchexbytes(config_file, (uint8_t *)&IPInfo.myip, 4);     /* Convet to hex string */
     last = &config_file[8];
     while (tries) {
         *last = '\0';        /* Zero-terminate string */
@@ -1151,26 +1148,23 @@ char __bss16 IPOption[3+4*16];
 static void genipopt(void)
 {
     char *p = IPOption;
+    const uint32_t *v = &IPInfo.myip;
+    int i;
 
     p = stpcpy(p, "ip=");
 
-    p += gendotquad(p, MyIP);
-    *p++ = ':';
-
-    p += gendotquad(p, server_ip);
-    *p++ = ':';
-
-    p += gendotquad(p, gate_way);
-    *p++ = ':';
-
-    gendotquad(p, net_mask);
+    for (i = 0; i < 4; i++) {
+	p += gendotquad(p, *v++);
+	*p++ = ':';
+    }
+    *--p = '\0';
 }
 
 
 /* Generate ip= option and print the ip adress */
 static void ip_init(void)
 {
-    uint32_t ip = MyIP;
+    uint32_t ip = IPInfo.myip;
 
     genipopt();
     gendotquad(dot_quad_buf, ip);
@@ -1412,7 +1406,7 @@ static void udp_init(void)
 {
     int err;
     static __lowmem struct s_PXENV_UDP_OPEN udp_open;
-    udp_open.src_ip = MyIP;
+    udp_open.src_ip = IPInfo.myip;
     err = pxe_call(PXENV_UDP_OPEN, &udp_open);
     if (err || udp_open.status) {
         printf("Failed to initialize UDP stack ");
diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h
index e801aea..cad6350 100644
--- a/core/fs/pxe/pxe.h
+++ b/core/fs/pxe/pxe.h
@@ -170,13 +170,20 @@ struct pxe_pvt_inode {
 #define PVT(i) ((struct pxe_pvt_inode *)((i)->pvt))
 
 /*
+ * Network boot information
+ */
+struct ip_info {
+    uint32_t ipv4;
+    uint32_t myip;
+    uint32_t serverip;
+    uint32_t gateway;
+    uint32_t netmask;
+};
+
+/*
  * Variable externs
  */
-extern uint32_t server_ip;
-extern uint32_t MyIP;
-extern uint32_t net_mask;
-extern uint32_t gate_way;
-extern uint16_t server_port;
+extern struct ip_info IPInfo;
 
 extern uint8_t MAC[];
 extern char BOOTIFStr[];
@@ -195,7 +202,6 @@ extern char dot_quad_buf[];
 
 extern uint32_t dns_server[];
 
-extern uint16_t real_base_mem;
 extern uint16_t APIVer;
 extern far_ptr_t PXEEntry;
 extern uint8_t KeepPXE;
@@ -209,6 +215,17 @@ extern char uuid[];
 extern uint16_t BIOS_fbm;
 extern const uint8_t TimeoutTable[];
 
+/*
+ * Compute the suitable gateway for a specific route -- too many
+ * vendor PXE stacks don't do this correctly...
+ */
+static inline uint32_t gateway(uint32_t ip)
+{
+    if ((ip ^ IPInfo.myip) & IPInfo.netmask)
+	return IPInfo.gateway;
+    else
+	return 0;
+}
 
 /*
  * functions 
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index 0b87e73..6fb77c2 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -530,7 +530,15 @@ exten_table_end:
 KeepPXE		db 0			; Should PXE be kept around?
 
 ;
-; IP information (initialized to "unknown" values)
+; IP information.  Note that the field are in the same order as the
+; Linux kernel expects in the ip= option.
+;
+		section .bss16
 		alignz 4
-                global MyIP
-MyIP		dd 0			; My IP address 
+		global IPInfo
+IPInfo:
+.IPv4		resd 1			; IPv4 information
+.MyIP		resd 1			; My IP address 
+.ServerIP	resd 1
+.GatewayIP	resd 1
+.Netmask	resd 1
diff --git a/doc/comboot.txt b/doc/comboot.txt
index f39d724..036bd78 100644
--- a/doc/comboot.txt
+++ b/doc/comboot.txt
@@ -448,6 +448,7 @@ AX=000Ah [2.00]	Get Derivative-Specific Information
 		ECX	Local IP number (network byte order) [3.85]
 		ES:BX	pointer to PXENV+ or !PXE structure
 		FS:SI	pointer to original stack with invocation record
+		GS:DI	pointer to network information [4.00]
 
 		Note: DX notes the API version detected by PXELINUX,
 		which may be more conservative than the actual version
@@ -481,6 +482,13 @@ AX=000Ah [2.00]	Get Derivative-Specific Information
 		[fs:si+44]	PXE return IP	<- t.o.s. when PXELINUX invoked
 		[fs:si+46]	PXE return CS
 
+		GS:DI points to a structure of the following form:
+
+		[gs:di+0]	4		- IPv4
+		[gs:di+4]	My IP
+		[gs:di+8]	Boot server IP
+		[gs:di+12]	Gateway IP
+		[gs:di+16]	Netmask
 
 	[ISOLINUX]
 	Input:	AX	000Ah



More information about the Syslinux-commits mailing list