[Dri-devel] Re: more evil firmwares found

2004-04-26 Thread Ryan Underwood

On Sun, Apr 25, 2004 at 11:57:28PM -0500, Ryan Underwood wrote:
 
 I think I'll be doing some footwork on this one.

I wrote a quick program to parse out the microcode from the XFree86
mga_ucode.h files.  From here a disassembler can be written if we can
ever figure out the op codes.  The DDK says that they are 64-bits wide
and 64-bit aligned.  It seems that might be incorrect though.  There are
a lot of dupes if you examine the values at a width of 32-bits.

-- 
Ryan Underwood, [EMAIL PROTECTED]

#include stdlib.h
#include stdio.h
#include errno.h

#include warp_opcodes.h

#define OPCODE_SIZE 8
/* Parse the XFree86 MGA ucodes and generate a source listing. */

static inline int whitespace(char c) {
	return (c == '\n' || c == '\r' || c == ' ' || c == '\t'); 
}

static char *slurp(char *src, char *what) {

	char *p = src;
	int i;

	while (p[0] != what[0]) {
		p++;
		if (*p == '\0') return src;
	}
	for (i = 0; what[i] != '\0'; i++) {
		if (p[i] != what[i]) {
			i--;
			break;
		}
	}
	src = p + i;
	return src;
}

static int disassemble_warp(int *ip, unsigned char *opcode) {

	int i;
	char buf[5];
	
	printf(%x:\t, *ip);
	/* for now just print op */
	for (i = 0; i  OPCODE_SIZE; i++) {
		printf(%2x , opcode[i]);
	}
	printf(\n);
	*ip += OPCODE_SIZE;
	return 1;
}

int main(int argc, char**argv) {

	FILE *inp;
	char *filebuf, *p;
	int done = 0;
	int error = 0;
	int size;

	if (argc  2) {
		fprintf(stderr, Need an argument; a filename or '-' for stdin.\n);
		exit(EXIT_FAILURE);
	}
/*	if (argv[1][0] == '-') {
		fprintf(stderr, Reading from standard input...\n);
		inp = stdin;
	}
	else {
*/
		if ((inp = fopen(argv[1], r)) == NULL) {
			perror(fopen);
			exit(EXIT_FAILURE);
		}
		fprintf(stderr, Reading from file %s...\n, argv[1]);
/*
	}
*/

	if (fseek(inp, 0, SEEK_END) == -1) {
		perror(fseek);
		exit(EXIT_FAILURE);
	}
	if ((size = ftell(inp)) == -1) {
		perror(ftell);
		exit(EXIT_FAILURE);
	}
	if (fseek(inp, 0, SEEK_SET) == -1) {
		perror(fseek);
		exit(EXIT_FAILURE);
	}
	
	filebuf = (char*)malloc(size+1);
	if (filebuf == NULL) {
		perror(malloc);
		exit(EXIT_FAILURE);
	}

	fread(filebuf, size, 1, inp);
	if (ferror(inp)) {
		perror(fread);
		error = 1;
		goto cleanup;
	}

	if (fclose(inp) == EOF) {
		perror(fclose);
	}

	filebuf[size] = '\0';
	p = filebuf;
	char cur_vname[255];
	int vname_next = 0;
	int data_next = 0;

	while (!done  *p != '\0') {
		while (whitespace(*p)) p++;
		if (vname_next) {
			if (*p == '*') { /* declared as pointer */
p++;
			}
			char *q;
			q = slurp(p,  );
			strncpy(cur_vname, p, q-p);
			cur_vname[q-p] = '\0';
			fprintf(stderr, Parsing variable %s...\n, cur_vname);
			p = q;
			p = slurp(p, {);
			vname_next = 0;
			data_next = 1;
			continue;
		}
		if (data_next) {
			int ip = 0;
			unsigned char cur_op[OPCODE_SIZE];
			int index = 0;

			printf(%s:\n, cur_vname);

			while (*p != '}') {
if (whitespace(*p)) {
	p++;
	continue;
}
if (*p == ',') {
	p++;
	continue;
}
if (strncmp(p, 0x, 2) == 0) { /* next component is ready */
	int i;
	long int val = strtol(p, p, 16);
	if (errno) {
		perror(strtol);
		goto cleanup;
	}
	cur_op[index] = (unsigned char)val;
	index++;
	if (index == OPCODE_SIZE) {
		index = 0;
		if (!disassemble_warp(ip, cur_op)) {
			fprintf(stderr, Error disassembly:\n);
			for (i = 0; i  OPCODE_SIZE; i++) {
fprintf(stderr, %x, cur_op[i]);
			}
			fprintf(stderr, \n);
		}
	}
}
else {
	char err[50+1];
	strncpy(err, p, 50);
	err[50] = '\0';
	fprintf(stderr, Malformed input at:\n%s\n, err);
	error = 1;
	goto cleanup;
}
			}
			data_next = 0;
			p = slurp(p, });
			p = slurp(p, ;);
			printf(\n);
		}
		if (strncmp(p, /*, 2) == 0) {  /* start comment */
			fprintf(stderr, slurping a comment\n);
			p = slurp(p, */);
			continue;
		}
		else if ((strncmp(p, static , sizeof(static)) == 0)
|| strncmp(p, unsigned , sizeof(unsigned)) == 0)
		{
			p = slurp(p,  );
			continue;
		}
		else if (strncmp(p, char , sizeof(char)) == 0) {
			vname_next = 1;
			p = slurp(p,  );
			continue;
		}
		else { /* advance */
//			fprintf(stderr, advancing\n);
			p++;
		}
	}

cleanup:
	free(filebuf);

	if (error) {
		fprintf(stderr, Errors were encountered.\n);
		exit(EXIT_FAILURE);
	}
	exit(EXIT_SUCCESS);
}


signature.asc
Description: Digital signature


[Dri-devel] Re: more evil firmwares found

2004-04-26 Thread Ryan Underwood
On Mon, Apr 26, 2004 at 02:49:36AM -0500, Ryan Underwood wrote:
 
 I wrote a quick program to parse out the microcode from the XFree86
 mga_ucode.h files.

attaching sample output.  seems that g200 and g400-mt ucodes are much
bigger than g400 ucodes in general.

-- 
Ryan Underwood, [EMAIL PROTECTED]


ucode_out.gz
Description: Binary data


signature.asc
Description: Digital signature