This project is submitted for

Description

The Bus Pirate is a neat tool for any hacker. I believe that the same concept can be extended to produce cheaper, more capable and more powerful Bus Pirate-style tools using Linux-based single-board computers. There's an incredible opportunity to leverage the wealth of software tools available for Linux, building a versatile and powerful hacker toolkit for very little money.

Right now I'm targeting the Raspberry Pi Zero as the platform to get the project off the ground, because it's dirt cheap, small, has USB gadget support and is very capable.

Details

Gadget is an attempt to build a Linux-based hacker toolkit on the Raspberry Pi zero. The concept is simple - plug a USB cable into the USB OTG port of the Pi, and connect it to a computer. The Pi exposes a network connection, USB mass storage and virtual serial port, along with an arsenal of useful software and associated documentation.

Project targets

Feature

Description

Priority

Status

Tool-rich Linux environment

Provide a suite of tools for interfacing with digital hardware, and supporting software to ease its use

Must Have

Ongoing.Currently buildroot-based environment with good tool support

Fast boot

In order to be an effective tool, Gadget should boot quickly as soon as it is plugged in.

< 10s boot. Must have

Not started.From prior experience, should be achievable

On-board documentation

To make Gadget easy to use, comprehensive documentation of the software and hardware must be available on-board (i.e. no internet connection required)

Project Logs

I got a private message this week asking about the status of this project, which means I definitely haven't updated it in too long!

After the hard-drive debacle of the last log, I never really got back into this project in-ernest, other than to reconstruct my build environment. So, the actual functional state of things is about where it was then (but I have written a little more documentation, and made some improvements to the webserver).

Use in the wild

In the meantime, I have been using my Gadget a reasonable amount. So far mainly for talking to i2c things (Like #picopixel), programming AVRs, and as a mega-super-overkill USB-serial adapter. So actually, I'm already calling that a win - I don't need to carry a Pi, USB-serial adapter and AVR programmer, I can just chuck Gadget in my bag and know that I'm set

A few weeks back I was at a conference where we had bluetooth-enabled badges which effectively let you exchange contact details with other delegates by tapping the badges together. They had e-ink screens showing a business-card type screen and maps/schedules for the conference.

That e-ink screen was just begging to have something else put on it, so I spent some of my time trying to reverse engineer the thing, helped by Gadget:

As you can see, I didn't really have the right equipment to do very well. I used my razor's blade for wire-stripping, twist-ties as wire, and Arduino and Gadget. The goal was to capture the traffic from those brass pins just above the battery (success, via AVR programmed via Gadget), and to dump the SPI flash (using Gadget - fail, due to not being able to hold 8 dodgy wires onto an SOIC package while typing). Still, it was entertaining, and I was glad I had Gadget with me.

In the end, I failed at my goal (and the CTO of the company that made the badges told me that actually the flash data was encrypted, so perhaps even if I had dumped it, that would only have been the beginning).

But, it taught me two things:

1. I need a 'proper' logic analyser on Gadget

2. Always take a multimeter!

Next Steps

Buildroot 2016.05 was just released, which includes support for Google Go (which I use for some of my utilities). So, the next thing for me to do is switch over to 2016.05, and update the kernel to 4.6

So I suffered a hard-drive failure the other week which has slowed me down a bit while I got that resolved, but the Gadget software is pretty much at a decent proof-of-concept stage. All the various services start automatically at boot (except for the webserver which starts on the first connection).

Here's how it goes:

Plug in Pi Zero

Wait 10 seconds

USB ethernet, serial and mass storage pop up

If needed, set ethernet device to "link local only" - this should be a one-time thing

Open README.html on mass storage to get linked to the documentation

Do what you gotta do

Here's a picture and a rather cramped screenshot showing all of this, and programming an AVR from the Pi:

I need polish this all, and neaten up my buildroot environment to make it more reproducible. The boot time is currently just over 9 seconds. I want to add SAMBA, which might push it over 10 seconds which would be a shame.

I haven't done anything about read-only rootfs yet. That also might have an impact on boot-time while the init script to set that up runs.

Still it's looking pretty good, for the most-part I'm happy with it.

I'm not too happy about the link-local addressing. For one, GNOME's network manager doesn't fall back to link-local (by design) when it can't get a DHCP address. Windows and Mac I believe do. Also I haven't managed to figure out how to bridge a link-local address so the Pi can get internet access. Might have to go back to on-board DHCP

I've been thinking a bit about how best to interact with it. Terminals are great for linux nerds, but perhaps not for the more casual hobbyist. Also, having to type in the hostname etc is a bit cumbersome. Here's two ideas I've been toying with:

I've got the base system running how I like now. It boots, starts the USB gadget serial and ethernet, and registers a link-local IP address. I've got AVAHI running, so I can find the board by hostname. So far so good. Boot time is currently sitting between 10-12 seconds.

Next I wanted to free up the serial port (i.e. no console logging on the serial port). It works OK, as long as you never ever use the serial port!

So:

if the kernel console uses the serial port: OK!

If no-one ever uses the serial port: OK!

If the kernel console doesn't use the serial port, but you later open it with minicom, picocom or whatever: System hang!

We're talking hard hang, LED doesn't flash any more etc.

I thought the kernel was panicking - but without the serial port console it's impossible to tell. I added some print statements in the relevant parts of the kernel and it looks like it's making it through all of the tty/serial code just fine. It actually crashes *after* minicom exits - this doesn't really match up with a panic. It there were a panic it should happen during the exit sequence.

So this week I got my new Pi Zero set up (that's right! I have two! Not even sorry.)I made a little case - whole thing is less than 10mm thick (full details forthcoming Update details here: https://hackaday.io/project/10540-gadget-case) and got to work on USB gadget support:

Actually setting up the gadget was easy. I enabled all the relevant config options in the kernel (CONFIG_USB_DWC_PERIPHERAL, CONFIG_USB_GADGET, CONFIG_USB_F_* and so on) and then you configure it in "configfs".

I'd never used configfs before, but it's a magical place. Creating a directory in configfs triggers some machinations in the kernel, creating a data structure (or structures) depending on where you create the directory. For USB gadget, you create directories in /sys/kernel/config/usb_gadget

I wrote a little script which creates a combination ("composite") gadget with an RNDIS ethernet port and a ACM serial port:

#!/bin/bash
CONFIGFS=/sys/kernel/config/usb_gadget
GADGET=$CONFIGFS/gadget
# Create a gadget
mkdir $GADGET# Set the VID/PID - this is a pid.codes test code. I'll get a proper one laterecho0x1209 > $GADGET/idVendor
echo0x0001 > $GADGET/idProduct
# Set strings - 0x409 is a magic number in the USB spec meaning "English (United States)"
mkdir $GADGET/strings/0x409
echo"00000001" > $GADGET/strings/0x409/serialnumber
echo"usedbytes" > $GADGET/strings/0x409/manufacturer
echo"Gadget" > $GADGET/strings/0x409/product
# Create a config called 'c.1'. Configs can have multiple functions. A device can have multiple configs. Only one config can be enabled at a time
mkdir $GADGET/configs/c.1
mkdir $GADGET/configs/c.1/strings/0x409
echo"Config 1" > $GADGET/configs/c.1/strings/0x409/configuration
echo500 > $GADGET/configs/c.1/MaxPower
# Create ACM and RNDIS functions, and add them to config 'c.1'# The 'acm' and 'rndis' parts of the directory name are important, they set the type of function. Other possibilities are 'lun' for mass storage, 'hid' for human interface....
mkdir $GADGET/functions/acm.usb0
ln -s$GADGET/functions/acm.usb0 $GADGET/configs/c.1
mkdir $GADGET/functions/rndis.0
ln -s$GADGET/functions/rndis.0$GADGET/configs/c.1# Finally, enable the gadget by setting its USB Device Controller. The 20980000.usb is the name of the (only) UDC on the Raspberry Piecho20980000.usb > $GADGET/UDC

This works a treat. The device enumerates on Linux fine (as long as you plug the cable into the right socket on the Zero... that took me longer to notice than I'd like to admit).

I think that easily-available, accurate and easy-to-consume documentation really provides significant value to any tool. I think its critical to provide this on Gadget and providing it on-board is about as easy as it gets.

Most open-source, hacker-oriented tools have online wiki-based documentation, which is great until you don't have a solid internet connection (actually happens to me more than I'd like to admit... yes, even in 2016!).

I like the idea of a wiki, but such an approach often leads to outdated, inconsistent or hard-to-follow docs. I've opted to go for Markdown-based documentation stored in a public Github which I think is a good middle-ground - anyone who wants to contribute is welcome to submit pull requests, but at the end of the day there is a controlled point of entry (...me) to try and make sure it stays in good order.

My aim is to have a basic page on each major feature of Gadget, this will provide an overview of what the feature is, what it can do, as well as the pins to use and basic usage of any commands. This should provide the bare-minimum required to make someone able to use the feature in its most common use-case. Here's a sneak-peek of a section of the i2c page:

The commands should not be thoroughly documented on these introductory pages - a simple "usage" text and example invocation should be enough - this should help jog the memory of any user who has used the tool before, and provide a known-good "Hello World" for any first-time user.

From these pages, more detailed pages on particular tools can be linked if deemed necessary, however I think for a lot of cases the best thing would be to link the the respective project's own documentation (which yes, needs an internet connection).

You can view the documentation repository on Github: https://github.com/usedbytes/gadget-doc. Of course it's a work in progress and pretty empty right now. It's more of a look-and-feel proof of concept than a useful resource at the moment

On-board documentation is a key feature for Gadget. There are several facets to the documentation project:

Easy to write documentation

The lower the barrier to writing it, the more likely it is to get written

Wide availability

Gadget is just a Linux box. Almost all of the documentation will have relevance outside of Gadget boards.

Uniformity

I want the documentation to look and act the same whether it's viewed on-board or online

Readable source code

With these constraints in mind, I decided that Markdown-based documentation was the right choice. It's easy to write, the source is almost as pretty as the rendered version and it's ubiquitous (if everyone knows it, everyone can help me write it, right?)

I want Gadget to be a light-weight as possible, so I decided to write a very simple web-server to render and serve the Markdown documentation.

I chose golang to implement it as it has a very powerful HTTP library built in, and its static linkage makes for easy deployment to the target without needing to do a whole bunch of configuration - single executable, run it with some arguments, lovely jubbly. This means I can just as easily run it on my development machine without needing to keep two web server configurations in sync (one on the target and one on the host).

The result is docserver, its less than 500 lines of Go and will render and serve Markdown pages with a minimum of fuss.

With this in place, I can set about writing the documentation to accompany my proof-of-concept dogfooding phase of the project.

As far as I know, this project mostly consists of default Linux packages with, sometimes, configuration files. It's a Pi, you can SSH into a Pi, you can install flashrom (SPI ROM flashing), avrdude (ATMega flashing), the USB gadget tutorials are very accessible. Basically, what he doesn't have is setup instructions (but no source code concerned, just console commands and editing some config files), since the docs he has and the server used to host them are both available (even the laser cut files are there). It would indeed be cool if the installation instructions were published, but that's something you can fix, too! =)