~z88dk-team/z88dk-pkg/trunk

« back to all changes in this revision

Viewing changes to support/rcmx000/boot.c

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna
  • Date: 2008-02-12 08:23:49 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080212082349-wgijt44scmgje90o
Tags: 1.7.ds1-1ubuntu1
* Merge from Debian unstable. Remaining Ubuntu changes:
  - build z88dk and z88dk-bin binary packages for lpia too
  - update Maintainer field as per spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
 
 
3
#include <stdio.h>
 
4
#include <stdlib.h>
 
5
 
 
6
#include <poll.h>
 
7
#include <unistd.h>
 
8
#include <netinet/in.h>
 
9
#include <sys/time.h>
 
10
#include <signal.h>
 
11
 
 
12
#include <sys/types.h>
 
13
#include <sys/stat.h>
 
14
#include <fcntl.h>
 
15
#include <termios.h>
 
16
#include <sys/ioctl.h>
 
17
 
 
18
#include <sys/poll.h>
 
19
 
 
20
#include "bootbytes.h"
 
21
 
 
22
static int debug_hex=0;
 
23
static int debug_dtr=0;
 
24
static int debug_flush=0;
 
25
 
 
26
static int debug_poll=0;
 
27
 
 
28
static int debug_rw=0;
 
29
 
 
30
static void dtr_ctl(int fd, int dtrval)
 
31
{
 
32
    int dtrflags=0;
 
33
 
 
34
    ioctl(fd, TIOCMGET, &dtrflags);
 
35
    if (debug_dtr) fprintf(stderr, "dtrFlags are %x.\n", dtrflags);
 
36
 
 
37
    if (dtrval)
 
38
    {
 
39
        dtrflags |= TIOCM_DTR;
 
40
    }
 
41
    else
 
42
    {
 
43
        dtrflags &= ~TIOCM_DTR;
 
44
    }
 
45
 
 
46
    ioctl(fd, TIOCMSET, &dtrflags);
 
47
    if (debug_dtr) fprintf(stderr, "Setting %x.\n", dtrflags);
 
48
 
 
49
    ioctl(fd, TIOCMGET, &dtrflags);
 
50
    if (debug_dtr) fprintf(stderr, "dtrFlags are %x.\n", dtrflags);
 
51
 
 
52
    return;
 
53
}
 
54
 
 
55
static void change_baudrate(int fd, int baudr)
 
56
{
 
57
  struct termios ios;
 
58
 
 
59
  memset(&ios, 0, sizeof(ios));
 
60
 
 
61
  tcgetattr(fd, &ios);
 
62
 
 
63
  if (debug_flush) fprintf(stderr, "IBaud=%d\n", cfgetispeed(&ios));
 
64
  if (debug_flush) fprintf(stderr, "OBaud=%d\n", cfgetospeed(&ios));
 
65
 
 
66
  switch(baudr)
 
67
    {
 
68
    case 2400:
 
69
      {
 
70
        cfsetospeed(&ios, B2400);
 
71
        break;
 
72
      }
 
73
    case 57600:
 
74
      {
 
75
        cfsetospeed(&ios, B57600);
 
76
        break;
 
77
      }
 
78
    default:
 
79
      {
 
80
        fprintf(stderr, "Illegal baudrate: %d\n", baudr);
 
81
        exit(1);
 
82
      }
 
83
    }
 
84
  
 
85
  tcsetattr(fd, TCSADRAIN, &ios);
 
86
 
 
87
}
 
88
 
 
89
static void msleep(int msec)
 
90
{
 
91
  poll(NULL, 0, msec);
 
92
}
 
93
 
 
94
 
 
95
/** Will wait indefinately for either stdin or serial data */
 
96
static void do_poll(int serfd)
 
97
{
 
98
  struct pollfd fds[2];
 
99
 
 
100
  memset(fds, 0, 2*sizeof(struct pollfd));
 
101
 
 
102
  if (debug_poll) fprintf(stderr, "Entering do_poll()\n");
 
103
 
 
104
  fds[0].fd=serfd;
 
105
  fds[1].fd=0; /* stdin */
 
106
 
 
107
  fds[0].events=POLLIN;
 
108
  fds[1].events=POLLIN;
 
109
 
 
110
  fds[0].revents=0;
 
111
  fds[1].revents=0;
 
112
 
 
113
  poll(fds, 2, -1);
 
114
 
 
115
  if (debug_poll) fprintf(stderr, "Leaving do_poll()\n");
 
116
}
 
117
 
 
118
static int check_fd(int anfd)
 
119
{
 
120
  struct pollfd fds;
 
121
  fds.fd=anfd;
 
122
  fds.events=POLLIN;
 
123
  fds.revents=0;
 
124
 
 
125
  poll(&fds, 1, 0);
 
126
 
 
127
  if (debug_poll)
 
128
    {
 
129
      if (fds.revents & POLLIN)
 
130
        {
 
131
          if (debug_poll) fprintf(stderr, "fd=%d, we have pollin data\n", anfd);
 
132
        }
 
133
      else
 
134
        {
 
135
          if (debug_poll) fprintf(stderr, "fd=%d, we have NO pollin data\n", anfd);       
 
136
        }
 
137
    }
 
138
  
 
139
  return (fds.revents & POLLIN);
 
140
}
 
141
 
 
142
/** Code below here should be fairly portable **/
 
143
 
 
144
static void usage(const char* argv0)
 
145
{
 
146
  fprintf(stderr, "Usage: %s -r <ttydev> <coldload binfile>\n", argv0);
 
147
  fprintf(stderr, "   or\n", argv0);
 
148
  fprintf(stderr, "Usage: %s -b <ttydev> <divisor> <binfile>\n", argv0);
 
149
  exit(1);
 
150
}
 
151
 
 
152
 
 
153
 
 
154
static void talk(int tty)
 
155
{
 
156
  unsigned char ch;
 
157
 
 
158
  while(1)
 
159
    {
 
160
      do_poll(tty); /** Infinite wait for either stdin or data from serial */
 
161
      
 
162
      if (check_fd(tty))
 
163
        {
 
164
          if (debug_rw) fprintf(stderr, "   Before read serial...\n");
 
165
          read(tty, &ch, 1);
 
166
          if (debug_rw) fprintf(stderr, "   After read serial...\n");
 
167
          
 
168
          if (debug_hex) fprintf(stderr, "Got: %.2x (hex))\n", ch);
 
169
      
 
170
          /** Print unprintables as stars '*' */
 
171
          if (ch>=' ' && ch<='~')
 
172
            {
 
173
              printf("%c", ch);
 
174
            }
 
175
          else if (ch==13)
 
176
            {
 
177
              printf("\n");
 
178
            }
 
179
          else if (ch==10)
 
180
            {
 
181
              printf("\n");
 
182
            }
 
183
          else
 
184
            {
 
185
              printf("<%.2X>", ch);
 
186
            }
 
187
          fflush(stdout);
 
188
        }
 
189
      else if (check_fd(0))
 
190
        {
 
191
          if (debug_rw) fprintf(stderr, "   Before read stdin...\n");
 
192
 
 
193
          read(0, &ch, 1);
 
194
          
 
195
          if (debug_rw) fprintf(stderr, "   After read stdin...\n");
 
196
          
 
197
          if (debug_rw) fprintf(stderr, "   Read stdin=%d\n", ch);
 
198
          
 
199
          write(tty, &ch, 1);
 
200
 
 
201
          if (!check_fd(tty))
 
202
            {
 
203
              msleep(100); /** Just sleep to give target a chance to respond */
 
204
            }
 
205
 
 
206
        }
 
207
 
 
208
    }
 
209
}
 
210
 
 
211
 
 
212
int main(int argc, char *argv[])
 
213
{
 
214
  /** Assume hex-ascii */
 
215
  int is_bin=0;
 
216
 
 
217
  /** This flag is set if we communicate raw with the target */
 
218
  int is_raw=0;
 
219
 
 
220
  unsigned char ch;
 
221
 
 
222
  int divisor;
 
223
 
 
224
  char* ttyname;
 
225
 
 
226
  char* fname;
 
227
 
 
228
  char* binfilename;
 
229
 
 
230
  int tty;
 
231
 
 
232
  FILE *coldboot;
 
233
 
 
234
  FILE *binfile;
 
235
 
 
236
  /** To keep the size of the .bin file */
 
237
  long fsize;
 
238
 
 
239
  unsigned csum;
 
240
 
 
241
  int i;
 
242
 
 
243
  if (argc!=4 && argc!=5)
 
244
    {
 
245
      usage(argv[0]);
 
246
    }
 
247
 
 
248
  if (0==strncmp(argv[1], "-b", 2))
 
249
    {
 
250
      if (argc!=5) usage(argv[0]);
 
251
 
 
252
      ttyname=argv[2];
 
253
      divisor=atoi(argv[3]);
 
254
      binfilename=argv[4];
 
255
      is_bin=1;
 
256
 
 
257
      binfile=fopen(binfilename, "rb");
 
258
      
 
259
      if (binfile==NULL)
 
260
        {
 
261
          fprintf(stderr, "Could not open %s\n", binfilename);
 
262
          exit(1);
 
263
        }
 
264
    }
 
265
  else if (0==strncmp(argv[1], "-r", 2))
 
266
    {
 
267
      if (argc!=4) usage(argv[0]);
 
268
 
 
269
      ttyname=argv[2];
 
270
      fname=argv[3];
 
271
 
 
272
      binfile=NULL;
 
273
 
 
274
      is_raw=1;
 
275
    }
 
276
  else
 
277
    {
 
278
      usage(argv[0]);
 
279
    }
 
280
  
 
281
  if (is_raw)
 
282
    {
 
283
      coldboot=fopen(fname, "rb");  
 
284
      if (coldboot==NULL)
 
285
        {
 
286
          fprintf(stderr, "Could not open %s\n", fname);
 
287
          exit(1);
 
288
        }
 
289
    }
 
290
 
 
291
  tty=open(ttyname, O_RDWR|O_NOCTTY);
 
292
  if (tty==-1)
 
293
    {
 
294
      fprintf(stderr, "Could not open device: %s\n", ttyname);
 
295
      exit(1);      
 
296
    }
 
297
 
 
298
  change_baudrate(tty, 2400);
 
299
 
 
300
  /** Reset active **/
 
301
  dtr_ctl(tty, 1);
 
302
 
 
303
  /** Reset turned off */
 
304
  dtr_ctl(tty, 0);
 
305
 
 
306
  /** Time to stabilize */
 
307
  msleep(500);
 
308
 
 
309
  /** Flush serial port */
 
310
  while (check_fd(tty))
 
311
    {
 
312
      unsigned char junk;
 
313
      read(tty, &junk, 1);
 
314
      if (debug_flush) fprintf(stderr, "Flushed %.2x off serial line\n", junk);
 
315
    }
 
316
 
 
317
  if (is_raw)  /** Take whole file from coldboot file @ 2400 */
 
318
    {
 
319
      printf("Using the -r (raw) option means that we will download the whole program\n");
 
320
      printf("with the ultra slow bootstrap utility @ 2400 baud, this means even\n");
 
321
      printf("the smallest hello-world program will take about 13-14 seconds to\n");
 
322
      printf("complete, please be patient.\n");
 
323
      printf("Also note that stdout will not work until it is set up in user code!!!\n");
 
324
 
 
325
      i=0;
 
326
      while (!feof(coldboot))
 
327
        {
 
328
          fread(&ch, 1, 1, coldboot);
 
329
          if (feof(coldboot)) break;
 
330
 
 
331
          /** Make the rawmode target code bypass the handshake BA BE etc. */
 
332
          if (i==0x3e)
 
333
            {
 
334
              /** Are we the dummy mnemonic ld hl,NN ???  */
 
335
              if (ch==0x21)
 
336
                {
 
337
                  ch=0xc3;  /** jp NN mnemonic, address is same */
 
338
                  fprintf(stderr, "Changing to jp at address 0x03h\n");
 
339
                }
 
340
              else
 
341
                {
 
342
                  fprintf(stderr, "Wrong magic pattern in .LOD file, have you changed rcmx000_boot.asm???\n");
 
343
                  exit(1);
 
344
                }
 
345
            }
 
346
          
 
347
          write(tty, &ch, 1);
 
348
          
 
349
          if (debug_hex) fprintf(stderr, "wrote: %.2x \n", ch);
 
350
          
 
351
          i++;
 
352
        }
 
353
      
 
354
    }
 
355
  else  /** We take the cold boot section from this binaries own data... */
 
356
    {
 
357
      for (i=0;i<s_num_bytes;i++)
 
358
        {
 
359
          ch=s_lodfile[i];
 
360
 
 
361
          /** Patch the divisor in... */
 
362
          if (i==0x23)
 
363
            {
 
364
              if (ch==42)
 
365
                {
 
366
                  ch=divisor-1;
 
367
                  fprintf(stderr, "Changing divisor to: %d\n", ch);
 
368
                }
 
369
              else
 
370
                {
 
371
                  fprintf(stderr, "Wrong magic pattern in .LOD file, have you changed rcmx000_boot.asm???\n");
 
372
                  exit(1);
 
373
                }
 
374
            }
 
375
 
 
376
          write(tty, &ch, 1);      
 
377
          if (debug_hex) fprintf(stderr, "(raw) wrote: %.2x \n", ch);
 
378
        }
 
379
      
 
380
    }
 
381
 
 
382
  if (is_raw) 
 
383
    {
 
384
      fprintf(stderr, "Waiting indefinately for reply...\n");
 
385
      talk(tty);
 
386
      exit(0);
 
387
    }
 
388
 
 
389
  /** Handshake protocol to bump baudrate */
 
390
  
 
391
  read(tty, &ch, 1);
 
392
  if (debug_hex) fprintf(stderr, "Got: %.2x (hex))\n", ch);
 
393
  if (ch!=0xba)
 
394
    {
 
395
      fprintf(stderr, "Wrong magic pattern\n");
 
396
      exit(1);
 
397
    }
 
398
 
 
399
  read(tty, &ch, 1);
 
400
  if (debug_hex) fprintf(stderr, "Got: %.2x (hex))\n", ch);
 
401
  if (ch!=0xbe)
 
402
    {
 
403
      fprintf(stderr, "Wrong magic pattern\n");
 
404
      exit(1);
 
405
    }
 
406
 
 
407
  ch=(divisor/24)-1;
 
408
  write(tty, &ch, 1);
 
409
  if (debug_hex) fprintf(stderr, "wrote: %.2x \n", ch);
 
410
  
 
411
  /** Bump the actual baudrate */
 
412
  change_baudrate(tty, 57600);
 
413
 
 
414
 
 
415
  ch=42;
 
416
  write(tty, &ch, 1);
 
417
  if (debug_hex) fprintf(stderr, "wrote: %.2x \n", ch);
 
418
 
 
419
  read(tty, &ch, 1);
 
420
  if (debug_hex) fprintf(stderr, "Got: %.2x (hex))\n", ch);
 
421
  if (ch!=42)
 
422
    {
 
423
      fprintf(stderr, "Wrong value returned from target\n");
 
424
      exit(1);
 
425
    }
 
426
 
 
427
  read(tty, &ch, 1);
 
428
  if (debug_hex) fprintf(stderr, "Got: %.2x (hex))\n", ch);
 
429
  if (ch!=(divisor/24)-1)
 
430
    {
 
431
      fprintf(stderr, "Wrong baudrate divisor in return\n");
 
432
      exit(1);
 
433
    }
 
434
 
 
435
  read(tty, &ch, 1);
 
436
  if (debug_hex) fprintf(stderr, "Got: %.2x (hex))\n", ch);
 
437
  if ( ch != (0xff^(divisor/24)-1) )
 
438
    {
 
439
      fprintf(stderr, "Wrong baudrate divisor in return\n");
 
440
      exit(1);
 
441
    }
 
442
 
 
443
  csum=0;
 
444
 
 
445
  /** Now we transfer the .bin file but first we find out its length */
 
446
  {
 
447
    fseek(binfile, 0, SEEK_END);
 
448
    
 
449
    fsize=ftell(binfile);
 
450
    
 
451
    if (debug_hex) fprintf(stderr, "fsize=%d\n", fsize);
 
452
    
 
453
    /** Network order, two bytes size (max 64k ;-) */
 
454
    ch=fsize&255;
 
455
    write(tty, &ch, 1);
 
456
    if (debug_hex) fprintf(stderr, "wrote: %.2x \n", ch);
 
457
    
 
458
    csum += ch;
 
459
 
 
460
    ch=(fsize>>8)&255;
 
461
    write(tty, &ch, 1);
 
462
    if (debug_hex) fprintf(stderr, "wrote: %.2x \n", ch);
 
463
 
 
464
    csum += ch;
 
465
  }
 
466
 
 
467
  fseek(binfile, 0, SEEK_SET);
 
468
 
 
469
  for (i=0;i<fsize;i++)
 
470
    {
 
471
      fread(&ch, 1, 1, binfile);
 
472
 
 
473
      csum += ch;
 
474
      
 
475
      if (feof(binfile))
 
476
        {
 
477
          fprintf(stderr, "Unexpected EOF in .bin file\n");
 
478
          exit(1);
 
479
        }
 
480
      
 
481
      write(tty, &ch, 1);
 
482
      if (debug_hex) fprintf(stderr, "wrote: %.2x \n", ch);
 
483
    }
 
484
 
 
485
  if (debug_hex) fprintf(stderr, "Checksum lo: %.2x (hex))\n", csum&255);
 
486
  if (debug_hex) fprintf(stderr, "Checksum hi: %.2x (hex))\n", (csum>>8)&255);
 
487
  /** Read the checksum */
 
488
 
 
489
  read(tty, &ch, 1);
 
490
  if (debug_hex) fprintf(stderr, "Got Checksum lo: %.2x (hex))\n", ch);
 
491
  if (ch!=(csum&255))
 
492
    {
 
493
      fprintf(stderr, "Wrong checksum\n");
 
494
      exit(1);
 
495
    }
 
496
 
 
497
  read(tty, &ch, 1);
 
498
  if (debug_hex) fprintf(stderr, "Got Checksum hi: %.2x (hex))\n", ch);
 
499
  if (ch!=((csum/256)&255))
 
500
    {
 
501
      fprintf(stderr, "Wrong checksum\n");
 
502
      exit(1);
 
503
    }
 
504
  
 
505
  /** Start conversation with stdin/stdout of target */
 
506
  talk(tty);
 
507
}