[Qemu-devel] [PATCH v2 2/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files

Thomas Huth posted 4 patches 7 years, 9 months ago
[Qemu-devel] [PATCH v2 2/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files
Posted by Thomas Huth 7 years, 9 months ago
Since it is quite cumbersome to manually create a combined kernel with
initrd image for network booting, we now support loading via pxelinux
configuration files, too. In these files, the kernel, initrd and command
line parameters can be specified seperately, and the firmware then takes
care of glueing everything together in memory after the files have been
downloaded.

The user can either specify a config file directly as bootfile via DHCP
(but in this case, the file has to start either with "default" or a "#"
comment so we can distinguish it from binary kernels), or a folder (i.e.
the bootfile name must end with "/") where the firmware should look for
the typical pxelinux.cfg file names based on MAC or IP address. If no
direct file or folder has been specified, we still look for certain
files in the default "pxelinux.cfg/" folder, but omit some of the file
names to avoid to download x86 config files here by mistake.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/netboot.mak |   5 +-
 pc-bios/s390-ccw/netmain.c   | 225 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 222 insertions(+), 8 deletions(-)

diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak
index a25d238..8db9573 100644
--- a/pc-bios/s390-ccw/netboot.mak
+++ b/pc-bios/s390-ccw/netboot.mak
@@ -24,8 +24,9 @@ CTYPE_OBJS = isdigit.o isxdigit.o toupper.o
 %.o : $(SLOF_DIR)/lib/libc/ctype/%.c
 	$(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@")
 
-STRING_OBJS = strcat.o strchr.o strcmp.o strcpy.o strlen.o strncmp.o strncpy.o \
-	      strstr.o memset.o memcpy.o memmove.o memcmp.o
+STRING_OBJS = strcasecmp.o strcat.o strchr.o strcmp.o strcpy.o strlen.o \
+	      strncasecmp.o strncmp.o strncpy.o strstr.o \
+	      memset.o memcpy.o memmove.o memcmp.o
 %.o : $(SLOF_DIR)/lib/libc/string/%.c
 	$(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@")
 
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index 8fa9e6c..129f009 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -39,11 +39,17 @@
 
 extern char _start[];
 
+#define KERNEL_ADDR             ((void *)0L)
+#define KERNEL_MAX_SIZE         ((long)_start)
+#define ARCH_COMMAND_LINE_SIZE  896              /* Taken from Linux kernel */
+
 char stack[PAGE_SIZE * 8] __attribute__((aligned(PAGE_SIZE)));
 IplParameterBlock iplb __attribute__((aligned(PAGE_SIZE)));
+static char cfgbuf[2048];
 
 static SubChannelId net_schid = { .one = 1 };
 static int ip_version = 4;
+static uint8_t mac[6];
 static uint64_t dest_timer;
 
 static uint64_t get_timer_ms(void)
@@ -136,9 +142,15 @@ static int tftp_load(filename_ip_t *fnip, void *buffer, int len)
     rc = tftp(fnip, buffer, len, DEFAULT_TFTP_RETRIES, &tftp_err, 1, 1428,
               ip_version);
 
-    if (rc > 0) {
-        printf("  TFTP: Received %s (%d KBytes)\n", fnip->filename,
-               rc / 1024);
+    if (rc < 0) {
+        /* Make sure that error messages are put into a new line */
+        printf("\n  ");
+    }
+
+    if (rc > 1024) {
+        printf("  TFTP: Received %s (%d KBytes)\n", fnip->filename, rc / 1024);
+    } else if (rc > 0) {
+        printf("  TFTP: Received %s (%d Bytes)\n", fnip->filename, rc);
     } else if (rc == -1) {
         puts("unknown TFTP error");
     } else if (rc == -2) {
@@ -201,7 +213,6 @@ static int tftp_load(filename_ip_t *fnip, void *buffer, int len)
 
 static int net_init(filename_ip_t *fn_ip)
 {
-    uint8_t mac[6];
     int rc;
 
     memset(fn_ip, 0, sizeof(filename_ip_t));
@@ -275,6 +286,202 @@ static void net_release(filename_ip_t *fn_ip)
     }
 }
 
+/* This structure holds the data from one pxelinux.cfg file entry */
+struct lkia {
+    const char *label;
+    const char *kernel;
+    const char *initrd;
+    const char *append;
+};
+
+static int load_kernel_with_initrd(filename_ip_t *fn_ip, struct lkia *kia)
+{
+    int rc;
+
+    printf("Loading pxelinux.cfg entry '%s'\n", kia->label);
+
+    if (!kia->kernel) {
+        printf("Kernel entry is missing!\n");
+        return -1;
+    }
+
+    strncpy((char *)&fn_ip->filename, kia->kernel, sizeof(fn_ip->filename));
+    rc = tftp_load(fn_ip, KERNEL_ADDR, KERNEL_MAX_SIZE);
+    if (rc < 0) {
+        return rc;
+    }
+
+    if (kia->initrd) {
+        uint64_t iaddr = (rc + 0xfff) & ~0xfffUL;
+
+        strncpy((char *)&fn_ip->filename, kia->initrd, sizeof(fn_ip->filename));
+        rc = tftp_load(fn_ip, (void *)iaddr, KERNEL_MAX_SIZE - iaddr);
+        if (rc < 0) {
+            return rc;
+        }
+        /* Patch location and size: */
+        *(uint64_t *)0x10408 = iaddr;
+        *(uint64_t *)0x10410 = rc;
+        rc += iaddr;
+    }
+
+    if (kia->append) {
+        strncpy((char *)0x10480, kia->append, ARCH_COMMAND_LINE_SIZE);
+    }
+
+    return rc;
+}
+
+#define MAX_PXELINUX_ENTRIES 16
+
+/**
+ * Parse a pxelinux-style configuration file.
+ * See the following URL for more inforation about the config file syntax:
+ * https://www.syslinux.org/wiki/index.php?title=PXELINUX
+ */
+static int handle_pxelinux_cfg(filename_ip_t *fn_ip, char *cfg, int cfgsize)
+{
+    struct lkia entries[MAX_PXELINUX_ENTRIES];
+    int num_entries = 0;
+    char *ptr = cfg, *eol, *arg;
+    char *defaultlabel = NULL;
+    int def_ent = 0;
+
+    while (ptr < cfg + cfgsize && num_entries < MAX_PXELINUX_ENTRIES) {
+        eol = strchr(ptr, '\n');
+        if (!eol) {
+            eol = cfg + cfgsize;
+        }
+        if (eol > ptr && *(eol - 1) == '\r') {
+            *(eol - 1) = 0;
+        }
+        *eol = '\0';
+        while (*ptr == ' ' || *ptr == '\t') {
+            ptr++;
+        }
+        if (*ptr == 0 || *ptr == '#') {   /* Ignore comments and empty lines */
+            goto nextline;
+        }
+        arg = strchr(ptr, ' ');    /* Look for space between command and arg */
+        if (!arg) {
+            arg = strchr(ptr, '\t');
+        }
+        if (!arg) {
+            printf("Failed to parse the following line:\n %s\n", ptr);
+            goto nextline;
+        }
+        *arg++ = 0;
+        while (*arg == ' ' || *arg == '\t') {
+            arg++;
+        }
+        if (!strcasecmp("default", ptr)) {
+            defaultlabel = arg;
+        } else if (!strcasecmp("label", ptr)) {
+            entries[num_entries].label = arg;
+            if (defaultlabel && !strcmp(arg, defaultlabel)) {
+                def_ent = num_entries;
+            }
+            num_entries++;
+        } else if (!strcasecmp("kernel", ptr) && num_entries > 0) {
+            entries[num_entries - 1].kernel = arg;
+        } else if (!strcasecmp("initrd", ptr) && num_entries > 0) {
+            entries[num_entries - 1].initrd = arg;
+        } else if (!strcasecmp("append", ptr) && num_entries > 0) {
+            entries[num_entries - 1].append = arg;
+        } else {
+            printf("Command '%s' is not supported.\n", ptr);
+        }
+nextline:
+        ptr = eol + 1;
+    }
+
+    return load_kernel_with_initrd(fn_ip, &entries[def_ent]);
+}
+
+static int net_try_pxelinux_cfgs(filename_ip_t *fn_ip)
+{
+    int rc, idx;
+    char basedir[256];
+    int has_basedir;
+
+    cfgbuf[sizeof(cfgbuf) - 1] = 0;   /* Make sure that it is NUL-terminated */
+
+    /* Did we get a usable base directory via DHCP? */
+    idx = strlen((char *)fn_ip->filename);
+    if (idx > 0 && idx < sizeof(basedir) - 40 &&
+        fn_ip->filename[idx - 1] == '/') {
+        has_basedir = true;
+        strcpy(basedir, (char *)fn_ip->filename);
+    } else {
+        has_basedir = false;
+        strcpy(basedir, "pxelinux.cfg/");
+    }
+
+    printf("Trying pxelinux.cfg files...\n");
+
+    /* Look for config file with MAC address in its name */
+    sprintf((char *)fn_ip->filename, "%s%02x-%02x-%02x-%02x-%02x-%02x",
+            basedir, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+    rc = tftp_load(fn_ip, cfgbuf, sizeof(cfgbuf) - 1);
+    if (rc > 0) {
+        return handle_pxelinux_cfg(fn_ip, cfgbuf, sizeof(cfgbuf));
+    }
+
+    /* Look for config file with IP address in its name */
+    if (ip_version == 4) {
+        for (idx = 0; (has_basedir && idx <= 7) || idx < 1; idx++) {
+            sprintf((char *)fn_ip->filename, "%s%02X%02X%02X%02X", basedir,
+                    (fn_ip->own_ip >> 24) & 0xff, (fn_ip->own_ip >> 16) & 0xff,
+                    (fn_ip->own_ip >> 8) & 0xff, fn_ip->own_ip & 0xff);
+            fn_ip->filename[strlen((char *)fn_ip->filename) - idx] = 0;
+            rc = tftp_load(fn_ip, cfgbuf, sizeof(cfgbuf) - 1);
+            if (rc > 0) {
+                return handle_pxelinux_cfg(fn_ip, cfgbuf, sizeof(cfgbuf));
+            }
+        }
+    }
+
+    /* Try "default" config file */
+    if (has_basedir) {
+        sprintf((char *)fn_ip->filename, "%sdefault", basedir);
+        rc = tftp_load(fn_ip, cfgbuf, sizeof(cfgbuf) - 1);
+        if (rc > 0) {
+            return handle_pxelinux_cfg(fn_ip, cfgbuf, sizeof(cfgbuf));
+        }
+    }
+
+    return -1;
+}
+
+static int net_try_direct_tftp_load(filename_ip_t *fn_ip)
+{
+    int rc;
+    void *baseaddr = (void *)0x2000;  /* Load right after the low-core */
+
+    rc = tftp_load(fn_ip, baseaddr, KERNEL_MAX_SIZE - (long)baseaddr);
+    if (rc < 0) {
+        return rc;
+    } else if (rc < 8) {
+        printf("'%s' is too small (%i bytes only).\n", fn_ip->filename, rc);
+        return -1;
+    }
+
+    /* Check whether it is a configuration file instead of a kernel */
+    if (rc < sizeof(cfgbuf) - 1) {
+        memcpy(cfgbuf, baseaddr, rc);
+        cfgbuf[rc] = 0;    /* Make sure that it is NUL-terminated */
+        if (!strncasecmp("default", cfgbuf, 7) || !strncmp("# ", cfgbuf, 2)) {
+            /* Looks like it is a pxelinux.cfg */
+            return handle_pxelinux_cfg(fn_ip, cfgbuf, rc);
+        }
+    }
+
+    /* Move kernel to right location */
+    memmove(KERNEL_ADDR, baseaddr, rc);
+
+    return rc;
+}
+
 void panic(const char *string)
 {
     sclp_print(string);
@@ -347,7 +554,7 @@ static void virtio_setup(void)
 void main(void)
 {
     filename_ip_t fn_ip;
-    int rc;
+    int rc, fnlen;
 
     sclp_setup();
     sclp_print("Network boot starting...\n");
@@ -359,7 +566,13 @@ void main(void)
         panic("Network initialization failed. Halting.\n");
     }
 
-    rc = tftp_load(&fn_ip, NULL, (long)_start);
+    fnlen = strlen((char *)fn_ip.filename);
+    if (fnlen > 0 && fn_ip.filename[fnlen - 1] != '/') {
+        rc = net_try_direct_tftp_load(&fn_ip);
+    }
+    if (rc <= 0) {
+        rc = net_try_pxelinux_cfgs(&fn_ip);
+    }
 
     net_release(&fn_ip);
 
-- 
1.8.3.1


Re: [Qemu-devel] [PATCH v2 2/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files
Posted by Viktor VM Mihajlovski 7 years, 9 months ago
On 23.04.2018 09:58, Thomas Huth wrote:
> Since it is quite cumbersome to manually create a combined kernel with
> initrd image for network booting, we now support loading via pxelinux
> configuration files, too. In these files, the kernel, initrd and command
> line parameters can be specified seperately, and the firmware then takes
> care of glueing everything together in memory after the files have been
> downloaded.
> 
> The user can either specify a config file directly as bootfile via DHCP
> (but in this case, the file has to start either with "default" or a "#"
> comment so we can distinguish it from binary kernels), or a folder (i.e.
> the bootfile name must end with "/") where the firmware should look for
> the typical pxelinux.cfg file names based on MAC or IP address. If no
> direct file or folder has been specified, we still look for certain
> files in the default "pxelinux.cfg/" folder, but omit some of the file
> names to avoid to download x86 config files here by mistake.
I don't think this is necessary, since the DHCP server configuration
SHOULD take into consideration the processor architecture. In fact it is
even annoying and hard to understand that an attempt is made to load the
uuid, mac and "full ip" based config files but not the "abbreviated ip"
or default file. After all, even if the config file for x86 was loaded,
the effect will be that the network boot fails (as it does now).
> 
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
>  pc-bios/s390-ccw/netboot.mak |   5 +-
>  pc-bios/s390-ccw/netmain.c   | 225 +++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 222 insertions(+), 8 deletions(-)
> 
[...]
-- 
Regards,
  Viktor Mihajlovski


Re: [Qemu-devel] [PATCH v2 2/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files
Posted by Thomas Huth 7 years, 9 months ago
On 24.04.2018 13:07, Viktor VM Mihajlovski wrote:
> On 23.04.2018 09:58, Thomas Huth wrote:
>> Since it is quite cumbersome to manually create a combined kernel with
>> initrd image for network booting, we now support loading via pxelinux
>> configuration files, too. In these files, the kernel, initrd and command
>> line parameters can be specified seperately, and the firmware then takes
>> care of glueing everything together in memory after the files have been
>> downloaded.
>>
>> The user can either specify a config file directly as bootfile via DHCP
>> (but in this case, the file has to start either with "default" or a "#"
>> comment so we can distinguish it from binary kernels), or a folder (i.e.
>> the bootfile name must end with "/") where the firmware should look for
>> the typical pxelinux.cfg file names based on MAC or IP address. If no
>> direct file or folder has been specified, we still look for certain
>> files in the default "pxelinux.cfg/" folder, but omit some of the file
>> names to avoid to download x86 config files here by mistake.
> I don't think this is necessary, since the DHCP server configuration
> SHOULD take into consideration the processor architecture. In fact it is
> even annoying and hard to understand that an attempt is made to load the
> uuid, mac and "full ip" based config files but not the "abbreviated ip"
> or default file.

If the DHCP server has been been properly configured to take the
processor architecture into account, there should be a usable entry in
the bootfile (i.e. either a binary, a config file or a folder where
config files should be probed). So in this case the skipping does not
take place.

And if you want the full probing in the pxelinux.cfg/ directory, you can
also specify "pxelinux.xfg/" in the bootfile entry.

The skipping only happens if there is no valid entry in the bootfile,
i.e. the server configuration was likely wrong anyway, and we just do
some desperate final guesses with the default "pxelinux.cfg/" directory
before giving up.

> After all, even if the config file for x86 was loaded,
> the effect will be that the network boot fails (as it does now).

Ok, that's true, too.

Actually, I don't mind too much whether we probe the files based on the
partial IP address or the "default" name, or whether we skip them. I
thought it might be a good idea to avoid a potential clash with x86
files, but if you think that this is rather confusing, I also see your
point. So I'd say let's wait for some more opinions from others before
we decide about the final behavior...

 Thomas

Re: [Qemu-devel] [PATCH v2 2/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files
Posted by Viktor VM Mihajlovski 7 years, 9 months ago
On 24.04.2018 13:23, Thomas Huth wrote:
> On 24.04.2018 13:07, Viktor VM Mihajlovski wrote:
>> On 23.04.2018 09:58, Thomas Huth wrote:
>>> Since it is quite cumbersome to manually create a combined kernel with
>>> initrd image for network booting, we now support loading via pxelinux
>>> configuration files, too. In these files, the kernel, initrd and command
>>> line parameters can be specified seperately, and the firmware then takes
>>> care of glueing everything together in memory after the files have been
>>> downloaded.
>>>
>>> The user can either specify a config file directly as bootfile via DHCP
>>> (but in this case, the file has to start either with "default" or a "#"
>>> comment so we can distinguish it from binary kernels), or a folder (i.e.
>>> the bootfile name must end with "/") where the firmware should look for
>>> the typical pxelinux.cfg file names based on MAC or IP address. If no
>>> direct file or folder has been specified, we still look for certain
>>> files in the default "pxelinux.cfg/" folder, but omit some of the file
>>> names to avoid to download x86 config files here by mistake.
>> I don't think this is necessary, since the DHCP server configuration
>> SHOULD take into consideration the processor architecture. In fact it is
>> even annoying and hard to understand that an attempt is made to load the
>> uuid, mac and "full ip" based config files but not the "abbreviated ip"
>> or default file.
> 
> If the DHCP server has been been properly configured to take the
> processor architecture into account, there should be a usable entry in
> the bootfile (i.e. either a binary, a config file or a folder where
> config files should be probed). So in this case the skipping does not
> take place.
> 
> And if you want the full probing in the pxelinux.cfg/ directory, you can
> also specify "pxelinux.xfg/" in the bootfile entry.
> 
> The skipping only happens if there is no valid entry in the bootfile,
> i.e. the server configuration was likely wrong anyway, and we just do
> some desperate final guesses with the default "pxelinux.cfg/" directory
> before giving up.
> 
My major concern is consistency. The emergency probing is different from
the normal one and this can be hell to debug (it took me a while to
understand what went wrong[1]).
I like the idea to improve the usability by doing a wild guess, but only
if it is consistent with the regular behavior.
>> After all, even if the config file for x86 was loaded,
>> the effect will be that the network boot fails (as it does now).
> 
> Ok, that's true, too.
> 
> Actually, I don't mind too much whether we probe the files based on the
> partial IP address or the "default" name, or whether we skip them. I
> thought it might be a good idea to avoid a potential clash with x86
> files, but if you think that this is rather confusing, I also see your
> point. So I'd say let's wait for some more opinions from others before
> we decide about the final behavior...
> 
>  Thomas
> 

[1] What I did was to keep my previous pxelinux configuration but delete
the pxelinux.0 file on the server to force the built-in processing.

-- 
Regards,
  Viktor Mihajlovski


Re: [Qemu-devel] [PATCH v2 2/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files
Posted by Viktor VM Mihajlovski 7 years, 9 months ago
On 23.04.2018 09:58, Thomas Huth wrote:
[...]
> +
> +static int net_try_pxelinux_cfgs(filename_ip_t *fn_ip)
> +{
> +    int rc, idx;
> +    char basedir[256];
> +    int has_basedir;
> +
> +    cfgbuf[sizeof(cfgbuf) - 1] = 0;   /* Make sure that it is NUL-terminated */
> +
> +    /* Did we get a usable base directory via DHCP? */
> +    idx = strlen((char *)fn_ip->filename);
> +    if (idx > 0 && idx < sizeof(basedir) - 40 &&
> +        fn_ip->filename[idx - 1] == '/') {
> +        has_basedir = true;
> +        strcpy(basedir, (char *)fn_ip->filename);
> +    } else {
> +        has_basedir = false;
> +        strcpy(basedir, "pxelinux.cfg/");
> +    }
> +
> +    printf("Trying pxelinux.cfg files...\n");
> +
> +    /* Look for config file with MAC address in its name */
> +    sprintf((char *)fn_ip->filename, "%s%02x-%02x-%02x-%02x-%02x-%02x",
> +            basedir, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Just noticed that the filename has to be <basedir>/pxelinux.cfg/01-<mac>
per [1].
> +    rc = tftp_load(fn_ip, cfgbuf, sizeof(cfgbuf) - 1);
> +    if (rc > 0) {
> +        return handle_pxelinux_cfg(fn_ip, cfgbuf, sizeof(cfgbuf));
> +    }
> +
> +    /* Look for config file with IP address in its name */
> +    if (ip_version == 4) {
> +        for (idx = 0; (has_basedir && idx <= 7) || idx < 1; idx++) {
> +            sprintf((char *)fn_ip->filename, "%s%02X%02X%02X%02X", basedir,
> +                    (fn_ip->own_ip >> 24) & 0xff, (fn_ip->own_ip >> 16) & 0xff,
> +                    (fn_ip->own_ip >> 8) & 0xff, fn_ip->own_ip & 0xff);
> +            fn_ip->filename[strlen((char *)fn_ip->filename) - idx] = 0;
> +            rc = tftp_load(fn_ip, cfgbuf, sizeof(cfgbuf) - 1);
> +            if (rc > 0) {
> +                return handle_pxelinux_cfg(fn_ip, cfgbuf, sizeof(cfgbuf));
> +            }
> +        }
> +    }
> +
> +    /* Try "default" config file */
> +    if (has_basedir) {
> +        sprintf((char *)fn_ip->filename, "%sdefault", basedir);
> +        rc = tftp_load(fn_ip, cfgbuf, sizeof(cfgbuf) - 1);
> +        if (rc > 0) {
> +            return handle_pxelinux_cfg(fn_ip, cfgbuf, sizeof(cfgbuf));
> +        }
> +    }
> +
> +    return -1;
> +}
> +
[...]

[1
]https://www.syslinux.org/wiki/index.php?title=PXELINUX#Configuration_filename

-- 
Regards,
  Viktor Mihajlovski


Re: [Qemu-devel] [PATCH v2 2/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files
Posted by Thomas Huth 7 years, 9 months ago
On 24.04.2018 15:41, Viktor VM Mihajlovski wrote:
> On 23.04.2018 09:58, Thomas Huth wrote:
> [...]
>> +
>> +static int net_try_pxelinux_cfgs(filename_ip_t *fn_ip)
>> +{
>> +    int rc, idx;
>> +    char basedir[256];
>> +    int has_basedir;
>> +
>> +    cfgbuf[sizeof(cfgbuf) - 1] = 0;   /* Make sure that it is NUL-terminated */
>> +
>> +    /* Did we get a usable base directory via DHCP? */
>> +    idx = strlen((char *)fn_ip->filename);
>> +    if (idx > 0 && idx < sizeof(basedir) - 40 &&
>> +        fn_ip->filename[idx - 1] == '/') {
>> +        has_basedir = true;
>> +        strcpy(basedir, (char *)fn_ip->filename);
>> +    } else {
>> +        has_basedir = false;
>> +        strcpy(basedir, "pxelinux.cfg/");
>> +    }
>> +
>> +    printf("Trying pxelinux.cfg files...\n");
>> +
>> +    /* Look for config file with MAC address in its name */
>> +    sprintf((char *)fn_ip->filename, "%s%02x-%02x-%02x-%02x-%02x-%02x",
>> +            basedir, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
> Just noticed that the filename has to be <basedir>/pxelinux.cfg/01-<mac>
> per [1].

Ok. I just also had a closer look at the URL that you've mentioned on
IRC (http://jk.ozlabs.org/blog/post/158/netbooting-petitboot/), and
noticed that there is even an additional DHCP option (210) for
specifying the prefix path ... so I'll try to rework my patches accordingly.

 Thomas