Logging my quest into the NetBSD universe.

Sunday, July 24, 2011

Guruplug meets NetBSD part two: Temporary userland

In my previous post I illustrated how to go from zero to booting a kernel on a Guruplug server, my first post ended with what Linux users would call a kernel kernel panic, cannot open root device or which was in the case of NetBSD a more polite enter root device query.


At this point I want to take the entire system one step further. This means that at this point I will extend the Guruplug with a USB stick of 1 gigabyte. But my main point here is that I will not yet make use of any MTD-alike device (more specifically the internal NAND flash) nor will I make use of an NFS rootfs, at the end of this post I want something which can be booted standalone and which can later on be improved.

So continuing where I left the last time, first we start with bringing our CVS tree up to date, and rebuild the kernel (for more details on this last step, see my last blog post):
edb@lapedb:~/netbsd/src$ cvs update 
edb@lapedb:~/netbsd/src$ export HOST_CC=/usr/bin/gcc-4.5
edb@lapedb:~/netbsd/src$ export HOST_CXX=/usr/bin/g++-4.5
edb@lapedb:~/netbsd/src$ ./build.sh -j 2 -u -m evbarm kernel=SHEEVAPLUG
In my specific case the kernel version did not change, so I will simply reuse the kernel uImage which I created last time.

And in the next step the so-called distribution build will be triggered:

edb@lapedb:~/netbsd/src$ time ./build.sh -j 2 -U -u -m evbarm distribution 
===> build.sh command:    ./build.sh -j 2 -U -u -m evbarm distribution
===> build.sh started:    Sat Jul 23 10:20:34 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
--- distribution ---
...
--- check_DESTDIR ---
--- checkflist ---
cd /home/edb/netbsd/src/distrib/sets &&  DESTDIR=/home/edb/netbsd/src/obj/destdir.evbarm  MACHINE=evbarm  MACHINE_ARCH=arm  AWK=/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbawk  CKSUM=/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbcksum  DB=/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbdb  HOST_SH=/bin/sh  MAKE=/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbmake  MKTEMP=/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbmktemp  MTREE=/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbmtree  PAX=/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbpax  COMPRESS_PROGRAM=gzip  PKG_CREATE=/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbpkg_create  SED=/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbsed  TSORT=/home/edb/netbsd/src/obj/tooldir.Linux-2.6.39-2-686-pae-i686/bin/nbtsort\ -q  /bin/sh /home/edb/netbsd/src/distrib/sets/checkflist  -L base  -M /home/edb/netbsd/src/obj/destdir.evbarm/METALOG.sanitised
make distribution started at:  Sat Jul 23 10:20:35 CEST 2011
make distribution finished at: Sat Jul 23 11:18:27 CEST 2011
===> Successful make distribution
===> build.sh ended:      Sat Jul 23 11:18:27 CEST 2011
===> Summary of results:
  build.sh command:    ./build.sh -j 2 -U -u -m evbarm distribution
  build.sh started:    Sat Jul 23 10:20:34 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
  Successful make distribution
  build.sh ended:      Sat Jul 23 11:18:27 CEST 2011
===> .
edb@lapedb:~/netbsd/src$ cd obj/
edb@lapedb:~/netbsd/src/obj$ ls
destdir.evbarm  tooldir.Linux-2.6.39-2-686-pae-i686
edb@lapedb:~/netbsd/src/obj$ du -sh destdir.evbarm 
459M destdir.evbarm

Here I instructed build.sh to:
  • -j 2: Use my two cores when building.
  • -U: Run an unpriviliged build (as a normal user, you don't want build.sh to upgrade your host too eagerly.
  • -u: Do an update, do not rebuild the toolchain and others just-for-fun.
  • -m evbarm: We are still crosscompiling the evaluation board ARM type.
  • distribution: We want to see build.sh create a distribution in $DESTDIR (-D dest Set DESTDIR to dest. [Default: destdir.MACHINE], this last expression means we can expect our rootfs in obj/destdir.evbarm relative to the src directory.

The BUILDING (located next to build.sh) describes the distribution target as follows:
distribution  Do a ``make build'', and then install a full distribution
                   (which does not include a kernel) into DESTDIR, including
                   files in DESTDIR/dev, DESTDIR/etc, DESTDIR/root and
                   DESTDIR/var.
Which is good since we have our kernel image already.


A next step is preparing our storage, remember I'm still running this all from my Debian-testing host. My initial attempt consisted out of creating a NetBSD disklabel on the stick and adding a UFS partitions there. Along that way I encountered some problems (a bug in ufsutils, the fact that I had to recompile the Linux UFS module with write support, ...) which resulted in an intermediary solution, I will in this scenario make use of an ext2 partition for my rootfilesystem (and not an UFS2). The fact that ext2 support is present in the kernel can be learned from the SHEEVAPLUG config file:

edb@lapedb:~/netbsd/src$ cat sys/arch/evbarm/conf/SHEEVAPLUG  | grep file-system
file-system  FFS  # UFS
file-system  EXT2FS  # second extended file system (linux)
#file-system  LFS  # log-structured file system
#file-system  MFS  # memory file system
file-system  NFS  # Network File System client
#file-system  NTFS  # Windows/NT file system (experimental)
#file-system  CD9660  # ISO 9660 + Rock Ridge file system
file-system  MSDOSFS  # MS-DOS file system
file-system  FDESC  # /dev/fd
file-system  KERNFS  # /kern
#file-system  NULLFS  # loopback file system
#file-system  OVERLAY  # overlay file system
#file-system  PORTAL  # portal filesystem (still experimental)
file-system  PROCFS  # /proc
#file-system  UMAPFS  # NULLFS + uid and gid remapping
#file-system  UNION  # union file system
#file-system  CODA  # Coda File System; also needs vcoda (below)
#file-system  SMBFS  # experimental - CIFS; also needs nsmb (below)
file-system  PTYFS  # /dev/ptm support
file-system  TMPFS  # Efficient memory file-system
#file-system  UDF  # experimental - OSTA UDF CD/DVD file-system
#file-system  HFS  # experimental - Apple HFS+ (read-only)

First I start with partitioning my USB stick, I will split the stick in two, first a small VFAT partition to contain the uImage, this for the simple reason that the bootloader on the Guruplug has support for FAT filesystems (and not for ext2) and also for the same reason, this partition will be outside the NetBSD disklabel.

lapedb:~# fdisk /dev/sdb 

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-1021, default 1): 1
Last cylinder, +cylinders or +size{K,M,G} (1-1021, default 1021): +100M

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (104-1021, default 104): 
Using default value 104
Last cylinder, +cylinders or +size{K,M,G} (104-1021, default 1021): 
Using default value 1021

Command (m for help): t
Partition number (1-4): 2
Hex code (type L to list codes): a9
Changed system type of partition 2 to a9 (NetBSD)

Command (m for help): t
Partition number (1-4): 1
Hex code (type L to list codes): b
Changed system type of partition 1 to b (W95 FAT32)

Command (m for help): p

Disk /dev/sdb: 1052 MB, 1052508160 bytes
33 heads, 61 sectors/track, 1021 cylinders
Units = cylinders of 2013 * 512 = 1030656 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xa02121e3

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1         103      103639    b  W95 FAT32
/dev/sdb2             104        1021      923967   a9  NetBSD


Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: If you have created or modified any DOS 6.x
partitions, please see the fdisk manual page for additional
information.
Syncing disks.
lapedb:~# fdisk /dev/sdb 

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): b
Reading disklabel of /dev/sdb2  at sector 207340.
/dev/sdb2  contains no disklabel.
Do you want to create a disklabel? (y/n) y
# /dev/sdb2 :
type: SCSI
disk: 
label: 
flags:
bytes/sector: 512
sectors/track: 61
tracks/cylinder: 33
sectors/cylinder: 2013
cylinders: 1021
rpm: 3600
interleave: 1
trackskew: 0
cylinderskew: 0
headswitch: 0  # milliseconds
track-to-track seek: 0 # milliseconds
drivedata: 0 
4 partitions:
#       start       end      size     fstype   [fsize bsize   cpg]
  c:      104      1021       918     unused        0     0       
  d:        1      1021      1021     unused        0     0       

BSD disklabel command (m for help): n
Partition (a-p): a
First cylinder (104-1021, default 104): 110
Last cylinder or +size or +sizeM or +sizeK (110-1021, default 1021): 1000

BSD disklabel command (m for help): t
Partition (a-d): a
Hex code (type L to list codes): L

 0  unused           5  4.1BSD           9  4.4LFS           d  boot           
 1  swap             6  Eighth Edition   a  unknown          e  ADOS           
 2  Version 6        7  4.2BSD           b  HPFS             f  HFS            
 3  Version 7        8  MS-DOS           c  ISO-9660        10  AdvFS          
 4  System V       
Hex code (type L to list codes): 7

BSD disklabel command (m for help): n
Partition (a-p): b
First cylinder (104-1021, default 104): 1000
Last cylinder or +size or +sizeM or +sizeK (1000-1021, default 1021): 
Using default value 1021

BSD disklabel command (m for help): t
Partition (a-d): b
Hex code (type L to list codes): 1

BSD disklabel command (m for help): w
Writing disklabel to /dev/sdb2 .

Syncing disks.
Calling ioctl() to re-read partition table.

BSD disklabel command (m for help): p

4 partitions:
#       start       end      size     fstype   [fsize bsize   cpg]
  a:      110      1000       891     4.2BSD        0     0     0 
  b:     1000      1021        22       swap                      
  c:      104      1021       918     unused        0     0       
  d:        1      1021      1021     unused        0     0       

BSD disklabel command (m for help): 

lapedb:~# dmesg | tail -n 3
[ 2358.300068] sd 7:0:0:0: [sdb] Assuming drive cache: write through
[ 2358.304145]  sdb: sdb1 sdb2
[ 2358.304146]  sdb2: <netbsd: sdb5 sdb6 >

Important note: Why did I create a swap partition ? (Remember this is a flash medium, the last thing you want to do there is use it as swap ...) To be honest I don't know (yet), when I just created the a partition covering cylinders 15 to 1020 the Linux kernel failed to detect the disklabel and my dmesg output was:
[10031.190078] sd 6:0:0:0: [sdb] Assuming drive cache: write through
[10031.191935]  sdb: sdb1 sdb2
[10031.191938]  sdb2: <netbsd: >

At this point we can access the VFAT partition through /dev/sdb1 and the NetBSD partition through /dev/sdb5. At this point we need to create the filesystems and populate them.

We start with the FAT partition which only needs to have the U-boot kernel image, which I still had from last time, I reuse the one which I used during the TFTP boot in my previous post:


lapedb:~# mkfs.vfat /dev/sdb1 
mkfs.vfat 3.0.9 (31 Jan 2010)
lapedb:~# mount /dev/sdb1 /tmp/target/
lapedb:~# cp /srv/tftp/uImage  /tmp/target
lapedb:~# umount /tmp/target

And the nexst step is creating an ext2 partition on /dev/sdb5, after this I create a tarball of the NetBSD distribution build and extract it on this partition:

lapedb:~# mkfs.ext2  /dev/sdb5
mke2fs 1.42-WIP (02-Jul-2011)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
56112 inodes, 224197 blocks
11209 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=230686720
7 block groups
32768 blocks per group, 32768 fragments per group
8016 inodes per group
Superblock backups stored on blocks: 
 32768, 98304, 163840

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 0 mounts or
0 days, whichever comes first.  Use tune2fs -c or -i to override.
lapedb:~# mount /dev/sdb5 /tmp/target
lapedb:~# cd /tmp/target
lapedb:/tmp/target# tar -xf /tmp/rootfs.tar 
lapedb:/tmp/target# cd ..
lapedb:/tmp/# umount /tmp/target 

At this point my USB stick is ready. And I clan plug it in into the Guruplug. Looking that the serial connection we can then instruct U-boot to obtain the kernel from the USB stick as follows (this could just as well be done using the TFTP image, but I want to end up in a situation where I can boot the Guruplug standalone):

Marvell>> usb start
(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
Marvell>> fatls usb 0:1 /
  4980889   uimage 

1 file(s), 0 dir(s)

Marvell>> fatload usb 0:1 0x100000 uImage
reading uImage
........................................................................
........................................................................
........................................................................
........................................................................
........................................................................
........................................................................
......................................................

4980889 bytes read

At this point my kernel image is loaded in DDR (at offset 0x100000) and I can instruct U-boot to start booting that image. Then I get the kernel messages again, but I can do something useful when NetBSD is asking me for a root filesystem:

Marvell>> bootm 0x100000
## 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
total memory = 512 MB
avail memory = 497 MB
mainbus0 (root)
cpu0 at mainbus0: Sheeva 88SV131 rev 1 (ARM9E-S core)
cpu0: DC enabled IC enabled WB enabled EABT branch prediction enabled
cpu0: 16KB/32B 4-way Instruction cache
cpu0: 16KB/32B 4-way write-back-locking-C Data cache
mvsoc0 at mainbus0: Marvell 88F6281 Rev. A1  Kirkwood
mvsoc0: CPU Clock 1200.000 MHz  SysClock 400.000 MHz  TClock 200.000 MHz
mvsoctmr0 at mvsoc0 unit 0 offset 0x20300-0x203ff: Marvell SoC Timer
mvsocgpp at mvsoc0 unit 0 not configured
mvsocrtc0 at mvsoc0 unit 0 offset 0x10300-0x10317: Marvell SoC Real Time Clock
com0 at mvsoc0 unit 0 offset 0x12000-0x1201f irq 33: ns16550a, working fifo
com0: console
com1 at mvsoc0 unit 1 offset 0x12100-0x1211f irq 34: ns16550a, working fifo
ehci0 at mvsoc0 unit 0 offset 0x50000-0x51fff irq 19: Marvell USB 2.0 Interface
usb0 at ehci0: USB revision 2.0
gttwsi0 at mvsoc0 unit 0 offset 0x11000-0x11fff irq 29: Marvell TWSI controller
iic0 at gttwsi0: I2C bus
mvcesa at mvsoc0 unit 0 not configured
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
mvpex at mvsoc0 unit 0 not configured
mvsata at mvsoc0 unit 0 not configured
mvsdio0 at mvsoc0 unit 0 offset 0x90000-0x9ffff irq 28: Marvell Secure Digital Input/Output Interface
sdmmc0 at mvsdio0
uhub0 at usb0: Marvell EHCI root hub, class 9/0, rev 2.00/1.00, addr 1
sdmmc0: bad CIS ptr 0
sdmmc0: couldn't read CIS
sdmmc0: i/o init failed
sdmmc0: bad CIS ptr 0
sdmmc0: couldn't read CIS
sdmmc0: i/o init failed
"Marvell, 802.11 SDIO ID: 10, " (manufacturer 0x2df, product 0x9103) at sdmmc0 function 1 not configured
"Marvell, 802.11 SDIO ID: 10, " (manufacturer 0x2df, product 0x9103) at sdmmc0 function 2 not configured
uhub1 at uhub0 port 1: Genesys Logic USB2.0 Hub, class 9/0, rev 2.00/77.63, addr 2
uhub1: single transaction translator
umass0 at uhub1 port 3 configuration 1 interface 0
umass0: USB Mass Storage, rev 2.00/1.07, addr 3
scsibus0 at umass0: 2 targets, 1 lun per target
sd0 at scsibus0 target 0 lun 0:  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 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): 
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: 

#

See that ? That's a shell crying for my commands ! Let's try something.

# uname -a
NetBSD  5.99.55 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 evbarm
# mount
root_device on / type ext2fs (read-only, local)
tmpfs on /dev type tmpfs (union, local)
# mount /dev/sd0a /
# mount
/dev/sd0a on / type ext2fs (local)
tmpfs on /dev type tmpfs (union, local)

Apparently the ext2fs was mounted read-only so we corrected this.



Some closing comments:
  • Although I managed to get away with just an ext2 filesystem, I did not manage to boot it without the NetBSD disklabel present on the USB stick
  • At this point by setting the U-boot bootcmd environment variables I could have the Guruplug auto-boot until the point where it queries for the rootfs. This will be fixed in the nexst post.
  • The rootfs is at this point clearly not configured properly, no rc.conf, no user authentication, ... no nothing.
  • A rootfs of half a gigabyte is rather large for an embedded box isn't it ?

These subjects will be tackled in coming posts.

References: