mntmn / interim

The Interim Operating System
1.24k stars 56 forks source link

Cannot boot properly into self-built Raspberry image #14

Open wasamasa opened 7 years ago

wasamasa commented 7 years ago

After executing

./rpi2-build.sh
./rpi2-release.sh
cp release-rpi2/* /media/boot/
umount /media/boot

and inserting the SD card into the Raspberry Pi, it boots into a white screen and is stuck there. No prompt appears. I can't get serial console working either. More instructions on how to debug this would be welcome, like for example how one can try it out in QEMU.

The following however works:

cd docs
tar -xf interim-0.1.0-rpi.tar.gz
cp release-rpi2/* /media/boot/
umount /media/boot

So I'm fairly sure something about the build process is not quite ideal...

wasamasa commented 7 years ago

I've figured out that the rpi2-build.sh script expects newlib in a location like on Debian, after patching it the resulting binaries grew a bit. Still a white screen. Debugging by setting the framebuffer color reveals that doing anything involving USPi avoids reaching the remaining code, so that's weird.

wasamasa commented 7 years ago

I've figured out how to load Interim on a more recent QEMU than in the bundled scripts. Here's my writeup so far:

You'll need a recent QEMU for this with the raspi2 system. The general command line for launching is:

qemu-system-arm -M raspi2 -m 1024 -kernel build/interim-arm.elf -serial stdio

Note that QEMU supports running the raw binary image (located at build/kernel7.img), however it expects an entry point of 0x10000 instead of 0x8000 in devices/rpi2/arm.ld.

The built kernel will hang, to debug why you'll have to boot QEMU with a gdb server:

qemu-system-arm -M raspi2 -m 1024 -kernel build/interim-arm.elf -gdb tcp::26000

Open a suitable gdb from the same toolchain as what you've compiled the kernel with:

arm-none-eabi-gdb
(gdb) target remote localhost:26000
(gdb) symbol-file build/interim-arm.elf
(gdb) continue
(gdb) ^C
(gdb) bt

The backtrace suggests that hardware timers aren't working correctly. The workaround for this is to replace the definition of uart_init with the commented out version that uses busy-waiting for delays. Starting the kernel then proceeds up to a white screen and prints out messages successfully via UART until encountering the USPi exception handler. Fixing this requires understanding the USPi library and how it's used...

wasamasa commented 7 years ago

I eventually got around these issues by upgrading the bundled rpi-boot library and playing with the compilation flags (for some bizarre reason changing the optimization settings allows you to boot further, possibly the fault of undefined behavior and related compiler optimizations removing such code). It appears that structs don't work on ARM at all:

sledge> (struct bar slot 1)
-- clib _write called:
[(struct bar slot 1)]
-- clib _write called:
EXPR: ((struct bar slot 1) . null)
-- clib _write called:
<- compiling 1: (struct bar slot 1)
-- clib _write called:
compiled 1
-- clib _write called:
bar
-- clib _write called:
bar
-- clib _write called:
[insert_symbol] bar entry at 0x11c53a0 (cell: 0x1007d24)
-- clib _write called:
~~ expr 1 res: 0x1007d24
-- clib _write called:
~> bar
nil
-- clib _write called:
sledge> (bar)
-- clib _write called:
[(bar)]
-- clib _write called:
EXPR: ((bar ) . null)
-- clib _write called:
<- compiling 1: (bar )
-- clib _write called:
<error: non-lambda/struct symbol bar in operator position>
-- clib _write called:
compiled 1
-- clib _write called:
[platform_eval] stopped at expression 1: '((bar ) . null)'
nil
sledge>
mntmn commented 5 years ago

Structs on ARM are fixed in the meantime btw!

wasamasa commented 5 years ago

Oh sure, I just haven't tested yet whether booting on the Raspberry Pi works.