[SLOF] [PATCH 7/9] libnet: Wire up pxelinux.cfg network booting
Thomas Huth
thuth at redhat.com
Fri May 18 03:40:54 AEST 2018
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 at redhat.com>
---
include/helpers.h | 2 ++
lib/libnet/netload.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++
slof/helpers.c | 15 ++++++++++---
3 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/include/helpers.h b/include/helpers.h
index 04ee771..9dfe3ae 100644
--- a/include/helpers.h
+++ b/include/helpers.h
@@ -36,6 +36,8 @@ extern void SLOF_pci_config_write16(long offset, long value);
extern void SLOF_pci_config_write8(long offset, long value);
extern void *SLOF_translate_my_address(void *addr);
extern int write_mm_log(char *data, unsigned int len, unsigned short type);
+extern void SLOF_set_chosen_int(const char *s, long val);
+extern void SLOF_set_chosen_bytes(const char *s, const char *addr, size_t size);
extern void SLOF_encode_bootp_response(void *addr, size_t size);
extern void SLOF_encode_dhcp_response(void *addr, size_t size);
diff --git a/lib/libnet/netload.c b/lib/libnet/netload.c
index 9208e10..4236be7 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
@@ -425,6 +426,60 @@ static int tftp_load(filename_ip_t *fnip, void *buffer, int len)
return rc;
}
+#define CFG_BUF_SIZE 2048
+#define MAX_LKIA_ENTRIES 16
+static int net_pxelinux_cfg_load(filename_ip_t *fnip, char *loadbase,
+ int maxloadlen, uint8_t *mac)
+{
+ static char cfgbuf[CFG_BUF_SIZE];
+ struct lkia entries[MAX_LKIA_ENTRIES];
+ int def, num_entries, rc, ilen;
+
+ num_entries = pxelinux_load_parse_cfg(fnip, mac, NULL, cfgbuf,
+ CFG_BUF_SIZE, entries,
+ MAX_LKIA_ENTRIES, &def);
+ if (num_entries <= 0)
+ return -1;
+
+ /* 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);
+ if (rc < 0)
+ return rc;
+
+ /* Load ramdisk */
+ if (entries[def].initrd) {
+ loadbase += rc;
+ maxloadlen -= rc;
+ if (maxloadlen <= 0) {
+ puts(" Not enough space for loading the initrd!");
+ return -1;
+ }
+ strncpy(fnip->filename, entries[def].initrd,
+ sizeof(fnip->filename) - 1);
+ ilen = tftp_load(fnip, loadbase, maxloadlen);
+ if (ilen < 0)
+ return ilen;
+ /* 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);
+ }
+
+ return rc;
+}
+
static void encode_response(char *pkt_buffer, size_t size, int ip_init)
{
switch(ip_init) {
@@ -689,6 +744,10 @@ 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);
+ if (rc <= 0 && !obp_tftp_args.filename[0]) {
+ rc = net_pxelinux_cfg_load(&fn_ip, buffer, len, own_mac);
+ }
+
if (obp_tftp_args.ip_init == IP_INIT_DHCP)
dhcp_send_release(fn_ip.fd);
diff --git a/slof/helpers.c b/slof/helpers.c
index a8d575c..bd0742e 100644
--- a/slof/helpers.c
+++ b/slof/helpers.c
@@ -181,7 +181,16 @@ int write_mm_log(char *data, unsigned int len, unsigned short type)
return forth_eval_pop("write-mm-log");
}
-static void SLOF_encode_response(void *addr, size_t size,char *s)
+void SLOF_set_chosen_int(const char *s, long val)
+{
+ forth_push(val);
+ forth_eval("encode-int");
+ forth_push((unsigned long)s);
+ forth_push(strlen(s));
+ forth_eval("set-chosen");
+}
+
+void SLOF_set_chosen_bytes(const char *s, const char *addr, size_t size)
{
forth_push((unsigned long)addr);
forth_push(size);
@@ -193,10 +202,10 @@ static void SLOF_encode_response(void *addr, size_t size,char *s)
void SLOF_encode_bootp_response(void *addr, size_t size)
{
- SLOF_encode_response(addr, size, "bootp-response");
+ SLOF_set_chosen_bytes("bootp-response", addr, size);
}
void SLOF_encode_dhcp_response(void *addr, size_t size)
{
- SLOF_encode_response(addr, size, "dhcp-response");
+ SLOF_set_chosen_bytes("dhcp-response", addr, size);
}
--
1.8.3.1
More information about the SLOF
mailing list