Commit edf41358 authored by Renaud Pacalet's avatar Renaud Pacalet
Browse files

Add VHDL and scripts

parent 463658c8
#
# SecBus ( https://secbus.telecom-paristech.fr/ ) - This file is part of SecBus
# Copyright (C) - Telecom Paris
# Contacts: contact-secbus@telecom-paris.fr
#
# This file must be used under the terms of the CeCILL.
# This source file is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at
# http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
#
####################
# Global variables #
####################
# Set to non-empty string to increase verbosity. If set to the empty string log
# files are created in O/
V :=
# Maximum number of parallel make jobs (for paralellizable targets).
J := 12
# Main build directory, all builds are done in O or subdirectories of
# O.
O := /opt/secbus/build
# Directory in which all files that must be copied on the SD card are stored.
SDCARDDIR := $(O)/sdcard
# Supported cross-compiler version
SUPPORTED_GCC_VERSION := 7.3.1
#######################
# Synthesis variables #
#######################
# Directory in which synthesis in run.
SYNDIR := $(O)/syn
# Target clock frequency of digital hardware design in MHz.
FREQUENCY := 70
# If set to non-empty string embed a ChipScope Integrated Logic Analyzer core
# allowing to observe the M_AXI signals from Vivado.
# NOT SUPPORTED YET, LEAVE EMPTY
CHIPSCOPE :=
##################################
# First Stage Boot Loader (FSBL) #
##################################
# FSBL sources are generated in FSBLDIR/orig, patched and compiled in
# FSBLDIR/new.
FSBLDIR := $(O)/fsbl
##############
# Das U-Boot #
##############
UBOOTGITTAG := xilinx-v2018.3
UBOOTDIR := $(O)/u-boot
XLNXUBOOT := /opt/u-boot-xlnx
##############
# Boot image #
##############
BOOTDIR := $(O)/boot
################
# Linux kernel #
################
LINUXGITTAG := xilinx-v2018.3
LINUXDIR := $(O)/linux
XLNXLINUX := /opt/linux-xlnx
LINUXLOADADDR := 0x50008000
###############
# Device Tree #
###############
DTSGITTAG := xilinx-v2018.3
DTDIR := $(O)/dt
XLNXDTS := /opt/device-tree-xlnx
##############################
# Buildroot root file system #
##############################
BUILDROOT := /opt/buildroot
BUILDROOTGITTAG := 2019.02.1
ROOTFSDIR := $(O)/rootfs
#################
# Demonstration #
#################
DEMODIR := $(O)/demo
/*
* SecBus ( https://secbus.telecom-paristech.fr/ ) - This file is part of SecBus
* Copyright (C) - Telecom Paris
* Contacts: contact-secbus@telecom-paris.fr
*
* This file must be used under the terms of the CeCILL.
* This source file is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at
* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
*/
/*
* Store the content of the data file at the beginning of four 4kB memory pages
* starting at base_address (see below). Then, enter an infinite loop where a
* textual menu is presented to the user asking to pick one of the four pages
* (or to exit). Read the chosen page and print it. Wait for a keystroke and
* loop.
*
*
* Usage: player INPUTFILE
*
* INPUTFILE Name of data file
*
* Example:
*
* $ player data.txt
* Loading data in memory, please wait...
*
* Play from:
* 1. Unprotected page
* 2. Encrypted page
* 3. Integrity-checked page
* 4. Encrypted and integrity-checked page
*
* 0. Quit
* >> 1
* ...
*
* Press any key to continue...
*/
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>
#define PAGE_SIZE 4096UL
#define ADDR_MASK (PAGE_SIZE - 1)
#define PAGE1_ADDR 0x4fffc000
#define PAGE2_ADDR 0x4fffd000
#define PAGE3_ADDR 0x4fffe000
#define PAGE4_ADDR 0x4ffff000
off_t phys_addr[4] = {PAGE1_ADDR, PAGE2_ADDR, PAGE3_ADDR, PAGE4_ADDR};
void *virt_base[4], *virt_addr[4];
int size;
char *page_labels[4] = {"Unprotected", "Encrypted", "Integrity-checked", "Encrypted and integrity-checked"};
char translate[256];
int text_read(char *fname, char *buffer);
void play(int p);
int main(int argc, char **argv) {
int p, r, stop;
#ifdef DEVMEM
int fd;
#endif
struct status {
int code;
int mem_opened;
int mapped;
int written;
};
struct status st = {-1, 0, 0, 0};
static struct termios oldt, newt;
while(1) {
if(argc != 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
break;
}
#ifdef DEVMEM
fd = open("/dev/mem", O_RDWR | O_SYNC);
if(fd == -1) {
fprintf(stderr, "cannot open /dev/mem\n");
break;
}
st.mem_opened = 1;
#endif
for(p = 0; p < 4; p++) {
#ifdef DEVMEM
virt_base[p] = mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, phys_addr[p] & ~ADDR_MASK);
if(virt_base[p] == (void *) -1) {
fprintf(stderr, "cannot map memory\n");
break;
}
virt_addr[p] = (void *)((int) virt_base[p] + (phys_addr[p] & ADDR_MASK));
#else
virt_base[p] = malloc(PAGE_SIZE);
if(virt_base[p] == NULL) {
fprintf(stderr, "cannot allocate memory\n");
break;
}
virt_addr[p] = virt_base[p];
#endif
st.mapped += 1;
}
if(p != 4) {
break;
}
size = text_read(argv[1], virt_addr[0]);
st.written = 1;
if(size < 0) {
fprintf(stderr, "decryption failed\n");
break;
}
for(p = 1; p < 4; p++) {
memcpy(virt_addr[p], virt_addr[0], size);
st.written += 1;
}
stop = 0;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
for(int i = 0; i < 256; i++) {
if(i >= 0x80) {
translate[i] = '?';
} else {
translate[i] = (char)(i);
}
}
while(!stop) {
fprintf(stdout, "\033[2J\033[1G");
fprintf(stdout, "\nPlay from:\n");
for(p = 0; p < 4; p++) {
fprintf(stdout, "%d. %s page\n", p + 1, page_labels[p]);
}
fprintf(stdout, "\n0. Quit\n");
fprintf(stdout, " >> ");
r = fgetc(stdin);
p = -1;
switch(r) {
case '0': stop = 1;
break;
case '1': p = 0;
break;
case '2': p = 1;
break;
case '3': p = 2;
break;
case '4': p = 3;
break;
default: break;
}
if(p >= 0 && p <= 3) {
play(p);
}
}
st.code = 0;
break;
}
fprintf(stdout, "\033[2J\033[1G");
fprintf(stdout, "Bye...\n");
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
#ifdef DEVMEM
if(st.mem_opened) {
close(fd);
}
#endif
for(p = 0; p < st.written; p++) {
memset(virt_base[p], 0, size);
}
for(p = 0; p < st.mapped; p++) {
#ifdef DEVMEM
if(munmap(virt_base[p], PAGE_SIZE) == -1) {
fprintf(stderr, "cannot unmap memory\n");
st.code = -1;
}
#else
free(virt_base[p]);
#endif
}
return st.code;
}
void play(int p) {
unsigned char *v = (unsigned char *)(virt_addr[p]);
fprintf(stdout, "\033[2J\033[1G");
fprintf(stdout, "Playing from %s page...\n\n", page_labels[p]);
for(int i = 0; i < size; i++, v++) {
putchar(translate[*v]);
}
fprintf(stdout, "\nPress any key to continue...");
fgetc(stdin);
}
int text_read(char *fname, char *buffer) {
size_t len = 0;
FILE *fi;
struct stat stat_fi;
struct status {
int code;
int file_opened;
int buffer_written;
};
struct status st = {-1, 0, 0};
while(1) {
fi = fopen(fname, "r");
if(fi == NULL) {
fprintf(stderr, "%s: file not found\n", fname);
break;
}
st.file_opened = 1;
if(stat(fname, &stat_fi)) {
fprintf(stderr, "%s: cannot stat file\n", fname);
break;
}
len = (size_t) stat_fi.st_size;
if(len == 0) {
fprintf(stderr, "%s: file empty\n", fname);
break;
}
if(len > PAGE_SIZE) {
fprintf(stderr, "maximum plaintext size (%lu) exceeded (%zu)\n", PAGE_SIZE, len);
break;
}
if(fread(buffer, 1, len, fi) != len) {
fprintf(stderr, "could not read text from file %s\n", fname);
break;
}
fclose(fi);
st.file_opened = 0;
st.buffer_written = 1;
st.code = len;
break;
}
if(st.buffer_written && st.code < 0) {
memset(buffer, 0, len);
}
if(st.file_opened) {
fclose(fi);
}
return st.code;
}
// vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab textwidth=0:
/*
* SecBus ( https://secbus.telecom-paristech.fr/ ) - This file is part of SecBus
* Copyright (C) - Telecom Paris
* Contacts: contact-secbus@telecom-paris.fr
*
* This file must be used under the terms of the CeCILL.
* This source file is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at
* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
*/
/*
* Load file <file> in memory at address <addr>. Write 4-bytes at a time using
* u2m_write. Supports addresses that are not aligned on a 4-bytes boundary and
* file sizes that are not multiples of 4 bytes: use byte enable (be) parameter
* of u2m_write to write right number of byte during first and last calls to
* u2m_write.
*/
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <ftdi.h>
#include "u2m_lib.h"
int main(int argc, char **argv) {
uint32_t addr, wdata, be;
int s, skip_first;
FILE *fd;
struct ftdi_context *ftdi;
if(argc != 3) {
fprintf(stderr, "usage: %s <addr> <file>\n", argv[0]);
exit(EXIT_FAILURE);
}
addr = strtoul(argv[1], NULL, 0);
fd = fopen(argv[2], "r");
if(fd == NULL) {
fprintf(stderr, "%s: file %s not found\n", argv[0], argv[2]);
return EXIT_FAILURE;
}
ftdi = u2m_open();
be = UINT32_C(0xf);
skip_first = addr % 4;
addr -= skip_first;
while((s = fread(&wdata, 1, 4 - skip_first, fd))) {
be = (1 << s) - 1;
be <<= skip_first;
wdata <<= skip_first * 8;
#ifdef DEBUG
if(skip_first)
fprintf(stderr, "addr=%08x, skip_first=%d, be=%1x, wdata=%08x, (s=%d)\n", addr, skip_first, be, wdata, s);
#endif
skip_first = 0;
s = u2m_write(ftdi, addr, wdata, be);
if(s != EXIT_SUCCESS)
break;
addr += 4;
}
fclose(fd);
u2m_close(ftdi);
return s;
}
/*
* SecBus ( https://secbus.telecom-paristech.fr/ ) - This file is part of SecBus
* Copyright (C) - Telecom Paris
* Contacts: contact-secbus@telecom-paris.fr
*
* This file must be used under the terms of the CeCILL.
* This source file is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at
* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
*/
/*
* Basic I/O routines for UART2MAXILITE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <time.h>
#include <ftdi.h>
/* FTDI / FT232R */
#define VENDOR 0x403
#define PRODUCT 0x6001
/* Line parameters */
#define BAUDRATE 115200
#define BITS_PER_CHAR BITS_8
#define PARITY NONE
#define STOP_BITS STOP_BIT_1
/* UART2MAXILITE command bytes */
#define MEM_READ (0<<4)
#define MEM_WRITE (1<<4)
#define REG_READ (2<<4)
#define REG_WRITE (3<<4)
/* UART2MAXILITE exit status bytes */
#define OKAY 0
#define SLVERR 2
#define DECERR 3
/* Number of retries when reading characters from UART */
#define READ_RETRY 1000
/* Sleep duration between to attempts to read characters from UART */
const struct timespec ms10_s = {0, 10000};
const struct timespec *ms10 = &ms10_s;
/* Initialize and open FTDI device. Exit with EXIT_FAILURE status if fail to
* find, initialize and open device. */
struct ftdi_context *u2m_open(void) {
struct ftdi_context *ftdi;
struct ftdi_device_list *devlist;
int ndev, status;
if ((ftdi = ftdi_new()) == 0)
{
fprintf(stderr, "u2m_open error: ftdi_new failed\n");
exit(EXIT_FAILURE);
}
ftdi_set_interface(ftdi, INTERFACE_ANY);
ndev = ftdi_usb_find_all(ftdi, &devlist, VENDOR, PRODUCT);
if (ndev < 0) {
fprintf(stderr, "u2m_open error: %d (idVendor=%x, idProduct=%x)\n", ndev, VENDOR, PRODUCT);
exit(EXIT_FAILURE);
}
if (ndev == 0) {
fprintf(stderr, "u2m_open error - no FTDI devices found (idVendor=%x, idProduct=%x)\n", VENDOR, PRODUCT);
exit(EXIT_FAILURE);
}
if (ndev > 1) {
fprintf(stderr, "u2m_open error - more than one FTDI devices found: %d (idVendor=%x, idProduct=%x)\n", ndev, VENDOR, PRODUCT);
exit(EXIT_FAILURE);
}
status = ftdi_usb_open_dev(ftdi, devlist[0].dev);
if(status != 0) {
fprintf(stderr, "u2m_open error - could not open FTDI device: %d (%s)\n", status, ftdi_get_error_string(ftdi));
exit(EXIT_FAILURE);
}
status = ftdi_set_baudrate(ftdi, BAUDRATE);
if (status < 0)
{
fprintf(stderr, "u2m_open error - could not set baudrate: %d (%s)\n", status, ftdi_get_error_string(ftdi));
exit(EXIT_FAILURE);
}
status = ftdi_set_line_property(ftdi, BITS_PER_CHAR, STOP_BITS, PARITY);
if (status < 0)
{
fprintf(stderr, "u2m_open error - could not set line parameters: %d (%s)\n", status, ftdi_get_error_string(ftdi));
exit(EXIT_FAILURE);
}
return ftdi;
}
/* Close FTDI device. */
void u2m_close(struct ftdi_context *ftdi) {
ftdi_usb_close(ftdi);
ftdi_free(ftdi);
}
/* Read one char from FTDI device. Wait 10 micro-seconds minimum between
* retries. Retry at most READ_RETRY times. Read char stored in rdata on
* success, undefined on failure. Return EXIT_SUCCESS on success, EXIT_FAILURE
* on failure. */
int u2m_getc(struct ftdi_context *ftdi, uint8_t *rdata) {
int i, status;
for(i = 0; i < READ_RETRY; i++) {
status = ftdi_read_data(ftdi, rdata, 1);
if(status != 0)
break;
nanosleep(ms10, NULL);
}
if (status != 1)
{
fprintf(stderr, "u2m_getc error - could not read char from FTDI device: %d (%s)\n", status, ftdi_get_error_string(ftdi));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
/* Read one 32-bits word at address <addr> in target memory and store read word
* in <rdata>. Send sequence of commands to FTDI device:
* - reg_write register a0 (a1, a2, a3) with addr[7..0] (addr[15..8]...)
* - mem_read
* - reg_read register d0 (d1, d2, d3)
* and read 5 characters using u2m_getc (status of mem_read plus the 4 read
* bytes).
*/
int u2m_read(struct ftdi_context *ftdi, uint32_t addr, uint32_t *rdata) {
uint8_t buf[13];
int i, status;
for(i = 0; i < 4; i++) {
buf[2 * i] = REG_WRITE | i;
buf[2 * i + 1] = (addr >> 8 * i) & 0xff;
}
buf[8] = MEM_READ;
for(i = 0; i < 4; i++) {
buf[9 + i] = REG_READ | (i + 4);
}
status = ftdi_write_data(ftdi, buf, 13);
if (status != 13)
{
fprintf(stderr, "u2m_read error - could not send command to FTDI device: %d (%s)\n", status, ftdi_get_error_string(ftdi));
return status;
}
status = u2m_getc(ftdi, buf);
if(status != EXIT_SUCCESS)
return status;
if(buf[0] != OKAY) {
fprintf(stderr, "u2m_read error - AXI response not OKAY: %d\n", buf[0]);
return buf[0];
}
*rdata = 0;
for(i = 1; i < 5; i++) {
status = u2m_getc(ftdi, buf + i);
if(status != EXIT_SUCCESS)
return status;
}
for(i = 4; i > 0; i--) {
*rdata = (*rdata << 8) | buf[i];
}
return EXIT_SUCCESS;
}
/* Write 32-bits word <wdata> at address <addr> in target memory with byte
* enable <be>. Send sequence of commands to FTDI device:
* - reg_write register a0 (a1, a2, a3) with addr[7..0] (addr[15..8]...)
* - reg_write register d0 (d1, d2, d3) with wdata[7..0] (wdata[15..8]...)
* - mem_write
* and read mem_write status character using u2m_getc.
*/
int u2m_write(struct ftdi_context *ftdi, uint32_t addr, uint32_t wdata, uint32_t be) {
uint8_t buf[17];
int i, status;
for(i = 0; i < 4; i++) {
buf[2 * i] = REG_WRITE | i;
buf[2 * i + 1] = (addr >> 8 * i) & 0xff;
}
for(i = 0; i < 4; i++) {
buf[8 + 2 * i] = REG_WRITE | (i + 4);
buf[8 + 2 * i + 1] = (wdata >> 8 * i) & 0xff;
}
buf[16] = MEM_WRITE | (be & 0xf);
status = ftdi_write_data(ftdi, buf, 17);
if (status != 17)
{
fprintf(stderr, "u2m_write error - could not send command to FTDI device: %d (%s)\n", status, ftdi_get_error_string(ftdi));
return status;
}
status = u2m_getc(ftdi, buf);
if(status != EXIT_SUCCESS)
return status;
if(buf[0] != OKAY) {
fprintf(stderr, "u2m_write error - AXI response not OKAY: %d\n", buf[0]);
return buf[0];
}
return EXIT_SUCCESS;
}
/*
* SecBus ( https://secbus.telecom-paristech.fr/ ) - This file is part of SecBus
* Copyright (C) - Telecom Paris
* Contacts: contact-secbus@telecom-paris.fr
*
* This file must be used under the terms of the CeCILL.
* This source file is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at