Intel 5100 EEPROM: Difference between revisions
No edit summary |
No edit summary |
||
Line 165: | Line 165: | ||
* | * | ||
0x000007ff: 00 | 0x000007ff: 00 | ||
= Das Programm zum Auslesen/Ändern = | |||
#include "system.h" | |||
#define WREN 0x0006 /* Write Enable */ | |||
#define WRDI 0x0004 /* Write Disable */ | |||
#define RDSR 0x0005 /* Read Status Register */ | |||
#define READ 0x0003 /* Read from Memory Array */ | |||
#define WRITE 0x0002 /* Write to Memory Array */ | |||
//#define WRITE_EEP | |||
#define READ_EEP | |||
/* | |||
* Der Chip reagiert auf die Befehle nur, wenn ChipSelect auf low steht während | |||
* wir die Befehle schicken | |||
* | |||
*/ | |||
void select_chip(void) { | |||
/* ChipSelect auf Low */ | |||
FIO0CLR = 0x01 << 8; | |||
} | |||
void unselect_chip(void) { | |||
/* ChipSelect auf High */ | |||
FIO0SET = 0x01 << 8; | |||
} | |||
/* Das Datenblatt sagt, dass wir min. 90 ns warten müssen, siehe Seite 32 des PDFs, | |||
* Tabelle 21 (AC characteristics) */ | |||
void sleep_90ns(void) { | |||
__asm("nop;nop;nop;nop;nop;nop;nop;nop;nop;nop"); | |||
} | |||
/* | |||
* Aktiviert das WRITE_ENABLE-bit, welches vor Schreibzugriffen gesetzt | |||
* werden muss. | |||
* | |||
*/ | |||
void write_enable(void) { | |||
select_chip(); | |||
spi_ReconfigTransceiveData(WREN, false, false); | |||
unselect_chip(); | |||
sleep_90ns(); | |||
printf("Write enable aktiviert\r\n"); | |||
} | |||
void write_disable(void) { | |||
select_chip(); | |||
spi_Transceive(WRDI); | |||
unselect_chip(); | |||
sleep_90ns(); | |||
printf("write disable\r\n"); | |||
} | |||
/* | |||
* Prüft das Statusregister solange, bis das Write in Progress-Bit | |||
* nicht mehr gesetzt ist. | |||
* | |||
*/ | |||
void wait_write(void) { | |||
while (1) { | |||
select_chip(); | |||
spi_ReconfigTransceiveData(RDSR, false, false); | |||
readWord = (spi_Transceive(0x0000) & 0x00FF); | |||
unselect_chip(); | |||
sleep_90ns(); | |||
printf("Statusreg = %02x\n", readWord); | |||
if (!(readWord & 0x1)) { | |||
printf("Fertig.\r\n"); | |||
break; | |||
} | |||
} | |||
} | |||
int main(void) { | |||
int i=0, j=0; | |||
BYTE readData[2048]; | |||
BYTE readWord; | |||
BOARD_Init(); | |||
SYSTEM_Init(); | |||
printf("System Up \r\n"); | |||
#ifdef WRITE_EEP | |||
/* write enable bit setzen */ | |||
write_enable(); | |||
/* Daten schreiben */ | |||
select_chip(); | |||
spi_ReconfigTransceiveData(WRITE, false, false); | |||
/* 16-Bit Adresse senden, wir sind im 8-Bit-Modus */ | |||
spi_Transceive(0x0000); | |||
spi_Transceive(0x0092); | |||
/* Daten senden */ | |||
spi_Transceive(0x0016); | |||
spi_Transceive(0x0000); | |||
spi_Transceive(0x00e5); | |||
spi_Transceive(0x00ea); | |||
spi_Transceive(0x0091); | |||
spi_Transceive(0x007e); | |||
unselect_chip(); | |||
sleep_90ns(); | |||
printf("Write abgesetzt\r\n"); | |||
/* Warten bis der Schreibvorgang fertig ist */ | |||
wait_write(); | |||
/* write-bit wieder deaktivieren */ | |||
write_disable(); | |||
#endif | |||
#ifdef READ_EEP | |||
printf("Begin\n\r"); | |||
select_chip(); | |||
spi_ReconfigTransceiveData(READ, false, false); | |||
/* 16-Bit Adresse senden, wir sind im 8-Bit-Modus */ | |||
spi_Transceive(0x0000); | |||
spi_Transceive(0x0000); | |||
/* Daten zuerst in einen Buffer einlesen, wir können hier | |||
* nicht direkt ausgeben, da wir sonst zulange warten würden | |||
* (auf die serielle Schnittstelle) */ | |||
for (i = 0; i < 2048; i++) | |||
readData[i] = (spi_Transceive(0x0000) & 0x00FF); | |||
unselect_chip(); | |||
for (i = 0; i < 2048; i++) { | |||
printf("0x%08x: 0x%02x\r\n",i, readData[i]); | |||
/* Warten bis die Daten über die serielle Schnittstelle sind */ | |||
for(j=0;j<500000;j++); | |||
} | |||
printf("End\r\n"); | |||
#endif | |||
/* Schleife um den ARM aufzufangen */ | |||
while (1) { | |||
printf("nix zu tun\r\n"); | |||
for(i=0;i<5000000;i++); | |||
} | |||
} |
Latest revision as of 14:43, 24 May 2009
Intel 5100agn
Die Intel 5100agn ist eine WLAN-Karte (MiniPCI-Express), die man z.B. in einem Thinkpad verbauen kann. Diese Karte gibt es in mehreren Varianten: Einmal rebranded von Lenovo, mit anderen IDs (kostet ca. 100 €) und einmal original von Intel (27 €). Der einzige Unterschied: Die IDs.
Die Idee war daher, entweder das BIOS zu modifizieren (siehe auch http://www.endeer.cz/bios.tools/ für Tools dazu und http://forum.thinkpads.com/viewtopic.php?f=29&t=55837 für den passenden Thread), was sich als frickelig herausgestellt hat. Wenn man das BIOS kaputtflashed, hat man einen sehr teuren Backstein in der Hand, somit haben wir also das EEPROM der Karte modifiziert ;-).
Getestet wurde diese Änderung übrigens mit dem derzeit aktuellen BIOS für das Thinkpad x200, also Version 3.01 (6DET51WW) von 2009-04-20.
Datenblätter
- http://download.intel.com/design/network/applnots/an446.pdf ist ein Gigabit-Ethernet-Controller, der vor dem eigentlichen WLAN-Teil sitzt
- http://www.st.com/stonline/products/literature/ds/8028/m95160-w.pdf ist das EEPROM, welches wir verändern wollen
Das Board
Zum Einsatz kam ein Keil MCB2300 Evaluation Board, welches einen LPC2300 ARM Mikroprozessor beinhaltet. Nachdem man das EEPROM abgelötet hat und die pins mit drähten an die Pin-Outs des Boards verbunden hat, spielt man die Software auf, mit der man das EEPROM zunächst ausliest und anschließend neu programmiert.
Nötige Änderungen
Da man das EEPROM nicht beliebig oft auf- und ablöten kann, haben wir vorsichtshalber alle IDs geändert. Daher kann ich nicht genau sagen, welche Teile das BIOS prüft. Unsere Änderungen (durch Suchen im Netz die nötigen IDs gefunden):
- PCI ID auf 8086:4237
- Subsystem ID auf 8086:1211
- Device ID auf 26-08-cb-ff-ff-ea-16-00
- MAC-Adresse auf 00:16:ea:e5:7e:92
Hexdump vom EEPROM mit Anmerkungen
0x00000000: 5a 40 00 50 70 00 04 30 00 3c 00 00 02 80 /***************************************/ /* PCI ID START */ /***************************************/ 0x0000000e: 0x80 -- PCI vendor ID 0x0000000f: 0x86 -- PCI vendor ID 0x00000010: 0x42 -- PCI device ID 0x00000011: 0x32 -- PCI device ID --> 0x37 /***************************************/ /* PCI ID END */ /***************************************/ /***************************************/ /* SUBSYSTEM ID START */ /***************************************/ 0x00000012: 0x80 -- subsystem vendor ID 0x00000013: 0x86 -- subsystem vendor ID 0x00000014: 0x12 -- subsystem device ID 0x00000015: 0x01 -- subsystem device ID --> 0x11 /***************************************/ /* SUBSYSTEM ID END */ /***************************************/ 0x00000016: 0d 01 03 8b 05 00 00 f0 00 40 de c9 14 50 24 3e 0x00000026: 01 31 88 4b /***************************************/ /* DEVICE SERIAL NUMBER (MAC-Adresse) */ /* geändert von f8-4e-0a-ff-ff-5d-21-00 auf 26-08-cb-ff-ff-ea-16-00 (siehe lspci -nv) */ /***************************************/ 0x0000002a: 0x21 --> 0x16 0x0000002b: 0x00 0x0000002c: 0x0a --> 0xcb 0x0000002d: 0x5d --> 0xea 0x0000002e: 0xf8 --> 0x26 0x0000002f: 0x4e --> 0x08 /***************************************/ /* DEVICE SERIAL NUMBER END */ /***************************************/ 0x00000030: 69 16 79 16 89 16 99 16 ff ff 00 10 ff fe 00 00 0x00000040: 19 54 03 0c 00 00 60 04 ec fc 1f 5d f8 00 b2 44 0x00000050: 77 cc 01 22 69 14 24 92 00 1a 31 98 cc 60 1f 8f 0x00000060: cf e0 07 80 c1 e0 3f b8 ff 3f cc 30 00 00 00 20 0x00000070: 0a 28 0e 81 00 00 00 00 00 00 00 00 00 00 00 00 0x00000080: 00 00 00 00 00 00 08 4c 01 1f 00 f0 10 34 00 00 0x00000090: 31 09 /****************************************/ /* "MAC Adresse" (siehe Aufkleber) */ /* geändert von 00:21:5d:0a:4e:f8 auf 00:16:ea:e5:7e:92 */ /****************************************/ 0x00000092: 0x21 -> 0x16 0x00000093: 0x00 0x00000094: 0x0a -> 0xe5 0x00000095: 0x5d -> 0xea 0x00000096: 0xf9 -> 0x92 0x00000097: 0x4e -> 0x7e /*****************************************/ /* MAC Adresse ENDE */ /*****************************************/ 0x00000098: 00 02 00 00 00 00 00 50 41 30 45 34 38 46 30 33 0x000000a8: 43 38 45 58 39 33 32 31 30 36 34 30 00 00 a1 58 0x000000b8: 38 f8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x000000c8: 00 6e 00 96 00 ab 01 0f 03 68 02 cb 00 00 00 00 0x000000d8: 00 00 00 00 00 20 00 00 00 00 00 00 00 00 00 00 0x000000e8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 0x00000148: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0e 0x00000158: 6f 4d 00 57 00 00 0f 6f 0f 6f 0f 6f 0f 6f 0f 6f 0x00000168: 0f 6f 0f 6f 0f 6f 0f 6f 0f 6f 0f 6f 0f 61 0f 61 0x00000178: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00000188: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00000198: 00 00 0e e1 00 00 0f e1 00 00 0f e1 00 00 0f e1 0x000001a8: 0f 31 0f 31 0f 31 0f 31 00 00 0f 31 0f 31 0f 31 0x000001b8: 0f 31 0f 31 0f 31 0f 31 0f 31 0f 31 0f 31 0f 31 0x000001c8: 00 00 00 00 0f a1 0f a1 0f a1 0f a1 0f a1 00 00 0x000001d8: 0a 6f 0f 6f 0f 6f 0f 6f 0f 6f 0f 6f 0d 6f 00 00 0x000001e8: 0a e1 0f e1 0f 31 0a 31 0f 31 0f 31 0f 31 0f 31 0x000001f8: 0f 31 0f 61 0f 61 0c 0c 0f 0f 0f 0f 0f 0f 0f 0f 0x00000208: 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0c 0c 0f 0f 0f 0f 0x00000218: 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 0x00000228: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 0x000002d8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 45 0x000002e8: 28 c1 29 41 28 b4 32 3c 28 9c 3d 37 28 7d 45 33 0x000002f8: 28 5c 00 00 00 00 06 28 f2 00 21 3c 28 ae 27 39 0x00000308: 28 9e 34 32 28 70 3b 2e 28 51 46 29 28 2a 00 00 0x00000318: 00 00 24 28 ee 00 21 3f 28 90 28 3b 28 73 32 36 0x00000328: 28 49 3c 31 28 23 45 2c 2a 0f 00 00 00 00 40 28 0x00000338: ee 00 22 3d 28 8b 28 3a 28 73 33 34 28 3f 3c 2f 0x00000348: 28 22 44 2b 28 10 00 00 00 00 64 28 ee 00 22 3d 0x00000358: 28 9b 28 3a 28 86 33 34 28 53 3d 2f 28 2e 45 2b 0x00000368: 2a 19 00 00 00 00 74 28 ee 00 22 39 2a 9d 28 36 0x00000378: 28 89 33 30 2a 58 3d 2b 28 31 45 27 2a 1b 00 00 0x00000388: 00 00 8c 28 ee 00 20 37 28 a9 27 34 2a 96 33 2d 0x00000398: 28 64 3b 29 2a 41 47 24 2a 1f 00 00 00 00 9d 28 0x000003a8: ee 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x000003b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 0x00000468: 00 00 00 00 00 00 00 5d 00 5d 00 00 00 00 00 00 0x00000478: 01 01 00 06 01 01 00 05 00 00 00 00 01 01 00 06 0x00000488: 01 01 00 05 00 00 00 00 00 00 00 00 00 00 00 00 0x00000498: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x000004a8: 01 02 00 08 01 02 00 08 00 00 00 00 01 02 00 09 0x000004b8: 01 02 00 08 00 00 00 00 00 00 00 00 00 00 00 00 0x000004c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x000004d8: 01 02 00 07 01 03 00 06 00 00 00 00 01 02 00 08 0x000004e8: 01 03 00 07 00 00 00 00 00 00 00 00 00 00 00 00 0x000004f8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00000508: 01 02 00 06 01 03 00 04 00 00 00 00 01 02 00 06 0x00000518: 01 03 00 05 00 00 00 00 00 00 00 00 00 00 00 00 0x00000528: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00000538: 01 02 00 05 01 02 00 03 00 00 00 00 01 02 00 05 0x00000548: 01 02 00 04 00 00 00 00 00 00 00 00 00 00 00 00 0x00000558: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00000568: 01 01 00 04 01 02 00 02 00 00 00 00 01 01 00 04 0x00000578: 01 02 00 02 00 00 00 00 00 00 00 00 00 00 00 00 0x00000588: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00000598: 01 01 00 06 01 05 00 03 00 00 00 00 01 01 00 06 0x000005a8: 01 06 00 03 00 00 00 00 00 00 00 00 00 00 00 00 0x000005b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 0x000007ff: 00
Das Programm zum Auslesen/Ändern
#include "system.h" #define WREN 0x0006 /* Write Enable */ #define WRDI 0x0004 /* Write Disable */ #define RDSR 0x0005 /* Read Status Register */ #define READ 0x0003 /* Read from Memory Array */ #define WRITE 0x0002 /* Write to Memory Array */ //#define WRITE_EEP #define READ_EEP /* * Der Chip reagiert auf die Befehle nur, wenn ChipSelect auf low steht während * wir die Befehle schicken * */ void select_chip(void) { /* ChipSelect auf Low */ FIO0CLR = 0x01 << 8; } void unselect_chip(void) { /* ChipSelect auf High */ FIO0SET = 0x01 << 8; } /* Das Datenblatt sagt, dass wir min. 90 ns warten müssen, siehe Seite 32 des PDFs, * Tabelle 21 (AC characteristics) */ void sleep_90ns(void) { __asm("nop;nop;nop;nop;nop;nop;nop;nop;nop;nop"); } /* * Aktiviert das WRITE_ENABLE-bit, welches vor Schreibzugriffen gesetzt * werden muss. * */ void write_enable(void) { select_chip(); spi_ReconfigTransceiveData(WREN, false, false); unselect_chip(); sleep_90ns(); printf("Write enable aktiviert\r\n"); } void write_disable(void) { select_chip(); spi_Transceive(WRDI); unselect_chip(); sleep_90ns(); printf("write disable\r\n"); } /* * Prüft das Statusregister solange, bis das Write in Progress-Bit * nicht mehr gesetzt ist. * */ void wait_write(void) { while (1) { select_chip(); spi_ReconfigTransceiveData(RDSR, false, false); readWord = (spi_Transceive(0x0000) & 0x00FF); unselect_chip(); sleep_90ns(); printf("Statusreg = %02x\n", readWord); if (!(readWord & 0x1)) { printf("Fertig.\r\n"); break; } } } int main(void) { int i=0, j=0; BYTE readData[2048]; BYTE readWord; BOARD_Init(); SYSTEM_Init(); printf("System Up \r\n"); #ifdef WRITE_EEP /* write enable bit setzen */ write_enable(); /* Daten schreiben */ select_chip(); spi_ReconfigTransceiveData(WRITE, false, false); /* 16-Bit Adresse senden, wir sind im 8-Bit-Modus */ spi_Transceive(0x0000); spi_Transceive(0x0092); /* Daten senden */ spi_Transceive(0x0016); spi_Transceive(0x0000); spi_Transceive(0x00e5); spi_Transceive(0x00ea); spi_Transceive(0x0091); spi_Transceive(0x007e); unselect_chip(); sleep_90ns(); printf("Write abgesetzt\r\n"); /* Warten bis der Schreibvorgang fertig ist */ wait_write(); /* write-bit wieder deaktivieren */ write_disable(); #endif #ifdef READ_EEP printf("Begin\n\r"); select_chip(); spi_ReconfigTransceiveData(READ, false, false); /* 16-Bit Adresse senden, wir sind im 8-Bit-Modus */ spi_Transceive(0x0000); spi_Transceive(0x0000); /* Daten zuerst in einen Buffer einlesen, wir können hier * nicht direkt ausgeben, da wir sonst zulange warten würden * (auf die serielle Schnittstelle) */ for (i = 0; i < 2048; i++) readData[i] = (spi_Transceive(0x0000) & 0x00FF); unselect_chip(); for (i = 0; i < 2048; i++) { printf("0x%08x: 0x%02x\r\n",i, readData[i]); /* Warten bis die Daten über die serielle Schnittstelle sind */ for(j=0;j<500000;j++); } printf("End\r\n"); #endif /* Schleife um den ARM aufzufangen */ while (1) { printf("nix zu tun\r\n"); for(i=0;i<5000000;i++); } }