diff doc/FTDI-EEPROM-tools @ 34:f5fbcf1ff032

doc: initial import from freecalypso-hwlab
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 09 Sep 2023 21:28:02 +0000
parents
children f548ae912622
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/FTDI-EEPROM-tools	Sat Sep 09 21:28:02 2023 +0000
@@ -0,0 +1,243 @@
+Mother Mychaela has developed a set of Linux command line tools for manipulating
+configuration EEPROMs that are attached to FT2232x devices and accessed in-band
+via USB.  This document describes these tools.
+
+Supported FTDI chips and EEPROMs
+================================
+
+The present tools work with 93C46, 93C56 and 93C66 EEPROMs attached behind
+FT2232x dual-channel UART/FIFO/MPSSE/etc chips, both FT2232C/D and FT2232H.
+We can read these EEPROMs for examination or backup, and we can program them
+with new bits, either restoring a previously saved backup or creating a new
+from-scratch configuration.  These EEPROM configurations (which we can save,
+restore or create from scratch) set the USB VID:PID and the textual strings
+naming the manufacturer, the product model and an optional serial number,
+select whether each FT2232x channel will come up in the default UART mode or
+one of the other EEPROM-configurable modes (245 FIFO, CPU-style FIFO or fast
+opto-isolated serial), and allow a few other obscure chip settings to be
+tweaked.
+
+Some work has also been done toward the goal of being able to program the
+internal EEPROM in FT232R chips (a very popular single-channel USB to UART
+converter needing no external components), but this work should be considered
+experimental: the tools appear to work on an UB232R module from Digi-Key
+(presumably containing a genuine FT232RQ chip) and on a no-name FT232RL adapter
+where the chip is uncertain, but because we have no real production use case
+yet, we are not ready to truly vouch for FT232R support.
+
+More generally:
+
+* our fteeprom-read tool should be able to read out the EEPROM content from
+  just about any FTDI chip;
+
+* our fteeprom-prog tool should be able to program a user-supplied set of bits
+  into any FTDI+EEPROM combo where the EEPROM is a separate chip, or into FT232R
+  internal EEPROM - but it most likely won't work for newer FT-X chips;
+
+* if the goal is to generate a new EEPROM config from scratch, as opposed to
+  restoring a saved backup, we currently have generators only for FT2232C/D,
+  for FT2232H and for FT232R, with the last one considered experimental and not
+  proven.
+
+libftdi dependency
+==================
+
+We use libftdi (which is in turn layered on libusb) to issue the special USB
+control pipe commands to FTDI chips which are needed to read and write their
+EEPROMs.  We use old-style libftdi-0.x (-lftdi on the link line) as opposed to
+libftdi1 (-lftdi1) because the new versions took away the ability to write to
+the EEPROM directly with ftdi_write_eeprom_location() calls, forcing users to
+go through libftdi1's own EEPROM smarts, which we don't want to do - our tools
+are all about more direct user empowerment at the lowest level.
+
+Selecting the device to operate on
+==================================
+
+Our fteeprom-read, fteeprom-prog and fteeprom-erase tools take a device selector
+argument, selecting the device to operate on.  This required argument is the
+string to be passed to the ftdi_usb_open_string() function in libftdi, allowing
+the device to be operated on to be selected in one of several ways.  Copying
+from libftdi documentation, the available formats are:
+
+d:<devicenode> - path of bus and device-node (e.g. "003/001") within usb device
+tree (usually at /proc/bus/usb/)
+
+i:<vendor>:<product> - first device with given vendor and product id, ids can
+be decimal, octal (preceded by "0") or hex (preceded by "0x")
+
+i:<vendor>:<product>:<index> - as above with index being the number of the
+device (starting with 0) if there are more than one
+
+s:<vendor>:<product>:<serial> - first device with given vendor id, product id
+and serial string
+
+If you have only one FTDI device connected to your PC or laptop at the time of
+your EEPROM manipulation session (generally a good idea to avoid hitting the
+wrong device by mistake) and if that FTDI device has some sensible starting
+USB VID:PID (either from the previous EEPROM config or the chip's sans-EEPROM
+default) that doesn't clash with anything else, then the i: form will probably
+be the most convenient, e.g.:
+
+i:0x0403:0x6001 for single-channel FT232x devices running with the default ID
+i:0x0403:0x6010 for dual-channel FT2232x devices running with the default ID
+i:0x0403:0xPPPP for custom PIDs assigned out of FTDI's VID range
+i:0xVVVV:0xPPPP for totally custom USB IDs
+
+Or if the current device config is totally hosed (the EEPROM has a passing
+checksum, but sets some completely bogus USB ID), then the d: form will
+probably be required for recovery.
+
+Reading the EEPROM
+==================
+
+The basic EEPROM read command is as follows:
+
+fteeprom-read <device-selector>
+
+See the previous section for the device selector argument.  In this default
+form the tool will read the first 64 EEPROM words, which is appropriate for
+93C46 external EEPROMs or for the internal 1024-bit EEPROM in the FT232R chip.
+However, if you are working with an FT2232x board with an external EEPROM and
+that EEPROM is of a larger variety (93C56 or 93C66), this basic form with give
+you an incomplete (truncated) read, and you will need one of the following
+extended forms to read the complete EEPROM:
+
+fteeprom-read -b <device-selector>	-- read 128 EEPROM words (93C56)
+fteeprom-read -B <device-selector>	-- read 256 EEPROM words (93C66)
+
+(If you use one of the extended forms on a smaller EEPROM, you will get 2 or 4
+ copies of the same bits.)
+
+The output of fteeprom-read is in the same format as the input to fteeprom-prog,
+thus you can redirect the output to a file and get a restorable backup copy of
+your EEPROM.
+
+It also needs to be noted that if the FTDI device has the kernel's ftdi_sio
+driver attached to it (ttyUSB device present) when you run fteeprom-read (same
+for fteeprom-prog and fteeprom-erase), the act of running any of our EEPROM
+tools will cause it to unbind, i.e., the ttyUSB device will disappear.  If the
+device being operated on is a dual-channel FT2232x, then only the ttyUSB device
+corresponding to Channel A will disappear, while the Channel B ttyUSB device
+will stay.
+
+Programming the EEPROM
+======================
+
+In terms of the primitives provided over USB, writing to EEPROMs sitting behind
+FTDI chips is accomplished by writing one 16-bit word at a time: the
+SIO_WRITE_EEPROM_REQUEST command writes a user-supplied word at a user-supplied
+EEPROM address.  However, our fteeprom-prog tool currently supports only writing
+complete EEPROMs (64 or 128 or 256 16-bit words starting at address 0) and we
+do not currently provide any kind of "random access write" utility; the primary
+reason for this design decision is practical usefulness: FTDI's EEPROM structure
+includes a checksum over the first 64 words for 1024-bit EEPROMs or over the
+first 128 words for larger ones, and if this checksum fails to match, the entire
+structure is deemed to be invalid - hence there is no practical use case for
+selectively rewriting individual words.  The only exception may be with 93C66
+EEPROMs: on these giants only the first half would be subject to the checksum,
+and the second half could be used arbitrarily.  However, we have not yet
+encountered any boards out in the wild with such big EEPROMs, and we have no
+plans to use such in any of our own hardware designs either, hence there is no
+business case at the present moment to develop tooling support for them.
+
+There are two primary modes of usage for our fteeprom-prog tool: restoring a
+saved EEPROM backup or writing a new EEPROM config which you generate yourself.
+To restore a saved EEPROM backup, run the tool as follows:
+
+fteeprom-prog <device-selector> <eeprom-image-file>
+
+To program a new EEPROM config of your own, run a pipeline of this form:
+
+<generator-tool> | fteeprom-prog <device-selector>
+
+fteeprom-prog reads the EEPROM image from stdin if no image file is named on
+the command line; the image format is the same in both cases, and the length of
+this EEPROM image tells the tool how many words need to be programmed - there
+are no -b or -B options to fteeprom-prog.
+
+Generator tools
+===============
+
+Unfortunately FTDI never documented the format of their EEPROM configuration
+structure - apparently they consider it a proprietary trade secret just like
+the wire protocol spoken over USB between their chips and their closed-source
+proprietary drivers.  All FOSS community support for these chips is based on
+reverse engineering, and that includes the EEPROM format.
+
+The present suite of tools includes ftee-gen2232c and ftee-gen2232h EEPROM image
+generators, meant for use with FT2232C/D and FT2232H chips, respectively.  These
+tools are based on the knowledge extracted from other (pre-existing) community
+tools, primarily the EEPROM config code built into various libftdi versions -
+we haven't done any FTDI RE of our own, instead the goal of this project has
+been to create a set of tools that are better fit for production use.
+
+Our ftee-gen2232c and ftee-gen2232h tools are invoked as follows:
+
+ftee-gen2232[ch] [-b|-B] <config-file> [serial-num]
+
+The output of these generator tools is meant to be piped directly into
+fteeprom-prog.
+
+The philosophy of which settings are given in the config file vs. which ones
+are given on the command line reflects configuration management and factory
+production line operations.  In the envisioned usage there would be a config
+file for each product, giving the USB VID:PID, textual manufacturer and product
+ID strings and possibly other config settings which need to be changed from the
+defaults, but the optional serial number string is given on the command line
+because it would be different for each individual unit being programmed.
+
+The EEPROM size selection is also made on the command line, so that the same
+config can be programmed into a smaller EEPROM or a bigger one.  By default our
+tools generate an image suitable for a 93C46 EEPROM: the generated image is 64
+words long, with a checksum in word 63, and the EEPROM type byte in FTDI's
+structure is set to 0x46.  Running with -b produces an image for a 93C56 EEPROM:
+the EEPROM type byte is set to 0x56, and the checksum-covered image length is
+extended to 128 words.  Finally, -B sets things up for a 93C66 EEPROM: the
+EEPROM type byte is set to 0x66, but the generated checksum-covered image is
+still 128 words long just like with -b, as that is what FT2232x chips apparently
+expect.  I said "apparently" because I don't have any FT2232x hardware with
+93C66 EEPROMs and I don't plan on acquiring or building any, hence this minimal
+93C66 support is completely untested - use at your own risk.
+
+It also needs to be noted that with our current RE-based understanding of FTDI's
+undocumented EEPROM structure, using a bigger EEPROM does NOT provide more room
+for strings: all that happens with -b and -B options is that a gap of 64 unused
+EEPROM words is inserted between the end of the fixed structure and the
+beginning of strings.  The exact same arrangement has been observed in all 93C56
+EEPROM images found in the wild, presumably produced with FTDI's official tools,
+including FTDI's own USB-COM232-PLUS2 board - thus it is not clear at all if
+FT2232x chips actually support longer strings with bigger EEPROMs, and if not,
+what does one need a bigger EEPROM for...
+
+For the format of config files read by our ftee-gen2232[ch] tools and what
+settings can be tweaked, read the source code.
+
+Erasing the EEPROM (making it blank)
+====================================
+
+If you are playing with a "generic" FT2232x breakout board that is made for
+tinkering, as opposed to a more finished product, such boards are typically
+shipped with their EEPROMs completely blank.  In that case restoring the EEPROM
+to its "pristine" state after playing around would mean erasing it, i.e.,
+bringing it into a blank (all ones) state.  FT2232x chips provide two ways to
+do so: one can explicitly write 0xFFFF into each individual EEPROM word with
+SIO_WRITE_EEPROM_REQUEST, or one can send a SIO_ERASE_EEPROM_REQUEST command to
+the chip, and the chip then erases the entire EEPROM.  But we don't know how
+the latter SIO_ERASE_EEPROM_REQUEST operation is implemented by FT2232x chips:
+does the FT2232x chip go through and erase each word individually, or does it
+issue an "erase full chip" opcode to the serial EEPROM?  If the latter, then
+according to some EEPROM datasheets that operation may not work if the EEPROM
+is powered from a 3.3V rail rather than the full USB 5V - may be an issue in
+FT2232H-based designs.
+
+In any case our tools provide both ways.  To perform the "automatic full chip
+erase" operation, run the following command:
+
+fteeprom-erase <device-selector>
+
+To blank the EEPROM by writing 0xFFFF into each word, run one of the following
+pipelines:
+
+ftee-mkblank | fteeprom-prog <device-selector>		-- blank a 93C46 EEPROM
+ftee-mkblank -b | fteeprom-prog <device-selector>	-- blank a 93C56 EEPROM
+ftee-mkblank -B | fteeprom-prog <device-selector>	-- blank a 93C66 EEPROM