[E3-hacking] Adding write support to pbltool

Matt Wright matt at consultmatt.co.uk
Sat Jan 28 01:14:45 GMT 2006


Evening,

Just a hi first of all, just got my e2 and I'm happily hacking away  
an ipod project. I don't know if you are specifically looking for  
write-jump-execute in PBL or not but Matt Evans' E2 monitor can do  
just that. Some relevant links:

http://axio.ms/projects/e2/
http://scimitar.consultmatt.co.uk/e2wiki/LoadingYourCode
http://scimitar.consultmatt.co.uk/e2wiki/InstallMonitor

Ta,

Matt

On 27 Jan 2006, at 21:55, Mark Underwood wrote:

> Hi guys,
>
> I'm trying add support for writing to RAM (and then jump &  
> execute). However, when I run the
> command I always get a NAK :-(.
> I'm sure I'm being stupid, but I can't see what I'm doing wrong,  
> please could someone else try
> this code (I'm talking to an E3) and give it a look over and point  
> out my mistake ;-).
>
> Does anyone know the memory layout of the E3? It could be that I'm  
> telling it to write to the
> wrong place!
>
> Cheers,
>
> Mark
>
>
> 		
> ___________________________________________________________
> To help you stay safe and secure online, we've developed the all  
> new Yahoo! Security Centre. http://uk.security.yahoo.com/*
>  * pbltool.c - Talks to the PBL of the Amstrad E3 (Delta)
>  *
>  * Copyright 2005 Jonathan McDowell <noodles at earth.li>
>  *
>  * This program is free software; you can redistribute it and/or  
> modify
>  * it under the terms of the GNU General Public License as  
> published by
>  * the Free Software Foundation; version 2 of the License.
>  *
>  * This program is distributed in the hope that it will be useful,
>  * but WITHOUT ANY WARRANTY; without even the implied warranty of
>  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>  * GNU General Public License for more details.
>  *
>  * You should have received a copy of the GNU General Public License
>  * along with this program; if not, write to the Free Software
>  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   
> 02111-1307  USA
>  */
>
> #include <fcntl.h>
> #include <stdbool.h>
> #include <stdint.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <sys/poll.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <termios.h>
> #include <unistd.h>
>
> int debug = 1;
>
> int sendpacket(int fd, unsigned char *buf, size_t len, size_t max)
> {
> 	struct pollfd p;
> 	unsigned char c;
> 	uint8_t checksum;
> 	int i;
> 	int ret;
> 	size_t replylen;
>
> 	/* Start byte */
> 	c = 2;
> 	write(fd, &c, 1);
> 	printf("%x, ",c);
> 	/* Not compressed */
> 	c = 0;
> 	write(fd, &c, 1);
> 	printf("%x, ",c);
> 	/* Length */
> 	checksum = 0;
> 	c = len & 0xFF;
> 	checksum += c;
> 	write(fd, &c, 1);
> 	printf("%x, ",c);
> 	c = (len >> 8) & 0xFF;
> 	checksum += c;
> 	write(fd, &c, 1);
> 	printf("%x, ",c);
>
> 	write(fd, buf, len);
> 	for (i=0;i<len;i++)
> 		printf("%x, ",buf[i]);
>
> 	/* Write checksum */
> 	for (i = 0; i < len; i++) {
> 		checksum += buf[i];
> 	}
> 	c = checksum;
> 	write(fd, &c, 1);
> 	printf("%x\n",c);
>
> 	ret = 0;
> 	p.fd = fd;
> 	p.events = POLLIN;
> 	if (poll(&p, 1, 10000) == 0) {
> 		/* Timed out */
> 		ret = 1;
> 	}
>
> 	if (!ret) {
> 		i = read(fd, &c, 1);
> 		if (i != 1 || c != 2) {
> 			printf("Didn't get expected 0x02 header -- 0x%02X.\n",
> 					c);
> 			ret = 2;
> 		}
> 	}
> 		
> 	if (!ret) {
> 		i = read(fd, &c, 1);
> 		if (i != 1 || c != 0) {
> 			printf("Compressed return block?\n");
> 			ret = 2;
> 		}
> 	}
>
> 	if (!ret) {
> 		i = read(fd, &c, 1);
> 		if (i != 1) {
> 			printf("Couldn't read low byte of reply len.\n");
> 			ret = 2;
> 		}
> 		replylen = c;
> 		checksum = c;
> 	}
>
> 	if (!ret) {
> 		i = read(fd, &c, 1);
> 		if (i != 1) {
> 			printf("Couldn't read high byte of reply len.\n");
> 			ret = 2;
> 		}
> 		replylen += (c << 8);
> 		checksum += c;
> 	}
>
> 	if (!ret) {
> 		if (replylen < max) {
> 			while (replylen > 0) {
> 				i = read(fd, buf, replylen);
> 				if (i > 0) {
> 					if (debug) {
> 						printf("Got %d of %d bytes.\n",
> 							i, replylen);
> 					}
> 					replylen -= i;
> 					buf += i;
> 				}
> 			}
> 		}
> 		while (read(fd, &c, 1) != 1) ;
> 		if (debug) {
> 			printf("Checksum = 0x%02X\n", c);
> 		}
> 	}
>
> 	/*
> 	 * Flush input if error.
> 	 */
> 	if (ret > 1) {
> 		while (poll(&p, 1, 1000) != 0) {
> 			while (read(fd, &c, 1) > 0) {
> 				printf("Flushing: 0x%02X\n", c);
> 			}
> 		}
> 	}
>
> 	return ret;
> }
>
>
> int writeblock(int fd, uint32_t start, char *file)
> {
> 	unsigned char buf[16384 + 8];
> 	int imgfd;
> 	uint16_t blocklen;
> 	size_t count;
> printf("Entering writeblock\n");
> 	count = 0;
> 	imgfd = open(file, O_RDONLY);
>
> 	if (imgfd != -1) {
> 		while ((blocklen = read(imgfd, buf + 8, 1024)) > 0) {
> 			buf[0] = 5;
> 			buf[1] = 0;
> 			*(uint32_t *) (buf + 2) = start + count;
> 			//buf[6] = 1;
> 			//buf[7] = 0;
> 			*(uint16_t *) (buf + 6) = blocklen;
> 			printf("Trying to write %d bytes starting %02X "
> 					"at 0x%08X.\n",
> 					blocklen,
> 					buf[8],
> 					start + count);
> 			printf("sendpacket: %d ",
> 				sendpacket(fd, buf, blocklen + 8,
> 					sizeof(buf)));
> 			printf("%02X %02X %02X %02X\n",
> 				buf[0], buf[1], buf[2], buf[3]);
> 			count += blocklen;
> 		}
> 	}
> 	close(imgfd);
>
> 	return 0;
> }
>
>
> int readblock(int fd, uint32_t start, size_t len, char *file)
> {
> 	uint32_t checksum;
> 	unsigned char buf[10];
> 	unsigned char c;
> 	int i;
> 	int fdout;
>
> 	fdout = open(file, O_CREAT | O_WRONLY, 0644);
>
> 	for (i = 0; i < len; i++) {
> 		if ((i % 16) == 0) {
> 			printf("\n0x%08X ", start + i);
> 		}
> 		buf[0] = 3;
> 		buf[1] = 0;
> 		*(uint32_t *) (buf + 2) = start + i;
> 		*(uint32_t *) (buf + 6) = 1;
> 		if (sendpacket(fd, buf, 10, sizeof(buf)) == 0) {
> 			c = *(uint32_t *)(buf + 2);
> 			printf("%02X ", c);
> 			write(fdout, &c, 1);
> 		}
> 	}
>
> 	close(fdout);
> }
>
>
> int readflashblock(int fd, uint32_t start, size_t len, char *file)
> {
> 	uint32_t checksum;
> 	unsigned char buf[10];
> 	unsigned char c;
> 	int i;
> 	int fdout;
>
> 	fdout = open(file, O_CREAT | O_WRONLY, 0644);
>
> 	if (start > 0x00400000) {
> 		buf[0] = 3;
> 		buf[1] = 0;
> 		buf[2] = 0x00;
> 		buf[3] = 0x00;
> 		buf[4] = 0x40;
> 		buf[5] = 0x00;
> 		*(uint32_t *) (buf + 6) = start - 0x00400000;
> 		sendpacket(fd, buf, 10, sizeof(buf));
> 		checksum = *(uint32_t *)(buf + 2);
> 	} else {
> 		checksum = 0;
> 	}
>
> 	for (i = 0; i < len; i++) {
> 		if ((i % 16) == 0) {
> 			printf("\n0x%08X ", start + i);
> 		}
> 		buf[0] = 3;
> 		buf[1] = 0;
> 		buf[2] = 0x00;
> 		buf[3] = 0x00;
> 		buf[4] = 0x40;
> 		buf[5] = 0x00;
> 		*(uint32_t *) (buf + 6) = start - 0x00400000 + i + 1;
> 		if (sendpacket(fd, buf, 10, sizeof(buf)) == 0) {
> 			c = *(uint32_t *)(buf + 2) - checksum;
> 			printf("%02X ", c);
> 			checksum = *(uint32_t *)(buf + 2);
> 			write(fdout, &c, 1);
> 		}
> 	}
>
> 	close(fdout);
> }
>
> int eraseflash(int fd, uint32_t start, size_t size)
> {
> 	unsigned char buf[10];
>
> 	buf[0] = 6;
> 	buf[1] = 0;
> 	*(uint32_t *) (buf + 2) = start;
> 	*(uint32_t *) (buf + 6) = size;
> 	*(uint16_t *) (buf + 10) = 1;
> 	return sendpacket(fd, buf, 12, sizeof(buf));
> }
>
> int programflash(int fd, uint32_t start, char *file)
> {
> 	unsigned char buf[16384 + 10];
> 	int imgfd;
> 	uint16_t blocklen;
> 	size_t count;
>
> 	count = 0;
> 	imgfd = open(file, O_RDONLY);
>
> 	if (imgfd != -1) {
> 		while ((blocklen = read(imgfd, buf + 10, 1024)) > 0) {
> 			buf[0] = 14;
> 			buf[1] = 0;
> 			*(uint32_t *) (buf + 2) = start + count;
> 			buf[6] = 1;
> 			buf[7] = 0;
> 			*(uint16_t *) (buf + 8) = blocklen;
> 			printf("Trying to program %d bytes starting %02X "
> 					"at 0x%08X.\n",
> 					blocklen,
> 					buf[10],
> 					start + count);
> 			printf("sendpacket: %d ",
> 				sendpacket(fd, buf, blocklen + 10,
> 					sizeof(buf)));
> 			printf("%02X %02X %02X %02X\n",
> 				buf[0], buf[1], buf[2], buf[3]);
> 			count += blocklen;
> 		}
> 	}
> 	close(imgfd);
>
> 	return 0;
>
> }
>
> void help(void)
> {
> 	printf("pbltool v0.1\n");
> 	exit(EXIT_FAILURE);
> }
>
> int main(int argc, char *argv[])
> {
> 	int fd;
> 	struct termios serialterm;
> 	struct pollfd p;
> 	unsigned char c;
> 	unsigned char buf[128];
> 	int i;
> 	int count;
> 	bool gotver;
>
> 	if (argc < 2) {
> 		help();
> 	}
>
> 	fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
> 	tcgetattr(fd, &serialterm);
> 	serialterm.c_cflag = CS8 | CLOCAL | CREAD;
> 	serialterm.c_lflag = 0;
> 	serialterm.c_oflag = 0;
> 	serialterm.c_iflag = IGNPAR;
> 	cfsetspeed(&serialterm, B9600);
> 	tcsetattr(fd, TCSANOW, &serialterm);
> 	tcflush(fd, TCIOFLUSH);
>
> 	gotver = false;
>
> 	buf[0] = 2;
> 	buf[1] = 0;
> 	if (sendpacket(fd, buf, 2, sizeof(buf)) == 0) {
> 		gotver = true;
> 		printf("Talking to PBL v%d.%d Build %d\n",
> 				buf[4], buf[5],
> 				buf[6] + (buf[7] << 8));
> 	}
>
> 	if (!gotver) {
> 		printf("Prodding...\n");
> 	
> 		while (c != 0x06) {
> 			c = 0x1B;
> 			write(fd, &c, 1);
>
> 			p.fd = fd;
> 			p.events = POLLIN;
> 			if (poll(&p, 1, 100) == 1) {
> 				do {
> 					i = read(fd, &c, 1);
> 					if ((i == 1) && (c == 0x06)) {
> 						break;
> 					}
> 				} while (i == 1);
> 			}
> 		}
> 		printf("Handshaking...\n");
>
> 		for (;;) {
> 			p.fd = fd;
> 			p.events = POLLIN;
> 			if (poll(&p, 1, 100) == 0)
> 				break;
> 			do {
> 				i = read(fd, &c, 1);
> 				if ((i == 1) && (c != 0x06)) {
> 				printf("Error: Got 0x%02X instead of expected"
> 						" 0x06.\n", c);
> 				}
> 			} while (i == 1);
> 		}
> 	}
>
> 	while (!gotver) {
> 		buf[0] = 2;
> 		buf[1] = 0;
> 		if (sendpacket(fd, buf, 2, sizeof(buf)) == 0) {
> 			gotver = true;
> 			printf("Talking to PBL v%d.%d Build %d\n",
> 					buf[4], buf[5],
> 					buf[6] + (buf[7] << 8));
> 		}
> 	}
>
> 	sleep(1);
>
> 	if (strcmp(argv[1], "meminfo") == 0) {
> 		buf[0] = 0x0B;
> 		buf[1] = 0;
> 		if (sendpacket(fd, buf, 2, sizeof(buf)) == 0) {
> 			count = buf[2];
> 		}
>
> 		for (i = 0; i < count; i++) {
> 			buf[0] = 12;
> 			buf[1] = 0;
> 			buf[2] = i;
> 			buf[3] = 0;
> 			if (sendpacket(fd, buf, 4, sizeof(buf)) == 0) {
> 				printf("%d 0x%08X 0x%08X 0x%08X 0x%08X "
> 					"0x%04X 0x%04X\n",
> 					i,
> 					*(uint32_t *)(buf + 2),
> 					*(uint32_t *)(buf + 6),
> 					*(uint32_t *)(buf + 10),
> 					*(uint32_t *)(buf + 14),
> 					*(uint16_t *)(buf + 18),
> 					*(uint16_t *)(buf + 20));
> 			}
> 		}
> 	} else if (strcmp(argv[1], "read") == 0) {
> 		if (argc < 5) {
> 			printf("\nUsage: pbltool read <start addr> <len> "
> 					"<file>\n");
> 			exit(EXIT_FAILURE);
> 		}
> 		readblock(fd, strtol(argv[2], NULL, 0),
> 				strtol(argv[3], NULL, 0),
> 				argv[4]);
> 	} else if (strcmp(argv[1], "write") == 0) {
> 		if (argc < 4) {
> 			printf("\nUsage: pbltool write <start addr> "
> 					"<file>\n");
> 			exit(EXIT_FAILURE);
> 		}
> 		writeblock(fd, strtol(argv[2], NULL, 0),
> 				argv[3]);
> 	} else if (strcmp(argv[1], "readflash") == 0) {
> 		if (argc < 5) {
> 			printf("\nUsage: pbltool readflash <start addr> <len> "
> 					"<file>\n");
> 			exit(EXIT_FAILURE);
> 		}
> 		readflashblock(fd, strtol(argv[2], NULL, 0) + 0x400000,
> 				strtol(argv[3], NULL, 0),
> 				argv[4]);
> 	} else if (strcmp(argv[1], "writeflash") == 0) {
> 		if (argc < 4) {
> 			printf("\nUsage: pbltool writeflash <start addr> "
> 					"<file>\n");
> 			exit(EXIT_FAILURE);
> 		}
> 		programflash(fd, strtol(argv[2], NULL, 0) + 0x400000,
> 				argv[3]);
> 	} else if (strcmp(argv[1], "eraseflash") == 0) {
> 		if (argc < 4) {
> 			printf("\nUsage: pbltool eraseflash <start addr> "
> 					"<number of 16k pages>\n");
> 			exit(EXIT_FAILURE);
> 		}
> 		eraseflash(fd, strtol(argv[2], NULL, 0),
> 				strtol(argv[3], NULL, 0) * 0x4000);
>
> 	} else {
> 		printf("Unknown command!\n");
> 		exit(EXIT_FAILURE);
> 	}
>
> 	close(fd);
> 	exit(EXIT_SUCCESS);
> }
> _______________________________________________
> e3-hacking mailing list
> e3-hacking at earth.li
> http://www.earth.li/cgi-bin/mailman/listinfo/e3-hacking




More information about the e3-hacking mailing list