Aironet radio card eeprom tool

Dan Lanciani <[email protected]> Mon, 20 Jun 2005 00:52:47 -0400 (EDT)
Newsgroups gmane.network.wireless.bay-area
Message-ID <[email protected]>
A while back I posted an eeprom dumper for Aironet cards.  Attached is
an improved version that can also write (-w) and delete (-d) tags.

				Dan Lanciani
				ddl@danlan.*com

----


#include <stdio.h>
#include <conio.h>

unsigned base = 0x180;
int wflag, dflag;

char *countries[] = { "US_Can", "Europe", "Japan", "Spain", "France", "Belgium",
	"Israel", "Canada", "Australia", "WideJapan", "World", "Test" };

main(argc, argv)
char **argv;
{
	char *argv0 = argv[0];
	register unsigned i, j, k;
	unsigned dat;
	long l;

again:
	if(argc > 1 && argv[1][0] == '-' && argv[1][1] == 'p') {
		sscanf(&argv[1][2], "%x", &base);
		argv++;
		argc--;
		goto again;
	}
	if(argc > 1 && argv[1][0] == '-' && argv[1][1] == 'w') {
		wflag = 1;
		argv++;
		argc--;
		goto again;
	}
	if(argc > 1 && argv[1][0] == '-' && argv[1][1] == 'd') {
		dflag = 1;
		argv++;
		argc--;
		goto again;
	}
	if(dflag || wflag) {
		if(argc < 2)
			goto usage;
		sscanf(argv[1], "%x", &dat);
	}
	else if(argc != 1) {
	usage:
		fprintf(stderr, "Usage: %s [-pbase] [-d] [-w] [tag [data]]\n",
			argv0);
		exit(1);
	}
	if(inpw(base) & 0x8000) {
		fprintf(stderr, "Busy bit set on startup\n");
		exit(1);
	}
	outpw(base, 0x0010);
	waitcmd();
	if(inpw(base + 0x08) != 0x0010) {
		fprintf(stderr, "NOP status: %04x\n", inpw(base + 0x08));
		dumpres();
		ackcmd();
		exit(1);
	}
	ackcmd();
	if(inpw(base) & 0x8000) {
		fprintf(stderr, "Busy bit set after NOP\n");
		exit(1);
	}

	if(dflag) {
		outpw(base + 0x02, dat);
		outpw(base, 0x002b);
		waitcmd();
		if(inpw(base + 0x08) != 0x002b) {
			fprintf(stderr, "DELTAG status: %04x\n",
				inpw(base + 0x08));
			dumpres();
			ackcmd();
			exit(1);
		}
		ackcmd();
		exit(0);
	}

	if(wflag) {
		outpw(base + 0x02, 4 + argc - 2);
		outpw(base, 0x0028);
		waitcmd();
		if(inpw(base + 0x08) != 0x0028) {
			fprintf(stderr, "ALLOC status: %04x\n",
				inpw(base + 0x08));
			dumpres();
			ackcmd();
			exit(1);
		}
		k = inpw(base + 0x0a);
		ackcmd();

		outpw(base + 0x3a, k);
		outpw(base + 0x3c, 4);
		outpw(base + 0x3e, dat);
		outpw(base + 0x3e, 4 + argc - 2);
		while(argc > 2) {
			sscanf(argv[2], "%x", &dat);
			j = dat;
			argv++;
			argc--;
			if(argc > 2) {
				sscanf(argv[2], "%x", &dat);
				j |= (dat << 8);
				argv++;
				argc--;
			}
			outpw(base + 0x3e, j);
		}

		outpw(base + 0x02, k);
		outpw(base, 0x002a);
		waitcmd();
		if(inpw(base + 0x08) != 0x002a) {
			fprintf(stderr, "WRITETAG status: %04x\n",
				inpw(base + 0x08));
			dumpres();
			ackcmd();
			exit(1);
		}
		ackcmd();
		exit(0);
	}

	for(l = 0; l < 0x10000L; l++) {
		i = l;
		outpw(base + 0x02, i);
		outpw(base, 0x0029);
		waitcmd();
		if(inpw(base + 0x08) == 0x0029) {
			printf("TAG %04x ", i);
			j = inpw(base + 0x0a);
			ackcmd();
			outpw(base + 0x3a, j);
			outpw(base + 0x3c, 6);
			k = inpw(base + 0x3e) - 4;
			dat = inpw(base + 0x3e);
			printf("LEN %02x DATA ", k);
			dumphex(j, 8, k);
			switch(i) {

				case 0x1000:
					printf(" CALLID\n");
					break;

				case 0x1001:
					printf(" COUNTRY ");
					if(dat < sizeof(countries) /
						sizeof(countries[0]))
						printf("%s\n", countries[dat]);
					else
						printf("%d\n", dat);
					break;

				case 0x1002:
					printf(" POWER %dmW\n", dat);
					break;

				case 0x1003:
					printf(" MODULATION ");
					if(dat == 1)
						printf("CCK\n");
					else if(dat == 2)
						printf("MBOK\n");
					else
						printf("unknown %d\n", dat);
					break;

				case 0x2010:
					printf(" LEAP user: ");
					dumpascii(j, 10, dat & 0xff);
					break;

				case 0x2011:
					printf(" LEAP password\n");
					break;

				case 0x3000:
				case 0x3001:
				case 0x3002:
				case 0x3003:
				case 0x3004:
					dumpwep(i, j, k);
					break;

				case 0x3fff:
					printf(" WEP transmit key #%d\n",dat+1);
					break;

				case 0xa000:
					printf(" BRIDGE %d\n", dat);
					break;

				case 0xf000:
					printf(" WEP flags:");
					if(dat&1)
						printf(" WEP40");
					if(dat&2)
						printf(" WEP128");
					printf("\n");
					break;
			}
			outpw(base + 0x02, j);
			outpw(base, 0x000c);
			waitcmd();
		}
		ackcmd();
	}

	exit(0);
}

ackcmd()
{
	outpw(base + 0x34, 0x0010);
}

waitcmd()
{
	while(!(inpw(base + 0x30)&0x0010))
		kbhit();
}

dumpres()
{
	register int i;

	printf("Results:");
	for(i = 0x0a; i <= 0x0e; i += 2)
		fprintf(stderr, " %04x", inpw(base + i));
	printf("\n");
}

dumphex(seg, off, cnt)
register unsigned cnt;
{
	register unsigned i;

	cnt = (cnt + 1) / 2;
	outpw(base + 0x3a, seg);
	outpw(base + 0x3c, off);
	while(cnt--) {
		i = inpw(base + 0x3e);
		printf("%02x %02x ", i & 0xff, i >> 8);
	}
	printf("\n");
}

dumpascii(seg, off, cnt)
register unsigned cnt;
{
	register unsigned i;

	cnt = (cnt + 1) / 2;
	outpw(base + 0x3a, seg);
	outpw(base + 0x3c, off);
	while(cnt--) {
		i = inpw(base + 0x3e);
		printf("%c%c", i & 0xff, i >> 8);
	}
	printf("\n");
}

dumpwep(tag, seg, len)
{
	register unsigned i, j;

	printf(" WEP key ");
	if(tag == 0x3004)
		printf("home ");
	else
		printf("#%d ", tag - 0x3000 + 1);
	if(len != 14 && len != 22) {
		printf("unknown record length %d\n", len);
		return;
	}
	outpw(base + 0x3a, seg);
	outpw(base + 0x3c, 8 + 6);
	i = inpw(base + 0x3e);
	printf("(LEN %02d) ", i);
	i = (i + 1) / 2;
	while(i--) {
		j = inpw(base + 0x3e);
		printf("%02x %02x ", (j & 0xff) ^ 0x55, (j >> 8) ^ 0xaa);
	}
	printf("\n");
}
_______________________________________________
BAWUG's general wireless chat mailing list
[unsubscribe] http://lists.bawug.org/mailman/listinfo/wireless