mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-26 22:52:34 +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:
parent
9ef4da746b
commit
971ea27d16
72
doc/contrib_howtos/board_enable/board_testing_howto.rst
Normal file
72
doc/contrib_howtos/board_enable/board_testing_howto.rst
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
===================
|
||||||
|
Board Testing HOWTO
|
||||||
|
===================
|
||||||
|
|
||||||
|
**Note the document below was migrated from old website and the content >10yrs old**
|
||||||
|
Patches to add/update documentation are very much appreciated.
|
||||||
|
|
||||||
|
This page gives you mainly hints on how to test flashrom support on mainboards.
|
||||||
|
Testing for graphics / network / SATA cards and external programmer devices is similar but less dangerous.
|
||||||
|
|
||||||
|
.. container:: danger, admonition
|
||||||
|
|
||||||
|
Important information
|
||||||
|
|
||||||
|
DO NOT ATTEMPT TO FOLLOW THESE INSTRUCTIONS UNLESS YOU KNOW WHAT YOU ARE DOING!
|
||||||
|
THIS CAN RENDER YOUR MAINBOARD TOTALLY UNUSABLE! YOU HAVE BEEN WARNED!
|
||||||
|
|
||||||
|
* If you have a laptop/notebook/netbook, please do NOT try flashrom because interactions
|
||||||
|
with the EC on these machines might crash your machine during flashing.
|
||||||
|
flashrom tries to detect if a machine is a laptop, but not all laptops follow the standard,
|
||||||
|
so this is not 100% reliable.
|
||||||
|
|
||||||
|
* To check whether flashrom knows about your chipset and ROM chip, run ``flashrom -p internal``.
|
||||||
|
|
||||||
|
* If it says ``"Found chipset CHIPSETNAME..."`` and ``"CHIPNAME found at..."`` that's a good first sign.
|
||||||
|
|
||||||
|
* To check if you can read the existing BIOS image from the chip, run ``flashrom -p internal -r backup.bin``.
|
||||||
|
Make sure that backup.bin contains a useful BIOS image (some chipsets will return 0xff for large areas
|
||||||
|
of flash without any error messages, but there might be actually large areas of 0xff in the original image as well).
|
||||||
|
|
||||||
|
* Now the really important part, checking if *writing* an image on the chip works:
|
||||||
|
|
||||||
|
* First, if the board has a flash socket and you have spare chips,
|
||||||
|
make sure you have a backup chip containing the original BIOS.
|
||||||
|
Also, you should have verified that it actually boots your system successfully.
|
||||||
|
Put away that backup chip somewhere safe and insert a chip which you can safely
|
||||||
|
overwrite (e.g. an empty one you bought).
|
||||||
|
|
||||||
|
* If that is not possible make sure you have some other way for complete recovery,
|
||||||
|
e.g. an external programmer that can do :doc:`/user_docs/in_system` on the board in question.
|
||||||
|
|
||||||
|
* Then write an image onto the chip, which is different from what's on the chip right now:
|
||||||
|
``flashrom -p internal -w new.bin``. If the image is equal you will get a notice since r1680.
|
||||||
|
If this works and flashrom reports "VERIFIED" your board is supported by flashrom.
|
||||||
|
|
||||||
|
* If not, you might try to enable the "Enable BIOS Update" or "Write-protect BIOS"
|
||||||
|
or similar options in your BIOS menu first, or set a jumper on your board
|
||||||
|
(this is highly board-dependent). Also, you might have to use the flashrom --mainboard
|
||||||
|
switch for some boards.
|
||||||
|
|
||||||
|
* If none of the above helps (but flashrom still *does* detect your chipset and ROM chip),
|
||||||
|
there's quite likely a board-specific initialization required in flashrom,
|
||||||
|
which is non-trivial to add (e.g. toggling certain custom GPIO lines etc).
|
||||||
|
In that case, contact us as we may be able to help.
|
||||||
|
|
||||||
|
* If you can't risk a write on a given chip and if the chip is SPI, the following guidelines may help:
|
||||||
|
|
||||||
|
* Try probing.
|
||||||
|
|
||||||
|
* For ICH/VIA SPI, lockdown can mean probe works, but write/erase or even read doesn't.
|
||||||
|
It can also mean that probe does not work, but write/read/erase (or any subset thereof) would work.
|
||||||
|
For all other SPI chipsets, there is no such lockdown, so you can issue any erase/write/read command.
|
||||||
|
|
||||||
|
* However, some SPI chips have a WP# pin which causes the block protection bits to become readonly.
|
||||||
|
Now if flashrom has a generic block protection checker for your chip, we're able to figure out
|
||||||
|
if write/erase is possible. Basically, you can check if you need a board enable
|
||||||
|
by setting all block protection bits, then unsetting them. If either of the operations fail,
|
||||||
|
you need a board enable. If they succeed, erase and write are guaranteed to work.
|
||||||
|
|
||||||
|
Please tell us about your results by sending the output of flashrom commands you ran,
|
||||||
|
the exact board manufacturer and model name, and all of your observations and test results
|
||||||
|
to the flashrom :ref:`mailing list`.
|
15
doc/contrib_howtos/board_enable/index.rst
Normal file
15
doc/contrib_howtos/board_enable/index.rst
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
=======================
|
||||||
|
Board enable collection
|
||||||
|
=======================
|
||||||
|
|
||||||
|
The term "board enable" describes mainboard specific code to make
|
||||||
|
flash rom write access possible on this mainboard.
|
||||||
|
|
||||||
|
Patches to add/update documentation are very much appreciated.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
overview
|
||||||
|
board_testing_howto
|
||||||
|
reverse_engineering
|
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.
|
107
doc/contrib_howtos/board_enable/reverse_engineering.rst
Normal file
107
doc/contrib_howtos/board_enable/reverse_engineering.rst
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
===========================================
|
||||||
|
Finding Board Enable by Reverse Engineering
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
**Note the document below was migrated from old website and the content >10yrs old**
|
||||||
|
Patches to add/update documentation are very much appreciated.
|
||||||
|
|
||||||
|
Finding the board enable code inside the flash rom seems like looking for a needle in a haystack,
|
||||||
|
but using the right search method might be as easy as finding a magnetic needle using a strong magnet.
|
||||||
|
This page explains approaches to find the board enable code in different vendor BIOSes.
|
||||||
|
|
||||||
|
Useful Tools
|
||||||
|
============
|
||||||
|
|
||||||
|
For free/open source reverse engineering tools, take a look at objdump and ndisasm.
|
||||||
|
|
||||||
|
For objdump, use::
|
||||||
|
|
||||||
|
objdump -b binary -m i386 -M i8086,intel --disassemble-all datafile.bin
|
||||||
|
|
||||||
|
(you might want to leave off the "intel" option if you prefer the AT&T assembler syntax)
|
||||||
|
|
||||||
|
But as all free tools we know of are not comparable to the commercial tool `IDA Pro <http://www.hex-rays.com/idapro/>`_
|
||||||
|
which has free-as-in-beer version for non-commercial use `IDA 4.9 Freeware <http://www.hex-rays.com/idapro/idadownfreeware.htm>`_
|
||||||
|
which has all features needed for BIOS analysis, it should be mentioned here, too.
|
||||||
|
|
||||||
|
General Hints
|
||||||
|
=============
|
||||||
|
|
||||||
|
* Get an lspci of that board before you start. Best way is to request it from the board owner,
|
||||||
|
but you might find it on Google. Everest Reports of systems include an hexdump of config space at the end.
|
||||||
|
|
||||||
|
* Get used to the binary PCI address specification: Device/function ID is combined into one byte,
|
||||||
|
the device ID (0..31) is multiplied by eight and added/ored with the function ID (0..7).
|
||||||
|
Most PCI addresses in the BIOS have the resulting byte hardcoded.
|
||||||
|
So if this byte is 0xF9 for example, it is 1f.1 in lspci syntax.
|
||||||
|
|
||||||
|
* In/Out to fixed I/O addresses above 0x400 is usually accessing GPIO pins.
|
||||||
|
The base address can usually be found in PCI config space, but many BIOS vendors hard-code
|
||||||
|
the address as they know what address their own BIOS configures the GPIO address to.
|
||||||
|
Typical base values are 0x400 or 0x800 on Intel ICH and 0x4400 on nVidia MCP.
|
||||||
|
Check the GPIO setting function for the chipset on the board early to recognize patterns
|
||||||
|
in the assembly code (you *did* get the lspci before you started,
|
||||||
|
so you can easily look up which chipset and which GPIO method is used, didn't you?)
|
||||||
|
|
||||||
|
Vendor-specific Hints
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Award BIOS
|
||||||
|
----------
|
||||||
|
|
||||||
|
First, you need the runtime BIOS, this is the 128KB thats available at the addresses E0000-FFFFF
|
||||||
|
when the system is running. You can either obtain it by dumping from a running system,
|
||||||
|
or by running "lha x bios.bin" on a BIOS image as it gets written to the chip.
|
||||||
|
|
||||||
|
From the 128KB you only need the second half (the f-segment). In this segment, look for the text "AWDFLASH".
|
||||||
|
This signature is followed by eleven 16-bit procedure offsets (all these procedures reside in the segment F000).
|
||||||
|
The second procedure offset points to the board/chipset enable function.
|
||||||
|
The third procedure offset points to the board/chipset disable function.
|
||||||
|
|
||||||
|
Useful hints:
|
||||||
|
|
||||||
|
* PCI register manipulation is common. If you find a procedure that outputs something to port CF8,
|
||||||
|
it accesses PCI configuration space. If a second out instruction follows, it is a PCI config write,
|
||||||
|
if an in instruction follows, it's a PCI config read. In AWARD BIOS code,
|
||||||
|
the Device/Function ID is passed in CH, the config space address in CL. Bus number
|
||||||
|
(if used at all, check the procedure called) in BH or BL. Data is exchanged via AL/AX/EAX
|
||||||
|
|
||||||
|
AMI BIOS
|
||||||
|
--------
|
||||||
|
|
||||||
|
Get the runtime F-segment of the BIOS. Currently there is no automated extraction method
|
||||||
|
available than dumping from a running machine. Flashing is handled through Int 16
|
||||||
|
(entry point at F000:E82E, look for AH=E0, usually catched in the very beginning),
|
||||||
|
but can also be found in a different way. For each similar group of flash chips,
|
||||||
|
there is a call table with three 16 bit offsets for identifying, erasing and writing the chip.
|
||||||
|
In most AMI biosses, this table is quite closely followed by a pointer to the flash chip name
|
||||||
|
and a list of strings containing all flash chip names in this group. The identification procedure
|
||||||
|
adjusts the pointer to point to the right string. Finding flashing procedures can be done by searching
|
||||||
|
for magic constants like 0x2AA, 0xAAA, 0x2AAA and looking at the code. All low-level-flashing code
|
||||||
|
for one group is quite close together, so poking around to find the main entry points is feasible.
|
||||||
|
|
||||||
|
There is a table at some other place that (amongs other data) contains the offset
|
||||||
|
of the call table for each group. The offset of this table is referenced in the generic flashing code
|
||||||
|
that tends to be shortly before the group-specific code. Usually, on detection the address of one group
|
||||||
|
call table is stored in a "current group" pointer, which in the running system points to one
|
||||||
|
of the group entries, too. There will be a function that references this current group pointer
|
||||||
|
and calls the erase function [bx+2] (maybe via a looping helper function) and the write function
|
||||||
|
[bx+4] in quick succession. The function called before the erase function is the flash enable function.
|
||||||
|
|
||||||
|
If you go the forward route, trace Int 16, AX=E025 which should call the erase procedure.
|
||||||
|
|
||||||
|
Useful hints:
|
||||||
|
|
||||||
|
* PCI access in AMI commonly uses a bit fiddling function. This function takes the bus number in DH,
|
||||||
|
the device/function number in DL, a bit mask in BH, bits to be set in BL, and the config space address in AH.
|
||||||
|
It clears all bits set in BH and sets the bit set in BL. It returns the old value (all bits) in AL,
|
||||||
|
and sets the zero flag if all bits in BH were already clear. This function is wrapped by a generic bit setting
|
||||||
|
and a generic bit clearing function. These functions take a bit mask (usually only one bit set) in AL.
|
||||||
|
The bit setting function calls the bit manipulation function with BH=0 and BL=AL,
|
||||||
|
the bit clearing function calls the bit manipulation function with BH=AL and BL=0.
|
||||||
|
|
||||||
|
FOSDEM presentation
|
||||||
|
===================
|
||||||
|
|
||||||
|
There was a talk at FOSDEM 2010 about reverse engineering board enables.
|
||||||
|
The `slides are here <http://people.freedesktop.org/~libv/flash_enable_bios_reverse_engineering_(FOSDEM2010_-_slides).pdf>`_
|
@ -8,6 +8,7 @@ Contributors howtos
|
|||||||
how_to_mark_chip_tested
|
how_to_mark_chip_tested
|
||||||
how_to_add_unit_test
|
how_to_add_unit_test
|
||||||
laptops_and_ec
|
laptops_and_ec
|
||||||
|
board_enable/index
|
||||||
|
|
||||||
../how_to_add_docs
|
../how_to_add_docs
|
||||||
../how_to_support_flashrom
|
../how_to_support_flashrom
|
||||||
|
Loading…
x
Reference in New Issue
Block a user