support reGNUal
authorNIIBE Yutaka <gniibe@fsij.org>
Wed, 19 Sep 2012 03:29:28 +0000 (12:29 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Wed, 19 Sep 2012 03:29:28 +0000 (12:29 +0900)
ChangeLog
src/main.c
src/neug.h
src/neug.ld.in
src/random.c
tool/neug_upgrade.py [new file with mode: 0755]

index b61762c..2ccd06c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2012-09-19  Niibe Yutaka  <gniibe@fsij.org>
+
+       * tool/neug_upgrade.py: New.
+
+       * src/main.c (main): Support reGNUal.
+       * src/neug.ld.in (__ram_end__): Define.
+       * src/random.c (rng): Finish upon request of termination.
+       (neug_fini): New.
+       * src/neug.h (neug_fini): New.
+
 2012-09-18  Niibe Yutaka  <gniibe@fsij.org>
 
        * src/random.c (NUM_NOISE_INPUTS, REPITITION_COUNT_TEST_CUTOFF)
index c02a678..197b177 100644 (file)
@@ -38,6 +38,8 @@
 extern void *memcpy(void *dest, const void *src, size_t n);
 extern void *memset (void *s, int c, size_t n);
 
+static Thread *main_thread = NULL;
+
 \f
 #define ENDP0_RXADDR        (0x40)
 #define ENDP0_TXADDR        (0x80)
@@ -218,19 +220,24 @@ neug_device_reset (void)
   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_RESULT     2
-#define USB_REGNUAL_FLASH      3
-#define USB_REGNUAL_PROTECT    4
-#define USB_REGNUAL_FINISH     5
+extern uint8_t _regnual_start, __heap_end__;
+
+static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
 
-static uint8_t mem[256];
-static uint32_t result;
+#define USB_FSIJ_MEMINFO  0
+#define USB_FSIJ_DOWNLOAD 1
+#define USB_FSIJ_EXEC     2
+#define USB_NEUG_EXIT   255    /* exit and receive reGNUal */
 
-extern uint8_t __flash_start__,  __flash_end__;
-static const uint8_t *const mem_info[] = { &__flash_start__,  &__flash_end__ };
+enum {
+  FSIJ_DEVICE_RUNNING = 0,
+  FSIJ_DEVICE_EXITED,
+  FSIJ_DEVICE_EXEC_REQUESTED,
+  /**/
+  FSIJ_DEVICE_NEUG_EXIT_REQUESTED = 255
+}; 
 
+static uint8_t fsij_device_state = FSIJ_DEVICE_RUNNING;
 
 static uint32_t rbit (uint32_t v)
 {
@@ -240,26 +247,23 @@ static uint32_t rbit (uint32_t v)
   return r;
 }
 
-static uint32_t fetch (int i)
-{
-  uint32_t v;
-
-  v = *(uint32_t *)(&mem[i*4]);
-  return rbit (v);
-}
-
-static uint32_t calc_crc32 (void)
+/* After calling this function, CRC module remain enabled.  */
+static int download_check_crc32 (const uint32_t *end_p)
 {
-  int i;
+  uint32_t crc32 = *end_p;
+  const uint32_t *p;
 
+  RCC->AHBENR |= RCC_AHBENR_CRCEN;
   CRC->CR = CRC_CR_RESET;
 
-  for (i = 0; i < 256/4; i++)
-    CRC->DR = fetch (i);
+  for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
+    CRC->DR = rbit (*p);
 
-  return rbit (CRC->DR);
-}
+  if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
+    return USB_SUCCESS;
 
+  return USB_UNSUPPORT;
+}
 
 static void neug_ctrl_write_finish (uint8_t req, uint8_t req_no,
                                    uint16_t value, uint16_t index,
@@ -267,22 +271,15 @@ static void neug_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))
+  if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)
+      && USB_SETUP_SET (req) && req_no == USB_FSIJ_EXEC && len == 0)
     {
-      if (req_no == USB_REGNUAL_SEND && value == 0)
-       result = calc_crc32 ();
-      else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0)
-       {
-         uint32_t dst_addr = (0x08000000 + value * 0x100);
+      if (fsij_device_state != FSIJ_DEVICE_EXITED)
+       return;
 
-         result = flash_write (dst_addr, mem, 256);
-       }
-      else if (req_no == USB_REGNUAL_PROTECT && len == 0
-              && value == 0 && index == 0)
-       result = flash_protect ();
-      else if (req_no == USB_REGNUAL_FINISH && len == 0
-              && value == 0 && index == 0)
-       nvic_system_reset ();
+      (void)value; (void)index;
+      usb_lld_prepare_shutdown (); /* No further USB communication */
+      fsij_device_state = FSIJ_DEVICE_EXEC_REQUESTED;
     }
 }
 
@@ -350,43 +347,50 @@ neug_setup (uint8_t req, uint8_t req_no,
     {
       if (USB_SETUP_GET (req))
        {
-         if (req_no == USB_REGNUAL_MEMINFO)
+         if (req_no == USB_FSIJ_MEMINFO)
            {
              usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
              return USB_SUCCESS;
            }
-         else if (req_no == USB_REGNUAL_RESULT)
-           {
-             usb_lld_set_data_to_send (&result, sizeof (uint32_t));
-             return USB_SUCCESS;
-           }
        }
       else /* SETUP_SET */
        {
-         if (req_no == USB_REGNUAL_SEND)
+         uint8_t *addr = (uint8_t *)(0x20000000 + value * 0x100 + index);
+
+         if (req_no == USB_FSIJ_DOWNLOAD)
            {
-             if (value != 0 || index + len > 256)
+             if (fsij_device_state != FSIJ_DEVICE_EXITED)
+               return USB_UNSUPPORT;
+
+             if (addr < &_regnual_start || addr + len > &__heap_end__)
                return USB_UNSUPPORT;
 
              if (index + len < 256)
-               memset (mem + index + len, 0xff, 256 - (index + len));
+               memset (addr + index + len, 0, 256 - (index + len));
 
-             usb_lld_set_data_to_recv (mem + index, len);
+             usb_lld_set_data_to_recv (addr, len);
              return USB_SUCCESS;
            }
-         else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0)
+         else if (req_no == USB_FSIJ_EXEC && len == 0)
            {
-             uint32_t dst_addr = (0x08000000 + value * 0x100);
+             if (fsij_device_state != FSIJ_DEVICE_EXITED)
+               return USB_UNSUPPORT;
+
+             if (((uint32_t)addr & 0x03))
+               return USB_UNSUPPORT;
 
-             if (dst_addr + 256 <= (uint32_t)&__flash_end__)
-               return USB_SUCCESS;
+             return download_check_crc32 ((uint32_t *)addr);
+           }
+         else if (req_no == USB_NEUG_EXIT && len == 0)
+           {
+             if (fsij_device_state != FSIJ_DEVICE_RUNNING)
+               return USB_UNSUPPORT;
+
+             fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
+             chEvtSignalFlagsI (main_thread, 1);
+             chSchReadyI (main_thread);
+             return USB_SUCCESS;
            }
-         else if (req_no == USB_REGNUAL_PROTECT && len == 0
-                  && value == 0 && index == 0)
-           return USB_SUCCESS;
-         else if (req_no == USB_REGNUAL_FINISH && len == 0
-                  && value == 0 && index == 0)
-           return USB_SUCCESS;
        }
     }
   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
@@ -556,8 +560,6 @@ static void fill_serial_no_by_unique_id (void)
     }
 }
 \f
-static Thread *main_thread = NULL;
-
 CH_IRQ_HANDLER (Vector90)
 {
   CH_IRQ_PROLOGUE();
@@ -613,6 +615,9 @@ static msg_t led_blinker (void *arg)
       eventmask_t m;
 
       m = chEvtWaitOne (ALL_EVENTS);
+      if (fsij_device_state != FSIJ_DEVICE_RUNNING)
+       break;
+
       set_led (1);
       if (m == LED_ONESHOT_SHORT)
        chThdSleep (MS2ST (100));
@@ -655,22 +660,31 @@ main (int argc, char **argv)
     {
       unsigned int count = 0;
 
+      if (fsij_device_state != FSIJ_DEVICE_RUNNING)
+       break;
+
       connected = 0;
       while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
        {
+         if (fsij_device_state != FSIJ_DEVICE_RUNNING)
+           break;
+
          (void)neug_get (NEUG_KICK_FILLING);
          if ((count & 0x000f) == 0)
            chEvtSignalFlags (led_thread, LED_ONESHOT_SHORT);
-         chThdSleep (MS2ST (25));
+         chEvtWaitOneTimeout (ALL_EVENTS, MS2ST (25));
          count++;
        }
 
     waiting_connection:
       while ((connected & 1) == 0)
        {
+         if (fsij_device_state != FSIJ_DEVICE_RUNNING)
+           break;
+
          neug_flush ();
          chEvtSignalFlags (led_thread, LED_ONESHOT_LONG);
-         chThdSleep (MS2ST (2500));
+         chEvtWaitOneTimeout (ALL_EVENTS, MS2ST (2500));
        }
 
       /* The connection opened.  */
@@ -678,6 +692,9 @@ main (int argc, char **argv)
 
       while (1)
        {
+         if (fsij_device_state != FSIJ_DEVICE_RUNNING)
+           break;
+
          if ((connected & 1) == 0)
            goto waiting_connection;
 
@@ -701,5 +718,54 @@ main (int argc, char **argv)
        }
     }
 
+  /*
+   * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED.
+   */
+  neug_fini ();
+
+  chEvtSignalFlags (led_thread, LED_ONESHOT_SHORT);
+  chThdWait (led_thread);
+
+  fsij_device_state = FSIJ_DEVICE_EXITED;
+
+  while (fsij_device_state == FSIJ_DEVICE_EXITED)
+    chThdSleep (MS2ST (500));
+
+  flash_unlock ();             /* Flash unlock should be done here */
+  set_led (1);
+  usb_lld_shutdown ();
+  /* Disable SysTick */
+  SysTick->CTRL = 0;
+  /* Disable all interrupts */
+  port_disable ();
+  /* Set vector */
+  SCB->VTOR = (uint32_t)&_regnual_start;
+#ifdef DFU_SUPPORT
+#define FLASH_SYS_START_ADDR 0x08000000
+#define FLASH_SYS_END_ADDR (0x08000000+0x1000)
+  {
+    extern uint8_t _sys;
+    uint32_t addr;
+    handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
+    void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[10];
+
+    /* Kill DFU */
+    for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
+        addr += FLASH_PAGE_SIZE)
+      flash_erase_page (addr);
+
+    /* copy system service routines */
+    flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
+
+    /* Leave NeuG to exec reGNUal */
+    (*func) (*((void (**)(void))(&_regnual_start+4)));
+    for (;;);
+  }
+#else
+  /* Leave NeuG to exec reGNUal */
+  flash_erase_all_and_exec (*((void (**)(void))(&_regnual_start+4)));
+#endif
+
+  /* Never reached */
   return 0;
 }
index f83d8a5..898c865 100644 (file)
@@ -9,3 +9,4 @@ uint32_t neug_get (int kick);
 void neug_kick_filling (void);
 void neug_flush (void);
 void neug_wait_full (void);
+void neug_fini (void);
index e34464d..a576cc9 100644 (file)
@@ -157,14 +157,17 @@ SECTIONS
         PROVIDE(_bss_end = .);
     } > ram
 
+    PROVIDE(end = .);
+    _end            = .;
+    . = ALIGN(512);
+    /* it is at offset 0x1400 from ram start */
+    _regnual_start = __ram_start__ + 0x1400;
+
     .fill_ffff :
     {
         . = ALIGN (@FLASH_PAGE_SIZE@);
     } > flash =0xffffffff
 }
 
-PROVIDE(end = .);
-_end            = .;
-
 __heap_base__   = _end;
 __heap_end__    = __ram_end__;
index 10e5d49..a373a0f 100644 (file)
@@ -370,7 +370,7 @@ static msg_t rng (void *arg)
   adcStart (&ADCD1, NULL);
   adcStartConversion (&ADCD1, &adcgrpcfg, samp, ADC_GRP1_BUF_DEPTH);
 
-  while (1)
+  while (!chThdShouldTerminate ())
     {
       chMtxLock (&rb->m);
       while (rb->full)
@@ -462,3 +462,15 @@ neug_wait_full (void)
     chCondWait (&rb->data_available);
   chMtxUnlock ();
 }
+
+void
+neug_fini (void)
+{
+  if (rng_thread)
+    {
+      chThdTerminate (rng_thread);
+      neug_get (1);
+      chThdWait (rng_thread);
+      rng_thread = NULL;
+    }
+}
diff --git a/tool/neug_upgrade.py b/tool/neug_upgrade.py
new file mode 100755 (executable)
index 0000000..c953c92
--- /dev/null
@@ -0,0 +1,339 @@
+#! /usr/bin/python
+
+"""
+neug_upgrade.py - a tool to upgrade firmware of Gnuk Token
+
+Copyright (C) 2012 Free Software Initiative of Japan
+Author: NIIBE Yutaka <gniibe@fsij.org>
+
+This file is a part of NeuG, a TRNG 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/>.
+"""
+
+from struct import *
+import sys, time, os, binascii, string
+
+# INPUT: binary file
+
+# Assume only single NeuG device is attached to computer
+
+import usb
+
+# USB class, subclass, protocol
+COM_CLASS = 0x0a
+COM_SUBCLASS = 0x00
+COM_PROTOCOL_0 = 0x00
+
+class regnual(object):
+    def __init__(self, dev):
+        conf = dev.configurations[0]
+        intf_alt = conf.interfaces[0]
+        intf = intf_alt[0]
+        if intf.interfaceClass != 0xff:
+            raise ValueError, "Wrong interface class"
+        self.__devhandle = dev.open()
+        try:
+            self.__devhandle.setConfiguration(conf)
+        except:
+            pass
+        self.__devhandle.claimInterface(intf)
+        self.__devhandle.setAltInterface(intf)
+
+    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)
+            crc32code = crc32(data[j*256:j*256+256])
+            res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
+                                              value = 0, index = 0, buffer = 4,
+                                              timeout = 10000)
+            r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
+            if (crc32code ^ r_value) != 0xffffffff:
+                print "failure"
+            self.__devhandle.controlMsg(requestType = 0x40, request = 3,
+                                        value = i, index = 0,
+                                        buffer = None,
+                                        timeout = 10000)
+            time.sleep(0.010)
+            res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
+                                              value = 0, index = 0, buffer = 4,
+                                              timeout = 10000)
+            r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
+            if r_value == 0:
+                print "failure"
+            i = i+1
+            j = j+1
+            addr = addr + 256
+        residue = len(data) % 256
+        if residue != 0:
+            print "# %08x: %d : %d" % (addr, i, residue)
+            self.__devhandle.controlMsg(requestType = 0x40, request = 1,
+                                        value = 0, index = 0,
+                                        buffer = data[j*256:],
+                                        timeout = 10000)
+            crc32code = crc32(data[j*256:].ljust(256,chr(255)))
+            res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
+                                              value = 0, index = 0, buffer = 4,
+                                              timeout = 10000)
+            r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
+            if (crc32code ^ r_value) != 0xffffffff:
+                print "failure"
+            self.__devhandle.controlMsg(requestType = 0x40, request = 3,
+                                        value = i, index = 0,
+                                        buffer = None,
+                                        timeout = 10000)
+            time.sleep(0.010)
+            res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
+                                              value = 0, index = 0, buffer = 4,
+                                              timeout = 10000)
+            r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
+            if r_value == 0:
+                print "failure"
+
+    def protect(self):
+        self.__devhandle.controlMsg(requestType = 0x40, request = 4,
+                                    value = 0, index = 0, buffer = None,
+                                    timeout = 10000)
+        time.sleep(0.100)
+        res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
+                                          value = 0, index = 0, buffer = 4,
+                                          timeout = 10000)
+        r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
+        if r_value == 0:
+            print "protection failure"
+
+    def finish(self):
+        self.__devhandle.controlMsg(requestType = 0x40, request = 5,
+                                    value = 0, index = 0, buffer = None,
+                                    timeout = 10000)
+
+    def reset_device(self):
+        try:
+            self.__devhandle.reset()
+        except:
+            pass
+
+class neug(object):
+    def __init__(self, device, configuration, interface):
+        """
+        __init__(device, configuration, interface) -> None
+        Initialize the device.
+        device: usb.Device object.
+        configuration: configuration number.
+        interface: usb.Interface object representing the interface and altenate setting.
+        """
+        if interface.interfaceClass !=COM_CLASS:
+            raise ValueError, "Wrong interface class"
+        if interface.interfaceSubClass != COM_SUBCLASS:
+            raise ValueError, "Wrong interface sub class"
+        self.__devhandle = device.open()
+        try:
+            self.__devhandle.setConfiguration(configuration)
+        except:
+            pass
+
+        self.__devhandle.detachKernelDriver(interface)
+        self.__devhandle.claimInterface(interface)
+        self.__devhandle.setAltInterface(interface)
+
+        self.__intf = interface.interfaceNumber
+        self.__alt = interface.alternateSetting
+        self.__conf = configuration
+
+        self.__timeout = 10000
+
+    def reset_device(self):
+        try:
+            self.__devhandle.reset()
+        except:
+            pass
+
+    def stop_neug(self):
+        self.__devhandle.controlMsg(requestType = 0x40, request = 255,
+                                    value = 0, index = 0, buffer = None,
+                                    timeout = 10)
+        self.__devhandle.releaseInterface()
+        self.__devhandle.setConfiguration(0)
+        return
+
+    def mem_info(self):
+        mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0,
+                                          value = 0, index = 0, buffer = 8,
+                                          timeout = 10)
+        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 - 0x20000000) / 0x100
+        j = 0
+        print "start %08x" % addr
+        print "end   %08x" % addr_end
+        while addr < addr_end:
+            print "# %08x: %d : %d" % (addr, i, 256)
+            self.__devhandle.controlMsg(requestType = 0x40, request = 1,
+                                        value = i, index = 0,
+                                        buffer = data[j*256:j*256+256],
+                                        timeout = 10)
+            i = i+1
+            j = j+1
+            addr = addr + 256
+        residue = len(data) % 256
+        if residue != 0:
+            print "# %08x: %d : %d" % (addr, i, residue)
+            self.__devhandle.controlMsg(requestType = 0x40, request = 1,
+                                        value = i, index = 0,
+                                        buffer = data[j*256:],
+                                        timeout = 10)
+
+    def execute(self, last_addr):
+        i = (last_addr - 0x20000000) / 0x100
+        o = (last_addr - 0x20000000) % 0x100
+        self.__devhandle.controlMsg(requestType = 0x40, request = 2,
+                                    value = i, index = o, buffer = None,
+                                    timeout = 10)
+
+def compare(data_original, data_in_device):
+    i = 0 
+    for d in data_original:
+        if ord(d) != data_in_device[i]:
+            raise ValueError, "verify failed at %08x" % i
+        i += 1
+
+def com_devices():
+    busses = usb.busses()
+    for bus in busses:
+        devices = bus.devices
+        for dev in devices:
+            for config in dev.configurations:
+                for intf in config.interfaces:
+                    for alt in intf:
+                        if alt.interfaceClass == COM_CLASS and \
+                                alt.interfaceSubClass == COM_SUBCLASS and \
+                                alt.interfaceProtocol == COM_PROTOCOL_0:
+                            yield dev, config, alt
+
+USB_VENDOR_FSIJ=0x234b
+USB_PRODUCT_GNUK=0x0000
+
+def gnuk_devices():
+    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
+            yield dev
+
+def to_string(t):
+    result = ""
+    for c in t:
+        result += chr(c)
+    return result
+
+def UNSIGNED(n):
+    return n & 0xffffffff
+
+def crc32(bytestr):
+    crc = binascii.crc32(bytestr)
+    return UNSIGNED(crc)
+
+def main(data_regnual, data_upgrade):
+    l = len(data_regnual)
+    if (l & 0x03) != 0:
+        data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0))
+    crc32code = crc32(data_regnual)
+    print "CRC32: %04x\n" % crc32code
+    data_regnual += pack('<I', crc32code)
+    com = None
+    for (dev, config, intf) in com_devices():
+        try:
+            com = neug(dev, config, intf)
+            print "Device: ", dev.filename
+            print "Configuration: ", config.value
+            print "Interface: ", intf.interfaceNumber
+            break
+        except:
+            pass
+    if not com:
+        raise ValueError, "No NeuG Device Present"
+    com.stop_neug()
+    time.sleep(0.500)
+    mem_info = com.mem_info()
+    print "%08x:%08x" % mem_info
+    print "Downloading flash upgrade program..."
+    com.download(mem_info[0], data_regnual)
+    print "Run flash upgrade program..."
+    com.execute(mem_info[0] + len(data_regnual) - 4)
+    #
+    time.sleep(3)
+    com.reset_device()
+    del com
+    com = None
+    #
+    print "Wait 3 seconds..."
+    time.sleep(3)
+    # Then, send upgrade program...
+    reg = None
+    for dev in gnuk_devices():
+        try:
+            reg = regnual(dev)
+            print "Device: ", dev.filename
+            break
+        except:
+            pass
+    mem_info = reg.mem_info()
+    print "%08x:%08x" % mem_info
+    print "Downloading the program"
+    reg.download(mem_info[0], data_upgrade)
+    reg.protect()
+    reg.finish()
+    reg.reset_device()
+    return 0
+
+
+if __name__ == '__main__':
+    filename_regnual = sys.argv[1]
+    filename_upgrade = sys.argv[2]
+    f = open(filename_regnual)
+    data_regnual = f.read()
+    f.close()
+    print "%s: %d" % (filename_regnual, len(data_regnual))
+    f = open(filename_upgrade)
+    data_upgrade = f.read()
+    f.close()
+    print "%s: %d" % (filename_upgrade, len(data_upgrade))
+    main(data_regnual, data_upgrade[4096:])