Hi, I tried the latest build and didn't get a crash - well mmap() emulation seems to be finally working ;) but when I tried to dump flash with -V -r it hanged after probing chip: AE49F2008, skipped I wait a minute but it didn't probed other chips, so I pressed CTRL+C... It also seems to have some problems with delay loop calibration. Maybe you can use DJGPP functions udelay() and uclock() with ~1us granularity. So I opened the case and lookoed for the flash chip - PMC Pm49FL004T and passed - c Pm49FL004 option. Then the chip was probed OK and flash content dumped, well done. http://rayer.ic.cz/350d/flashrom.jpg Here's the dumped BIOS image http://rayer.ic.cz/350d/dell320.bin
Martin
Hi Martin,
thanks for testing this.
On 07.04.2010 12:21, rayer wrote:
I tried the latest build and didn't get a crash - well mmap() emulation seems to be finally working ;)
Great.
but when I tried to dump flash with -V -r it hanged after probing chip: AE49F2008, skipped I wait a minute but it didn't probed other chips, so I pressed CTRL+C...
This is really bad. It means that low memory access to the SPI controller MMIO region still does not work reliably.
It also seems to have some problems with delay loop calibration. Maybe you can use DJGPP functions udelay() and uclock() with ~1us granularity.
The big problem here is that gettimeofday() apparently does not have any usable precision on your machine (maybe DOS/DJGPP related). Sometimes (always?) the time has not changed at all even after we delay for 10000 us and that causes the timer code to bail out.
So I opened the case and lookoed for the flash chip - PMC Pm49FL004T and passed - c Pm49FL004 option. Then the chip was probed OK and flash content dumped, well done.
Great.
To summarize: - gettimeofday() has precision worse than 10 ms and that triggers timer recalculation. - Low uncached memory access is still broken on DOS or our SB600 SPI code has a bug. It would be cool if you could run flashrom under Linux on that machine (no read/write needed) and post the output in verbose mode. OTOH, it is possible that the BIOS screwed up caching of the SB600 SPI MMIO region and in this case we can't do anything about it because checking MTRRs is infeasible.
Regards, Carl-Daniel
Hi,
The big problem here is that gettimeofday() apparently does not have any usable precision on your machine (maybe DOS/DJGPP related). Sometimes (always?) the time has not changed at all even after we delay for 10000 us and that causes the timer code to bail out.
Yes this function in DJGPP probably use standard timer at 18,2Hz (55ms) So I recomended uclock()...
To summarize:
- gettimeofday() has precision worse than 10 ms and that triggers timer
recalculation.
- Low uncached memory access is still broken on DOS or our SB600 SPI
code has a bug. It would be cool if you could run flashrom under Linux on that machine (no read/write needed) and post the output in verbose mode. OTOH, it is possible that the BIOS screwed up caching of the SB600 SPI MMIO region and in this case we can't do anything about it because checking MTRRs is infeasible.
Today I tried linux version (static linked by Rudolf) and it hanged at probing of the same chip, see log. So it's not DJGPP releated problem.
Martin
flashrom v0.9.1-r994 on Linux 2.6.24.07-alt16 (i686), built with libpci 3.0.0, GCC 4.4.1 No coreboot table found. DMI string system-manufacturer: "Dell Inc. " DMI string system-product-name: "OptiPlex 320 " DMI string system-version: "Not Specified" DMI string baseboard-manufacturer: "Dell Inc. " DMI string baseboard-product-name: "0CU395" DMI string baseboard-version: " " DMI string chassis-type: "Tower" Found chipset "AMD SB600", enabling flash write... SPI base address is at 0xd8000 AltSpiCSEnable=0, SpiRomEnable=0, AbortEnable=0 PrefetchEnSPIFromIMC=0, PrefetchEnSPIFromHost=0, SpiOpEnInLpcMode=0 SpiArbEnable=1, SpiAccessMacRomEn=1, SpiHostAccessRomEn=1, ArbWaitCount=4, SpiBridgeDisable=0, DropOneClkOnRd=0 GPIO11 used for SPI_DO GPIO12 used for SPI_DI GPIO31 used for SPI_HOLD GPIO32 used for SPI_CS GPIO47 used for SPI_CLK ROM strap override is not active OK. This chipset supports the following protocols: LPC,FWH,SPI. Calibrating delay loop... 1987M loops per second, 10 myus = 10 us, 100 myus = 99 us, 1000 myus = 1001 us, 10000 myus = 9996 us, OK. Probing for AMD Am29F010A/B, 128 KB: skipped. Probing for AMD Am29F002(N)BB, 256 KB: skipped. Probing for AMD Am29F002(N)BT, 256 KB: skipped. Probing for AMD Am29F016D, 2048 KB: skipped. Probing for AMD Am29F040B, 512 KB: skipped. Probing for AMD Am29F080B, 1024 KB: skipped. Probing for AMD Am29LV040B, 512 KB: skipped. Probing for AMD Am29LV081B, 1024 KB: skipped. Probing for ASD AE49F2008, 256 KB: skipped. Probing for Atmel AT25DF021, 256 KB: [it hangs here, breaked by ctrl-c]
Hi Martin,
On 23.04.2010 22:17, RayeR wrote:
The big problem here is that gettimeofday() apparently does not have any usable precision on your machine (maybe DOS/DJGPP related). Sometimes (always?) the time has not changed at all even after we delay for 10000 us and that causes the timer code to bail out.
Yes this function in DJGPP probably use standard timer at 18,2Hz (55ms) So I recomended uclock()...
Ah yes. I'll change that soon. For now, the delay function will complain, but it should work.
To summarize:
- gettimeofday() has precision worse than 10 ms and that triggers timer
recalculation.
- Low uncached memory access is still broken on DOS or our SB600 SPI
code has a bug. It would be cool if you could run flashrom under Linux on that machine (no read/write needed) and post the output in verbose mode. OTOH, it is possible that the BIOS screwed up caching of the SB600 SPI MMIO region and in this case we can't do anything about it because checking MTRRs is infeasible.
Today I tried linux version (static linked by Rudolf) and it hanged at probing of the same chip, see log. So it's not DJGPP releated problem.
Great, thanks for checking. The patch below will allow you to relocate the SB600/SB700 SPI memory BAR to a location that is less problematic. Basically, you want a memory address which is not used by other memory BARs and not backed by RAM. And the address should be in a region which is routed to the southbridge. If you have such an address (the free region needs to be at least 4kB in size), please run flashrom -p internal:sb600spibar=addr and replace addr with the address you want (e.g. 0xfd000000)
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-sb600_spibar/flashrom.8 =================================================================== --- flashrom-sb600_spibar/flashrom.8 (Revision 994) +++ flashrom-sb600_spibar/flashrom.8 (Arbeitskopie) @@ -222,12 +222,20 @@ .sp If your mainboard uses an ITE IT87 series Super I/O for LPC<->SPI flash bus translation, flashrom should autodetect that configuration. You can use +.sp .B "flashrom -p internal:it87spiport=portnum" syntax as explained in the .B it87spi programmer section to use a non-default port for controlling the IT87 series Super I/O. In the unlikely case flashrom doesn't detect an active IT87 LPC<->SPI bridge, you can try to force recognition by using the it87spi programmer. +.sp +If your mainboard uses a SB600/SB700 family southbridge and the default SPI +memory BAR is placed at an inconvenient location (e.g. in cached memory), +you can use +.sp +.B "flashrom -p internal:sb600spibar=addr" +syntax with addr being the memory address you want to have the SPI BAR at. .TP .BR "dummy " programmer An optional parameter specifies the bus types it Index: flashrom-sb600_spibar/chipset_enable.c =================================================================== --- flashrom-sb600_spibar/chipset_enable.c (Revision 994) +++ flashrom-sb600_spibar/chipset_enable.c (Arbeitskopie) @@ -809,9 +809,11 @@ static int enable_flash_sb600(struct pci_dev *dev, const char *name) { uint32_t tmp, prot; + uint8_t sb600_spiconfig; uint8_t reg; struct pci_dev *smbus_dev; int has_spi = 1; + char *sb600_spibar_text = NULL;
/* Clear ROM protect 0-3. */ for (reg = 0x50; reg < 0x60; reg += 4) { @@ -837,8 +839,24 @@
/* Read SPI_BaseAddr */ tmp = pci_read_long(dev, 0xa0); + sb600_spiconfig = tmp & 0x1f; tmp &= 0xffffffe0; /* remove bits 4-0 (reserved) */ printf_debug("SPI base address is at 0x%x\n", tmp); + if (programmer_param && !strlen(programmer_param)) { + free(programmer_param); + programmer_param = NULL; + } + if (programmer_param) { + sb600_spibar_text = extract_param(&programmer_param, + "sb600spibar=", ",:"); + if (sb600_spibar_text) { + tmp = strtoul(sb600_spibar_text, (char **)NULL, 0); + msg_pinfo("Forcing SB600 flash BAR to 0x%08x\n", + tmp); + pci_write_long(dev, 0xa0, tmp | sb600_spiconfig); + free(sb600_spibar_text); + } + }
/* If the BAR has address 0, it is unlikely SPI is used. */ if (!tmp) @@ -849,14 +867,15 @@ sb600_spibar = physmap("SB600 SPI registers", tmp & 0xfffff000, 0x1000); /* The low bits of the SPI base address are used as offset into - * the mapped page. + * the mapped page. The BAR can never be outside the allocated + * area due to BAR alignment rules. */ sb600_spibar += tmp & 0xfff;
- tmp = pci_read_long(dev, 0xa0); printf_debug("AltSpiCSEnable=%i, SpiRomEnable=%i, " - "AbortEnable=%i\n", tmp & 0x1, (tmp & 0x2) >> 1, - (tmp & 0x4) >> 2); + "AbortEnable=%i\n", sb600_spiconfig & 0x1, + (sb600_spiconfig & 0x2) >> 1, + (sb600_spiconfig & 0x4) >> 2); tmp = (pci_read_byte(dev, 0xba) & 0x4) >> 2; printf_debug("PrefetchEnSPIFromIMC=%i, ", tmp);