diff mbox series

[7/9] libnet: Wire up pxelinux.cfg network booting

Message ID 1526578856-30967-8-git-send-email-thuth@redhat.com
State Superseded
Headers show
Series Support network booting with pxelinux.cfg files | expand

Commit Message

Thomas Huth May 17, 2018, 5:40 p.m. UTC
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>
---
 include/helpers.h    |  2 ++
 lib/libnet/netload.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 slof/helpers.c       | 15 ++++++++++---
 3 files changed, 73 insertions(+), 3 deletions(-)
diff mbox series

Patch

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);
 }