mirror of
https://review.coreboot.org/flashrom.git
synced 2025-07-03 15:03:22 +02:00
doc: Migrate collection of docs about board enable
Collection is gathered from these docs: https://wiki.flashrom.org/Board_Enable https://wiki.flashrom.org/Board_Testing_HOWTO https://wiki.flashrom.org/Finding_Board_Enable_by_Reverse_Engineering Change-Id: I0aaa39679514f667c70ba50f6b726e8d1bd07825 Signed-off-by: Anastasia Klimchuk <aklm@flashrom.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/86329 Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
161
doc/contrib_howtos/board_enable/overview.rst
Normal file
161
doc/contrib_howtos/board_enable/overview.rst
Normal file
@ -0,0 +1,161 @@
|
||||
=====================
|
||||
Board Enable Overview
|
||||
=====================
|
||||
|
||||
**Note the document below was migrated from old website and the content >10yrs old**
|
||||
Patches to add/update documentation are very much appreciated.
|
||||
|
||||
The term "board enable" describes mainboard specific code to make flash rom
|
||||
write access possible on this mainboard. Usually this means programming some
|
||||
directly programmable output pin (usually called general purpose I/O or GPIO for short)
|
||||
of the chipset that is connect to a write protect input of the BIOS ROM chip to release write protection.
|
||||
|
||||
How to find the board enable procedure on your board
|
||||
====================================================
|
||||
|
||||
The reverse engineering method at the end is preferred because it has a bit lower risk.
|
||||
|
||||
Try & Error method on GPIO pins
|
||||
-------------------------------
|
||||
|
||||
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.
|
||||
|
||||
Reverse Engineering your BIOS
|
||||
-----------------------------
|
||||
|
||||
Reverse engineering the BIOS is more straight-forward than just poking around all GPIO pins,
|
||||
but in itself a quite advanced topic, so it is explained in detail in :doc:`reverse_engineering`.
|
||||
It basically is about analyzing what the BIOS or the vendor tool does to update the flash rom.
|
||||
|
||||
How to add the board enable to flashrom
|
||||
=======================================
|
||||
|
||||
First, find out whether the board enable method you found out is already used for another mainboard.
|
||||
In the case that it is just raising or lowering one GPIO pin, it could be quite possible that this is the case.
|
||||
As we don't like code duplication, reuse that function. If it is named something like "board_vendor_model"
|
||||
but really just changes a single pin (board_epox_ep_bx3 is an example in r803), rename it to what it does,
|
||||
which would be intel_piix4_gpo22_raise in this case. Add a comment to the function that it also works on your board.
|
||||
|
||||
If you don't find a function that does what you want, write it yourself,
|
||||
also trying to reuse codes for parts of what you have to do.
|
||||
Add a comment mentioning the board name and the involved chips in this case too.
|
||||
|
||||
After having written an enable function, you just need to add it to the board enable table
|
||||
(board_pciids_enables). This table maps PCI IDs found on the board to the correct enabling functions.
|
||||
Be sure to write a good match (which mostly means that you have to choose onboard chips
|
||||
that have vendor-assigned subsystem IDs that are unique for each board that vendor produced).
|
||||
If a unique match is not possible at all, provide vendor and model name (short form, usually lower case only)
|
||||
as "coreboot IDs" for use with the "-m" option, which means that the board won't be autodetected
|
||||
but can be selected by hand. The board name and vendor name following the coreboot ID strings are freeform
|
||||
and should disply vendor and model name in their preferred form.
|
Reference in New Issue
Block a user