Wiki page by fallen on 24/02/2014 12:37:26


What it does so far:

  • Boots the kernel all the way up to mounting rootfs from ramdisk
  • Loads /sbin/init from the ramdisk and starts executing it in user space
  • /sbin/init executes entirely, it contains 3 open() and 1 write() syscalls
    • init opens /dev/console 3 times (stdin, stdout, stderr) and writes "hello, world!" to stdout which shows up in the uart console
  • Then init "returns to 0x0" and crashes the machine

How to build EdgeBSD/lm32:

  • Fetch the source: git clone http://git.edgebsd.org/EdgeBSD/edgebsd-src.git
  • Go to my branch: cd edgebsd-src && git checkout fallen-port-milkymist
  • Fetch the submodule (init_src): git submodule update --init
  • Build the lm32 cross toolchain: ./build.sh -m milkymist -U tools
  • Build EdgeBSD kernel: ./build.sh -m milkymist -U kernel=GENERIC
Note, if you are rebuilding after a modification or a git pull, this is faster: ./build.sh -m milkymist -U -u kernel=GENERIC

Run EdgeBSD/lm32 in qemu:

  • ./lm32-softmmu/qemu-system-lm32 -M milkymist -cpu lm32-full-mmu -nographic -kernel /path/to/edgebsd-src/sys/arch/milkymist/compile/obj/GENERIC/netbsd

Build Qemu for Milkymist SoC with support for lm32-mmu:

  • git clone https://github.com/fallen/qemu.git && cd qemu && ./configure --target-list=lm32-softmmu && make

Debug with Qemu and GDB:

  • Build EdgeBSD kernel with debug information: DEBUG=-g ./build.sh -m milkymist -U kernel=GENERIC
  • ./lm32-softmmu/qemu-system-lm32 -M milkymist -cpu lm32-full-mmu -nographic -s -S -kernel /path/to/edgebsd-src/sys/arch/milkymist/compile/obj/GENERIC/netbsd.gdb
  • gdb -x /path/to/edgebsd-src/sys/arch/milkymist/compile/obj/GENERIC/.gdbinit /path/to/edgebsd-src/sys/arch/milkymist/compile/obj/GENERIC/netbsd.gdb
  • (inside gdb) target remote :1234

Embed a ramdisk (MFS : memory file system) inside the kernel with a simple static init binary:

  • Build EdgeBSD kernel with MFS support: DEBUG=-g ./build.sh -m milkymist -U kernel=GENERIC_MFS
  • Build init binary: make -C init_src
    • Beware, if you are not under Mac OS X you need to tell the makefile where your lm32 crosstoolchain is by prefixing the previous command with: TOOLCHAIN_DIR=$PWD/obj/tooldir.NetBSD-7.0-i386/
  • Install init binary inside the kernel image: debug=1 make -C init_src install
    • you still need the TOOLCHAIN_DIR variable if not under OS X
    • you will need to enter your SUDO password
  • Run the kernel with Qemu and wait for GDB to attach: ./lm32-softmmu/qemu-system-lm32 -M milkymist -cpu lm32-full-mmu -nographic -kernel /path/to/edgebsd-src/sys/arch/milkymist/compile/obj/GENERIC_MFS/netbsd.gdb -s -S
  • Attach GDB: gdb -x /path/to/edgebsd-src/sys/arch/milkymist/compile/obj/GENERIC/.gdbinit /path/to/edgebsd-src/sys/arch/milkymist/compile/obj/GENERIC_MFS/netbsd.gdb
  • Inside GDB:
    • (gdb) target remote :1234
    • 0x10000000 is the virtual address where init binary gets loaded (you can inspect the binary with readelf)
      (gdb) break *0x10000000
    • (gdb) continue
    • 0x47eb4000 is the physical address where init binary gets loaded in RAM
      (gdb) x/10i 0x47eb4000
    • Then you can single step using "si" and see the registers changing values according to the instructions you printed at the previous step
    • (gdb) break syscall
      (gdb) continue
    • So far the init program will do 3 open("/dev/console") and one write(0, "hello, world\n", 12), you can break on sys_open and sys_write to catch them or just single step from the break to syscall
1.6 (diff)fallen
1.5 (diff)
1.4 (diff)
1.3 (diff)khorben
1.2 (diff)khorben