aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-06-18 18:45:02 -0700
committerH. Peter Anvin <hpa@zytor.com>2010-06-18 18:45:02 -0700
commit7c890f5a328f6f0fc7e293247cbbcb18d369c447 (patch)
tree0f0a2a13578c9aeecba8d0fcf2f88d33309db450
parente554f2fadd8d7a79a0f84707e545c31997c93528 (diff)
parentc81d67125d108a5e76039ac6ebaf5b24bca7c107 (diff)
downloadsyslinux-7c890f5a328f6f0fc7e293247cbbcb18d369c447.tar.gz
syslinux-7c890f5a328f6f0fc7e293247cbbcb18d369c447.tar.xz
syslinux-7c890f5a328f6f0fc7e293247cbbcb18d369c447.zip
Merge branch 'pathbased' of ssh://terminus.zytor.com/pub/git/syslinux/syslinux into pathbasedsyslinux-4.00-pre50
-rw-r--r--com32/include/syslinux/config.h9
-rw-r--r--com32/sysdump/acpi.c175
-rw-r--r--com32/sysdump/be_tftp.c27
-rw-r--r--com32/sysdump/main.c1
-rw-r--r--com32/sysdump/memmap.c6
-rw-r--r--com32/sysdump/sysdump.h1
-rw-r--r--com32/sysdump/vesa.c7
-rw-r--r--core/comboot.inc4
-rw-r--r--core/fs/pxe/dhcp_option.c12
-rw-r--r--core/fs/pxe/dnsresolv.c4
-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
15 files changed, 289 insertions, 52 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/com32/sysdump/acpi.c b/com32/sysdump/acpi.c
new file mode 100644
index 00000000..48b890ae
--- /dev/null
+++ b/com32/sysdump/acpi.c
@@ -0,0 +1,175 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2010 Intel Corporation; author: H. Peter Anvin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston MA 02110-1301, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Dump ACPI information
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "sysdump.h"
+#include "backend.h"
+
+struct acpi_rsdp {
+ uint8_t magic[8]; /* "RSD PTR " */
+ uint8_t csum;
+ char oemid[6];
+ uint8_t rev;
+ uint32_t rsdt_addr;
+ uint32_t len;
+ uint64_t xdst_addr;
+ uint8_t xcsum;
+ uint8_t rsvd[3];
+};
+
+struct acpi_hdr {
+ char sig[4]; /* Signature */
+ uint32_t len;
+ uint8_t rev;
+ uint8_t csum;
+ char oemid[6];
+ char oemtblid[16];
+ uint32_t oemrev;
+ uint32_t creatorid;
+ uint32_t creatorrev;
+};
+
+struct acpi_rsdt {
+ struct acpi_hdr hdr;
+ uint32_t entry[0];
+};
+
+enum tbl_errs {
+ ERR_NONE, /* No errors */
+ ERR_CSUM, /* Invalid checksum */
+ ERR_SIZE, /* Impossibly large table */
+ ERR_NOSIG /* No signature */
+};
+
+static uint8_t checksum_range(const void *start, uint32_t size)
+{
+ const uint8_t *p = start;
+ uint8_t csum = 0;
+
+ while (size--)
+ csum += *p++;
+
+ return csum;
+}
+
+static enum tbl_errs is_valid_table(const void *ptr)
+{
+ const struct acpi_hdr *hdr = ptr;
+
+ if (hdr->sig[0] == 0)
+ return ERR_NOSIG;
+
+ if (hdr->len < 10 || hdr->len > (1 << 20)) {
+ /* Either insane or too large to dump */
+ return ERR_SIZE;
+ }
+
+ return checksum_range(hdr, hdr->len) == 0 ? ERR_NONE : ERR_CSUM;
+}
+
+static const struct acpi_rsdp *scan_for_rsdp(uint32_t base, uint32_t end)
+{
+ for (base &= ~15; base < end-20; base += 16) {
+ const struct acpi_rsdp *rsdp = (const struct acpi_rsdp *)base;
+
+ if (memcmp(rsdp->magic, "RSD PTR ", 8))
+ continue;
+
+ if (checksum_range(rsdp, 20))
+ continue;
+
+ if (rsdp->rev > 0) {
+ if (base + rsdp->len >= end ||
+ checksum_range(rsdp, rsdp->len))
+ continue;
+ }
+
+ return rsdp;
+ }
+
+ return NULL;
+}
+
+static const struct acpi_rsdp *find_rsdp(void)
+{
+ uint32_t ebda;
+ const struct acpi_rsdp *rsdp;
+
+ ebda = (*(uint16_t *)0x40e) << 4;
+ if (ebda >= 0x70000 && ebda < 0xa0000) {
+ rsdp = scan_for_rsdp(ebda, ebda+1024);
+
+ if (rsdp)
+ return rsdp;
+ }
+
+ return scan_for_rsdp(0xe0000, 0x100000);
+}
+
+static void dump_table(struct backend *be,
+ const char name[], const void *ptr, uint32_t len)
+{
+ char namebuf[64];
+
+ /* XXX: this make cause the same directory to show up more than once */
+ snprintf(namebuf, sizeof namebuf, "acpi/%4.4s", name);
+ cpio_mkdir(be, namebuf);
+
+ snprintf(namebuf, sizeof namebuf, "acpi/%4.4s/%08x", name, (uint32_t)ptr);
+ cpio_hdr(be, MODE_FILE, len, namebuf);
+
+ write_data(be, ptr, len);
+}
+
+void dump_acpi(struct backend *be)
+{
+ const struct acpi_rsdp *rsdp;
+ const struct acpi_rsdt *rsdt;
+ uint32_t rsdp_len;
+ uint32_t i, n;
+
+ rsdp = find_rsdp();
+
+ if (!rsdp)
+ return; /* No ACPI information found */
+
+ cpio_mkdir(be, "acpi");
+
+ rsdp_len = rsdp->rev > 0 ? rsdp->len : 20;
+
+ dump_table(be, "RSDP", rsdp, rsdp_len);
+
+ rsdt = (const struct acpi_rsdt *)rsdp->rsdt_addr;
+
+ if (memcmp(rsdt->hdr.sig, "RSDT", 4) || is_valid_table(rsdt) != ERR_NONE)
+ return;
+
+ dump_table(be, rsdt->hdr.sig, rsdt, rsdt->hdr.len);
+
+ if (rsdt->hdr.len < 36)
+ return;
+
+ n = (rsdt->hdr.len - 36) >> 2;
+
+ for (i = 0; i < n; i++) {
+ const struct acpi_hdr *hdr = (const struct acpi_hdr *)(rsdt->entry[i]);
+
+ if (is_valid_table(hdr) <= ERR_CSUM)
+ dump_table(be, hdr->sig, hdr, hdr->len);
+ }
+}
diff --git a/com32/sysdump/be_tftp.c b/com32/sysdump/be_tftp.c
index 07fdb084..8c92d4d6 100644
--- a/com32/sysdump/be_tftp.c
+++ b/com32/sysdump/be_tftp.c
@@ -21,23 +21,30 @@ enum tftp_opcode {
struct tftp_state {
uint32_t my_ip;
uint32_t srv_ip;
+ uint32_t srv_gw;
uint16_t my_port;
uint16_t srv_port;
uint16_t seq;
};
+#define RCV_BUF 2048
+
static int send_ack_packet(struct tftp_state *tftp,
const void *pkt, size_t len)
{
com32sys_t ireg, oreg;
- t_PXENV_UDP_WRITE *uw = __com32.cs_bounce;
- t_PXENV_UDP_READ *ur = __com32.cs_bounce;
+ t_PXENV_UDP_WRITE *uw;
+ t_PXENV_UDP_READ *ur;
clock_t start;
static const clock_t timeouts[] = {
2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31,
37, 44, 53, 64, 77, 92, 110, 132, 159, 191, 229, 0
};
const clock_t *timeout;
+ int err = -1;
+
+ uw = lmalloc(sizeof *uw + len);
+ ur = lmalloc(sizeof *ur + RCV_BUF);
memset(&ireg, 0, sizeof ireg);
ireg.eax.w[0] = 0x0009;
@@ -46,6 +53,7 @@ static int send_ack_packet(struct tftp_state *tftp,
memset(uw, 0, sizeof uw);
memcpy(uw+1, pkt, len);
uw->ip = tftp->srv_ip;
+ uw->gw = tftp->srv_gw;
uw->src_port = tftp->my_port;
uw->dst_port = tftp->srv_port ? tftp->srv_port : htons(69);
uw->buffer_size = len;
@@ -65,7 +73,7 @@ static int send_ack_packet(struct tftp_state *tftp,
ur->dest_ip = tftp->my_ip;
ur->s_port = tftp->srv_port;
ur->d_port = tftp->my_port;
- ur->buffer_size = __com32.cs_bounce_size - sizeof *ur;
+ ur->buffer_size = RCV_BUF;
ur->buffer = FAR_PTR(ur+1);
ireg.ebx.w[0] = PXENV_UDP_READ;
@@ -82,15 +90,20 @@ static int send_ack_packet(struct tftp_state *tftp,
if (ntohs(xb[0]) == TFTP_ACK &&
ntohs(xb[1]) == tftp->seq) {
tftp->srv_port = ur->s_port;
- return 0; /* All good! */
+ err = 0; /* All good! */
+ goto done;
} else if (ntohs(xb[1]) == TFTP_ERROR) {
- return -1; /* All bad! */
+ goto done;
}
}
} while ((clock_t)(times(NULL) - start) < *timeout);
}
- return -1; /* No success... */
+done:
+ lfree(ur);
+ lfree(uw);
+
+ return err;
}
static int be_tftp_write(struct backend *be)
@@ -108,6 +121,8 @@ static int be_tftp_write(struct backend *be)
tftp.my_ip = sdi->pxe.myip;
tftp.my_port = htons(local_port++);
tftp.srv_ip = pxe_dns(be->argv[1]);
+ tftp.srv_gw = ((tftp.srv_ip ^ tftp.my_ip) & sdi->pxe.ipinfo->netmask)
+ ? sdi->pxe.ipinfo->gateway : 0;
tftp.srv_port = 0;
tftp.seq = 0;
diff --git a/com32/sysdump/main.c b/com32/sysdump/main.c
index d4a0320e..26f562be 100644
--- a/com32/sysdump/main.c
+++ b/com32/sysdump/main.c
@@ -41,6 +41,7 @@ static void dump_all(struct backend *be, const char *argv[])
dump_memory_map(be);
dump_memory(be);
dump_dmi(be);
+ dump_acpi(be);
dump_cpuid(be);
dump_pci(be);
dump_vesa_tables(be);
diff --git a/com32/sysdump/memmap.c b/com32/sysdump/memmap.c
index a85f0925..251107d5 100644
--- a/com32/sysdump/memmap.c
+++ b/com32/sysdump/memmap.c
@@ -19,10 +19,12 @@ struct e820_info {
static void dump_e820(struct backend *be)
{
com32sys_t ireg, oreg;
- struct e820_info *curr = __com32.cs_bounce;
+ struct e820_info *curr;
struct e820_info *buf, *p;
int nentry, nalloc;
+ curr = lmalloc(sizeof *curr);
+
buf = p = NULL;
nentry = nalloc = 0;
memset(&ireg, 0, sizeof ireg);
@@ -56,7 +58,9 @@ static void dump_e820(struct backend *be)
if (nentry)
cpio_writefile(be, "memmap/15e820", buf, nentry*sizeof *buf);
+
free(buf);
+ lfree(curr);
}
void dump_memory_map(struct backend *be)
diff --git a/com32/sysdump/sysdump.h b/com32/sysdump/sysdump.h
index 61a04a2b..a5b963f8 100644
--- a/com32/sysdump/sysdump.h
+++ b/com32/sysdump/sysdump.h
@@ -7,6 +7,7 @@ void dump_memory_map(struct backend *);
void snapshot_lowmem(void);
void dump_memory(struct backend *);
void dump_dmi(struct backend *);
+void dump_acpi(struct backend *);
void dump_cpuid(struct backend *);
void dump_pci(struct backend *);
void dump_vesa_tables(struct backend *);
diff --git a/com32/sysdump/vesa.c b/com32/sysdump/vesa.c
index 9bdc7153..017f9e4f 100644
--- a/com32/sysdump/vesa.c
+++ b/com32/sysdump/vesa.c
@@ -7,6 +7,7 @@
void dump_vesa_tables(struct backend *be)
{
com32sys_t rm;
+ struct vesa_info *vip;
struct vesa_general_info *gip, gi;
struct vesa_mode_info *mip, mi;
uint16_t mode, *mode_ptr;
@@ -15,8 +16,9 @@ void dump_vesa_tables(struct backend *be)
printf("Scanning VESA BIOS... ");
/* Allocate space in the bounce buffer for these structures */
- gip = &((struct vesa_info *)__com32.cs_bounce)->gi;
- mip = &((struct vesa_info *)__com32.cs_bounce)->mi;
+ vip = lmalloc(sizeof *vip);
+ gip = &vip->gi;
+ mip = &vip->mi;
memset(&rm, 0, sizeof rm);
memset(gip, 0, sizeof *gip);
@@ -56,5 +58,6 @@ void dump_vesa_tables(struct backend *be)
cpio_writefile(be, modefile, &mi, sizeof mi);
}
+ lfree(vip);
printf("done.\n");
}
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..134f24e3 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;
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