85db14cb5c12cb6cbd5cd157c9a0d4dc831d7db2
[gnuk/gnuk.git] / regnual / regnual.c
1 /*
2  * regnual.c -- Firmware installation for STM32F103 Flash ROM
3  *
4  * Copyright (C) 2012, 2013, 2015, 2016
5  *               Free Software Initiative of Japan
6  * Author: NIIBE Yutaka <gniibe@fsij.org>
7  *
8  * This file is a part of Gnuk, a GnuPG USB Token implementation.
9  *
10  * Gnuk is free software: you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18  * License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 /*
26  * ReGNUal
27  */
28
29 #include "types.h"
30 #include "usb_lld.h"
31 #include "sys.h"
32
33 extern void *memset (void *s, int c, size_t n);
34
35 extern void set_led (int);
36 extern int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len);
37 extern int flash_protect (void);
38 extern void nvic_system_reset (void);
39
40
41 #define FLASH_START_ADDR 0x08000000 /* Fixed for all STM32F1.  */
42 #define FLASH_OFFSET     0x1000     /* First pages are not-writable.  */
43 #define FLASH_START      (FLASH_START_ADDR+FLASH_OFFSET)
44 #define FLASH_SIZE_REG   ((uint16_t *)0x1ffff7e0)
45 static uint32_t flash_end;
46
47
48 #define ENDP0_RXADDR        (0x40)
49 #define ENDP0_TXADDR        (0x80)
50
51 /* USB Standard Device Descriptor */
52 static const uint8_t regnual_device_desc[] = {
53   18,   /* bLength */
54   DEVICE_DESCRIPTOR,     /* bDescriptorType */
55   0x10, 0x01,   /* bcdUSB = 1.1 */
56   0xFF,   /* bDeviceClass: VENDOR */
57   0x00,   /* bDeviceSubClass */
58   0x00,   /* bDeviceProtocol */
59   0x40,   /* bMaxPacketSize0 */
60 #include "../src/usb-vid-pid-ver.c.inc"
61   1, /* Index of string descriptor describing manufacturer */
62   2, /* Index of string descriptor describing product */
63   3, /* Index of string descriptor describing the device's serial number */
64   0x01    /* bNumConfigurations */
65 };
66
67 #if defined(USB_SELF_POWERED)
68 #define REGNUAL_FEATURE_INIT 0xC0  /* self powered */
69 #else
70 #define REGNUAL_FEATURE_INIT 0x80  /* bus powered */
71 #endif
72
73 static const uint8_t regnual_config_desc[] = {
74   9,
75   CONFIG_DESCRIPTOR,    /* bDescriptorType: Configuration */
76   18, 0,                /* wTotalLength: no of returned bytes */
77   1,                    /* bNumInterfaces: single vendor interface */
78   0x01,                 /* bConfigurationValue: Configuration value */
79   0x00,                 /* iConfiguration: None */
80   REGNUAL_FEATURE_INIT, /* bmAttributes: bus powered */
81   50,                   /* MaxPower 100 mA */
82
83   /* Interface Descriptor */
84   9,
85   INTERFACE_DESCRIPTOR,     /* bDescriptorType: Interface */
86   0,                        /* bInterfaceNumber: Index of this interface */
87   0,                        /* Alternate setting for this interface */
88   0,                        /* bNumEndpoints: None */
89   0xFF,
90   0,
91   0,
92   0,                            /* string index for interface */
93 };
94
95 static const uint8_t regnual_string_lang_id[] = {
96   4,                            /* bLength */
97   STRING_DESCRIPTOR,
98   0x09, 0x04                    /* LangID = 0x0409: US-English */
99 };
100
101 #include "../src/usb-strings.c.inc"
102
103 static const uint8_t regnual_string_serial[] = {
104   8*2+2,
105   STRING_DESCRIPTOR,
106   /* FSIJ-0.0 */
107   'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, 
108   '0', 0, '.', 0, '0', 0,
109 };
110
111
112 void
113 usb_cb_device_reset (void)
114 {
115   usb_lld_reset (REGNUAL_FEATURE_INIT);
116
117   /* Initialize Endpoint 0 */
118   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR,
119                           64);
120 }
121
122 #define USB_REGNUAL_MEMINFO     0
123 #define USB_REGNUAL_SEND        1
124 #define USB_REGNUAL_RESULT      2
125 #define USB_REGNUAL_FLASH       3
126 #define USB_REGNUAL_PROTECT     4
127 #define USB_REGNUAL_FINISH      5
128
129 static uint32_t mem[256/4];
130 static uint32_t result;
131
132
133 static uint32_t rbit (uint32_t v)
134 {
135   uint32_t r;
136
137   asm ("rbit    %0, %1" : "=r" (r) : "r" (v));
138   return r;
139 }
140
141 static uint32_t fetch (int i)
142 {
143   uint32_t v;
144
145   v = mem[i];
146   return rbit (v);
147 }
148
149 struct CRC {
150   __IO uint32_t DR;
151   __IO uint8_t  IDR;
152   uint8_t   RESERVED0;
153   uint16_t  RESERVED1;
154   __IO uint32_t CR;
155 };
156
157 #define  CRC_CR_RESET 0x01
158 static uint32_t calc_crc32 (void)
159 {
160   struct CRC *CRC = (struct CRC *)0x40023000;
161   int i;
162
163   CRC->CR = CRC_CR_RESET;
164
165   for (i = 0; i < 256/4; i++)
166     CRC->DR = fetch (i);
167
168   return rbit (CRC->DR);
169 }
170
171
172 void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no,
173                                struct req_args *arg)
174 {
175   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
176
177   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req))
178     {
179       if (req_no == USB_REGNUAL_SEND && arg->value == 0)
180         result = calc_crc32 ();
181       else if (req_no == USB_REGNUAL_FLASH)
182         {
183           uint32_t dst_addr = (0x08000000 + arg->value * 0x100);
184
185           result = flash_write (dst_addr, (const uint8_t *)mem, 256);
186         }
187       else if (req_no == USB_REGNUAL_PROTECT && arg->value == 0)
188         result = flash_protect ();
189       else if (req_no == USB_REGNUAL_FINISH && arg->value == 0)
190         nvic_system_reset ();
191     }
192 }
193
194 int
195 usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
196 {
197   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
198
199   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT))
200     {
201       if (USB_SETUP_GET (req))
202         {
203           if (req_no == USB_REGNUAL_MEMINFO)
204             {
205               const uint8_t *mem_info[2];
206
207               mem_info[0] = (const uint8_t *)FLASH_START;
208               mem_info[1] = (const uint8_t *)flash_end;
209               return usb_lld_reply_request (mem_info, sizeof (mem_info), arg);
210             }
211           else if (req_no == USB_REGNUAL_RESULT)
212             return usb_lld_reply_request (&result, sizeof (uint32_t), arg);
213         }
214       else /* SETUP_SET */
215         {
216           if (req_no == USB_REGNUAL_SEND)
217             {
218               if (arg->value != 0 || arg->index + arg->len > 256)
219                 return USB_UNSUPPORT;
220
221               if (arg->index + arg->len < 256)
222                 memset ((uint8_t *)mem + arg->index + arg->len, 0xff,
223                         256 - (arg->index + arg->len));
224
225               usb_lld_set_data_to_recv (mem + arg->index, arg->len);
226               return USB_SUCCESS;
227             }
228           else if (req_no == USB_REGNUAL_FLASH && arg->len == 0
229                    && arg->index == 0)
230             {
231               uint32_t dst_addr = (0x08000000 + arg->value * 0x100);
232
233               if (dst_addr + 256 <= flash_end)
234                 return USB_SUCCESS;
235             }
236           else if (req_no == USB_REGNUAL_PROTECT && arg->len == 0
237                    && arg->value == 0 && arg->index == 0)
238             return USB_SUCCESS;
239           else if (req_no == USB_REGNUAL_FINISH && arg->len == 0
240                    && arg->value == 0 && arg->index == 0)
241             return USB_SUCCESS;
242         }
243     }
244
245   return USB_UNSUPPORT;
246 }
247
248 int
249 usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
250                        struct req_args *arg)
251 {
252   if (rcp != DEVICE_RECIPIENT)
253     return USB_UNSUPPORT;
254
255   if (desc_type == DEVICE_DESCRIPTOR)
256     return usb_lld_reply_request (regnual_device_desc,
257                                   sizeof (regnual_device_desc), arg);
258   else if (desc_type == CONFIG_DESCRIPTOR)
259     return usb_lld_reply_request (regnual_config_desc,
260                                      sizeof (regnual_config_desc), arg); 
261   else if (desc_type == STRING_DESCRIPTOR)
262     {
263       const uint8_t *str;
264       int size;
265
266       switch (desc_index)
267         {
268         case 0:
269           str = regnual_string_lang_id;
270           size = sizeof (regnual_string_lang_id);
271           break;
272         case 1:
273           str = gnuk_string_vendor;
274           size = sizeof (gnuk_string_vendor);
275           break;
276         case 2:
277           str = gnuk_string_product;
278           size = sizeof (gnuk_string_product);
279           break;
280         case 3:
281           str = regnual_string_serial;
282           size = sizeof (regnual_string_serial);
283           break;
284         default:
285           return USB_UNSUPPORT;
286         }
287
288       return usb_lld_reply_request (str, size, arg);
289     }
290
291   return USB_UNSUPPORT;
292 }
293
294 int usb_cb_handle_event (uint8_t event_type, uint16_t value)
295 {
296   (void)value;
297
298   switch (event_type)
299     {
300     case USB_EVENT_ADDRESS:
301     case USB_EVENT_CONFIG:
302       return USB_SUCCESS;
303     default:
304       break;
305     }
306
307   return USB_UNSUPPORT;
308 }
309
310 int usb_cb_interface (uint8_t cmd, struct req_args *arg)
311 {
312   (void)cmd; (void)arg;
313   return USB_UNSUPPORT;
314 }
315
316 void usb_cb_rx_ready (uint8_t ep_num)
317 {
318   (void)ep_num;
319 }
320
321 void usb_cb_tx_done (uint8_t ep_num)
322 {
323   (void)ep_num;
324 }
325
326 static void wait (int count)
327 {
328   int i;
329
330   for (i = 0; i < count; i++)
331     asm volatile ("" : : "r" (i) : "memory");
332 }
333
334 #define WAIT 2400000
335
336 /* NVIC: Nested Vectored Interrupt Controller.  */
337 struct NVIC {
338   volatile uint32_t ISER[8];
339   uint32_t unused1[24];
340   volatile uint32_t ICER[8];
341   uint32_t unused2[24];
342   volatile uint32_t ISPR[8];
343   uint32_t unused3[24];
344   volatile uint32_t ICPR[8];
345   uint32_t unused4[24];
346   volatile uint32_t IABR[8];
347   uint32_t unused5[56];
348   volatile uint32_t IPR[60];
349 };
350 static struct NVIC *const NVIC = (struct NVIC *const)0xE000E100;
351 #define NVIC_ISER(n)    (NVIC->ISER[n >> 5])
352
353 static void nvic_enable_intr (uint8_t irq_num)
354 {
355   NVIC_ISER (irq_num) = 1 << (irq_num & 0x1f);
356 }
357
358 #define USB_LP_CAN1_RX0_IRQn     20
359
360 int
361 main (int argc, char *argv[])
362 {
363   (void)argc; (void)argv;
364
365   set_led (0);
366
367   flash_end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
368
369   /*
370    * NVIC interrupt priority was set by Gnuk.
371    * USB interrupt is disabled by NVIC setting.
372    * We enable the interrupt again by nvic_enable_intr.
373    */
374   usb_lld_init (REGNUAL_FEATURE_INIT);
375   nvic_enable_intr (USB_LP_CAN1_RX0_IRQn);
376
377   while (1)
378     {
379       set_led (1);
380       wait (WAIT);
381       set_led (0);
382       wait (WAIT);
383     }
384 }