pxe: make gPXE work
authorH. Peter Anvin <hpa@zytor.com>
Sat, 6 Feb 2010 00:17:06 +0000 (16:17 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Sat, 6 Feb 2010 00:17:06 +0000 (16:17 -0800)
Make the gPXE interface code work.  gpxelinux.0 now appears
functional.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
core/fs/pxe/pxe.c

index 4d82d80..d48473f 100644 (file)
@@ -36,7 +36,7 @@ const uint8_t TimeoutTable[] = {
 
 /* PXE unload sequences */
 const uint8_t new_api_unload[] = {
-    PXENV_UDP_CLOSE, PXENV_UNDI_SHUTDOWN, 
+    PXENV_UDP_CLOSE, PXENV_UNDI_SHUTDOWN,
     PXENV_UNLOAD_STACK, PXENV_STOP_UNDI, 0
 };
 const uint8_t old_api_unload[] = {
@@ -80,20 +80,20 @@ static void files_init(void)
 /*
  * Allocate a local UDP port structure.
  * return the socket pointer if success, or null if failure
- *    
+ *
  */
 static struct open_file_t *allocate_socket(void)
 {
     int i;
     struct open_file_t *socket = Files;
     uint16_t nextport;
-    
+
     for (i = 0; i < MAX_OPEN; i++) {
         if (!socket->tftp_localport)
            break;
         socket++;
     }
-    
+
     if (i == MAX_OPEN)
        return NULL;
 
@@ -129,7 +129,7 @@ static void pxe_close_file(struct file *file)
 }
 
 /**
- * Take a nubmer of bytes in memory and convert to lower-case hxeadecimal 
+ * Take a nubmer of bytes in memory and convert to lower-case hxeadecimal
  *
  * @param: dst, output buffer
  * @param: src, input buffer
@@ -141,12 +141,12 @@ static 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 = *s++;
         half   = ((c >> 4) & 0x0f) + '0';
         *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half;
-        
+
         half   = (c & 0x0f) + '0';
         *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half;
     }
@@ -161,12 +161,12 @@ static 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 = *s++;
         half   = ((c >> 4) & 0x0f) + '0';
         *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half;
-        
+
         half   = (c & 0x0f) + '0';
         *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half;
     }
@@ -202,7 +202,7 @@ static int gendotquad(char *dst, uint32_t ip)
     int i = 0, j;
     char temp[4];
     char *p = dst;
-    
+
     for (; i < 4; i++) {
         j = 0;
         part = ip & 0xff;
@@ -212,12 +212,12 @@ static int gendotquad(char *dst, uint32_t ip)
         for (; j > 0; j--)
             *p++ = temp[j-1];
         *p++ = '.';
-        
+
         ip >>= 8;
     }
     /* drop the last dot '.' and zero-terminate string*/
     *(--p) = 0;
-    
+
     return p - dst;
 }
 
@@ -232,44 +232,44 @@ static const char *parse_dotquad(const char *ip_str, uint32_t *res)
     int  i  = 0;
     uint8_t part = 0;
     uint32_t ip  = 0;
-    
+
     for (; i < 4; i++) {
         while (is_digit(*p)) {
             part = part * 10 + *p - '0';
             p++;
         }
-        if (i != 3 && *p != '.') 
+        if (i != 3 && *p != '.')
             return NULL;
-        
+
         ip = (ip << 8) | part;
         part = 0;
         p++;
     }
     p --;
-    
+
     *res = ip;
-    return p;    
+    return p;
 }
+
 /*
  * the ASM pxenv function wrapper, return 1 if error, or 0
  *
- */    
+ */
 int pxe_call(int opcode, void *data)
 {
     extern void pxenv(void);
     com32sys_t regs;
-    
+
 #if 0
     printf("pxe_call op %04x data %p\n", opcode, data);
 #endif
 
-    memset(&regs, 0, sizeof regs);    
+    memset(&regs, 0, sizeof regs);
     regs.ebx.w[0] = opcode;
     regs.es       = SEG(data);
     regs.edi.w[0] = OFFS(data);
     call16(pxenv, &regs, &regs);
-    
+
     return regs.eflags.l & EFLAGS_CF;  /* CF SET if fail */
 }
 
@@ -295,7 +295,7 @@ static void tftp_error(struct open_file_t *file, uint16_t errnum,
     err_buf.err_num = errnum;
     memcpy(err_buf.err_msg, errstr, len);
     err_buf.err_msg[len] = '\0';
-    
+
     udp_write.src_port    = file->tftp_localport;
     udp_write.dst_port    = file->tftp_remoteport;
     udp_write.ip          = file->tftp_remoteip;
@@ -305,7 +305,7 @@ static void tftp_error(struct open_file_t *file, uint16_t errnum,
 
     /* If something goes wrong, there is nothing we can do, anyway... */
     pxe_call(PXENV_UDP_WRITE, &udp_write);
-}    
+}
 
 
 /**
@@ -313,14 +313,14 @@ static void tftp_error(struct open_file_t *file, uint16_t errnum,
  *
  * @param: file,    TFTP block pointer
  * @param: ack_num, Packet # to ack (network byte order)
- * 
+ *
  */
 static void ack_packet(struct open_file_t *file, uint16_t ack_num)
 {
     int err;
     static __lowmem uint16_t ack_packet_buf[2];
-    static __lowmem struct s_PXENV_UDP_WRITE udp_write;    
+    static __lowmem struct s_PXENV_UDP_WRITE udp_write;
+
     /* Packet number to ack */
     ack_packet_buf[0]     = TFTP_ACK;
     ack_packet_buf[1]     = ack_num;
@@ -343,14 +343,14 @@ static void ack_packet(struct open_file_t *file, uint16_t ack_num)
  *
  * @param:  type,  packet type
  * @return: buffer size
- * 
+ *
  */
 static int pxe_get_cached_info(int type)
 {
     int err;
     static __lowmem struct s_PXENV_GET_CACHED_INFO get_cached_info;
     printf(" %02x", type);
-    
+
     get_cached_info.Status      = 0;
     get_cached_info.PacketType  = type;
     get_cached_info.BufferSize  = 8192;
@@ -360,50 +360,44 @@ static int pxe_get_cached_info(int type)
         printf("PXE API call failed, error  %04x\n", err);
        kaboom();
     }
-    
+
     return get_cached_info.BufferSize;
 }
 
-  
+
 
 #if GPXE
 
 /*
- * Return 1 if and only if the buffer pointed to by
- * url is a URL (contains ://)
- *
+ * Return true if and only if the buffer pointed to by
+ * url is a URL -- it must contain :// and it must be the
+ * first colon.
  */
-static int is_url(const char *url)
+static inline bool is_url(const char *url)
 {
-    while (*url) {
-        if (!strncmp(url, "://", 3))
-            return 1;
-          
-        url++;
-    }    
-    return 0;
+    const char *p = strchr(url, ':');
+
+    return p && p[1] == '/' && p[2] == '/';
 }
 
 
 /*
- * 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 
+ * 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.
  */
-static bool is_gpxe(char *url)
+static bool is_gpxe(const char *url)
 {
     static bool already;
-    const char gpxe_warning_msg[] = 
-        "URL syntax, but gPXE extensions not detected, tring plain TFTP...\n";
-    
+
     if (!is_url(url))
         return false;
-    
+
     if (!has_gpxe && !already) {
-       printf("%s\n", gpxe_warning_msg);
+       fputs("URL syntax, but gPXE extensions not detected, tring plain TFTP...\n", stdout);
        already = true;
     }
-    
+
     return has_gpxe;
 }
 
@@ -416,7 +410,7 @@ static void get_packet_gpxe(struct open_file_t *file)
 {
     static __lowmem struct s_PXENV_FILE_READ file_read;
     int err;
+
     while (1) {
         file_read.FileHandle  = file->tftp_remoteport;
         file_read.Buffer.offs = file->tftp_pktbuf;
@@ -430,14 +424,15 @@ static void get_packet_gpxe(struct open_file_t *file)
            kaboom();
     }
 
+    file->tftp_dataptr   = file->tftp_pktbuf;
     file->tftp_bytesleft = file_read.BufferSize;
     file->tftp_filepos  += file_read.BufferSize;
-    
+
     if (file->tftp_bytesleft == 0)
         file->tftp_filesize = file->tftp_filepos;
-    
+
     /* if we're done here, close the file */
-    if (file->tftp_filesize > file->tftp_filepos) 
+    if (file->tftp_filesize > file->tftp_filepos)
         return;
 
     /* Got EOF, close it */
@@ -460,7 +455,7 @@ static void pxe_mangle_name(char *dst, const char *src)
     const char *p = src;
     uint32_t ip = server_ip;
     int i = 0;
-   
+
 #if GPXE
     if (is_url(src)) {
         ip = -1;
@@ -494,9 +489,9 @@ static void pxe_mangle_name(char *dst, const char *src)
             }
         }
     }
-  
+
  store:
-    *(uint32_t *)dst = ip;  
+    *(uint32_t *)dst = ip;
     dst += 4;
     i = FILENAME_MAX - 5;
 
@@ -516,14 +511,14 @@ static void pxe_mangle_name(char *dst, const char *src)
 
 /*
  * Does the opposite of mangle_name; converts a DOS-mangled
- * filename to the conventional representation.  This is 
+ * filename to the conventional representation.  This is
  * needed for the BOOT_IMAGE= parameter for the kernel.
  */
 static char *pxe_unmangle_name(char *dst, const char *src)
 {
     uint32_t ip = *(uint32_t *)src;
     int ip_len = 0;
-   
+
     if (ip != 0 && ip != -1) {
         ip_len = gendotquad(dst, *(uint32_t *)src);
         dst += ip_len;
@@ -531,7 +526,7 @@ static char *pxe_unmangle_name(char *dst, const char *src)
     src += 4;
     return stpcpy(dst, src);
 }
-       
+
 /*
  * Get a fresh packet if the buffer is drained, and we haven't hit
  * EOF yet.  The buffer should be filled immediately after draining!
@@ -546,7 +541,7 @@ static void fill_buffer(struct open_file_t *file)
     uint32_t oldtime;
     void *data = NULL;
     static __lowmem struct s_PXENV_UDP_READ udp_read;
-        
+
     if (file->tftp_bytesleft || file->tftp_goteof)
         return;
 
@@ -562,10 +557,10 @@ static void fill_buffer(struct open_file_t *file)
      * Start by ACKing the previous packet; this should cause
      * the next packet to be sent.
      */
- ack_again:   
+ ack_again:
     ack_packet(file, file->tftp_lastpkt);
-    
-    timeout_ptr = TimeoutTable;    
+
+    timeout_ptr = TimeoutTable;
     timeout = *timeout_ptr++;
     oldtime = jiffies();
     while (timeout) {
@@ -588,14 +583,14 @@ static void fill_buffer(struct open_file_t *file)
            }
             continue;
         }
-    
+
         if (udp_read.buffer_size < 4)  /* Bad size for a DATA packet */
-            continue;    
+            continue;
 
         data = MK_PTR(PKTBUF_SEG, file->tftp_pktbuf);
         if (*(uint16_t *)data != TFTP_DATA)    /* Not a data packet */
             continue;
-                
+
         /* If goes here, recevie OK, break */
         break;
     }
@@ -603,7 +598,7 @@ static void fill_buffer(struct open_file_t *file)
     /* time runs out */
     if (timeout == 0)
        kaboom();
-    
+
     last_pkt = file->tftp_lastpkt;
     last_pkt = ntohs(last_pkt);       /* Host byte order */
     last_pkt++;
@@ -620,7 +615,7 @@ static void fill_buffer(struct open_file_t *file)
 #endif
         goto ack_again;
     }
-    
+
     /* It's the packet we want.  We're also EOF if the size < blocksize */
     file->tftp_lastpkt = last_pkt;    /* Update last packet number */
     buffersize = udp_read.buffer_size - 4;  /* Skip TFTP header */
@@ -646,11 +641,11 @@ static void fill_buffer(struct open_file_t *file)
  * @param: buf, buffer to store the read data
  * @param: openfile, TFTP socket pointer
  * @param: blocks, 512-byte block count; 0FFFFh = until end of file
- * 
+ *
  * @return: the bytes read
  *
  */
-static uint32_t pxe_getfssec(struct file *gfile, char *buf, 
+static uint32_t pxe_getfssec(struct file *gfile, char *buf,
                             int blocks, bool *have_more)
 {
     struct open_file_t *file = gfile->open_file;
@@ -663,7 +658,7 @@ static uint32_t pxe_getfssec(struct file *gfile, char *buf,
         fill_buffer(file);         /* If we have no 'fresh' buffer, get it */
         if (!file->tftp_bytesleft)
             break;
-        
+
         chunk = count;
         if (chunk > file->tftp_bytesleft)
             chunk = file->tftp_bytesleft;
@@ -675,22 +670,22 @@ static uint32_t pxe_getfssec(struct file *gfile, char *buf,
         count -= chunk;
     }
 
-    
+
     if (file->tftp_bytesleft || (file->tftp_filepos < file->tftp_filesize)) {
        fill_buffer(file);
         *have_more = 1;
     } else if (file->tftp_goteof) {
-        /* 
+        /*
          * The socket is closed and the buffer drained; the caller will
         * call close_file and therefore free the socket.
          */
         *have_more = 0;
     }
-    
+
     return bytes_read;
  }
 
+
 
 /*
  * Fill the packet tail with the tftp informations then retures the lenght
@@ -698,7 +693,7 @@ static uint32_t pxe_getfssec(struct file *gfile, char *buf,
 static int fill_tail(char *dst)
 {
     static const char tail[] = "octet\0""tsize\0""0\0""blksize\0""1408";
-    
+
     memcpy(dst, tail, sizeof tail);
     return sizeof tail;
 }
@@ -723,7 +718,6 @@ static void pxe_searchdir(char *filename, struct file *file)
     static __lowmem struct s_PXENV_UDP_WRITE udp_write;
     static __lowmem struct s_PXENV_UDP_READ  udp_read;
     static __lowmem struct s_PXENV_FILE_OPEN file_open;
-    static __lowmem struct s_PXENV_GET_FILE_SIZE get_file_size;
     const struct tftp_options *tftp_opt;
     int i = 0;
     int err;
@@ -736,14 +730,14 @@ static void pxe_searchdir(char *filename, struct file *file)
     uint16_t blk_num;
     uint32_t ip;
     uint32_t opdata, *opdata_ptr;
-    
+
     open_file = allocate_socket();
     if (!open_file) {
        file->file_len = 0;
        file->open_file = NULL;
        return;
     }
-    
+
     timeout_ptr = TimeoutTable;   /* Reset timeout */
 
  sendreq:
@@ -751,7 +745,7 @@ static void pxe_searchdir(char *filename, struct file *file)
     udp_write.buffer.seg  = 0;
     *(uint16_t *)buf = TFTP_RRQ;  /* TFTP opcode */
     buf += 2;
-    
+
     ip = *(uint32_t *)p;      /* ip <- server override (if any) */
     p += 4;
     if (ip == 0) {
@@ -763,31 +757,23 @@ static void pxe_searchdir(char *filename, struct file *file)
 
     strcpy(buf, p);                /* Copy the filename */
     buf += strlen(p) + 1;          /* advance the pointer, null char included */
-    
+
 #if GPXE
     if (is_gpxe(packet_buf + 2)) {
         file_open.Status        = PXENV_STATUS_BAD_FUNC;
-        file_open.FileName.offs = OFFS_WRT(packet_buf + 2, 0);
-        file_open.FileName.seg  = 0;
+        file_open.FileName.offs = OFFS(packet_buf + 2);
+        file_open.FileName.seg  = SEG(packet_buf + 2);
         err = pxe_call(PXENV_FILE_OPEN, &file_open);
-        if (err) 
+        if (err)
             goto done;
-        
+
         open_file->tftp_localport = -1;
         open_file->tftp_remoteport = file_open.FileHandle;
-        get_file_size.FileHandle = file_open.FileHandle;
-        
-#if 0
-        err = pxe_call(PXENV_GET_FILE_SIZE, &get_file_size);
-        if (!err)
-            open_file->tftp_filesize = get_file_size.FileSize;
-        else
-#endif
-           open_file->tftp_filesize = -1;
+       open_file->tftp_filesize = -1;
         goto done;
     }
 #endif /* GPXE */
-    
+
     open_file->tftp_remoteip = ip;
     tid = open_file->tftp_localport;   /* TID(local port No) */
     udp_write.ip        = ip;
@@ -798,7 +784,7 @@ static void pxe_searchdir(char *filename, struct file *file)
     udp_write.buffer_size = buf - packet_buf;
     err = pxe_call(PXENV_UDP_WRITE, &udp_write);
     if (err || udp_write.status != 0)
-        goto failure;            /* 
+        goto failure;            /*
                                  * In fact, the 'failure' target will not do
                                  * a failure thing; it will move on to the
                                  * next timeout, then tries again until
@@ -809,7 +795,7 @@ static void pxe_searchdir(char *filename, struct file *file)
      * Danger, Will Robinson! We need to support tiemout
      * and retry lest we just lost a packet ...
      */
-    
+
     /* Packet transmitted OK, now we need to receive */
     timeout = *timeout_ptr++;
     oldtime = jiffies();
@@ -832,11 +818,11 @@ static void pxe_searchdir(char *filename, struct file *file)
         if (udp_read.src_ip == open_file->tftp_remoteip)
             break;
     }
-          
+
     /* Got packet; reset timeout */
     timeout_ptr = TimeoutTable;
     open_file->tftp_remoteport = udp_read.s_port;
-    
+
     /* filesize <- -1 == unknown */
     open_file->tftp_filesize = -1;
     /* Default blksize unless blksize option negotiated */
@@ -844,9 +830,9 @@ static void pxe_searchdir(char *filename, struct file *file)
     buffersize = udp_read.buffer_size - 2;  /* bytes after opcode */
     if (buffersize < 0)
         goto failure;                     /* Garbled reply */
-    
+
     /*
-     * Get the opcode type, and parse it 
+     * Get the opcode type, and parse it
      */
     opcode = *(uint16_t *)packet_buf;
     switch (opcode) {
@@ -861,9 +847,9 @@ static void pxe_searchdir(char *filename, struct file *file)
          * buffer and go with the default value for all options...
          *
          * We got a DATA packet, meaning no options are
-         * suported. Save the data away and consider the 
-         * length undefined, *unless* this is the only 
-         * data packet... 
+         * suported. Save the data away and consider the
+         * length undefined, *unless* this is the only
+         * data packet...
          */
         buffersize -= 2;
         if (buffersize < 0)
@@ -877,9 +863,9 @@ static void pxe_searchdir(char *filename, struct file *file)
         if (buffersize > TFTP_BLOCKSIZE)
             goto err_reply;  /* Corrupt */
         else if (buffersize < TFTP_BLOCKSIZE) {
-            /* 
+            /*
              * This is the final EOF packet, already...
-             * We know the filesize, but we also want to 
+             * We know the filesize, but we also want to
              * ack the packet and set the EOF flag.
              */
             open_file->tftp_filesize = buffersize;
@@ -893,14 +879,14 @@ static void pxe_searchdir(char *filename, struct file *file)
        break;
 
     case TFTP_OACK:
-        /* 
+        /*
          * Now we need to parse the OACK packet to get the transfer
          * and packet sizes.
          */
 
         options = packet_buf + 2;
        p = options;
-        
+
        while (buffersize) {
            char *opt = p;
 
@@ -931,7 +917,7 @@ static void pxe_searchdir(char *filename, struct file *file)
            if (!buffersize)
                break;          /* No option data */
 
-            /* 
+            /*
              * Parse option pointed to by options; guaranteed to be
             * null-terminated
              */
@@ -944,11 +930,11 @@ static void pxe_searchdir(char *filename, struct file *file)
             if (i == tftp_nopts)
                 goto err_reply; /* Non-negotitated option returned,
                                   no idea what it means ...*/
-            
+
             /* get the address of the filed that we want to write on */
             opdata_ptr = (uint32_t *)((char *)open_file + tftp_opt->offset);
            opdata = 0;
-            
+
             /* do convert a number-string to decimal number, just like atoi */
             while (buffersize--) {
                uint8_t d = *p++;
@@ -962,12 +948,12 @@ static void pxe_searchdir(char *filename, struct file *file)
            *opdata_ptr = opdata;
        }
        break;
-       
+
     default:
        printf("TFTP unknown opcode %d\n", ntohs(opcode));
        goto err_reply;
     }
-    
+
 done:
     if (!open_file->tftp_filesize) {
         free_socket(open_file);
@@ -984,13 +970,13 @@ err_reply:
     tftp_error(open_file, TFTP_EOPTNEG, "TFTP protocol error");
     printf("TFTP server sent an incomprehesible reply\n");
     kaboom();
-        
+
 failure:
     timeout_ptr++;
     if (*timeout_ptr)
         goto sendreq;  /* Try again */
 }
+
 
 /*
  * Store standard filename prefix
@@ -1000,30 +986,30 @@ static void get_prefix(void)
     int len;
     char *p;
     char c;
-    
+
     if (DHCPMagic & 0x04)         /* Did we get a path prefix option */
         goto got_prefix;
-    
+
     strcpy(path_prefix, boot_file);
     len = strlen(path_prefix);
-    p = &path_prefix[len - 1]; 
+    p = &path_prefix[len - 1];
 
     while (len--) {
         c = *p--;
         c |= 0x20;
-        
-        c = (c >= '0' && c <= '9') || 
-            (c >= 'a' && c <= 'z') || 
+
+        c = (c >= '0' && c <= '9') ||
+            (c >= 'a' && c <= 'z') ||
             (c == '.' || c == '-');
         if (!c)
             break;
     };
-    
+
     if (len < 0)
         p --;
 
     *(p + 2) = 0;                /* Zero-terminate after delimiter */
-    
+
  got_prefix:
     printf("TFTP prefix: %s\n", path_prefix);
     strcpy(CurrentDirName, path_prefix);
@@ -1032,14 +1018,14 @@ static void get_prefix(void)
  /*
   * try to load a config file, if found, return 1, or return 0
   *
-  */   
+  */
 static int try_load(char *config_name)
 {
     com32sys_t regs;
-    
+
     printf("Trying to load: %-50s ", config_name);
     pxe_mangle_name(KernelName, config_name);
-    
+
     memset(&regs, 0, sizeof regs);
     regs.edi.w[0] = OFFS_WRT(KernelName, 0);
     call16(core_open, &regs, &regs);
@@ -1060,23 +1046,23 @@ static int pxe_load_config(void)
     const char *default_str = "default";
     char *config_file;
     char *last;
-    char *p;   
+    char *p;
     uint8_t *uuid_ptr;
     int tries = 8;
-    
+
     get_prefix();
     if (DHCPMagic & 0x02) {
         /* We got a DHCP option, try it first */
        if (try_load(boot_file))
            return 0;
     }
-    
+
     /*
      * Have to guess config file name ...
-     */  
+     */
     memcpy(ConfigName, cfgprefix, strlen(cfgprefix));
     config_file = ConfigName + strlen(cfgprefix);
-      
+
     /* Try loading by UUID */
     if (have_uuid) {
         uuid_ptr  = uuid_dashes;
@@ -1084,7 +1070,7 @@ static int pxe_load_config(void)
         while (*uuid_ptr) {
             int len = *uuid_ptr;
             char *src = uuid;
-            
+
             lchexbytes(p, src, len);
             p += len * 2;
             src += len;
@@ -1101,7 +1087,7 @@ static int pxe_load_config(void)
     strcpy(config_file, MAC_str);
     if (try_load(ConfigName))
         return 0;
-    
+
     /* Nope, try hexadecimal IP prefixes... */
     uchexbytes(config_file, (uint8_t *)&MyIP, 4);     /* Convet to hex string */
     last = &config_file[8];
@@ -1112,7 +1098,7 @@ static int pxe_load_config(void)
         last--;           /* Drop one character */
         tries--;
     };
-    
+
     /* Final attempt: "default" string */
     strcpy(config_file, default_str);
     if (try_load(ConfigName))
@@ -1123,7 +1109,7 @@ static int pxe_load_config(void)
 }
 
 /*
- * Generate the botif string, and the hardware-based config string 
+ * Generate the botif string, and the hardware-based config string
  */
 static void make_bootif_string(void)
 {
@@ -1131,7 +1117,7 @@ static void make_bootif_string(void)
     char *src = mac;
     char *dst = MAC_str;
     int i = MAC_len + 1;
-    
+
     *(uint8_t *)src++ = MAC_type;
     memcpy(src, MAC, MAC_len);
     src = mac;
@@ -1158,10 +1144,10 @@ static void genipopt(void)
 {
     char *p = IPOption;
     int ip_len;
-    
+
     strcpy(p, "ip=");
     p += 3;
-    
+
     ip_len = gendotquad(p, MyIP);
     p += ip_len;
     *p++ = ':';
@@ -1173,19 +1159,19 @@ static void genipopt(void)
     ip_len = gendotquad(p, gate_way);
     p += ip_len;
     *p++ = ':';
-    
+
     ip_len = gendotquad(p, net_mask);
 }
-    
+
 
 /* Generate ip= option and print the ip adress */
 static void ip_init(void)
 {
     uint32_t ip = MyIP;
-       
+
     genipopt();
     gendotquad(dot_quad_buf, ip);
-    
+
     ip = ntohl(ip);
     printf("My IP address seems to be %08X %s\n", ip, dot_quad_buf);
     printf("%s\n", IPOption);
@@ -1223,7 +1209,7 @@ static int is_pxenv(const void *buf)
     const uint8_t *p = buf;
     int i = pxenv->length;
     uint8_t sum = 0;
-    
+
     /* The pxeptr field isn't present in old versions */
     if (i < offsetof(struct pxenv_t, pxeptr) ||
        memcmp(pxenv->signature, "PXENV+", 6))
@@ -1234,7 +1220,7 @@ static int is_pxenv(const void *buf)
 
     return sum == 0;
 }
-        
+
 
 
 /*
@@ -1258,14 +1244,14 @@ static const void *memory_scan(uintptr_t start, int (*func)(const void *))
     }
     return NULL;
 }
-    
+
 static const struct pxe_t *memory_scan_for_pxe_struct(void)
 {
     extern uint16_t BIOS_fbm;  /* Starting segment */
 
     return memory_scan(BIOS_fbm << 10, is_pxe);
 }
-    
+
 static const struct pxenv_t *memory_scan_for_pxenv_struct(void)
 {
     return memory_scan(0x10000, is_pxenv);
@@ -1280,8 +1266,8 @@ static const struct pxenv_t *memory_scan_for_pxenv_struct(void)
  * d. Search memory for !PXE
  * e. Search memory for PXENV+
  *
- * If we find a PXENV+ structure, we try to find a !PXE structure from 
- * if if the API version is 2.1 or later 
+ * If we find a PXENV+ structure, we try to find a !PXE structure from
+ * if if the API version is 2.1 or later
  *
  */
 static int pxe_init(void)
@@ -1299,12 +1285,12 @@ static int pxe_init(void)
 
     /* Assume API version 2.1 */
     APIVer = 0x201;
-    
+
     /* Plan A: !PXE structure as SS:[SP + 4] */
     off = *(uint16_t *)(base + 48);
     seg = *(uint16_t *)(base + 50);
     pxe = MK_PTR(seg, off);
-    if (is_pxe(pxe)) 
+    if (is_pxe(pxe))
         goto have_pxe;
 
     /* Plan B: PXENV+ structure at [ES:BX] */
@@ -1330,7 +1316,7 @@ static int pxe_init(void)
     plan++;
     if ((pxe = memory_scan_for_pxe_struct()))
         goto have_pxe;
-    
+
     /* Plan E: PXENV+ memory scan */
     plan++;
     if ((pxenv = memory_scan_for_pxenv_struct()))
@@ -1339,7 +1325,7 @@ static int pxe_init(void)
     /* Found nothing at all !! */
     printf("No !PXE or PXENV+ API found; we're dead...\n");
     kaboom();
-    
+
  have_pxenv:
     APIVer = pxenv->version;
     printf("Found PXENV+ structure\nPXE API version is %04x\n", APIVer);
@@ -1349,7 +1335,7 @@ static int pxe_init(void)
        if (pxenv->length >= sizeof(struct pxenv_t)) {
            pxe = GET_PTR(pxenv->pxeptr);
            if (is_pxe(pxe))
-               goto have_pxe;  
+               goto have_pxe;
            /*
             * Nope, !PXE structure missing despite API 2.1+, or at least
             * the pointer is missing. Do a last-ditch attempt to find it
@@ -1359,7 +1345,7 @@ static int pxe_init(void)
        }
        APIVer = 0x200;         /* PXENV+ only, assume version 2.00 */
     }
-    
+
     /* Otherwise, no dice, use PXENV+ structure */
     data_len = pxenv->undidatasize;
     data_seg = pxenv->undidataseg;
@@ -1389,7 +1375,7 @@ static int pxe_init(void)
     real_base_mem = max(code_seg, data_seg) >> 6; /* Convert to kilobytes */
 
     return 0;
-}                                  
+}
 
 /*
  * See if we have gPXE
@@ -1412,7 +1398,7 @@ static void gpxe_init(void)
 }
 
 /*
- * Initialize UDP stack 
+ * Initialize UDP stack
  *
  */
 static void udp_init(void)
@@ -1427,18 +1413,18 @@ static void udp_init(void)
        kaboom();
     }
 }
-  
-    
+
+
 /*
  * Network-specific initialization
- */   
+ */
 static void network_init(void)
-{   
+{
     struct bootp_t *bp = (struct bootp_t *)trackbuf;
     int pkt_len;
 
     *LocalDomain = 0;   /* No LocalDomain received */
-    
+
     /*
      * Get the DHCP client identifiers (query info 1)
      */
@@ -1455,7 +1441,7 @@ static void network_init(void)
      * it in the future for vendor encapsulated options.
      */
     *(char *)&DHCPMagic = 1;
-    
+
     /*
      * Get the BOOTP/DHCP packet that brought us file (and an IP
      * address). This lives in the DHCPACK packet (query info 2)
@@ -1463,20 +1449,20 @@ static void network_init(void)
     pkt_len = pxe_get_cached_info(2);
     parse_dhcp(pkt_len);
     /*
-     * Save away MAC address (assume this is in query info 2. If this 
+     * Save away MAC address (assume this is in query info 2. If this
      * turns out to be problematic it might be better getting it from
      * the query info 1 packet
      */
     MAC_len = bp->hardlen > 16 ? 0 : bp->hardlen;
     MAC_type = bp->hardware;
-    memcpy(MAC, bp->macaddr, MAC_len);    
+    memcpy(MAC, bp->macaddr, MAC_len);
 
     /*
      * Get the boot file and other info. This lives in the CACHED_REPLY
      * packet (query info 3)
      */
     pkt_len = pxe_get_cached_info(3);
-    parse_dhcp(pkt_len); 
+    parse_dhcp(pkt_len);
     printf("\n");
 
     make_bootif_string();
@@ -1499,7 +1485,7 @@ static void network_init(void)
 static int pxe_fs_init(struct fs_info *fs)
 {
     (void)fs;    /* drop the compile warning message */
-    
+
     /* Initialize the Files structure */
     files_init();
 
@@ -1605,7 +1591,7 @@ void reset_pxe(void)
 }
 
 /*
- * This function unloads the PXE and UNDI stacks and 
+ * This function unloads the PXE and UNDI stacks and
  * unclaims the memory.
  */
 void unload_pxe(void)
@@ -1618,7 +1604,7 @@ void unload_pxe(void)
     static __lowmem struct s_PXENV_UNLOAD_STACK unload_stack;
 
     pxe_idle_cleanup();
-   
+
     if (KeepPXE) {
        /*
         * We want to keep PXE around, but still we should reset
@@ -1635,12 +1621,12 @@ void unload_pxe(void)
        if (err || unload_stack.Status != PXENV_STATUS_SUCCESS)
            goto cant_free;
     }
-    
+
     flag = 0xff00;
     if (real_base_mem <= BIOS_fbm)  /* Santiy check */
        goto cant_free;
     flag ++;
-    
+
     /* Check that PXE actually unhooked the INT 0x1A chain */
     int_addr = (int)MK_PTR(*(uint16_t *)(4*0x1a+2), *(uint16_t *)(4*0x1a));
     int_addr >>= 10;
@@ -1648,15 +1634,15 @@ void unload_pxe(void)
        BIOS_fbm = real_base_mem;
        return;
     }
-    
+
 cant_free:
-    printf("Failed to free base memory error %04x-%08x\n", 
+    printf("Failed to free base memory error %04x-%08x\n",
           flag, *(uint32_t *)(4 * 0x1a));
     return;
 }
-    
 
-    
+
+
 const struct fs_ops pxe_fs_ops = {
     .fs_name       = "pxe",
     .fs_flags      = FS_NODEV,