diff --git a/regnual/Makefile.in b/regnual/Makefile.in new file mode 100644 index 0000000..58254d8 --- /dev/null +++ b/regnual/Makefile.in @@ -0,0 +1,182 @@ +# Makefile for reGNUal + +BOARD_DIR=@BOARD_DIR@ + +############################################################################## +# Build global options +# NOTE: Can be overridden externally. +# + +# Compiler options here. +ifeq ($(USE_OPT),) + USE_OPT = -O2 -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 register caching optimization (read documentation). +ifeq ($(USE_CURRP_CACHING),) + USE_CURRP_CACHING = 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 = regnual + +# Define linker script file here +LDSCRIPT= regnual.ld + +# Imported source files +CHIBIOS = ../ChibiOS_2.0.8 +include $(CHIBIOS)/os/hal/platforms/STM32/platform.mk +include $(CHIBIOS)/os/hal/hal.mk +include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/port.mk +include $(CHIBIOS)/os/kernel/kernel.mk + +# C sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CSRC = $(PORTSRC) \ + $(KERNSRC) \ + $(HALSRC) \ + $(PLATFORMSRC) \ + $(BOARDSRC) \ + ../boards/common/hw_config.c \ + $(BOARD_DIR)/board.c \ + $(CHIBIOS)/os/various/evtimer.c \ + $(CHIBIOS)/os/various/syscalls.c \ + regnual.c usb_lld.c + +# List ASM source files here +ASMSRC = $(PORTASM) \ + $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s + +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 +CWARN = -Wall -Wextra -Wstrict-prototypes + +# Define C++ warning options here +CPPWARN = -Wall -Wextra + +# +# Compiler settings +############################################################################## + +############################################################################## +# Start of default section +# + +# List all default C defines here, like -D_DEBUG=1 +DDEFS = -DCORTEX_USE_BASEPRI=TRUE + +# 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 = + +# 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/ARM/rules.mk +MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd + +distclean: clean + -rm -f Makefile regnual.ld diff --git a/regnual/regnual.c b/regnual/regnual.c new file mode 100644 index 0000000..9f1d3f8 --- /dev/null +++ b/regnual/regnual.c @@ -0,0 +1,280 @@ +/* + * regnual.c -- Firmware installation for STM32F103 Flash ROM + * + * Copyright (C) 2012 Free Software Initiative of Japan + * 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 . + * + */ + +/* + * ReGNUal + */ + +#include "ch.h" +#include "usb_lld.h" + +extern void set_led (int); +extern void *memset (void *s, int c, size_t n); + +#define ENDP0_RXADDR (0x40) +#define ENDP0_TXADDR (0x80) + +/* USB Standard Device Descriptor */ +static const uint8_t regnual_device_desc[] = { + 18, /* bLength */ + USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */ + 0x10, 0x01, /* bcdUSB = 1.1 */ + 0xFF, /* bDeviceClass: VENDOR */ + 0x00, /* bDeviceSubClass */ + 0x00, /* bDeviceProtocol */ + 0x40, /* bMaxPacketSize0 */ +#include "usb-vid-pid-ver.c.inc" + 1, /* Index of string descriptor describing manufacturer */ + 2, /* Index of string descriptor describing product */ + 3, /* Index of string descriptor describing the device's serial number */ + 0x01 /* bNumConfigurations */ +}; + +static const uint8_t regnual_config_desc[] = { + 9, + USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */ + 9, 0, /* wTotalLength: no of returned bytes */ + 0, /* bNumInterfaces: None, but control pipe */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: None */ +#if defined(USB_SELF_POWERED) + 0xC0, /* bmAttributes: self powered */ +#else + 0x80, /* bmAttributes: bus powered */ +#endif + 50, /* MaxPower 100 mA */ +}; + +static const uint8_t regnual_string_lang_id[] = { + 4, /* bLength */ + USB_STRING_DESCRIPTOR_TYPE, + 0x09, 0x04 /* LangID = 0x0409: US-English */ +}; + +#include "usb-string-vendor-product.c.inc" + +static const uint8_t regnual_string_serial[] = { + 8*2+2, + USB_STRING_DESCRIPTOR_TYPE, + /* FSIJ-0.0 */ + 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, + '0', 0, '.', 0, '0', 0, +}; + +const struct Descriptor Device_Descriptor = { + regnual_device_desc, + sizeof (regnual_device_desc) +}; + +const struct Descriptor Config_Descriptor = { + regnual_config_desc, + sizeof (regnual_config_desc) +}; + +const struct Descriptor String_Descriptors[] = { + {regnual_string_lang_id, sizeof (regnual_string_lang_id)}, + {gnukStringVendor, sizeof (gnukStringVendor)}, + {gnukStringProduct, sizeof (gnukStringProduct)}, + {regnual_string_serial, sizeof (regnual_string_serial)}, +}; + +#define NUM_STRING_DESC (sizeof (String_Descriptors)/sizeof (struct Descriptor)) + +static void +regnual_device_init (void) +{ + usb_lld_set_configuration (0); + USB_Cable_Config (1); +} + +static void +regnual_device_reset (void) +{ + /* Set DEVICE as not configured */ + usb_lld_set_configuration (0); + + /* Current Feature initialization */ + usb_lld_set_feature (Config_Descriptor.Descriptor[7]); + + usb_lld_reset (); + + /* Initialize Endpoint 0 */ + usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, + 64); +} + +#define USB_REGNUAL_MEMINFO 0 +#define USB_REGNUAL_SEND 1 +#define USB_REGNUAL_CRC32 2 +#define USB_REGNUAL_FLASH 3 +#define USB_REGNUAL_ERASE 4 +#define USB_REGNUAL_PROTECT 5 +#define USB_REGNUAL_FINISH 6 + +static uint8_t mem[1024]; + +static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no, + uint16_t value, uint16_t index, + uint16_t len) +{ + uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); + + if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) + && USB_SETUP_SET (req) && req_no == USB_REGNUAL_FINISH && len == 0) + { + (void)value; (void)index; + /* RESET MCU */ + } +} + +extern uint8_t _flash_start, _flash_end; +static const uint8_t *const mem_info[] = { &_flash_start, &_flash_end, }; + +static int +regnual_setup (uint8_t req, uint8_t req_no, + uint16_t value, uint16_t index, uint16_t len) +{ + uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); + + if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)) + { + if (USB_SETUP_GET (req)) + { + if (req_no == USB_REGNUAL_MEMINFO) + { + usb_lld_set_data_to_send (mem_info, sizeof (mem_info)); + return USB_SUCCESS; + } + else if (req_no == USB_REGNUAL_CRC32) + { + static uint32_t crc32_check = 0; /* calculate CRC32 for mem */ + + usb_lld_set_data_to_send (&crc32_check, sizeof (uint32_t)); + return USB_SUCCESS; + } + } + else /* SETUP_SET */ + { + if (req_no == USB_REGNUAL_SEND) + { + if (value >= 4 || value * 0x100 + index + len > 1024) + return USB_UNSUPPORT; + + if (value == 0 && index == 0) + memset (mem + value * 0x100, 0xff, 1024); + usb_lld_set_data_to_recv (mem + value * 0x100 + index, len); + return USB_SUCCESS; + } + else if (req_no == USB_REGNUAL_FLASH && len == 0) + { + uint8_t *addr = (uint8_t *)(0x08000000 + value * 0x400); + + /* flash write, verify */ + return USB_SUCCESS; + } + } + } + + return USB_UNSUPPORT; +} + +static int +regnual_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value) +{ + (void)index; + if (desc_type == DEVICE_DESCRIPTOR) + { + usb_lld_set_data_to_send (Device_Descriptor.Descriptor, + Device_Descriptor.Descriptor_Size); + return USB_SUCCESS; + } + else if (desc_type == CONFIG_DESCRIPTOR) + { + usb_lld_set_data_to_send (Config_Descriptor.Descriptor, + Config_Descriptor.Descriptor_Size); + return USB_SUCCESS; + } + else if (desc_type == STRING_DESCRIPTOR) + { + uint8_t desc_index = value & 0xff; + + if (desc_index < NUM_STRING_DESC) + { + usb_lld_set_data_to_send (String_Descriptors[desc_index].Descriptor, + String_Descriptors[desc_index].Descriptor_Size); + return USB_SUCCESS; + } + } + + return USB_UNSUPPORT; +} + +static int regnual_usb_event (uint8_t event_type, uint16_t value) +{ + (void)value; + + switch (event_type) + { + case USB_EVENT_ADDRESS: + case USB_EVENT_CONFIG: + return USB_SUCCESS; + default: + break; + } + + return USB_UNSUPPORT; +} + +static int regnual_interface (uint8_t cmd, uint16_t interface, uint16_t alt) +{ + (void)cmd; (void)interface; (void)alt; + return USB_UNSUPPORT; +} + +const struct usb_device_method Device_Method = { + regnual_device_init, + regnual_device_reset, + regnual_ctrl_write_finish, + regnual_setup, + regnual_get_descriptor, + regnual_usb_event, + regnual_interface, +}; + +int +main (int argc, char *argv[]) +{ + (void)argc; (void)argv; + + set_led (0); + + usb_lld_init (); + + while (1) + { + set_led (1); + chThdSleep (MS2ST (200)); + set_led (0); + chThdSleep (MS2ST (200)); + } +} diff --git a/regnual/regnual.ld.in b/regnual/regnual.ld.in new file mode 100644 index 0000000..54aceb5 --- /dev/null +++ b/regnual/regnual.ld.in @@ -0,0 +1,98 @@ +/* + * ST32F103 memory setup. + */ +__main_stack_size__ = 0x0400; +__process_stack_size__ = 0x0200; +__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; + +MEMORY +{ + flash : org = @ORIGIN@, len = @FLASH_SIZE@k + ram0 : org = 0x20000000, len = @REGNUAL_START@ + ram1 : org = 0x20001300, len = 20k - @REGNUAL_START@ +} + +_flash_start = 0x08000000; +_flash_end = @FLASH_END@; + +__ram_start__ = ORIGIN(ram0); +__ram_size__ = 20k; +__ram_end__ = __ram_start__ + __ram_size__; + +SECTIONS +{ + . = 0; + + .bss : + { + _bss_start = .; + *(.bss) + . = ALIGN(4); + *(.bss.*) + . = ALIGN(4); + *(COMMON) + . = ALIGN(4); + _bss_end = .; + } > ram0 + + .text : ALIGN(16) SUBALIGN(16) + { + _text = .; + KEEP(*(vectors)) + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + *(.glue_7t) + *(.glue_7) + *(.gcc*) + } > ram1 + + .ctors : + { + PROVIDE(_ctors_start_ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(_ctors_end_ = .); + } > ram1 + + .dtors : + { + PROVIDE(_dtors_start_ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(_dtors_end_ = .); + } > ram1 + + .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} + + __exidx_start = .; + .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > ram1 + __exidx_end = .; + + .eh_frame_hdr : {*(.eh_frame_hdr)} + + .eh_frame : ONLY_IF_RO {*(.eh_frame)} + + . = ALIGN(4); + _etext = .; + _textdata = _etext; + + .data : + { + _data = .; + *(.data) + . = ALIGN(4); + *(.data.*) + . = ALIGN(4); + *(.ramtext) + . = ALIGN(4); + _edata = .; + } > ram1 + + PROVIDE(end = .); + _end = .; +} + +__heap_base__ = _end; +__heap_end__ = __ram_end__ - __stacks_total_size__;