# BAL Xilinx Overview

The BAL Xilinx package is an implementation of the 
[Binary Abstraction Layer (BAL)](https://github.com/ballon-rouge/bal) framework for Xilinx FPGA.
It supports packing/unpacking of most of the bitstream, target device/encryption detection and 
pin modification (force the pin high/low).
It is supposed to be a dependency of a project, not a boilerplate project to be customized.
It was first introduced at Black Hat 2019 ([presentation](https://redballoonsecurity.com/files/CycIhULVL5FS6VNM/100_seconds_of_solitude.pdf), [research paper](https://www.usenix.org/conference/woot19/presentation/kataria)).

The full api documentation is available [here](https://RedBalloonShenanigans.github.io/bal-xilinx/).

## Contributors:


 - Jatin Kataria (Researcher)
 - Rick Housley (Researcher)
 - Alex Massonneau (Developer)
 - Andrew O'Brien (Developer)

## Installation

The BAL Xilinx package can be installed from PyPi with the following command:
```
pip install bal-xilinx
```

The BAL Xilinx package can also be installed from the repository. It requires the BAL package. See the [installation instructions](https://github.com/ballon-rouge/bal).

To install the BAL Xilinx package from source, run:

```
git clone https://github.com/RedBalloonShenanigans/bal-xilinx.git
cd bal-xilinx
pip install .
```

To generate the documentation, run:
```
pip install .[docs]
make html-docs
```

## Tools

While this module is meant to be used as a dependency for another project, it currently offers a 
single tool called `pin`. It turns on/off a given pin for an existing Xilinx FPGA bitstream. It is
accessible by running:

```python
python -m bal_xilinx.tools.pin 
``` 

The documentation for the pin tool can be accessed by running it with the `-h` flag.

## Methodology

The Xilinx converters rely heavily on format definitions contained in [bal_xilinx/configs](bal_xilinx/configs). The methodology used to create these JSON files will be published shortly.

## Guide

This guide assumes familiarity with the [BAL framework](https://github.com/ballon-rouge/bal).
As the name of the project implies, this is an implementation of it for Xilinx FPGA bitstreams.
Complete examples are available under [./example](./example).

### Analyzers

There are 3 analyzers available:

 - `bal_xilinx.analyzers.device_analyzer.XilinxDeviceAnalyzer` Determines the type of device 
 targeted by the bitstream.
 - `bal_xilinx.analyzers.encryption_analyzer.XilinxEncryptionAnalyzer` Determines if the FDRI 
 packets are encrypted.
 - `bal_xilinx.analyzers.visualizer_analyzer.XilinxVisualizerAnalyzer` Generate the configuration
  data for the [BAL visualizer](https://github.com/ballon-rouge/bal-visualizer/).
  
### Modifiers

There is currently a single analyzer:

- `bal_xilinx.modifiers.pin_modifier.XilinxPinModifer` Force a pin to be low/high regardless of 
the logic executed by the FPGA.

### Examples

Here is an example that puts together all the analyzers and modifiers available.

```python
# Configure the default converters
xilinx_context_factory = default_xilinx_context(XilinxContextFactory(
    # Register the formats for the LX9 and LX45T
    default_xilinx_formats(XilinxFormatBuilder()).build()
))

lx9_bin = wget.download('https://redballoonsecurity.com/files/JwfEU4veQSNFao8h/lx9.bin')
with open(lx9_bin, "rb") as f:
    data = f.read()
    
bitstream_context = xilinx_context_factory.create(data)

# Get the device type targeted by the bitstream
device_type = bitstream_context.create_analyzer(XilinxDeviceAnalyzer)\
    .analyze()
print("Device info: {}".format(device_type))

# Determine if the FDRI packets are encrypted.
is_encrypted = bitstream_context.create_analyzer(XilinxEncryptionAnalyzer)\
    .analyze()
print("Is encrypted: {}".format(is_encrypted))

# Unpack the entire bitstream to make sure the visualization includes everything
bitstream_context.get_data().unpack_all()

print("Writing the visualizer config to {}".format(os.path.abspath("data.json")))
with open("data.json", "w") as f:
    # Generate the visualization config file
    visualizer_config = bitstream_context.create_analyzer(VisualizerAnalyzer) \
        .analyze()
    json.dump(visualizer_config,  f)

print("Pulling the pins low")
pin_modifier = bitstream_context.create_modifier(XilinxPinModifer)
for pin in ["P134", "P133", "P132", "P131", "P127", "P126", "P124", "P123"]:
    pin_modifier.modify(pin, False)


print("Analysis and modifications done!")

```

That is it for the guide. Have fun!


