diff --git a/src/core/main.c b/src/core/main.c index e0cac222..35c7bb2c 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -39,11 +39,6 @@ int url_port; char as_main_program = 1; -#ifdef IMAGE_FREEBSD -int freebsd_howto = 0; -char freebsd_kernel_env[FREEBSD_KERNEL_ENV_SIZE]; -#endif - #if 0 static inline unsigned long ask_boot(unsigned *index) @@ -282,6 +277,16 @@ static int main_loop(int state) if (dev->how_probe == PROBE_FAILED) { state = -1; } + if (state == 1) { + /* The bootp reply might have been changed, re-parse. */ + decode_rfc1533(bootp_data.bootp_reply.bp_vend, 0, +#ifdef NO_DHCP_SUPPORT + BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, +#else + DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, +#endif /* NO_DHCP_SUPPORT */ + 1); + } } } switch(state) { diff --git a/src/core/nic.c b/src/core/nic.c index f80caabb..be6eb7bc 100644 --- a/src/core/nic.c +++ b/src/core/nic.c @@ -33,6 +33,14 @@ char *hostname = ""; int hostnamelen = 0; static uint32_t xid; unsigned char *end_of_rfc1533 = NULL; +unsigned char *addparam; +int addparamlen; + +#ifdef IMAGE_FREEBSD +int freebsd_howto = 0; +char freebsd_kernel_env[FREEBSD_KERNEL_ENV_SIZE]; +#endif /* IMAGE_FREEBSD */ + static int vendorext_isvalid; static const unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* äEth */ static const unsigned char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; @@ -261,9 +269,8 @@ static int nic_configure ( struct type_dev *type_dev ) { #endif /* PXE_EXPORT */ #endif /* ! NO_DHCP_SUPPORT */ printf(", TFTP: %@", arptable[ARP_SERVER].ipaddr.s_addr); - if (BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr) - printf(", Relay: %@", - BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr); + if (bootp_data.bootp_reply.bp_giaddr.s_addr) + printf(", Relay: %@", bootp_data.bootp_reply.bp_giaddr.s_addr); if (arptable[ARP_GATEWAY].ipaddr.s_addr) printf(", Gateway %@", arptable[ARP_GATEWAY].ipaddr.s_addr); if (arptable[ARP_NAMESERVER].ipaddr.s_addr) @@ -316,6 +323,22 @@ static int nic_load ( struct type_dev *type_dev, struct buffer *buffer ) { NULL #endif : KERNEL_BUF; +#ifdef ZPXE_SUFFIX_STRIP + { + int i = 0; + while (kernel[i++]); + if(i > 5) { + if(kernel[i - 6] == '.' && + kernel[i - 5] == 'z' && + kernel[i - 4] == 'p' && + kernel[i - 3] == 'x' && + kernel[i - 2] == 'e') { + printf("Trimming .zpxe extension\n"); + kernel[i - 6] = 0; + } + } + } +#endif if ( kernel ) { return download_url ( kernel, buffer ); } else { @@ -659,8 +682,8 @@ static int await_bootp(int ival __unused, void *ptr __unused, #endif /* NO_DHCP_SUPPORT */ netmask = default_netmask(); /* bootpreply->bp_file will be copied to KERNEL_BUF in the memcpy */ - memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t)); - decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend, 0, + memcpy((char *)&bootp_data, (char *)bootpreply, sizeof(struct bootpd_t)); + decode_rfc1533(bootp_data.bootp_reply.bp_vend, 0, #ifdef NO_DHCP_SUPPORT BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, #else @@ -740,6 +763,8 @@ static int bootp(void) #else while ( remaining_time > 0 ) { if (await_reply(await_bootp, 0, NULL, remaining_time)){ + if (arptable[ARP_CLIENT].ipaddr.s_addr) + break; } remaining_time = stop_time - currticks(); } @@ -1029,6 +1054,8 @@ int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int e #else vendorext_isvalid = 0; #endif + addparam = NULL; + addparamlen = 0; if (memcmp(p, rfc1533_cookie, 4)) return(0); /* no RFC 1533 header found */ p += 4; @@ -1039,7 +1066,7 @@ int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int e return(0); /* no RFC 1533 header found */ p += 4; len -= 4; } - if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) { + if (extend + len <= (unsigned char *)&(bootp_data.bootp_extension[MAX_BOOTP_EXTLEN])) { memcpy(extend, p, len); extend += len; } else { @@ -1096,6 +1123,17 @@ int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int e p[6] == RFC1533_VENDOR_MAJOR ) vendorext_isvalid++; + else if (c == RFC1533_VENDOR_ADDPARM) { + /* This tag intentionally works for BOTH the encapsulated and + * non-encapsulated case, since the current menu code (in mknbi) + * creates this tag without encapsulation. In the future both the + * menu from mknbi and this code should learn about the proper + * encapsulation (which will require substantial changes to various + * stuff from mknbi, which will break compatibility with older + * versions of Etherboot). */ + addparam = p + 2; + addparamlen = *(p + 1); + } else if (NON_ENCAP_OPT c == RFC1533_VENDOR_ETHERBOOT_ENCAP) { in_encapsulated_options = 1; decode_rfc1533(p+2, 0, TAG_LEN(p), -1); diff --git a/src/core/vsprintf.c b/src/core/vsprintf.c index fda0e96c..83a494a6 100644 --- a/src/core/vsprintf.c +++ b/src/core/vsprintf.c @@ -45,7 +45,7 @@ static int vsprintf(char *buf, const char *fmt, va_list args) while (*fmt >= '0' && *fmt <= '9') fmt++; if (*fmt == 's') { - for(p = va_arg(args, char *); *p != '\0'; p++) + for(p = va_arg(args, char *); *p != '\0'; p++) buf ? *s++ = *p : putchar(*p); } else if (*fmt == 'm') { for(p = strerror(errno); *p != '\0'; p++) @@ -70,7 +70,7 @@ static int vsprintf(char *buf, const char *fmt, va_list args) fmt++; } } - + /* * Before each format q points to tmp buffer * After each format q points past end of item @@ -182,11 +182,12 @@ int sprintf(char *buf, const char *fmt, ...) * @err None - * */ -void printf(const char *fmt, ...) +int printf(const char *fmt, ...) { va_list args; int i; va_start(args, fmt); i=vsprintf(0, fmt, args); va_end(args); + return i; } diff --git a/src/include/vsprintf.h b/src/include/vsprintf.h index 553ebeb5..122fcc66 100644 --- a/src/include/vsprintf.h +++ b/src/include/vsprintf.h @@ -45,6 +45,6 @@ */ extern int sprintf ( char *buf, const char *fmt, ... ); -extern void printf ( const char *fmt, ... ); +extern int printf ( const char *fmt, ... ); #endif /* VSPRINTF_H */ diff --git a/src/interface/pxe/pxe_preboot.c b/src/interface/pxe/pxe_preboot.c index bed32042..f0e12bbb 100644 --- a/src/interface/pxe/pxe_preboot.c +++ b/src/interface/pxe/pxe_preboot.c @@ -99,7 +99,7 @@ PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO memcpy ( cached_info->bootfile, KERNEL_BUF, sizeof(cached_info->bootfile) ); /* Copy DHCP vendor options */ - memcpy ( &cached_info->vendor.d, BOOTP_DATA_ADDR->bootp_reply.bp_vend, + memcpy ( &cached_info->vendor.d, bootp_data.bootp_reply.bp_vend, sizeof(cached_info->vendor.d) ); /* Copy to user-specified buffer, or set pointer to our buffer */