From ee7d72743e051f456f851a4f6049e7d7cc3878da Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 20 Jun 2013 16:19:49 +0900 Subject: [PATCH] port to chopstx --- .gitmodules | 3 + ChangeLog | 6 + chopstx | 1 + polarssl/library/aes.c | 6 +- src/Makefile.in | 205 ++++--------------- src/ac.c | 5 +- src/adc.h | 6 +- src/adc_stm32f103.c | 126 +++++++----- src/call-ec_p256.c | 3 +- src/call-rsa.c | 4 +- src/config.h.in | 1 - src/configure | 32 +-- src/debug.c | 7 +- src/debug.h | 9 + src/flash.c | 7 +- src/gnuk.h | 48 ++--- src/gnuk.ld.in | 139 ++++++------- src/main.c | 389 +++++++++++++++++++++---------------- src/neug.c | 131 ++++++++----- src/openpgp-do.c | 4 +- src/openpgp.c | 31 +-- src/random.c | 5 +- src/stdlib.h | 13 +- src/stm32f103.h | 204 +++++++++++++++++++ src/sys.c | 432 ++++++++++++++++++++++++++++++++++------- src/sys.h | 22 ++- src/usb-icc.c | 91 +++++---- src/usb_ctrl.c | 151 ++++++++------ src/usb_desc.c | 5 +- src/usb_stm32f103.c | 22 +-- 30 files changed, 1349 insertions(+), 759 deletions(-) create mode 160000 chopstx create mode 100644 src/debug.h create mode 100644 src/stm32f103.h diff --git a/.gitmodules b/.gitmodules index ad61fd3..2917670 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "chibios"] path = chibios url = git@gitorious.org:gnuk/chibios.git +[submodule "chopstx"] + path = chopstx + url = git@gitorious.org:chopstx/chopstx.git diff --git a/ChangeLog b/ChangeLog index 8c85c90..8baa98b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2013-06-20 Niibe Yutaka + + * src/sys.c, src/sys.h, src/neug.c, rc/usb_stm32f103.c: Update + from NeuG 0.10. + * src/stm32f103.h: New. From NeuG 0.10. + 2013-06-18 Niibe Yutaka * src/openpgp-do.c (gpg_do_write_prvkey, proc_key_import, gpg_do_table) diff --git a/chopstx b/chopstx new file mode 160000 index 0000000..8447b2b --- /dev/null +++ b/chopstx @@ -0,0 +1 @@ +Subproject commit 8447b2ba8e7caf10f0c986f629bf457d3db7c5e7 diff --git a/polarssl/library/aes.c b/polarssl/library/aes.c index ece7ee5..2a46f72 100644 --- a/polarssl/library/aes.c +++ b/polarssl/library/aes.c @@ -177,15 +177,15 @@ static const unsigned char FSb[256] = V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) #define V(a,b,c,d) 0x##a##b##c##d -static const uint32_t FT0[256] __attribute__((section(".sys.0"))) = { FT }; +const uint32_t FT0[256] __attribute__((section(".sys.0"))) = { FT }; #undef V #define V(a,b,c,d) 0x##b##c##d##a -static const uint32_t FT1[256] __attribute__((section(".sys.1"))) = { FT }; +const uint32_t FT1[256] __attribute__((section(".sys.1"))) = { FT }; #undef V #define V(a,b,c,d) 0x##c##d##a##b -static const uint32_t FT2[256] __attribute__((section(".sys.2"))) = { FT }; +const uint32_t FT2[256] __attribute__((section(".sys.2"))) = { FT }; #undef V #define V(a,b,c,d) 0x##d##a##b##c diff --git a/src/Makefile.in b/src/Makefile.in index a9f3ee3..3975ea1 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,91 +1,34 @@ # Makefile for Gnuk -BOARD_DIR=@BOARD_DIR@ -@PINPAD_MAKE_OPTION@ -@DEBUG_MAKE_OPTION@ - -############################################################################## -# Build global options -# NOTE: Can be overridden externally. -# - -# Compiler options here. -ifeq ($(USE_OPT),) - USE_OPT = -O3 -Os -ggdb -fomit-frame-pointer -falign-functions=16 -endif - -# C++ specific options here (added to USE_OPT). -ifeq ($(USE_CPPOPT),) - USE_CPPOPT = -fno-rtti -endif - -# Enable this if you want the linker to remove unused code and data -ifeq ($(USE_LINK_GC),) - USE_LINK_GC = yes -endif - -# If enabled, this option allows to compile the application in THUMB mode. -ifeq ($(USE_THUMB),) - USE_THUMB = yes -endif - -# Enable this if you want to see the full log while compiling. -ifeq ($(USE_VERBOSE_COMPILE),) - USE_VERBOSE_COMPILE = no -endif - -# -# Build global options -############################################################################## - -############################################################################## -# Architecture or project specific options -# - -# Enable this if you really want to use the STM FWLib. -ifeq ($(USE_FWLIB),) - USE_FWLIB = no -endif - -# -# Architecture or project specific options -############################################################################## - -############################################################################## -# Project, sources and paths -# - # Define project name here PROJECT = gnuk -# Imported source files -CHIBIOS = ../chibios -include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform.mk -include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk -include $(CHIBIOS)/os/kernel/kernel.mk -include crypt.mk +CHOPSTX = ../chopstx # Define linker script file here LDSCRIPT= gnuk.ld -# C sources that can be compiled in ARM or THUMB mode depending on the global -# setting. -CSRC = $(PORTSRC) \ - $(KERNSRC) \ - $(HALSRC) \ - $(PLATFORMSRC) \ - $(BOARDSRC) \ - ../boards/common/board-common.c \ - $(BOARD_DIR)/board.c \ - $(CHIBIOS)/os/various/evtimer.c \ - $(CHIBIOS)/os/various/syscalls.c \ - $(CRYPTSRC) \ - main.c usb_stm32f103.c adc_stm32f103.c \ +CSRC = main.c usb_stm32f103.c adc_stm32f103.c \ usb_desc.c usb_ctrl.c \ + call-rsa.c \ usb-icc.c openpgp.c ac.c openpgp-do.c flash.c \ bn.c modp256.c jpc.c mod.c ec_p256.c call-ec_p256.c \ - random.c neug.c sys.c + random.c neug.c sha256.c sys.c + +INCDIR = + +CRYPTDIR = ../polarssl +CRYPTSRCDIR = $(CRYPTDIR)/library +CRYPTINCDIR = $(CRYPTDIR)/include +CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/aes.c + +CSRC += $(CRYPTSRC) +INCDIR += $(CRYPTINCDIR) + +@PINPAD_MAKE_OPTION@ +@DEBUG_MAKE_OPTION@ + +USE_EVENTFLAG = yes ifneq ($(ENABLE_DEBUG),) CSRC += debug.c @@ -99,102 +42,28 @@ ifeq ($(ENABLE_PINPAD),dnd) CSRC += usb-msc.c endif -# List ASM source files here -ASMSRC = $(PORTASM) +################################### +CROSS = arm-none-eabi- +CC = $(CROSS)gcc +LD = $(CROSS)gcc +OBJCOPY = $(CROSS)objcopy -INCDIR = $(CRYPTINCDIR) \ - $(PORTINC) $(KERNINC) $(TESTINC) \ - $(HALINC) $(PLATFORMINC) ../boards/common $(BOARD_DIR) \ - $(CHIBIOS)/os/various - -# -# Project, sources and paths -############################################################################## - -############################################################################## -# Compiler settings -# - -MCU = cortex-m3 - -#TRGT = arm-elf- -TRGT = arm-none-eabi- -CC = $(TRGT)gcc -CPPC = $(TRGT)g++ -# Enable loading with g++ only if you need C++ runtime support. -# NOTE: You can use C++ even without C++ support if you are careful. C++ -# runtime support makes code size explode. -LD = $(TRGT)gcc -#LD = $(TRGT)g++ -CP = $(TRGT)objcopy -AS = $(TRGT)gcc -x assembler-with-cpp -OD = $(TRGT)objdump -HEX = $(CP) -O ihex -BIN = $(CP) -O binary - -# ARM-specific options here -AOPT = - -# THUMB-specific options here -TOPT = -mthumb -DTHUMB - -# Define C warning options here +MCU = cortex-m3 CWARN = -Wall -Wextra -Wstrict-prototypes +# DEFS: Add +DEFS = -DRSA_AUTH @KEYGEN_SUPPORT@ @HAVE_SYS_H@ +OPT = -O3 -Os -g +LIBS = -# Define C++ warning options here -CPPWARN = -Wall -Wextra +####################### +include $(CHOPSTX)/rules.mk -# -# Compiler settings -############################################################################## +board.h: + @echo Please run configure to have a symbolic link \'board.h\' + @exit 1 -############################################################################## -# Start of default section -# - -# List all default C defines here, like -D_DEBUG=1 -DDEFS = - -# List all default ASM defines here, like -D_DEBUG=1 -DADEFS = - -# List all default directories to look for include files here -DINCDIR = - -# List the default directory to look for the libraries here -DLIBDIR = - -# List all default libraries here -DLIBS = - -# -# End of default section -############################################################################## - -############################################################################## -# Start of user section -# - -# List all user C define here, like -D_DEBUG=1 -UDEFS = @KEYGEN_SUPPORT@ - -# Define ASM defines here -UADEFS = - -# List all user directories here -UINCDIR = - -# List the user directory to look for the libraries here -ULIBDIR = - -# List all user libraries here -ULIBS = - -# -# End of user defines -############################################################################## - -include $(CHIBIOS)/os/ports/GCC/ARMCMx/rules.mk +sys.c: board.h distclean: clean - -rm -f Makefile gnuk.ld config.h *.inc + -rm -f gnuk.ld config.h board.h Makefile \ + usb-strings.c.inc usb-vid-pid-ver.c.inc diff --git a/src/ac.c b/src/ac.c index 8011f26..fc40ac5 100644 --- a/src/ac.c +++ b/src/ac.c @@ -21,8 +21,11 @@ * */ +#include +#include + #include "config.h" -#include "ch.h" + #include "gnuk.h" #include "sha256.h" #include "random.h" diff --git a/src/adc.h b/src/adc.h index 366f22e..2ed9bf6 100644 --- a/src/adc.h +++ b/src/adc.h @@ -1,5 +1,7 @@ -#define ADC_DATA_AVAILABLE ((eventmask_t)1) -extern Thread *rng_thread; +extern chopstx_mutex_t adc_mtx; +extern chopstx_cond_t adc_cond; +extern int adc_waiting; +extern int adc_data_available; void adc_init (void); void adc_start (void); diff --git a/src/adc_stm32f103.c b/src/adc_stm32f103.c index 8566968..88480de 100644 --- a/src/adc_stm32f103.c +++ b/src/adc_stm32f103.c @@ -1,7 +1,7 @@ /* * adc_stm32f103.c - ADC driver for STM32F103 * - * Copyright (C) 2011, 2012 Free Software Initiative of Japan + * Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of NeuG, a True Random Number Generator @@ -22,15 +22,17 @@ * */ -#include "ch.h" -#include "hal.h" +#include +#include +#include + #include "neug.h" +#include "stm32f103.h" #include "adc.h" #define NEUG_CRC32_COUNTS 4 #define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_ADC1_IRQ_PRIORITY 5 #define ADC_SMPR1_SMP_VREF(n) ((n) << 21) #define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18) @@ -82,6 +84,7 @@ #define NEUG_DMA_MODE_CRC32 \ ( STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY) \ | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD \ + | STM32_DMA_CR_MINC \ | STM32_DMA_CR_TCIE | STM32_DMA_CR_TEIE) #define NEUG_ADC_SETTING1_SMPR1 ADC_SMPR1_SMP_VREF(ADC_SAMPLE_VREF) \ @@ -108,8 +111,10 @@ */ void adc_init (void) { - chSysLock (); - rccEnableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE); + RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN); + RCC->APB2RSTR = (RCC_APB2RSTR_ADC1RST | RCC_APB2RSTR_ADC2RST); + RCC->APB2RSTR = 0; + ADC1->CR1 = 0; ADC1->CR2 = ADC_CR2_ADON; ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL; @@ -129,21 +134,48 @@ void adc_init (void) while ((ADC2->CR2 & ADC_CR2_CAL) != 0) ; ADC2->CR2 = 0; - rccDisableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE); - chSysUnlock (); + RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN); } -static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags); +extern uint8_t __process4_stack_base__, __process4_stack_size__; +const uint32_t __stackaddr_adc = (uint32_t)&__process4_stack_base__; +const size_t __stacksize_adc = (size_t)&__process4_stack_size__; +#define PRIO_ADC 3 + +static void adc_lld_serve_rx_interrupt (uint32_t flags); + +#define INTR_REQ_DMA1_Channel1 11 +static void * +adc_intr_thread (void *arg) +{ + chopstx_intr_t interrupt; + + (void)arg; + chopstx_claim_irq (&interrupt, INTR_REQ_DMA1_Channel1); + + while (1) + { + uint32_t flags; + + chopstx_intr_wait (&interrupt); + flags = DMA1->ISR & STM32_DMA_ISR_MASK; /* Channel 1 interrupt cause. */ + DMA1->IFCR = STM32_DMA_ISR_MASK; /* Clear interrupt of channel 1. */ + adc_lld_serve_rx_interrupt (flags); + } + + return NULL; +} + +static chopstx_t adc_thd; void adc_start (void) { - dmaStreamAllocate (NEUG_DMA_CHANNEL, STM32_ADC_ADC1_IRQ_PRIORITY, - adc_lld_serve_rx_interrupt, NULL); - dmaStreamSetPeripheral (NEUG_DMA_CHANNEL, &ADC1->DR); + /* Use DMA channel 1. */ + RCC->AHBENR |= RCC_AHBENR_DMA1EN; + DMA1_Channel1->CCR = STM32_DMA_CCR_RESET_VALUE; + DMA1->IFCR = 0xffffffff; - chSysLock (); - - rccEnableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE); + RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN); ADC1->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0 | ADC_CR1_SCAN); @@ -169,12 +201,14 @@ void adc_start (void) ADC1->CR2 = 0; #endif - chSysUnlock (); + adc_thd = chopstx_create (PRIO_ADC, __stackaddr_adc, __stacksize_adc, + adc_intr_thread, NULL); } static int adc_mode; static uint32_t *adc_ptr; static int adc_size; +static uint32_t adc_buf[64]; static void adc_start_conversion_internal (void) { @@ -202,17 +236,19 @@ void adc_start_conversion (int mode, uint32_t *p, int size) if (mode == ADC_SAMPLE_MODE) { - dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, p); - dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, size / 4); - dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_SAMPLE); - dmaStreamEnable (NEUG_DMA_CHANNEL); + DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */ + DMA1_Channel1->CMAR = (uint32_t)p; /* SetMemory0 */ + DMA1_Channel1->CNDTR = (uint32_t)size / 4; /* counter */ + DMA1_Channel1->CCR = NEUG_DMA_MODE_SAMPLE; /*mode*/ + DMA1_Channel1->CCR |= DMA_CCR1_EN; /* Enable */ } else { - dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, &CRC->DR); - dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, NEUG_CRC32_COUNTS); - dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_CRC32); - dmaStreamEnable (NEUG_DMA_CHANNEL); + DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */ + DMA1_Channel1->CMAR = (uint32_t)adc_buf; /* SetMemory0 */ + DMA1_Channel1->CNDTR = size; /* counter */ + DMA1_Channel1->CCR = NEUG_DMA_MODE_CRC32; /*mode*/ + DMA1_Channel1->CCR |= DMA_CCR1_EN; /* Enable */ } adc_start_conversion_internal (); @@ -221,7 +257,8 @@ void adc_start_conversion (int mode, uint32_t *p, int size) static void adc_stop_conversion (void) { - dmaStreamDisable (NEUG_DMA_CHANNEL); + DMA1_Channel1->CCR &= ~DMA_CCR1_EN; + #ifdef DELIBARATELY_DO_IT_WRONG_START_STOP ADC1->CR2 = 0; ADC2->CR2 = 0; @@ -239,15 +276,16 @@ void adc_stop (void) ADC2->CR1 = 0; ADC2->CR2 = 0; - dmaStreamRelease (NEUG_DMA_CHANNEL); - rccDisableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE); + RCC->AHBENR &= ~RCC_AHBENR_DMA1EN; + RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN); + + chopstx_cancel (adc_thd); + chopstx_join (adc_thd, NULL); } -static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags) +static void adc_lld_serve_rx_interrupt (uint32_t flags) { - (void)arg; - if ((flags & STM32_DMA_ISR_TEIF) != 0) /* DMA errors */ { /* Should never happened. If any, it's coding error. */ @@ -262,27 +300,23 @@ static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags) if (adc_mode != ADC_SAMPLE_MODE) { - adc_size -= 4; - *adc_ptr++ = CRC->DR; + int i; - if (adc_size > 0) + for (i = 0; i < adc_size;) { - dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, &CRC->DR); - dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, NEUG_CRC32_COUNTS); - dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_CRC32); - dmaStreamEnable (NEUG_DMA_CHANNEL); - - adc_start_conversion_internal (); + CRC->DR = adc_buf[i++]; + CRC->DR = adc_buf[i++]; + CRC->DR = adc_buf[i++]; + CRC->DR = adc_buf[i++]; + *adc_ptr++ = CRC->DR; } } - if (adc_mode == ADC_SAMPLE_MODE || adc_size <= 0) - { - chSysLockFromIsr(); - if (rng_thread) - chEvtSignalFlagsI (rng_thread, ADC_DATA_AVAILABLE); - chSysUnlockFromIsr(); - } + chopstx_mutex_lock (&adc_mtx); + adc_data_available++; + if (adc_waiting) + chopstx_cond_signal (&adc_cond); + chopstx_mutex_unlock (&adc_mtx); } } } diff --git a/src/call-ec_p256.c b/src/call-ec_p256.c index a929fb1..3cce2ae 100644 --- a/src/call-ec_p256.c +++ b/src/call-ec_p256.c @@ -28,7 +28,8 @@ #include "jpc-ac.h" #include "ec_p256.h" -#include "ch.h" +#include "config.h" + #include "gnuk.h" /* We are little endian. */ diff --git a/src/call-rsa.c b/src/call-rsa.c index 89ebf16..4d47423 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -21,9 +21,11 @@ * */ +#include +#include #include #include "config.h" -#include "ch.h" + #include "gnuk.h" #include "openpgp.h" #include "random.h" diff --git a/src/config.h.in b/src/config.h.in index cb61d1b..37fbb30 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -6,4 +6,3 @@ @PINPAD_DEFINE@ @PINPAD_MORE_DEFINE@ @CERTDO_DEFINE@ -#define FLASH_PAGE_SIZE @FLASH_PAGE_SIZE@ diff --git a/src/configure b/src/configure index a5636b7..b01f563 100755 --- a/src/configure +++ b/src/configure @@ -3,7 +3,7 @@ # # This file is *NOT* generated by GNU Autoconf, but written by NIIBE Yutaka # -# Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan +# Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan # # This file is a part of Gnuk, a GnuPG USB Token implementation. # Gnuk is free software: you can redistribute it and/or modify it @@ -86,12 +86,9 @@ Configuration: --target=TARGET specify target [OLIMEX_STM32_H103] supported targets are: OLIMEX_STM32_H103 - STM32_PRIMER2 - CQ_STARM - STBEE_MINI STM8S_DISCOVERY - STBEE FST_01 + FST_01_00 --enable-debug debug with virtual COM port [no] --enable-pinpad={cir,dial} PIN entry support [no] @@ -107,13 +104,10 @@ if test "$vidpid" = "none"; then exit 1 fi -BOARD_DIR=../boards/$target -if test -d $BOARD_DIR; then - echo "Configured for target: $target" -else - echo "Unsupported target \`$target'" >&2 - exit 1 -fi +TARGET_DEFINE="#define BOARD_$target 1" +BOARD_HEADER_FILE=board-`echo $target | tr '_[:upper:]' '-[:lower:]'`.h +echo Header file is: $BOARD_HEADER_FILE +ln -sf ../chopstx/board/$BOARD_HEADER_FILE board.h # Flash page size in byte FLASH_PAGE_SIZE=1024 @@ -172,6 +166,7 @@ else fi # --enable-pinpad option +MSC_SIZE="0" if test "$pinpad" = "no"; then PINPAD_MAKE_OPTION="# ENABLE_PINPAD=" PINPAD_DEFINE="#undef PINPAD_SUPPORT" @@ -182,6 +177,9 @@ else PINPAD_DEFINE="#define PINPAD_SUPPORT 1" PINPAD_MORE_DEFINE="#define PINPAD_${pinpad^^[a-z]}_SUPPORT 1" echo "PIN pad option enabled ($pinpad)" + if test "$pinpad" = "dnd"; then + MSC_SIZE="0x0200" + fi fi # --enable-certdo option @@ -250,7 +248,12 @@ then exit 1 fi -sed -e "s%@BOARD_DIR@%$BOARD_DIR%" \ +# Enable when you are sure that it's sys version 2.0. +# Note that Gnuk 1.0 and Neug (until 0.06) uses sys version 1.0. +# have_sys_h="-DHAVE_SYS_H" +have_sys_h="" + +sed -e "s%@HAVE_SYS_H@%$have_sys_h%" \ -e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \ -e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \ -e "s%@KEYGEN_SUPPORT@%$KEYGEN_SUPPORT%" \ @@ -260,12 +263,14 @@ if test "$certdo" = "yes"; then -e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \ -e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \ -e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \ + -e "s/@MSC_SIZE@/$MSC_SIZE/" \ < gnuk.ld.in > gnuk.ld else sed -e "/^@CERTDO_SUPPORT_START@$/,/^@CERTDO_SUPPORT_END@$/ d" \ -e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \ -e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \ -e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \ + -e "s/@MSC_SIZE@/$MSC_SIZE/" \ < gnuk.ld.in > gnuk.ld fi sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \ @@ -273,6 +278,5 @@ sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \ -e "s/@PINPAD_DEFINE@/$PINPAD_DEFINE/" \ -e "s/@PINPAD_MORE_DEFINE@/$PINPAD_MORE_DEFINE/" \ -e "s/@CERTDO_DEFINE@/$CERTDO_DEFINE/" \ - -e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \ < config.h.in > config.h exit 0 diff --git a/src/debug.c b/src/debug.c index 43978a8..2de4092 100644 --- a/src/debug.c +++ b/src/debug.c @@ -21,9 +21,10 @@ * */ -#include "config.h" -#include "ch.h" -#include "gnuk.h" +#include +#include + +extern void _write (const char *s, int len); static void put_hex (uint8_t nibble) diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..091c0c5 --- /dev/null +++ b/src/debug.h @@ -0,0 +1,9 @@ +struct stdout { + chopstx_mutex_t m; + /**/ + chopstx_mutex_t m_dev; + chopstx_cond_t cond_dev; + uint8_t connected; +}; + +extern struct stdout stdout; diff --git a/src/flash.c b/src/flash.c index bc62b9b..850b870 100644 --- a/src/flash.c +++ b/src/flash.c @@ -30,9 +30,12 @@ * page(s). */ +#include +#include + #include "config.h" -#include "ch.h" -#include "hal.h" + +#include "board.h" #include "sys.h" #include "gnuk.h" diff --git a/src/gnuk.h b/src/gnuk.h index d0c0226..9601981 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -1,31 +1,3 @@ -/* - * We declare some of libc functions here, because we will - * remove dependency on libc in future, possibly. - */ -extern size_t strlen (const char *s); -extern int strncmp(const char *s1, const char *s2, size_t n); -extern void *memcpy (void *dest, const void *src, size_t n); -extern void *memset (void *s, int c, size_t n); -extern int memcmp (const void *s1, const void *s2, size_t n); -extern void *memmove(void *dest, const void *src, size_t n); - -/* - * Debug functions - */ -extern Thread *stdout_thread; -#define EV_TX_READY ((eventmask_t)1) - -extern void put_byte (uint8_t b); -extern void put_byte_with_no_nl (uint8_t b); -extern void put_short (uint16_t x); -extern void put_word (uint32_t x); -extern void put_int (uint32_t x); -extern void put_string (const char *s); -extern void put_binary (const char *s, int len); - -extern void _write (const char *, int); - - /* * Application layer <-> CCID layer data structure */ @@ -49,9 +21,9 @@ extern struct apdu apdu; #define EV_EXEC_FINISHED ((eventmask_t)2) /* GPG Execution finished */ /* GPG thread */ -#define EV_PINPAD_INPUT_DONE ((eventmask_t)1) -#define EV_NOP ((eventmask_t)2) -#define EV_CMD_AVAILABLE ((eventmask_t)4) +#define EV_PINPAD_INPUT_DONE ((eventmask_t)1) +#define EV_EXIT ((eventmask_t)2) +#define EV_CMD_AVAILABLE ((eventmask_t)4) #define EV_VERIFY_CMD_AVAILABLE ((eventmask_t)8) #define EV_MODIFY_CMD_AVAILABLE ((eventmask_t)16) @@ -222,6 +194,18 @@ extern int gpg_change_keystring (int who_old, const uint8_t *old_ks, extern struct key_data kd[3]; #ifdef DEBUG +#define DEBUG_MORE 1 +/* + * Debug functions in debug.c + */ +extern void put_byte (uint8_t b); +extern void put_byte_with_no_nl (uint8_t b); +extern void put_short (uint16_t x); +extern void put_word (uint32_t x); +extern void put_int (uint32_t x); +extern void put_string (const char *s); +extern void put_binary (const char *s, int len); + #define DEBUG_INFO(msg) put_string (msg) #define DEBUG_WORD(w) put_word (w) #define DEBUG_SHORT(h) put_short (h) @@ -396,4 +380,4 @@ extern int pinpad_getline (int msg_code, systime_t timeout); #endif -extern uint8_t _regnual_start, __heap_end__; +extern uint8_t _regnual_start, __heap_end__[]; diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index aeeddcf..c6dce32 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -1,34 +1,14 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - --- - - A special exception to the GPL can be applied should you wish to distribute - a combined work that includes ChibiOS/RT, without being obliged to provide - the source code for any proprietary components. See the file exception.txt - for full details of how and when the exception can be applied. -*/ - /* * ST32F103 memory setup. */ -__main_stack_size__ = 0x0400; -__process_stack_size__ = 0x0400; +__main_stack_size__ = 0x0100; /* Exception handlers */ +__process0_stack_size__ = 0x0100; /* main */ +__process1_stack_size__ = 0x0140; /* ccid */ +__process2_stack_size__ = 0x0180; /* rng */ +__process3_stack_size__ = 0x0b00; /* gpg */ +__process4_stack_size__ = 0x0100; /* intr: adc dma */ +__process5_stack_size__ = 0x0100; /* intr: usb */ +__process6_stack_size__ = @MSC_SIZE@; /* msc */ MEMORY { @@ -39,7 +19,7 @@ MEMORY /* __flash_start__: flash ROM start address regardless of DFU_SUPPORT */ __flash_start__ = 0x08001000; -__flash_end__ = ORIGIN(flash) + LENGTH(flash); +__flash_end__ = ORIGIN(flash) + LENGTH(flash); __ram_start__ = ORIGIN(ram); __ram_size__ = LENGTH(ram); @@ -49,46 +29,30 @@ SECTIONS { . = 0; - .sys : ALIGN(16) SUBALIGN(16) + .sys : ALIGN(4) SUBALIGN(4) { _sys = .; KEEP(*(.vectors)) - . = ALIGN(16); - *(.sys.version) - */sys.o(.text) - */sys.o(.text.*) - */sys.o(.rodata) - */sys.o(.rodata.*) - . = ALIGN(1024); - *(.sys.0) - *(.sys.1) - *(.sys.2) + . = ALIGN(16); + *(.sys.version) + build/sys.o(.text) + build/sys.o(.text.*) + build/sys.o(.rodata) + build/sys.o(.rodata.*) + . = ALIGN(1024); + *(.sys.0) + *(.sys.1) + *(.sys.2) } > flash0 _text = .; - startup : ALIGN(16) SUBALIGN(16) + .startup : ALIGN(128) SUBALIGN(128) { - KEEP(*(vectors)) + KEEP(*(.startup.vectors)) . = ALIGN (16); } > flash =0xffffffff - constructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__init_array_end = .); - } > flash - - destructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__fini_array_start = .); - KEEP(*(.fini_array)) - KEEP(*(SORT(.fini_array.*))) - PROVIDE(__fini_array_end = .); - } > flash - .text : ALIGN(16) SUBALIGN(16) { *(.text.startup.*) @@ -120,17 +84,40 @@ SECTIONS .stacks : { + . = ALIGN(8); + __process6_stack_base__ = .; + . += __process6_stack_size__; + . = ALIGN(8); + __process6_stack_end__ = .; + __process5_stack_base__ = .; + . += __process5_stack_size__; + . = ALIGN(8); + __process5_stack_end__ = .; + __process4_stack_base__ = .; + . += __process4_stack_size__; + . = ALIGN(8); + __process4_stack_end__ = .; + __process3_stack_base__ = .; + . += __process3_stack_size__; + . = ALIGN(8); + __process3_stack_end__ = .; + __process2_stack_base__ = .; + . += __process2_stack_size__; + . = ALIGN(8); + __process2_stack_end__ = .; + __process1_stack_base__ = .; + . += __process1_stack_size__; + . = ALIGN(8); + __process1_stack_end__ = .; + __process0_stack_base__ = .; + . += __process0_stack_size__; + . = ALIGN(8); + __process0_stack_end__ = .; . = ALIGN(8); __main_stack_base__ = .; . += __main_stack_size__; . = ALIGN(8); __main_stack_end__ = .; - __process_stack_base__ = .; - __main_thread_stack_base__ = .; - . += __process_stack_size__; - . = ALIGN(8); - __process_stack_end__ = .; - __main_thread_stack_end__ = .; } > ram .data : @@ -170,8 +157,8 @@ SECTIONS { . = ALIGN (@FLASH_PAGE_SIZE@); ch_certificate_start = .; - LONG(0xffffffff); - . += 1920; + LONG(0xffffffff); + . += 1920; . = ALIGN (@FLASH_PAGE_SIZE@); } > flash =0xffffffff @CERTDO_SUPPORT_END@ @@ -179,16 +166,16 @@ SECTIONS .gnuk_flash : { . = ALIGN (@FLASH_PAGE_SIZE@); - _data_pool = .; - KEEP(*(.gnuk_data)) - . = ALIGN(@FLASH_PAGE_SIZE@); - . += @FLASH_PAGE_SIZE@; - _keystore_pool = .; - . += 512*3; - . = ALIGN(@FLASH_PAGE_SIZE@); - _updatekey_store = .; - . += 1024; - . = ALIGN(@FLASH_PAGE_SIZE@); + _data_pool = .; + KEEP(*(.gnuk_data)) + . = ALIGN(@FLASH_PAGE_SIZE@); + . += @FLASH_PAGE_SIZE@; + _keystore_pool = .; + . += 512*3; + . = ALIGN(@FLASH_PAGE_SIZE@); + _updatekey_store = .; + . += 1024; + . = ALIGN(@FLASH_PAGE_SIZE@); } > flash =0xffffffff } diff --git a/src/main.c b/src/main.c index 79cd59a..d0edfe0 100644 --- a/src/main.c +++ b/src/main.c @@ -21,141 +21,83 @@ * */ +#include +#include +#include +#include + #include "config.h" -#include "ch.h" -#include "hal.h" + #include "sys.h" #include "adc.h" #include "gnuk.h" #include "usb_lld.h" #include "usb-cdc.h" #include "random.h" +#include "stm32f103.h" #ifdef DEBUG -struct stdout { - Mutex m; - CondVar start_cnd; - CondVar finish_cnd; - const char *str; - int size; -}; +#include "debug.h" -static struct stdout stdout; +struct stdout stdout; static void stdout_init (void) { - chMtxInit (&stdout.m); - chCondInit (&stdout.start_cnd); - chCondInit (&stdout.finish_cnd); - stdout.size = 0; - stdout.str = NULL; + chopstx_mutex_init (&stdout.m); + chopstx_mutex_init (&stdout.m_dev); + chopstx_cond_init (&stdout.cond_dev); + stdout.connected = 0; } void -_write (const char *s, int size) +_write (const char *s, int len) { - if (size == 0) + int packet_len; + + if (len == 0) return; - chMtxLock (&stdout.m); - while (stdout.str) - chCondWait (&stdout.finish_cnd); - stdout.str = s; - stdout.size = size; - chCondSignal (&stdout.start_cnd); - chCondWait (&stdout.finish_cnd); - chMtxUnlock (); -} + chopstx_mutex_lock (&stdout.m); -Thread *stdout_thread; -uint32_t count_in; -uint8_t buffer_in[VIRTUAL_COM_PORT_DATA_SIZE]; + chopstx_mutex_lock (&stdout.m_dev); + if (!stdout.connected) + chopstx_cond_wait (&stdout.cond_dev, &stdout.m_dev); + chopstx_mutex_unlock (&stdout.m_dev); -static WORKING_AREA(waSTDOUTthread, 128); - -static msg_t -STDOUTthread (void *arg) -{ - (void)arg; - stdout_thread = chThdSelf (); - - again: - - while (1) + do { - if (bDeviceState == CONFIGURED) - break; + packet_len = + (len < VIRTUAL_COM_PORT_DATA_SIZE) ? len : VIRTUAL_COM_PORT_DATA_SIZE; - chThdSleepMilliseconds (100); + chopstx_mutex_lock (&stdout.m_dev); + usb_lld_write (ENDP3, s, packet_len); + chopstx_cond_wait (&stdout.cond_dev, &stdout.m_dev); + chopstx_mutex_unlock (&stdout.m_dev); + + s += packet_len; + len -= packet_len; } + /* Send a Zero-Length-Packet if the last packet is full size. */ + while (len != 0 || packet_len == VIRTUAL_COM_PORT_DATA_SIZE); - while (1) - { - const char *p; - int len; - - if (bDeviceState != CONFIGURED) - break; - - chMtxLock (&stdout.m); - if (stdout.str == NULL) - chCondWait (&stdout.start_cnd); - - p = stdout.str; - len = stdout.size; - while (1) - { - int i; - - if (len == 0) - if (count_in != VIRTUAL_COM_PORT_DATA_SIZE) - break; - - if (len < VIRTUAL_COM_PORT_DATA_SIZE) - { - for (i = 0; i < len; i++) - buffer_in[i] = p[i]; - count_in = len; - len = 0; - } - else - { - for (i = 0; i < VIRTUAL_COM_PORT_DATA_SIZE; i++) - buffer_in[i] = p[i]; - len -= VIRTUAL_COM_PORT_DATA_SIZE; - count_in = VIRTUAL_COM_PORT_DATA_SIZE; - p += count_in; - } - - chEvtClear (EV_TX_READY); - - usb_lld_write (ENDP3, buffer_in, count_in); - - chEvtWaitOne (EV_TX_READY); - } - - stdout.str = NULL; - stdout.size = 0; - chCondBroadcast (&stdout.finish_cnd); - chMtxUnlock (); - } - - goto again; - return 0; + chopstx_mutex_unlock (&stdout.m); } void EP3_IN_Callback (void) { - if (stdout_thread) - chEvtSignalFlagsI (stdout_thread, EV_TX_READY); + chopstx_mutex_lock (&stdout.m_dev); + chopstx_cond_signal (&stdout.cond_dev); + chopstx_mutex_unlock (&stdout.m_dev); } void EP5_OUT_Callback (void) { + chopstx_mutex_lock (&stdout.m_dev); usb_lld_rx_enable (ENDP5); + chopstx_mutex_unlock (&stdout.m_dev); } #else void @@ -166,18 +108,17 @@ _write (const char *s, int size) } #endif -static WORKING_AREA(waUSBthread, 128); -extern msg_t USBthread (void *arg); +extern void *USBthread (void *arg); /* * main thread does 1-bit LED display output */ -#define MAIN_TIMEOUT_INTERVAL MS2ST(5000) +#define MAIN_TIMEOUT_INTERVAL (5000*1000) -#define LED_TIMEOUT_INTERVAL MS2ST(75) -#define LED_TIMEOUT_ZERO MS2ST(25) -#define LED_TIMEOUT_ONE MS2ST(100) -#define LED_TIMEOUT_STOP MS2ST(200) +#define LED_TIMEOUT_INTERVAL (75*1000) +#define LED_TIMEOUT_ZERO (25*1000) +#define LED_TIMEOUT_ONE (100*1000) +#define LED_TIMEOUT_STOP (200*1000) /* It has two-byte prefix and content is "FSIJ-1.0.1-" (2 + 11*2). */ @@ -211,44 +152,44 @@ device_initialize_once (void) } } -static volatile uint8_t fatal_code; -static Thread *main_thread; +static volatile uint8_t fatal_code; +static struct eventflag led_event; static void display_fatal_code (void) { while (1) { set_led (1); - chThdSleep (LED_TIMEOUT_ZERO); + chopstx_usec_wait (LED_TIMEOUT_ZERO); set_led (0); - chThdSleep (LED_TIMEOUT_INTERVAL); + chopstx_usec_wait (LED_TIMEOUT_INTERVAL); set_led (1); - chThdSleep (LED_TIMEOUT_ZERO); + chopstx_usec_wait (LED_TIMEOUT_ZERO); set_led (0); - chThdSleep (LED_TIMEOUT_INTERVAL); + chopstx_usec_wait (LED_TIMEOUT_INTERVAL); set_led (1); - chThdSleep (LED_TIMEOUT_ZERO); + chopstx_usec_wait (LED_TIMEOUT_ZERO); set_led (0); - chThdSleep (LED_TIMEOUT_STOP); + chopstx_usec_wait (LED_TIMEOUT_STOP); set_led (1); if (fatal_code & 1) - chThdSleep (LED_TIMEOUT_ONE); + chopstx_usec_wait (LED_TIMEOUT_ONE); else - chThdSleep (LED_TIMEOUT_ZERO); + chopstx_usec_wait (LED_TIMEOUT_ZERO); set_led (0); - chThdSleep (LED_TIMEOUT_INTERVAL); + chopstx_usec_wait (LED_TIMEOUT_INTERVAL); set_led (1); if (fatal_code & 2) - chThdSleep (LED_TIMEOUT_ONE); + chopstx_usec_wait (LED_TIMEOUT_ONE); else - chThdSleep (LED_TIMEOUT_ZERO); + chopstx_usec_wait (LED_TIMEOUT_ZERO); set_led (0); - chThdSleep (LED_TIMEOUT_INTERVAL); + chopstx_usec_wait (LED_TIMEOUT_INTERVAL); set_led (1); - chThdSleep (LED_TIMEOUT_STOP); + chopstx_usec_wait (LED_TIMEOUT_STOP); set_led (0); - chThdSleep (LED_TIMEOUT_INTERVAL*10); + chopstx_usec_wait (LED_TIMEOUT_INTERVAL*10); } } @@ -259,10 +200,10 @@ static eventmask_t emit_led (int on_time, int off_time) eventmask_t m; set_led (!led_inverted); - m = chEvtWaitOneTimeout (ALL_EVENTS, on_time); + m = eventflag_wait_timeout (&led_event, on_time); set_led (led_inverted); if (m) return m; - if ((m = chEvtWaitOneTimeout (ALL_EVENTS, off_time))) + if ((m = eventflag_wait_timeout (&led_event, off_time))) return m; return 0; } @@ -297,12 +238,12 @@ static eventmask_t display_status_code (void) if (icc_state == ICC_STATE_WAIT) { - if ((m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_STOP * 2))) + if ((m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_STOP * 2))) return m; } else { - if ((m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL))) + if ((m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_INTERVAL))) return m; if ((m = emit_led (icc_state == ICC_STATE_RECEIVE? @@ -318,7 +259,7 @@ static eventmask_t display_status_code (void) void led_blink (int spec) { - chEvtSignalFlags (main_thread, spec); + eventflag_signal (&led_event, spec); } /* @@ -338,6 +279,22 @@ calculate_regnual_entry_address (const uint8_t *addr) return v; } +extern uint8_t __process1_stack_base__, __process1_stack_size__; +extern uint8_t __process5_stack_base__, __process5_stack_size__; + +const uint32_t __stackaddr_ccid = (uint32_t)&__process1_stack_base__; +const size_t __stacksize_ccid = (size_t)&__process1_stack_size__; + +const uint32_t __stackaddr_usb = (uint32_t)&__process5_stack_base__; +const size_t __stacksize_usb = (size_t)&__process5_stack_size__; + +#define PRIO_CCID 2 +#define PRIO_USB 4 + +extern void *usb_intr (void *arg); + +static void gnuk_malloc_init (void); + /* * Entry point. @@ -350,48 +307,45 @@ main (int argc, char *argv[]) { unsigned int count = 0; uint32_t entry; + chopstx_t usb_thd; + chopstx_t ccid_thd; (void)argc; (void)argv; + gnuk_malloc_init (); + flash_unlock (); device_initialize_once (); - halInit (); adc_init (); - chSysInit (); - main_thread = chThdSelf (); + eventflag_init (&led_event, chopstx_main); - usb_lld_init (usb_initial_feature); random_init (); +#ifdef DEBUG + stdout_init (); +#endif + + ccid_thd = chopstx_create (PRIO_CCID, __stackaddr_ccid, + __stacksize_ccid, USBthread, NULL); + + usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb, + usb_intr, NULL); + +#ifdef PINPAD_DND_SUPPORT + msc_init (); +#endif + while (1) { if (bDeviceState != UNCONNECTED) break; - chThdSleepMilliseconds (250); + chopstx_usec_wait (250*1000); } -#ifdef DEBUG - stdout_init (); - - /* - * Creates 'stdout' thread. - */ - chThdCreateStatic (waSTDOUTthread, sizeof(waSTDOUTthread), - NORMALPRIO, STDOUTthread, NULL); -#endif - - chThdCreateStatic (waUSBthread, sizeof(waUSBthread), - NORMALPRIO, USBthread, NULL); - -#ifdef PINPAD_DND_SUPPORT - msc_init (); -#endif - - while (1) { eventmask_t m; @@ -399,17 +353,17 @@ main (int argc, char *argv[]) if (icc_state_p != NULL && *icc_state_p == ICC_STATE_EXEC_REQUESTED) break; - m = chEvtWaitOneTimeout (ALL_EVENTS, MAIN_TIMEOUT_INTERVAL); + m = eventflag_wait_timeout (&led_event, MAIN_TIMEOUT_INTERVAL); got_it: count++; switch (m) { case LED_ONESHOT: - if ((m = emit_led (MS2ST (100), MAIN_TIMEOUT_INTERVAL))) goto got_it; + if ((m = emit_led (100*1000, MAIN_TIMEOUT_INTERVAL))) goto got_it; break; case LED_TWOSHOTS: - if ((m = emit_led (MS2ST (50), MS2ST (50)))) goto got_it; - if ((m = emit_led (MS2ST (50), MAIN_TIMEOUT_INTERVAL))) goto got_it; + if ((m = emit_led (50*1000, 50*1000))) goto got_it; + if ((m = emit_led (50*1000, MAIN_TIMEOUT_INTERVAL))) goto got_it; break; case LED_SHOW_STATUS: if ((count & 0x07) != 0) continue; /* Display once for eight times */ @@ -420,7 +374,7 @@ main (int argc, char *argv[]) led_inverted = 1; break; case LED_FINISH_COMMAND: - m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_STOP); + m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_STOP); led_inverted = 0; set_led (0); if (m) @@ -436,12 +390,12 @@ main (int argc, char *argv[]) } #ifdef DEBUG_MORE - if (bDeviceState == CONFIGURED && (count % 10) == 0) + if (stdout.connected && (count % 10) == 0) { DEBUG_SHORT (count / 10); - _write ("\r\nThis is ChibiOS 2.0.8 on STM32.\r\n" + _write ("\r\nThis is Gnuk on STM32F103.\r\n" "Testing USB driver.\n\n" - "Hello world\r\n\r\n", 35+21+15); + "Hello world\r\n\r\n", 30+21+15); } #endif } @@ -450,10 +404,13 @@ main (int argc, char *argv[]) set_led (1); usb_lld_shutdown (); - /* Disable SysTick */ - SysTick->CTRL = 0; - /* Disable all interrupts */ - port_disable (); + + /* Finish application. */ + chopstx_join (ccid_thd, NULL); + + chopstx_cancel (usb_thd); + chopstx_join (usb_thd, NULL); + /* Set vector */ SCB->VTOR = (uint32_t)&_regnual_start; entry = calculate_regnual_entry_address (&_regnual_start); @@ -491,7 +448,115 @@ void fatal (uint8_t code) { fatal_code = code; - chEvtSignalFlags (main_thread, LED_FATAL); + eventflag_signal (&led_event, LED_FATAL); _write ("fatal\r\n", 7); for (;;); } + + +extern uint8_t __heap_base__[]; +extern uint8_t __heap_end__[]; + +#define MEMORY_END (__heap_end__) +#define ALIGN_TO_WORD(n) ((n + 3) & ~3) + +static uint8_t *heap_p; +static chopstx_mutex_t malloc_mtx; + +/* + * Assume the size of heap is less than 64KiB - 1. + */ +struct mem_head { + uint16_t next_mem_offset; /* pointer to next. */ + uint16_t size; +} __attribute__((packed)); + +static uint16_t free_mem_offset; +#define FREE_MEM_NONE (0xffff) + +static void +gnuk_malloc_init (void) +{ + chopstx_mutex_init (&malloc_mtx); + heap_p = __heap_base__; + free_mem_offset = FREE_MEM_NONE; +} + +static +void *sbrk (size_t size) +{ + void *p = (void *)heap_p; + + if ((size_t)(__heap_end__ - heap_p) < size) + return NULL; + + heap_p += size; + return p; +} + +void * +gnuk_malloc (size_t size) +{ + struct mem_head *m; + uint16_t mem_offset; + uint16_t *mem_offset_prev; + + size = ALIGN_TO_WORD (size); + + chopstx_mutex_lock (&malloc_mtx); + DEBUG_INFO ("malloc: "); + DEBUG_SHORT (size); + mem_offset_prev = &free_mem_offset; + mem_offset = free_mem_offset; + + while (1) + { + if (mem_offset == FREE_MEM_NONE) + { + m = sbrk (size + sizeof (struct mem_head)); + if (m) + { + m->next_mem_offset = FREE_MEM_NONE; + m->size = size; + } + break; + } + + m = (struct mem_head *)(__heap_base__ + mem_offset); + if (m->size >= size) + { + *mem_offset_prev = m->next_mem_offset; + m->next_mem_offset = FREE_MEM_NONE; + break; + } + + mem_offset_prev = &m->next_mem_offset; + mem_offset = m->next_mem_offset; + } + + chopstx_mutex_unlock (&malloc_mtx); + if (m == NULL) + { + DEBUG_WORD (0); + return m; + } + else + { + DEBUG_WORD ((uint32_t)(m+1)); + return (void *)(m + 1); + } +} + +void +gnuk_free (void *p) +{ + struct mem_head *m = ((struct mem_head *)p) - 1; + + chopstx_mutex_lock (&malloc_mtx); + DEBUG_INFO ("free: "); + DEBUG_SHORT (m->size); + DEBUG_WORD ((uint32_t)p); + m->next_mem_offset = free_mem_offset; + free_mem_offset = (uint16_t)((uint8_t *)m - __heap_base__); + chopstx_mutex_unlock (&malloc_mtx); +} diff --git a/src/neug.c b/src/neug.c index 91636ca..7e8065f 100644 --- a/src/neug.c +++ b/src/neug.c @@ -1,7 +1,7 @@ /* * neug.c - random number generation (from NeuG/src/random.c) * - * Copyright (C) 2011, 2012 Free Software Initiative of Japan + * Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of NeuG, a True Random Number Generator @@ -22,18 +22,20 @@ * */ -#include /* for memcpy */ -#include "config.h" +#include +#include +#include -#include "ch.h" -#include "hal.h" #include "sys.h" #include "neug.h" +#include "stm32f103.h" #include "adc.h" #include "sha256.h" -Thread *rng_thread; -#define ADC_DATA_AVAILABLE ((eventmask_t)1) +chopstx_mutex_t adc_mtx; +chopstx_cond_t adc_cond; +int adc_waiting; +int adc_data_available; static uint32_t adc_buf[SHA256_BLOCK_SIZE/sizeof (uint32_t)]; @@ -95,7 +97,8 @@ static void ep_fill_initial_string (void) static void ep_init (int mode) { - chEvtClearFlags (ADC_DATA_AVAILABLE); + adc_data_available = 0; + if (mode == NEUG_MODE_RAW) { ep_round = EP_ROUND_RAW; @@ -356,9 +359,9 @@ static void noise_source_continuous_test (uint8_t noise) */ struct rng_rb { uint32_t *buf; - Mutex m; - CondVar data_available; - CondVar space_available; + chopstx_mutex_t m; + chopstx_cond_t data_available; + chopstx_cond_t space_available; uint8_t head, tail; uint8_t size; unsigned int full :1; @@ -369,9 +372,9 @@ static void rb_init (struct rng_rb *rb, uint32_t *p, uint8_t size) { rb->buf = p; rb->size = size; - chMtxInit (&rb->m); - chCondInit (&rb->data_available); - chCondInit (&rb->space_available); + chopstx_mutex_init (&rb->m); + chopstx_cond_init (&rb->data_available); + chopstx_cond_init (&rb->space_available); rb->head = rb->tail = 0; rb->full = 0; rb->empty = 1; @@ -401,27 +404,41 @@ static uint32_t rb_del (struct rng_rb *rb) } uint8_t neug_mode; +static int rng_should_terminate; +static chopstx_t rng_thread; + /** * @brief Random number generation thread. */ -static msg_t rng (void *arg) +static void * +rng (void *arg) { struct rng_rb *rb = (struct rng_rb *)arg; - rng_thread = chThdSelf (); + rng_should_terminate = 0; + chopstx_mutex_init (&adc_mtx); + chopstx_cond_init (&adc_cond); /* Enable ADCs */ adc_start (); ep_init (NEUG_MODE_CONDITIONED); - while (!chThdShouldTerminate ()) + while (!rng_should_terminate) { int n; int mode = neug_mode; - chEvtWaitOne (ADC_DATA_AVAILABLE); /* Get ADC sampling. */ + chopstx_mutex_lock (&adc_mtx); + if (!adc_data_available) + { + adc_waiting = 1; + chopstx_cond_wait (&adc_cond, &adc_mtx); + adc_waiting = 0; + } + adc_data_available = 0; + chopstx_mutex_unlock (&adc_mtx); if ((n = ep_process (mode))) { @@ -438,9 +455,9 @@ static msg_t rng (void *arg) vp = ep_output (mode); - chMtxLock (&rb->m); + chopstx_mutex_lock (&rb->m); while (rb->full) - chCondWait (&rb->space_available); + chopstx_cond_wait (&rb->space_available, &rb->m); for (i = 0; i < n; i++) { @@ -449,18 +466,22 @@ static msg_t rng (void *arg) break; } - chCondSignal (&rb->data_available); - chMtxUnlock (); + chopstx_cond_signal (&rb->data_available); + chopstx_mutex_unlock (&rb->m); } } adc_stop (); - return 0; + return NULL; } static struct rng_rb the_ring_buffer; -static WORKING_AREA(wa_rng, 256); + +extern uint8_t __process2_stack_base__, __process2_stack_size__; +const uint32_t __stackaddr_rng = (uint32_t)&__process2_stack_base__; +const size_t __stacksize_rng = (size_t)&__process2_stack_size__; +#define PRIO_RNG 2 /** * @brief Initialize NeuG. @@ -484,7 +505,9 @@ neug_init (uint32_t *buf, uint8_t size) neug_mode = NEUG_MODE_CONDITIONED; rb_init (rb, buf, size); - chThdCreateStatic (wa_rng, sizeof (wa_rng), NORMALPRIO, rng, rb); + + rng_thread = chopstx_create (PRIO_RNG, __stackaddr_rng, __stacksize_rng, + rng, rb); } /** @@ -495,11 +518,11 @@ neug_flush (void) { struct rng_rb *rb = &the_ring_buffer; - chMtxLock (&rb->m); + chopstx_mutex_lock (&rb->m); while (!rb->empty) (void)rb_del (rb); - chCondSignal (&rb->space_available); - chMtxUnlock (); + chopstx_cond_signal (&rb->space_available); + chopstx_mutex_unlock (&rb->m); } @@ -511,10 +534,10 @@ neug_kick_filling (void) { struct rng_rb *rb = &the_ring_buffer; - chMtxLock (&rb->m); + chopstx_mutex_lock (&rb->m); if (!rb->full) - chCondSignal (&rb->space_available); - chMtxUnlock (); + chopstx_cond_signal (&rb->space_available); + chopstx_mutex_unlock (&rb->m); } /** @@ -529,13 +552,13 @@ neug_get (int kick) struct rng_rb *rb = &the_ring_buffer; uint32_t v; - chMtxLock (&rb->m); + chopstx_mutex_lock (&rb->m); while (rb->empty) - chCondWait (&rb->data_available); + chopstx_cond_wait (&rb->data_available, &rb->m); v = rb_del (rb); if (kick) - chCondSignal (&rb->space_available); - chMtxUnlock (); + chopstx_cond_signal (&rb->space_available); + chopstx_mutex_unlock (&rb->m); return v; } @@ -546,15 +569,15 @@ neug_get_nonblock (uint32_t *p) struct rng_rb *rb = &the_ring_buffer; int r = 0; - chMtxLock (&rb->m); + chopstx_mutex_lock (&rb->m); if (rb->empty) { r = -1; - chCondSignal (&rb->space_available); + chopstx_cond_signal (&rb->space_available); } else *p = rb_del (rb); - chMtxUnlock (); + chopstx_mutex_unlock (&rb->m); return r; } @@ -564,7 +587,7 @@ int neug_consume_random (void (*proc) (uint32_t, int)) int i = 0; struct rng_rb *rb = &the_ring_buffer; - chMtxLock (&rb->m); + chopstx_mutex_lock (&rb->m); while (!rb->empty) { uint32_t v; @@ -573,8 +596,8 @@ int neug_consume_random (void (*proc) (uint32_t, int)) proc (v, i); i++; } - chCondSignal (&rb->space_available); - chMtxUnlock (); + chopstx_cond_signal (&rb->space_available); + chopstx_mutex_unlock (&rb->m); return i; } @@ -584,22 +607,18 @@ neug_wait_full (void) { struct rng_rb *rb = &the_ring_buffer; - chMtxLock (&rb->m); + chopstx_mutex_lock (&rb->m); while (!rb->full) - chCondWait (&rb->data_available); - chMtxUnlock (); + chopstx_cond_wait (&rb->data_available, &rb->m); + chopstx_mutex_unlock (&rb->m); } void neug_fini (void) { - if (rng_thread) - { - chThdTerminate (rng_thread); - neug_get (1); - chThdWait (rng_thread); - rng_thread = NULL; - } + rng_should_terminate = 1; + neug_get (1); + chopstx_join (rng_thread, NULL); } void @@ -610,8 +629,14 @@ neug_mode_select (uint8_t mode) neug_wait_full (); - while (rng_thread->p_state != THD_STATE_WTCOND) - chThdSleep (MS2ST (1)); + chopstx_mutex_lock (&adc_mtx); + while (adc_waiting == 0) + { + chopstx_mutex_unlock (&adc_mtx); + chopstx_usec_wait (1000); + chopstx_mutex_lock (&adc_mtx); + } + chopstx_mutex_unlock (&adc_mtx); ep_init (mode); noise_source_cnt_max_reset (); diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 426b3d0..e6e5c3b 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -22,10 +22,12 @@ * */ +#include +#include #include #include "config.h" -#include "ch.h" + #include "sys.h" #include "gnuk.h" #include "openpgp.h" diff --git a/src/openpgp.c b/src/openpgp.c index 8f5c31f..2007a2e 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -22,15 +22,21 @@ * */ +#include +#include +#include +#include + #include "config.h" -#include "ch.h" -#include "hal.h" + #include "gnuk.h" #include "sys.h" #include "openpgp.h" #include "sha256.h" #include "random.h" +static struct eventflag *openpgp_comm; + #define ADMIN_PASSWD_MINLEN 8 #define CLS(a) a.cmd_apdu_head[0] @@ -1081,7 +1087,7 @@ cmd_external_authenticate (void) return; } - chThdTerminate (chThdSelf ()); + eventflag_signal (openpgp_comm, EV_EXIT); /* signal to self. */ set_res_sw (0xff, 0xff); DEBUG_INFO ("EXTERNAL AUTHENTICATE done.\r\n"); } @@ -1161,18 +1167,17 @@ process_command_apdu (void) } } -msg_t +void * GPGthread (void *arg) { - Thread *icc_thread = (Thread *)arg; + struct eventflag *ccid_comm = (struct eventflag *)arg; + openpgp_comm = ccid_comm + 1; gpg_init (); - chEvtClearFlags (ALL_EVENTS); - - while (!chThdShouldTerminate ()) + while (1) { - eventmask_t m = chEvtWaitOne (ALL_EVENTS); + eventmask_t m = eventflag_wait (openpgp_comm); #if defined(PINPAD_SUPPORT) int len, pw_len, newpw_len; #endif @@ -1259,16 +1264,16 @@ GPGthread (void *arg) goto done; #endif } - else if (m == EV_NOP) - continue; + else if (m == EV_EXIT) + break; led_blink (LED_START_COMMAND); process_command_apdu (); led_blink (LED_FINISH_COMMAND); done: - chEvtSignalFlags (icc_thread, EV_EXEC_FINISHED); + eventflag_signal (ccid_comm, EV_EXEC_FINISHED); } gpg_fini (); - return 0; + return NULL; } diff --git a/src/random.c b/src/random.c index d2dca77..13ed2a4 100644 --- a/src/random.c +++ b/src/random.c @@ -21,8 +21,11 @@ * */ +#include +#include + #include "config.h" -#include "ch.h" + #include "gnuk.h" #include "neug.h" diff --git a/src/stdlib.h b/src/stdlib.h index c55e0ac..886794e 100644 --- a/src/stdlib.h +++ b/src/stdlib.h @@ -1,10 +1,13 @@ /* - * stdlib.h replacement, so that we can replace malloc functions + * stdlib.h replacement to replace malloc functions */ typedef unsigned int size_t; -#include "ch.h" -#include "chheap.h" -#define malloc(size) chHeapAlloc (NULL, size) -#define free(p) chHeapFree (p) +#include /* NULL */ + +#define malloc(size) gnuk_malloc (size) +#define free(p) gnuk_free (p) + +void *gnuk_malloc (size_t); +void gnuk_free (void *); diff --git a/src/stm32f103.h b/src/stm32f103.h new file mode 100644 index 0000000..a4ecaa1 --- /dev/null +++ b/src/stm32f103.h @@ -0,0 +1,204 @@ +#define PERIPH_BASE 0x40000000 +#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) +#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) + +#define RCC_APB2RSTR_ADC1RST 0x00000200 +#define RCC_APB2RSTR_ADC2RST 0x00000400 + +struct RCC { + volatile uint32_t CR; + volatile uint32_t CFGR; + volatile uint32_t CIR; + volatile uint32_t APB2RSTR; + volatile uint32_t APB1RSTR; + volatile uint32_t AHBENR; + volatile uint32_t APB2ENR; + volatile uint32_t APB1ENR; + volatile uint32_t BDCR; + volatile uint32_t CSR; +}; + +#define RCC_BASE (AHBPERIPH_BASE + 0x1000) +static struct RCC *const RCC = ((struct RCC *const)RCC_BASE); + +#define RCC_AHBENR_DMA1EN 0x00000001 +#define RCC_AHBENR_CRCEN 0x00000040 + +#define RCC_APB2ENR_ADC1EN 0x00000200 +#define RCC_APB2ENR_ADC2EN 0x00000400 + +#define CRC_CR_RESET 0x00000001 + +struct CRC { + volatile uint32_t DR; + volatile uint8_t IDR; + uint8_t RESERVED0; + uint16_t RESERVED1; + volatile uint32_t CR; +}; + +#define CRC_BASE (AHBPERIPH_BASE + 0x3000) +static struct CRC *const CRC = ((struct CRC *const)CRC_BASE); + + +struct ADC { + volatile uint32_t SR; + volatile uint32_t CR1; + volatile uint32_t CR2; + volatile uint32_t SMPR1; + volatile uint32_t SMPR2; + volatile uint32_t JOFR1; + volatile uint32_t JOFR2; + volatile uint32_t JOFR3; + volatile uint32_t JOFR4; + volatile uint32_t HTR; + volatile uint32_t LTR; + volatile uint32_t SQR1; + volatile uint32_t SQR2; + volatile uint32_t SQR3; + volatile uint32_t JSQR; + volatile uint32_t JDR1; + volatile uint32_t JDR2; + volatile uint32_t JDR3; + volatile uint32_t JDR4; + volatile uint32_t DR; +}; + +#define ADC1_BASE (APB2PERIPH_BASE + 0x2400) +#define ADC2_BASE (APB2PERIPH_BASE + 0x2800) + +static struct ADC *const ADC1 = (struct ADC *const)ADC1_BASE; +static struct ADC *const ADC2 = (struct ADC *const)ADC2_BASE; + +#define ADC_CR1_DUALMOD_0 0x00010000 +#define ADC_CR1_DUALMOD_1 0x00020000 +#define ADC_CR1_DUALMOD_2 0x00040000 +#define ADC_CR1_DUALMOD_3 0x00080000 + +#define ADC_CR1_SCAN 0x00000100 + +#define ADC_CR2_ADON 0x00000001 +#define ADC_CR2_CONT 0x00000002 +#define ADC_CR2_CAL 0x00000004 +#define ADC_CR2_RSTCAL 0x00000008 +#define ADC_CR2_DMA 0x00000100 +#define ADC_CR2_ALIGN 0x00000800 +#define ADC_CR2_EXTSEL 0x000E0000 +#define ADC_CR2_EXTSEL_0 0x00020000 +#define ADC_CR2_EXTSEL_1 0x00040000 +#define ADC_CR2_EXTSEL_2 0x00080000 +#define ADC_CR2_EXTTRIG 0x00100000 +#define ADC_CR2_SWSTART 0x00400000 +#define ADC_CR2_TSVREFE 0x00800000 + +struct DMA_Channel { + volatile uint32_t CCR; + volatile uint32_t CNDTR; + volatile uint32_t CPAR; + volatile uint32_t CMAR; +}; + +struct DMA { + volatile uint32_t ISR; + volatile uint32_t IFCR; +}; + +#define STM32_DMA_CR_MINC DMA_CCR1_MINC +#define STM32_DMA_CR_MSIZE_WORD DMA_CCR1_MSIZE_1 +#define STM32_DMA_CR_PSIZE_WORD DMA_CCR1_PSIZE_1 +#define STM32_DMA_CR_TCIE DMA_CCR1_TCIE +#define STM32_DMA_CR_TEIE DMA_CCR1_TEIE +#define STM32_DMA_CR_HTIE DMA_CCR1_HTIE +#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1 +#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1 +#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1 + +#define STM32_DMA_ISR_MASK 0x0F +#define STM32_DMA_CCR_RESET_VALUE 0x00000000 +#define STM32_DMA_CR_PL_MASK DMA_CCR1_PL +#define STM32_DMA_CR_PL(n) ((n) << 12) + +#define DMA_CCR1_EN 0x00000001 +#define DMA_CCR1_TCIE 0x00000002 +#define DMA_CCR1_HTIE 0x00000004 +#define DMA_CCR1_TEIE 0x00000008 +#define DMA_CCR1_DIR 0x00000010 +#define DMA_CCR1_CIRC 0x00000020 +#define DMA_CCR1_PINC 0x00000040 +#define DMA_CCR1_MINC 0x00000080 +#define DMA_CCR1_PSIZE 0x00000300 +#define DMA_CCR1_PSIZE_0 0x00000100 +#define DMA_CCR1_PSIZE_1 0x00000200 +#define DMA_CCR1_MSIZE 0x00000C00 +#define DMA_CCR1_MSIZE_0 0x00000400 +#define DMA_CCR1_MSIZE_1 0x00000800 +#define DMA_CCR1_PL 0x00003000 +#define DMA_CCR1_PL_0 0x00001000 +#define DMA_CCR1_PL_1 0x00002000 +#define DMA_CCR1_MEM2MEM 0x00004000 + +#define DMA_ISR_GIF1 0x00000001 +#define DMA_ISR_TCIF1 0x00000002 +#define DMA_ISR_HTIF1 0x00000004 +#define DMA_ISR_TEIF1 0x00000008 +#define DMA_ISR_GIF2 0x00000010 +#define DMA_ISR_TCIF2 0x00000020 +#define DMA_ISR_HTIF2 0x00000040 +#define DMA_ISR_TEIF2 0x00000080 +#define DMA_ISR_GIF3 0x00000100 +#define DMA_ISR_TCIF3 0x00000200 +#define DMA_ISR_HTIF3 0x00000400 +#define DMA_ISR_TEIF3 0x00000800 +#define DMA_ISR_GIF4 0x00001000 +#define DMA_ISR_TCIF4 0x00002000 +#define DMA_ISR_HTIF4 0x00004000 +#define DMA_ISR_TEIF4 0x00008000 +#define DMA_ISR_GIF5 0x00010000 +#define DMA_ISR_TCIF5 0x00020000 +#define DMA_ISR_HTIF5 0x00040000 +#define DMA_ISR_TEIF5 0x00080000 +#define DMA_ISR_GIF6 0x00100000 +#define DMA_ISR_TCIF6 0x00200000 +#define DMA_ISR_HTIF6 0x00400000 +#define DMA_ISR_TEIF6 0x00800000 +#define DMA_ISR_GIF7 0x01000000 +#define DMA_ISR_TCIF7 0x02000000 +#define DMA_ISR_HTIF7 0x04000000 +#define DMA_ISR_TEIF7 0x08000000 + +#define DMA1_BASE (AHBPERIPH_BASE + 0x0000) +static struct DMA *const DMA1 = (struct DMA *const)DMA1_BASE; + +#define DMA1_Channel1_BASE (AHBPERIPH_BASE + 0x0008) +static struct DMA_Channel *const DMA1_Channel1 = + (struct DMA_Channel *const)DMA1_Channel1_BASE; + +/* System Control Block */ +struct SCB +{ + volatile uint32_t CPUID; + volatile uint32_t ICSR; + volatile uint32_t VTOR; + volatile uint32_t AIRCR; + volatile uint32_t SCR; + volatile uint32_t CCR; + volatile uint8_t SHP[12]; + volatile uint32_t SHCSR; + volatile uint32_t CFSR; + volatile uint32_t HFSR; + volatile uint32_t DFSR; + volatile uint32_t MMFAR; + volatile uint32_t BFAR; + volatile uint32_t AFSR; + volatile uint32_t PFR[2]; + volatile uint32_t DFR; + volatile uint32_t ADR; + volatile uint32_t MMFR[4]; + volatile uint32_t ISAR[5]; + uint32_t RESERVED0[5]; + volatile uint32_t CPACR; +}; + +#define SCS_BASE 0xE000E000 +#define SCB_BASE (SCS_BASE + 0x0D00) +static struct SCB *const SCB = (struct SCB *const)SCB_BASE; diff --git a/src/sys.c b/src/sys.c index 7e70df1..36184b7 100644 --- a/src/sys.c +++ b/src/sys.c @@ -1,62 +1,330 @@ /* - * sys.c - system services at the first flash ROM blocks + * sys.c - system routines for the initial page for STM32F103. * - * Copyright (C) 2012 Free Software Initiative of Japan + * Copyright (C) 2013 Flying Stone Technology * Author: NIIBE Yutaka * - * This file is a part of Gnuk, a GnuPG USB Token implementation. - * - * Gnuk is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Gnuk is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - * License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. This file is offered as-is, + * without any warranty. * + * When the flash ROM is protected, we cannot modify the initial page. + * We put some system routines (which is useful for any program) here. */ -#include "config.h" -#include "ch.h" -#include "hal.h" +#include +#include #include "board.h" -#include "usb_lld.h" -extern uint8_t __flash_start__, __flash_end__; +#define CORTEX_PRIORITY_BITS 4 +#define CORTEX_PRIORITY_MASK(n) ((n) << (8 - CORTEX_PRIORITY_BITS)) +#define USB_LP_CAN1_RX0_IRQn 20 +#define STM32_USB_IRQ_PRIORITY 11 + + +#define STM32_SW_PLL (2 << 0) +#define STM32_PLLSRC_HSE (1 << 16) + +#define STM32_PLLXTPRE_DIV1 (0 << 17) +#define STM32_PLLXTPRE_DIV2 (1 << 17) + +#define STM32_HPRE_DIV1 (0 << 4) + +#define STM32_PPRE1_DIV2 (4 << 8) + +#define STM32_PPRE2_DIV1 (0 << 11) +#define STM32_PPRE2_DIV2 (4 << 11) + +#define STM32_ADCPRE_DIV4 (1 << 14) +#define STM32_ADCPRE_DIV6 (2 << 14) + +#define STM32_USBPRE_DIV1P5 (0 << 22) + +#define STM32_MCO_NOCLOCK (0 << 24) + +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#define STM32_ADCPRE STM32_ADCPRE_DIV6 +#define STM32_MCOSEL STM32_MCO_NOCLOCK +#define STM32_USBPRE STM32_USBPRE_DIV1P5 + +#define STM32_PLLCLKIN (STM32_HSECLK / 1) +#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) +#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) +#define STM32_SYSCLK STM32_PLLCLKOUT +#define STM32_HCLK (STM32_SYSCLK / 1) + +#define STM32_FLASHBITS 0x00000012 + +struct NVIC { + uint32_t ISER[8]; + uint32_t unused1[24]; + uint32_t ICER[8]; + uint32_t unused2[24]; + uint32_t ISPR[8]; + uint32_t unused3[24]; + uint32_t ICPR[8]; + uint32_t unused4[24]; + uint32_t IABR[8]; + uint32_t unused5[56]; + uint32_t IPR[60]; +}; + +static struct NVIC *const NVICBase = ((struct NVIC *const)0xE000E100); +#define NVIC_ISER(n) (NVICBase->ISER[n >> 5]) +#define NVIC_ICPR(n) (NVICBase->ICPR[n >> 5]) +#define NVIC_IPR(n) (NVICBase->IPR[n >> 2]) + +static void +nvic_enable_vector (uint32_t n, uint32_t prio) +{ + unsigned int sh = (n & 3) << 3; + + NVIC_IPR (n) = (NVIC_IPR(n) & ~(0xFF << sh)) | (prio << sh); + NVIC_ICPR (n) = 1 << (n & 0x1F); + NVIC_ISER (n) = 1 << (n & 0x1F); +} + + +#define PERIPH_BASE 0x40000000 +#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) +#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) + +struct RCC { + volatile uint32_t CR; + volatile uint32_t CFGR; + volatile uint32_t CIR; + volatile uint32_t APB2RSTR; + volatile uint32_t APB1RSTR; + volatile uint32_t AHBENR; + volatile uint32_t APB2ENR; + volatile uint32_t APB1ENR; + volatile uint32_t BDCR; + volatile uint32_t CSR; +}; + +#define RCC_BASE (AHBPERIPH_BASE + 0x1000) +static struct RCC *const RCC = ((struct RCC *const)RCC_BASE); + +#define RCC_APB1ENR_USBEN 0x00800000 +#define RCC_APB1RSTR_USBRST 0x00800000 + +#define RCC_CR_HSION 0x00000001 +#define RCC_CR_HSIRDY 0x00000002 +#define RCC_CR_HSITRIM 0x000000F8 +#define RCC_CR_HSEON 0x00010000 +#define RCC_CR_HSERDY 0x00020000 +#define RCC_CR_PLLON 0x01000000 +#define RCC_CR_PLLRDY 0x02000000 + +#define RCC_CFGR_SWS 0x0000000C +#define RCC_CFGR_SWS_HSI 0x00000000 + +#define RCC_AHBENR_CRCEN 0x0040 + +struct FLASH { + volatile uint32_t ACR; + volatile uint32_t KEYR; + volatile uint32_t OPTKEYR; + volatile uint32_t SR; + volatile uint32_t CR; + volatile uint32_t AR; + volatile uint32_t RESERVED; + volatile uint32_t OBR; + volatile uint32_t WRPR; +}; + +#define FLASH_R_BASE (AHBPERIPH_BASE + 0x2000) +static struct FLASH *const FLASH = ((struct FLASH *const) FLASH_R_BASE); + +static void +clock_init (void) +{ + /* HSI setup */ + RCC->CR |= RCC_CR_HSION; + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; + RCC->CFGR = 0; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; + + /* HSE setup */ + RCC->CR |= RCC_CR_HSEON; + while (!(RCC->CR & RCC_CR_HSERDY)) + ; + + /* PLL setup */ + RCC->CFGR |= STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC; + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; + + /* Clock settings */ + RCC->CFGR = STM32_MCOSEL | STM32_USBPRE | STM32_PLLMUL | STM32_PLLXTPRE + | STM32_PLLSRC | STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; + + /* Flash setup */ + FLASH->ACR = STM32_FLASHBITS; + + /* CRC */ + RCC->AHBENR |= RCC_AHBENR_CRCEN; + + /* Switching on the configured clock source. */ + RCC->CFGR |= STM32_SW; + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; +} + +#define RCC_APB2ENR_IOPAEN 0x00000004 +#define RCC_APB2RSTR_IOPARST 0x00000004 +#define RCC_APB2ENR_IOPBEN 0x00000008 +#define RCC_APB2RSTR_IOPBRST 0x00000008 +#define RCC_APB2ENR_IOPCEN 0x00000010 +#define RCC_APB2RSTR_IOPCRST 0x00000010 +#define RCC_APB2ENR_IOPDEN 0x00000020 +#define RCC_APB2RSTR_IOPDRST 0x00000020 + + +struct GPIO { + volatile uint32_t CRL; + volatile uint32_t CRH; + volatile uint32_t IDR; + volatile uint32_t ODR; + volatile uint32_t BSRR; + volatile uint32_t BRR; + volatile uint32_t LCKR; +}; + +#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) +#define GPIOA ((struct GPIO *) GPIOA_BASE) +#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) +#define GPIOB ((struct GPIO *) GPIOB_BASE) +#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) +#define GPIOC ((struct GPIO *) GPIOC_BASE) +#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400) +#define GPIOD ((struct GPIO *) GPIOD_BASE) +#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800) +#define GPIOE ((struct GPIO *) GPIOE_BASE) + +static struct GPIO *const GPIO_USB = ((struct GPIO *const) GPIO_USB_BASE); +static struct GPIO *const GPIO_LED = ((struct GPIO *const) GPIO_LED_BASE); + +static void +gpio_init (void) +{ + /* Enable GPIO clock. */ + RCC->APB2ENR |= RCC_APB2ENR_IOP_EN; + RCC->APB2RSTR = RCC_APB2RSTR_IOP_RST; + RCC->APB2RSTR = 0; + + GPIO_USB->ODR = VAL_GPIO_ODR; + GPIO_USB->CRH = VAL_GPIO_CRH; + GPIO_USB->CRL = VAL_GPIO_CRL; + +#if GPIO_USB_BASE != GPIO_LED_BASE + GPIO_LED->ODR = VAL_GPIO_LED_ODR; + GPIO_LED->CRH = VAL_GPIO_LED_CRH; + GPIO_LED->CRL = VAL_GPIO_LED_CRL; +#endif +} static void usb_cable_config (int enable) { -#if defined(SET_USB_CONDITION) - if (SET_USB_CONDITION (enable)) - palSetPad (IOPORT_USB, GPIO_USB); +#if defined(GPIO_USB_SET_TO_ENABLE) + if (enable) + GPIO_USB->BSRR = (1 << GPIO_USB_SET_TO_ENABLE); else - palClearPad (IOPORT_USB, GPIO_USB); + GPIO_USB->BRR = (1 << GPIO_USB_SET_TO_ENABLE); +#elif defined(GPIO_USB_CLEAR_TO_ENABLE) + if (enable) + GPIO_USB->BRR = (1 << GPIO_USB_CLEAR_TO_ENABLE); + else + GPIO_USB->BSRR = (1 << GPIO_USB_CLEAR_TO_ENABLE); #else (void)enable; #endif } -static void +void set_led (int on) { - if (SET_LED_CONDITION (on)) - palSetPad (IOPORT_LED, GPIO_LED); +#if defined(GPIO_LED_CLEAR_TO_EMIT) + if (on) + GPIO_LED->BRR = (1 << GPIO_LED_CLEAR_TO_EMIT); else - palClearPad (IOPORT_LED, GPIO_LED); + GPIO_LED->BSRR = (1 << GPIO_LED_CLEAR_TO_EMIT); +#else + if (on) + GPIO_LED->BSRR = (1 << GPIO_LED_SET_TO_EMIT); + else + GPIO_LED->BRR = (1 << GPIO_LED_SET_TO_EMIT); +#endif } +static void wait (int count) +{ + int i; + + for (i = 0; i < count; i++) + asm volatile ("" : : "r" (i) : "memory"); +} + +#define USB_IRQ 20 +#define USB_IRQ_PRIORITY ((11) << 4) + +static void +usb_lld_sys_shutdown (void) +{ + RCC->APB1ENR &= ~RCC_APB1ENR_USBEN; + RCC->APB1RSTR = RCC_APB1RSTR_USBRST; + usb_cable_config (0); +} + +static void +usb_lld_sys_init (void) +{ + if ((RCC->APB1ENR & RCC_APB1ENR_USBEN) + && (RCC->APB1RSTR & RCC_APB1RSTR_USBRST) == 0) + /* Make sure the device is disconnected, even after core reset. */ + { + usb_lld_sys_shutdown (); + /* Disconnect requires SE0 (>= 2.5uS). */ + wait (300); + } + + usb_cable_config (1); + RCC->APB1ENR |= RCC_APB1ENR_USBEN; + nvic_enable_vector (USB_LP_CAN1_RX0_IRQn, + CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY)); + /* + * Note that we also have other IRQ(s): + * USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous) + * USBWakeUp_IRQn (suspend/resume) + */ + RCC->APB1RSTR = RCC_APB1RSTR_USBRST; + RCC->APB1RSTR = 0; +} #define FLASH_KEY1 0x45670123UL #define FLASH_KEY2 0xCDEF89ABUL -static void +enum flash_status +{ + FLASH_BUSY = 1, + FLASH_ERROR_PG, + FLASH_ERROR_WRP, + FLASH_COMPLETE, + FLASH_TIMEOUT +}; + +static void __attribute__ ((used)) flash_unlock (void) { FLASH->KEYR = FLASH_KEY1; @@ -64,6 +332,25 @@ flash_unlock (void) } +#define intr_disable() asm volatile ("cpsid i" : : : "memory") +#define intr_enable() asm volatile ("cpsie i" : : : "memory") + +#define FLASH_SR_BSY 0x01 +#define FLASH_SR_PGERR 0x04 +#define FLASH_SR_WRPRTERR 0x10 +#define FLASH_SR_EOP 0x20 + +#define FLASH_CR_PG 0x0001 +#define FLASH_CR_PER 0x0002 +#define FLASH_CR_MER 0x0004 +#define FLASH_CR_OPTPG 0x0010 +#define FLASH_CR_OPTER 0x0020 +#define FLASH_CR_STRT 0x0040 +#define FLASH_CR_LOCK 0x0080 +#define FLASH_CR_OPTWRE 0x0200 +#define FLASH_CR_ERRIE 0x0400 +#define FLASH_CR_EOPIE 0x1000 + static int flash_wait_for_last_operation (uint32_t timeout) { @@ -90,7 +377,7 @@ flash_program_halfword (uint32_t addr, uint16_t data) status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); - port_disable (); + intr_disable (); if (status == 0) { FLASH->CR |= FLASH_CR_PG; @@ -100,7 +387,7 @@ flash_program_halfword (uint32_t addr, uint16_t data) status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); FLASH->CR &= ~FLASH_CR_PG; } - port_enable (); + intr_enable (); return status; } @@ -112,7 +399,7 @@ flash_erase_page (uint32_t addr) status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); - port_disable (); + intr_disable (); if (status == 0) { FLASH->CR |= FLASH_CR_PER; @@ -122,7 +409,7 @@ flash_erase_page (uint32_t addr) status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); FLASH->CR &= ~FLASH_CR_PER; } - port_enable (); + intr_enable (); return status; } @@ -139,6 +426,8 @@ flash_check_blank (const uint8_t *p_start, size_t size) return 1; } +extern uint8_t __flash_start__, __flash_end__; + static int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) { @@ -175,7 +464,7 @@ flash_protect (void) status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); - port_disable (); + intr_disable (); if (status == 0) { FLASH->OPTKEYR = FLASH_KEY1; @@ -187,7 +476,7 @@ flash_protect (void) status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); FLASH->CR &= ~FLASH_CR_OPTER; } - port_enable (); + intr_enable (); if (status != 0) return 0; @@ -196,7 +485,6 @@ flash_protect (void) return (option_bytes_value & 0xff) == 0xff ? 1 : 0; } - static void __attribute__((naked)) flash_erase_all_and_exec (void (*entry)(void)) { @@ -219,39 +507,32 @@ flash_erase_all_and_exec (void (*entry)(void)) for (;;); } -static void -nvic_enable_vector (uint32_t n, uint32_t prio) +struct SCB { - unsigned int sh = (n & 3) << 3; + volatile uint32_t CPUID; + volatile uint32_t ICSR; + volatile uint32_t VTOR; + volatile uint32_t AIRCR; + volatile uint32_t SCR; + volatile uint32_t CCR; + volatile uint8_t SHP[12]; + volatile uint32_t SHCSR; + volatile uint32_t CFSR; + volatile uint32_t HFSR; + volatile uint32_t DFSR; + volatile uint32_t MMFAR; + volatile uint32_t BFAR; + volatile uint32_t AFSR; + volatile uint32_t PFR[2]; + volatile uint32_t DFR; + volatile uint32_t ADR; + volatile uint32_t MMFR[4]; + volatile uint32_t ISAR[5]; +}; - NVIC_IPR (n >> 2) = (NVIC_IPR(n >> 2) & ~(0xFF << sh)) | (prio << sh); - NVIC_ICPR (n >> 5) = 1 << (n & 0x1F); - NVIC_ISER (n >> 5) = 1 << (n & 0x1F); -} - -static void -usb_lld_sys_init (void) -{ - RCC->APB1ENR |= RCC_APB1ENR_USBEN; - nvic_enable_vector (USB_LP_CAN1_RX0_IRQn, - CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY)); - /* - * Note that we also have other IRQ(s): - * USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous) - * USBWakeUp_IRQn (suspend/resume) - */ - RCC->APB1RSTR = RCC_APB1RSTR_USBRST; - RCC->APB1RSTR = 0; - - usb_cable_config (1); -} - -static void -usb_lld_sys_shutdown (void) -{ - RCC->APB1ENR &= ~RCC_APB1ENR_USBEN; - usb_cable_config (0); -} +#define SCS_BASE (0xE000E000) +#define SCB_BASE (SCS_BASE + 0x0D00) +static struct SCB *const SCB = ((struct SCB *const) SCB_BASE); #define SYSRESETREQ 0x04 static void @@ -259,11 +540,14 @@ nvic_system_reset (void) { SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SYSRESETREQ); asm volatile ("dsb"); + for (;;); } static void __attribute__ ((naked)) reset (void) { + extern const unsigned long *FT0, *FT1, *FT2; + asm volatile ("cpsid i\n\t" /* Mask all interrupts. */ "mov.w r0, #0xed00\n\t" /* r0 = SCR */ "movt r0, #0xe000\n\t" @@ -278,6 +562,11 @@ reset (void) "ldr r0, [r1]\n\t" /* Reset handler. */ "bx r0\n" : /* no output */ : /* no input */ : "memory"); + + /* Never reach here. */ + /* Artificial entry to refer FT0, FT1, and FT2. */ + asm volatile ("" + : : "r" (FT0), "r" (FT1), "r" (FT2)); } typedef void (*handler)(void); @@ -297,11 +586,14 @@ handler vector[] __attribute__ ((section(".vectors"))) = { usb_lld_sys_init, usb_lld_sys_shutdown, nvic_system_reset, + clock_init, + gpio_init, + NULL, }; const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = { 3*2+2, /* bLength */ 0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE*/ - /* sys version: "1.0" */ - '1', 0, '.', 0, '0', 0, + /* sys version: "2.0" */ + '2', 0, '.', 0, '0', 0, }; diff --git a/src/sys.h b/src/sys.h index 3884c95..25d33f1 100644 --- a/src/sys.h +++ b/src/sys.h @@ -1,7 +1,7 @@ extern const uint8_t sys_version[8]; typedef void (*handler)(void); -extern handler vector[14]; +extern handler vector[16]; static inline const uint8_t * unique_device_id (void) @@ -93,3 +93,23 @@ nvic_system_reset (void) { (*vector[12]) (); } + +/* + * Users can override INLINE by 'attribute((used))' to have an + * implementation defined. + */ +#if !defined(INLINE) +#define INLINE __inline__ +#endif + +static INLINE void +clock_init (void) +{ + (*vector[13]) (); +} + +static INLINE void +gpio_init (void) +{ + (*vector[14]) (); +} diff --git a/src/usb-icc.c b/src/usb-icc.c index ec20658..ba2bc54 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -1,7 +1,7 @@ /* - * usb-icc.c -- USB CCID/ICCD protocol handling + * usb-icc.c -- USB CCID protocol handling * - * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan + * Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -21,14 +21,18 @@ * */ +#include +#include +#include +#include + #include "config.h" -#include "ch.h" -#include "hal.h" + #include "gnuk.h" #include "usb_lld.h" /* - * USB buffer size of USB-ICC driver + * USB buffer size of USB-CCID driver */ #if MAX_RES_APDU_DATA_SIZE > MAX_CMD_APDU_DATA_SIZE #define USB_BUF_SIZE (MAX_RES_APDU_DATA_SIZE+5) @@ -189,14 +193,16 @@ struct ccid { uint8_t sw1sw2[2]; uint8_t chained_cls_ins_p1_p2[4]; - Thread *icc_thread; - Thread *application; - /* lower layer */ struct ep_out *epo; struct ep_in *epi; + /* from both layers */ + struct eventflag ccid_comm; + /* upper layer */ + struct eventflag openpgp_comm; + chopstx_t application; struct apdu *a; }; @@ -242,7 +248,7 @@ static void ccid_reset (struct ccid *c) } static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo, - struct apdu *a, Thread *t) + struct apdu *a, chopstx_t thd) { icc_state_p = &c->icc_state; @@ -257,8 +263,9 @@ static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo, memset (&c->icc_header, 0, sizeof (struct icc_header)); c->sw1sw2[0] = 0x90; c->sw1sw2[1] = 0x00; - c->icc_thread = t; - c->application = NULL; + eventflag_init (&c->ccid_comm, thd); + c->application = 0; + eventflag_init (&c->openpgp_comm, 0); c->epi = epi; c->epo = epo; c->a = a; @@ -310,7 +317,7 @@ static void notify_tx (struct ep_in *epi) struct ccid *c = (struct ccid *)epi->priv; /* The sequence of Bulk-IN transactions finished */ - chEvtSignalFlagsI (c->icc_thread, EV_TX_FINISHED); + eventflag_signal (&c->ccid_comm, EV_TX_FINISHED); } static void no_buf (struct ep_in *epi, size_t len) @@ -403,7 +410,7 @@ static void notify_icc (struct ep_out *epo) struct ccid *c = (struct ccid *)epo->priv; c->err = epo->err; - chEvtSignalFlagsI (c->icc_thread, EV_RX_DATA_READY); + eventflag_signal (&c->ccid_comm, EV_RX_DATA_READY); } static int end_icc_rx (struct ep_out *epo, size_t orig_len) @@ -617,8 +624,6 @@ static void icc_abdata (struct ep_out *epo, size_t len) static void icc_prepare_receive (struct ccid *c) { - DEBUG_INFO ("Rx ready\r\n"); - c->epo->err = 0; c->epo->buf = (uint8_t *)&c->icc_header; c->epo->buf_len = sizeof (struct icc_header); @@ -626,6 +631,7 @@ icc_prepare_receive (struct ccid *c) c->epo->next_buf = icc_abdata; c->epo->end_rx = end_icc_rx; usb_lld_rx_enable (c->epo->ep_num); + DEBUG_INFO ("Rx ready\r\n"); } /* @@ -736,8 +742,12 @@ static void icc_error (struct ccid *c, int offset) usb_lld_write (c->epi->ep_num, icc_reply, ICC_MSG_HEADER_SIZE); } -static WORKING_AREA(waGPGthread, 128*16); -extern msg_t GPGthread (void *arg); +extern void *GPGthread (void *arg); + +extern uint8_t __process3_stack_base__, __process3_stack_size__; +const uint32_t __stackaddr_gpg = (uint32_t)&__process3_stack_base__; +const size_t __stacksize_gpg = (size_t)&__process3_stack_size__; +#define PRIO_GPG 1 /* Send back ATR (Answer To Reset) */ @@ -747,10 +757,10 @@ icc_power_on (struct ccid *c) size_t size_atr = sizeof (ATR); uint8_t p[ICC_MSG_HEADER_SIZE]; - if (c->application == NULL) - c->application = chThdCreateStatic (waGPGthread, sizeof(waGPGthread), - NORMALPRIO, GPGthread, - (void *)c->icc_thread); + if (c->application == 0) + c->application = chopstx_create (PRIO_GPG, __stackaddr_gpg, + __stacksize_gpg, + GPGthread, (void *)&c->ccid_comm); p[0] = ICC_DATA_BLOCK_RET; p[1] = size_atr; @@ -812,10 +822,9 @@ icc_power_off (struct ccid *c) { if (c->application) { - chThdTerminate (c->application); - chEvtSignalFlags (c->application, EV_NOP); - chThdWait (c->application); - c->application = NULL; + eventflag_signal (&c->openpgp_comm, EV_EXIT); + chopstx_join (c->application, NULL); + c->application = 0; } c->icc_state = ICC_STATE_START; /* This status change should be here */ @@ -1138,7 +1147,7 @@ icc_handle_data (struct ccid *c) c->a->res_apdu_data_len = 0; c->a->res_apdu_data = &icc_buffer[5]; - chEvtSignalFlags (c->application, EV_CMD_AVAILABLE); + eventflag_signal (&c->openpgp_comm, EV_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } } @@ -1197,7 +1206,7 @@ icc_handle_data (struct ccid *c) c->a->res_apdu_data_len = 0; c->a->res_apdu_data = &c->p[5]; - chEvtSignalFlags (c->application, EV_VERIFY_CMD_AVAILABLE); + eventflag_signal (&c->openpgp_comm, EV_VERIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } else if (c->p[10-10] == 0x01) /* PIN Modification */ @@ -1231,7 +1240,7 @@ icc_handle_data (struct ccid *c) c->a->res_apdu_data_len = 0; c->a->res_apdu_data = &icc_buffer[5]; - chEvtSignalFlags (c->application, EV_MODIFY_CMD_AVAILABLE); + eventflag_signal (&c->openpgp_comm, EV_MODIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } else @@ -1283,36 +1292,44 @@ icc_handle_timeout (struct ccid *c) return next_state; } -#define USB_ICC_TIMEOUT MS2ST(1950) +#define USB_ICC_TIMEOUT (1950*1000) static struct ccid ccid; #define GPG_THREAD_TERMINATED 0xffff -msg_t +static void *ccid_thread (chopstx_t) __attribute__ ((noinline)); + +void * __attribute__ ((naked)) USBthread (void *arg) +{ + chopstx_t thd; + (void)arg; + + asm ("mov %0, sp" : "=r" (thd)); + return ccid_thread (thd); +} + +static void * +ccid_thread (chopstx_t thd) { struct ep_in *epi = &endpoint_in; struct ep_out *epo = &endpoint_out; struct ccid *c = &ccid; struct apdu *a = &apdu; - (void)arg; - epi_init (epi, ENDP1, notify_tx, c); epo_init (epo, ENDP1, notify_icc, c); - ccid_init (c, epi, epo, a, chThdSelf ()); + ccid_init (c, epi, epo, a, thd); apdu_init (a); - chEvtClearFlags (ALL_EVENTS); - icc_prepare_receive (c); while (1) { eventmask_t m; - m = chEvtWaitOneTimeout (ALL_EVENTS, USB_ICC_TIMEOUT); + m = eventflag_wait_timeout (&c->ccid_comm, USB_ICC_TIMEOUT); if (m == EV_RX_DATA_READY) c->icc_state = icc_handle_data (c); @@ -1373,5 +1390,5 @@ USBthread (void *arg) c->icc_state = icc_handle_timeout (c); } - return 0; + return NULL; } diff --git a/src/usb_ctrl.c b/src/usb_ctrl.c index 51a7d45..968824b 100644 --- a/src/usb_ctrl.c +++ b/src/usb_ctrl.c @@ -24,12 +24,20 @@ /* Packet size of USB Bulk transfer for full speed */ #define GNUK_MAX_PACKET_SIZE 64 +#include +#include +#include + #include "config.h" -#include "ch.h" -#include "hal.h" + +#ifdef DEBUG +#include "debug.h" +#endif + #include "usb_lld.h" #include "usb_conf.h" #include "gnuk.h" +#include "stm32f103.h" #ifdef ENABLE_VIRTUAL_COM_PORT #include "usb-cdc.h" @@ -50,7 +58,7 @@ static struct line_coding line_coding = { }; static int -vcom_port_data_setup (uint8_t req, uint8_t req_no) +vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value) { if (USB_SETUP_GET (req)) { @@ -68,8 +76,29 @@ vcom_port_data_setup (uint8_t req, uint8_t req_no) return USB_SUCCESS; } else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE) - /* Do nothing and success */ - return USB_SUCCESS; + { + uint8_t connected_saved = stdout.connected; + + if (value != 0) + { + if (stdout.connected == 0) + /* It's Open call */ + stdout.connected++; + } + else + { + if (stdout.connected) + /* Close call */ + stdout.connected = 0; + } + + chopstx_mutex_lock (&stdout.m_dev); + if (stdout.connected != connected_saved) + chopstx_cond_signal (&stdout.cond_dev); + chopstx_mutex_unlock (&stdout.m_dev); + + return USB_SUCCESS; + } } return USB_UNSUPPORT; @@ -182,7 +211,7 @@ static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */ static const uint8_t lun_table[] = { 0, 0, 0, 0, }; #endif -static const uint8_t *const mem_info[] = { &_regnual_start, &__heap_end__, }; +static const uint8_t *const mem_info[] = { &_regnual_start, __heap_end__, }; #define USB_FSIJ_GNUK_MEMINFO 0 #define USB_FSIJ_GNUK_DOWNLOAD 1 @@ -239,7 +268,7 @@ usb_cb_setup (uint8_t req, uint8_t req_no, if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) return USB_UNSUPPORT; - if (addr < &_regnual_start || addr + len > &__heap_end__) + if (addr < &_regnual_start || addr + len > __heap_end__) return USB_UNSUPPORT; if (index + len < 256) @@ -261,51 +290,53 @@ usb_cb_setup (uint8_t req, uint8_t req_no, } } else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)) - if (index == 0) - { - if (USB_SETUP_GET (req)) - { - if (req_no == USB_CCID_REQ_GET_CLOCK_FREQUENCIES) - { - usb_lld_set_data_to_send (freq_table, sizeof (freq_table)); - return USB_SUCCESS; - } - else if (req_no == USB_CCID_REQ_GET_DATA_RATES) - { - usb_lld_set_data_to_send (data_rate_table, - sizeof (data_rate_table)); - return USB_SUCCESS; - } - } - else - { - if (req_no == USB_CCID_REQ_ABORT) - /* wValue: bSeq, bSlot */ - /* Abortion is not supported in Gnuk */ - return USB_UNSUPPORT; - } - } + { + if (index == 0) + { + if (USB_SETUP_GET (req)) + { + if (req_no == USB_CCID_REQ_GET_CLOCK_FREQUENCIES) + { + usb_lld_set_data_to_send (freq_table, sizeof (freq_table)); + return USB_SUCCESS; + } + else if (req_no == USB_CCID_REQ_GET_DATA_RATES) + { + usb_lld_set_data_to_send (data_rate_table, + sizeof (data_rate_table)); + return USB_SUCCESS; + } + } + else + { + if (req_no == USB_CCID_REQ_ABORT) + /* wValue: bSeq, bSlot */ + /* Abortion is not supported in Gnuk */ + return USB_UNSUPPORT; + } + } #ifdef ENABLE_VIRTUAL_COM_PORT - else if (index == 1) - return vcom_port_data_setup (req, req_no); + else if (index == 1) + return vcom_port_data_setup (req, req_no, value); #endif #ifdef PINPAD_DND_SUPPORT - else if (index == MSC_INTERFACE_NO) - { - if (USB_SETUP_GET (req)) - { - if (req_no == MSC_GET_MAX_LUN_COMMAND) - { - usb_lld_set_data_to_send (lun_table, sizeof (lun_table)); - return USB_SUCCESS; - } - } - else - if (req_no == MSC_MASS_STORAGE_RESET_COMMAND) - /* Should call resetting MSC thread, something like msc_reset() */ - return USB_SUCCESS; - } + else if (index == MSC_INTERFACE_NO) + { + if (USB_SETUP_GET (req)) + { + if (req_no == MSC_GET_MAX_LUN_COMMAND) + { + usb_lld_set_data_to_send (lun_table, sizeof (lun_table)); + return USB_SUCCESS; + } + } + else + if (req_no == MSC_MASS_STORAGE_RESET_COMMAND) + /* Should call resetting MSC thread, something like msc_reset() */ + return USB_SUCCESS; + } #endif + } return USB_UNSUPPORT; } @@ -398,13 +429,25 @@ int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt) } -CH_IRQ_HANDLER (Vector90) -{ - CH_IRQ_PROLOGUE(); - chSysLockFromIsr(); +#define INTR_REQ_USB 20 +void * +usb_intr (void *arg) +{ + chopstx_intr_t interrupt; + + (void)arg; + usb_lld_init (usb_initial_feature); + chopstx_claim_irq (&interrupt, INTR_REQ_USB); usb_interrupt_handler (); - chSysUnlockFromIsr(); - CH_IRQ_EPILOGUE(); + while (1) + { + chopstx_intr_wait (&interrupt); + + /* Process interrupt. */ + usb_interrupt_handler (); + } + + return NULL; } diff --git a/src/usb_desc.c b/src/usb_desc.c index 482f9b5..c99b9e4 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -2,8 +2,11 @@ * usb_desc.c - USB Descriptor */ +#include +#include + #include "config.h" -#include "ch.h" + #include "sys.h" #include "usb_lld.h" #include "usb_conf.h" diff --git a/src/usb_stm32f103.c b/src/usb_stm32f103.c index 74f5acf..b75dfdb 100644 --- a/src/usb_stm32f103.c +++ b/src/usb_stm32f103.c @@ -1,9 +1,9 @@ -#ifdef FREE_STANDING -#include "types.h" -#else -#include "ch.h" -#include "hal.h" -#endif +#include +#include + +#define TRUE 1 +#define FALSE 0 + #include "sys.h" #include "usb_lld.h" @@ -83,15 +83,15 @@ static struct DATA_INFO *const data_p = &data_info; #define PMA_ADDR (0x40006000UL) /* USB_IP Packet Memory Area base address */ /* Control register */ -#define CNTR ((__IO uint16_t *)(REG_BASE + 0x40)) +#define CNTR ((volatile uint16_t *)(REG_BASE + 0x40)) /* Interrupt status register */ -#define ISTR ((__IO uint16_t *)(REG_BASE + 0x44)) +#define ISTR ((volatile uint16_t *)(REG_BASE + 0x44)) /* Frame number register */ -#define FNR ((__IO uint16_t *)(REG_BASE + 0x48)) +#define FNR ((volatile uint16_t *)(REG_BASE + 0x48)) /* Device address register */ -#define DADDR ((__IO uint16_t *)(REG_BASE + 0x4C)) +#define DADDR ((volatile uint16_t *)(REG_BASE + 0x4C)) /* Buffer Table address register */ -#define BTABLE ((__IO uint16_t *)(REG_BASE + 0x50)) +#define BTABLE ((volatile uint16_t *)(REG_BASE + 0x50)) #define ISTR_CTR (0x8000) /* Correct TRansfer (clear-only bit) */ #define ISTR_DOVR (0x4000) /* DMA OVeR/underrun (clear-only bit) */