Anastasia Klimchuk has submitted this change. ( https://review.coreboot.org/c/flashrom/+/86329?usp=email )
Change subject: doc: Migrate collection of docs about board enable ......................................................................
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(-)
Approvals: build bot (Jenkins): Verified Stefan Reinauer: Looks good to me, approved
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