aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Aleaxander <Aleaxander@gmail.com>2009-07-31 17:18:21 +0800
committerLiu Aleaxander <Aleaxander@gmail.com>2009-07-31 17:18:21 +0800
commit93dc20622287f0c15333e5ff3e6498b74d090c57 (patch)
treef4a7a7cc7f665adb7e4cd922827d0701f4ad1e29
parent0df8459206c0f622442af76e80d5851100d30318 (diff)
downloadpxelinux-93dc20622287f0c15333e5ff3e6498b74d090c57.tar.gz
pxelinux-93dc20622287f0c15333e5ff3e6498b74d090c57.tar.xz
pxelinux-93dc20622287f0c15333e5ff3e6498b74d090c57.zip
Core:PXELINUX: commit the patch from hpa
-rw-r--r--core/pxe.c200
1 files changed, 114 insertions, 86 deletions
diff --git a/core/pxe.c b/core/pxe.c
index da989f94..e09c9ff7 100644
--- a/core/pxe.c
+++ b/core/pxe.c
@@ -2,6 +2,7 @@
#include <string.h>
#include <core.h>
#include <pxe.h>
+#include <sys/cpu.h>
#define MAX_OPEN_LG2 5
#define MAX_OPEN (1 << MAX_OPEN_LG2)
@@ -15,7 +16,7 @@
#define MAX(a,b) (a > b ? a : b)
-#define GPXE 1
+#define GPXE 0
#define USE_PXE_PROVIDED_STACK 0
#define is_digit(c) (((c) >= '0') && ((c) <= '9'))
@@ -151,7 +152,7 @@ extern uint32_t RebootTime;
/* TFTP ACK packet */
extern uint16_t ack_packet_buf[];
-extern void kaboom();
+extern void kaboom(void);
extern char trackbuf[];
extern char BootFile[];
extern char PathPrefix[];
@@ -164,8 +165,8 @@ extern char DotQuadBuf[];
extern uint32_t DNSServers[];
extern uint16_t LastDNSServer;
-extern void dhcp_option_list();
-extern void dhcp_option_list_end();
+extern void dhcp_option_list(void);
+extern void dhcp_option_list_end(void);
char *err_nopxe = "No !PXE or PXENV+ API found; we're dead...\n";
char *err_pxefailed = "PXE API call failed, error ";
@@ -188,12 +189,10 @@ com32sys_t temp;
extern uint16_t RealBaseMem;
extern uint16_t APIVer;
-extern void PXEEntry();
-uint16_t *pxeentry = (uint16_t *)PXEEntry;
+extern far_ptr_t PXEEntry;
uint16_t StructPtr[2];
-extern uint32_t InitStack;
-uint16_t *init_stack = (uint16_t *)&InitStack;
+extern far_ptr_t InitStack;
struct stack {
uint32_t esp;
@@ -202,11 +201,11 @@ struct stack {
extern char BaseStack[];
struct stack *stack = (struct stack *)BaseStack;
-extern uint16_t volatile BIOS_timer;
-uint8_t TimeoutTable[] = {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, 255, 255, 255, 255, 0};
-
+extern volatile uint16_t BIOS_timer;
+static const uint8_t TimeoutTable[] = {
+ 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, 255, 255, 255, 255, 0
+};
inline void pusha(com32sys_t *regs)
{
@@ -269,6 +268,11 @@ void is_url(com32sys_t *regs)
}
regs->eflags.l |= EFLAGS_CF;
}
+#else
+void is_url(com32sys_t *regs)
+{
+ regs->eflags.l |= EFLAGS_CF;
+}
#endif /* GPXE */
/*
@@ -321,8 +325,8 @@ void mangle_name(com32sys_t *regs)
if ((p = parse_dotquad(p, &ip)) && !strncmp(p, "::", 2))
goto gotprefix;
else {
- extern void dns_resolv();
- dns_resolv(regs);
+ extern void dns_resolv(void);
+ call16(dns_resolv, regs, regs);
p = (char *)MK_PTR(regs->ds, regs->esi.w[0]);
ip = regs->eax.l;
if (! strncmp(p, "::", 2))
@@ -379,13 +383,14 @@ void mangle_name(com32sys_t *regs)
*
* Trashes AX, DX
*/
-void lchexbytes(uint8_t *dst, uint8_t *src, int count)
+void lchexbytes(char *dst, const void *src, int count)
{
uint8_t half;
uint8_t c;
+ const uint8_t *s = src;
for(; count > 0; count--) {
- c = *src++;
+ c = *s++;
half = ((c >> 4) & 0x0f) + '0';
*dst++ = half > '9' ? (half + 'a' - '9' - 1) : half;
@@ -398,13 +403,14 @@ void lchexbytes(uint8_t *dst, uint8_t *src, int count)
* just like the lchexbytes, except to upper-case
*
*/
-void uchexbytes(uint8_t *dst, uint8_t *src, int count)
+void uchexbytes(char *dst, const void *src, int count)
{
uint8_t half;
uint8_t c;
+ const uint8_t *s = src;
for(; count > 0; count--) {
- c = *src++;
+ c = *s++;
half = ((c >> 4) & 0x0f) + '0';
*dst++ = half > '9' ? (half + 'A' - '9' - 1) : half;
@@ -424,17 +430,17 @@ void uchexbytes(uint8_t *dst, uint8_t *src, int count)
*/
int is_pxe(com32sys_t *regs)
{
- char *p = (char *)MK_PTR(regs->es, regs->ebx.w[0]);
+ uint8_t *p = MK_PTR(regs->es, regs->ebx.w[0]);
int i;
uint8_t sum = 0;
-
- if (strncmp(p, "!PXE", 4))
+
+ if (memcmp(p, "!PXE", 4))
goto bad;
- i = (int)*(p + 4);
- if ( i < 0x58)
+ i = p[4];
+ if (i < 0x58)
goto bad;
- for (; i > 0; i--)
+ while (i--)
sum += *p++;
if (sum == 0) {
@@ -443,6 +449,7 @@ int is_pxe(com32sys_t *regs)
}
bad:
+ regs->eflags.l &= ~EFLAGS_ZF;
return 0;
}
@@ -452,17 +459,17 @@ int is_pxe(com32sys_t *regs)
*/
int is_pxenv(com32sys_t *regs)
{
- char *p = (char *)MK_PTR(regs->es, regs->ebx.w[0]);
+ uint8_t *p = MK_PTR(regs->es, regs->ebx.w[0]);
int i;
uint8_t sum = 0;
- if (strncmp(p, "PXENV+", 6))
+ if (memcmp(p, "PXENV+", 6))
goto bad;
- i = (int)*(p + 8);
- if ( i < 0x28)
+ i = p[8];
+ if (i < 0x28)
goto bad;
- for (; i > 0; i--)
+ while (i--)
sum += *p++;
if (sum == 0) {
@@ -471,6 +478,7 @@ int is_pxenv(com32sys_t *regs)
}
bad:
+ regs->eflags.l &= ~EFLAGS_ZF;
return 0;
}
@@ -497,7 +505,7 @@ int is_pxenv(com32sys_t *regs)
inline int memory_scan(uint16_t seg, com32sys_t *regs,
int (*func)(com32sys_t *))
{
- while (seg < 0xA000 - 1) {
+ while (seg < 0xA000) {
regs->es = seg;
regs->ebx.w[0] = 0;
if (func(regs))
@@ -593,12 +601,11 @@ void genipopt(com32sys_t *regs)
*/
int try_load(com32sys_t *regs)
{
- extern void open();
+ extern void open(void);
extern char KernelName[];
char *config_name = (char *)MK_PTR(regs->ds, regs->edi.w[0]);
- char *trying_msg = "Trying to load: ";
- printf("%s%s ", trying_msg, config_name);
+ printf("Trying to load: %-50s ", config_name);
regs->edi.w[0] = OFFS_WRT(KernelName, 0);
regs->esi.w[0] = OFFS_WRT(config_name, 0);
@@ -609,7 +616,7 @@ int try_load(com32sys_t *regs)
printf(" [FAILED]\n");
return 0;
} else {
- printf(" [OK ]\n");
+ printf(" [ OK ]\n");
return 1;
}
}
@@ -621,16 +628,16 @@ int try_load(com32sys_t *regs)
*/
void pxe_load_config(com32sys_t *regs)
{
- extern void no_config();
+ extern void no_config(void);
char *cfgprefix = "pxelinux.cfg/";
char *default_str = "default";
- char *config_file;
-
+ char *config_file; /* Pointer to the variable suffix */
+ char *p;
uint8_t *uuid_ptr;
int tries = 8;
- uint8_t *last;
+ char *last;
if (DHCPMagic & 0x02) {
/* We got a DHCP option, try it first */
@@ -647,18 +654,19 @@ void pxe_load_config(com32sys_t *regs)
/* Try loading by UUID */
if (HaveUUID) {
uuid_ptr = uuid_dashes;
+ p = config_file;
while (*uuid_ptr) {
int len = *uuid_ptr;
char *src = UUID;
- lchexbytes(config_file, src, len);
- config_file += len * 2;
+ lchexbytes(p, src, len);
+ p += len * 2;
src += len;
uuid_ptr++;
- *config_file++ = '-';
+ *p++ = '-';
}
/* Remove last dash and zero-terminate */
- *(config_file - 1) = 0;
+ *--p = '\0';
regs->edi.w[0] = OFFS_WRT(ConfigName, 0);
if (try_load(regs))
return;
@@ -675,7 +683,7 @@ void pxe_load_config(com32sys_t *regs)
#endif
/* Nope, try hexadecimal IP prefixes... */
- uchexbytes(config_file, &MyIP, 4); /* Convet to hex string */
+ uchexbytes(config_file, (uint8_t *)&MyIP, 4); /* Convet to hex string */
//
last = &config_file[8];
while (tries) {
@@ -684,7 +692,7 @@ void pxe_load_config(com32sys_t *regs)
if (try_load(regs))
return;
last--; /* Drop one character */
- tries --;
+ tries--;
};
/* Final attempt: "default" string */
@@ -785,11 +793,14 @@ int ip_ok(uint32_t ip)
int pxe_call(int opcode, void *data)
{
- extern void pxenv();
+ extern void pxenv(void);
com32sys_t in_regs, out_regs;
+#if 0
+ printf("pxe_call op %04x data %p\n", opcode, data);
+#endif
+
memset(&in_regs, 0, sizeof in_regs);
- memset(&out_regs, 0, sizeof out_regs);
in_regs.ebx.w[0] = opcode;
in_regs.es = SEG(data);
@@ -813,10 +824,10 @@ int pxe_call(int opcode, void *data)
*/
void ack_packet(com32sys_t *regs)
{
- extern void pxenv();
+ extern void pxenv(void);
int err;
struct pxe_udp_write_pkt *uw_pkt = (struct pxe_udp_write_pkt *)pxe_udp_write_pkt;;
- struct open_file_t *file = (struct open_file_t *)MK_PTR(0, regs->esi.w[0]);
+ struct open_file_t *file = MK_PTR(0, regs->esi.w[0]);
/* Packet number to ack */
ack_packet_buf[1] = regs->eax.w[0];
@@ -824,7 +835,7 @@ void ack_packet(com32sys_t *regs)
uw_pkt->rport = file->tftp_remoteport;
uw_pkt->sip = file->tftp_remoteip;
uw_pkt->gip = ((uw_pkt->sip ^ MyIP) & Netmask) ? Gateway : 0;
- uw_pkt->buffer[0] = (uint16_t)ack_packet_buf;
+ uw_pkt->buffer[0] = OFFS_WRT(ack_packet_buf, 0);
uw_pkt->buffer[1] = 0; /* seems SEG and OFFS stuff doesn't work here */
uw_pkt->buffersize = 4;
@@ -854,7 +865,7 @@ void pxe_get_cached_info(com32sys_t *regs)
bq_pkt->status = 0;
bq_pkt->packettype = type;
bq_pkt->buffersize = 8192;
- bq_pkt->buffer[0] = (uint16_t)trackbuf;
+ bq_pkt->buffer[0] = OFFS_WRT(trackbuf, 0);
bq_pkt->buffer[1] = 0;
err = pxe_call(PXENV_GET_CACHED_INFO, bq_pkt);
@@ -870,7 +881,7 @@ void pxe_get_cached_info(com32sys_t *regs)
* Initialize UDP stack
*
*/
-void udp_init()
+void udp_init(void)
{
int err;
struct pxe_udp_open_pkt *uo_pkt = (struct pxe_udp_open_pkt *)pxe_udp_open_pkt;
@@ -887,7 +898,7 @@ void udp_init()
/*
* Store standard filename prefix
*/
-void get_prefix()
+void get_prefix(void)
{
int len;
char *p;
@@ -925,11 +936,15 @@ void get_prefix()
void subnet_mask(void *data, int opt_len)
{
+ if (opt_len != 4)
+ return;
Netmask = *(uint32_t *)data;
}
void router(void *data, int opt_len)
{
+ if (opt_len != 4)
+ return;
Gateway = *(uint32_t *)data;
}
@@ -947,12 +962,12 @@ void dns_servers(void *data, int opt_len)
}
/* NOT SURE FOR NOW */
- LastDNSServer = (uint16_t)&DNSServers[num - 1];
+ LastDNSServer = OFFS_WRT(&DNSServers[num - 1], 0);
}
void local_domain(void *data, int opt_len)
{
- extern void dns_mangle();
+ extern void dns_mangle(void);
com32sys_t regs;
char *p = (char *)data + opt_len;
char end = *p;
@@ -969,7 +984,7 @@ void vendor_encaps(void *data, int opt_len)
{
extern void parse_dhcp_options(com32sys_t *);
com32sys_t regs;
-
+
memset(&regs, 0 ,sizeof regs);
regs.edx.b[1] = 208; /* Only recongnize PXELINUX options */
regs.ecx.w[0] = opt_len;
@@ -979,6 +994,8 @@ void vendor_encaps(void *data, int opt_len)
void option_overload(void *data, int opt_len)
{
+ if (opt_len != 1)
+ return;
OverLoad = *(uint8_t *)data;
}
@@ -986,6 +1003,9 @@ void option_overload(void *data, int opt_len)
void server(void *data, int opt_len)
{
uint32_t ip;
+
+ if (opt_len != 4)
+ return;
if (ServerIP)
return;
@@ -1188,19 +1208,18 @@ void parse_dhcp(com32sys_t *regs)
}
}
-//#if GPXE
+#if 0 /* GPXE */
/*
* Return CF=0 if and only if the buffer pointed to by DS:SI is a URL
* (contains ://) *and* the gPXE extensions API is available. No
* registers modified.
*/
-/*
void is_gpxe(com32sys_t *regs)
{
struct gpxe_file_api_check *ac = (struct gpxe_file_api_check *)gpxe_file_api_check;
int flag;
- if (!is_url) {
+ if (!is_url(regs)) {
regs->eflags.l |= EFLAGS_CF;
return;
}
@@ -1288,7 +1307,7 @@ void fill_buffer(com32sys_t *regs)
{
int err;
int last_pkt;
- uint8_t *timeout_ptr = TimeoutTable;
+ const uint8_t *timeout_ptr = TimeoutTable;
uint8_t timeout;
uint16_t buffersize;
uint16_t old_time;
@@ -1328,12 +1347,18 @@ void fill_buffer(com32sys_t *regs)
pkt->lport = file->tftp_localport;
err = pxe_call(PXENV_UDP_READ, pkt);
if (err) {
- if (BIOS_timer == old_time)
+ if (BIOS_timer == old_time) {
+ printf(".");
continue;
+ }
+ printf("+");
- timeout --; /* decrease one second */
- if (!timeout)
- timeout = *timeout_ptr++;
+ timeout--; /* decrease one timer tick */
+ if (!timeout) {
+ timeout = *timeout_ptr++;
+ if (!timeout)
+ break;
+ }
continue;
}
@@ -1354,7 +1379,7 @@ void fill_buffer(com32sys_t *regs)
last_pkt = file->tftp_lastpkt;
last_pkt = ntohs(last_pkt); /* Host byte order */
- last_pkt ++;
+ last_pkt++;
last_pkt = htons(last_pkt); /* Network byte order */
if (*(uint16_t *)(data + 2) != last_pkt) {
/*
@@ -1362,6 +1387,7 @@ void fill_buffer(com32sys_t *regs)
* This is presumably because the ACK got lost,
* so the server just resent the previous packet.
*/
+ printf("Wrong packet, wanted %d, got %d\n", last_pkt, *(uint16_t *)(data+2));
regs->eax.w[0] = *(uint16_t *)(data + 2);
ack_packet(regs);
goto again;
@@ -1375,7 +1401,7 @@ void fill_buffer(com32sys_t *regs)
file->tftp_bytesleft = buffersize;
if (buffersize < file->tftp_blksize) {
/* it's the last block, ACK packet immediately */
- regs->eax.w[0] = *(uint16_t *)data;
+ regs->eax.w[0] = *(uint16_t *)(data + 2);
ack_packet(regs);
/* Make sure we know we are at end of file */
@@ -1408,12 +1434,14 @@ void fill_buffer(com32sys_t *regs)
void getfssec_c(com32sys_t *regs)
{
uint16_t pktbuf_seg = 0x4000;
- char *buf = (char *)MK_PTR(regs->es, regs->ebx.w[0]);
+ char *buf = MK_PTR(regs->es, regs->ebx.w[0]);
struct open_file_t *file = (struct open_file_t *)MK_PTR(0, regs->esi.w[0]);
int count = regs->ecx.w[0];
int chunk;
int bytes_read = 0;
-
+
+ sti();
+
regs->fs = pktbuf_seg;
count <<= TFTP_BLOCKSIZE_LG2;
@@ -1426,17 +1454,17 @@ void getfssec_c(com32sys_t *regs)
if (chunk > file->tftp_bytesleft)
chunk = file->tftp_bytesleft;
file->tftp_bytesleft -= chunk;
- memcpy(buf, (void *)MK_PTR(regs->fs, file->tftp_dataptr), chunk);
+ memcpy(buf, MK_PTR(regs->fs, file->tftp_dataptr), chunk);
+ file->tftp_dataptr += chunk;
buf += chunk;
bytes_read += chunk;
count -= chunk;
}
- fill_buffer(regs);
-
regs->ecx.l = bytes_read; /* number of bytes actually read */
if (file->tftp_bytesleft || (file->tftp_filepos < file->tftp_filesize)) {
+ fill_buffer(regs);
regs->eflags.l &= ~EFLAGS_CF;
return;
}
@@ -1459,15 +1487,15 @@ void getfssec_c(com32sys_t *regs)
/*
* Generate the botif string, and the hardware-based config string
*/
-void make_bootif_string()
+void make_bootif_string(void)
{
char *bootif_str = "BOOTIF=";
uint8_t *src = &MACType; /* MACType just followed by MAC */
- uint8_t *dst;
+ char *dst;
int i = MACLen + 1; /* MACType included */
strcpy(BOOTIFStr, bootif_str);
- dst = (uint8_t *)BOOTIFStr + strlen(bootif_str);
+ dst = strchr(BOOTIFStr, '\0');
for (; i > 0; i--) {
lchexbytes(dst, src, 1);
dst += 2;
@@ -1489,7 +1517,7 @@ void make_bootif_string()
; Assumes CS == DS == ES.
;
*/
-void genipopt()
+void genipopt(void)
{
char *p = IPOption;
int ip_len;
@@ -1514,7 +1542,7 @@ void genipopt()
/* Generate ip= option and print the ip adress */
-void ip_init()
+void ip_init(void)
{
int ip = MyIP;
char *myipaddr_msg = "My IP address seems to be ";
@@ -1545,10 +1573,10 @@ void ip_init()
*/
void pxe_init(com32sys_t *regs)
{
- int plan = 'A';
+ char plan = 'A';
uint16_t code_seg, code_len;
uint16_t data_seg, data_len;
- void *base = (void *)((init_stack[1] << 4) + init_stack[0]);
+ char *base = GET_PTR(InitStack);
/* Assume API version 2.1 */
APIVer = 0x201;
@@ -1560,7 +1588,7 @@ void pxe_init(com32sys_t *regs)
goto have_pxe;
/* Plan B: PXENV+ structure at [ES:BX] */
- plan ++;
+ plan++;
regs->ebx.w[0] = *(uint16_t *)(base + 24); /* Original BX */
regs->es = *(uint16_t *)(base + 4); /* Original ES */
if (is_pxenv(regs))
@@ -1572,7 +1600,7 @@ void pxe_init(com32sys_t *regs)
* for now, we just skip it since it must be run in Real mode
*/
extern void plan_c(void);
- plan ++;
+ plan++;
goto plan_D;
call16(plan_c, regs, regs);
if (((regs->eflags.l & EFLAGS_CF) == 0) && (regs->eax.w[0] == 0x564e))
@@ -1581,14 +1609,14 @@ void pxe_init(com32sys_t *regs)
plan_D:
/* Plan D: !PXE memory scan */
- plan ++;
+ plan++;
goto plan_E;
if (memory_scan_for_pxe_struct(regs))
goto have_pxe;
plan_E:
/* Plan E: PXENV+ memory scan */
- plan ++;
+ plan++;
if (memory_scan_for_pxenv_struct(regs))
goto have_pxenv;
@@ -1627,7 +1655,7 @@ void pxe_init(com32sys_t *regs)
data_seg = *(uint16_t *)(base + 0x20); /* UNDI data seg */
code_len = *(uint16_t *)(base + 0x26); /* UNDI code len */
code_seg = *(uint16_t *)(base + 0x24); /* UNDI code seg */
- *(uint32_t *)pxeentry = *(uint32_t *)(base + 0x0a); /* PXENV+ entry point */
+ PXEEntry = *(far_ptr_t *)(base + 0x0a); /* PXENV+ entry point */
printf("PXENV+ entry point found (we hope) at ");
goto have_entrypoint;
@@ -1640,11 +1668,11 @@ void pxe_init(com32sys_t *regs)
data_seg = *(uint16_t *)(base + 0x28); /* UNDI data seg */
code_len = *(uint16_t *)(base + 0x36); /* UNDI code len */
code_seg = *(uint16_t *)(base + 0x30); /* UNDI code seg */
- *(uint32_t *)pxeentry = *(uint32_t *)(base + 0x10); /* PXENV+ entry point */
+ PXEEntry = *(far_ptr_t *)(base + 0x10); /* !PXE entry point */
printf("!PXE entry point found (we hope) at ");
have_entrypoint:
- printf("%04X:%04X via plan %c\n", pxeentry[1], pxeentry[0], plan);
+ printf("%04X:%04X via plan %c\n", PXEEntry.seg, PXEEntry.offs, plan);
printf("UNDI code segment at %04X len %04X\n", code_seg, code_len);
code_seg = code_seg + ((code_len + 15) >> 4);
@@ -1727,5 +1755,5 @@ void network_init(com32sys_t *regs)
if ((DHCPMagic & 1) == 0)
DHCPMagic = 0;
- //udp_init();
+ udp_init();
}