redboot based boot loader for kernels?

John Hay jhay at meraka.org.za
Tue Mar 6 09:59:03 UTC 2007


> : > 
> : > The at91 boot2 groks ufs and only needs a function that can read the
> : > sectors from the underlying media to grok new media.  Of course, it
> : > inherited most of that from the i386 boot2.
> : 
> : Ok, I have it somewhat working for my Avila Gateworks board. I have
> : a bug somewhere in the code that do 16 bit reads from the CF, so for
> : now I have switched to 8 bit accesses. :-/ I'll search for that a
> : little later.
> 
> Cool!  I'd love to check out the source...

I'm not going to keep it hidden. You will recognise a lot of it. :-)
It is still full of lots of debugging printfs and #ifs.

In boot2.c load() I had to clip the destination and entry point
addresses:

@@ -221,15 +239,18 @@
            j++;
     }
     for (i = 0; i < 2; i++) {
-       p = (caddr_t)ep[i].p_paddr;
+       p = (caddr_t)(ep[i].p_paddr & 0x0fffffff);
        fs_off = ep[i].p_offset;
        if (xfsread(ino, p, ep[i].p_filesz))
            return;
     }
-    addr = eh.e_entry;
-    ((void(*)(int))addr)(RB_BOOTINFO | (opts & RBX_MASK));
+    addr = eh.e_entry & 0x0fffffff;
+    printf("Entry point %x for %s\n", addr, kname);
+    clr_board();
+    ((void(*)(int))addr)(RB_BOOTINFO /* XXX | (opts & RBX_MASK) */);
 }

In boot2.c dskread() I had to swap some of the 32 bit values in the
mbr:

########################################################
@@ -278,28 +300,35 @@
            return -1;
        dp = (void *)(sec + DOSPARTOFF);
        for (i = 0; i < NDOSPART; i++) {
-           if (dp[i].dp_typ == DOSPTYP_386BSD)
+           if ((dp[i].dp_typ == DOSPTYP_386BSD) && (dp[i].dp_flag == 0x80))
                    break;
        }
        if (i == NDOSPART)
                return -1;
+       printf("Found an active fbsd partition/slice. (%d)\n", i);
        // Although dp_start is aligned within the disk partition structure,
        // DOSPARTOFF is 446, which is only word (2) aligned, not longword (4)
        // aligned.  Cope by using memcpy to fetch the start of this partition.
        memcpy(&dsk_start, &dp[i].dp_start, 4);
+       dsk_start = swap32(dsk_start);
        if (drvread(sec, dsk_start + LABELSECTOR, 1))
                return -1;
        d = (void *)(sec + LABELOFFSET);
-       if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) {
+       if ((d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) &&
+           (swap32(d->d_magic) != DISKMAGIC || swap32(d->d_magic2) != DISKMAGIC
)) {
                printf("Invalid %s\n", "label");
                return -1;
        }
        if (!d->d_partitions[0].p_size) {
                printf("Invalid %s\n", "partition");
                return -1;
        }
-       dsk_start += d->d_partitions[0].p_offset;
-       dsk_start -= d->d_partitions[RAW_PART].p_offset;
+       dsk_start += swap32(d->d_partitions[0].p_offset);
+       dsk_start -= swap32(d->d_partitions[RAW_PART].p_offset);
        dsk_meta++;
     }
########################################################

Why do I have to swap them and you didn't need to? I created the disk
mbr and slices/partitions with fdisk and bsdlabel on an arm box.

> 
> : One thing that I would like to do is to pass the disk/slice info to
> : the kernel. The reason being that I have 2 FreeBSD slices and would
> : like the kernel to mount the one the boot loader tells it to. From
> : looking at how some of the other archs do it, it looks like I will
> : need some arm assembler foo. :-/ Anybody got ideas/code? I even
> : thought of compiling the kernel with "options ROOTDEVNAME" and then
> : the loader can load the kernel in ram and then search for the
> : ufs:ad0s1a string and twiddle it as appropriate, but that would not
> : work well with .gz.tramp kernels. :-)
> 
> The way that's normally done is that the boot loader tells the OS in
> some block of memory...  Trouble is that none of that is standard, and
> besides, the boot loader doesn't really pass anything on ARM right now
> (it should be passing the board type, but that's about it).  That's a
> long way of saying 'we should invent something'.  However, since we're
> in the Linux space here, chances are good there's already a standard
> for passing strings in, and maybe we should piggy back on it...

Well I wasn't really thinking passing something from redboot itself,
more that my boot2 program can tell the kernel which slice/partition
to use as its root partition. At the moment I don't even want to do
that interactively, it should just look for an active FreeBSD slice,
load ther kernel from there (which it does) and then get the kernel
to use the same slice/partition as its root.

Maybe I should just implement a simple bootinfo structure and call
the kernel with its pointer. I'm not sure how easy it will be to
have that survive the tramp stuff though. Maybe I should look into
building unzip into boot2, then I don't need the tramp mechanism.

John
-- 
John Hay -- John.Hay at meraka.csir.co.za / jhay at FreeBSD.org


More information about the freebsd-arm mailing list