foboot/doc/HACKING.md
Sean Cross 239aa660ef documentation: update readme and license
Update the LICENSE file to Apache 2.0.

Modify README.md to include information for the end-user.

Signed-off-by: Sean Cross <sean@xobs.io>
2019-04-07 13:47:29 +08:00

4.1 KiB

Hacking on Foboot

Foboot lives inside an FPGA bitstream. This bitstream is fragile and can take a lot of time to build. Because of this, rapid changes to the code can be difficult to make.

There are two ways around this: Either store Foboot on a SPI flash and use XIP, or swap out the program ROM before loading the bitstream.

The bitstream generation program supports both approaches, however for development with an EVT board and fomu-flash, it is recommended to use the program-swap method.

Replacing the boot ROM

When synthesizing a bitstream, a program ROM is loaded with the $readmemh() instruction. Synthesis is inherently random, and so the mapping of bits within the bitstream file is very different from the mapping as seen by the softcore.

There is, however, some pattern to the mapping, and with some heuristics it is possible to create a mapping and swap bits out. It is better to fill the ROM with random data, so that this process can ensure that it's replacing the correct bits -- if the ROM is entirely filled with zeroes, then it's impossible to know if the bit you're replacing is the correct one.

One program to do this is icebram, which is part of Project Icestorm. The fomu-flash utility also has an option to patch the rom as it uploads the bitstream. Currently, fomu-flash relies on a predefined "random" pattern, and requires the ROM to be 8192 bytes. This limitation can be adjusted if a usecase is found. The fomu-flash patching process is very fast.

Building Foboot with a random ROM

To build Foboot with a random rom, add --boot-source rand to the build command:

$ python3 ./foboot-bitstream.py --boot-source rand --revision evt

This will synthesize a bitstream and store the result in build/gateware/top.bin. This is a fully-working bitstream, however it has no ROM, and so doesn't do anything useful. To actually do something with it, we need to build a ROM and patch it in.

Building Foboot software

Normally, Foboot is built as part of the HW build process. You can build it separately by going to the sw/ directory and typing make. This will generate several files. Of interest is foboot.bin.

Note that if you change major components from the HW part, you will need to regenerate the CSR header files. Copy them from hw/build/software/include/generated/ into sw/include/generated/.

Patching the ROM

To patch the ROM and load a new bitstream using fomu-flash, run:

$ fomu-flash -f hw/build/gateware/top.bin -l sw/foboot.bin`

This will reset the Fomu, patch the bitstream, and load the new bitstream into the FPGA.

Patching the ROM with icebram

The icebram command also has the ability to patch the bitstream, however it requires files to be in a specific format.

To begin with, you need the following Python program to convert foboot.bin to a suitable foboot.hex file:

#!/usr/bin/env python3
def swap32(d):
    d = list(d)
    while len(d) < 4:
        d.append(0)
    t = d[0]
    d[0] = d[3]
    d[3] = t

    t = d[1]
    d[1] = d[2]
    d[2] = t
    return bytes(d)

with open("foboot.bin", "rb") as inp:
    with open("foboot.hex", "w", newline="\n") as outp:
        while True:
            d = inp.read(4)
            if len(d) == 0:
                break
            print(swap32(d).hex(), file=outp)

Then, you need to generate a padded random.hex file from the foboot bitstream (the actual --revision doesn't matter, but must be something valid):

$ python3 ./foboot-bitstream.py --export-random-rom-file random.hex --revision evt

Then, you can use a script to patch the ROM:

$ icepack -u ~/top.bin | icebram random.hex foboot.hex | icepack - top-patched.bin

This will result in a file called top-patched.bin that can be written.

Running Tests

You can run tests by using the unittest command:

python3 lxbuildenv.py -r -m unittest -v valentyusb.usbcore.cpu.epfifo_test.TestPerEndpointFifoInterface

Note that many tests are not working at this time, due to issues in how CSRs and events are handled in litex simulation.