Skip to content
rememberthe8bit edited this page Jan 24, 2013 · 22 revisions

While not an absolutely necessity, a bootloader such as UBoot is nice to have, mostly so that we can load binaries to test over serial or Ethernet instead of having to remove the SD card, write files, and re-insert the card every time we update the code. It may also be possible to add one of these transfers as a target in our Makefile for added convenience.

FreeBSD developer Oleksandr Tymoshenko (blog) has been working on porting UBoot to the Pi. The current binary in use is here. The instructions to install it are as follows:

  • Download Raspian
  • dd if=<raspian-image> of=<sd-card-dev> bs=2M
  • Extract the UBoot .tar.gz into the boot partition
  • Connect serial device/monitor and boot the Pi

To load Raspian:

  • fatload mmc 0:1 0x00200000 kernel.img (loads the Raspian kernel)
  • bootz (boots zImage binaries)

To [possibly] load Xinu:

  • fatload mmc 0:1 0x00000000 xinu.bin
  • go 0

Currently, nothing interesting happens when we try to boot Xinu. This may be an issue with how we're loading the binary into memory or something more subtle. The xinu.bin file was also tried, but it would not boot with any boot mode.

Fellow GitHub-er David Welch has been developing on the Pi "bare metal"-style, his notes are available on his project page.


Brain Dump, beware of possible inaccuracies and sudden changes

The ARM effectively boots from 0x8000, kernel.img is a raw binary that's loaded here.

XINU currently (1/22/2013) wants to run starting at 0x10000. From there, it branches to the address at 0x10020 which is 0x0x10044, the Reset_Handler routine. (this is confirmed via arm-...-objdump -D on xinu.elf) UBoot also booted by jumping to this area (Starting application at 0x00010044 ...) so I think the Pi does, in fact, use this address as the reset vector.

Sadly, we can't just .org 0x8000 then b 0x10020 in start.S because we're already at 0x10000 by the time we get to assembling it. Changing compile/platforms/arm-qemu/ld.script allows us to set the initial address to 0x8000. The behavior of .org is a bit odd in that it doesn't seem to set or advance the current code address, but rather it seems to increment it. Using this, we can insert a small bit of code to keep the start.S code where it normally lives at 0x10000 and still boot at 0x8000:

/* the GPU starts the CPU at 0x8000 */
                b  Reset_Handler
.org 0x8000

Currently the Pi does boot our Xinu code from the SD card, but it is not able to get far enough to send anything over the UART to tell us that it booted. We know it does at least start executing because the following ARM code will light up the "ACT" ("OK" on some cases) LED:

                /* turn on an LED */
                ldr   r0, GPFSEL1         //allocate registers poorly
                ldr   r1, GPSET0
                ldr   r2, GPCLR0
                ldr   r3, MASK0
                ldr   r4, MASK1
                ldr   r5, MASK2
                ldr   r7, LOOPCT

                ldr   r6, [r0, #0]        //GPFSEL1 &= ~(7<<18)                                                         
                and   r6, r6, r3
                str   r6, [r0, #0]

                ldr   r6, [r0, #0]        //GPFSEL1 |= (1<<18)                                                          
                orr   r6, r6, r4
                str   r6, [r0, #0]

loop:   
                ldr   r6, [r2, #0]        //GPCLR0 |= (1<<16)                                                           
                orr   r6, r6, r5
                str   r6, [r2, #0]

                ldr   r6, [r1, #0]        //GPSET0 |= (1<<16)
                orr   r6, r6, r5
                str   r6, [r1, #0]

                subs  r7, r7, #1          //loop until r7 is zero                                                       
                bne loop
                b done

.align  2                                                                                                               
GPFSEL1:   
        .word   0x20200004   
GPSET0:   
        .word   0x2020001C   
GPCLR0:   
        .word   0x20200028   
MASK0:   
        .word   0xFFE3FFFF //~(7<<18)                                                                                   
MASK1:   
        .word   0x00040000 //(1<<18)                                                                                    
MASK2:   
        .word   0x00010000 //(1<<16)                                                                                    
LOOPCT:   
        .word   0x00FFFFFF //big                                                                                        
done:
Clone this wiki locally