/* Written by Tony 'Nicoya' Mantler <nicoya@apia.dhs.org> */

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/fcntl.h>

char * progname;

uint32_t beq1 = 0x10e80009; /* beq       a3,a4,+0x0009 */
uint32_t beq2 = 0x116c0009; /* beq       a7,t0,+0x0009 */
uint32_t b    = 0x10000009; /* b         +0x0009 */

void usage(int status) {
	printf(
			"This program modifies the Phobos E100 driver to work with standard 3c597 cards.\n"
			"Usage: %s if_fe.o\n"
			, progname);
	exit(status);
}

int main (int argc, char* argv[]) {
	int thefd;
	uint32_t curop;
	off_t err;
	int beq1found = 0, beq2found = 0;
	
	progname = argv[0];
	/* check for the right number of arguments*/
	if (argc != 2) usage(1);
	
	/* open driver to modify */
	thefd = open(argv[1], O_RDWR);
	if (thefd == -1) {
		perror("Could not open file");
		usage(errno);
	}
	
	while (sizeof(uint32_t) == read(thefd, &curop, sizeof(uint32_t))) {
		if (curop == beq1) {
			err = lseek(thefd, -(sizeof(uint32_t)), SEEK_CUR);
			printf("Found first beq at %d in %s!\n", err, argv[1]);
			err = write(thefd, &b, sizeof(uint32_t));
			if (err != sizeof(uint32_t))
				perror("Could not write changed operand");
			else {
				printf("Changed!\n");
				beq1found++;
			}
		}
		if (curop == beq2) {
			err = lseek(thefd, -(sizeof(uint32_t)), SEEK_CUR);
			printf("Found second beq at %d in %s!\n", err, argv[1]);
			err = write(thefd, &b, sizeof(uint32_t));
			if (err != sizeof(uint32_t))
				perror("Coult not write changed operand");
			else {
				printf("Changed!\n");
				beq2found++;
			}
		}	
	}
	/* If we modified more or less than one of each, PANIC! */
	if (beq1found != 1 || beq2found != 1) {
		printf("Uh oh, something bad happened. DO NOT ATTEMPT TO USE THIS DRIVER!\n\n");
		usage(1);
	}
	printf("Success! (But no guarantees it'll actually work) ;)\n");
	close(thefd);
}

