Patchwork DOS flashrom - partial success on Dell Optiplex 320

Submitter Carl-Daniel Hailfinger
Date 2010-04-24 00:07:15
Message ID <>
Download mbox | patch
Permalink /patch/1260/
State Bitrotted
Headers show


Carl-Daniel Hailfinger - 2010-04-24 00:07:15
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 <>


Index: flashrom-sb600_spibar/flashrom.8
--- flashrom-sb600_spibar/flashrom.8	(Revision 994)
+++ flashrom-sb600_spibar/flashrom.8	(Arbeitskopie)
@@ -222,12 +222,20 @@ 
 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
 .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.
+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
+.B "flashrom -p internal:sb600spibar=addr"
+syntax with addr being the memory address you want to have the SPI BAR at.
 .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,
 		/* 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);