diff options
author | Thomas Huth <thuth@redhat.com> | 2018-05-26 08:06:05 +0200 |
---|---|---|
committer | Alexey Kardashevskiy <aik@ozlabs.ru> | 2018-05-29 19:06:45 +1000 |
commit | 08e22e4019030b2f643f65c192c64f3a939fec24 (patch) | |
tree | 31b73ab866e1b205282a8a74d8b483f67cda1587 /lib | |
parent | 696e2036f44788769038e998a4465dfe58906d29 (diff) | |
download | SLOF-08e22e4019030b2f643f65c192c64f3a939fec24.zip SLOF-08e22e4019030b2f643f65c192c64f3a939fec24.tar.gz SLOF-08e22e4019030b2f643f65c192c64f3a939fec24.tar.bz2 |
libnet: Wire up pxelinux.cfg network booting
In case the normal network loading failed, try to load a pxelinux.cfg
config file. If that succeeds, load the kernel and initrd with the
information that could be found in this file.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libnet/netload.c | 84 |
1 files changed, 82 insertions, 2 deletions
diff --git a/lib/libnet/netload.c b/lib/libnet/netload.c index f06c2fd..8a38771 100644 --- a/lib/libnet/netload.c +++ b/lib/libnet/netload.c @@ -26,6 +26,7 @@ #include <helpers.h> #include "args.h" #include "netapps.h" +#include "pxelinux.h" #define IP_INIT_DEFAULT 5 #define IP_INIT_NONE 0 @@ -426,6 +427,75 @@ static int tftp_load(filename_ip_t *fnip, void *buffer, int len, return rc; } +#define CFG_BUF_SIZE 2048 +#define MAX_PL_CFG_ENTRIES 16 +static int net_pxelinux_load(filename_ip_t *fnip, char *loadbase, + int maxloadlen, uint8_t *mac, int retries) +{ + struct pl_cfg_entry entries[MAX_PL_CFG_ENTRIES]; + int def, rc, ilen; + static char *cfgbuf; + + cfgbuf = malloc(CFG_BUF_SIZE); + if (!cfgbuf) { + puts("Not enough memory for pxelinux config file buffer!"); + return -1; + } + + rc = pxelinux_load_parse_cfg(fnip, mac, retries, cfgbuf, CFG_BUF_SIZE, + entries, MAX_PL_CFG_ENTRIES, &def); + if (rc < 0) + goto out_free; + if (rc == 0) { + puts("No valid entries in pxelinux config file."); + rc = -1; + goto out_free; + } + + /* Load kernel */ + strncpy(fnip->filename, entries[def].kernel, + sizeof(fnip->filename) - 1); + fnip->filename[sizeof(fnip->filename) - 1] = 0; + rc = tftp_load(fnip, loadbase, maxloadlen, retries); + if (rc <= 0) + goto out_free; + + /* Load ramdisk */ + if (entries[def].initrd) { + loadbase += rc; + maxloadlen -= rc; + if (maxloadlen <= 0) { + puts(" Not enough space for loading the initrd!"); + rc = -1; + goto out_free; + } + strncpy(fnip->filename, entries[def].initrd, + sizeof(fnip->filename) - 1); + ilen = tftp_load(fnip, loadbase, maxloadlen, retries); + if (ilen < 0) { + rc = ilen; + goto out_free; + } + /* The ELF loader will move the kernel to some spot in low mem + * later, thus move the initrd to the end of the RAM instead */ + memmove(loadbase + maxloadlen - ilen, loadbase, ilen); + /* Encode the initrd information in the device tree */ + SLOF_set_chosen_int("linux,initrd-start", + (long)loadbase + maxloadlen - ilen); + SLOF_set_chosen_int("linux,initrd-end", + (long)loadbase + maxloadlen); + } + + if (entries[def].append) { + SLOF_set_chosen_bytes("bootargs", entries[def].append, + strlen(entries[def].append) + 1); + } + +out_free: + free(cfgbuf); + return rc; +} + static void encode_response(char *pkt_buffer, size_t size, int ip_init) { switch(ip_init) { @@ -444,7 +514,7 @@ static void encode_response(char *pkt_buffer, size_t size, int ip_init) int netload(char *buffer, int len, char *args_fs, int alen) { - int rc; + int rc, filename_len; filename_ip_t fn_ip; int fd_device; obp_tftp_args_t obp_tftp_args; @@ -687,7 +757,17 @@ int netload(char *buffer, int len, char *args_fs, int alen) } /* Do the TFTP load and print error message if necessary */ - rc = tftp_load(&fn_ip, buffer, len, obp_tftp_args.tftp_retries); + rc = 0; + filename_len = strlen(fn_ip.filename); + if (filename_len > 0 && fn_ip.filename[filename_len - 1] != '/') { + rc = tftp_load(&fn_ip, buffer, len, obp_tftp_args.tftp_retries); + } + + if (rc <= 0 && !obp_tftp_args.filename[0] && + (!filename_len || fn_ip.filename[filename_len - 1] == '/')) { + rc = net_pxelinux_load(&fn_ip, buffer, len, own_mac, + obp_tftp_args.tftp_retries); + } if (obp_tftp_args.ip_init == IP_INIT_DHCP) dhcp_send_release(fn_ip.fd); |