Pablo Greco e6a3ae
From 2f0454ccd0dd12429e8c204933cafe71a248d4eb Mon Sep 17 00:00:00 2001
Pablo Greco e6a3ae
From: Thomas Huth <thuth@redhat.com>
Pablo Greco e6a3ae
Date: Mon, 14 Oct 2019 10:06:30 +0100
Pablo Greco e6a3ae
Subject: [PATCH 05/21] pc-bios/s390-ccw/net: Use diag308 to reset machine
Pablo Greco e6a3ae
 before jumping to the OS
Pablo Greco e6a3ae
Pablo Greco e6a3ae
RH-Author: Thomas Huth <thuth@redhat.com>
Pablo Greco e6a3ae
Message-id: <20191014100645.22862-3-thuth@redhat.com>
Pablo Greco e6a3ae
Patchwork-id: 91777
Pablo Greco e6a3ae
O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 02/17] pc-bios/s390-ccw/net: Use diag308 to reset machine before jumping to the OS
Pablo Greco e6a3ae
Bugzilla: 1664376
Pablo Greco e6a3ae
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: David Hildenbrand <david@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Jens Freimann <jfreimann@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
The netboot firmware so far simply jumped directly into the OS kernel
Pablo Greco e6a3ae
after the download has been completed. This, however, bears the risk
Pablo Greco e6a3ae
that the virtio-net device still might be active in the background and
Pablo Greco e6a3ae
incoming packets are still placed into the buffers - which could destroy
Pablo Greco e6a3ae
memory of the now-running Linux kernel in case it did not take over the
Pablo Greco e6a3ae
device fast enough. Also the SCLP console is not put into a well-defined
Pablo Greco e6a3ae
state here. We should hand over the system in a clean state when jumping
Pablo Greco e6a3ae
into the kernel, so let's use the same mechanism as it's done in the
Pablo Greco e6a3ae
main s390-ccw firmware and reset the machine with diag308 into a clean
Pablo Greco e6a3ae
state before jumping into the OS kernel code. To be able to share the
Pablo Greco e6a3ae
code with the main s390-ccw firmware, the related functions are now
Pablo Greco e6a3ae
extracted from bootmap.c into a new file called jump2ipl.c.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Since we now also set the boot device schid at address 184 for the network
Pablo Greco e6a3ae
boot device, this patch also slightly changes the way how we detect the
Pablo Greco e6a3ae
entry points for non-ELF binary images: The code now looks for the "S390EP"
Pablo Greco e6a3ae
magic first and then jumps to 0x10000 in case it has been found. This is
Pablo Greco e6a3ae
necessary for booting from network devices, since the normal kernel code
Pablo Greco e6a3ae
(where the PSW at ddress 0 points to) tries to do a block load from the
Pablo Greco e6a3ae
boot device. This of course fails for a virtio-net device and causes the
Pablo Greco e6a3ae
kernel to abort with a panic-PSW silently.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Pablo Greco e6a3ae
Signed-off-by: Thomas Huth <thuth@redhat.com>
Pablo Greco e6a3ae
(cherry picked from commit 9a848adf45d6732e62551decb3c0255173090767)
Pablo Greco e6a3ae
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
Pablo Greco e6a3ae
---
Pablo Greco e6a3ae
 pc-bios/s390-ccw/Makefile    |  4 +-
Pablo Greco e6a3ae
 pc-bios/s390-ccw/bootmap.c   | 63 +-----------------------------
Pablo Greco e6a3ae
 pc-bios/s390-ccw/bootmap.h   |  4 --
Pablo Greco e6a3ae
 pc-bios/s390-ccw/jump2ipl.c  | 91 ++++++++++++++++++++++++++++++++++++++++++++
Pablo Greco e6a3ae
 pc-bios/s390-ccw/netboot.mak |  3 +-
Pablo Greco e6a3ae
 pc-bios/s390-ccw/netmain.c   | 11 +++++-
Pablo Greco e6a3ae
 pc-bios/s390-ccw/s390-ccw.h  |  4 ++
Pablo Greco e6a3ae
 7 files changed, 111 insertions(+), 69 deletions(-)
Pablo Greco e6a3ae
 create mode 100644 pc-bios/s390-ccw/jump2ipl.c
Pablo Greco e6a3ae
Pablo Greco e6a3ae
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
Pablo Greco e6a3ae
index 1712c2d..439e3cc 100644
Pablo Greco e6a3ae
--- a/pc-bios/s390-ccw/Makefile
Pablo Greco e6a3ae
+++ b/pc-bios/s390-ccw/Makefile
Pablo Greco e6a3ae
@@ -9,7 +9,9 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 .PHONY : all clean build-all
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o virtio-blkdev.o libc.o menu.o
Pablo Greco e6a3ae
+OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \
Pablo Greco e6a3ae
+	  virtio.o virtio-scsi.o virtio-blkdev.o libc.o
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
 QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
Pablo Greco e6a3ae
 QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
Pablo Greco e6a3ae
 QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing
Pablo Greco e6a3ae
diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
Pablo Greco e6a3ae
index ffbf671..d13b7cb 100644
Pablo Greco e6a3ae
--- a/pc-bios/s390-ccw/bootmap.c
Pablo Greco e6a3ae
+++ b/pc-bios/s390-ccw/bootmap.c
Pablo Greco e6a3ae
@@ -29,14 +29,6 @@
Pablo Greco e6a3ae
 /* Scratch space */
Pablo Greco e6a3ae
 static uint8_t sec[MAX_SECTOR_SIZE*4] __attribute__((__aligned__(PAGE_SIZE)));
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-typedef struct ResetInfo {
Pablo Greco e6a3ae
-    uint32_t ipl_mask;
Pablo Greco e6a3ae
-    uint32_t ipl_addr;
Pablo Greco e6a3ae
-    uint32_t ipl_continue;
Pablo Greco e6a3ae
-} ResetInfo;
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-static ResetInfo save;
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
 const uint8_t el_torito_magic[] = "EL TORITO SPECIFICATION"
Pablo Greco e6a3ae
                                   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
@@ -57,53 +49,6 @@ static inline bool is_iso_vd_valid(IsoVolDesc *vd)
Pablo Greco e6a3ae
            vd->type <= VOL_DESC_TYPE_PARTITION;
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-static void jump_to_IPL_2(void)
Pablo Greco e6a3ae
-{
Pablo Greco e6a3ae
-    ResetInfo *current = 0;
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-    void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue;
Pablo Greco e6a3ae
-    *current = save;
Pablo Greco e6a3ae
-    ipl(); /* should not return */
Pablo Greco e6a3ae
-}
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-static void jump_to_IPL_code(uint64_t address)
Pablo Greco e6a3ae
-{
Pablo Greco e6a3ae
-    /* store the subsystem information _after_ the bootmap was loaded */
Pablo Greco e6a3ae
-    write_subsystem_identification();
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-    /* prevent unknown IPL types in the guest */
Pablo Greco e6a3ae
-    if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) {
Pablo Greco e6a3ae
-        iplb.pbt = S390_IPL_TYPE_CCW;
Pablo Greco e6a3ae
-        set_iplb(&iplb);
Pablo Greco e6a3ae
-    }
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-    /*
Pablo Greco e6a3ae
-     * The IPL PSW is at address 0. We also must not overwrite the
Pablo Greco e6a3ae
-     * content of non-BIOS memory after we loaded the guest, so we
Pablo Greco e6a3ae
-     * save the original content and restore it in jump_to_IPL_2.
Pablo Greco e6a3ae
-     */
Pablo Greco e6a3ae
-    ResetInfo *current = 0;
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-    save = *current;
Pablo Greco e6a3ae
-    current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2;
Pablo Greco e6a3ae
-    current->ipl_continue = address & 0x7fffffff;
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-    debug_print_int("set IPL addr to", current->ipl_continue);
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-    /* Ensure the guest output starts fresh */
Pablo Greco e6a3ae
-    sclp_print("\n");
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-    /*
Pablo Greco e6a3ae
-     * HACK ALERT.
Pablo Greco e6a3ae
-     * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2
Pablo Greco e6a3ae
-     * can then use r15 as its stack pointer.
Pablo Greco e6a3ae
-     */
Pablo Greco e6a3ae
-    asm volatile("lghi 1,1\n\t"
Pablo Greco e6a3ae
-                 "diag 1,1,0x308\n\t"
Pablo Greco e6a3ae
-                 : : : "1", "memory");
Pablo Greco e6a3ae
-    panic("\n! IPL returns !\n");
Pablo Greco e6a3ae
-}
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
 /***********************************************************************
Pablo Greco e6a3ae
  * IPL an ECKD DASD (CDL or LDL/CMS format)
Pablo Greco e6a3ae
  */
Pablo Greco e6a3ae
@@ -744,13 +689,7 @@ static void load_iso_bc_entry(IsoBcSection *load)
Pablo Greco e6a3ae
                         (void *)((uint64_t)bswap16(s.load_segment)),
Pablo Greco e6a3ae
                         blks_to_load);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-    /* Trying to get PSW at zero address */
Pablo Greco e6a3ae
-    if (*((uint64_t *)0) & IPL_PSW_MASK) {
Pablo Greco e6a3ae
-        jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff);
Pablo Greco e6a3ae
-    }
Pablo Greco e6a3ae
-
Pablo Greco e6a3ae
-    /* Try default linux start address */
Pablo Greco e6a3ae
-    jump_to_IPL_code(KERN_IMAGE_START);
Pablo Greco e6a3ae
+    jump_to_low_kernel();
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 static uint32_t find_iso_bc(void)
Pablo Greco e6a3ae
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
Pablo Greco e6a3ae
index f1ce423..94f53a5 100644
Pablo Greco e6a3ae
--- a/pc-bios/s390-ccw/bootmap.h
Pablo Greco e6a3ae
+++ b/pc-bios/s390-ccw/bootmap.h
Pablo Greco e6a3ae
@@ -355,10 +355,6 @@ static inline uint32_t iso_733_to_u32(uint64_t x)
Pablo Greco e6a3ae
 #define ISO_SECTOR_SIZE 2048
Pablo Greco e6a3ae
 /* El Torito specifies boot image size in 512 byte blocks */
Pablo Greco e6a3ae
 #define ET_SECTOR_SHIFT 2
Pablo Greco e6a3ae
-#define KERN_IMAGE_START 0x010000UL
Pablo Greco e6a3ae
-#define PSW_MASK_64 0x0000000100000000ULL
Pablo Greco e6a3ae
-#define PSW_MASK_32 0x0000000080000000ULL
Pablo Greco e6a3ae
-#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 #define ISO_PRIMARY_VD_SECTOR 16
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c
Pablo Greco e6a3ae
new file mode 100644
Pablo Greco e6a3ae
index 0000000..266f150
Pablo Greco e6a3ae
--- /dev/null
Pablo Greco e6a3ae
+++ b/pc-bios/s390-ccw/jump2ipl.c
Pablo Greco e6a3ae
@@ -0,0 +1,91 @@
Pablo Greco e6a3ae
+/*
Pablo Greco e6a3ae
+ * QEMU s390-ccw firmware - jump to IPL code
Pablo Greco e6a3ae
+ *
Pablo Greco e6a3ae
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
Pablo Greco e6a3ae
+ * your option) any later version. See the COPYING file in the top-level
Pablo Greco e6a3ae
+ * directory.
Pablo Greco e6a3ae
+ */
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+#include "libc.h"
Pablo Greco e6a3ae
+#include "s390-ccw.h"
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+#define KERN_IMAGE_START 0x010000UL
Pablo Greco e6a3ae
+#define PSW_MASK_64 0x0000000100000000ULL
Pablo Greco e6a3ae
+#define PSW_MASK_32 0x0000000080000000ULL
Pablo Greco e6a3ae
+#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+typedef struct ResetInfo {
Pablo Greco e6a3ae
+    uint32_t ipl_mask;
Pablo Greco e6a3ae
+    uint32_t ipl_addr;
Pablo Greco e6a3ae
+    uint32_t ipl_continue;
Pablo Greco e6a3ae
+} ResetInfo;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+static ResetInfo save;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+static void jump_to_IPL_2(void)
Pablo Greco e6a3ae
+{
Pablo Greco e6a3ae
+    ResetInfo *current = 0;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue;
Pablo Greco e6a3ae
+    *current = save;
Pablo Greco e6a3ae
+    ipl(); /* should not return */
Pablo Greco e6a3ae
+}
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+void jump_to_IPL_code(uint64_t address)
Pablo Greco e6a3ae
+{
Pablo Greco e6a3ae
+    /* store the subsystem information _after_ the bootmap was loaded */
Pablo Greco e6a3ae
+    write_subsystem_identification();
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    /* prevent unknown IPL types in the guest */
Pablo Greco e6a3ae
+    if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) {
Pablo Greco e6a3ae
+        iplb.pbt = S390_IPL_TYPE_CCW;
Pablo Greco e6a3ae
+        set_iplb(&iplb);
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    /*
Pablo Greco e6a3ae
+     * The IPL PSW is at address 0. We also must not overwrite the
Pablo Greco e6a3ae
+     * content of non-BIOS memory after we loaded the guest, so we
Pablo Greco e6a3ae
+     * save the original content and restore it in jump_to_IPL_2.
Pablo Greco e6a3ae
+     */
Pablo Greco e6a3ae
+    ResetInfo *current = 0;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    save = *current;
Pablo Greco e6a3ae
+    current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2;
Pablo Greco e6a3ae
+    current->ipl_continue = address & 0x7fffffff;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    debug_print_int("set IPL addr to", current->ipl_continue);
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    /* Ensure the guest output starts fresh */
Pablo Greco e6a3ae
+    sclp_print("\n");
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    /*
Pablo Greco e6a3ae
+     * HACK ALERT.
Pablo Greco e6a3ae
+     * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2
Pablo Greco e6a3ae
+     * can then use r15 as its stack pointer.
Pablo Greco e6a3ae
+     */
Pablo Greco e6a3ae
+    asm volatile("lghi 1,1\n\t"
Pablo Greco e6a3ae
+                 "diag 1,1,0x308\n\t"
Pablo Greco e6a3ae
+                 : : : "1", "memory");
Pablo Greco e6a3ae
+    panic("\n! IPL returns !\n");
Pablo Greco e6a3ae
+}
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+void jump_to_low_kernel(void)
Pablo Greco e6a3ae
+{
Pablo Greco e6a3ae
+    /*
Pablo Greco e6a3ae
+     * If it looks like a Linux binary, i.e. there is the "S390EP" magic from
Pablo Greco e6a3ae
+     * arch/s390/kernel/head.S here, then let's jump to the well-known Linux
Pablo Greco e6a3ae
+     * kernel start address (when jumping to the PSW-at-zero address instead,
Pablo Greco e6a3ae
+     * the kernel startup code fails when we booted from a network device).
Pablo Greco e6a3ae
+     */
Pablo Greco e6a3ae
+    if (!memcmp((char *)0x10008, "S390EP", 6)) {
Pablo Greco e6a3ae
+        jump_to_IPL_code(KERN_IMAGE_START);
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    /* Trying to get PSW at zero address */
Pablo Greco e6a3ae
+    if (*((uint64_t *)0) & IPL_PSW_MASK) {
Pablo Greco e6a3ae
+        jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff);
Pablo Greco e6a3ae
+    }
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    /* No other option left, so use the Linux kernel start address */
Pablo Greco e6a3ae
+    jump_to_IPL_code(KERN_IMAGE_START);
Pablo Greco e6a3ae
+}
Pablo Greco e6a3ae
diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak
Pablo Greco e6a3ae
index a25d238..4f64128 100644
Pablo Greco e6a3ae
--- a/pc-bios/s390-ccw/netboot.mak
Pablo Greco e6a3ae
+++ b/pc-bios/s390-ccw/netboot.mak
Pablo Greco e6a3ae
@@ -1,7 +1,8 @@
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 SLOF_DIR := $(SRC_PATH)/roms/SLOF
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-NETOBJS := start.o sclp.o virtio.o virtio-net.o netmain.o libnet.a libc.a
Pablo Greco e6a3ae
+NETOBJS := start.o sclp.o virtio.o virtio-net.o jump2ipl.o netmain.o \
Pablo Greco e6a3ae
+	   libnet.a libc.a
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include
Pablo Greco e6a3ae
 LIBNET_INC := -I$(SLOF_DIR)/lib/libnet
Pablo Greco e6a3ae
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
Pablo Greco e6a3ae
index d86d46b..d60e84f 100644
Pablo Greco e6a3ae
--- a/pc-bios/s390-ccw/netmain.c
Pablo Greco e6a3ae
+++ b/pc-bios/s390-ccw/netmain.c
Pablo Greco e6a3ae
@@ -281,6 +281,15 @@ void panic(const char *string)
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
+void write_subsystem_identification(void)
Pablo Greco e6a3ae
+{
Pablo Greco e6a3ae
+    SubChannelId *schid = (SubChannelId *) 184;
Pablo Greco e6a3ae
+    uint32_t *zeroes = (uint32_t *) 188;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    *schid = net_schid;
Pablo Greco e6a3ae
+    *zeroes = 0;
Pablo Greco e6a3ae
+}
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
 static bool find_net_dev(Schib *schib, int dev_no)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
     int i, r;
Pablo Greco e6a3ae
@@ -354,7 +363,7 @@ void main(void)
Pablo Greco e6a3ae
     rc = net_load(NULL, (long)_start);
Pablo Greco e6a3ae
     if (rc > 0) {
Pablo Greco e6a3ae
         sclp_print("Network loading done, starting kernel...\n");
Pablo Greco e6a3ae
-        asm volatile (" lpsw 0(%0) " : : "r"(0) : "memory");
Pablo Greco e6a3ae
+        jump_to_low_kernel();
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     panic("Failed to load OS from network\n");
Pablo Greco e6a3ae
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
Pablo Greco e6a3ae
index a1bdb4c..9828aa2 100644
Pablo Greco e6a3ae
--- a/pc-bios/s390-ccw/s390-ccw.h
Pablo Greco e6a3ae
+++ b/pc-bios/s390-ccw/s390-ccw.h
Pablo Greco e6a3ae
@@ -87,6 +87,10 @@ ulong get_second(void);
Pablo Greco e6a3ae
 /* bootmap.c */
Pablo Greco e6a3ae
 void zipl_load(void);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
+/* jump2ipl.c */
Pablo Greco e6a3ae
+void jump_to_IPL_code(uint64_t address);
Pablo Greco e6a3ae
+void jump_to_low_kernel(void);
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
 /* menu.c */
Pablo Greco e6a3ae
 void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout);
Pablo Greco e6a3ae
 int menu_get_zipl_boot_index(const char *menu_data);
Pablo Greco e6a3ae
-- 
Pablo Greco e6a3ae
1.8.3.1
Pablo Greco e6a3ae