OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [boot/] [atari/] [bootstrap.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1623 jcastillo
/*
2
** bootstrap.c -- Load and launch the Atari Linux kernel
3
**
4
** Copyright 1993 by Arjan Knor
5
**
6
** This file is subject to the terms and conditions of the GNU General Public
7
** License.  See the file COPYING in the main directory of this archive
8
** for more details.
9
**
10
** History:
11
**  10 Dec 1995 BOOTP/TFTP support (Roman)
12
**      03 Oct 1995 Allow kernel to be loaded to TT ram again (Andreas)
13
**      11 Jul 1995 Add support for ELF format kernel (Andreas)
14
**      16 Jun 1995 Adapted to Linux 1.2: kernel always loaded into ST ram
15
**                  (Andreas)
16
**      14 Nov 1994 YANML (Yet Another New Memory Layout :-) kernel
17
**                  start address is KSTART_ADDR + PAGE_SIZE, this
18
**                  does not need the ugly kludge with
19
**                  -fwritable-strings (++andreas)
20
**      09 Sep 1994 Adapted to the new memory layout: All the boot_info entry
21
**                  mentions all ST-Ram and the mover is located somewhere
22
**                  in the middle of memory (roman)
23
**                  Added the default arguments file known from the other
24
**                  bootstrap version
25
**      19 Feb 1994 Changed everything so that it works? (rdv)
26
**      14 Mar 1994 New mini-copy routine used (rdv)
27
*/
28
 
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <unistd.h>
32
#include <stddef.h>
33
#include <string.h>
34
#include <ctype.h>
35
#include "sysvars.h"
36
#include <osbind.h>
37
#include <sys/types.h>
38
#include <sys/file.h>
39
 
40
/* linux specific include files */
41
#include <linux/a.out.h>
42
#include <linux/elf.h>
43
#include <asm/page.h>
44
 
45
#define _LINUX_TYPES_H          /* Hack to prevent including <linux/types.h> */
46
#include <asm/bootinfo.h>
47
 
48
/* Atari bootstrap include file */
49
#include "bootstrap.h"
50
 
51
#define MIN_RAMSIZE     (3)     /* 3 MB */
52
#define TEMP_STACKSIZE 256
53
 
54
extern char *optarg;
55
extern int optind;
56
static void get_default_args( int *argc, char ***argv );
57
/* This is missing in <unistd.h> */
58
extern int sync (void);
59
 
60
struct bootinfo bi;
61
u_long *cookiejar;
62
u_long userstk;
63
 
64
/* getcookie -- function to get the value of the given cookie. */
65
static int getcookie(char *cookie, u_long *value)
66
{
67
    int i = 0;
68
 
69
    while(cookiejar[i] != 0L) {
70
        if(cookiejar[i] == *(u_long *)cookie) {
71
            *value = cookiejar[i + 1];
72
            return 1;
73
        }
74
        i += 2;
75
    }
76
    return -1;
77
}
78
 
79
static void usage(void)
80
{
81
    fprintf(stderr, "Usage:\n"
82
            "\tbootstrap [-dst] [-k kernel_executable] [-r ramdisk_file]"
83
            " [option...]\n");
84
    exit(EXIT_FAILURE);
85
}
86
 
87
/*
88
 * Copy the kernel and the ramdisk to their final resting places.
89
 *
90
 * I assume that the kernel data and the ramdisk reside somewhere
91
 * in the middle of the memory.
92
 *
93
 * This program itself should be somewhere in the first 4096 bytes of memory
94
 * where the kernel never will be. In this way it can never be overwritten
95
 * by itself.
96
 *
97
 * At this point the registers have:
98
 * a0: the start of the final kernel
99
 * a1: the start of the current kernel
100
 * a2: the end of the final ramdisk
101
 * a3: the end of the current ramdisk
102
 * d0: the kernel size
103
 * d1: the ramdisk size
104
 */
105
asm ("
106
.text
107
.globl _copyall, _copyallend
108
_copyall:
109
 
110
        movel   a0,a4           /* save the start of the kernel for booting */
111
 
112
1:      movel   a1@+,a0@+       /* copy the kernel starting at the beginning */
113
        subql   #4,d0
114
        jcc     1b
115
 
116
        tstl    d1
117
        beq             3f
118
 
119
2:      movel   a3@-,a2@-       /* copy the ramdisk starting at the end */
120
        subql   #4,d1
121
        jcc     2b
122
 
123
3:      jmp     a4@             /* jump to the start of the kernel */
124
_copyallend:
125
");
126
 
127
extern char copyall, copyallend;
128
 
129
 
130
/* Test for a Medusa: This is the only machine on which address 0 is
131
 * writeable!
132
 * ...err! On the Afterburner040 (for the Falcon) it's the same... So we do
133
 * another test with 0x00ff82fe, that gives a bus error on the Falcon, but is
134
 * in the range where the Medusa always asserts DTACK.
135
 */
136
 
137
int test_medusa( void )
138
 
139
{       int             rv = 0;
140
 
141
        __asm__ __volatile__
142
                ( "movel        0x8,a0\n\t"
143
                  "movel        sp,a1\n\t"
144
                  "moveb        0x0,d1\n\t"
145
                  "movel        #Lberr,0x8\n\t"
146
                  "moveq        #0,%0\n\t"
147
                  "clrb         0x0\n\t"
148
                  "nop          \n\t"
149
                  "moveb        d1,0x0\n\t"
150
                  "nop          \n\t"
151
                  "tstb         0x00ff82fe\n\t"
152
                  "nop          \n\t"
153
                  "moveq        #1,%0\n"
154
                "Lberr:\t"
155
                  "movel        a1,sp\n\t"
156
                  "movel        a0,0x8"
157
                  : "=d" (rv)
158
                  : /* no inputs */
159
                  : "d1", "a0", "a1", "memory" );
160
 
161
        return( rv );
162
}
163
 
164
 
165
void get_medusa_bank_sizes( u_long *bank1, u_long *bank2 )
166
 
167
{       static u_long   save_addr;
168
        u_long                  test_base, saved_contents[16];
169
#define TESTADDR(i)     (*((u_long *)((char *)test_base + i*8*MB)))
170
#define TESTPAT         0x12345678
171
        unsigned short  oldflags;
172
        int                             i;
173
 
174
        /* This ensures at least that none of the test addresses conflicts
175
         * with the test code itself */
176
        test_base = ((unsigned long)&save_addr & 0x007fffff) | 0x20000000;
177
        *bank1 = *bank2 = 0;
178
 
179
        /* Interrupts must be disabled because arbitrary addresses may be
180
         * temporarily overwritten, even code of an interrupt handler */
181
        __asm__ __volatile__ ( "movew sr,%0; oriw #0x700,sr" : "=g" (oldflags) : );
182
        disable_cache();
183
 
184
        /* save contents of the test addresses */
185
        for( i = 0; i < 16; ++i )
186
                saved_contents[i] = TESTADDR(i);
187
 
188
        /* write 0s into all test addresses */
189
        for( i = 0; i < 16; ++i )
190
                TESTADDR(i) = 0;
191
 
192
        /* test for bank 1 */
193
#if 0
194
        /* This is Freddi's original test, but it didn't work. */
195
        TESTADDR(0) = TESTADDR(1) = TESTPAT;
196
        if (TESTADDR(1) == TESTPAT) {
197
                if (TESTADDR(2) == TESTPAT)
198
                        *bank1 = 8*MB;
199
                else if (TESTADDR(3) == TESTPAT)
200
                        *bank1 = 16*MB;
201
                else
202
                        *bank1 = 32*MB;
203
        }
204
        else {
205
                if (TESTADDR(2) == TESTPAT)
206
                        *bank1 = 0;
207
                else
208
                        *bank1 = 16*MB;
209
        }
210
#else
211
        TESTADDR(0) = TESTPAT;
212
        if (TESTADDR(1) == TESTPAT)
213
                *bank1 = 8*MB;
214
        else if (TESTADDR(2) == TESTPAT)
215
                *bank1 = 16*MB;
216
        else if (TESTADDR(4) == TESTPAT)
217
                *bank1 = 32*MB;
218
        else
219
                *bank1 = 64*MB;
220
#endif
221
 
222
        /* test for bank2 */
223
        if (TESTADDR(8) != 0)
224
                *bank2 = 0;
225
        else {
226
                TESTADDR(8) = TESTPAT;
227
                if (TESTADDR(9) != 0) {
228
                        if (TESTADDR(10) == TESTPAT)
229
                                *bank2 = 8*MB;
230
                        else
231
                                *bank2 = 32*MB;
232
                }
233
                else {
234
                        TESTADDR(9) = TESTPAT;
235
                        if (TESTADDR(10) == TESTPAT)
236
                                *bank2 = 16*MB;
237
                        else
238
                                *bank2 = 64*MB;
239
                }
240
        }
241
 
242
        /* restore contents of the test addresses and restore interrupt mask */
243
        for( i = 0; i < 16; ++i )
244
                TESTADDR(i) = saved_contents[i];
245
        __asm__ __volatile__ ( "movew %0,sr" : : "g" (oldflags) );
246
}
247
 
248
#undef TESTADDR
249
#undef TESTPAT
250
 
251
#ifdef USE_BOOTP
252
# include "bootp.h"
253
#else
254
# define kread  read
255
# define klseek lseek
256
# define kclose close
257
#endif
258
 
259
 
260
/* ++andreas: this must be inline due to Super */
261
static inline void boot_exit (int) __attribute__ ((noreturn));
262
static inline void boot_exit(int status)
263
{
264
    /* first go back to user mode */
265
    (void)Super(userstk);
266
        getchar();
267
    exit(status);
268
}
269
 
270
int main(int argc, char *argv[])
271
{
272
    int debugflag = 0, ch, kfd, rfd = -1, i, ignore_ttram = 0;
273
    int load_to_stram = 0;
274
    char *ramdisk_name, *kernel_name, *memptr;
275
    u_long ST_ramsize, TT_ramsize, memreq;
276
    u_long cpu_type, fpu_type, mch_type, mint;
277
    struct exec kexec;
278
    int elf_kernel = 0;
279
    Elf32_Ehdr kexec_elf;
280
    Elf32_Phdr *kernel_phdrs = NULL;
281
    u_long start_mem, mem_size, rd_size, text_offset = 0, kernel_size;
282
#ifdef USE_BOOTP
283
    int prefer_bootp = 1, kname_set = 0;
284
#endif
285
 
286
    ramdisk_name = NULL;
287
    kernel_name = "vmlinux";
288
 
289
    /* print the startup message */
290
    puts("\fLinux/68k Atari Bootstrap version 1.6"
291
#ifdef USE_BOOTP
292
         " (with BOOTP)"
293
#endif
294
         );
295
    puts("Copyright 1993,1994 by Arjan Knor, Robert de Vries, Roman Hodek, Andreas Schwab\n");
296
 
297
        /* ++roman: If no arguments on the command line, read them from
298
         * file */
299
        if (argc == 1)
300
                get_default_args( &argc, &argv );
301
 
302
    /* machine is Atari */
303
    bi.machtype = MACH_ATARI;
304
 
305
    /* check arguments */
306
#ifdef USE_BOOTP
307
    while ((ch = getopt(argc, argv, "bdtsk:r:")) != EOF)
308
#else
309
    while ((ch = getopt(argc, argv, "dtsk:r:")) != EOF)
310
#endif
311
        switch (ch) {
312
          case 'd':
313
            debugflag = 1;
314
            break;
315
          case 't':
316
            ignore_ttram = 1;
317
            break;
318
          case 's':
319
            load_to_stram = 1;
320
            break;
321
          case 'k':
322
            kernel_name = optarg;
323
#ifdef USE_BOOTP
324
            kname_set = 1;
325
#endif
326
            break;
327
          case 'r':
328
            ramdisk_name = optarg;
329
            break;
330
#ifdef USE_BOOTP
331
          case 'b':
332
            prefer_bootp = 1;
333
            break;
334
#endif
335
          case '?':
336
          default:
337
            usage();
338
        }
339
 
340
    argc -= optind;
341
    argv += optind;
342
 
343
    /* We have to access some system variables to get
344
     * the information we need, so we must switch to
345
     * supervisor mode first.
346
     */
347
    userstk = Super(0L);
348
 
349
    /* get the info we need from the cookie-jar */
350
    cookiejar = *_p_cookies;
351
    if(cookiejar == 0L) {
352
        /* if we find no cookies, it's probably an ST */
353
        fprintf(stderr, "Error: No cookiejar found. Is this an ST?\n");
354
        boot_exit(EXIT_FAILURE);
355
    }
356
 
357
    /* Exit if MiNT/MultiTOS is running.  */
358
    if(getcookie("MiNT", &mint) != -1)
359
    {
360
        puts("Warning: MiNT is running\n");
361
#if 0
362
        puts("Linux cannot be started when MiNT is running. Aborting...\n");
363
        boot_exit(EXIT_FAILURE);
364
#endif
365
    }
366
 
367
    /* get _CPU, _FPU and _MCH */
368
    getcookie("_CPU", &cpu_type);
369
    getcookie("_FPU", &fpu_type);
370
    getcookie("_MCH", &mch_type);
371
 
372
    /* check if we are on a 68030/40 with FPU */
373
    if ((cpu_type != 30 && cpu_type != 40 && cpu_type != 60) ||
374
                (fpu_type >> 16) < 2)
375
    {
376
        puts("Machine type currently not supported. Aborting...");
377
        boot_exit(EXIT_FAILURE);
378
    }
379
 
380
    switch(cpu_type) {
381
      case  0:
382
      case 10: break;
383
      case 20: bi.cputype = CPU_68020; break;
384
      case 30: bi.cputype = CPU_68030; break;
385
      case 40: bi.cputype = CPU_68040; break;
386
      case 60: bi.cputype = CPU_68060; break;
387
      default:
388
        fprintf(stderr, "Error: Unknown CPU type. Aborting...\n");
389
        boot_exit(EXIT_FAILURE);
390
        break;
391
    }
392
 
393
    printf("CPU: %ld; ", cpu_type + 68000);
394
    printf("FPU: ");
395
 
396
    /* check for FPU; in case of a '040 or '060, don't look at _FPU itself,
397
     * some software may set it to wrong values (68882 or the like) */
398
        if (cpu_type == 40) {
399
                bi.cputype |= FPU_68040;
400
                puts( "68040\n" );
401
        }
402
        else if (cpu_type == 60) {
403
                bi.cputype |= FPU_68060;
404
                puts( "68060\n" );
405
        }
406
        else {
407
                switch ((fpu_type >> 16) & 6) {
408
                  case 0:
409
                        puts("not present\n");
410
                        break;
411
                  case 2:
412
                        /* try to determine real type */
413
                        if (fpu_idle_frame_size () != 0x18)
414
                                goto m68882;
415
                        /* fall through */
416
                  case 4:
417
                        bi.cputype |= FPU_68881;
418
                        puts("68881\n");
419
                        break;
420
                  case 6:
421
                  m68882:
422
                        bi.cputype |= FPU_68882;
423
                        puts("68882\n");
424
                        break;
425
                  default:
426
                        puts("Unknown FPU type. Assuming no FPU.");
427
                        break;
428
                }
429
        }
430
 
431
    memset(&bi.bi_atari.hw_present, 0, sizeof(bi.bi_atari.hw_present));
432
 
433
    /* Get the amounts of ST- and TT-RAM. */
434
    /* The size must be a multiple of 1MB. */
435
    i = 0;
436
 
437
    if (!test_medusa()) {
438
        struct {
439
                unsigned short version;   /* version - currently 1 */
440
                unsigned long fr_start; /* start addr FastRAM */
441
                unsigned long fr_len;   /* length FastRAM */
442
        } *magn_cookie;
443
        struct {
444
                unsigned long version;
445
                unsigned long fr_start; /* start addr */
446
                unsigned long fr_len;   /* length */
447
        } *fx_cookie;
448
 
449
        TT_ramsize = 0;
450
        if (!ignore_ttram) {
451
            /* "Original" or properly emulated TT-Ram */
452
            if (*ramtop) {
453
                /* the 'ramtop' variable at 0x05a4 is not
454
                 * officially documented. We use it anyway
455
                 * because it is the only way to get the TTram size.
456
                 * (It is zero if there is no TTram.)
457
                 */
458
                bi.memory[i].addr = TT_RAM_BASE;
459
                bi.memory[i].size = (*ramtop - TT_RAM_BASE) & ~(MB - 1);
460
                TT_ramsize = bi.memory[i].size / MB;
461
                i++;
462
                printf("TT-RAM: %ld Mb; ", TT_ramsize);
463
            }
464
 
465
            /* test for MAGNUM alternate RAM
466
             * added 26.9.1995 M. Schwingen, rincewind@discworld.oche.de
467
             */
468
            if (getcookie("MAGN", (u_long *)&magn_cookie) != -1) {
469
                bi.memory[i].addr = magn_cookie->fr_start;
470
                bi.memory[i].size = magn_cookie->fr_len & ~(MB - 1);
471
                TT_ramsize += bi.memory[i].size / MB;
472
                printf("MAGNUM alternate RAM: %ld Mb; ", bi.memory[i].size/MB);
473
                i++;
474
            }
475
 
476
            /* BlowUps FX */
477
            if (getcookie("BPFX", (u_long *)&fx_cookie) != -1 && fx_cookie) {
478
                /* if fx is set (cookie call above),
479
                 * we assume that BlowUps FX-card
480
                 * is installed. (Nat!)
481
                 */
482
                bi.memory[i].addr = fx_cookie->fr_start;
483
                bi.memory[i].size = fx_cookie->fr_len & ~(MB - 1);
484
                printf("FX alternate RAM: %ld Mb; ", bi.memory[i].size/MB);
485
                i++;
486
            }
487
        }
488
 
489
        bi.memory[i].addr = 0;
490
        bi.memory[i].size = *phystop & ~(MB - 1);
491
        ST_ramsize = bi.memory[i].size / MB;
492
        i++;
493
        printf("ST-RAM: %ld Mb\n", ST_ramsize );
494
 
495
        bi.num_memory = i;
496
 
497
        if (load_to_stram && i > 1) {
498
            /* Put ST-RAM first in the list of mem blocks */
499
            struct mem_info temp = bi.memory[i - 1];
500
            bi.memory[i - 1] = bi.memory[0];
501
            bi.memory[0] = temp;
502
        }
503
    }
504
    else {
505
        u_long  bank1, bank2, medusa_st_ram;
506
 
507
        get_medusa_bank_sizes( &bank1, &bank2 );
508
        medusa_st_ram = *phystop & ~(MB - 1);
509
        bank1 -= medusa_st_ram;
510
        TT_ramsize = 0;
511
 
512
        bi.memory[i].addr = 0;
513
        bi.memory[i].size = medusa_st_ram;
514
        ST_ramsize = bi.memory[i].size / MB;
515
        i++;
516
        printf("Medusa pseudo ST-RAM from bank 1: %ld Mb; ", ST_ramsize );
517
 
518
        if (!ignore_ttram && bank1 > 0) {
519
            bi.memory[i].addr = 0x20000000 + medusa_st_ram;
520
            bi.memory[i].size = bank1;
521
            TT_ramsize += bank1;
522
            i++;
523
            printf("TT-RAM bank 1: %ld Mb; ", bank1/MB );
524
        }
525
 
526
        if (!ignore_ttram && bank2 > 0) {
527
            bi.memory[i].addr = 0x24000000;
528
            bi.memory[i].size = bank2;
529
            TT_ramsize += bank2;
530
            i++;
531
            printf("TT-RAM bank 2: %ld Mb; ", bank2/MB );
532
        }
533
 
534
        bi.num_memory = i;
535
        printf("\n");
536
    }
537
 
538
    /* verify that there is enough RAM; ST- and TT-RAM combined */
539
    if (ST_ramsize + TT_ramsize < MIN_RAMSIZE) {
540
        puts("Not enough RAM. Aborting...");
541
        boot_exit(10);
542
    }
543
 
544
#if 0   
545
    /* Get language/keyboard info */
546
    /* TODO: do we need this ? */
547
    /* Could be used to auto-select keyboard map later on. (rdv) */
548
    if (getcookie("_AKP",&language) == -1)
549
    {
550
        /* Get the language info from the OS-header */
551
        os_header = *_sysbase;
552
        os_header = os_header->os_beg;
553
        lang = (os_header->os_conf) >> 1;
554
        printf("Language: ");
555
        switch(lang) {
556
          case HOL: puts("Dutch"); break; /* Own country first :-) */
557
          case USA: puts("American"); break;
558
          case SWG: puts("Switzerland (German)"); break;
559
          case FRG: puts("German"); break;
560
          case FRA: puts("French"); break;
561
          case SWF: puts("Switzerland (French)"); break;
562
          case UK:  puts("English"); break;
563
          case SPA: puts("Spanish"); break;
564
          case ITA: puts("Italian"); break;
565
          case SWE: puts("Swedish"); break;
566
          case TUR: puts("Turkey"); break;
567
          case FIN: puts("Finnish"); break;
568
          case NOR: puts("Norwegian"); break;
569
          case DEN: puts("Danish"); break;
570
          case SAU: puts("Saudi-Arabian"); break;
571
          default:  puts("Unknown"); break;
572
        }
573
    }
574
    else
575
    {
576
        printf("Language: ");
577
        switch(language & 0x0F)
578
        {
579
          case 1: printf("German "); break;
580
          case 2: printf("French "); break;
581
          case 4: printf("Spanish "); break;
582
          case 5: printf("Italian "); break;
583
          case 7: printf("Swiss French "); break;
584
          case 8: printf("Swiss German "); break;
585
          default: printf("English ");
586
        }
587
        printf("Keyboard type :");
588
        switch(language >> 8)
589
        {
590
          case 1: printf("German "); break;
591
          case 2: printf("French "); break;
592
          case 4: printf("Spanish "); break;
593
          case 5: printf("Italian "); break;
594
          case 7: printf("Swiss French "); break;
595
          case 8: printf("Swiss German "); break;
596
          default: printf("English ");
597
        }
598
        printf("\n");
599
    }
600
#endif
601
 
602
    /* Pass contents of the _MCH cookie to the kernel */
603
    bi.bi_atari.mch_cookie = mch_type;
604
 
605
    /*
606
     * Copy command line options into the kernel command line.
607
     */
608
    i = 0;
609
    while (argc--) {
610
        if ((i+strlen(*argv)+1) < CL_SIZE) {
611
            i += strlen(*argv) + 1;
612
            if (bi.command_line[0])
613
                strcat (bi.command_line, " ");
614
            strcat (bi.command_line, *argv++);
615
        }
616
    }
617
    printf ("Command line is '%s'\n", bi.command_line);
618
 
619
    start_mem = bi.memory[0].addr;
620
    mem_size = bi.memory[0].size;
621
 
622
    /* tell us where the kernel will go */
623
    printf("\nThe kernel will be located at 0x%08lx\n", start_mem);
624
 
625
#ifdef TEST
626
    /*
627
    ** Temporary exit point for testing
628
    */
629
    boot_exit(-1);
630
#endif /* TEST */
631
 
632
#ifdef USE_BOOTP
633
    kfd = -1;
634
    if (prefer_bootp) {
635
        /* First try to get a remote kernel, then use a local kernel (if
636
         * present) */
637
        if (get_remote_kernel( kname_set ? kernel_name : NULL ) < 0) {
638
            printf( "\nremote boot failed; trying local kernel\n" );
639
            if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
640
                fprintf (stderr, "Unable to open kernel file %s\n",
641
                         kernel_name);
642
                boot_exit (EXIT_FAILURE);
643
            }
644
        }
645
    }
646
    else {
647
        /* Try BOOTP if local kernel cannot be opened */
648
        if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
649
            printf( "\nlocal kernel failed; trying remote boot\n" );
650
            if (get_remote_kernel( kname_set ? kernel_name : NULL ) < 0) {
651
                fprintf (stderr, "Unable to remote boot and "
652
                         "to open kernel file %s\n", kernel_name);
653
                boot_exit (EXIT_FAILURE);
654
            }
655
        }
656
    }
657
#else
658
    /* open kernel executable and read exec header */
659
    if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
660
        fprintf (stderr, "Unable to open kernel file %s\n", kernel_name);
661
        boot_exit (EXIT_FAILURE);
662
    }
663
#endif
664
 
665
    if (kread (kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec))
666
    {
667
        fprintf (stderr, "Unable to read exec header from %s\n", kernel_name);
668
        boot_exit (EXIT_FAILURE);
669
    }
670
 
671
    switch (N_MAGIC(kexec)) {
672
    case ZMAGIC:
673
        text_offset = N_TXTOFF(kexec);
674
        break;
675
    case QMAGIC:
676
        text_offset = sizeof(kexec);
677
        /* the text size includes the exec header; remove this */
678
        kexec.a_text -= sizeof(kexec);
679
        break;
680
    default:
681
        /* Try to parse it as an ELF header */
682
        klseek (kfd, 0, SEEK_SET);
683
        if (kread (kfd, (void *)&kexec_elf, sizeof (kexec_elf)) == sizeof (kexec_elf)
684
            && memcmp (&kexec_elf.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0)
685
          {
686
            elf_kernel = 1;
687
            /* A few plausibility checks */
688
            if (kexec_elf.e_type != ET_EXEC || kexec_elf.e_machine != EM_68K
689
                || kexec_elf.e_version != EV_CURRENT)
690
              {
691
                fprintf (stderr, "Invalid ELF header contents in kernel\n");
692
                boot_exit (EXIT_FAILURE);
693
              }
694
            /* Load the program headers */
695
            kernel_phdrs = (Elf32_Phdr *) Malloc (kexec_elf.e_phnum * sizeof (Elf32_Phdr));
696
            if (kernel_phdrs == NULL)
697
              {
698
                fprintf (stderr, "Unable to allocate memory for program headers\n");
699
                boot_exit (EXIT_FAILURE);
700
              }
701
            klseek (kfd, kexec_elf.e_phoff, SEEK_SET);
702
            if (kread (kfd, (void *) kernel_phdrs,
703
                      kexec_elf.e_phnum * sizeof (*kernel_phdrs))
704
                != kexec_elf.e_phnum * sizeof (*kernel_phdrs))
705
              {
706
                fprintf (stderr, "Unable to read program headers from %s\n",
707
                         kernel_name);
708
                boot_exit (EXIT_FAILURE);
709
              }
710
            break;
711
          }
712
        fprintf (stderr, "Wrong magic number %lo in kernel header\n",
713
                 N_MAGIC(kexec));
714
        boot_exit (EXIT_FAILURE);
715
    }
716
 
717
    /* Load the kernel one page after start of mem */
718
    start_mem += PAGE_SIZE;
719
    mem_size -= PAGE_SIZE;
720
    /* Align bss size to multiple of four */
721
    if (!elf_kernel)
722
      kexec.a_bss = (kexec.a_bss + 3) & ~3;
723
 
724
    /* init ramdisk */
725
    if(ramdisk_name) {
726
        if((rfd = open(ramdisk_name, O_RDONLY)) == -1) {
727
            fprintf(stderr, "Unable to open ramdisk file %s\n",
728
                    ramdisk_name);
729
            boot_exit(EXIT_FAILURE);
730
        }
731
        bi.ramdisk_size = (lseek(rfd, 0, SEEK_END) + 1023) / 1024;
732
    }
733
    else
734
        bi.ramdisk_size = 0;
735
 
736
    rd_size = bi.ramdisk_size << 10;
737
    if (mem_size - rd_size < MB && bi.num_memory > 1)
738
      /* If running low on ST ram load ramdisk into alternate ram.  */
739
      bi.ramdisk_addr = (u_long) bi.memory[1].addr + bi.memory[1].size - rd_size;
740
    else
741
      /* Else hopefully there is enough ST ram. */
742
      bi.ramdisk_addr = (u_long)start_mem + mem_size - rd_size;
743
 
744
    /* calculate the total required amount of memory */
745
    if (elf_kernel)
746
      {
747
        u_long min_addr = 0xffffffff, max_addr = 0;
748
        for (i = 0; i < kexec_elf.e_phnum; i++)
749
          {
750
            if (min_addr > kernel_phdrs[i].p_vaddr)
751
              min_addr = kernel_phdrs[i].p_vaddr;
752
            if (max_addr < kernel_phdrs[i].p_vaddr + kernel_phdrs[i].p_memsz)
753
              max_addr = kernel_phdrs[i].p_vaddr + kernel_phdrs[i].p_memsz;
754
          }
755
        /* This is needed for newer linkers that include the header in
756
           the first segment.  */
757
        if (min_addr == 0)
758
          {
759
            min_addr = PAGE_SIZE;
760
            kernel_phdrs[0].p_vaddr += PAGE_SIZE;
761
            kernel_phdrs[0].p_offset += PAGE_SIZE;
762
            kernel_phdrs[0].p_filesz -= PAGE_SIZE;
763
            kernel_phdrs[0].p_memsz -= PAGE_SIZE;
764
          }
765
        kernel_size = max_addr - min_addr;
766
      }
767
    else
768
      kernel_size = kexec.a_text + kexec.a_data + kexec.a_bss;
769
    memreq = kernel_size + sizeof (bi) + rd_size;
770
 
771
    /* allocate RAM for the kernel */
772
    if (!(memptr = (char *)Malloc (memreq)))
773
    {
774
        fprintf (stderr, "Unable to allocate memory for kernel and ramdisk\n");
775
        boot_exit (EXIT_FAILURE);
776
    }
777
    else
778
        fprintf(stderr, "kernel at address %lx\n", (u_long) memptr);
779
 
780
    (void)memset(memptr, 0, memreq);
781
 
782
    /* read the text and data segments from the kernel image */
783
    if (elf_kernel)
784
      {
785
        for (i = 0; i < kexec_elf.e_phnum; i++)
786
          {
787
            if (klseek (kfd, kernel_phdrs[i].p_offset, SEEK_SET) == -1)
788
              {
789
                fprintf (stderr, "Failed to seek to segment %d\n", i);
790
                boot_exit (EXIT_FAILURE);
791
              }
792
            if (kread (kfd, memptr + kernel_phdrs[i].p_vaddr - PAGE_SIZE,
793
                      kernel_phdrs[i].p_filesz)
794
                != kernel_phdrs[i].p_filesz)
795
              {
796
                fprintf (stderr, "Failed to read segment %d\n", i);
797
                boot_exit (EXIT_FAILURE);
798
              }
799
          }
800
      }
801
    else
802
      {
803
        if (klseek (kfd, text_offset, SEEK_SET) == -1)
804
        {
805
            fprintf (stderr, "Failed to seek to text\n");
806
            Mfree ((void *)memptr);
807
            boot_exit (EXIT_FAILURE);
808
        }
809
 
810
        if (kread (kfd, memptr, kexec.a_text) != kexec.a_text)
811
        {
812
            fprintf (stderr, "Failed to read text\n");
813
            Mfree ((void *)memptr);
814
            boot_exit (EXIT_FAILURE);
815
        }
816
 
817
        /* data follows immediately after text */
818
        if (kread (kfd, memptr + kexec.a_text, kexec.a_data) != kexec.a_data)
819
        {
820
            fprintf (stderr, "Failed to read data\n");
821
            Mfree ((void *)memptr);
822
            boot_exit (EXIT_FAILURE);
823
        }
824
      }
825
    kclose (kfd);
826
 
827
    /* copy the boot_info struct to the end of the kernel image */
828
    memcpy ((void *)(memptr + kernel_size),
829
            &bi, sizeof(bi));
830
 
831
    /* read the ramdisk image */
832
    if (rfd != -1)
833
    {
834
        if (lseek (rfd, 0, SEEK_SET) == -1)
835
        {
836
            fprintf (stderr, "Failed to seek to beginning of ramdisk file\n");
837
            Mfree ((void *)memptr);
838
            boot_exit (EXIT_FAILURE);
839
        }
840
        if (read (rfd, memptr + kernel_size + sizeof (bi),
841
                  rd_size) != rd_size)
842
        {
843
            fprintf (stderr, "Failed to read ramdisk file\n");
844
            Mfree ((void *)memptr);
845
            boot_exit (EXIT_FAILURE);
846
        }
847
        close (rfd);
848
    }
849
 
850
    /* for those who want to debug */
851
    if (debugflag)
852
    {
853
        if (bi.ramdisk_size)
854
            printf ("RAM disk at %#lx, size is %ldK\n",
855
                    (u_long)memptr + kernel_size,
856
                    bi.ramdisk_size);
857
 
858
        if (elf_kernel)
859
          {
860
            for (i = 0; i < kexec_elf.e_phnum; i++)
861
              {
862
                printf ("Kernel segment %d at %#lx, size %ld\n", i,
863
                        start_mem + kernel_phdrs[i].p_vaddr - PAGE_SIZE,
864
                        kernel_phdrs[i].p_memsz);
865
              }
866
          }
867
        else
868
          {
869
            printf ("\nKernel text at %#lx, code size %d\n",
870
                    start_mem, kexec.a_text);
871
            printf ("Kernel data at %#lx, data size %d\n",
872
                    start_mem + kexec.a_text, kexec.a_data );
873
            printf ("Kernel bss  at %#lx, bss  size %d\n",
874
                    start_mem + kexec.a_text + kexec.a_data, kexec.a_bss );
875
          }
876
        printf ("\nboot_info is at %#lx\n",
877
                start_mem + kernel_size);
878
        printf ("\nKernel entry is %#lx\n",
879
                elf_kernel ? kexec_elf.e_entry : kexec.a_entry);
880
        printf ("ramdisk dest top is %#lx\n", bi.ramdisk_addr + rd_size);
881
        printf ("ramdisk lower limit is %#lx\n",
882
                (u_long)(memptr + kernel_size));
883
        printf ("ramdisk src top is %#lx\n",
884
                (u_long)(memptr + kernel_size) +
885
                rd_size);
886
 
887
        printf ("Type a key to continue the Linux boot...");
888
        fflush (stdout);
889
        getchar();
890
    }
891
 
892
    printf("Booting Linux...\n");
893
 
894
    sync ();
895
 
896
    /* turn off interrupts... */
897
    disable_interrupts();
898
 
899
    /* turn off caches... */
900
    disable_cache();
901
 
902
    /* ..and any MMU translation */
903
    disable_mmu();
904
 
905
    /* ++guenther: allow reset if launched with MiNT */
906
    *(long*)0x426 = 0;
907
 
908
    /* copy mover code to a safe place if needed */
909
    memcpy ((void *) 0x400, &copyall, &copyallend - &copyall);
910
 
911
    /* setup stack */
912
    change_stack ((void *) PAGE_SIZE);
913
 
914
    /*
915
     * On the Atari you can have two situations:
916
     * 1. One piece of contiguous RAM (Falcon)
917
     * 2. Two pieces of contiguous RAM (TT)
918
     * In case 2 you can load your program into ST-ram and load your data in
919
     * any old RAM you have left.
920
     * In case 1 you could overwrite your own program when copying the
921
     * kernel and ramdisk to their final positions.
922
     * To solve this the mover code is copied to a safe place first.
923
     * Then this program jumps to the mover code. After the mover code
924
     * has finished it jumps to the start of the kernel in its new position.
925
     * I thought the memory just after the interrupt vector table was a safe
926
     * place because it is used by TOS to store some system variables.
927
     * This range goes from 0x400 to approx. 0x5B0.
928
     * This is more than enough for the miniscule mover routine (16 bytes).
929
     */
930
 
931
    jump_to_mover((char *) start_mem, memptr,
932
                  (char *) bi.ramdisk_addr + rd_size, memptr + memreq,
933
                  kernel_size + sizeof (bi),
934
                  rd_size,
935
                  (void *) 0x400);
936
 
937
    for (;;);
938
    /* NOTREACHED */
939
}
940
 
941
 
942
 
943
#define MAXARGS         30
944
 
945
static void get_default_args( int *argc, char ***argv )
946
 
947
{       FILE            *f;
948
        static char     *nargv[MAXARGS];
949
        char            arg[256], *p;
950
        int                     c, quote, state;
951
 
952
        if (!(f = fopen( "bootargs", "r" )))
953
                return;
954
 
955
        *argc = 1;
956
        if (***argv)
957
          nargv[0] = **argv;
958
        else
959
          nargv[0] = "bootstrap";
960
        *argv = nargv;
961
 
962
        quote = state = 0;
963
        p = arg;
964
        while( (c = fgetc(f)) != EOF ) {
965
 
966
                if (state == 0) {
967
                        /* outside args, skip whitespace */
968
                        if (!isspace(c)) {
969
                                state = 1;
970
                                p = arg;
971
                        }
972
                }
973
 
974
                if (state) {
975
                        /* inside an arg: copy it into 'arg', obeying quoting */
976
                        if (!quote && (c == '\'' || c == '"'))
977
                                quote = c;
978
                        else if (quote && c == quote)
979
                                quote = 0;
980
                        else if (!quote && isspace(c)) {
981
                                /* end of this arg */
982
                                *p = 0;
983
                                nargv[(*argc)++] = strdup(arg);
984
                                state = 0;
985
                        }
986
                        else
987
                                *p++ = c;
988
                }
989
        }
990
        if (state) {
991
                /* last arg finished by EOF! */
992
                *p = 0;
993
                nargv[(*argc)++] = strdup(arg);
994
        }
995
        fclose( f );
996
 
997
        nargv[*argc] = 0;
998
}
999
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.