summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-06-18 18:16:48 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2010-06-18 18:19:37 -0700
commit42615d2c7eb2aeaea280891b80f1e76ac670fbf2 (patch)
tree6b46c98f6c4c30fc8d22e89f088256deae88d8ab
parentf23e586f898704626b4db5287a1c70cdfb11af5d (diff)
downloadsyslinux-42615d2c7eb2aeaea280891b80f1e76ac670fbf2.tar.gz
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@linux.intel.com>
-rw-r--r--com32/include/syslinux/config.h9
-rw-r--r--core/comboot.inc4
-rw-r--r--core/fs/pxe/dhcp_option.c12
-rw-r--r--core/fs/pxe/dnsresolv.c5
-rw-r--r--core/fs/pxe/idle.c2
-rw-r--r--core/fs/pxe/pxe.c42
-rw-r--r--core/fs/pxe/pxe.h29
-rw-r--r--core/pxelinux.asm14
-rw-r--r--doc/comboot.txt8
9 files changed, 82 insertions, 43 deletions
diff --git a/com32/include/syslinux/config.h b/com32/include/syslinux/config.h
index 868b0f10..60d8d231 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 45b770f3..0c9956a0 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 e18b605d..39b51666 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 df7f33c1..ecee7854 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 0538b163..52a87c34 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 011ef293..ef2398b4 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 e801aea5..cad63507 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 0b87e735..6fb77c25 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 f39d7243..036bd784 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