From 49436633011b8f912cd201989ce3c7cefd848a94 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 9 Feb 2005 21:08:17 +0000 Subject: [PATCH] Handle keys/passwords needed to access most Super-I/O chips. This should let us dump Winbond Super-I/O chips past the few first dozens registers. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@2899 7894878c-1315-0410-8ee3-d5d059ff63e0 --- prog/dump/Module.mk | 6 +++- prog/dump/isadump.c | 40 ++++++++++++++++++++++++- prog/dump/superio.c | 71 +++++++++++++++++++++++++++++++++++++++++++++ prog/dump/superio.h | 30 +++++++++++++++++++ 4 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 prog/dump/superio.c create mode 100644 prog/dump/superio.h diff --git a/prog/dump/Module.mk b/prog/dump/Module.mk index 053ebcb4..b82cb1b1 100644 --- a/prog/dump/Module.mk +++ b/prog/dump/Module.mk @@ -35,7 +35,8 @@ PROGDUMPBININSTALL := $(MODULE_DIR)/i2cdump $(MODULE_DIR)/i2cset ifneq (,$(findstring $(MACHINE), i386 i486 i586 i686 x86_64)) PROGDUMPMAN8FILES += $(MODULE_DIR)/isadump.8 $(MODULE_DIR)/isaset.8 PROGDUMPTARGETS += $(MODULE_DIR)/isadump $(MODULE_DIR)/isaset -PROGDUMPSOURCES += $(MODULE_DIR)/isadump.c $(MODULE_DIR)/isaset.c +PROGDUMPSOURCES += $(MODULE_DIR)/isadump.c $(MODULE_DIR)/isaset.c \ + $(MODULE_DIR)/superio.c PROGDUMPBININSTALL += $(MODULE_DIR)/isadump $(MODULE_DIR)/isaset endif @@ -55,6 +56,9 @@ $(MODULE_DIR)/i2cdump: $(MODULE_DIR)/i2cdump.ro $(MODULE_DIR)/i2cbusses.ro $(MODULE_DIR)/i2cset: $(MODULE_DIR)/i2cset.ro $(MODULE_DIR)/i2cbusses.ro $(CC) $(EXLDFLAGS) -o $@ $^ +$(MODULE_DIR)/isadump: $(MODULE_DIR)/isadump.ro $(MODULE_DIR)/superio.ro + $(CC) $(EXLDFLAGS) -o $@ $^ + install-prog-dump: all-prog-dump $(MKDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(PROGDUMPMAN8DIR) $(INSTALL) -m 755 $(PROGDUMPBININSTALL) $(DESTDIR)$(SBINDIR) diff --git a/prog/dump/isadump.c b/prog/dump/isadump.c index 8a2a935c..a88a60bc 100644 --- a/prog/dump/isadump.c +++ b/prog/dump/isadump.c @@ -33,6 +33,8 @@ #include #include +#include "superio.h" + /* To keep glibc2 happy */ #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ >= 0 @@ -59,7 +61,7 @@ void help(void) { fprintf(stderr, "Syntax for I2C-like access:\n" - " isadump [-y] ADDRREG DATAREG [BANK [BANKREG]]\n" + " isadump [-y] [-k V1,V2...] ADDRREG DATAREG [BANK [BANKREG]]\n" "Syntax for flat address space:\n" " isadump [-y] -f ADDRESS [RANGE [BANK [BANKREG]]]\n"); } @@ -107,12 +109,24 @@ int main(int argc, char *argv[]) int flags = 0; int flat = 0, yes = 0; char *end; + unsigned char enter_key[SUPERIO_MAX_KEY+1]; + + enter_key[0] = 0; /* handle (optional) flags first */ while (1+flags < argc && argv[1+flags][0] == '-') { switch (argv[1+flags][1]) { case 'f': flat = 1; break; case 'y': yes = 1; break; + case 'k': + if (2+flags >= argc + || superio_parse_key(enter_key, argv[2+flags]) < 0) { + fprintf(stderr, "Invalid or missing key\n"); + help(); + exit(1); + } + flags++; + break; default: fprintf(stderr, "Warning: Unsupported flag " "\"-%c\"!\n", argv[1+flags][1]); @@ -122,6 +136,12 @@ int main(int argc, char *argv[]) flags++; } + /* key is never needed in flat mode */ + if (flat && enter_key[0]) { + fprintf(stderr, "Error: Cannot use key in flat mode\n"); + exit(1); + } + /* verify that the argument count is correct */ if ((!flat && argc < 1+flags+2) || (flat && argc < 1+flags+1)) { @@ -255,12 +275,26 @@ int main(int argc, char *argv[]) } #endif + /* Enter Super-I/O configuration mode */ + if (enter_key[0]) + superio_write_key(addrreg, enter_key); + if (bank >= 0) oldbank = set_bank(flat, addrreg, datareg, bank, bankreg); printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); for (i = 0; i < range; i += 16) { printf("%c0: ", hexchar(i/16)); + + /* It was noticed that Winbond Super-I/O chips + would leave the configuration mode after + an arbitrary number of register reads, + causing any subsequent read attempt to + silently fail. Repeating the key every 16 reads + prevents that. */ + if (enter_key[0]) + superio_write_key(addrreg, enter_key); + for (j = 0; j < 16; j++) { if (flat) { res = inb(addrreg + i + j); @@ -277,5 +311,9 @@ int main(int argc, char *argv[]) if (bank >= 0) set_bank(flat, addrreg, datareg, oldbank, bankreg); + /* Exit Super-I/O configuration mode */ + if (enter_key[0]) + superio_reset(addrreg, datareg); + exit(0); } diff --git a/prog/dump/superio.c b/prog/dump/superio.c new file mode 100644 index 00000000..7a6b3efa --- /dev/null +++ b/prog/dump/superio.c @@ -0,0 +1,71 @@ +/* + superio: Handle special I/O operations needed by most Super-I/O chips + + Copyright (C) 2005 Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ >= 0 +#include +#else +#include +#endif + +#include "superio.h" + +int superio_parse_key(unsigned char *key, const char *s) +{ + char *end; + int tmp; + key[0] = 0; + + while (*s != '\0') { + tmp = strtol(s, &end, 0); + if ((*end != '\0' && *end != ',') + || (tmp < 0x00 || tmp > 0xff)) + return -1; + + /* Byte is valid, store it */ + key[++key[0]] = tmp; + + /* Last byte? */ + if (key[0] == SUPERIO_MAX_KEY + || *end == '\0') + return 0; + + /* Skip comma */ + s = end + 1; + } + + /* Unexpected end of string */ + return -1; +} + +void superio_write_key(int addrreg, unsigned char *key) +{ + int i; + + for (i = 1; i <= key[0]; i++) + outb(key[i], addrreg); +} + +void superio_reset(int addrreg, int datareg) +{ + outb(0x02, addrreg); + outb(0x02, datareg); +} diff --git a/prog/dump/superio.h b/prog/dump/superio.h new file mode 100644 index 00000000..44f6d25f --- /dev/null +++ b/prog/dump/superio.h @@ -0,0 +1,30 @@ +/* + superio: Handle special I/O operations needed by most Super-I/O chips + + Copyright (C) 2005 Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _SUPERIO_H +#define _SUPERIO_H + +#define SUPERIO_MAX_KEY 8 + +int superio_parse_key(unsigned char *key, const char *s); +void superio_write_key(int addrreg, unsigned char *key); +void superio_reset(int addrreg, int datareg); + +#endif /* _SUPERIO_H */