2012-05-18 17:07:31 +00:00
|
|
|
/*
|
|
|
|
* regnual.c -- Firmware installation for STM32F103 Flash ROM
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Free Software Initiative of Japan
|
|
|
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
|
|
|
*
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ReGNUal
|
|
|
|
*/
|
|
|
|
|
2012-05-22 01:44:37 +00:00
|
|
|
#include "types.h"
|
2012-05-18 17:07:31 +00:00
|
|
|
#include "usb_lld.h"
|
2012-05-25 06:20:08 +00:00
|
|
|
#include "sys.h"
|
2012-05-18 17:07:31 +00:00
|
|
|
|
|
|
|
extern void *memset (void *s, int c, size_t n);
|
|
|
|
|
2012-05-22 08:02:54 +00:00
|
|
|
extern void set_led (int);
|
|
|
|
extern uint8_t _flash_start, _flash_end;
|
|
|
|
extern int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len);
|
2012-05-23 06:25:20 +00:00
|
|
|
extern int flash_protect (void);
|
2012-05-22 08:02:54 +00:00
|
|
|
extern void nvic_system_reset (void);
|
|
|
|
|
|
|
|
|
2012-05-18 17:07:31 +00:00
|
|
|
#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 */
|
2012-05-22 02:20:16 +00:00
|
|
|
#include "../src/usb-vid-pid-ver.c.inc"
|
2012-05-18 17:07:31 +00:00
|
|
|
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 */
|
|
|
|
};
|
|
|
|
|
2012-05-22 02:20:16 +00:00
|
|
|
#include "../src/usb-string-vendor-product.c.inc"
|
2012-05-18 17:07:31 +00:00
|
|
|
|
|
|
|
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,
|
|
|
|
};
|
|
|
|
|
2012-05-22 08:02:54 +00:00
|
|
|
const struct Descriptor device_desc = {
|
2012-05-18 17:07:31 +00:00
|
|
|
regnual_device_desc,
|
|
|
|
sizeof (regnual_device_desc)
|
|
|
|
};
|
|
|
|
|
2012-05-22 08:02:54 +00:00
|
|
|
const struct Descriptor config_desc = {
|
2012-05-18 17:07:31 +00:00
|
|
|
regnual_config_desc,
|
|
|
|
sizeof (regnual_config_desc)
|
|
|
|
};
|
|
|
|
|
2012-05-22 08:02:54 +00:00
|
|
|
const struct Descriptor string_descs[] = {
|
2012-05-18 17:07:31 +00:00
|
|
|
{regnual_string_lang_id, sizeof (regnual_string_lang_id)},
|
|
|
|
{gnukStringVendor, sizeof (gnukStringVendor)},
|
|
|
|
{gnukStringProduct, sizeof (gnukStringProduct)},
|
|
|
|
{regnual_string_serial, sizeof (regnual_string_serial)},
|
|
|
|
};
|
|
|
|
|
2012-05-22 08:02:54 +00:00
|
|
|
#define NUM_STRING_DESC (sizeof (string_descs)/sizeof (struct Descriptor))
|
2012-05-18 17:07:31 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
regnual_device_reset (void)
|
|
|
|
{
|
|
|
|
/* Set DEVICE as not configured */
|
|
|
|
usb_lld_set_configuration (0);
|
|
|
|
|
|
|
|
/* Current Feature initialization */
|
2012-05-22 08:02:54 +00:00
|
|
|
usb_lld_set_feature (config_desc.Descriptor[7]);
|
2012-05-18 17:07:31 +00:00
|
|
|
|
|
|
|
usb_lld_reset ();
|
|
|
|
|
|
|
|
/* Initialize Endpoint 0 */
|
|
|
|
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR,
|
|
|
|
64);
|
|
|
|
}
|
|
|
|
|
2012-05-23 03:16:31 +00:00
|
|
|
#define USB_REGNUAL_MEMINFO 0
|
|
|
|
#define USB_REGNUAL_SEND 1
|
|
|
|
#define USB_REGNUAL_RESULT 2
|
|
|
|
#define USB_REGNUAL_FLASH 3
|
|
|
|
#define USB_REGNUAL_PROTECT 4
|
|
|
|
#define USB_REGNUAL_FINISH 5
|
2012-05-18 17:07:31 +00:00
|
|
|
|
2012-05-22 08:02:54 +00:00
|
|
|
static uint8_t mem[256];
|
2012-05-23 03:16:31 +00:00
|
|
|
static uint32_t result;
|
2012-05-22 08:02:54 +00:00
|
|
|
|
|
|
|
static const uint8_t *const mem_info[] = { &_flash_start, &_flash_end, };
|
|
|
|
|
2012-05-18 17:07:31 +00:00
|
|
|
|
|
|
|
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)
|
2012-05-22 08:02:54 +00:00
|
|
|
&& USB_SETUP_SET (req) && len == 0)
|
2012-05-18 17:07:31 +00:00
|
|
|
{
|
2012-05-23 03:16:31 +00:00
|
|
|
if (req_no == USB_REGNUAL_SEND && index == 0)
|
|
|
|
{
|
|
|
|
result = 0; // calculate crc32 here!!!
|
|
|
|
}
|
|
|
|
else if (req_no == USB_REGNUAL_FLASH && index == 0)
|
|
|
|
{
|
|
|
|
uint32_t dst_addr = (0x08000000 + value * 0x100);
|
|
|
|
|
|
|
|
result = flash_write (dst_addr, mem, 256);
|
|
|
|
}
|
2012-05-23 06:25:20 +00:00
|
|
|
else if (req_no == USB_REGNUAL_PROTECT && value == 0 && index == 0)
|
|
|
|
result = flash_protect ();
|
2012-05-23 03:16:31 +00:00
|
|
|
else if (req_no == USB_REGNUAL_FINISH && value == 0 && index == 0)
|
2012-05-22 08:02:54 +00:00
|
|
|
nvic_system_reset ();
|
2012-05-23 03:16:31 +00:00
|
|
|
}
|
2012-05-18 17:07:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2012-05-23 03:16:31 +00:00
|
|
|
else if (req_no == USB_REGNUAL_RESULT)
|
2012-05-18 17:07:31 +00:00
|
|
|
{
|
2012-05-23 03:16:31 +00:00
|
|
|
usb_lld_set_data_to_send (&result, sizeof (uint32_t));
|
2012-05-18 17:07:31 +00:00
|
|
|
return USB_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else /* SETUP_SET */
|
|
|
|
{
|
|
|
|
if (req_no == USB_REGNUAL_SEND)
|
|
|
|
{
|
2012-05-22 08:02:54 +00:00
|
|
|
if (value != 0 || index + len > 256)
|
2012-05-18 17:07:31 +00:00
|
|
|
return USB_UNSUPPORT;
|
|
|
|
|
2012-05-23 03:16:31 +00:00
|
|
|
if (index + len < 256)
|
|
|
|
memset (mem + index + len, 0xff, 256 - (index + len));
|
2012-05-22 08:02:54 +00:00
|
|
|
|
|
|
|
usb_lld_set_data_to_recv (mem + index, len);
|
2012-05-18 17:07:31 +00:00
|
|
|
return USB_SUCCESS;
|
|
|
|
}
|
2012-05-23 03:16:31 +00:00
|
|
|
else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0)
|
2012-05-18 17:07:31 +00:00
|
|
|
{
|
2012-05-22 08:02:54 +00:00
|
|
|
uint32_t dst_addr = (0x08000000 + value * 0x100);
|
2012-05-18 17:07:31 +00:00
|
|
|
|
2012-05-23 03:16:31 +00:00
|
|
|
if (dst_addr + 256 <= (uint32_t)&_flash_end)
|
2012-05-22 08:02:54 +00:00
|
|
|
return USB_SUCCESS;
|
|
|
|
}
|
2012-05-23 06:25:20 +00:00
|
|
|
else if (req_no == USB_REGNUAL_PROTECT && len == 0
|
|
|
|
&& value == 0 && index == 0)
|
|
|
|
return USB_SUCCESS;
|
2012-05-22 08:02:54 +00:00
|
|
|
else if (req_no == USB_REGNUAL_FINISH && len == 0
|
|
|
|
&& value == 0 && index == 0)
|
|
|
|
return USB_SUCCESS;
|
2012-05-18 17:07:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2012-05-22 08:02:54 +00:00
|
|
|
usb_lld_set_data_to_send (device_desc.Descriptor,
|
|
|
|
device_desc.Descriptor_Size);
|
2012-05-18 17:07:31 +00:00
|
|
|
return USB_SUCCESS;
|
|
|
|
}
|
|
|
|
else if (desc_type == CONFIG_DESCRIPTOR)
|
|
|
|
{
|
2012-05-22 08:02:54 +00:00
|
|
|
usb_lld_set_data_to_send (config_desc.Descriptor,
|
|
|
|
config_desc.Descriptor_Size);
|
2012-05-18 17:07:31 +00:00
|
|
|
return USB_SUCCESS;
|
|
|
|
}
|
|
|
|
else if (desc_type == STRING_DESCRIPTOR)
|
|
|
|
{
|
|
|
|
uint8_t desc_index = value & 0xff;
|
|
|
|
|
|
|
|
if (desc_index < NUM_STRING_DESC)
|
|
|
|
{
|
2012-05-22 08:02:54 +00:00
|
|
|
usb_lld_set_data_to_send (string_descs[desc_index].Descriptor,
|
|
|
|
string_descs[desc_index].Descriptor_Size);
|
2012-05-18 17:07:31 +00:00
|
|
|
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_reset,
|
|
|
|
regnual_ctrl_write_finish,
|
|
|
|
regnual_setup,
|
|
|
|
regnual_get_descriptor,
|
|
|
|
regnual_usb_event,
|
|
|
|
regnual_interface,
|
|
|
|
};
|
|
|
|
|
2012-05-22 01:44:37 +00:00
|
|
|
static void wait (int count)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
asm volatile ("" : : "r" (i) : "memory");
|
|
|
|
}
|
|
|
|
|
|
|
|
#define WAIT 2400000
|
|
|
|
|
2012-05-18 17:07:31 +00:00
|
|
|
int
|
|
|
|
main (int argc, char *argv[])
|
|
|
|
{
|
|
|
|
(void)argc; (void)argv;
|
|
|
|
|
|
|
|
set_led (0);
|
|
|
|
|
|
|
|
usb_lld_init ();
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
set_led (1);
|
2012-05-22 01:44:37 +00:00
|
|
|
wait (WAIT);
|
2012-05-18 17:07:31 +00:00
|
|
|
set_led (0);
|
2012-05-22 01:44:37 +00:00
|
|
|
wait (WAIT);
|
2012-05-18 17:07:31 +00:00
|
|
|
}
|
|
|
|
}
|