Anastasia Klimchuk submitted this change.
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>
---
A doc/contrib_howtos/board_enable/board_testing_howto.rst
A doc/contrib_howtos/board_enable/index.rst
A doc/contrib_howtos/board_enable/overview.rst
A doc/contrib_howtos/board_enable/reverse_engineering.rst
M doc/contrib_howtos/index.rst
5 files changed, 356 insertions(+), 0 deletions(-)
diff --git a/doc/contrib_howtos/board_enable/board_testing_howto.rst b/doc/contrib_howtos/board_enable/board_testing_howto.rst
new file mode 100644
index 0000000..1847156
--- /dev/null
+++ b/doc/contrib_howtos/board_enable/board_testing_howto.rst
@@ -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`.
diff --git a/doc/contrib_howtos/board_enable/index.rst b/doc/contrib_howtos/board_enable/index.rst
new file mode 100644
index 0000000..d6808e4
--- /dev/null
+++ b/doc/contrib_howtos/board_enable/index.rst
@@ -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
diff --git a/doc/contrib_howtos/board_enable/overview.rst b/doc/contrib_howtos/board_enable/overview.rst
new file mode 100644
index 0000000..98e1748
--- /dev/null
+++ b/doc/contrib_howtos/board_enable/overview.rst
@@ -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.
diff --git a/doc/contrib_howtos/board_enable/reverse_engineering.rst b/doc/contrib_howtos/board_enable/reverse_engineering.rst
new file mode 100644
index 0000000..c188d55
--- /dev/null
+++ b/doc/contrib_howtos/board_enable/reverse_engineering.rst
@@ -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>`_
diff --git a/doc/contrib_howtos/index.rst b/doc/contrib_howtos/index.rst
index 3df2fac..bbdb9a7 100644
--- a/doc/contrib_howtos/index.rst
+++ b/doc/contrib_howtos/index.rst
@@ -8,6 +8,7 @@
how_to_mark_chip_tested
how_to_add_unit_test
laptops_and_ec
+ board_enable/index
../how_to_add_docs
../how_to_support_flashrom
To view, visit change 86329. To unsubscribe, or for help writing mail filters, visit settings.