Random notes: Difference between revisions

From flashrom
Jump to navigation Jump to search
 
(24 intermediate revisions by 6 users not shown)
Line 1: Line 1:
Feel free to cut-n-paste from mails and IRC into this page. Grammar and spelling are not so important.
Feel free to cut-n-paste from mails and IRC into this page. Grammar and spelling are not so important.
== How to check for valid AMD IMC firmware in an image? ==
They must have the signature '''_AMD_IMC_C''' in them. So just look for that, for example with <code>strings -a -10 {IMAGENAME} | grep _AMD_IMC_C</code>.
The blob actually starts 8 kB (0x2000) before that string, usually at 0x20000 of the flash image (but other fixed offsets are possible too). See also http://www.coreboot.org/AMD_IMC.


== What numbers do FWH/LPC chips tend to start with? ==
== What numbers do FWH/LPC chips tend to start with? ==
Line 11: Line 16:
1. old parallel flash chips often need a special board enable or the flash chip will ignore any commands (get ID, erase, write)
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*)
(that's the case with most boards of PIIX4 or older era, flash chip model names are usually *29*) Also, many *28* chips require high voltage to respond to any identification routines.


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


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).
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|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 ==
== Command set secrets ==
Line 120: Line 113:
All TEST_* definitions are in flash.h.
All TEST_* definitions are in flash.h.


== Finding GPIOs for board enable routines ==
== Bios Shadowing ==
 
Shadowing the ROM is either happening below 1 MB (old 16bit address space), and we don't care about that area, regardless of how much you shadow. Or it is happening close to 4 GB, but for that you either need a processor which can handle non-contiguous RAM  (basically, AMD, but only if you don't use onboard video) or if you have 4 GB installed in the machine and don't mind very very weird problems on bootup so basically it is very very extremely unlikely that shadowing can bite us.


The following is a mail from Ron:
But, other features like bios flashing protection set in bios are affecting flashrom.


we just had the need to find a flash write enable on some servers.
== Bios content changes between reboots ==
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
Many BIOSes out there change a few bytes in the ROM on each boot. They store boot date/time and some configuration data. Such
LANL and have used from time to time when I could not get the info I
changes are expected. As long as the readback doesn't change between subsequent reads (without any boot in between), you're in the clear.
needed on enabling FLASH write.


One thing we have found over the past 10 years: the single most common
And if you are patient enough you can figure what bios change and where.
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
== Writing a chip driver ==
which one it is.


First, we find the southbridge, which in this case is an ICH5. The
For parallel/LPC/FWH chips:
GPIO programming on this part is little changed from earlier parts.
* Check if you can use the stuff in jedec.c . If yes, use the functions directly instead of copying them.
* If jedec.c is not compatible with your chip, try to find a chip driver file which works for your chip. Use these functions directly instead of copying them.


Then we find the pci function which has the GPIOs. It's usually the LPC bridge.
For SPI chips:
* spi.c contains both chip-specific command functions and SPI general infrastructure. Try to find compatible functions in there and use them directly instead of copying. spi.c will be split into infrastructure and chip commands in the future, so check if this note still applies.


So for ICH5:
For all chips:
* Hook up the driver functions in flashchips.c . Easiest way is to copy the entry for a similar chip and modify as needed.
* IDs are defined in flashchips.h which also acts as a database for IDs not yet hooked up and IDs which are aliases for other chips (see the comments in there).


00:1f.0 ISA bridge: Intel Corporation 82801EB/ER (ICH5/ICH5R) LPC
== Writing a programmer driver ==
Interface Bridge (rev 02)


it's that one.
This task entirely depends on the communication protocol you want to use for talking to the chip. There are two main interface classes: Address-value pairs (Parallel/LPC/FWH protocols) and explicit commands (SPI). Our generic programmer infrastructure can handle both, even in the same programmer.


So, to make it easy, rather than look at the BAR for the GPIO, just
The easiest way to get started is to hack dummyflasher.c which supports both interface classes. You get immediate results by running
cat /proc/ioports and find this:
flashrom -p dummy
0880-08bf : 0000:00:1f.0
without having to touch a single line outside dummyflasher.c . Once your hacked up dummyflasher does something useful (that means it differs in a nontrivial way from vanilla dummyflasher), we strongly suggest post it to the mailing list. Then we can help you separate your code from dummyflasher and make it a real driver on its own (some of us have predefined templates for that). You don't have to touch any code or Makefile outside your driver if you don't want to.
0880-08bf : pnp 00:06


OK, we are about ready to go. The base address of the GPIOs is 0x880.
A new programmer driver is automatically added to the output of ''flashrom --help'' and the only file you have to touch outside your own driver file is the man page. Qualified help is available for that task, so you can get by with supplying the text if you don't know man page syntax.
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,
Generally, we recommend to submit early and often, even if your code is nowhere near ready. Maybe someone else already has unfinished/unreleased code for your favourite programmer.
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
Programmer drivers can be merged even if they are not completely working yet, but they will be disabled by default in that case. You save yourself the hassle of carring a large patch forward and can contentrate on driver development instead of forward porting your patch every few commits (which is painful to do over large time periods). Plus, your code gets some exposure on the list and interested users may help with development and debugging.


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


F2 = Setup
(In case you wondered, this is not about concurrent execution.)


I changed it to
Here is a patch to use a generic locking infrastructure: http://patchwork.coreboot.org/patch/581/


F2 = FIXup
I (Carl-Daniel) would like to keep the now-unused chip driver files around until we have the locking
conversion/refactoring done. My patch to do this (see above) probably doesn't apply
anymore, and it also can't handle partial locking/unlocking. I can
repost next week, but I welcome comments about the interface.


I may have used some other F-based words, as time went on, but that's
One of my
another story.
new ideas is to have the locking function take an struct lockblock
{blocksize, lockstatus}array as parameter. To retrieve the locking
status, one would pass action=get array=NULL and the function would
allocate and return the lockblock array. To set the locking status, one
would first retrieve the array (see previous sentence), then walk it and
set the desired status of each lockblock, then pass action=set and the
modified array to the locking function. Advantages: You can do lock
printing in a generic function which just walks the returned array, you
can handle enabling and disabling all locks in the same way. Even
something like (un)locking only a specific region can be done with a
generic wrapper.


You want to make sure that if you really do rewrite it that it is easy
Unsolved (well, design is not completely ready): Where should we store
to tell! With this change, as soon as the
lock blocks?
BIOS splash screen comes up, you will know.
* In struct flashchip (works mostly OK for LPC/FWH chips because locking status is usually stored in register space at the corresponding block address, will be a nightmare for SPI chips because there are usually just 4 bits in the status reg for this, and undecided for Parallel chips because they have the status reg variant and the corresponding block address variant).
* In the chip drivers (would avoid cluttering flashchips.c, handle the various locking encodings (bitfield, corresponding address in register space)


OK, some code:
== Figuring out if you need a board enable or a new chip driver ==
Just set a few things up we think we'll need.
To determine if we're missing a chip definition or if we need a board enable. Just use grep on the log:
grep -v "parity violation"
To narrow it down further, try:
grep -v "id1 is normal flash content, id2 is normal flash content"
And of course you want to ignore the skipped probes:
grep -v "skipped"
The remaining lines are worth examining, and if those look bogus as well, you can bet that we just need a board enable.


#include <stdio.h>
== Porting flashrom to different platforms ==
#include <sys/io.h>


  #define LVL 0xc
=== GCC/clang builtin #defines ===
Get them by running (replace $CC with your compiler)
  echo | $CC -E -dM -


LVL is the level register for the GPIO.
* GCC 4.3.4 on x86 Cygwin: http://coreboot.pastebin.com/57Ejhgtp
Now let's go to work.
* GCC 4.2.1 on x86 Linux: http://coreboot.pastebin.com/QKkbDTu7
* clang/LLVM 2.6.99svn97231 on x86 Linux: http://coreboot.pastebin.com/F1svusL5
* GCC 4.1.2 on PPC Linux: http://coreboot.pastebin.com/QRR8e1W7


int main(int argc, char *argv[])
== Finding unused functions in C code ==
{
        unsigned long gpioport = 0x880;
        unsigned long gpioval;


        iopl(3);
There's the straightforward approach which fails:
gcc -Wunused-function
GCC 4.2 and 4.3 are totally unable to find any unused functions that way (except if they are marked static, and that defeats the purpose of finding unused global functions), and I doubt their testsuite even checks for that. Later gcc may suffer from that misfeature as well.


        /* 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 */
There's the complicated approach which works somewhat (no idea if this works on all gcc/binutils combinations):
        gpioval = ~gpioval;
gcc -ffunction-sections -Wl,--gc-sections -Wl,--print-gc-sections -fno-inline -combine *.c
        printf("GPIO will be set to 0x%x \n", gpioval);
* -ffunction-sections causes each function to end up in a different section.
        outl(gpioval, gpioport + LVL);
* --gc-sections causes the linker to drop unused sections (i.e. unused functions).
        gpioval = inl(gpioport + LVL);
* --print-gc-sections causes the linker to print a diagnostic message for each dropped function.
        printf("GPIO is 0x%x \n", gpioval);
* -fno-inline tells gcc not to screw up as gcc will happily emit functions twice (or even more often): inlined and non-inlined, and the non-inlined function will be dropped and warned about even though the code was used (albeit auto-inlined in another place).
}
* -combine allows you to get meaningful diagnostics for the whole program


OK, call this program 'one'. At this point, you want to try a flashrom
Do NOT use -fwhole-program because gcc will then optimize away any unused functions without any diagnostic message.
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.
== Embedding cwsdpmi in the binary produced with "make djgpp-dos" ==


First try gpioval ^= 0xffff0000;
[13/07/2010 17:05:34] <ruik> carldani: you can embed the cwsdpmni into final executable


If that works, then try 0xff000000, etc. etc. Even if you get it
[13/07/2010 17:05:47] <ruik> carldani: and also you can compress that with UPX
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
[13/07/2010 17:18:57] <ruik> i586-pc-msdosdjgpp-objcopy flashrom.exe a.coff -O coff-go32
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
[13/07/2010 17:19:12] <ruik> cat CWSDSTUB.EXE a.coff >x.exe
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.


== Bios Shadowing ==
[13/07/2010 17:19:26] <ruik> upx --best x.exe


Shadowing the ROM is either happening below 1 MB (old 16bit address space), and we don't care about that area, regardless of how much you shadow. Or it is happening close to 4 GB, but for that you either need a processor which can handle non-contiguous RAM  (basically, AMD, but only if you don't use onboard video) or if you have 4 GB installed in the machine and don't mind very very weird problems on bootup so basically it is very very extremely unlikely that shadowing can bite us.  
== Low-level access rights ==
We document the access rights each programmer requires in the man page.
Below is a short summary of the mapping between functions used in flashrom and the wording in the manpage.


But, other features like bios flashing protection set in bios are affecting flashrom.
{|bgcolor="#d0d0d0"
!Function(ality)||Wording
|- bgcolor="#e0e0e0"
| *physmap* (*mmio*)||raw memory access
|- bgcolor="#f0f0f0"
|IN[BWL]/OUT[BWL]||raw I/O port access
|- bgcolor="#e0e0e0"
|Reading PCI IDs<br/>(i.e., all PCI-based<br/>programmers)||PCI configuration space '''read''' access
|- bgcolor="#f0f0f0"
| *pci_write*||PCI configuration space access
|- bgcolor="#e0e0e0"
| *msr||MSR access
|}

Latest revision as of 23:28, 17 July 2014

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

How to check for valid AMD IMC firmware in an image?

They must have the signature _AMD_IMC_C in them. So just look for that, for example with strings -a -10 {IMAGENAME} | grep _AMD_IMC_C. The blob actually starts 8 kB (0x2000) before that string, usually at 0x20000 of the flash image (but other fixed offsets are possible too). See also http://www.coreboot.org/AMD_IMC.

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*) Also, many *28* chips require high voltage to respond to any identification routines.

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).

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.

Bios Shadowing

Shadowing the ROM is either happening below 1 MB (old 16bit address space), and we don't care about that area, regardless of how much you shadow. Or it is happening close to 4 GB, but for that you either need a processor which can handle non-contiguous RAM (basically, AMD, but only if you don't use onboard video) or if you have 4 GB installed in the machine and don't mind very very weird problems on bootup so basically it is very very extremely unlikely that shadowing can bite us.

But, other features like bios flashing protection set in bios are affecting flashrom.

Bios content changes between reboots

Many BIOSes out there change a few bytes in the ROM on each boot. They store boot date/time and some configuration data. Such changes are expected. As long as the readback doesn't change between subsequent reads (without any boot in between), you're in the clear.

And if you are patient enough you can figure what bios change and where.

Writing a chip driver

For parallel/LPC/FWH chips:

  • Check if you can use the stuff in jedec.c . If yes, use the functions directly instead of copying them.
  • If jedec.c is not compatible with your chip, try to find a chip driver file which works for your chip. Use these functions directly instead of copying them.

For SPI chips:

  • spi.c contains both chip-specific command functions and SPI general infrastructure. Try to find compatible functions in there and use them directly instead of copying. spi.c will be split into infrastructure and chip commands in the future, so check if this note still applies.

For all chips:

  • Hook up the driver functions in flashchips.c . Easiest way is to copy the entry for a similar chip and modify as needed.
  • IDs are defined in flashchips.h which also acts as a database for IDs not yet hooked up and IDs which are aliases for other chips (see the comments in there).

Writing a programmer driver

This task entirely depends on the communication protocol you want to use for talking to the chip. There are two main interface classes: Address-value pairs (Parallel/LPC/FWH protocols) and explicit commands (SPI). Our generic programmer infrastructure can handle both, even in the same programmer.

The easiest way to get started is to hack dummyflasher.c which supports both interface classes. You get immediate results by running

flashrom -p dummy

without having to touch a single line outside dummyflasher.c . Once your hacked up dummyflasher does something useful (that means it differs in a nontrivial way from vanilla dummyflasher), we strongly suggest post it to the mailing list. Then we can help you separate your code from dummyflasher and make it a real driver on its own (some of us have predefined templates for that). You don't have to touch any code or Makefile outside your driver if you don't want to.

A new programmer driver is automatically added to the output of flashrom --help and the only file you have to touch outside your own driver file is the man page. Qualified help is available for that task, so you can get by with supplying the text if you don't know man page syntax.

Generally, we recommend to submit early and often, even if your code is nowhere near ready. Maybe someone else already has unfinished/unreleased code for your favourite programmer.

Programmer drivers can be merged even if they are not completely working yet, but they will be disabled by default in that case. You save yourself the hassle of carring a large patch forward and can contentrate on driver development instead of forward porting your patch every few commits (which is painful to do over large time periods). Plus, your code gets some exposure on the list and interested users may help with development and debugging.

Flash chip locking

(In case you wondered, this is not about concurrent execution.)

Here is a patch to use a generic locking infrastructure: http://patchwork.coreboot.org/patch/581/

I (Carl-Daniel) would like to keep the now-unused chip driver files around until we have the locking conversion/refactoring done. My patch to do this (see above) probably doesn't apply anymore, and it also can't handle partial locking/unlocking. I can repost next week, but I welcome comments about the interface.

One of my new ideas is to have the locking function take an struct lockblock {blocksize, lockstatus}array as parameter. To retrieve the locking status, one would pass action=get array=NULL and the function would allocate and return the lockblock array. To set the locking status, one would first retrieve the array (see previous sentence), then walk it and set the desired status of each lockblock, then pass action=set and the modified array to the locking function. Advantages: You can do lock printing in a generic function which just walks the returned array, you can handle enabling and disabling all locks in the same way. Even something like (un)locking only a specific region can be done with a generic wrapper.

Unsolved (well, design is not completely ready): Where should we store lock blocks?

  • In struct flashchip (works mostly OK for LPC/FWH chips because locking status is usually stored in register space at the corresponding block address, will be a nightmare for SPI chips because there are usually just 4 bits in the status reg for this, and undecided for Parallel chips because they have the status reg variant and the corresponding block address variant).
  • In the chip drivers (would avoid cluttering flashchips.c, handle the various locking encodings (bitfield, corresponding address in register space)

Figuring out if you need a board enable or a new chip driver

To determine if we're missing a chip definition or if we need a board enable. Just use grep on the log:

grep -v "parity violation"

To narrow it down further, try:

grep -v "id1 is normal flash content, id2 is normal flash content"

And of course you want to ignore the skipped probes:

grep -v "skipped"

The remaining lines are worth examining, and if those look bogus as well, you can bet that we just need a board enable.

Porting flashrom to different platforms

GCC/clang builtin #defines

Get them by running (replace $CC with your compiler)

echo | $CC -E -dM -

Finding unused functions in C code

There's the straightforward approach which fails:

gcc -Wunused-function

GCC 4.2 and 4.3 are totally unable to find any unused functions that way (except if they are marked static, and that defeats the purpose of finding unused global functions), and I doubt their testsuite even checks for that. Later gcc may suffer from that misfeature as well.


There's the complicated approach which works somewhat (no idea if this works on all gcc/binutils combinations):

gcc -ffunction-sections -Wl,--gc-sections -Wl,--print-gc-sections -fno-inline -combine *.c
  • -ffunction-sections causes each function to end up in a different section.
  • --gc-sections causes the linker to drop unused sections (i.e. unused functions).
  • --print-gc-sections causes the linker to print a diagnostic message for each dropped function.
  • -fno-inline tells gcc not to screw up as gcc will happily emit functions twice (or even more often): inlined and non-inlined, and the non-inlined function will be dropped and warned about even though the code was used (albeit auto-inlined in another place).
  • -combine allows you to get meaningful diagnostics for the whole program

Do NOT use -fwhole-program because gcc will then optimize away any unused functions without any diagnostic message.

Embedding cwsdpmi in the binary produced with "make djgpp-dos"

[13/07/2010 17:05:34] <ruik> carldani: you can embed the cwsdpmni into final executable

[13/07/2010 17:05:47] <ruik> carldani: and also you can compress that with UPX

[13/07/2010 17:18:57] <ruik> i586-pc-msdosdjgpp-objcopy flashrom.exe a.coff -O coff-go32

[13/07/2010 17:19:12] <ruik> cat CWSDSTUB.EXE a.coff >x.exe

[13/07/2010 17:19:26] <ruik> upx --best x.exe

Low-level access rights

We document the access rights each programmer requires in the man page. Below is a short summary of the mapping between functions used in flashrom and the wording in the manpage.

Function(ality) Wording
*physmap* (*mmio*) raw memory access
IN[BWL]/OUT[BWL] raw I/O port access
Reading PCI IDs
(i.e., all PCI-based
programmers)
PCI configuration space read access
*pci_write* PCI configuration space access
*msr MSR access