Random notes: Difference between revisions

From flashrom
Jump to navigation Jump to search
(Finding GPIOs)
Line 119: Line 119:


All TEST_* definitions are in flash.h.
All TEST_* definitions are in flash.h.
== Finding GPIOs for board enable routines ==
The following is a mail from Ron:
we just had the need to find a flash write enable on some servers.
These are Dell S1850s and we're tired of having a non-Linux-based
Flash tool, and, still worse, one to which we do not have source.
Flashrom would be great, save that it can't get the flash to write. We
decided to see if it was the classic GPIO-enabled FLASH write pin,
which is the standard it seems in PC hardware.
In this note I am just describing a program that I wrote long ago at
LANL and have used from time to time when I could not get the info I
needed on enabling FLASH write.
One thing we have found over the past 10 years: the single most common
write enable control is a GPIO attached to
a southbridge. Don't know why it always seems to be this way, but there it is.
This leads to a simple strategy to test for a GPIO enable, and to find
which one it is.
First, we find the southbridge, which in this case is an ICH5. The
GPIO programming on this part is little changed from earlier parts.
Then we find the pci function which has the GPIOs. It's usually the LPC bridge.
So for ICH5:
00:1f.0 ISA bridge: Intel Corporation 82801EB/ER (ICH5/ICH5R) LPC
Interface Bridge (rev 02)
it's that one.
So, to make it easy, rather than look at the BAR for the GPIO, just
cat /proc/ioports and find this:
0880-08bf : 0000:00:1f.0
  0880-08bf : pnp 00:06
OK, we are about ready to go. The base address of the GPIOs is 0x880.
If you're paranoid confirm it with setpci:
[root@tn4 ~]# setpci -s 0:1f.0 58.l
00000881
[root@tn4 ~]#
You need to look up the IO space mappings of SOME of the registers,
but for this simple program, not ALL. In fact all we're going to do is
read in the GPIO data level register, complement it, write it out,
then run flashrom to see if it works.
But, you ask:
* what if you read inputs and write them out nothing, so don't worry. They're inputs.
* you change GPIO pins that do some other thing well, it gets harder in that case. For instance, some laptops use a
GPIO pin to enable DRAM power. Don't worry, you'll find out if they do. In that case, you'll have to do 32 boot/test cycles in the worst case, instead of the five we do here. It actually can be instructive on a laptop to change output GPIO levels and see what happens, so this is a fun test to do anyway.
First, though, do this: flashrom -r factory.img
Then emacs factory.img, (Go into OVRWRT mode!) and look for a string like this:
F2 = Setup
I changed it to
F2 = FIXup
I may have used some other F-based words, as time went on, but that's
another story.
You want to make sure that if you really do rewrite it that it is easy
to tell! With this change, as soon as the
BIOS splash screen comes up, you will know.
OK, some code:
Just set a few things up we think we'll need.
#include <stdio.h>
#include <sys/io.h>
#define LVL 0xc
LVL is the level register for the GPIO.
Now let's go to work.
int main(int argc, char *argv[])
{
        unsigned long gpioport = 0x880;
        unsigned long gpioval;
        iopl(3);
        /* first simple test: read in all GPIOs, complement them,
        * output them, see if flashrom works */
        gpioval = inl(gpioport + LVL);
        printf("GPIO is 0x%x (default 0x1f1f0000)\n", gpioval);
        /* invert */
        gpioval = ~gpioval;
        printf("GPIO will be set to 0x%x \n", gpioval);
        outl(gpioval, gpioport + LVL);
        gpioval = inl(gpioport + LVL);
        printf("GPIO is 0x%x \n", gpioval);
}
OK, call this program 'one'. At this point, you want to try a flashrom
run. As it happens this works and is sufficient to allow us to use
flashrom!
How to finish the task? It's actually a fairly simple newtonian search.
First try gpioval ^= 0xffff0000;
If that works, then try 0xff000000, etc. etc. Even if you get it
wrong, which I did, it still doesn't take long to find it.
Warning, though: each time you try, be sure to change the FIXup string
in the rom image, to be very very sure that you really did rewrite it.
You need to be careful about this step.
Anyway, hope that is a little useful. It really is a very simple
process to find a GPIO enable. That's one reason that vendors are
going to make this much, much harder on future systems. GPIO enables
are not a security feature, in spite of what you may have heard; they
are really accident protection in case some piece of software goes
insane and starts writing to random memory locations.

Revision as of 19:08, 26 September 2009

Feel free to cut-n-paste from mails and IRC into this page. Grammar and spelling are not so important.

What numbers do FWH/LPC chips tend to start with?

39/49/50 with 49 being the most common. I've seen 39/49 chips which are parallel but that's ususual. 50 is not very common as model number.

Dirty little secrets why chips are not found although the chipset and the chip are supported

There are a few dirty little secrets about probing for flash EEPROMs:

1. old parallel flash chips often need a special board enable or the flash chip will ignore any commands (get ID, erase, write)

(that's the case with most boards of PIIX4 or older era, flash chip model names are usually *29*)

2. modern chipsets usually have more than one flash bus, and some boards even have additional bus translation chips

so for modern boards you have to check the LPC/FWH bus of the chipset, then you check the SPI bus of the chipset (if supported by the chipset and supported by flashrom), then you check the SPI bus of any LPC-to-SPI bus translation chip

on the M2N68, we only probe for LPC chips, but the chip on the board is SPI

that means the SPI chip is either attached to the SPI bus of the chipset (and we don't have a driver for that due to lack of docs) or it is behind some LPC/SPI translation chip (some of which we support)

the translation test is performed with -p it87spi

As you can see, it's complicated. Worst of all, autodetection is basically impossible.

3. To top it off, on some boards the BIOS disables all chip writes (which are needed for ID) and then it locks the chipset and unlocking is only possible by resetting (after reset, the BIOS runs and locks everything down again).

Patch submission

The following guidelines are for coreboot, but most of them apply to flashrom as well: http://www.coreboot.org/Development_Guidelines The really important part is about the Signed-off-by procedure.

We try to reuse as much code as possible and create new files only if absolutely needed, so if you find a function somewhere in the tree which already does what you want (even if it is for a totally different chip), please use it. Most chips work fine with probe_jedec even if the command sequence seems to differ at first glance. See also Command set secrets below.

The patch reviews may sound harsh, but please don't get discouraged. We try to merge simple patches after one or two iterations and complicated ones after a maximum of three iterations.

If you introduce new features (not flash chips, but stuff like partial programming, support for new external programmers, voltage handling, etc) please discuss your plans on the list first. That way, we can avoid duplicated work and know about how flashrom internals need to be adjusted and you avoid frustration if there is some disagreement about the design.

Command set secrets

This is only mentioned in very few datasheets, but it applies to most parallel (and some LPC) chips I saw: Upper address bits of commands are ignored if they are not mentioned explicitly. If a datasheet specifies the following sequence:

chip_writeb(0xAA, bios + 0x555);
chip_writeb(0x55, bios + 0x2AA);
chip_writeb(0x90, bios + 0x555);

then it is quite likely the following sequence will work as well

chip_writeb(0xAA, bios + 0x5555);
chip_writeb(0x55, bios + 0x2AAA);
chip_writeb(0x90, bios + 0x5555);

However, if the chip datasheet specifies addresses like 0x5555, you can't shorten them to 0x555.

To summarize, replacing short addresses with long addresses usually works, but the other way round usually fails.

Writing or reusing a probe function

If you have a chip with id1 0xc2, id2 0x18, first run

flashrom -V

to get an overview of the probe results for the existing probe functions. There's a good chance you'll find a probe function (or even many of them) that works for you. To automate this, run

flashrom -V|grep "0xc2.*0x18"|sed "s/.*probe/probe/"|sort|uniq

and you get a neat list of probe function names and their results, looking roughly like this:

probe_29f002: id1 0xc2, id2 0x18
probe_29f040b: id1 0xc2, id2 0x18
probe_jedec: id1 0xc2, id2 0x18
probe_stm50flw0x0x: id1 0xc2, id2 0x18
probe_w39v040c: id1 0xc2, id2 0x18
probe_winbond_fwhub: id1 0xc2, id2 0x18

As you can see, there are quite a lot of probe functions which seem to work fine (and that's mostly because of the ignored address bits). probe_jedec is the most-used function in our tree, so if the sequence looks ok, please use that one.

flashchips.c rules

Timing

In general, you should try to fill in the probe timing info even if the current probe function ignores it. Someone may later try to unify your probe function with another one, possibly with probe_jedec and you help this person a lot if he/she doesn't have to look up the timing info. To sumarize,

.probe_timing = TIMING_IGNORED,

is not liked that much. If the datasheet doesn't say anything useful about timing (such a phrase is "standard microporocessor timing"), you can use

.probe_timing = TIMING_FIXME,

and if the datasheet says there should be no delays (or doesn't mention delays at all), you should use

.probe_timing = TIMING_ZERO,

There's a special case:

.probe_timing = 0,

will give an error because flashrom assumes you just forgot to fill it in.

Testing

If you didn't test the chip, use

.tested = TEST_UNTESTED,

If you tested and everything (probe, read, erase, write) worked, use

.tested = TEST_OK_PREW,

If you only tested parts (e.g. probe and read) of the functionality, use

.tested = TEST_OK_PR,

If you tested and some things work and others failed (e.g. probe worked, erase failed), use

.tested = TEST_OK_PROBE|TEST_BAD_ERASE,

All TEST_* definitions are in flash.h.

Finding GPIOs for board enable routines

The following is a mail from Ron:

we just had the need to find a flash write enable on some servers. These are Dell S1850s and we're tired of having a non-Linux-based Flash tool, and, still worse, one to which we do not have source. Flashrom would be great, save that it can't get the flash to write. We decided to see if it was the classic GPIO-enabled FLASH write pin, which is the standard it seems in PC hardware.

In this note I am just describing a program that I wrote long ago at LANL and have used from time to time when I could not get the info I needed on enabling FLASH write.

One thing we have found over the past 10 years: the single most common write enable control is a GPIO attached to a southbridge. Don't know why it always seems to be this way, but there it is.

This leads to a simple strategy to test for a GPIO enable, and to find which one it is.

First, we find the southbridge, which in this case is an ICH5. The GPIO programming on this part is little changed from earlier parts.

Then we find the pci function which has the GPIOs. It's usually the LPC bridge.

So for ICH5: 00:1f.0 ISA bridge: Intel Corporation 82801EB/ER (ICH5/ICH5R) LPC Interface Bridge (rev 02)

it's that one.

So, to make it easy, rather than look at the BAR for the GPIO, just cat /proc/ioports and find this:

0880-08bf : 0000:00:1f.0
 0880-08bf : pnp 00:06

OK, we are about ready to go. The base address of the GPIOs is 0x880. If you're paranoid confirm it with setpci: [root@tn4 ~]# setpci -s 0:1f.0 58.l 00000881 [root@tn4 ~]#

You need to look up the IO space mappings of SOME of the registers, but for this simple program, not ALL. In fact all we're going to do is read in the GPIO data level register, complement it, write it out, then run flashrom to see if it works. But, you ask:

  • what if you read inputs and write them out nothing, so don't worry. They're inputs.
  • you change GPIO pins that do some other thing well, it gets harder in that case. For instance, some laptops use a

GPIO pin to enable DRAM power. Don't worry, you'll find out if they do. In that case, you'll have to do 32 boot/test cycles in the worst case, instead of the five we do here. It actually can be instructive on a laptop to change output GPIO levels and see what happens, so this is a fun test to do anyway.

First, though, do this: flashrom -r factory.img

Then emacs factory.img, (Go into OVRWRT mode!) and look for a string like this:

F2 = Setup

I changed it to

F2 = FIXup

I may have used some other F-based words, as time went on, but that's another story.

You want to make sure that if you really do rewrite it that it is easy to tell! With this change, as soon as the BIOS splash screen comes up, you will know.

OK, some code: Just set a few things up we think we'll need.

#include <stdio.h>
#include <sys/io.h>
#define LVL 0xc

LVL is the level register for the GPIO. Now let's go to work.

int main(int argc, char *argv[])
{
       unsigned long gpioport = 0x880;
       unsigned long gpioval;
       iopl(3);
       /* first simple test: read in all GPIOs, complement them,
        * output them, see if flashrom works */
       gpioval = inl(gpioport + LVL);
       printf("GPIO is 0x%x (default 0x1f1f0000)\n", gpioval);
       /* invert */
       gpioval = ~gpioval;
       printf("GPIO will be set to 0x%x \n", gpioval);
       outl(gpioval, gpioport + LVL);
       gpioval = inl(gpioport + LVL);
       printf("GPIO is 0x%x \n", gpioval);
}

OK, call this program 'one'. At this point, you want to try a flashrom run. As it happens this works and is sufficient to allow us to use flashrom!

How to finish the task? It's actually a fairly simple newtonian search.

First try gpioval ^= 0xffff0000;

If that works, then try 0xff000000, etc. etc. Even if you get it wrong, which I did, it still doesn't take long to find it.

Warning, though: each time you try, be sure to change the FIXup string in the rom image, to be very very sure that you really did rewrite it. You need to be careful about this step.

Anyway, hope that is a little useful. It really is a very simple process to find a GPIO enable. That's one reason that vendors are going to make this much, much harder on future systems. GPIO enables are not a security feature, in spite of what you may have heard; they are really accident protection in case some piece of software goes insane and starts writing to random memory locations.