[SLOF] [PATCH v2 07/11] libnet: Wire up pxelinux.cfg network booting

Alexey Kardashevskiy aik at ozlabs.ru
Fri May 25 17:08:17 AEST 2018


On 19/5/18 1:45 am, Thomas Huth wrote:
> 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.

Without that, my test setup would report error like this:


Trying to load:  from: /pci at 800000020000000/ethernet at 1 ...
 Initializing NIC
  Reading MAC address from device: c0:41:49:4b:00:30
  Requesting information via DHCP: done
  Using IPv4 address: 10.61.191.48
  Requesting file "image.aiktest48" via TFTP from 10.61.2.7
  Receiving data:  0 KBytes
E3009 (net) file not found: image.aiktest48

E3407: Load failed



With this patch applied:

Trying to load:  from: /pci at 800000020000000/ethernet at 1 ...
 Initializing NIC
  Reading MAC address from device: c0:41:49:4b:00:30
  Requesting information via DHCP: done
  Using IPv4 address: 10.61.191.48
  Requesting file "image.aiktest48" via TFTP from 10.61.2.7
  Receiving data:  0 KBytes
E3009 (net) file not found: image.aiktest48
Trying pxelinux.cfg files...
  TFTP error: TFTP buffer of 2047 bytes is too small for pxelinux.cfg/default

E3407: Load failed


this is because....


> 
> 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 ba1008c..2a2a7c5 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]) {



.... obp_tftp_args.filename == "" in this particular case as tftp_load()
does not seem to store the filename if loading fails.





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


-- 
Alexey


More information about the SLOF mailing list