April 28, 2017

FreeBSD USB Mass Storage Target Project Update

FreeBSD runs on many embedded boards that provide a USB target or USB On-the-Go (OTG) interface. This allows the embedded target to act as a USB device, and present one or more interfaces (USB device classes) to a USB host. That host could be running FreeBSD, Linux, Mac OS, Windows, Android, or another operating system. USB device classes include audio input or output (e.g. headphones), mass storage (USB flash drives), human interface device (keyboards, mice), communications (Ethernet adapters), and many others.

The Foundation awarded a project grant to Edward Tomasz Napierała to develop a USB mass storage target driver, using the FreeBSD CAM Target Layer (CTL) as a backend. This project allows FreeBSD running on an embedded platform, such as a BeagleBone Black or Raspberry Pi Zero, to emulate a USB mass storage target, commonly known as a USB flash stick. The backing storage for the emulated mass storage target is on the embedded board’s own storage media. It can be configured at runtime using the standard CTL configuration mechanism – the ctladm(8) utility, or the ctl.conf(5) file.

The FreeBSD target can now present a mass storage interface, a serial interface (for a console on the embedded system), and an Ethernet interface for network access. A typical usage scenario for the mass storage interface is to provide users with documentation and drivers that can be accessed from their host system. This makes it easier for new users to interact with the embedded FreeBSD board, especially in cases where the host operating system may require drivers to access all of the functionality, as with Windows and OS X.

As an example, the following steps will configure a BeagleBone Black to act as a flash memory stick attached to a host computer. Commands entered by the user appear in blue text.

1. Obtain a FreeBSD snapshot image for the BeagleBone Black, write it to an SD card and boot it.

Instructions for FreeBSD on the BeagleBone Black can be found on the wiki at https://wiki.freebsd.org/FreeBSD/arm/BeagleBoneBlack. For this example we’re using the snapshot image obtained from ftp://ftp.freebsd.org/pub/FreeBSD/snapshots/ISO-IMAGES/12.0/FreeBSD-12.0-CURRENT-arm-armv6-BEAGLEBONE-20170420-r317181.img.xz

2. Load the required kernel modules. Also create a /boot/loader.conf file so they are loaded automatically on boot.

# kldload cfumass iscsi
# echo 'cfumass_load="YES"' >> /boot/loader.conf
# echo 'iscsi_load="YES"' >> /boot/loader.conf

3. Create an MSDOS filesystem image to be exported by cfumass. The warning emitted by newfs_msdos can be ignored. Populate it with an example text file.

# truncate -s 16M /tmp/flash-image
# mdconfig -a -f /tmp/flash-image
# newfs_msdos /dev/da0

newfs_msdos: cannot get number of sectors per track: Operation not supported
newfs_msdos: cannot get number of heads: Operation not supported
/dev/md0: 32696 sectors in 4087 FAT16 clusters (4096 bytes/cluster)
BytesPerSec=512 SecPerClust=8 ResSectors=1 FATs=2 RootDirEnts=512 Sectors=32768 Media=0xf0 FATsecs=16 SecPerTrack=63 Heads=1 HiddenSecs=0

# mount -t msdosfs /dev/md0 /mnt
# echo "Hello from the BeagleBone Black!" > /mnt/README.TXT
# umount /mnt
# mdconfig -d -u 0

4. Export the filesystem image via cfumass.

# ctladm create -b block -o file=/tmp/flash-image
LUN created successfully
backend: block
device type: 0
LUN size: 16777216 bytes
blocksize 512 bytes
LUN ID: 0
Serial Number: MYSERIAL 0
Device ID; MYDEVID 0

5. Connect the BeagleBone Black’s USB port to a host computer, and open the example file. In this example I’ve plugged it into a MacBook.