On Thu, Jun 14, 2007 at 09:47:06PM -0400, Kevin O'Connor wrote:
> On Thu, Jun 14, 2007 at 09:17:13PM -0400, Kevin O'Connor wrote:
> > >   Another issue I hit during experiments is that initrd buffer wanted
> > > to overwrite itself. I fixed that with memmove-like solution, moving
> > > blocks from the end instead of beginning.
> > 
> > Be careful - if you copy the pages in reverse order, you need to make
> > sure the pages don't overwrite the preloader.
> 
> On further thought, I don't think this will work at all.

Paul,

Could try the following patch on your 27MB initrd?  I think this
overwriting prevention algorithm should work in the general case.

When testing on devices that have fbduringboot support, you may want
to run "set kernelcrc 1" - that should find any cases where the
relocation stuff messes up.

-Kevin
Index: src/memory.cpp
===================================================================
RCS file: /cvs/haret/src/memory.cpp,v
retrieving revision 1.32
diff -u -r1.32 memory.cpp
--- src/memory.cpp      12 Jun 2007 01:14:50 -0000      1.32
+++ src/memory.cpp      16 Jun 2007 01:57:17 -0000
@@ -462,12 +462,6 @@
  * Page allocation
  ****************************************************************/
 
-static int physPageComp(const void *e1, const void *e2) {
-    pageAddrs *i1 = (pageAddrs*)e1, *i2 = (pageAddrs*)e2;
-    return (i1->physLoc < i2->physLoc ? -1
-            : (i1->physLoc > i2->physLoc ? 1 : 0));
-}
-
 // Free pages allocated with allocPages()
 void
 freePages(void *data, int pageCount)
@@ -508,9 +502,6 @@
         pd->physLoc = pfns[i]; // XXX should: x << UserKInfo[KINX_PFN_SHIFT]
     }
 
-    // Sort the pages by physical location.
-    qsort(pages, pageCount, sizeof(pages[0]), physPageComp);
-
     return data;
 }
 
Index: src/linboot.cpp
===================================================================
RCS file: /cvs/haret/src/linboot.cpp,v
retrieving revision 1.53
diff -u -r1.53 linboot.cpp
--- src/linboot.cpp     14 Jun 2007 23:13:01 -0000      1.53
+++ src/linboot.cpp     16 Jun 2007 01:57:17 -0000
@@ -420,6 +420,34 @@
     struct pageAddrs *pg_data = &pages[totalCount-2];
     struct pageAddrs *pg_preload = &pages[totalCount-1];
 
+    // Prevent pages from being overwritten during relocation
+    for (int i=0; i<totalCount; i++) {
+        struct pageAddrs *pg = &pages[i], *ovpg;
+        uint32 relPhys = pg->physLoc - memPhysAddr;
+        // See if this page will be overwritten in preloader.
+        if (relPhys == 0)
+            ovpg = pg_tag;
+        else if (relPhys >= PHYSOFFSET_KERNEL
+                 && relPhys < PHYSOFFSET_KERNEL + kernelSize)
+            ovpg = &pgs_kernel[(relPhys - PHYSOFFSET_KERNEL) / PAGE_SIZE];
+        else if (initrdSize
+                 && (relPhys >= PHYSOFFSET_INITRD
+                     && relPhys < PHYSOFFSET_INITRD + initrdSize))
+            ovpg = &pgs_initrd[(relPhys - PHYSOFFSET_INITRD) / PAGE_SIZE];
+        else
+            // This page wont be overwritten.
+            continue;
+        if (pg == ovpg)
+            // This page will be overwritten by itself - no problem
+            continue;
+        // This page will be overwritten - swap it with the page that
+        // it will be overwritten by and retry.
+        struct pageAddrs tmp = *pg;
+        *pg = *ovpg;
+        *ovpg = tmp;
+        i--;
+    }
+
     Output("Allocated %d pages (tags=%p/%08x kernel=%p/%08x initrd=%p/%08x"
            " index=%p/%08x)"
            , totalCount
@@ -428,25 +456,6 @@
            , pgs_initrd->virtLoc, pgs_initrd->physLoc
            , pgs_index->virtLoc, pgs_index->physLoc);
 
-    if (pg_tag->physLoc < memPhysAddr + PHYSOFFSET_TAGS) {
-        Output(C_ERROR "Allocated memory for tags will overwrite itself");
-        cleanupBootMem(bm);
-        return NULL;
-    }
-
-    if (pgs_kernel->physLoc < memPhysAddr + PHYSOFFSET_KERNEL) {
-        Output(C_ERROR "Allocated memory for kernel will overwrite itself");
-        cleanupBootMem(bm);
-        return NULL;
-    }
-
-    if ((initrdSize
-            && pgs_initrd->physLoc < memPhysAddr + PHYSOFFSET_INITRD)) {
-        Output(C_ERROR "Allocated memory for initrd will overwrite itself");
-        cleanupBootMem(bm);
-        return NULL;
-    }
-
     // Setup linux tags.
     setup_linux_params(pg_tag->virtLoc, memPhysAddr + PHYSOFFSET_INITRD
                        , initrdSize);
_______________________________________________
Haret mailing list
[email protected]
https://handhelds.org/mailman/listinfo/haret

Reply via email to