mirror of
https://github.com/im-tomu/foboot.git
synced 2024-09-20 02:40:09 +00:00
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>
This commit is contained in:
parent
5f7cd9d2ab
commit
239aa660ef
13
LICENSE
13
LICENSE
@ -0,0 +1,13 @@
|
||||
Copyright 2019 Sean Cross
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
59
README.md
59
README.md
@ -1,10 +1,10 @@
|
||||
# Foboot: The Bootloader for Fomu
|
||||
|
||||
Foboot is a failsafe bootloader for Fomu. It exposes a DFU interface to the host. Foboot comes in two halves: A Software half and a Hardware half.
|
||||
Foboot is a failsafe bootloader for Fomu. It exposes a DFU interface to the host. Foboot comes in two halves: A Software half and a Hardware half. These two halves are integrated into a single "bitstream" that is directly loaded onto an ICE40UP5k board, such as Fomu.
|
||||
|
||||
## Building the Hardware
|
||||
## Requirements
|
||||
|
||||
The hardware half is written in LiteX, and uses `lxbuildenv` to handle Python dependencies. Hardware is contained within the `hw/` directory. You must install software dependencies yourself:
|
||||
To build the hardware, you need:
|
||||
|
||||
* Python 3.5+
|
||||
* Nextpnr
|
||||
@ -12,23 +12,60 @@ The hardware half is written in LiteX, and uses `lxbuildenv` to handle Python de
|
||||
* Yosys
|
||||
* Git
|
||||
|
||||
Subproject dependencies will be taken care of with `lxbuildenv`.
|
||||
Subproject hardware dependencies will be taken care of with `lxbuildenv`.
|
||||
|
||||
To build the software, you need:
|
||||
|
||||
* RISC-V toolchain
|
||||
|
||||
## Building the project
|
||||
|
||||
The hardware half will take care of building the software half, if it is run with `--boot-source bios` (which is the default). Therefore, to build Foboot, enter the `hw/` directory and run:
|
||||
|
||||
```
|
||||
$ python3 foboot-bitstream.py --revision hacker
|
||||
```
|
||||
|
||||
This will verify you have the correct dependencies installed, compile the Foboot software, then synthesize the Foboot bitstream. The resulting output will be in `build/gateware/`. You should write `build/gateware/top-multiboot.bin` to your Fomu device in order to get basic bootloader support.
|
||||
|
||||
### Usage
|
||||
|
||||
To build, run `foboot-bitstream.py`:
|
||||
You can write the bitstream to your SPI flash. If you're using `fomu-flash`, you would run the following:
|
||||
|
||||
`python3 .\foboot-bitstream.py`
|
||||
```sh
|
||||
$ fomu-flash -w build/gateware/top-multiboot.bin
|
||||
Erasing @ 018000 / 01973a Done
|
||||
Programming @ 01973a / 01973a Done
|
||||
$ fomu-flash -r
|
||||
resetting fpga
|
||||
$
|
||||
```
|
||||
|
||||
There are multiple build options available. Use `--help` to list them.
|
||||
Fomu should now show up when you connect it to your machine:
|
||||
|
||||
Build files will be generated in the `build/` directory. You will probably be most interested in `build/gateware/top.bin` and `build/software/include/generated/`.
|
||||
```
|
||||
[172294.296354] usb 1-1.3: new full-speed USB device number 33 using dwc_otg
|
||||
[172294.445661] usb 1-1.3: New USB device found, idVendor=1209, idProduct=70b1
|
||||
[172294.445675] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
|
||||
[172294.445684] usb 1-1.3: Product: Fomu Bootloader (0)
|
||||
[172294.445692] usb 1-1.3: Manufacturer: Kosagi
|
||||
```
|
||||
|
||||
## Tests
|
||||
To load a new bitstream, use the `dfu-util -D` command. For example:
|
||||
|
||||
You can run tests by using the `unittest` command:
|
||||
```sh
|
||||
$ dfu-util -D blink.bin
|
||||
```
|
||||
|
||||
`python .\lxbuildenv.py -r -m unittest -v valentyusb.usbcore.cpu.epfifo_test.TestPerEndpointFifoInterface`
|
||||
This will reflash the SPI beginning at offset 262144.
|
||||
|
||||
To exit DFU and run the bitstream at offset 262144, run:
|
||||
|
||||
```sh
|
||||
$ dfu-util -e
|
||||
```
|
||||
|
||||
**Note that, unlike Toboot, Foboot requires you to issue `dfu-util -e` in order to start the program.**
|
||||
|
||||
## Building the Software
|
||||
|
||||
|
93
doc/HACKING.md
Normal file
93
doc/HACKING.md
Normal file
@ -0,0 +1,93 @@
|
||||
# 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:
|
||||
|
||||
```python
|
||||
#!/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:
|
||||
|
||||
```sh
|
||||
$ 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.
|
Loading…
Reference in New Issue
Block a user