view rvinterf/lowlevel/tfc139.c @ 923:10b4bed10192

gsm-fw/L1: fix for the DSP patch corruption bug The L1 code we got from the LoCosto fw contains a feature for DSP CPU load measurement. This feature is a LoCosto-ism, i.e., not applicable to earlier DBB chips (Calypso) with their respective earlier DSP ROMs. Most of the code dealing with that feature is conditionalized as #if (DSP >= 38), but one spot was missed, and the MCU code was writing into an API word dealing with this feature. In TCS211 this DSP API word happens to be used by the DSP code patch, hence that write was corrupting the patched DSP code.
author Mychaela Falconia <falcon@ivan.Harhan.ORG>
date Mon, 19 Oct 2015 17:13:56 +0000
parents 15e69d31c96f
children 0d7cc054ef72
line wrap: on
line source

/*
 * This program is a contender for the title of the ugliest hack
 * in the FreeCalypso project.  It will attempt to break into a
 * locked-down TracFone C139 by mimicking the actions of the
 * mot931c.exe TF "unlocker".
 */

#include <sys/types.h>
#include <sys/errno.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include "../include/pktmux.h"
#include "../include/limits.h"

extern int target_fd;
extern char *baudrate_name;

extern u_char rxpkt[];
extern size_t rxpkt_len;

char *logfname;
FILE *logF;
time_t logtime;
int no_output;	/* for output.c */

int wakeup_after_sec = 7;

/* see ../../target-utils/tf-breakin/payload.S for the source */
static u_char iram_payload[112] = {
	0xD3, 0xF0, 0x21, 0xE3, 0x58, 0x10, 0x9F, 0xE5,
	0xF5, 0x00, 0xA0, 0xE3, 0xB2, 0x00, 0xC1, 0xE1,
	0xA0, 0x00, 0xA0, 0xE3, 0xB2, 0x00, 0xC1, 0xE1,
	0x48, 0x60, 0x9F, 0xE5, 0x05, 0x00, 0xD6, 0xE5,
	0x20, 0x00, 0x10, 0xE3, 0xFC, 0xFF, 0xFF, 0x0A,
	0x2C, 0x10, 0x8F, 0xE2, 0x06, 0x20, 0xA0, 0xE3,
	0x01, 0x00, 0xD1, 0xE4, 0x00, 0x00, 0xC6, 0xE5,
	0x01, 0x20, 0x52, 0xE2, 0xFB, 0xFF, 0xFF, 0x1A,
	0x05, 0x00, 0xD6, 0xE5, 0x40, 0x00, 0x10, 0xE3,
	0xFC, 0xFF, 0xFF, 0x0A, 0x18, 0x10, 0x9F, 0xE5,
	0x01, 0x2C, 0xA0, 0xE3, 0xB0, 0x20, 0xC1, 0xE1,
	0x00, 0xF0, 0xA0, 0xE3, 0x02, 0x02, 0x02, 0x4F,
	0x4B, 0x02, 0x00, 0x00, 0x02, 0xF8, 0xFF, 0xFF,
	0x00, 0x58, 0xFF, 0xFF, 0x10, 0xFB, 0xFF, 0xFF
};

static unsigned iram_load_addr = 0x800000;
static unsigned stack_smash_addr = 0x837C54;

static u_char stack_smash_payload[4];

static char *target_tty_port;

static void
send_compal_memwrite(addr, payload, payload_len)
	unsigned addr;
	u_char *payload;
{
	u_char pkt[MAX_PKT_TO_TARGET];
	int i, csum, csum_offset;

	pkt[0] = RVT_TM_HEADER;
	pkt[1] = 0x40;		/* Compal's non-standard addition */
	pkt[2] = addr;
	pkt[3] = addr >> 8;
	pkt[4] = addr >> 16;
	pkt[5] = addr >> 24;
	bcopy(payload, pkt + 6, payload_len);
	csum_offset = payload_len + 6;
	csum = 0;
	for (i = 1; i < csum_offset; i++)
		csum ^= pkt[i];
	pkt[i] = csum;
	send_pkt_to_target(pkt, i + 1);
}

main(argc, argv)
	char **argv;
{
	extern char *optarg;
	extern int optind;
	int c;
	fd_set fds;

	baudrate_name = "57600";	/* what C139 firmware uses */
	while ((c = getopt(argc, argv, "a:B:l:s:w:")) != EOF)
		switch (c) {
		case 'a':
			iram_load_addr = strtoul(optarg, 0, 16);
			continue;
		case 'B':
			baudrate_name = optarg;
			continue;
		case 'l':
			logfname = optarg;
			continue;
		case 's':
			stack_smash_addr = strtoul(optarg, 0, 16);
			continue;
		case 'w':
			wakeup_after_sec = strtoul(optarg, 0, 0);
			continue;
		case '?':
		default:
usage:			fprintf(stderr,
				"usage: %s [options] ttyport\n", argv[0]);
			exit(1);
		}
	if (argc - optind != 1)
		goto usage;
	open_target_serial(argv[optind]);
	target_tty_port = argv[optind];

	set_serial_nonblock(0);
	setlinebuf(stdout);
	if (logfname) {
		logF = fopen(logfname, "w");
		if (!logF) {
			perror(logfname);
			exit(1);
		}
		setlinebuf(logF);
		fprintf(logF, "*** Log of TFC139 break-in session ***\n");
	}
	time(&logtime);
	output_line("Sending IRAM payload");
	send_compal_memwrite(iram_load_addr, iram_payload, sizeof iram_payload);
	stack_smash_payload[0] = iram_load_addr;
	stack_smash_payload[1] = iram_load_addr >> 8;
	stack_smash_payload[2] = iram_load_addr >> 16;
	stack_smash_payload[3] = iram_load_addr >> 24;
	for (;;) {
		FD_ZERO(&fds);
		FD_SET(target_fd, &fds);
		c = select(target_fd+1, &fds, 0, 0, 0);
		time(&logtime);
		if (c < 0) {
			if (errno == EINTR)
				continue;
			perror("select");
			exit(1);
		}
		if (FD_ISSET(target_fd, &fds))
			process_serial_rx();
	}
}

static void
handle_etm_response()
{
	char msgbuf[80];

	if (rxpkt_len != 4 || rxpkt[1] != 0x40 || rxpkt[2] || rxpkt[3] != 0x40){
		output_line("ETM response differs from expected");
		return;
	}
	sprintf(msgbuf, "Sending stack smash write at 0x%x", stack_smash_addr);
	output_line(msgbuf);
	send_compal_memwrite(stack_smash_addr, stack_smash_payload, 4);
	stack_smash_addr += 4;
}

handle_rx_packet()
{
	if (rxpkt_len == 2 && rxpkt[0] == 'O' && rxpkt[1] == 'K') {
		output_line(
		"Success: target should now be in boot ROM download wait");
		printf("You can now run fc-loadtool -h compal -c none %s\n",
			target_tty_port);
		exit(0);
	}
	switch (rxpkt[0]) {
	case RVT_RV_HEADER:
		if (rxpkt_len < 6)
			goto unknown;
		print_rv_trace();
		return;
	case RVT_L1_HEADER:
		print_l1_trace();
		return;
	case RVT_L23_HEADER:
		print_g23_trace();
		return;
	case RVT_TM_HEADER:
		print_etm_output_raw();
		handle_etm_response();
		return;
	default:
	unknown:
		print_unknown_packet();
	}
}