firmware/iso7816soc-usb: Import minimal USB firmware

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
Sylvain Munaut 2022-05-02 15:33:27 +02:00
parent a6a5c12c1e
commit 43e563d4cb
5 changed files with 421 additions and 0 deletions

4
firmware/iso7816soc-usb/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*.bin
*.elf
*.o
*.gen.h

View File

@ -0,0 +1,62 @@
BOARD ?= icebreaker
CROSS ?= riscv-none-embed-
CC = $(CROSS)gcc
OBJCOPY = $(CROSS)objcopy
ICEPROG = iceprog
BOARD_DEFINE=BOARD_$(shell echo $(BOARD) | tr a-z\- A-Z_)
CFLAGS=-Wall -Os -march=rv32i -mabi=ilp32 -ffreestanding -flto -nostartfiles -fomit-frame-pointer -Wl,--gc-section --specs=nano.specs -D$(BOARD_DEFINE) -I. -I../common
HEADERS_common=$(addprefix ../common/, \
config.h \
console.h \
led.h \
mini-printf.h \
misc.h \
no2iso7816.h \
spi.h \
utils.h \
)
SOURCES_common=$(addprefix ../common/, \
start.S \
console.c \
led.c \
mini-printf.c \
misc.c \
no2iso7816.c \
spi.c \
utils.c \
)
NO2USB_FW_VERSION=0
include ../../gateware/cores/no2usb/fw/fw.mk
CFLAGS += $(INC_no2usb)
HEADERS_common += $(HEADERS_no2usb)
SOURCES_common += $(SOURCES_no2usb)
HEADERS_app=\
usb_str_app.gen.h \
$(NULL)
SOURCES_app=\
fw_app.c \
usb_desc_app.c \
$(NULL)
all: fw_app.bin
fw_app.elf: ../common/lnk-app.lds $(HEADERS_app) $(SOURCES_app) $(HEADERS_common) $(SOURCES_common)
$(CC) $(CFLAGS) -Wl,-Bstatic,-T,../common/lnk-app.lds,--strip-debug -o $@ $(SOURCES_common) $(SOURCES_app)
%.bin: %.elf
$(OBJCOPY) -O binary $< $@
prog: fw_app.bin
$(ICEPROG) -o 640k $<
clean:
rm -f *.bin *.hex *.elf *.o *.gen.h
.PHONY: prog clean

View File

@ -0,0 +1,265 @@
/*
* fw_app.c
*
* Copyright (C) 2021-2022 Sylvain Munaut
* SPDX-License-Identifier: MIT
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "console.h"
#include "led.h"
#include "mini-printf.h"
#include "misc.h"
#include "no2iso7816.h"
#include "spi.h"
#include "utils.h"
#include "config.h"
#include <no2usb/usb.h>
#include <no2usb/usb_dfu_rt.h>
// ---------------------------------------------------------------------------
// ISO7816 test
// ---------------------------------------------------------------------------
static void
iso7816_read_data(const char *desc)
{
printf("%s :", desc);
while (1) {
int v = iso7816_get_char();
if (v < 0)
break;
printf(" %02x", v);
}
printf("\n");
}
static void
iso7816_test()
{
/* Setup core with default params */
iso7816_init(4);
/* Power up card */
ncn8025_power_up();
wait(1000); // 100_000 us
/* Read ATR */
iso7816_read_data("ATR");
/* Send PPS Request */
iso7816_put_char(0xff); // PPPS
iso7816_put_char(0x10); // PPS0
iso7816_put_char(0x96); // PPS1
iso7816_put_char(0x79); // PCK
wait(100); // 10_000 us
/* Read PPS response */
iso7816_read_data("PPS Response");
/* Switch core to higher speed */
iso7816_setup_brg(512, 32, 4);
/* Test APDU */
iso7816_put_char(0xA0);
iso7816_put_char(0xC0);
iso7816_put_char(0x00);
iso7816_put_char(0x00);
iso7816_put_char(0x1A);
wait(10000); // 100_000 us
iso7816_read_data("APDU");
}
// ---------------------------------------------------------------------------
// USB integration
// ---------------------------------------------------------------------------
extern const struct usb_stack_descriptors app_stack_desc;
void
usb_dfu_rt_cb_reboot(void)
{
/* Force re-enumeration */
usb_disconnect();
/* Reboot to bootloader */
reboot(1);
}
static void
serial_no_init()
{
uint8_t buf[8];
char *id, *desc;
int i;
flash_manuf_id(buf);
printf("Flash Manufacturer : %s\n", hexstr(buf, 3, true));
flash_unique_id(buf);
printf("Flash Unique ID : %s\n", hexstr(buf, 8, true));
/* Overwrite descriptor string */
/* In theory in rodata ... but nothing is ro here */
id = hexstr(buf, 8, false);
desc = (char*)app_stack_desc.str[1];
for (i=0; i<16; i++)
desc[2 + (i << 1)] = id[i];
}
// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------
void main()
{
int cmd = 0;
bool card_pwr = false;
bool card_rst = true;
bool card_clk = false;
/* Init console IO */
console_init();
puts("Booting App image..\n");
/* LED */
led_init();
led_color(48, 96, 5);
led_blink(true, 200, 1000);
led_breathe(true, 100, 200);
led_state(true);
/* Setup NCN8025 */
ncn8025_init();
/* SPI */
spi_init();
/* Setup USB */
serial_no_init();
usb_init(&app_stack_desc);
usb_dfu_rt_init();
usb_connect();
/* Main loop */
while (1)
{
/* Prompt ? */
if (cmd >= 0)
printf("Command> ");
/* Poll for command */
cmd = getchar_nowait();
if (cmd >= 0) {
if (cmd > 32 && cmd < 127)
putchar(cmd);
putchar('\r');
putchar('\n');
switch (cmd)
{
/* Select voltage */
case 'q':
printf("Voltage 1V8\n");
ncn8025_set_vsel(1800);
break;
case 'w':
printf("Voltage 3V\n");
ncn8025_set_vsel(3000);
break;
case 'e':
printf("Voltage 5V\n");
ncn8025_set_vsel(5000);
break;
/* Select clock div */
case '1':
printf("Divider 1:1 (20 MHz)\n");
ncn8025_set_clk_div(1);
break;
case '2':
printf("Divider 1:2 (10 MHz)\n");
ncn8025_set_clk_div(2);
break;
case '4':
printf("Divider 1:4 (5 MHz)\n");
ncn8025_set_clk_div(4);
break;
case '8':
printf("Divider 1:8 (2.5 MHz)\n");
ncn8025_set_clk_div(8);
break;
/* Toggle reset */
case 'r':
card_rst ^= 1;
printf("Card reset: %s\n", card_rst ? "Asserted" : "not asserted");
ncn8025_set_ll(card_pwr, card_rst, card_clk);
break;
/* Toggle power */
case 'p':
card_pwr ^= 1;
printf("Card power: %s\n", card_pwr ? "Enabled" : "Disabled");
ncn8025_set_ll(card_pwr, card_rst, card_clk);
break;
/* Toggle clock */
case 'c':
card_clk ^= 1;
printf("Card clock: %s\n", card_clk ? "Active" : "Inactive");
ncn8025_set_ll(card_pwr, card_rst, card_clk);
break;
/* Probe int_n */
case 'i':
printf("INT_N: %s\n", ncn8025_get_int_n() ? "High" : "Low");
break;
/* Power 'up' sequence */
case 'u':
ncn8025_power_up();
break;
/* Power 'down' sequence */
case 'd':
ncn8025_power_down();
break;
case 's':
iso7816_debug();
break;
case 'S':
iso7816_init(4);
break;
case 'T':
iso7816_test();
break;
case 'R':
printf("%08x\n", iso7816_get_char());
break;
default:
break;
}
}
/* USB poll */
usb_poll();
}
}

View File

@ -0,0 +1,85 @@
/*
* usb_desc_app.c
*
* Copyright (C) 2019-2022 Sylvain Munaut
* SPDX-License-Identifier: MIT
*/
#include <no2usb/usb_proto.h>
#include <no2usb/usb_dfu_proto.h>
#include <no2usb/usb.h>
static const struct {
/* Configuration */
struct usb_conf_desc conf;
/* DFU Runtime */
struct {
struct usb_intf_desc intf;
struct usb_dfu_func_desc func;
} __attribute__ ((packed)) dfu;
} __attribute__ ((packed)) _app_conf_desc = {
.conf = {
.bLength = sizeof(struct usb_conf_desc),
.bDescriptorType = USB_DT_CONF,
.wTotalLength = sizeof(_app_conf_desc),
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = 4,
.bmAttributes = 0x80,
.bMaxPower = 0x32, /* 100 mA */
},
.dfu = {
.intf = {
.bLength = sizeof(struct usb_intf_desc),
.bDescriptorType = USB_DT_INTF,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 0,
.bInterfaceClass = USB_CLS_APP_SPECIFIC,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01,
.iInterface = 5,
},
.func = {
.bLength = sizeof(struct usb_dfu_func_desc),
.bDescriptorType = USB_DFU_DT_FUNC,
.bmAttributes = 0x0d,
.wDetachTimeOut = 0,
.wTransferSize = 4096,
.bcdDFUVersion = 0x0101,
},
},
};
static const struct usb_conf_desc * const _conf_desc_array[] = {
&_app_conf_desc.conf,
};
static const struct usb_dev_desc _dev_desc = {
.bLength = sizeof(struct usb_dev_desc),
.bDescriptorType = USB_DT_DEV,
.bcdUSB = 0x0200,
.bDeviceClass = 0,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = 64,
.idVendor = 0x1d50,
.idProduct = 0x6147,
.bcdDevice = 0x0001, /* v0.1 */
.iManufacturer = 2,
.iProduct = 3,
.iSerialNumber = 1,
.bNumConfigurations = num_elem(_conf_desc_array),
};
#include "usb_str_app.gen.h"
const struct usb_stack_descriptors app_stack_desc = {
.dev = &_dev_desc,
.conf = _conf_desc_array,
.n_conf = num_elem(_conf_desc_array),
.str = _str_desc_array,
.n_str = num_elem(_str_desc_array),
};

View File

@ -0,0 +1,5 @@
0000000000000000
osmocom
ISO7816 USB SoC
Main
DFU runtime