diff mbox

[3/4] pc-bios/s390-ccw: fix for fragmented SCSI bootmap

Message ID 1403093807-32836-4-git-send-email-jfrei@linux.vnet.ibm.com
State New
Headers show

Commit Message

Jens Freimann June 18, 2014, 12:16 p.m. UTC
From: "Eugene (jno) Dvurechenski" <jno@linux.vnet.ibm.com>

We need to interpret the last entry of the bootmap with zero
block count as "continuation pointer".
The "last entry" is being detected by pre-filling of the scratch
space with known values and respective look-ahead.

Signed-off-by: Eugene (jno) Dvurechenski <jno@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Tested-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 pc-bios/s390-ccw/bootmap.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

Comments

Eugene \"jno\" Dvurechenski June 18, 2014, 12:53 p.m. UTC | #1
On 06/18/2014 04:16 PM, Jens Freimann wrote:
> +static inline bool unused_space(const void *p, unsigned int size)
> +{
> +    int i;

s390-ccw.h has a def for size_t (well, it's just "long").
So, we can use a bit more "gentile" version:

+static inline bool unused_space(const void *p, size_t size)
+{
+    size_t i;
Cornelia Huck June 23, 2014, 10:47 a.m. UTC | #2
On Wed, 18 Jun 2014 16:53:15 +0400
"Eugene \"jno\" Dvurechenski" <jno@linux.vnet.ibm.com> wrote:

> 
> 
> On 06/18/2014 04:16 PM, Jens Freimann wrote:
> > +static inline bool unused_space(const void *p, unsigned int size)
> > +{
> > +    int i;
> 
> s390-ccw.h has a def for size_t (well, it's just "long").
> So, we can use a bit more "gentile" version:
> 
> +static inline bool unused_space(const void *p, size_t size)
> +{
> +    size_t i;
> 
> 

Let's stick with the posted version for now. We can do further cleanup
of the bios code later on.
diff mbox

Patch

diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index c07553b..5ee3fcb 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -118,10 +118,26 @@  static int zipl_magic(uint8_t *ptr)
     return 1;
 }
 
+#define FREE_SPACE_FILLER '\xAA'
+
+static inline bool unused_space(const void *p, unsigned int size)
+{
+    int i;
+    const unsigned char *m = p;
+
+    for (i = 0; i < size; i++) {
+        if (m[i] != FREE_SPACE_FILLER) {
+            return false;
+        }
+    }
+    return true;
+}
+
 static int zipl_load_segment(struct component_entry *entry)
 {
     const int max_entries = (SECTOR_SIZE / sizeof(struct scsi_blockptr));
     struct scsi_blockptr *bprs = (void*)sec;
+    const int bprs_size = sizeof(sec);
     uint64_t blockno;
     long address;
     int i;
@@ -133,6 +149,7 @@  static int zipl_load_segment(struct component_entry *entry)
     debug_print_int("addr", address);
 
     do {
+        memset(bprs, FREE_SPACE_FILLER, bprs_size);
         if (virtio_read(blockno, (uint8_t *)bprs)) {
             debug_print_int("failed reading bprs at", blockno);
             goto fail;
@@ -150,6 +167,16 @@  static int zipl_load_segment(struct component_entry *entry)
             if (i == (max_entries - 1))
                 break;
 
+            if (bprs[i].blockct == 0 && unused_space(&bprs[i + 1],
+                sizeof(struct scsi_blockptr))) {
+                /* This is a "continue" pointer.
+                 * This ptr is the last one in the current script section.
+                 * I.e. the next ptr must point to the unused memory area.
+                 * The blockno is not zero, so the upper loop must continue
+                 * reading next section of BPRS.
+                 */
+                break;
+            }
             address = virtio_load_direct(cur_desc[0], cur_desc[1], 0,
                                          (void*)address);
             if (address == -1)