Am 25.07.2011 01:34 schrieb Stefan Tauner:
On Fri, 22 Jul 2011 21:00:48 +0200 Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net wrote:
=================================================================== --- flashrom-ich_fwh_idsel_programmer_param_docfix/flashrom.8 (Revision 1380) +++ flashrom-ich_fwh_idsel_programmer_param_docfix/flashrom.8 (Arbeitskopie)
i did not check the facts, but it looks ok. maybe a concrete example would be nice.
Done.
Using flashrom on laptops is dangerous and may easily make your hardware unusable (see also the .B BUGS Index: flashrom-ich_fwh_idsel_programmer_param_docfix/chipset_enable.c =================================================================== --- flashrom-ich_fwh_idsel_programmer_param_docfix/chipset_enable.c (Revision 1380) +++ flashrom-ich_fwh_idsel_programmer_param_docfix/chipset_enable.c (Arbeitskopie) @@ -301,7 +301,7 @@
static int enable_flash_ich_dc(struct pci_dev *dev, const char *name) {
- uint32_t fwh_conf;
- uint64_t fwh_conf;
fwh_idsel? would increase the patch size though
I created a separate fwh_idsel variable with narrower scope.
int i; char *idsel = NULL; int tmp; @@ -311,15 +311,18 @@
idsel = extract_programmer_param("fwh_idsel"); if (idsel && strlen(idsel)) {
fwh_conf = (uint32_t)strtoul(idsel, NULL, 0);
/* FIXME: Need to undo this on shutdown. */
msg_pinfo("\nSetting IDSEL=0x%x for top 16 MB", fwh_conf);
rpci_write_long(dev, 0xd0, fwh_conf);
rpci_write_word(dev, 0xd4, fwh_conf);
fwh_conf = pci_read_long(dev, 0xd0);
fwh_conf <<= 16;
fwh_conf |= pci_read_word(dev, 0xd4);
msg_pinfo("\nSetting IDSEL from 0x%012llx ", fwh_conf);
/* Base 16, nothing else makes sense. */
fwh_conf = (uint64_t)strtoull(idsel, NULL, 16);
msg_pinfo("to 0x%012llx for top 16 MB", fwh_conf);
the "from to" message is a good idea imo, i am not sure if the verbosity level is the right choice. most of the time parameters are just applied without a message (but when there is an error). maybe msg_pdbg would be better? OTOH if i specify something on the cli i would like to know if it has changed anything or not (even in the default verbosity). so i personally would leave it as it is, but i am not so sure what carldani the output slayer would recommend ;)
Downgraded to dbg, thanks for noticing this.
apart from that, this does not compile on my machine: error: format ‘%012llx’ expects type ‘long long unsigned int’, but argument 3 has type ‘uint64_t’
Changed format specifier to PRIx64.
also the strtoul result is not checked for errors. note from the man page:
Since strtoul() can legitimately return 0 or LONG_MAX (LLONG_MAX for strtoull()) on both success and failure, the calling program should set errno to 0 before the call, and then determine if an error occurred by checking whether errno has a nonzero value after the call.
Done.
you have also mentioned an idea to check for values >= (1<<48) this could be combined to one check/message or be done in two (one warning/info, one error).
Both are errors now.
Fix ICH FWH IDSEL setting with the fwh_idsel= internal programmer parameter. The code took 32 bits of input and wrote them to an 48 bit register, duplicating some values. Document the fwh_idsel= parameter in the man page.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-ich_fwh_idsel_programmer_param_docfix/flashrom.8 =================================================================== --- flashrom-ich_fwh_idsel_programmer_param_docfix/flashrom.8 (Revision 1380) +++ flashrom-ich_fwh_idsel_programmer_param_docfix/flashrom.8 (Arbeitskopie) @@ -298,6 +298,23 @@ .B it87spi programmer. .sp +If you have an Intel chipset with an ICH6 or later southbridge and if you want +to set specific IDSEL values for a non-default flash chip or an embedded +controller (EC), you can use the +.sp +.B " flashrom -p internal:fwh_idsel=value" +.sp +syntax where value is the 48-bit hexadecimal raw value to be written in the +IDSEL registers of the Intel southbridge. The upper 32 bits use one hex digit +each per 512 kB range between 0xffc00000 and 0xffffffff, and the lower 16 bits +use one hex digit each per 1024 kB range between 0xff400000 and 0xff7fffff. +The rightmost hex digit corresponds with the lowest address range. All address +ranges have a corresponding sister range 4 MB below with identical IDSEL +settings. The default value for ICH7 is given in the example below. +.sp +Example: +.B "flashrom -p internal:fwh_idsel=0x001122334567" +.sp Using flashrom on laptops is dangerous and may easily make your hardware unusable (see also the .B BUGS Index: flashrom-ich_fwh_idsel_programmer_param_docfix/chipset_enable.c =================================================================== --- flashrom-ich_fwh_idsel_programmer_param_docfix/chipset_enable.c (Revision 1380) +++ flashrom-ich_fwh_idsel_programmer_param_docfix/chipset_enable.c (Arbeitskopie) @@ -30,6 +30,8 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <inttypes.h> +#include <errno.h> #include "flash.h" #include "programmer.h"
@@ -311,15 +313,31 @@
idsel = extract_programmer_param("fwh_idsel"); if (idsel && strlen(idsel)) { - fwh_conf = (uint32_t)strtoul(idsel, NULL, 0); - - /* FIXME: Need to undo this on shutdown. */ - msg_pinfo("\nSetting IDSEL=0x%x for top 16 MB", fwh_conf); - rpci_write_long(dev, 0xd0, fwh_conf); - rpci_write_word(dev, 0xd4, fwh_conf); + uint64_t fwh_idsel; + fwh_idsel = pci_read_long(dev, 0xd0); + fwh_idsel <<= 16; + fwh_idsel |= pci_read_word(dev, 0xd4); + msg_pdbg("\nSetting IDSEL from 0x%012" PRIx64 " ", fwh_idsel); + errno = 0; + /* Base 16, nothing else makes sense. */ + fwh_idsel = (uint64_t)strtoull(idsel, NULL, 16); + if (errno) { + msg_perr("Error: fwh_idsel= specified, but value could " + "not be converted.\n"); + goto idsel_garbage_out; + } + if (fwh_idsel & 0xffff000000000000ULL) { + msg_perr("Error: fwh_idsel= specified, but value had " + "unusued bits set.\n"); + goto idsel_garbage_out; + } + msg_pdbg("to 0x%012llx for top 16 MB", fwh_idsel); + rpci_write_long(dev, 0xd0, (fwh_idsel >> 16) & 0xffffffff); + rpci_write_word(dev, 0xd4, fwh_idsel & 0xffff); /* FIXME: Decode settings are not changed. */ } else if (idsel) { - msg_perr("Error: idsel= specified, but no number given.\n"); + msg_perr("Error: fwh_idsel= specified, but no value given.\n"); +idsel_garbage_out: free(idsel); /* FIXME: Return failure here once internal_init() starts * to care about the return value of the chipset enable.