regnual: flash write support
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 22 May 2012 08:02:54 +0000 (17:02 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 22 May 2012 08:02:54 +0000 (17:02 +0900)
regnual/regnual.c
tool/gnuk_upgrade.py

index 8611d98..21fab3f 100644 (file)
 #include "types.h"
 #include "usb_lld.h"
 
-extern void set_led (int);
 extern void *memset (void *s, int c, size_t n);
 
+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);
+extern int flash_erase_page (uint32_t addr);
+extern int flash_protect (void);
+extern void nvic_system_reset (void);
+
+
 #define ENDP0_RXADDR        (0x40)
 #define ENDP0_TXADDR        (0x80)
 
@@ -81,24 +88,24 @@ static const uint8_t regnual_string_serial[] = {
   '0', 0, '.', 0, '0', 0,
 };
 
-const struct Descriptor Device_Descriptor = {
+const struct Descriptor device_desc = {
   regnual_device_desc,
   sizeof (regnual_device_desc)
 };
 
-const struct Descriptor Config_Descriptor = {
+const struct Descriptor config_desc = {
   regnual_config_desc,
   sizeof (regnual_config_desc)
 };
 
-const struct Descriptor String_Descriptors[] = {
+const struct Descriptor string_descs[] = {
   {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))
+#define NUM_STRING_DESC (sizeof (string_descs)/sizeof (struct Descriptor))
 
 static void
 regnual_device_reset (void)
@@ -107,7 +114,7 @@ regnual_device_reset (void)
   usb_lld_set_configuration (0);
 
   /* Current Feature initialization */
-  usb_lld_set_feature (Config_Descriptor.Descriptor[7]);
+  usb_lld_set_feature (config_desc.Descriptor[7]);
 
   usb_lld_reset ();
 
@@ -124,7 +131,10 @@ regnual_device_reset (void)
 #define USB_REGNUAL_PROTECT    5
 #define USB_REGNUAL_FINISH     6
 
-static uint8_t mem[1024];
+static uint8_t mem[256];
+
+static const uint8_t *const mem_info[] = { &_flash_start,  &_flash_end, };
+
 
 static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no,
                                    uint16_t value, uint16_t index,
@@ -133,16 +143,13 @@ static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no,
   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)
+      && USB_SETUP_SET (req) && len == 0)
     {
-      (void)value; (void)index;
-      /* RESET MCU */
-    }
+      if (req_no == USB_REGNUAL_FINISH && value == 0 && index == 0)
+       nvic_system_reset ();
+    }  
 }
 
-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)
@@ -170,21 +177,38 @@ regnual_setup (uint8_t req, uint8_t req_no,
        {
          if (req_no == USB_REGNUAL_SEND)
            {
-             if (value >= 4 || value * 0x100 + index + len > 1024)
+             if (value != 0 || index + len > 256)
                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);
+             if (index != 0)
+               memset (mem, 0xff, 256);
+
+             usb_lld_set_data_to_recv (mem + index, len);
              return USB_SUCCESS;
            }
          else if (req_no == USB_REGNUAL_FLASH && len == 0)
            {
-             uint8_t *addr = (uint8_t *)(0x08000000 + value * 0x400);
+             uint32_t dst_addr = (0x08000000 + value * 0x100);
 
-             /* flash write, verify */
-             return USB_SUCCESS;
+             if (flash_write (dst_addr, mem, 256) == 0)
+               return USB_SUCCESS;
+           }
+         else if (req_no == USB_REGNUAL_ERASE && len == 0 && index == 0)
+           {
+             uint32_t dst_addr = (0x08000000 + value * 0x100);
+
+             if (flash_erase_page (dst_addr))
+               return USB_SUCCESS;
+           }
+         else if (req_no == USB_REGNUAL_PROTECT && len == 0
+                  && value == 0 && index == 0)
+           {
+             if (flash_protect ())
+               return USB_SUCCESS;
            }
+         else if (req_no == USB_REGNUAL_FINISH && len == 0
+                  && value == 0 && index == 0)
+           return USB_SUCCESS;
        }
     }
 
@@ -197,14 +221,14 @@ 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);
+      usb_lld_set_data_to_send (device_desc.Descriptor,
+                               device_desc.Descriptor_Size);
       return USB_SUCCESS;
     }
   else if (desc_type == CONFIG_DESCRIPTOR)
     {
-      usb_lld_set_data_to_send (Config_Descriptor.Descriptor,
-                               Config_Descriptor.Descriptor_Size);
+      usb_lld_set_data_to_send (config_desc.Descriptor,
+                               config_desc.Descriptor_Size);
       return USB_SUCCESS;
     }
   else if (desc_type == STRING_DESCRIPTOR)
@@ -213,8 +237,8 @@ regnual_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
 
       if (desc_index < NUM_STRING_DESC)
        {
-         usb_lld_set_data_to_send (String_Descriptors[desc_index].Descriptor,
-                           String_Descriptors[desc_index].Descriptor_Size);
+         usb_lld_set_data_to_send (string_descs[desc_index].Descriptor,
+                                   string_descs[desc_index].Descriptor_Size);
          return USB_SUCCESS;
        }
     }
index 43a53fa..52ac333 100755 (executable)
@@ -48,6 +48,59 @@ def iso7816_compose(ins, p1, p2, data):
     else:
         return pack('>BBBBB', cls, ins, p1, p2, data_len) + data
 
+class regnual:
+    def __init__(self, device):
+        self.__devhandle = device.open()
+
+    def mem_info(self):
+        mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0,
+                                          value = 0, index = 0, buffer = 8,
+                                          timeout = 10000)
+        start = ((mem[3]*256 + mem[2])*256 + mem[1])*256 + mem[0]
+        end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
+        return (start, end)
+
+    def download(self, start, data):
+        addr = start
+        addr_end = (start + len(data)) & 0xffffff00
+        i = (addr - 0x08000000) / 0x100
+        j = 0
+        print "start %08x" % addr
+        print "end   %08x" % addr_end
+        while addr < addr_end:
+            print "# %08x: %d: %d : %d" % (addr, i, j, 256)
+            self.__devhandle.controlMsg(requestType = 0x40, request = 1,
+                                        value = 0, index = 0,
+                                        buffer = data[j*256:j*256+256],
+                                        timeout = 10000)
+            print "flash"
+            self.__devhandle.controlMsg(requestType = 0x40, request = 3,
+                                        value = i, index = 0,
+                                        buffer = None,
+                                        timeout = 10000)
+            i = i+1
+            j = j+1
+            addr = addr + 256
+        residue = len(data) % 256
+        if residue != 0:
+            print "# %08x: %d : %d" % (addr, i, residue)
+            print "send"
+            self.__devhandle.controlMsg(requestType = 0x40, request = 1,
+                                        value = 0, index = 0,
+                                        buffer = data[j*256:],
+                                        timeout = 10000)
+        if (i % 4) != 0 or residue:
+            print "flash"
+            self.__devhandle.controlMsg(requestType = 0x40, request = 3,
+                                        value = i, index = 0,
+                                        buffer = None,
+                                        timeout = 10000)
+
+    def finish(self):
+        self.__devhandle.controlMsg(requestType = 0x40, request = 6,
+                                    value = 0, index = 0, buffer = None,
+                                    timeout = 10000)
+
 # This class only supports Gnuk (for now) 
 class gnuk_token:
     def __init__(self, device, configuration, interface):
@@ -80,9 +133,9 @@ class gnuk_token:
         self.__timeout = 10000
         self.__seq = 0
 
-    def stop_icc(self):
-        # XXX: need to disclaim interface and close device and re-open???
-        self.__devhandle.setConfiguration(0)
+    def stop_gnuk(self):
+        self.__devhandle.releaseInterface()
+        self.__devhandle.setConfiguration(0)
         return
 
     def mem_info(self):
@@ -237,7 +290,7 @@ def compare(data_original, data_in_device):
             raise ValueError, "verify failed at %08x" % i
         i += 1
 
-def get_device():
+def get_ccid_device():
     busses = usb.busses()
     for bus in busses:
         devices = bus.devices
@@ -251,6 +304,21 @@ def get_device():
                             return dev, config, alt
     raise ValueError, "Device not found"
 
+USB_VENDOR_FSIJ=0x234b
+USB_PRODUCT_GNUK=0x0000
+
+def get_gnuk_device():
+    busses = usb.busses()
+    for bus in busses:
+        devices = bus.devices
+        for dev in devices:
+            if dev.idVendor != USB_VENDOR_FSIJ:
+                continue
+            if dev.idProduct != USB_PRODUCT_GNUK:
+                continue
+            return dev
+    raise ValueError, "Device not found"
+
 def to_string(t):
     result = ""
     for c in t:
@@ -260,7 +328,7 @@ def to_string(t):
 def main(passwd, data_regnual, data_upgrade):
     data_regnual += pack('<i', binascii.crc32(data_regnual))
 
-    dev, config, intf = get_device()
+    dev, config, intf = get_ccid_device()
     print "Device: ", dev.filename
     print "Configuration: ", config.value
     print "Interface: ", intf.interfaceNumber
@@ -274,15 +342,27 @@ def main(passwd, data_regnual, data_upgrade):
     challenge = icc.cmd_get_challenge()
     signed = to_string(challenge)
     icc.cmd_external_authenticate(signed)
-    icc.stop_icc() # disable all interfaces but control pipe
+    icc.stop_gnuk()
     mem_info = icc.mem_info()
     print "%08x:%08x" % mem_info
     print "Downloading flash upgrade program..."
     icc.download(mem_info[0], data_regnual)
     print "Run flash upgrade program..."
     icc.execute(mem_info[1] + len(data_regnual))
+    del icc
+    icc = None
+    #
+    print "Wait 3 seconds..."
+    time.sleep(3)
     # Then, send upgrade program...
-    print "NOT YET: Downloading the program"
+    dev = get_gnuk_device()
+    print "Device: ", dev.filename
+    reg = regnual(dev)
+    mem_info = reg.mem_info()
+    print "%08x:%08x" % mem_info
+    print "Downloading the program"
+    reg.download(mem_info[0]+0x3000, data_upgrade)
+    reg.finish()
     return 0
 
 DEFAULT_PW3 = "12345678"