[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add suppo
From: |
Viktor VM Mihajlovski |
Subject: |
Re: [Qemu-devel] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files |
Date: |
Thu, 19 Apr 2018 09:41:19 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.7.0 |
On 18.04.2018 14:31, Thomas Huth wrote:
> Since it is quite cumbersome to manually create a combined kernel with
> initrd image for network booting, we now support loading via pxelinux
> configuration files, too. In these files, the kernel, initrd and command
> line parameters can be specified seperately, and the firmware then takes
> care of glueing everything together in memory after the files have been
> downloaded.
>
> Signed-off-by: Thomas Huth <address@hidden>
> ---
> pc-bios/s390-ccw/netboot.mak | 5 +-
> pc-bios/s390-ccw/netmain.c | 203
> +++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 201 insertions(+), 7 deletions(-)
>
> diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak
> index a25d238..8db9573 100644
> --- a/pc-bios/s390-ccw/netboot.mak
> +++ b/pc-bios/s390-ccw/netboot.mak
> @@ -24,8 +24,9 @@ CTYPE_OBJS = isdigit.o isxdigit.o toupper.o
> %.o : $(SLOF_DIR)/lib/libc/ctype/%.c
> $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@
> $<,"CC","$(TARGET_DIR)$@")
>
> -STRING_OBJS = strcat.o strchr.o strcmp.o strcpy.o strlen.o strncmp.o
> strncpy.o \
> - strstr.o memset.o memcpy.o memmove.o memcmp.o
> +STRING_OBJS = strcasecmp.o strcat.o strchr.o strcmp.o strcpy.o strlen.o \
> + strncasecmp.o strncmp.o strncpy.o strstr.o \
> + memset.o memcpy.o memmove.o memcmp.o
> %.o : $(SLOF_DIR)/lib/libc/string/%.c
> $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@
> $<,"CC","$(TARGET_DIR)$@")
>
> diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
> index e11ed4e..fa62bfe 100644
> --- a/pc-bios/s390-ccw/netmain.c
> +++ b/pc-bios/s390-ccw/netmain.c
> @@ -39,11 +39,17 @@
>
> extern char _start[];
>
> +#define KERNEL_ADDR ((void *)0L)
> +#define KERNEL_MAX_SIZE ((long)_start)
> +#define ARCH_COMMAND_LINE_SIZE 896 /* Taken from Linux kernel
> */
> +
> char stack[PAGE_SIZE * 8] __attribute__((aligned(PAGE_SIZE)));
> IplParameterBlock iplb __attribute__((aligned(PAGE_SIZE)));
> +static char cfgbuf[2048];
>
> static SubChannelId net_schid = { .one = 1 };
> static int ip_version = 4;
> +static uint8_t mac[6];
> static uint64_t dest_timer;
>
> static uint64_t get_timer_ms(void)
> @@ -136,9 +142,15 @@ static int tftp_load(filename_ip_t *fnip, void *buffer,
> int len)
> rc = tftp(fnip, buffer, len, DEFAULT_TFTP_RETRIES, &tftp_err, 1, 1428,
> ip_version);
>
> - if (rc > 0) {
> - printf(" TFTP: Received %s (%d KBytes)\n", fnip->filename,
> - rc / 1024);
> + if (rc < 0) {
> + /* Make sure that error messages are put into a new line */
> + printf("\n ");
> + }
> +
> + if (rc > 1024) {
> + printf(" TFTP: Received %s (%d KBytes)\n", fnip->filename, rc /
> 1024);
> + } else if (rc > 0) {
> + printf(" TFTP: Received %s (%d Bytes)\n", fnip->filename, rc);
> } else if (rc == -1) {
> puts("unknown TFTP error");
> } else if (rc == -2) {
> @@ -201,7 +213,6 @@ static int tftp_load(filename_ip_t *fnip, void *buffer,
> int len)
>
> static int net_init(filename_ip_t *fn_ip)
> {
> - uint8_t mac[6];
> int rc;
>
> memset(fn_ip, 0, sizeof(filename_ip_t));
> @@ -276,6 +287,183 @@ static void net_uninit(filename_ip_t *fn_ip)
> virtio_net_uninit();
> }
>
> +/* This structure holds the data from one pxelinux.cfg file entry */
> +struct lkia {
> + const char *label;
> + const char *kernel;
> + const char *initrd;
> + const char *append;
> +};
> +
> +static int load_kernel_with_initrd(filename_ip_t *fn_ip, struct lkia *kia)
> +{
> + int rc;
> +
> + printf("Loading pxelinux.cfg entry '%s'\n", kia->label);
> +
> + if (!kia->kernel) {
> + printf("Kernel entry is missing!\n");
> + return -1;
> + }
> +
> + strncpy((char *)&fn_ip->filename, kia->kernel, sizeof(fn_ip->filename));
> + rc = tftp_load(fn_ip, KERNEL_ADDR, KERNEL_MAX_SIZE);
> + if (rc < 0) {
> + return rc;
> + }
> +
> + if (kia->initrd) {
> + uint64_t iaddr = (rc + 0xfff) & ~0xfffUL;
> +
> + strncpy((char *)&fn_ip->filename, kia->initrd,
> sizeof(fn_ip->filename));
> + rc = tftp_load(fn_ip, (void *)iaddr, KERNEL_MAX_SIZE - iaddr);
> + if (rc < 0) {
> + return rc;
> + }
> + /* Patch location and size: */
> + *(uint64_t *)0x10408 = iaddr;
> + *(uint64_t *)0x10410 = rc;
> + rc += iaddr;
> + }
> +
> + if (kia->append) {
> + strncpy((char *)0x10480, kia->append, ARCH_COMMAND_LINE_SIZE);
> + }
> +
> + return rc;
> +}
> +
> +#define MAX_PXELINUX_ENTRIES 16
> +
> +/**
> + * Parse a pxelinux-style configuration file.
> + * See the following URL for more inforation about the config file syntax:
> + * https://www.syslinux.org/wiki/index.php?title=PXELINUX
> + */
> +static int handle_pxelinux_cfg(filename_ip_t *fn_ip, char *cfg, int cfgsize)
> +{
> + struct lkia entries[MAX_PXELINUX_ENTRIES];
> + int num_entries = 0;
> + char *ptr = cfg, *eol, *arg;
> + char *defaultlabel = NULL;
> + int def_ent = 0;
> +
> + while (ptr < cfg + cfgsize && num_entries < MAX_PXELINUX_ENTRIES) {
> + eol = strchr(ptr, '\n');
> + if (!eol) {
> + eol = cfg + cfgsize;
> + }
> + if (eol > ptr && *(eol - 1) == '\r') {
> + *(eol - 1) = 0;
> + }
> + *eol = '\0';
> + while (*ptr == ' ' || *ptr == '\t') {
> + ptr++;
> + }
> + if (*ptr == 0 || *ptr == '#') { /* Ignore comments and empty lines
> */
> + goto nextline;
> + }
> + arg = strchr(ptr, ' '); /* Look for space between command and arg
> */
> + if (!arg) {
> + arg = strchr(ptr, '\t');
> + }
> + if (!arg) {
> + printf("Failed to parse the following line:\n %s\n", ptr);
> + goto nextline;
> + }
> + *arg++ = 0;
> + while (*arg == ' ' || *arg == '\t') {
> + arg++;
> + }
> + if (!strcasecmp("default", ptr)) {
> + defaultlabel = arg;
> + } else if (!strcasecmp("label", ptr)) {
> + entries[num_entries].label = arg;
> + if (defaultlabel && !strcmp(arg, defaultlabel)) {
> + def_ent = num_entries;
> + }
> + num_entries++;
> + } else if (!strcasecmp("kernel", ptr)) {
> + entries[num_entries - 1].kernel = arg;
> + } else if (!strcasecmp("initrd", ptr)) {
> + entries[num_entries - 1].initrd = arg;
> + } else if (!strcasecmp("append", ptr)) {
> + entries[num_entries - 1].append = arg;
> + } else {
> + printf("Command '%s' is not supported.\n", ptr);
> + }
> +nextline:
> + ptr = eol + 1;
> + }
> +
> + return load_kernel_with_initrd(fn_ip, &entries[def_ent]);
> +}
> +
> +static int net_try_pxelinux_cfgs(filename_ip_t *fn_ip)
> +{
> + int rc, idx;
> +
> + cfgbuf[sizeof(cfgbuf) - 1] = 0; /* Make sure that it is NUL-terminated
> */
> +
> + printf("Trying pxelinux.cfg files...\n");
> +
> + /* Look for config file with MAC address in its name */
> + sprintf((char *)fn_ip->filename,
> + "pxelinux.cfg/%02x-%02x-%02x-%02x-%02x-%02x",
> + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
> + rc = tftp_load(fn_ip, cfgbuf, sizeof(cfgbuf) - 1);
> + if (rc > 0) {
> + return handle_pxelinux_cfg(fn_ip, cfgbuf, sizeof(cfgbuf));
> + }
> +
> + /* Look for config file with IP address in its name */
> + if (ip_version == 4) {
> + for (idx = 0; idx <= 7; idx++) {
> + sprintf((char *)fn_ip->filename,
> + "pxelinux.cfg/%02X%02X%02X%02X",
> + (fn_ip->own_ip >> 24) & 0xff, (fn_ip->own_ip >> 16) &
> 0xff,
> + (fn_ip->own_ip >> 8) & 0xff, fn_ip->own_ip & 0xff);
> + fn_ip->filename[strlen((char *)fn_ip->filename) - idx] = 0;
> + rc = tftp_load(fn_ip, cfgbuf, sizeof(cfgbuf) - 1);
> + if (rc > 0) {
> + return handle_pxelinux_cfg(fn_ip, cfgbuf, sizeof(cfgbuf));
> + }
> + }
> + }
> +
> + /* Try "default" config file */
> + strcpy((char *)fn_ip->filename, "pxelinux.cfg/default");
> + rc = tftp_load(fn_ip, cfgbuf, sizeof(cfgbuf) - 1);
> + if (rc > 0) {
> + return handle_pxelinux_cfg(fn_ip, cfgbuf, sizeof(cfgbuf));
> + }
> +
> + return -1;
> +}
> +
> +static int net_try_direct_tftp_load(filename_ip_t *fn_ip)
> +{
> + int rc;
> + void *baseaddr = (void *)0x2000; /* Load right after the low-core */
> +
> + rc = tftp_load(fn_ip, baseaddr, KERNEL_MAX_SIZE - (long)baseaddr);
> +
> + if (rc > 0 && rc < sizeof(cfgbuf) - 1) {
> + /* Check whether it is a configuration file instead of a kernel */
That's interesting because treating the bootfile as pxe-ish config is
what DPM does. Which means that with this change the processor
architecture type 0x1f (Basic) will turn into a superset of 0x20
(Extended). I guess this should be documented somewhere(TM) to avoid
confusion.
> + memcpy(cfgbuf, baseaddr, rc);
> + cfgbuf[rc] = 0; /* Make sure that it is NUL-terminated */
> + if (!strncasecmp("default", cfgbuf, 7) || !strncmp("# ", cfgbuf, 2))
> {
> + /* Looks like it is a pxelinux.cfg */
> + return handle_pxelinux_cfg(fn_ip, cfgbuf, rc);> + }
> + }
> +
> + /* Move kernel to right location */
> + memmove(KERNEL_ADDR, baseaddr, rc);
Move this into the if block above. If the tftp_load fails with rc < 0
bad things will happen...
> +
> + return rc;
> +}
> +
> void panic(const char *string)
> {
> sclp_print(string);
> @@ -360,7 +548,12 @@ void main(void)
> panic("Network initialization failed. Halting.\n");
> }
>
> - rc = tftp_load(&fn_ip, NULL, (long)_start);
> + if (strlen((char *)fn_ip.filename) > 0) {
> + rc = net_try_direct_tftp_load(&fn_ip);
> + }
> + if (rc <= 0) {
> + rc = net_try_pxelinux_cfgs(&fn_ip);
> + }
>
> net_uninit(&fn_ip);
>
--
Regards,
Viktor Mihajlovski
- [Qemu-devel] [PATCH v1 for-2.13 0/4] pc-bios/s390-ccw: Network boot improvements, Thomas Huth, 2018/04/18
- [Qemu-devel] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files, Thomas Huth, 2018/04/18
- Re: [Qemu-devel] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files,
Viktor VM Mihajlovski <=
- Re: [Qemu-devel] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files, Thomas Huth, 2018/04/19
- Re: [Qemu-devel] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files, Viktor VM Mihajlovski, 2018/04/19
- Re: [Qemu-devel] [qemu-s390x] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files, Thomas Huth, 2018/04/19
- Re: [Qemu-devel] [qemu-s390x] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files, Viktor VM Mihajlovski, 2018/04/20
- Re: [Qemu-devel] [qemu-s390x] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files, Thomas Huth, 2018/04/20
- Re: [Qemu-devel] [qemu-s390x] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files, Viktor VM Mihajlovski, 2018/04/20
- Re: [Qemu-devel] [qemu-s390x] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files, Thomas Huth, 2018/04/20
- Re: [Qemu-devel] [qemu-s390x] [PATCH v1 for-2.13 3/4] pc-bios/s390-ccw/net: Add support for pxelinux-style config files, Viktor VM Mihajlovski, 2018/04/20
[Qemu-devel] [PATCH v1 for-2.13 4/4] pc-bios/s390-ccw/net: Add support for .INS config files, Thomas Huth, 2018/04/18