revert between 56095 -> 55830 in arch
[AROS.git] / arch / .unmaintained / m68k-pp-native / loader / loader.c
blob530a17ffa643ccd9b0707adb5029326a8a740e93
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Code for downloading an ELF file onto a Palm Pilot(TM).
6 */
8 #include <Pilot.h>
9 #include <System/SerialMgr.h>
10 #include <System/StringMgr.h>
11 #include <string.h>
12 #include "callback.h"
13 #define __PILOT_CODE__
14 #include "../registers.h"
16 #include "loaderRsc.h"
18 ULong get_ssp(void);
21 #ifndef FALSE
22 #define FALSE 0
23 #endif
25 #ifndef TRUE
26 #define TRUE 1
27 #endif
29 #define UNPROTECT_MEMORY \
30 csa0 = RREG_L(CSA0); \
31 csa1 = RREG_L(CSA1); \
32 csa2 = RREG_L(CSA2); \
33 csa3 = RREG_L(CSA3); \
34 WREG_L(CSA0)=csa0 &(~8); \
35 WREG_L(CSA1)=csa1 &(~8); \
36 WREG_L(CSA2)=csa2 &(~8); \
37 WREG_L(CSA3)=csa3 &(~8);
39 #define PROTECT_MEMORY \
40 WREG_L(CSA0)=csa0;\
41 WREG_L(CSA1)=csa1;\
42 WREG_L(CSA2)=csa2;\
43 WREG_L(CSA3)=csa3;
45 #define BAUDRATE 57600
47 int _strncmp(const char * s1, const char * s2, int len)
49 int c = 0;
50 int d;
51 while (c < len) {
52 d = s1[c] - s2[c];
53 if (d != 0)
54 return d;
55 c++;
57 return 0;
60 void _strncpy(char * d, const char * s, int len)
62 int c = 0;
63 while (c < len) {
64 d[c] = s[c];
65 c++;
69 void _delay(UInt ctr)
71 while (ctr > 0) {
72 int i = 1000;
73 int x = 2;
74 while (i > 0) {
75 i--;
76 x = x*x;
78 ctr--;
82 #define TYPE_HANDSHAKE 0x01
83 #define TYPE_READ_MEM 0x02
84 #define TYPE_WRITE_MEM 0x03
85 #define TYPE_MEM_CONTENT 0x04
86 #define TYPE_WRITE_MEM_ACK 0x05
87 #define TYPE_GET_SPECIAL_INFO 0x06
88 #define TYPE_START_PROGRAM 0x07
89 #define TYPE_START_PROGRAM_ACK 0x08
90 #define TYPE_QUIT 0x10
92 struct Packet
94 unsigned short payload_length;
95 unsigned char payload_type;
96 char * payload;
97 int state;
98 unsigned short pos;
101 enum {
102 GET_FRAME_BEGINNING = 0x01,
103 GET_PAYLOAD_LENGTH_HI,
104 GET_PAYLOAD_LENGTH_LO,
105 GET_TYPE,
106 GET_PAYLOAD,
107 GET_FRAME_END
110 void free_packet(struct Packet * packet)
112 if (packet->payload)
113 MemPtrFree(packet->payload);
114 MemPtrFree(packet);
117 struct Packet * ready_packet = NULL;
118 struct Packet * current_packet = NULL;
120 void free_all_packets(void)
122 if (NULL != current_packet) {
123 free_packet(current_packet);
126 if (NULL != ready_packet)
127 free_packet(ready_packet);
131 struct Packet * get_next_packet(UInt refnum)
133 struct Packet * p = NULL;
134 ULong len;
135 Err err;
137 err = SerReceiveCheck(refnum, &len);
139 if (0 != len) {
140 char * buf;
141 int i;
143 buf = MemPtrNew(len);
144 if (NULL != buf) {
146 len = SerReceive(refnum,
147 buf,
148 len,
149 1000,
150 &err);
153 i = 0;
154 while (i < len) {
156 if (NULL == current_packet) {
157 current_packet = MemPtrNew(sizeof(struct Packet));
158 current_packet->state = GET_FRAME_BEGINNING;
159 current_packet->pos = 0;
162 switch (current_packet->state) {
163 case GET_FRAME_BEGINNING:
164 if (0x7f == buf[i])
165 current_packet->state = GET_PAYLOAD_LENGTH_HI;
166 i++;
167 break;
169 case GET_PAYLOAD_LENGTH_HI:
170 current_packet->payload_length = ((unsigned short)buf[i]) << 8;
171 current_packet->state = GET_PAYLOAD_LENGTH_LO;
172 i++;
173 break;
175 case GET_PAYLOAD_LENGTH_LO:
176 current_packet->payload_length |= ((unsigned short)buf[i]);
177 current_packet->state = GET_TYPE;
178 current_packet->payload = MemPtrNew(current_packet->payload_length);
179 i++;
180 break;
182 case GET_TYPE:
183 current_packet->payload_type = buf[i];
184 current_packet->state = GET_PAYLOAD;
185 i++;
186 break;
188 case GET_PAYLOAD:
189 while (i < len &&
190 current_packet->pos < current_packet->payload_length) {
192 current_packet->payload[current_packet->pos++] = buf[i];
193 i++;
196 if (current_packet->pos == current_packet->payload_length)
197 current_packet->state = GET_FRAME_END;
198 break;
200 case GET_FRAME_END:
201 if (0x7f == buf[i]) {
202 ready_packet = current_packet;
203 } else {
204 free_packet(current_packet);
206 i++;
207 current_packet = NULL;
208 break;
210 default:
211 i++;
217 * Try to get the first complete packet in the list.
219 p = (struct Packet *)ready_packet;
220 if (NULL != p) {
221 int i = 0;
222 int c = 0;
224 ready_packet = NULL;
226 * Reconvert the payload (if necessary)
228 while (i < p->payload_length) {
229 if (0x27 == p->payload[i])
230 c++;
231 i++;
234 if (c != 0) {
236 * Convert the payload
238 char * pl = MemPtrNew(p->payload_length - c);
239 if (NULL != pl) {
240 int _i = 0;
241 i = 0;
242 while (i < p->payload_length) {
243 if (0x27 == p->payload[i]) {
244 if (0x28 == p->payload[i+1]) {
245 pl[_i] = 0x27;
246 } else
247 pl[_i] = 0x7f;
248 i++;
249 } else
250 pl[_i] = p->payload[i];
251 i++;
252 _i++;
255 MemPtrFree(p->payload);
256 p->payload = pl;
257 p->payload_length -= c;
260 return p;
264 void send_packet(UInt refnum, char * buffer, unsigned short len, unsigned char type)
266 ULong i = 0, c = 0;
267 char * packet;
268 Err err;
270 while (i < len) {
272 * Count number of characters to escape.
274 if (0x7f == buffer[i] || 0x27 == buffer[i])
275 c++;
276 i++;
279 packet = MemPtrNew(1 + /* frame begin */
280 2 + /* length of payload indicator */
281 1 + /* type */
282 len + c + /* payload */
283 1 /* frame end */);
285 if (NULL != packet) {
286 int pos = 4;
287 packet[0] = 0x7f;
288 packet[1] = ((len+c) >> 8) & 0xff;
289 packet[2] = ((len+c) ) & 0xff;
290 packet[3] = type;
292 i = 0;
294 * convert forbidden bytes.
296 while (i < len) {
297 if (0x7f == buffer[i]) {
298 packet[pos++] = 0x27;
299 packet[pos] = 0x29; /* = 0x7f */
300 } else if (0x27 == buffer[i]) {
301 packet[pos++] = 0x27;
302 packet[pos] = 0x28; /* = 0x27 */
303 } else {
304 packet[pos] = buffer[i];
306 pos++;
307 i++;
309 packet[pos] = 0x7f;
312 * Send this packet
314 SerSend(refnum,packet,pos+1,&err);
315 SerSendWait(refnum,-1);
317 MemPtrFree(packet);
322 * Do a handshake. I send "AROS?", expect "AROS!" and send back
323 * "greets!".
325 int do_handshake(UInt refnum)
327 struct Packet * packet;
328 int ctr = 0;
330 while (ctr < 10) {
331 send_packet(refnum, "AROS?", 5, TYPE_HANDSHAKE);
332 _delay(1000);
333 packet = get_next_packet(refnum);
334 if (NULL != packet) {
335 if (0 == _strncmp("AROS!", &packet->payload[0], 5) &&
336 5 == packet->payload_length) {
337 free_packet(packet);
338 send_packet(refnum, "greets!", 7, TYPE_HANDSHAKE);
339 return 0;
342 ctr++;
345 return -1;
348 void howdy(UInt refnum)
350 send_packet(refnum,"HOWDY!",6,0xff);
353 void read_mem(UInt refnum, struct Packet * packet)
356 * Layout of packet:
357 * ULong: Start address
358 * unsigned short: Num Bytes
360 if (6 == packet->payload_length) {
361 char * buf;
362 unsigned short i;
363 ULong ctr;
364 ULong addr = (((ULong)packet->payload[0]) << 24) |
365 (((ULong)packet->payload[1]) << 16) |
366 (((ULong)packet->payload[2]) << 8) |
367 (((ULong)packet->payload[3]) << 0);
368 ULong numbytes = (((ULong)packet->payload[4]) << 8) |
369 (((ULong)packet->payload[5]) );
371 buf = MemPtrNew((ULong)numbytes+ sizeof(addr));
373 _strncpy(buf, (char *)&addr, sizeof(addr));
375 ctr = numbytes;
376 i = sizeof(addr);
377 if (NULL != buf) {
378 while (ctr > 0) {
379 buf[i] = RREG_B(addr);
380 i++;
381 addr++;
382 ctr--;
384 send_packet(refnum,buf,numbytes+sizeof(addr),TYPE_MEM_CONTENT);
389 void write_mem(UInt refnum, struct Packet * packet)
392 * Layout of packet:
393 * ULong: Start address
395 if (packet->payload_length >= 4) {
396 ULong ctr, i;
397 ULong csa0, csa1, csa2, csa3;
398 ULong addr = (((ULong)packet->payload[0]) << 24) |
399 (((ULong)packet->payload[1]) << 16) |
400 (((ULong)packet->payload[2]) << 8) |
401 (((ULong)packet->payload[3]) << 0);
402 i = packet->payload_length - 4;
403 ctr = 4;
404 UNPROTECT_MEMORY
405 while (i > 0) {
406 *(Byte *)addr = packet->payload[ctr];
407 addr++;
408 ctr++;
409 i--;
411 PROTECT_MEMORY
413 * Send back the start address as ack!
415 send_packet(refnum,packet->payload,4,TYPE_WRITE_MEM_ACK);
419 void execute(void * func())
421 (*func)();
424 void start_program(UInt refnum, struct Packet * packet)
427 * Layout of packet:
428 * ULong: Start address
430 if (packet->payload_length == 4) {
431 ULong csa0,csa1,csa2,csa3;
432 ULong addr = (((ULong)packet->payload[0]) << 24) |
433 (((ULong)packet->payload[1]) << 16) |
434 (((ULong)packet->payload[2]) << 8) |
435 (((ULong)packet->payload[3]) << 0);
437 * Send back the start address as ack!
439 send_packet(refnum,packet->payload,4,TYPE_START_PROGRAM_ACK);
440 UNPROTECT_MEMORY
441 execute((void *)addr);
442 PROTECT_MEMORY
446 struct special_info
448 ULong start;
449 ULong end;
450 ULong ssp;
453 extern void end_marker();
454 extern void start();
456 void get_special_info(UInt refnum)
458 struct special_info si;
459 si.start = (ULong)start;
460 si.end = (ULong)end_marker;
461 si.ssp = get_ssp();
462 send_packet(refnum,(char *)&si,sizeof(struct special_info),TYPE_GET_SPECIAL_INFO);
465 int download_AROS(void)
467 int rc = 0;
468 Err err;
469 UInt refNum;
472 err = SysLibFind("Serial Library",&refNum);
473 if (0 == err) {
474 err = SerOpen(refNum, 0, BAUDRATE);
475 if (0 == err) {
476 VoidPtr serbuf = MemPtrNew(0x400);
477 if (NULL != serbuf)
478 SerSetReceiveBuffer(refNum, serbuf, 0x400);
480 * Serial Port is opened. So let's try a handshake
482 if (0 == do_handshake(refNum)) {
484 * Let's read all packets and act upon.
486 int end = FALSE;
487 while (FALSE == end) {
488 struct Packet * packet;
489 _delay(100);
490 packet = get_next_packet(refNum);
491 if (NULL != packet) {
492 switch (packet->payload_type) {
493 case TYPE_READ_MEM:
494 read_mem(refNum,packet);
495 break;
497 case TYPE_WRITE_MEM:
498 write_mem(refNum,packet);
499 break;
501 case TYPE_GET_SPECIAL_INFO:
502 get_special_info(refNum);
503 break;
505 case TYPE_START_PROGRAM:
506 start_program(refNum, packet);
507 break;
509 case TYPE_QUIT:
510 end = TRUE;
511 break;
513 free_packet(packet);
518 if (NULL != serbuf) {
519 SerSetReceiveBuffer(refNum, serbuf, 0);
520 MemPtrFree(serbuf);
523 SerClose(refNum);
525 else
526 return -1;
527 } else
528 rc = -1;
529 return rc;
532 static Boolean MainFormHandleEvent (EventPtr e)
534 Boolean handled = false;
535 FormPtr frm;
536 int rc;
537 CALLBACK_PROLOGUE
539 switch (e->eType) {
540 case frmOpenEvent:
541 frm = FrmGetActiveForm();
542 FrmDrawForm(frm);
544 handled = true;
545 break;
547 case menuEvent:
548 MenuEraseStatus(NULL);
550 switch(e->data.menu.itemID) {
553 handled = true;
554 break;
556 case ctlSelectEvent:
557 switch(e->data.ctlSelect.controlID) {
558 case Button1:
559 rc = download_AROS();
560 break;
562 break;
564 default:
565 break;
568 CALLBACK_EPILOGUE
570 return handled;
573 static Boolean ApplicationHandleEvent(EventPtr e)
575 FormPtr frm;
576 Word formId;
577 Boolean handled = false;
579 if (e->eType == frmLoadEvent) {
580 formId = e->data.frmLoad.formID;
581 frm = FrmInitForm(formId);
582 FrmSetActiveForm(frm);
584 switch(formId) {
585 case MainForm:
586 FrmSetEventHandler(frm, MainFormHandleEvent);
587 break;
589 handled = true;
592 return handled;
595 /* Get preferences, open (or create) app database */
596 static Word StartApplication(void)
598 FrmGotoForm(MainForm);
599 return 0;
602 /* Save preferences, close forms, close app database */
603 static void StopApplication(void)
605 FrmSaveAllForms();
606 FrmCloseAllForms();
609 /* The main event loop */
610 static void EventLoop(void)
612 Word err;
613 EventType e;
615 do {
616 EvtGetEvent(&e, evtWaitForever);
617 if (! SysHandleEvent (&e))
618 if (! MenuHandleEvent (NULL, &e, &err))
619 if (! ApplicationHandleEvent (&e))
620 FrmDispatchEvent (&e);
621 } while (e.eType != appStopEvent);
626 /* Main entry point; it is unlikely you will need to change this except to
627 handle other launch command codes */
628 DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
630 Word err;
633 if (cmd == sysAppLaunchCmdNormalLaunch) {
635 err = StartApplication();
636 if (err) return err;
638 EventLoop();
639 StopApplication();
641 } else {
642 return sysErrParamErr;
645 return 0;