<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="bbPress/1.0.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>LeafLabs Garden &#187; Topic: patches for boot loader DFU_UPLOAD support</title>
		<link>http://forums.leaflabs.com/topic.php?id=9321</link>
		<description>A place to share, learn, and grow...</description>
		<language>en-US</language>
		<pubDate>Fri, 22 Jan 2016 00:04:58 +0000</pubDate>
		<generator>http://bbpress.org/?v=1.0.2</generator>
		<textInput>
			<title><![CDATA[Search]]></title>
			<description><![CDATA[Search all topics from these forums.]]></description>
			<name>q</name>
			<link>http://forums.leaflabs.com/search.php</link>
		</textInput>
		<atom:link href="http://forums.leaflabs.com/rss.php?topic=9321" rel="self" type="application/rss+xml" />

		<item>
			<title>tormod on "patches for boot loader DFU_UPLOAD support"</title>
			<link>http://forums.leaflabs.com/topic.php?id=9321#post-104853</link>
			<pubDate>Mon, 04 Nov 2013 13:55:25 +0000</pubDate>
			<dc:creator>tormod</dc:creator>
			<guid isPermaLink="false">104853@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;playaspec, the patch is for the Maple firmware (and was committed to the Leaflabs git repository). dfu-util is on the other side of the cable, and could always do DFU_UPLOAD :)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>playaspec on "patches for boot loader DFU_UPLOAD support"</title>
			<link>http://forums.leaflabs.com/topic.php?id=9321#post-104846</link>
			<pubDate>Fri, 01 Nov 2013 14:54:44 +0000</pubDate>
			<dc:creator>playaspec</dc:creator>
			<guid isPermaLink="false">104846@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Any idea if this patch has been submitted to the main dfu-util repository?
&#60;/p&#62;</description>
		</item>
		<item>
			<title>tormod on "patches for boot loader DFU_UPLOAD support"</title>
			<link>http://forums.leaflabs.com/topic.php?id=9321#post-20520</link>
			<pubDate>Sun, 28 Oct 2012 05:52:21 +0000</pubDate>
			<dc:creator>tormod</dc:creator>
			<guid isPermaLink="false">20520@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;This second patch is the DFU_UPLOAD support (also mailed to info@).&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;From f2c01ce01e5dca4f0be3cf0e71bedcb888b7ac06 Mon Sep 17 00:00:00 2001
From: Tormod Volden &#38;lt;debian.tormod@gmail.com&#38;gt;
Date: Sun, 28 Oct 2012 02:24:29 +0200
Subject: [PATCH 2/2] Add DFU_UPLOAD support

The DFU_UPLOAD support allows copying the contents of the flash or RAM
memory of the Maple to the computer.

Note that we use the wValue (BlockNum in the DFU standard) to calculate
the target address. We therefore rely on the host program (for instance
dfu-util) to set (increase) wValue for each block.

This use of wValue is not mandated by the DFU standard, which only says
wValue should be incremented by the host &#38;quot;to provide useful context&#38;quot; to
the device, but this implementation allows random access of memory
locations.

On the other hand the DFU_DNLOAD code does not make use of BlockNum but
simply increases its memory pointer for each block received. Maybe this
was done because reading out wValue was broken due to endian mix-up?

Signed-off-by: Tormod Volden &#38;lt;debian.tormod@gmail.com&#38;gt;
---

Hi,

This will permit taking backups of existing flash contents, and verifying
proper flashing.

The RAM uploading can also be used for debugging: If you reset into the
bootloader, the RAM contents (above 0x20000c00) is preserved, and you
can upload it to the computer for analysis.

I have not tested it on a real Maple, only on a development board with a
port of the maple-mini bootloader.

I have noticed that dfu-util receives a pipe error on the last
libusb_control_msg() call, but the transfers seems fine nevertheless so I
am not looking into it at this time.

Best regards,
Tormod

 config.h         &#124;    2 ++
 dfu.c            &#124;   47 ++++++++++++++++++++++++++++++++++++++++++-----
 usb.c            &#124;    1 +
 usb_descriptor.c &#124;    4 ++--
 4 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/config.h b/config.h
index d2d980c..def4f99 100644
--- a/config.h
+++ b/config.h
@@ -47,7 +47,9 @@
 #define BOOTLOADER_WAIT 6

 #define USER_CODE_RAM     ((u32)0x20000C00)
+#define RAM_END           ((u32)0x20005000)
 #define USER_CODE_FLASH   ((u32)0x08005000)
+#define FLASH_END         ((u32)0x08020000)

 #define VEND_ID0 0xAF
 #define VEND_ID1 0x1E
diff --git a/dfu.c b/dfu.c
index cf05f3b..d5ddad1 100644
--- a/dfu.c
+++ b/dfu.c
@@ -36,6 +36,7 @@

 /* DFU globals */
 u32 userAppAddr = USER_CODE_RAM; /* default RAM user code location */
+u32 userAppEnd = RAM_END;
 DFUStatus dfuAppStatus;       /* includes state */
 bool userFlash = FALSE;
 bool dfuBusy = FALSE;
@@ -43,6 +44,7 @@ bool dfuBusy = FALSE;
 u8 recvBuffer[wTransferSize];
 u32 userFirmwareLen = 0;
 u16 thisBlockLen = 0;
+u16 uploadBlockLen = 0;

 PLOT code_copy_lock;
@@ -58,6 +60,7 @@ void dfuInit(void) {
     userFirmwareLen = 0;
     thisBlockLen = 0;;
     userAppAddr = USER_CODE_RAM; /* default RAM user code location */
+    userAppEnd = RAM_END;
     userFlash = FALSE;
     code_copy_lock = WAIT;
     dfuBusy = FALSE;
@@ -99,6 +102,19 @@ bool dfuUpdateByRequest(void) {
             }
         } else if (pInformation-&#38;gt;USBbRequest == DFU_UPLOAD) {
             dfuAppStatus.bState  = dfuUPLOAD_IDLE;
+            /* record length of first block for calculating target
+               address from wValue in consecutive blocks */
+            uploadBlockLen = pInformation-&#38;gt;USBwLengths.w;
+            thisBlockLen = uploadBlockLen; /* for this first block as well */
+            /* calculate where the data should be copied from */
+            userFirmwareLen = uploadBlockLen * pInformation-&#38;gt;USBwValue;
+            if (pInformation-&#38;gt;Current_AlternateSetting == 1) {
+                userAppAddr = USER_CODE_FLASH;
+	         userAppEnd = FLASH_END;
+            } else {
+                userAppAddr = USER_CODE_RAM;
+                userAppEnd = RAM_END;
+            }
         } else if (pInformation-&#38;gt;USBbRequest == DFU_ABORT) {
             dfuAppStatus.bState  = dfuIDLE;
             dfuAppStatus.bStatus = OK;  /* are we really ok? we were just aborted */
@@ -211,9 +227,26 @@ bool dfuUpdateByRequest(void) {
         /* device expecting further dfu_upload requests */

         if (pInformation-&#38;gt;USBbRequest == DFU_UPLOAD) {
-            /* todo, add routine to wait for last block write to finish */
-            dfuAppStatus.bState  = dfuERROR;
-            dfuAppStatus.bStatus = errSTALLEDPKT;
+            if (pInformation-&#38;gt;USBwLengths.w &#38;gt; 0) {
+                /* check that this is not the last possible block */
+                userFirmwareLen = uploadBlockLen * pInformation-&#38;gt;USBwValue;
+                if (userAppAddr + userFirmwareLen + uploadBlockLen &#38;lt;= userAppEnd) {
+                    thisBlockLen = uploadBlockLen;
+                    dfuAppStatus.bState  = dfuUPLOAD_IDLE;
+                } else {
+                    /* if above comparison was just equal, thisBlockLen becomes zero
+                    next time when USBWValue has been increased by one */
+                    thisBlockLen = userAppEnd - userAppAddr - userFirmwareLen;
+                    /* check for overflow due to USBwValue out of range */
+                    if (thisBlockLen &#38;gt;= pInformation-&#38;gt;USBwLengths.w) {
+                        thisBlockLen = 0;
+                    }
+                    dfuAppStatus.bState  = dfuIDLE;
+                }
+            } else {
+	        dfuAppStatus.bState  = dfuERROR;
+	        dfuAppStatus.bStatus = errNOTDONE;
+            }
         } else if (pInformation-&#38;gt;USBbRequest == DFU_ABORT) {
             dfuAppStatus.bState  = dfuIDLE;
         } else if (pInformation-&#38;gt;USBbRequest == DFU_GETSTATUS) {
@@ -313,8 +346,12 @@ u8 *dfuCopyDNLOAD(u16 length) {
 }

 u8 *dfuCopyUPLOAD(u16 length) {
-    /* not implemented here nor supported by dfu-util */
-    return NULL;
+    if (length == 0) {
+        pInformation-&#38;gt;Ctrl_Info.Usb_wLength = thisBlockLen - pInformation-&#38;gt;Ctrl_Info.Usb_wOffset;
+        return NULL;
+    } else {
+        return((u8*) userAppAddr + userFirmwareLen + pInformation-&#38;gt;Ctrl_Info.Usb_wOffset);
+    }
 }

 void dfuCopyBufferToExec() {
diff --git a/usb.c b/usb.c
index 5a5238b..b6d2a67 100644
--- a/usb.c
+++ b/usb.c
@@ -297,6 +297,7 @@ RESULT usbDataSetup(u8 request) {
                 break;
             case(DFU_UPLOAD):
                 CopyRoutine = dfuCopyUPLOAD;
+                break;
             default:
                 /* leave copy routine null */
                 break;
diff --git a/usb_descriptor.c b/usb_descriptor.c
index b9fcc09..3a0c7f0 100644
--- a/usb_descriptor.c
+++ b/usb_descriptor.c
@@ -66,7 +66,7 @@ u8 u8_usbFunctionalDescriptor[9] = {
     /******************** DFU Functional Descriptor********************/
     0x09,   /*blength = 7 Bytes*/
     0x21,   /* DFU Functional Descriptor*/
-    0x01,   /*bmAttribute, can only download for now */
+    0x03,   /*bmAttributes, bitCanDnload &#124; bitCanUpload */
     0xFF,   /*DetachTimeOut= 255 ms*/
     0x00,
     (wTransferSize &#38;amp; 0x00FF),
@@ -122,7 +122,7 @@ u8 u8_usbConfigDescriptorDFU[36] = {
     /******************** DFU Functional Descriptor********************/
     0x09,   /*blength = 7 Bytes*/
     0x21,   /* DFU Functional Descriptor*/
-    0x01,   /*bmAttribute, can only download for now */
+    0x03,   /*bmAttributes, bitCanDnload &#124; bitCanUpload */
     0xFF,   /*DetachTimeOut= 255 ms*/
     0x00,
     (wTransferSize &#38;amp; 0x00FF),
--
1.7.9.5&#60;/code&#62;&#60;/pre&#62;</description>
		</item>
		<item>
			<title>tormod on "patches for boot loader DFU_UPLOAD support"</title>
			<link>http://forums.leaflabs.com/topic.php?id=9321#post-20519</link>
			<pubDate>Sun, 28 Oct 2012 05:48:11 +0000</pubDate>
			<dc:creator>tormod</dc:creator>
			<guid isPermaLink="false">20519@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;DFU_UPLOAD means transfers from Maple to computer.&#60;/p&#62;
&#60;p&#62;The patches apply to git://github.com/leaflabs/maple-bootloader.git master&#60;/p&#62;
&#60;p&#62;This first patch is a general bug fix and can also be applied alone. (Patch also mailed to info@)&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;From b7c8ce89331653c6d92fd7a52a43f444c8bcb739 Mon Sep 17 00:00:00 2001
From: Tormod Volden &#38;lt;debian.tormod@gmail.com&#38;gt;
Date: Sun, 28 Oct 2012 01:34:03 +0200
Subject: [PATCH 1/2] Fix endian mix-up in usb_core

USB uses little endian, as does ARM, so there should not be any byte
swapping. Bytes were swapped back and forth inconsistently and would
break word access of u16_u8 union types. It seems like this has gone
unnoticed for long because the word values are mostly used for comparing
against zero.

Signed-off-by: Tormod Volden &#38;lt;debian.tormod@gmail.com&#38;gt;
---

These endian bugs were causing great headaches in the debugging of the
following patch...

 usb_lib/usb_core.c &#124;    9 +++------
 usb_lib/usb_core.h &#124;    5 ++++-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/usb_lib/usb_core.c b/usb_lib/usb_core.c
index 211f221..50f5111 100644
--- a/usb_lib/usb_core.c
+++ b/usb_lib/usb_core.c
@@ -31,9 +31,6 @@
 #define USB_StatusIn() Send0LengthData()
 #define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID)

-#define StatusInfo0 StatusInfo.bw.bb1 /* Reverse bb0 &#38;amp; bb1 */
-#define StatusInfo1 StatusInfo.bw.bb0
-
 /* Private macro -------------------------------------------------------------*/
 /* Private variables ---------------------------------------------------------*/
 u16_u8 StatusInfo;
@@ -860,11 +857,11 @@ u8 Setup0_Process(void)
     pInformation-&#38;gt;USBbmRequestType = *pBuf.b++; /* bmRequestType */
     pInformation-&#38;gt;USBbRequest = *pBuf.b++; /* bRequest */
     pBuf.w++;  /* word not accessed because of 32 bits addressing */
-    pInformation-&#38;gt;USBwValue = ByteSwap(*pBuf.w++); /* wValue */
+    pInformation-&#38;gt;USBwValue = *pBuf.w++; /* wValue in Little Endian */
     pBuf.w++;  /* word not accessed because of 32 bits addressing */
-    pInformation-&#38;gt;USBwIndex  = ByteSwap(*pBuf.w++); /* wIndex */
+    pInformation-&#38;gt;USBwIndex  = *pBuf.w++; /* wIndex in Little Endian */
     pBuf.w++;  /* word not accessed because of 32 bits addressing */
-    pInformation-&#38;gt;USBwLength = *pBuf.w; /* wLength */
+    pInformation-&#38;gt;USBwLength = *pBuf.w; /* wLength in Little Endian */
   }

   pInformation-&#38;gt;ControlState = SETTING_UP;
diff --git a/usb_lib/usb_core.h b/usb_lib/usb_core.h
index b7bc4c7..4a5e0df 100644
--- a/usb_lib/usb_core.h
+++ b/usb_lib/usb_core.h
@@ -97,8 +97,9 @@ typedef union
   u16 w;
   struct BW
   {
-    u8 bb1;
+    /* Little Endian */
     u8 bb0;
+    u8 bb1;
   }
   bw;
 } u16_u8;
@@ -208,6 +209,8 @@ USER_STANDARD_REQUESTS;
 #define USBwLength USBwLengths.w
 #define USBwLength0 USBwLengths.bw.bb0
 #define USBwLength1 USBwLengths.bw.bb1
+#define StatusInfo0 StatusInfo.bw.bb0
+#define StatusInfo1 StatusInfo.bw.bb1

 /* Exported macro ------------------------------------------------------------*/
 /* Exported functions ------------------------------------------------------- */
--
1.7.9.5&#60;/code&#62;&#60;/pre&#62;</description>
		</item>

	</channel>
</rss>
