Open rtreffer opened 3 years ago
With all this knowledge I thought it would be time to try an actual upgrade.
I took the UPDATE.mem 2.0.2.6
from https://github.com/denisandroid/uPD72020x-Firmware
(
echo -ne '\x28\x00\x00\xff\x01\xff\x02\xff\x03\xff\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x55\x17\x00\x18\x00\x19\x00\x1a\x01\x1b\x05\xe7\xef'
cat uPD72020x-Firmware/UPDATE.mem\ 2.0.2.6
cat ff
) | head -c $((16*1024)) > fw_block
# ./upd72020x-load -b 4 -d 0 -f 0 -w -i fw_block
Doing the writing
bus = 4
dev = 0
fct = 0
fname = fw_block
Found an UPD720201 chipset
got firmware version: 201308
EEPROM installed
got rom_info: 5e2013
got rom_config: 0
setting rom_config: 700
STATUS: enabling EEPROM write
STATUS: performing EEPROM write
STATUS: finishing EEPROM write
STATUS: confirming EEPROM write
======> PASSED
And after a full power off and power on I checked a backup of the FW
# ./upd72020x-load -b 4 -d 0 -f 0 -r -o backup2
Doing the reading
bus = 4
dev = 0
fct = 0
fname = backup2
Found an UPD720201 chipset
got firmware version: 202609
EEPROM installed
got rom_info: 5e2013
got rom_config: 0
setting rom_config: 700
======> PASSED
so here we go, got firmware version: 202609
which means 2.0.2.6
Flashing with this tool works if you know the block size and have a valid vendor specific configuration :smile:
Thank you a lot for your research and this write-up. If you agree, I would like to put this either into a wiki page or some documentation file in the repository.
The block alignment you discovered really puzzles me, because it clearly conflicts with the datasheet which says that firmware blocks are aligned to erase blocks.
Yes, it would be great to have that in a wiki or markdown file.
I was puzzled by the erase block size too. But I by now assume that the hardware does not fully understand these (which is why we need the rom config for writing) and probes different offsets (or alike).
So as long as smaller blocks work it might be fine. It could also be that unknown chips use 16kb.
Hard to tell without someone dumping the contents of another chip.
Btw, the linked issue for working CM4 PCIe devices has pictures and a bit more documentation like content, feel free to pull that in, too!
That datasheet also says it should be possible to update the first copy by issuing a chip erase (not implemented, but would be easy) followed by an upload.
And @pclinuxer uploaded a less-thab-blocksize image. That seems to work, too.
The ROM config register might be the equivalent to the flashrom chip table.
Well, I guess that fact that those flash memories are smarter than old-fashioned EEPROM makes this possible. They automatically perform a readout-erase-program cycle for the whole erase block if I understand the datasheet right.
That datasheet also says it should be possible to update the first copy by issuing a chip erase (not implemented, but would be easy) followed by an upload.
Yes, but I do not see me implement such a feature. Either a card is not bricked (yet), then one should probably not do something like this, or it is and then one needs an external interface. I would argue that if someone really wants to fiddle with the factory image, that person then should directly interface the flash because this way, a recovery path is also already available.
The ROM config register might be the equivalent to the flashrom chip table.
In which terms? I had a look into flashchips.c but that structure is contains much more information than the single register can hold. Or do you think of some kind of index to an internal database? The SST ROMs do not really fit there, I guess. Some flags which signal certain features? That appears more plausible to me, guess one could find some correlation between flash ROM properties and the set bits.
You can get away with 1. block erase / full erase function, 2. block size and 3. write function.
This might be doable with a few bytes of config. Just a wild guess though, but it could reduce the complexity of the chip, which sounds likely to me.... It would also explain the strange numbering.
Hi. First, thanks for the great work!
I ordered a 4 port USB 3 card from AliExpress and it works thanks to this tool. I am currently on Ubuntu 21.10 kernel 5.13.0-23-generic
But, I would like to flash the frimware permanently instead of loading it via systemd. Problem is, this card seems to have some kind of new EEPROM chip:
Found an UPD720201 chipset
got firmware version: 202609
EEPROM installed
got rom_info: 5e3213
got rom_config: 0
unknown EEPROM, no parameters found
ERROR: can not perform action
I would love to help add support for it, and I don't mind risking bricking the card in the process, but I have no idea where to start. So if you could guide me what actions to take / information to provide, I will do my best and share the results.
Should I open a separate issue for this discussion?
@lvmtime I've done a write up with pictures of the flash at https://github.com/geerlingguy/raspberry-pi-pcie-devices/issues/103#issuecomment-804034815
It shows you what a EEPROM chip looks like, how to flash it out of band etc. A simple clamp can save your card (backup/restore the EEPROM if the card is dead).
What you need to find out (before flashing) is
@rtreffer an update:
My board looks almost identical to the one in the writeup, except they added a heatsink over the controller chip. The writing on the flash chip says:
T25S40
PB2018
EA5(S?)089
I tried adding the ID 5e3213 to the lookup_rompar
function to return 0x700, but I got ERROR: GET_DATAx never go to zero
.
I tried unbinding the xhci_hcd as per the readme, but that did not solve the problem.
I will try out other addresses, and probably order a programmer with a clip.
I wonder if there is any way other than guessing to find out the rom config? If I dump the firmware with a reader, will it be somewhere in there?
@lvmtime ok, T25S40 is the same I got (datasheet), at it worked for me in 0x700 mode, so this is probably a bug and may warrant a dedicated issue.
Anyway, it would be interesting if you could do it out of band and add the IDs to flashrom, see https://github.com/flashrom/flashrom/pull/200/files
I assume that I might have picked the wrong config with 0x700 or that the chip has special write protection enabled in your case. The config parameter is tied to the upd chips (see the dumped table). So anything the chip does not expect should result in an error, especially for chips the vendor did not foresee.
But flashrom is way more flexible and forgiving and can try multiple ways to flash. Plus it supports unlocking of the flash chip. So it would be interesting if that works. Plus you could dump the ROM first and check if you have the same vendor specific configuration :-)
I wonder if there is any way other than guessing to find out the rom config? If I dump the firmware with a reader, will it be somewhere in there?
Non that I am aware of. And I hesitate to add ROM configurations with some random parameters without an official source. The magic numbers in the Renesas datasheet are likely based on some rules for which I have not seen any documentation and which I do not know. So there is not much I can do, sadly.
Just a quick update: my programmer and clip arrived today. I will get the card out of my PC and try to dump the flash chip in a few days and let you know if I find out anything.
Update: success!
I finally got to pull the card out of my PC, removed the heat sink, and used a ch341a programmer from AliExpress to dump the firmware and flash a new firmware.
Here is what I learned, hope it will help someone else along the way:
The flash chip model ID on my card was 0x3213 not 0x2013 as in @rtreffer write up.
I had to patch flashrom
but the rest of the configuration from @rtreffer patch worked fine.
The "vendor specific configuration" was identical to what is shown in the writeup.
There was no second copy of the firmware on the chip, nor a second copy of the "vendor specific configuration". Just the first block, then all 0xff. When building the new ROM image I followed @rtreffer instructions but skipped adding the block for the second time. This worked for my card.
The chip was not write protected. I do not know why flashing via PCIe commands did not work, but flashing with the programmer worked right away, and the card is now working without the need to load firmware on boot.
I've successfully recovered my card using https://github.com/markusj/upd72020x-load/issues/15#issuecomment-798889799 instructions. Thank you!
After writing the flash, I read it and saw corruption. I think that was because the kernel driver was also using the same USB controller chip and messing with the reads. After echo -n 0000:$device > /sys/bus/pci/drivers/xhci_hcd/unbind
reads matched what I wrote.
BTW. The card had been working for a long time. The flash got corrupted when I supplied the 2026 firmware file from k2026fwup1.exe as /lib/firmware/renesas_usb_fw.mem in /boot/initrd.img in Ubuntu 23.10. Recent kernels complain about lack of that file, but apparently, supplying it is dangerous. I could make the card work using that same firmware file and upd72020x-check-and-init from here, but I wanted firmware in flash, so it doesn't have to be loaded like that.
The k2026fwup1.exe and K2024FWUP1 Windows firmware updaters were useless. They failed when the device was non-functional, and said firmware was already up to date when upd72020x-check-and-init temporarily made the device work and I rebooted into Windows with the device working because of that.
I went down the rabbit hole of datasheets, random flash chips and flashrom recovery with an not yet supported T25S40.
But on the bright sight I've now got a working uPD720201 card and would like to share the experience with everyone.
I've bricked the device a few times and in the end recovered it with an inexpensive ch341 programmer (paid ~10€ because I wanted it fast).
Vendor Specific Configuration
When writing data to flash the FW needs to be prefixed with "vendor specific configuration". The easiest is to have a backup of your rom (use the download /
-r
option).Here is a documented version of my vendor specific configuration for a 4 port card.
so this contains nothing but a sane default for PCI and the port registers. It also sets the secret HWInit bits to 0. The card won't boot the firmware without a valid / good vendor specific configuration and good CRC16. Oh and a FW that works....
The CRC16 can be recomputed with the following c code:
NOTE: be double careful about byte order.
Building a rom image
The ROM image has 2 copies of the vendor specific configuration + firmware, aligned to the block size as noted in the datasheet. Unused space in the blocks is filled with
0xff
.My flash was undocumented but the dump contained 2 copies starting at 0x0000 and 0x4000 which translates 16kb blocks (the datasheet says 32kb and 64kb block erases are supported by the chip :facepalm:)
I generated a 512kb bytes (rom size) 0xff file (
for i in $(seq 512) ; do for j in $(seq 1024) ; do echo -ne '\xff' ; done ; done > ff
). Generating a working ROM block is then a matter ofI needed a double version of that to flash the whole ROM with flashrom:
Uploading an image
upd72020x-load is able to upload a firmware block, this should overwrite only the second copy of the firmware.
I have not verified the result, but I would expect it to work.
Flashing the whole ROM file with flashrom (offline / card pulled):
I hope this helps others to recover / flash their card to a sane firmware version.
TODO: verification of the upload should be possible by mutating the order of PCI writes in the vendor specific configuration, then uploading that through upd72020x and dumping/verifying it with flashrom