Patchwork Dediprog SF100 support

login
register
about
Submitter Carl-Daniel Hailfinger
Date 2010-01-14 04:24:48
Message ID <4B4E9C90.5060600@gmx.net>
Download mbox | patch
Permalink /patch/789/
State Superseded
Headers show

Comments

Carl-Daniel Hailfinger - 2010-01-14 04:24:48
Dediprog SF100 support. Very fragile, lots of stuff guessed from logs.
May explode spontaneously.

I think I know enough to actually use it to ID the chip, but that's it.
A USB log with which includes writing an image from the original
software (pretty much any image) would help clear up a few ambiguities.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Stefan Reinauer - 2010-01-14 13:14:15
On 1/14/10 5:24 AM, Carl-Daniel Hailfinger wrote:
> Dediprog SF100 support. Very fragile, lots of stuff guessed from logs.
> May explode spontaneously.
>
> I think I know enough to actually use it to ID the chip, but that's it.
> A USB log with which includes writing an image from the original
> software (pretty much any image) would help clear up a few ambiguities.
>
> Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
>   
Acked-by: Stefan Reinauer <stepan@coresystems.de>

Here's a complete dump of all responses on my SF100:

flashrom v0.9.1-r862
Found USB device (0483:dada).
Receiving response 0: 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Receiving response 1: 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Receiving response 2: ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Receiving response 3: 53 46 31 30 30 20 20 20 56 3a 33 2e 31 2e 38 20
Found a Dediprog SF100 V:3.1.8
Receiving response 4: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Receiving response 5: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Sending RDID
Receiving response 6: 9f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Receiving response 7: 20 20 16 10 00 00 00 00 00 00 00 00 00 00 00 00
Calibrating delay loop... 761M loops per second, 100 myus = 200 us. OK.

Stefan
Carl-Daniel Hailfinger - 2010-01-15 15:28:03
Hi Stefan,

On 14.01.2010 14:08, Stefan Reinauer wrote:
> On 1/14/10 5:24 AM, Carl-Daniel Hailfinger wrote:
>   
>> Dediprog SF100 support. Very fragile, lots of stuff guessed from logs.
>> May explode spontaneously.
>>
>> I think I know enough to actually use it to ID the chip, but that's it.
>> A USB log with which includes writing an image from the original
>> software (pretty much any image) would help clear up a few ambiguities.
>>
>> Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
>>   
>>     
>
> Awesome..!
>   

Thanks!


> It seems to be talking to the device and get through the initialization,
> but it ends up with no "SPI" chips being "incompatible":
>   

Actually, that's intentional. That way I could avoid hooking up the
driver in the SPI core (which would mean I'd have to create dummy
command functions) and still get initialization testing.


> MacPro:flashrom stepan$ ./flashrom -p dediprog -V
> flashrom v0.9.1-r862
> Found USB device (0483:dada).
> Sending RDID
> Receiving response: 20 20 16 10 00 00 00 00 00 00 00 00 00 00 00 00

Which flash chip is this? The response suggests a ST M25P32 flash chip,
but the extra "10" at the end looks rather strange.


> Not sure if this code is intended:
>   
>> /* URB 9. Command Receive Device String. */
>> memset(buf, 0, sizeof(buf));
>> ret = usb_control_msg(dediprog_handle, 0xc2, 0x8, 0xff, 0xff, buf,
>> 0x10, DEFAULT_TIMEOUT);
>> if ((ret != 0x10) || !memcmp(buf, "SF100 V:2.1.1 ", 0x10)) {
>>     
> This would bail out if the version string is "SF100 V:2.1.1 "
>   

Right, that's a bug. Considering that this was coded at 5am, I'm
surprised there was only one bug.


>> msg_perr("Unexpected response 3!\n");
>> return 1;
>> }
>>     
> Here I added this:
>   
>> buf[0xf]=0;
>> msg_pdbg("Found a Dediprog %s\n", buf);
>>     

That potentially truncates the string. I'll use strnlen/strncpy to write
the string to a separate buffer which is big enough.


> Which got me:
>
> flashrom v0.9.1-r862
> Found USB device (0483:dada).
> Found a Dediprog SF100 V:3.1.8
>   

Hm. The best idea might be to match against the model name and the major
version.


> Let me know if you need more information
>   

A log with SniffUsb 2.0.0006 from
http://www.pcausa.com/Utilities/UsbSnoop/ would be very appreciated.
I wrote a tool to decode the log generated with that SniffUsb version.
Feel free to point me to a private upload via IRC (the log may contain
programmer serial numbers).

What the log should contain:
- Plugging in the SF100
- Starting the programming software
- SPI device detection/probe
- Full read
- Erase (optional)
- Full write (optional)
- No custom settings (but you can do a probe-only run with changed
settings in another file if you want to help decode a few more commands)

It would be cool if you could use a small SPI chip (4 Mbit or so)
because the logs roughly have 4x-20x the size of the flash chip.

Please do not use a SST chip (log would be at least 100x the size of the
flash chip). Pretty much all other vendors are OK.

I will post an updated patch soon.


Regards,
Carl-Daniel
Stefan Reinauer - 2010-01-15 16:08:16
On 1/15/10 4:28 PM, Carl-Daniel Hailfinger wrote:
>> MacPro:flashrom stepan$ ./flashrom -p dediprog -V
>> flashrom v0.9.1-r862
>> Found USB device (0483:dada).
>> Sending RDID
>> Receiving response: 20 20 16 10 00 00 00 00 00 00 00 00 00 00 00 00
>>     
> Which flash chip is this? The response suggests a ST M25P32 flash chip,
> but the extra "10" at the end looks rather strange.
>   
It's a Numonyx M25P32 (until a couple of years ago parts of the company
were known as SP)
Here I added this:

>>> buf[0xf]=0;
>>> msg_pdbg("Found a Dediprog %s\n", buf);
>>>     
>>>       
> That potentially truncates the string. I'll use strnlen/strncpy to write
> the string to a separate buffer which is big enough.
>   
Yes, I just didn't want to fiddle with the buffer size and all dediprog
devices I've seen have a space in the last character.
Using a 0x11 bytes big buffer would be the correct approach.


>> Let me know if you need more information
>>   
>>     
> A log with SniffUsb 2.0.0006 from
> http://www.pcausa.com/Utilities/UsbSnoop/ would be very appreciated.
> I wrote a tool to decode the log generated with that SniffUsb version.
> Feel free to point me to a private upload via IRC (the log may contain
> programmer serial numbers).
>
>   
Will produce these asap.

> It would be cool if you could use a small SPI chip (4 Mbit or so)
> because the logs roughly have 4x-20x the size of the flash chip.
>   
That might be a problem, I think 32MBit are the only ones I have here at
the moment.. :-}
I'll have a look.

> Please do not use a SST chip (log would be at least 100x the size of the
> flash chip). Pretty much all other vendors are OK.
>   
Why is that?


Stefan
Carl-Daniel Hailfinger - 2010-01-15 16:26:14
On 15.01.2010 17:08, Stefan Reinauer wrote:
> On 1/15/10 4:28 PM, Carl-Daniel Hailfinger wrote:
>   
>>> MacPro:flashrom stepan$ ./flashrom -p dediprog -V
>>> flashrom v0.9.1-r862
>>> Found USB device (0483:dada).
>>> Sending RDID
>>> Receiving response: 20 20 16 10 00 00 00 00 00 00 00 00 00 00 00 00
>>>     
>>>       
>> Which flash chip is this? The response suggests a ST M25P32 flash chip,
>> but the extra "10" at the end looks rather strange.
>>   
>>     
> It's a Numonyx M25P32 (until a couple of years ago parts of the company
> were known as SP)
>   

OK, thanks for confirming.


> Here I added this:
>   
>>>> buf[0xf]=0;
>>>> msg_pdbg("Found a Dediprog %s\n", buf);
>>>>     
>>>>       
>>>>         
>> That potentially truncates the string. I'll use strnlen/strncpy to write
>> the string to a separate buffer which is big enough.
>>   
>>     
> Yes, I just didn't want to fiddle with the buffer size and all dediprog
> devices I've seen have a space in the last character.
> Using a 0x11 bytes big buffer would be the correct approach.
>   

That's an option as well, right.


>>> Let me know if you need more information
>>>   
>>>     
>>>       
>> A log with SniffUsb 2.0.0006 from
>> http://www.pcausa.com/Utilities/UsbSnoop/ would be very appreciated.
>> I wrote a tool to decode the log generated with that SniffUsb version.
>> Feel free to point me to a private upload via IRC (the log may contain
>> programmer serial numbers).
>>
>>   
>>     
> Will produce these asap.
>   

Thanks.


>> It would be cool if you could use a small SPI chip (4 Mbit or so)
>> because the logs roughly have 4x-20x the size of the flash chip.
>>   
>>     
> That might be a problem, I think 32MBit are the only ones I have here at
> the moment.. :-}
> I'll have a look.
>   

OK, I can parse that stuff, it's just that the log may be rather large
(80-160 MByte).


>> Please do not use a SST chip (log would be at least 100x the size of the
>> flash chip). Pretty much all other vendors are OK.
>>   
>>     
> Why is that?
>   

SST doesn't support page write, so you get one USB transaction per
written byte. And one transaction takes ~1100 bytes (so yes, I was off
by an order of magnitude) in the log. I doubt you want to upload a log
with a size of 4 Gigabytes. Plus, my scripts will take a long time to
run on such a big log, and besides that the information gathered from a
SST log would be essentially zero because it has no long write
transactions (which is pretty much the only transaction type I don't
have in my log yet).

Regards,
Carl-Daniel
Carl-Daniel Hailfinger - 2010-01-16 05:48:41
Good news:
I decoded a few more commands.
The v2 and v3 firmware seem to have identical commands.

Bad news:
Some things are done internally by the programmer (namely, big reads and
writes) and it seems you can't influence the actual SPI commands for that.
It is unclear whether commands bigger than 4 bytes can be sent (i.e.
writes).
It is unclear whether more than 4 bytes of chip response can be read.
Some commands are still totally undecoded (one is probably IDLE and
another one RESET, but that's pretty much speculation).

I know how to test my assumptions, though.

AFAIK the Dediprog can do "fast" (partial) writes. A log from such a
partial write (i.e. zero out some area that was 0xff before) would clear
up a lot of stuff.

Separate logs from ID/read with changed frequencies (one log per
frequency) would help as well.

What else can be set? Voltage? Timing? Other stuff?

Regards,
Carl-Daniel

Patch

Index: flashrom-dediprog/flash.h
===================================================================
--- flashrom-dediprog/flash.h	(Revision 862)
+++ flashrom-dediprog/flash.h	(Arbeitskopie)
@@ -67,6 +67,9 @@ 
 #if BUSPIRATE_SPI_SUPPORT == 1
 	PROGRAMMER_BUSPIRATESPI,
 #endif
+#if DEDIPROG_SUPPORT == 1
+	PROGRAMMER_DEDIPROG,
+#endif
 	PROGRAMMER_INVALID /* This must always be the last entry. */
 };
 
@@ -470,6 +473,10 @@ 
 int buspirate_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
 int buspirate_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
 
+/* dediprog.c */
+int dediprog_init(void);
+int dediprog_shutdown(void);
+
 /* flashrom.c */
 extern enum chipbustype buses_supported;
 struct decode_sizes {
Index: flashrom-dediprog/Makefile
===================================================================
--- flashrom-dediprog/Makefile	(Revision 862)
+++ flashrom-dediprog/Makefile	(Arbeitskopie)
@@ -96,6 +96,9 @@ 
 # Always enable Bus Pirate SPI for now.
 CONFIG_BUSPIRATESPI ?= yes
 
+# Always enable Dediprog SF100 for now.
+CONFIG_DEDIPROG ?= yes
+
 # Disable wiki printing by default. It is only useful if you have wiki access.
 CONFIG_PRINT_WIKI ?= no
 
@@ -160,6 +163,12 @@ 
 PROGRAMMER_OBJS += buspirate_spi.o
 endif
 
+ifeq ($(CONFIG_DEDIPROG), yes)
+FEATURE_CFLAGS += -D'DEDIPROG_SUPPORT=1'
+FEATURE_LIBS += -lusb
+PROGRAMMER_OBJS += dediprog.o
+endif
+
 # Ugly, but there's no elif/elseif.
 ifeq ($(CONFIG_SERPROG), yes)
 LIB_OBJS += serial.o
Index: flashrom-dediprog/flashrom.c
===================================================================
--- flashrom-dediprog/flashrom.c	(Revision 862)
+++ flashrom-dediprog/flashrom.c	(Arbeitskopie)
@@ -44,7 +44,7 @@ 
  * if more than one of them is selected. If only one is selected, it is clear
  * that the user wants that one to become the default.
  */
-#if NIC3COM_SUPPORT+GFXNVIDIA_SUPPORT+DRKAISER_SUPPORT+SATASII_SUPPORT+FT2232_SPI_SUPPORT+SERPROG_SUPPORT+BUSPIRATE_SPI_SUPPORT > 1
+#if NIC3COM_SUPPORT+GFXNVIDIA_SUPPORT+DRKAISER_SUPPORT+SATASII_SUPPORT+FT2232_SPI_SUPPORT+SERPROG_SUPPORT+BUSPIRATE_SPI_SUPPORT+DEDIPROG_SUPPORT > 1
 #error Please enable either CONFIG_DUMMY or CONFIG_INTERNAL or disable support for all external programmers except one.
 #endif
 enum programmer programmer =
@@ -69,6 +69,9 @@ 
 #if BUSPIRATE_SPI_SUPPORT == 1
 	PROGRAMMER_BUSPIRATESPI
 #endif
+#if DEDIPROG_SUPPORT == 1
+	PROGRAMMER_DEDIPROG
+#endif
 ;
 #endif
 
@@ -283,6 +286,25 @@ 
 	},
 #endif
 
+#if DEDIPROG_SUPPORT == 1
+	{
+		.name			= "dediprog",
+		.init			= dediprog_init,
+		.shutdown		= dediprog_shutdown,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+		.chip_readb		= noop_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= noop_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.delay			= internal_delay,
+	},
+#endif
+
 	{}, /* This entry corresponds to PROGRAMMER_INVALID. */
 };
 
Index: flashrom-dediprog/dediprog.c
===================================================================
--- flashrom-dediprog/dediprog.c	(Revision 0)
+++ flashrom-dediprog/dediprog.c	(Revision 0)
@@ -0,0 +1,200 @@ 
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Carl-Daniel Hailfinger
+ *
+ * This program 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; version 2 of the License.
+ *
+ * This program 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <usb.h>
+#include "flash.h"
+
+#define DEFAULT_TIMEOUT 3000
+usb_dev_handle *dediprog_handle;
+
+void print_hex(void *buf, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++)
+		msg_pdbg(" %02x", ((uint8_t *)buf)[i]);
+}
+
+struct usb_device *get_device_by_vid_pid(uint16_t vid, uint16_t pid)
+{
+	struct usb_bus *bus;
+	struct usb_device *dev;
+
+	for (bus = usb_get_busses(); bus; bus = bus->next)
+		for (dev = bus->devices; dev; dev = dev->next)
+			if ((dev->descriptor.idVendor == vid) &&
+			    (dev->descriptor.idProduct == pid))
+				return dev;
+
+	return NULL;
+}
+
+int dediprog_init(void)
+{
+	struct usb_device *dev;
+	int ret;
+	char buf[0x10];
+
+	msg_pspew("%s\n", __func__);
+
+	/* For now, just to make sure nothing is sent. */
+	buses_supported = CHIP_BUSTYPE_NONE;
+
+	/* Here comes the USB stuff. */
+	usb_init();
+	usb_find_busses();
+	usb_find_devices();
+	dev = get_device_by_vid_pid(0x0483, 0xdada);
+	if (!dev) {
+		msg_perr("Could not find a Dediprog SF100 on USB!\n");
+		return 1;
+	}
+	msg_pdbg("Found USB device (%04x:%04x).\n",
+		 dev->descriptor.idVendor,
+		 dev->descriptor.idProduct);
+	dediprog_handle = usb_open(dev);
+//int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);
+	/* URB 6. Command A. */
+	memset(buf, 0, sizeof(buf));
+	ret = usb_control_msg(dediprog_handle, 0xc3, 0xb, 0x0, 0x0, buf, 0x1, DEFAULT_TIMEOUT);
+	if ((ret != 0x1) || (buf[0] != 0x6f)) {
+		msg_perr("Unexpected response 0!\n");
+		return 1;
+	}
+	/* URB 7. Command A. */
+	memset(buf, 0, sizeof(buf));
+	ret = usb_control_msg(dediprog_handle, 0xc3, 0xb, 0x0, 0x0, buf, 0x1, DEFAULT_TIMEOUT);
+	if ((ret != 0x1) || (buf[0] != 0x6f)) {
+		msg_perr("Unexpected response 1!\n");
+		return 1;
+	}
+	/* URB 8. Command B. */
+	memset(buf, 0, sizeof(buf));
+	ret = usb_control_msg(dediprog_handle, 0xc3, 0x7, 0x0, 0xef03, buf, 0x1, DEFAULT_TIMEOUT);
+	/* The char casting is needed to stop gcc complaining about an always true comparison. */
+	if ((ret != 0x1) || (buf[0] != (char)0xff)) {
+		msg_perr("Unexpected response 2!\n");
+		return 1;
+	}
+	/* URB 9. Command Receive Device String. */
+	memset(buf, 0, sizeof(buf));
+	ret = usb_control_msg(dediprog_handle, 0xc2, 0x8, 0xff, 0xff, buf, 0x10, DEFAULT_TIMEOUT);
+	if ((ret != 0x10) || !memcmp(buf, "SF100   V:2.1.1 ", 0x10)) {
+		msg_perr("Unexpected response 3!\n");
+		return 1;
+	}
+	/* URB 10. No idea. */
+	memset(buf, 0, sizeof(buf));
+	ret = usb_control_msg(dediprog_handle, 0x42, 0x4, 0x0, 0x0, buf, 0x0, DEFAULT_TIMEOUT);
+	if (ret != 0x0) {
+		msg_perr("Unexpected response 4!\n");
+		return 1;
+	}
+	/* URB 11. No idea. */
+	memset(buf, 0, sizeof(buf));
+	ret = usb_control_msg(dediprog_handle, 0x42, 0x9, 0x10, 0xff, buf, 0x0, DEFAULT_TIMEOUT);
+	if (ret != 0x0) {
+		msg_perr("Unexpected response 5!\n");
+		return 1;
+	}
+	/* URB 12. Command Send SPI. */
+	memset(buf, 0, sizeof(buf));
+	/* JEDEC RDID */
+	msg_pdbg("Sending RDID\n");
+	buf[0] = 0x9f;
+	ret = usb_control_msg(dediprog_handle, 0x42, 0x1, 0xff, 0x1, buf, 0x1, DEFAULT_TIMEOUT);
+	if (ret != 0x1) {
+		msg_perr("Unexpected response 6!\n");
+		return 1;
+	}
+	/* URB 13. Command Receive SPI. */
+	memset(buf, 0, sizeof(buf));
+	ret = usb_control_msg(dediprog_handle, 0xc2, 0x01, 0xbb8, 0x0000, buf, 0x4, DEFAULT_TIMEOUT);
+	if (ret != 0x4) {
+		msg_perr("Unexpected response 7!\n");
+		return 1;
+	}
+	msg_pdbg("Receiving response: ");
+	print_hex(buf, 0x10);
+#if 0
+	/* URB 14+15,16+17 are just RDID again. URB 18-27 are more SPI commands. */
+	/* URB 28. No idea. */
+	memset(buf, 0, sizeof(buf));
+	ret = usb_control_msg(dediprog_handle, 0x42, 0x09, 0x0, 0xff, buf, 0x0, DEFAULT_TIMEOUT);
+	if (ret != 0x0)) {
+		msg_perr("Unexpected response 8!\n");
+		return 1;
+	}
+	/* URB 29-38. No idea. Wait unsuccessfully for 544 (maybe 600) ms to read one byte.
+	 * Could also be a wait for 10 requests.
+	 */
+	memset(buf, 0, sizeof(buf));
+	ret = usb_control_msg(dediprog_handle, 0xc2, 0x11, 0xff, 0xff, buf, 0x1, 544);
+	if (ret != 0x0) {
+		msg_perr("Unexpected response 9!\n");
+		return 1;
+	}
+	/* URB 39 is just URB 11. */
+	/* URB 40. No idea. */
+	memset(buf, 0, sizeof(buf));
+	ret = usb_control_msg(dediprog_handle, 0x42, 0x61, 0x2, 0xff, buf, 0x0, DEFAULT_TIMEOUT);
+	if (ret != 0x0) {
+		msg_perr("Unexpected response 10!\n");
+		return 1;
+	}
+	/* URB 41 is just URB 28. */
+	/* URB 42,44,46,48,51,53 is just URB 8. */
+	/* URB 43,45,47,49,52,54 is just URB 9. */
+	/* URB 50 is just URB 6/7. */
+	/* URB 55-131 is just URB 29-38. (wait unsuccessfully for 4695 (maybe 4751) ms)*/
+	/* URB 132,134 is just URB 6/7. */
+	/* URB 133 is just URB 29-38. */
+	/* URB 135 is just URB 8. */
+	/* URB 136 is just URB 9. */
+	/* URB 137 is just URB 11. */
+
+	/* Command I is probably Start Bulk Read. Data is u16 blockcount, u16 blocksize. */
+
+	/* URB  is just URB . */
+	/* URB . No idea. */
+	memset(buf, 0, sizeof(buf));
+	ret = usb_control_msg(dediprog_handle, , buf, , DEFAULT_TIMEOUT);
+	if ((ret != 0x1) || (buf[0] != )) {
+		msg_perr("Unexpected response 11!\n");
+		return 1;
+	}
+#endif	
+
+	return 0;
+}
+
+int dediprog_shutdown(void)
+{
+	msg_pspew("%s\n", __func__);
+
+	if (usb_close(dediprog_handle)) {
+		msg_perr("Couldn't close USB device!\n");
+		return 1;
+	}
+	return 0;
+}