Gerber files in EAGLE

I have worked with files describing electronic schematics and PCB board layout. But so far I have never really worked with Gerber files myself. As I found out it’s not rocket science, it’s not complicated at all.

The Gerber format is used to describe monochrome vector images by an ordered stream of graphics objects. The format uses printable ASCII (7 bit) characters only.

The schematic and PCB design software EAGLE provides a job mechanism with the aid of which the creation of the output data for a board can be automated (CAM). This tool can be used to create Gerber files. The predefined job is called gerb274x.cam.

For a 2-layer PCB the standard process will lead to five Gerber files (where cmp stands for component side and sol for solder side):

  • Copper, component side (.cmp)
  • Copper, solder side (.sol)
  • Silk screen, component side (.plc)
  • Solder stop mask, component side (.stc)
  • Solder stop mask, solder side (.sts)

You might want to add (if your manufacturer allows you to have it:

  • Silk screen, solder side (.pls)

Additional steps: you may want to add a drill file, specified by the Excellon file format. That’s another job in Eagle called excellon.cam. The Excellon format (variant of the RS-274-C standard) is widely used to drive CNC drilling and routing machines in PCB manufacturing.

This will create the following two files:

 

  • Drill file (.drd)
  • Drill Station Info File (.dri)

The drill file is used by a drill program and includes sizes and locations of holes in the PCB.

To check my results I used the gerbv tool under Linux:

gerbv
Screenshot of gerbv tool

References:

 

Dumping a NAND flash, part 1

NAND flash organization

The memory of a NAND flash is organized in a hierarchy of:

  • blocks,
  • pages,
  • sectors,
  • planes.

The Hynix HY27UF084G2B consists of 4096 blocks. Each block of a NAND Flash consists of 64 pages. Each page consists of 4 sectors of data (512 Byte each) and 4 small sectors (16 Byte) of spare data, i.e. a single page consists of 2112 Byte where 2048 Bytes are data and 64 Bytes are spare. 2112 Byte blocks are also called “large block” opposed to “small blocks” of 528 Bytes (holding 512 Bytes of data and 16 Bytes of spare data).

Memory: 4096 blocks × 64 pages/block × 4 sectors/page × 512 Byte/sector = 512 MiB
Spare memory: 4096 blocks × 64 pages/block × 4 sectors/page × 16 Byte/sector = 16 MiB
Overall memory: 512 MiB + 16 MiB = 528 MiB

Flash memory is read and written in pages and erased in blocks of data. Memory must be erased before it is written to! This is also true for single byte writes.

Content of the spare areas: those out of band (OOB) area store data for error detection (e.g. a checksum), correction coding (ECC, most algorithms are based on Hamming codes) and bad block markers (if ECC cannot handle the amount of errors anymore). But can also contain data for the logical/virtual organization (blocks, pages) of physical blocks and pages. The ECC is usually a vendor/model dependent algorithm.

Creating a flash dump

Know your chip

Sometimes the interface to update firmware (e.g. via JTAG or serial port) is not exposed or not easy to find. It may then be an option to take the NAND flash device from the printed circuit board. The desoldering process is followed by dumping the flash memory, sometimes referred to as “off-chip forensics” (used in security analysis and data recovery).

In a next step the device is taken and put into a NAND flash reader/writer. There are commercial tools, but they can also be built from some basic hardware. A popular choice is to build a serial/parallel to USB adapter*. The FTDI FT2232H (and a breakout board) is a good starting point as you can toggle various GPIO pins in “bit bang” mode via its USB interface (mostly used as dual-port USB/serial converter). There’s also a project about using an Arduino NAND flash reader (no focus on speed).

It’s also good to know the NAND flash memory chip’s parameters and pinout in advance. Those specifications can be read from the datasheet, if you can read the labels written on the IC package. It is possible that your flash complies with the Open NAND Flash Interface specifications.

Taking the Hynix HY27UF084G2B again as an example:

  • 512M x 8bit NAND flash
  • package: 48-TSOP1, dimensions: 12x20x1mm, 0.5mm pitch
  • supply voltage: 3.3V (Vcc range: 2.7V..3.6V)
  • memory organization already mentioned above;
    page organization: separate data and spare areas, i.e. main field with 4x 512 Byte of data comes first, followed by 4x 16 Bytes spare
  • timings can be read from the datasheet
  • interface pins
    • x8 bus width I/O interface, i.e. IO0..IO7
    • nCE: chip enable
    • nWE: write enable
    • nRE: read enable
    • RnB: ready/busy indication
    • CLE: command latch enable
    • ALE: address latch enable
    • nWP: write protect
      (8 + 7 = 15 pins needed)
  • capacitance between Vcc and Vss as a buffer: 0.1 uF
  • address cycle map: which address bit is latched when on the I/O interface?
    • the HY27UF084G2B has 5 cycles, i.e. 5 x 8 bit = 40 potential bits
    • 512M addresses needed: log2(512M)=29, i.e. only 30 bits required (A29..A0) and 10 bits to be kept at a low logic level
  • definition of the device’s command set; some commands are single byte operations, others are composed of multiple bytes e.g.
    • READ1 (0x00 in 1st cycle, 0x30 in 2nd cycle)
    • READ ID (0x90 in 1st cycle)
    • RESET (0xFF)

The READ ID command is a good one to test if the connection with the flash can be established successfully and without causing a potentially high damage to the flash device. However, you should know what you do.

The ID to be read for my chip is: 0xAD 0xDC 0x10 0x95 0x54. Those bytes can be interpreted in the following way:

  1. Manufacturer Code: 0xAD (=Hynix)
  2. Device Identifier: 0xDC
  3. Device Identifier Description: 0x10 = 0b00010000
    • Write Cache: not supported
    • Interleave program between multiple chips: not supported
    • Number of simultaneously programmed pages: 2
    • Cell type: 2 level cell
    • Die/package: 1
  4. Device Identifier Description:0x95 = 0b10010101
    • Serial access time: 25 ns
    • Organization: X8
    • Block size (w/o spare area): 128K (see above: 64 pages × 2KB/page)
    • Spare area size (Bytes per 512 Byte): 16
    • Page size (w/o spare area): 2KB
  5. Device Identifier Description (Multiplane information): 0x54 = 0b01010100
    • Plane size: 2 Gbit = 256 MByte
    • Plane number: 2

(*Side note: our flash IC is a parallel flash, but a similar approach could be taken for an SPI flash as well, using an SPI to USB bridge.)

Building the hardware for a DIY NAND flash reader

Required hardware:

  • TSOP-48 socket
  • 0.1uF capacitor
  • wires & jumper wires
  • breakout board with the FTDI FT2232H (to read/write data from/to the NAND flash; communication with a host PC)
  • USB cable

The pins of the TSOP-48 socket (being directly connected with NAND flash memory device) are wired with the pins of the FTDI FT2232H.

(Side note: the TSOP socket may also be used to get the NAND flash memory working in it’s embedded system environment and eavesdropping on how it is accessed with a logic analyzer – flash memory at which addresses and when, e.g. at boot.)

Using software with the DIY NAND flash reader

I will run my DIY NAND flash reader under a Linux operating system. Therefore tools which already work under Windows are not applicable here. But at least the source code of spritesmods.com ftdinandreader (Download) and Bjoern Kerler’s advancement NAND Reader FTDI can help here. I may start from scratch but also may re-use some source code.

First I got the source code and build files for libftdi. The build process and the dependencies for libftdi in turn (e.g. libusb-*-dev) are documented well in README and README.build. Afterwards I could run one of the examples coming with libftdi as I had a small breakout board with an FTDI 232RQ laying around.

$ lsusb
Bus 002 Device 004: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
(...)

Let’s use the example:

/libftdi1-1.3/build/examples $ ./find_all_pp -v 0x0403 -p 0x6001
Found devices ( VID: 0x403, PID: 0x6001 )
------------------------------------------------
FTDI (0x228c950): , ,  (Open FAILED)

Using higher access rights results in:

/libftdi1-1.3/build/examples $ ./find_all_pp -v 0x0403 -p 0x6001
Found devices ( VID: 0x403, PID: 0x6001 )
------------------------------------------------
FTDI (0xd64cb0): FTDI, FT232R USB UART, <#serial> (Open OK)

There’s another example, shipped with libftdi, to access the FTDI’s internal EEPROM memory:

/libftdi1-1.3/build/examples $ ./eeprom 
Chip type 3 ftdi_eeprom_size: 128
0x000: 00 40 03 04 01 60 00 00  a0 2d 08 00 00 00 98 0a .@...`.. .-......
0x010: a2 20 c2 12 23 10 05 00  0a 03 46 00 54 00 44 00 . ..#... ..F.T.D.
0x020: 49 00 20 03 46 00 54 00  32 00 33 00 32 00 52 00 I. .F.T. 2.3.2.R.
0x030: 20 00 55 00 53 00 42 00  20 00 55 00 41 00 52 00  .U.S.B.  .U.A.R.
0x040: 54 00 12 03 XX 00 XX 00  XX 00 XX 00 XX 00 XX 00 T...X.X. X.X.X.X.
0x050: XX 00 XX 00 c4 7a 34 70  00 00 00 00 00 00 00 00 X.X..z4p ........
0x060: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 ........ ........
0x070: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 38 fd ........ ......8.
0x080: 28 04 d7 fb 00 00 c4 7a  34 70 42 00 00 00 00 00 (......z 4pB.....
0x090: 00 00 00 00 00 00 00 00  37 41 59 53 54 4c 46 43 ........ 7AYSTLFC
VID:     0x0403
PID:     0x6001
Release: 0x0000
Bus Powered:  90 mA USB Remote Wake Up
Manufacturer: FTDI
Product:      FT232R USB UART
Serial:       <#serial>
Checksum      : <#checksum>
Internal EEPROM
Oscillator: Internal
Enable Remote Wake Up
PNP: 1
Channel A has Mode UART VCP
C0 Function: TXLED
C1 Function: RXLED
C2 Function: TXDEN
C3 Function: PWREN
C4 Function: SLEEP

In a next step I used some of the example code and used it in my own first C file. I compiled it using a simple Makefile and the gcc build tools.

Next steps:

  • getting the required hardware
  • assemble the parts
  • unsolder the flash IC
  • use/develop software to dump the NAND flash memory
  • analyze the dump

Good resources

 

How to produce EXEs that only contain printable ASCII

Dr. Tom Murphy (@tom7) wrote a paper about “compilers, bits and assembly” – it is about producing DOS-executable EXE file which contain the limited set of only the printable ASCII bytes. In principle, he explains which steps to be taken and some necessary tricks/workarounds when writing a C89 compiler to fulfil these requirements. You can also learn something about the x86 instruction set. Find the paper (20 pages with some ASCII art in it) here. And he also made an explanation video:

SDS011 sensor data for air quality measurement

I got a Nova Fitness SDS011 sensor for measuring air quality. It has a serial interface and outputs data with 9600 baud. The serial interface pins Rx and Tx are specified as TTL with 3.3V levels.

It can be plugged into a USB port via the serial/USB converter (based on an CH340 IC) it is shipped with. dmesg outputs the following system log:

usb 2-1.2: ch341-uart converter now attached to ttyUSB0

Check lsusb‘s output:

Bus 002 Device 005: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter

It uses a baud rate of 9600 (ssty). The serial data stream can be formatted with od as stream of hexadecimal numbers and printed to stdout:

# od -x < /dev/ttyUSB0 
0000000 c0aa 001a 001c 4bea ab6b c0aa 001a 001d
0000020 4bea ab6c c0aa 001a 001d 4bea ab6c c0aa
0000040 001a 001d 4bea ab6c c0aa 001a 001d 4bea
0000060 ab6c c0aa 001a 001d 4bea ab6c c0aa 001a
0000100 001e 4bea ab6d c0aa 001a 001e 4bea ab6d
...

The UART protocol (described in the datasheet) uses a packet of 10 Bytes sent each second. It contains two 16-bit values for both PM2.5 and PM10.

The blog article “Feinstaubmessung mit dem Raspberry Pi” [German] gives a good introduction of how to work on the raw data. It also provides an explanation of how to calculate the particulate matter measurement data in µg/m³ from the raw values. You can also find a Bash script on that site which can help as a “getting started” guide.

After some modifications you get two values per second (indoor test):

$ ./sds011_loop.sh 
preamble ok
[2017-03-20 19:40:50] particulate matter PM25: 14.8 µg/m³
[2017-03-20 19:40:50] particulate matter PM10: 36.1 µg/m³
preamble ok
[2017-03-20 19:40:51] particulate matter PM25: 14.9 µg/m³
[2017-03-20 19:40:51] particulate matter PM10: 36.4 µg/m³
preamble ok
[2017-03-20 19:40:52] particulate matter PM25: 14.9 µg/m³
[2017-03-20 19:40:52] particulate matter PM10: 36.4 µg/m³

The Bash script currently does not calculate and check the checksum which is also transmitted within the UART data stream.

Bern Laquai used an Arduino and described his step in the document “Arduino-basierte Auswertung von Messdaten und Data- Logging für den Feinstaubsensor SDS011 von Nova Fitness” [German pdf file].

The sensor itself has a limited service lifetime of “up to 8000 hours” – which would translate to 333.3 days or not even a whole calendar year. To prolong the service lifetime it’s recommended to power down the sensor and use it in a discontinuous way.

Possible next steps: use a simple wireless NodeMCU, add temperature and humidity sensor(s) and contribute to projects like “luftdaten.info – Feinstaub selber messen“.

Tiptoi firmware update

The firmware update files can directly be downloaded from Ravensburger’s website. The file names for the German version are Update3202.upd (~10.8 MiB) and update.upd (~6.1 MiB).

String analysis

The strings command can be run on those files to check for any insights into how the embedded system works or how updates are carried out. It would also be interesting to find out what is actually written to the NAND flash memory and possibly also other non-volatile memories.

Interesting entries:

  • List of NAND flash names (including the Hynix HY27UF084G2B with several others from Samsung, Hynix, Toshiba, Micron, ST and Intel)
  • Hints about the NTFL (NAND Flash Translation Layer)
  • Library/function names: FSLib (FS probably stands for filesystem), NandMtd, MtdLib (Mtd probably stands for “Memory Technology Device”), FatLib, MediaLib, Utl_*
  • Version strings
  • “Serial trace is active!”
  • File system names: FAT32, FAT16, FAT12
  • List of German words: Apfel, Auto, Baum, …, Wort, Wurm, Zelt – What could they be used for?
  • Strings containing references to media files (“ID3x”, “RIFF”, “WAVEfm”)
  • Strings containing the word “battery”
  • Strings referring to possible SCSI data transfers
  • Firmware version strings at the end, e.g. “ANYKA_IDRAV_N0038” and “RAV_V0136”
  • C file names (e.g. “medium.c”)
  • “End of userware”, “This is userware”
  • Warning and error messages, probably also debug strings

Both firmware update files seem to contain RIFF wave files. As a first indicator the number of matches is counted:

$ strings update.upd | grep RIFF | wc -l
49
$ strings Update3202.upd | grep RIFF | wc -l
58

Using burntool

There is a burntool for the AK98 / AK37 / AK39 / AK10L / 10xx / 11xx MCUs.

Firmware update files

Using the burntool the firmware update files are split up and stored separately in the subdirectory /Update_Files when being imported:

  • BOOT.bin (~27 kB; “nandboot”)
  • codepage.bin (~880 kB; “download_to_nand2”)
  • producer.bin (~111/88 kB; “producer”)
  • PROG.bin (~3.7 MB/1 MB; “download_to_nand1”)
  • voice/Chomp_Voice.bin (~4.3 MB; “download_to_udisk1”)
  • Language/BatLowUpdate[DUTCH|FRENCH|GERMAN].wav
  • Language/Update[DUTCH|FRENCH|GERMAN].wav

The tool can also be used to re-assemble those files to a single .upd firmware update file (export function).

Configuration

The burntool also comes with a configuration file (config.txt) where several settings can or need to be defined:

  • run address for the producer binary
  • MAC addresses and serial numbers to be written
  • chipset specific settings
    • MCU chip type (AK_*)
    • mode (there seems to be a reference to JTAG on the AK_11XX devices)
  • Download to different sections:
    • udisk: contents from PC directory /voice go here (audio files),
      UDISK destination is “A:VOIMG”
    • MTD: root file system files(?) from PC (root.jffs2, root.sqsh4) to be stored in device’s disks A and B; not sure if applicable for Tiptoi pen
    • Flash: PROG.bin and codepage.bin fo to the Flash memory
  • formatting with partition table
  • number of supported flash devices and
  • lists of those supported NAND flash, SPI NAND flash and SD card flash devices
  • definition of USB VID and PID
  • command line support

NAND flash configuration

The definition list of the NAND flash devices includes the following details: chip ID and chip organization:

  • page size (usually 512, 2048 or 4096 Bytes)
  • pages per block (usually 32, 64, 128)
  • total block count (e.g. 4096)
  • group block number[?]
  • plane block number[?]
  • spare size (16 or 64; Byte per page!)
  • column address cycle + last column address cycle mask bit
  • row address cycle + last column address cycle mask bit
  • custom NAND flash configuration (reserved for future use?)
  • flag (set of bits)
  • command length for timing considerations
  • data length for timing considerations
  • descriptor string (device name)

Those settings can be both read and written from the burntool GUI. So changes in the GUI can be tracked in the config.txt file and its file format can be understood.

Example configuration entry for a NAND flash device:

burntool NAND flash configuration list
burntool NAND flash configuration list

Corresponding entry in the config.txt (the entry no. is automatically filled in). You can see that some values are defined in decimal, others in hex:

nand supported count = ...
nand 1 = 0x2,    3,   4, 5, 6, 7,   8, 9, 10, 11,  12, 0xd, 0x14, 0x15, 0x16, 17

Instead of using this reverse engineering approach – there is one version of the burntool the data contained in the .upd file can be read on import and is then stored in the config.txt file. For the specific Flash IC mentioned above the line in the configuration file is:

nandXXX = 0x9510dcad, 2048,  64, 4096, 4096, 2048,  64, 2, 15, 3,   7, 0x2, 0x1, 0xf5ad1, 0x40203, Hynix HY27UF084G2B
  • chip ID: 0x9510dcad (seems to be a little endian representation of the ID which can be read from the IC with the READ ID command,
    i.e. 0xAD =Manufacturer Code for Hynix, 0xDC = Device Identifier,
    0x10 0x95 = Device Details, 0x54 = Multiplane info is missing however)
  • page size: 2048 Bytes
  • pages per block: 64
  • total block count: 4096
  • group block number[?]: 4096
  • plane block number[?]: 2048
  • spare size: 64 Byte per page
  • column address cycle + last column address cycle mask bit: 2, 15
  • row address cycle + last column address cycle mask bit: 3, 7
  • custom NAND flash configuration (reserved for future use?): 2
  • flag (set of bits): 0x1
  • command length for timing considerations: 0xf5ad1 = 1’006’289d
  • data length for timing considerations: 0x40203 = 262’659d
  • descriptor string (device name): Hynix HY27UF084G2B

The list of SPI flash configurations is not too important for us as the Tiptoi does not use SPI flash.

Partition table configuration

The data structure for a partition includes:

  • symbol (seen: A/B, probably A..G)
  • user disk (seen: yes/no)
  • “infor” (seen: normal/check/read-only)
  • attribute (seen: primary/slave/MMI/STANDARD/UNSTANDARD)
  • size
  • volume label (string)

Back to the .upd firmware update file

Maybe we can find out something about the format of the firmware update files. As we know that the string of the flash device is stored in the .upd file let’s have a look for its location and the area around it within the file using the strings command with option -t (-td for decimal, -tx for hex):

$ strings update.upd -tx | grep 'Hynix HY27UF084G2B'
   2ef8 Hynix HY27UF084G2B
$ strings Update3202.upd -td | grep 'Hynix HY27UF084G2B'
   3552 Hynix HY27UF084G2B

The firmware update files pretty much start with a list of the supported flash devices.

The entries have a fixed width/spacing of 287 bytes (measured between the start of strings) in update.upd. The entries end with the string (NULL-terminated, up to 255 bytes), the other information (32 byte) can be found before it:

flash_device_descriptor

  • 32-bit Chip ID (0x9510DCAD)
  • 16-bit: page size: value is 0x0800 = 2048 Bytes (little endian)
  • 16-bit: pages per block is 0x0040 = 64
  • 16-bit: total block count is 0x1000 = 4096
  • 16-bit: group block number[?] is 0x1000 = 4096
  • 16-bit: plane block number[?] is 0x0800 =2048
  • 8-bit: spare size is 0x40 = 64 Byte per page
  • 8-bit: column address cycle is 0x02 = 2
  • 8-bit: last column address cycle mask bit: 0x0F = 15
  • 8-bit: row address cycle: 0x03 = 3
  • 8-bit: last column address cycle mask bit:  0x0B = 11 != 7 (?)
  • 8-bit: custom NAND flash configuration (reserved for future use?): 0x02 = 2
  • 32-bit flag (set of bits): 0x09000001 != 0x1 (masked?)
  • 32-bit command length for timing considerations: 0xf5ad1 = 1’006’289d
  • 32-bit data length for timing considerations: 0x40203 = 262’659d (shifted by 4 bit?)
  • 255 byte NULL-terminated descriptor string (device name): Hynix HY27UF084G2B

The format used by Update32.upd is slightly different: the width/spacing of each entry is 64 bytes:

flash_device_descriptor_2

It’s just a more dense representation saving some NULL bytes in the descriptor string. The string may now only take up to 32 bytes instead of 255.

burntool program

About the burntool itself: BurnTool.exe (~1-2 MB): it is a PE32 executable (GUI) Intel 80386, for MS Windows. There’s different versions of the burntool available in the internet. Also found source code around the web for the burntool itself!

Open questions

  • Which sections of the .upd files are transferred to the Tiptoi device?
  • How to build a valid config.txt configuration file?
  • Which sections include actual firmware code and in which instruction set?
  • Which addresses are used and where are the peripherals mapped?
  • What is the difference in the firmware update files for the different languages?

Tiptoi pen as mass storage NAND flash drive

I plugged the Tiptoi pen into a free USB slot of my computer. It can then be used as a USB flash drive and you can put new game files and firmware update files on it.

The pen is used as mass storage device just as any other hard drive, CD, DVD or flash drive.

The pen under investigation is a Feature/Revision A4 (Date: 2010.3.26; PCB Revision: 1391A4). My version of the pen includes a Hynix HY27UF084G2B NAND Flash with a capacity of 512 MiB (512Mbit x 8). The package of the flash IC is a TSOP-48 with a pitch of 0.5 mm.

Listing my USB devices using lsbusb outputs:

Bus 002 Device 017: ID 2546:e301  
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         6 
  bMaxPacketSize0        64
  idVendor           0x2546 
  idProduct          0xe301 
  bcdDevice            1.00
  iManufacturer           1 tiptoi
  iProduct                2 tiptoi
  iSerial                 3 USB 2.0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           32
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower              400mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         8 Mass Storage
      bInterfaceSubClass      6 SCSI
      bInterfaceProtocol     80 Bulk-Only
      iInterface              1 tiptoi
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         6 
  bMaxPacketSize0        64
  bNumConfigurations      1
Device Status:     0x0006
  (Bus Powered)
  Remote Wakeup Enabled
  Test Mode

The USB Interface Class is defined as 8 (“Mass Storage”), the interface’s sub class is defined as 6 (“SCSI”), and the interface protocol is 80d = 0x50 (“Bulk-Only Transport”).

Running the dmesg command on my Linux machine outputs:

usb 2-1.2: new high-speed USB device number 12 using ehci-pci
usb 2-1.2: new high-speed USB device number 12 using ehci-pci
usb 2-1.2: new high-speed USB device number 13 using ehci-pci
usb 2-1.2: New USB device found, idVendor=2546, idProduct=e301
usb 2-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 2-1.2: Product: tiptoi
usb 2-1.2: Manufacturer: tiptoi
usb 2-1.2: SerialNumber: USB 2.0
usb-storage 2-1.2:1.0: USB Mass Storage device detected
scsi9 : usb-storage 2-1.2:1.0
scsi 9:0:0:0: Direct-Access     Tiptoi   ZC3201                PQ: 0 ANSI: 2
sd 9:0:0:0: Attached scsi generic sg2 type 0
sd 9:0:0:0: [sdb] 955904 512-byte logical blocks: (489 MB/466 MiB)
sd 9:0:0:0: [sdb] Write Protect is off
sd 9:0:0:0: [sdb] Mode Sense: 0b 00 00 08
sd 9:0:0:0: [sdb] No Caching mode page found
sd 9:0:0:0: [sdb] Assuming drive cache: write through
 sdb:
sd 9:0:0:0: [sdb] Attached SCSI removable disk
FAT-fs (sdb): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.

As 466 MiB out of 512 MiB are used for the mass storage (from a logical block addressing point of view), there is some space left for the actual firmware of the pen.

The output of /proc/scsi is:

Attached devices:
[...]
Host: scsi9 Channel: 00 Id: 00 Lun: 00
  Vendor: Tiptoi   Model: ZC3201           Rev:     
  Type:   Direct-Access                    ANSI  SCSI revision: 02

Using sg_inq an SCSI INQUIRY command is issued and the response is output and decoded:

$ sudo sg_inq /dev/sdb 
standard INQUIRY:
  PQual=0  Device_type=0  RMB=1  version=0x02  [SCSI-2]
  [AERC=0]  [TrmTsk=0]  NormACA=0  HiSUP=0  Resp_data_format=2
  SCCS=0  ACC=0  TPGS=0  3PC=0  Protect=0  [BQue=0]
  EncServ=0  MultiP=0  [MChngr=0]  [ACKREQQ=0]  Addr16=0
  [RelAdr=0]  WBus16=0  Sync=0  Linked=0  [TranDis=0]  CmdQue=0
    length=36 (0x24)   Peripheral device type: disk
 Vendor identification: Tiptoi
 Product identification: ZC3201
 Product revision level:

And the output of /proc/scsi/usb-storage/9 is:

   Host scsi9: usb-storage
       Vendor: tiptoi
      Product: tiptoi
Serial Number: USB 2.0
     Protocol: Transparent SCSI
    Transport: Bulk
       Quirks:

The following command can be used to extract the first 512 Byte of memory, known as the Master Boot Record (MBR). The data is stored in a binary file.

sudo dd if=/dev/sdb of=mbr.bin bs=512 count=1

The binary data in file can then be analyzed without affecting the real memory. This can be accomplished using hexdump or any other hex editor:

hexdump -C mbr.bin
 00000000 eb 58 90 4d 53 57 49 4e 34 2e 31 00 02 04 20 00 |.X.MSWIN4.1... .|
 00000010 02 00 00 00 00 f8 00 00 3f 00 ff 00 2b 2d e2 04 |........?...+-..|
 00000020 f0 95 0e 00 44 07 00 00 00 00 00 00 02 00 00 00 |....D...........|
 00000030 01 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
 00000040 80 01 29 78 56 34 12 4e 4f 20 4e 41 4d 45 20 20 |..)xV4.NO NAME |
 00000050 20 20 46 41 54 33 32 20 20 20 33 c9 8e d1 bc f4 | FAT32 3.....|
 [...]
 00000170 4e 54 4c 44 52 20 20 20 20 20 20 00 00 00 00 00 |NTLDR .....|
 00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
 *
 000001a0 00 00 00 00 00 00 00 00 00 00 00 00 0d 0a 52 65 |..............Re|
 000001b0 6d 6f 76 65 20 64 69 73 6b 73 20 6f 72 20 6f 74 |move disks or ot|
 000001c0 68 65 72 20 6d 65 00 00 00 00 ff 0d 0a 44 69 73 |her me.......Dis|
 000001d0 6b 20 65 72 72 6f 72 ff 0d 0a 50 72 65 73 73 20 |k error...Press |
 000001e0 61 6e 79 20 6b 65 79 20 74 6f 20 72 65 73 74 61 |any key to resta|
 000001f0 72 74 0d 0a 00 00 00 00 00 ac cb d8 00 00 55 aa |rt............U.|
 00000200

Furthermore the file command can be used as a help to determine the file type and additional info. Unfortunately it is not of too much help here:

$ file mbr.bin
mbr.bin: x86 boot sector

The MBR does not contain a valid partition table (starts at 0x1BE and can be up to 64 Bytes). At least the end matches the magic number 0x55 0xAA. How is the file system found?

The Gnome partition editor gparted seems to get it right:

gparted
/dev/sdb shown as fat32 filesystem in gparted

The output can also be seen without the use of a graphical UI, simply using the partition manipulation program parted:

$ sudo parted /dev/sdb print
Model: Tiptoi ZC3201 (scsi)
Disk /dev/sdb: 489MB
Sector size (logical/physical): 512B/512B
Partition Table: loop

Number  Start  End    Size   File system  Flags
 1      0.00B  489MB  489MB  fat32

The file system is automatically mounted on my system, check the mount command:

$ mount
 [...]
 /dev/sdb on /media/maehw/tiptoi type vfat (rw,nosuid,nodev,uid=1000,gid=1000,shortname=mixed,dmask=0077,utf8=1,showexec,flush,uhelper=udisks2)

As a consequence of the details listed above the tiptoi pen’s firmware must include:

  • code to interface between the controller and the NAND flash device (low-level media controller)
  • code to support access to the VFAT filesystem (e.g. the game files)
  • code to interface between the controller and a computer via USB to allow access to the NAND flash in a standard way (USB mass storage protocol, logical block addressing, SCSI command interface)