So to summarize where we are at this point or the step of actions that are still required at this point to get the Guruplug booted to a shell prompt.
- In U-boot we need to enter some magical commands
- We needed to answer some of NetBSD's initial questions
- At this point the rootfs is still unconfigured
And at this point we have a system which does something bit is not yet that close to the real stuff as we'd want it to be.
The first step we will do is not NetBSD specific but it just consists out of updating the U-boot environment variables so that the bootloader will automatically attempt loading NetBSD.
The printenv command will show you what the current U-boot environment variables are:
Marvell>> printenv
bootcmd=${x_bootcmd_ethernet}; ${x_bootcmd_usb}; ${x_bootcmd_kernel}; setenv bootargs ${x_bootargs} ${x_bootargs_root}; bootm 0x6400000;
bootdelay=3
baudrate=115200
x_bootcmd_ethernet=ping 192.168.2.1
x_bootcmd_usb=usb start
x_bootcmd_kernel=nand read.e 0x6400000 0x100000 0x400000
x_bootargs=console=ttyS0,115200
ethact=egiga0
ethaddr=F0:AD:4E:FF:11:D5
x_bootargs_root=root=/dev/sda1 rootdelay=10
stdin=serial
stdout=serial
stderr=serial
Environment size: 439/131068 bytes
Which variables are important here ?
- bootcmd: This is the actual command U-boot will executed when it will start booting. And these rely on several sub-commands (the length of a U-boot command is limited, and making small changes over a serial line with limited text editing capabilities is not that great either, this is why it's split up in several subcommands).
- bootdelay: The amount of time U-boot will wait for user input to start executing bootcmd
Hence I will just leave bootdelay at 3, giving me three seconds to do some manual override. But I will replace the entire bootcmd by my own (not using the x_... commands). This can be done as follows:
Marvell>> setenv bootcmd ping 1.2.3.4\; usb start\; fatload usb 0:1 0x100000 uImage \; bootm 0x100000
Marvell>> printenv
bootdelay=3
baudrate=115200
x_bootcmd_ethernet=ping 192.168.2.1
x_bootcmd_usb=usb start
x_bootcmd_kernel=nand read.e 0x6400000 0x100000 0x400000
x_bootargs=console=ttyS0,115200
ethact=egiga0
ethaddr=F0:AD:4E:FF:11:D5
x_bootargs_root=root=/dev/sda1 rootdelay=10
stdin=serial
stdout=serial
stderr=serial
bootcmd=usb start; fatload usb 0:1 0x100000 uImage ; bootm 0x100000
Environment size: 370/131068 bytes
Marvell>> saveenv
Saving Environment to NAND...
Erasing Nand...
Erasing at 0x40000 -- 100% complete.
Writing to Nand... done
With
- setenv : You set variable to value, do keep in mind to escape the ; or U-boot will interpret this as a sequence of commands instead of a value containing a sequence. Put value to an empty string to unset the variable.
- saveenv: Save the entire U-boot environment to a designated sector in Flash (NAND flash in the case of the Guruplug, this is just a name value list protected with a CRC, the CRC is used at boottime to figure out if the environment is a valid one).
- printenv: Shows the current environment variables. Keep in mind that variables are only written to flash after a saveenv, this means that a printenv will show the current state of the variables in memory, not that of the variables stored in flash.
IMPORTANT NOTE: The bootcommand starts with a ping 1.2.3.4, just a ping of a bogus IP address, if this is omitted then NetBSD will not be able detect the PHY and you will have no ethernet connectivity whatsoever.
Without ping U-boot:
mvgbec0 at mvsoc0 unit 0 offset 0x70000-0x73fff: Marvell Gigabit Ethernet Controller
mvgbe at mvgbec0 port 0 not configured
mvgbec1 at mvsoc0 unit 1 offset 0x74000-0x77fff: Marvell Gigabit Ethernet Controller
mvgbe at mvgbec1 port 0 not configured
With ping in U-boot:
mvgbec0 at mvsoc0 unit 0 offset 0x70000-0x73fff: Marvell Gigabit Ethernet Controller
mvgbe0 at mvgbec0 port 0 irq 11
mvgbe0: Ethernet address f0:ad:4e:ff:11:d5
makphy0 at mvgbe0 phy 0: Marvell 88E1149 Gigabit PHY, rev. 3
makphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, 1000baseT, 1000baseT-FDX, auto
mvgbec1 at mvsoc0 unit 1 offset 0x74000-0x77fff: Marvell Gigabit Ethernet Controller
mvgbe at mvgbec1 port 0 not configured
If we powercycle the unit now, then we will see it boot to the point where the NetBSD kernel starts prompting us for input:
Marvell>> reset
resetting ...
U-Boot 2009.11-rc1-00602-g8e6db3d (Dec 24 2009 - 03:11:17)
Marvell-Plug2
SoC: Kirkwood 88F6281_A0
DRAM: 512 MB
NAND: 512 MiB
In: serial
Out: serial
Err: serial
Net: egiga0
88E1121 Initialized on egiga0
Hit any key to stop autoboot: 0
(Re)start USB...
USB: Register 10011 NbrPorts 1
USB EHCI 1.00
scanning bus for devices... 3 USB Device(s) found
scanning bus for storage devices... 1 Storage Device(s) found
reading uImage
......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
4980889 bytes read
## Booting kernel from Legacy Image at 00100000 ...
Image Name: netbsd
Image Type: ARM NetBSD Kernel Image (uncompressed)
Data Size: 4980825 Bytes = 4.8 MB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
## Transferring control to NetBSD stage-2 loader (at address 00000000) ...
NetBSD/evbarm (sheevaplug) booting ...
Loaded initial symtab at 0xc0388ec8, strtab at 0xc03bf1e4, # entries 13786
pmap_postinit: Allocated 35 static L1 descriptor tables
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.
NetBSD 5.99.55 (SHEEVAPLUG) #0: Wed Jul 13 17:57:19 CEST 2011
edb@lapedb:/home/edb/netbsd/src/sys/arch/evbarm/compile/obj/SHEEVAPLUG
...
This actually solves the first goal, and brings us to our second goal. The NetBSD kernel is now asking us the following questions:
boot device: <unknown>
root device: sd0a
dump device (default sd0b): none
file system (default generic): ext2fs
root on sd0a
sd0: fabricating a geometry
warning: no /dev/console
init path (default /sbin/init):
After this it knows where to find init, and what remains is part of our third goal. But the question remains, how are we able to tell NetBSD that it is fairly good idea to attempt to mount an ext2 formatted rootfs which we hid as /dev/sd0a and from that point starts executing /sbin/init ?
In the Linux world, the kernel would learn that information from the bootargs U-boot environment variable (see also the U-boot printenv output shown earlier).
The SHEEVAPLUG kernel configuration
src/sys/arch/evbarm/conf/SHEEVAPLUG contains the following line:
config netbsd root on ? type ?
Let's change this into:
config netbsd root on sd0a type ext2fs
Which should already get us a bit further. Next we recompile it, and put the u-boot image on the USB stick and retry.
edb@lapedb:~/netbsd/src$ ./build.sh -j 2 -u -m evbarm kernel=SHEEVAPLUG
...
/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbmkubootimage -A arm -T kernel -a 0x00008000 -n NetBSD/sheevaplug 5.99.55 -C none netbsd.bin netbsd.ub
magic: 0x27051956
time: Sat Aug 6 17:14:25 2011
size: 4415424
load addr: 0x00008000
entry point: 0x00008000
data crc: 0x128165e8
os: 2 (netbsd)
arch: 2 (arm)
type: 2 (kernel)
comp: 0 (none)
name: NetBSD/sheevaplug 5.99.55
header crc: 0xa6c200d2
/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbmkubootimage -A arm -T kernel -a 0x00008000 -e 0x00800000 -n NetBSD/sheevaplug 5.99.55 -C none netbsd.bin netbsd-old.ub
magic: 0x27051956
time: Sat Aug 6 17:14:25 2011
size: 4415424
load addr: 0x00008000
entry point: 0x00800000
data crc: 0x128165e8
os: 2 (netbsd)
arch: 2 (arm)
type: 2 (kernel)
comp: 0 (none)
name: NetBSD/sheevaplug 5.99.55
header crc: 0xa14b2f1b
===> Kernels built from SHEEVAPLUG:
/home/edb/netbsd/src/sys/arch/evbarm/compile/obj/SHEEVAPLUG/netbsd
===> build.sh ended: Sat Aug 6 17:14:26 CEST 2011
===> Summary of results:
build.sh command: ./build.sh -j 2 -u -m evbarm kernel=SHEEVAPLUG
build.sh started: Sat Aug 6 17:14:05 CEST 2011
NetBSD version: 5.99.55
MACHINE: evbarm
MACHINE_ARCH: arm
Build platform: Linux 2.6.39-2-686-pae i686
HOST_SH: /bin/sh
TOOLDIR path: /home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686
DESTDIR path: /home/edb/netbsd/src/obj/destdir.evbarm
RELEASEDIR path: /home/edb/netbsd/src/obj/releasedir
Updated makewrapper: /home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbmake-evbarm
Building kernel without building new tools
Building kernel: SHEEVAPLUG
Build directory: /home/edb/netbsd/src/sys/arch/evbarm/compile/obj/SHEEVAPLUG
Kernels built from SHEEVAPLUG:
/home/edb/netbsd/src/sys/arch/evbarm/compile/obj/SHEEVAPLUG/netbsd
build.sh ended: Sat Aug 6 17:14:26 CEST 2011
===> .
edb@lapedb:~/netbsd/src$ mount /dev/sdb1 /mnt/
edb@lapedb:~/netbsd/src$ sudo cp /home/edb/netbsd/src/sys/arch/evbarm/compile/obj/SHEEVAPLUG/netbsd
netbsd netbsd-old.ub netbsd.bin netbsd.bin.gz netbsd.gdb netbsd.gz.ub netbsd.map netbsd.ub
edb@lapedb:~/netbsd/src$ sudo cp /home/edb/netbsd/src/sys/arch/evbarm/compile/obj/SHEEVAPLUG/netbsd.ub /mnt/uImage
edb@lapedb:~/netbsd/src$ umount /mnt/
And when we use this image, the startup gets a bit further again:
...
sd0 at scsibus0 target 0 lun 0: <USB, USB 2.0 Flash, 8.07> disk removable
sd0: fabricating a geometry
sd0: 1003 MB, 1003 cyl, 64 head, 32 sec, 512 bytes/sect x 2055680 sectors
boot device: <unknown>
root on sd0a dumps on sd0b
sd0: fabricating a geometry
warning: no /dev/console
init: copying out path `/sbin/init' 11
/etc/rc.conf is not configured. Multiuser boot aborted.
Enter pathname of shell or RETURN for /bin/sh:
This means that our first two goals are already completed, the bootloader and the kernel are already cooperating. At this point we lack some userland configuration, these a probably the files which get generated during a regular installation (rc.conf and passwd, shadow and friends come immediately to mind).
Now how do we prepare the filesystem ? Well I could start guessing and fixing things as we go (I actually started this way), but a more sensible approach is to just steal the flow from somewhere. And this somewhere is actually the installer, the installer (sysinst) is located in
src/distrib/utils/sysinst and there is a file install.c which contains the function do_install() which will setup the partitioning but after that it gets interesting:
if (make_filesystems())
return;
if (make_fstab() != 0)
return;
if (md_post_newfs() != 0)
return;
/* Unpack the distribution. */
if (get_and_unpack_sets(0, MSG_disksetupdone,
MSG_extractcomplete, MSG_abortinst) != 0)
return;
if (md_post_extract() != 0)
return;
set_timezone();
set_root_password();
set_root_shell();
sanity_check();
md_cleanup_install();
msg_display(MSG_instcomplete);
Deducing from this we will need to:
- Create an fstab
- Set the timezone, but when no timezone is set, the box will default to UTC, which sounds sensible enough to me.
- Setup the root user (password and shell)
- And sanity_check() actually calls enable_rc_conf() hence, cleanup rc.conf
So the first setup will consist out of setting up fstab, to make sure the partitions can be found. First we make sure our rootfs is mounted read-writeable
# mount /dev/sd0a /
And we create an
/etc/fstab (inspired by
src/distrib/utils/sysinst/disks.c and the files in
src/share/examples/fstab).
# cat /etc/fstab
/dev/sd0a / ext2fs rw 1 1
/dev/sd0b none swap sw 0 0
/kern /kern kernfs rw 0 0
/proc /proc procfs rw 0 0
ptyfs /dev/pts ptyfs rw 0 0
# mkdir /kern /proc
After this (and after a reboot) the following is sufficient to setup mounts properly (this will be done automagically once rc.conf is configured):
# mount -a
/dev/sd0a: file system not clean; please fsck(8)
# mount
/dev/sd0a on / type ext2fs (local)
tmpfs on /dev type tmpfs (union, local)
kernfs on /kern type kernfs (local)
procfs on /proc type procfs (local)
ptyfs on /dev/pts type ptyfs (local)
Next is setting up a password for root:
# passwd -l root
New password:
Retype new password:
If you would want to change the shell for root (the default in /etc/passwd is csh for root) you can use
chpass -s /path/to/shell root where
/etc/shells contains supported shells.
And last but not least we mark rc.conf and being properly set up, this is what keeping us away from booting properly into a multiuser system. For now it contains:
# cat /etc/rc.conf
# $NetBSD: rc.conf,v 1.96 2000/10/14 17:01:29 wiz Exp $
#
# see rc.conf(5) for more information.
#
# Use program=YES to enable program, NO to disable it. program_flags are
# passed to the program on the command line.
#
# Load the defaults in from /etc/defaults/rc.conf (if it's readable).
# These can be overridden below.
#
if [ -r /etc/defaults/rc.conf ]; then
. /etc/defaults/rc.conf
fi
# If this is not set to YES, the system will drop into single-user mode.
#
rc_configured=NO
# Add local overrides below
#
And we update this the following way:
# sed 's/rc_configured=NO/rc_configured=YES/' /etc/rc.conf > /tmp/rc.conf ; mv /tmp/rc.conf /etc/rc.conf
# echo 'hostname="GURUPLUGGER"'>> /etc/rc.conf
(Note that at the end we also added the hostname, otherwise some additional warnings will appear while rebooting).
And now we reboot. And we see that now init really kicks in ! Starting from the detection of the rootfilesystem the output looks as follows:
root on sd0a dumps on sd0b
sd0: fabricating a geometry
WARNING: clock lost 2536 days
WARNING: using filesystem time
WARNING: CHECK AND RESET THE DATE!
warning: no /dev/console
init: copying out path `/sbin/init' 11
Sun Jul 24 10:01:46 UTC 2011
Starting root file system check:
/dev/rsd0a: file system is clean; not checking
swapctl: adding /dev/sd0b as swap device at priority 0
Starting file system checks:
Setting tty flags.
Setting sysctl variables:
ddb.onpanic: 1 -> 0
Starting network.
Hostname: GURUPLUGGER
IPv6 mode: host
Configuring network interfaces:.
Adding interface aliases:.
Building databases: dev, utmp, utmpx, services done
Starting syslogd.
Mounting all filesystems...
Clearing temporary files.
Creating a.out runtime link editor directory cache.
Checking quotas: done.
Setting securelevel: kern.securelevel: 0 -> 1
Starting virecover.
Checking for core dump...
savecore: no core dump
Starting local daemons:.
Updating motd.
postfix: rebuilding /etc/mail/aliases (missing /etc/mail/aliases.db)
Jul 24 10:02:02 GURUPLUGGER postfix/master[578]: fatal: open lock file /var/db/postfix/master.lock: cannot create file exclusively: Permission denied
Starting inetd.
Starting cron.
Sun Jul 24 10:02:02 UTC 2011
NetBSD/evbarm (GURUPLUGGER) (console)
login: root
Password:
Jul 24 10:02:14 GURUPLUGGER syslogd[182]: last message repeated 5 times
Jul 24 10:02:14 GURUPLUGGER login: ROOT LOGIN (root) on tty console
Jul 24 10:02:14 GURUPLUGGER login: /etc/login.conf: not owned by root
Last login: Sun Jul 24 09:56:11 2011 on console
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.
NetBSD 5.99.55 (SHEEVAPLUG) #6: Sat Aug 6 17:14:12 CEST 2011
Welcome to NetBSD!
This system is running a development snapshot of the NetBSD operating system,
also known as NetBSD-current. It is very possible that it has serious bugs,
regressions, broken features or other problems. Please bear this in mind
and use the system with care.
You are encouraged to test this version as thoroughly as possible. Should you
encounter any problem, please report it back to the development team using the
send-pr(1) utility (requires a working MTA). If yours is not properly set up,
use the web interface at: http://www.NetBSD.org/support/send-pr.html
Thank you for helping us test and improve NetBSD.
Terminal type is vt100.
We recommend that you create a non-root account and use su(1) for root access.
GURUPLUGGER#
In order to set the time we should use the date command (which apparently syncs the RTC as well, there doesn't seem to be a hwclock variant on NetBSD)
GURUPLUGGER# date 201108061940.15
Aug 6 19:40:15 date: date set by root
Sat Aug 6 19:40:15 UTC 2011
GURUPLUGGER# date
Sat Aug 6 19:40:18 UTC 2011
GURUPLUGGER# reboot
This will remove the time warnings shown in the boot log.
But we achieved the from zero to login prompt without the need to do any typing.