Conware's goal is to automatically model hardware peripherals in software for emulation.
The overall arhitecture is as follows:
[Arduino]+[Peripheral] + LLVM Pass --> conware-recorder
[Log File (TSV)] --> conware-model-generate
--> conware-model-optimize
--> conware-emulate
The arduino code is instrumented with LLVM to record any MMIO read or write.
This code is than run on a real arduino with the real peripheral attached.
After a designated amount of time the log of all of the MMIO accesses are dumped over UART and stored in a log file.
This log file is then consummed by conware-model-generate
, which will generate a .pickle model file which can be consummed by conware-emulate
and run on emulated hardware.
To optimize this model, which is the real power of conware, we execute conware-model-optimize
.
-
Install direnv.
sudo apt-get install -y direnv
This is needed to help manage all of the environment path variables that must be set.
-
We use LLVM and the arduino framework to build and manipulate our firmware.
To install these and setup your environment variables run:Be patient: This will take a looong time... If you have an expecially powerful machine, you can remove the -l parameter from ninja. It is currently configured to be gentle on your machine.
./install_dependencies.sh
This will install all of the neccessary dependencies, build LLVM, and setup your local environment properly with direnv
-
We use of Avatar^2 (w/ OpenOCD) for our emulation framework.
Install this in a virtualenv.
For example, in fish:
vf create conware
Once virtualenv is installed and conware environment is created, run:
./install_avatar.sh
- Build and instrument the arduino firmware:
./rebuild_runtime.sh
- Build and instrument an arduino project:
./instrument_project.sh <arduino directory>
For example:
./instrument_project.sh firmware/custom/blink/
- Execute the firmware log the data (saved a TSV file in the specified directory). The device address is the filename in
/dev/
(e.g., ttyACM0)
conware-recorder -l <device address> <output directory>
For example,
conware-recorder -l ttyACM0 firmware/custom/blink/
This will result in a recording.tsv
in the output directory specified. Every other script assumes these default names.
Buffer size is defined in '/conware/runtime/arduino-1.8.8/portable/packages/arduino/hardware/sam/1.6.11/system/libsam/source'
-
You can then generate a model file using:
conware-model-generate
For example:
conware-model-generate firmware/custom/blink/
This will output a model.pickle
file in the same directory. This model is effectively a graph representation of the input file, but represented as a state machine and with memory reads represented as simple models (e.g., storage, pattern, or markov). It has a lot of room for improvement (i.e., the point of this project)
-
To optimize this model, use:
conware-model-optimize
For example:
conware-model-optimize firmware/custom/blink/model.pickle
-
To visualize a model we created, run:
conware-model-visualize
For example:
conware-model-visualize firmware/custom/blink/model.pickle
Or, to run on the optimized model,
conware-model-visualize firmware/custom/blink/model_optimized.pickle
The current version will dump PDF files, which can be opened to see the state machine. (e.g., UART.gv.pdf)
xdg-open firmware/custom/blink/model_optimized_UART.pdf
To view the output files, we use qpdfview:
qpdfview firmware/custom/blink/model_optimized*.pdf
-
Once the model is optmized, it can be used to rehost the firmware using
conware-emulate
For example,
conware-emulate -s firmware/custom/blink/build/blink.ino.bin -r firmware/custom/blink -t 30
will run a verbatim replay model the firmware for 30 seconds in an emulator. Or, run the optimized model with:
conware-emulate -s firmware/custom/blink/build/blink.ino.bin -r firmware/custom/blink -t 30 -m firmware/custom/blink/model_optimized.pickle
Conware also offers the ability merge models (before optimization) using
**conware-model-merge**
For example,
conware-model-merge firmware/custom/knock/model.pickle firmware/custom/irremote/model.pickle -o merged/merged.pickle
will create a new model, which is a combination of the two, and save it as merged.pickle. This model can then be optimized into a general form as well
conware-model-optimize merged/merged.pickle
and this merged, optimized model can be used to emulate either of the original firmware binaries.
We care about the Pio struct, found in runtime/arduino-1.8.8/portable/packages/arduino/hardware/sam/1.6.11/system/CMSIS/Device/ATMEL/sam3xa/include/component/component_pio.h
The actual pins are defined in runtime/arduino-1.8.8/portable/packages/arduino/hardware/sam/1.6.11/system/CMSIS/Device/ATMEL/sam3xa/include/pio/pio_sam3x8e.h
/* Memory mapping of Cortex-M0 Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
All of the MMIO structures are defined in sam/system/CMSIS/Device/ATMEL/sam3xa/include/component/
- Install J-Link software
- Connect 4 SWD pins
- Run J-Link
$ JLinkExe
- Configure J-Link
si 1
speed 4000
device Cortex-M3
r