[SLOF] [PATCH v2 07/11] libnet: Wire up pxelinux.cfg network booting
Alexey Kardashevskiy
aik at ozlabs.ru
Fri May 25 12:44:40 AEST 2018
On 25/5/18 12:39 am, Thomas Huth wrote:
> On 24.05.2018 11:01, Alexey Kardashevskiy wrote:
>> 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.
>>>
>>> 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)
>>
>>
>> The name confused me, there is already pxelinux_load_cfg().
>> net_pxelinux_load() may be?
>
> Sure, I'll rename it.
>
>>> +{
>>> + static char cfgbuf[CFG_BUF_SIZE];
>>
>> This belongs to pxelinux_load_parse_cfg().
>
> The pointer in the struct lkia entries[] below will point to the
> original location in the above buffer, so this cfgbuf needs to remain
> valid until the end of this function. That means, the memory for the
> buffer should be managed in the calling function instead of doing it in
> pxelinux_load_parse_cfg(). I should maybe update the comments there to
> make this clear... Alternatively, I could also "strdup" the strings for
> the struct lkia entries, but then this caller here has to make sure to
> free the strings again once the information from struct lkia is not
> needed anymore - and IMHO that's uglier and more error-prone than to
> allocate the cfgbuf buffer here on the calling site.
Open coding pxelinux_load_parse_cfg() here would have eliminated the
question in the first place. You export pxelinux_parse_cfg() anyway even
though you do not use it outside lib/libnet/pxelinux.c.
>
>> And why static?
>
> Allocating big buffers on the stack is always critical within paflof,
> we've seen more than enough buffer overruns in the past already. But I
> could malloc() the buffer instead if you prefer that.
It is just 2KB, is it still too much for slof? And when it is static - this
space is always taken even if pxelinux is not used so malloc seems
appropriate here.
>
>>> + 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;
>>> +}
>
> Thomas
>
--
Alexey
More information about the SLOF
mailing list