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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [m68k/] [boot/] [amiga/] [bootstrap.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
** bootstrap.c -- This program loads the Linux/68k kernel into an Amiga
3
**                and launches it.
4
**
5
** Copyright 1993,1994 by Hamish Macdonald, Greg Harp
6
**
7
** Modified 11-May-94 by Geert Uytterhoeven
8
**                      (Geert.Uytterhoeven@cs.kuleuven.ac.be)
9
**     - A3640 MapROM check
10
** Modified 31-May-94 by Geert Uytterhoeven
11
**     - Memory thrash problem solved
12
** Modified 07-March-95 by Geert Uytterhoeven
13
**     - Memory block sizes are rounded to a multiple of 256K instead of 1M
14
**       This _requires_ >0.9pl5 to work!
15
**       (unless all block sizes are multiples of 1M :-)
16
**
17
** This file is subject to the terms and conditions of the GNU General Public
18
** License.  See the file COPYING in the main directory of this archive
19
** for more details.
20
**
21
*/
22
 
23
#include <stddef.h>
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <string.h>
27
#include <sys/file.h>
28
#include <sys/types.h>
29
#include <unistd.h>
30
 
31
/* Amiga bootstrap include file */
32
#include "bootstrap.h"
33
 
34
/* required Linux/68k include files */
35
#include <linux/a.out.h>
36
#include <asm/bootinfo.h>
37
 
38
/* temporary stack size */
39
#define TEMP_STACKSIZE  256
40
 
41
/* Exec Base */
42
extern struct ExecBase *SysBase;
43
 
44
extern char *optarg;
45
 
46
struct exec kexec;
47
char *memptr;
48
u_long start_mem;
49
u_long mem_size;
50
u_long rd_size;
51
 
52
struct ExpansionBase *ExpansionBase;
53
struct GfxBase *GfxBase;
54
 
55
struct bootinfo bi;
56
u_long bi_size = sizeof bi;
57
 
58
caddr_t CustomBase = (caddr_t)CUSTOM_PHYSADDR;
59
 
60
void usage(void)
61
{
62
        fprintf (stderr, "Usage:\n"
63
                 "\tbootstrap [-d] [-k kernel_executable] [-r ramdisk_file]"
64
                 " [option...]\n");
65
        exit (EXIT_FAILURE);
66
}
67
 
68
/*
69
 * This assembler code is copied to chip ram, and
70
 * then executed.
71
 * It copies the kernel (and ramdisk) to their
72
 * final resting place.
73
 */
74
#ifndef __GNUC__
75
#error GNU CC is required to compile the bootstrap program
76
#endif
77
asm("
78
.text
79
.globl _copyall, _copyallend
80
_copyall:
81
                                | /* put variables in registers because they may */
82
        lea     _kexec,a3       | /* be overwritten by kernel/ramdisk copy!! - G.U. */
83
        movel   _memptr,a4
84
        movel   _start_mem,a5
85
        movel   _mem_size,d0
86
        movel   _rd_size,d1
87
        movel   _bi_size,d5
88
        movel   a3@(4),d2       | kexec.a_text
89
        movel   a3@(8),d3       | kexec.a_data
90
        movel   a3@(12),d4      | kexec.a_bss
91
 
92
                                | /* copy kernel text and data */
93
        movel   a4,a0           | src = (u_long *)memptr;
94
        movel   a0,a2           | limit = (u_long *)(memptr + kexec.a_text + kexec.a_data);
95
        addl    d2,a2
96
        addl    d3,a2
97
        movel   a5,a1           | dest = (u_long *)start_mem;
98
1:      cmpl    a0,a2
99
        beqs    2f              | while (src < limit)
100
        moveb   a0@+,a1@+       |       *dest++ = *src++;
101
        bras    1b
102
2:
103
 
104
                                | /* clear kernel bss */
105
        movel   a1,a0           | dest = (u_long *)(start_mem + kexec.a_text + kexec.a_data);
106
        movel   a1,a2           | limit = dest + kexec.a_bss / sizeof(u_long);
107
        addl    d4,a2
108
1:      cmpl    a0,a2
109
        beqs    2f              | while (dest < limit)
110
        clrb    a0@+            |       *dest++ = 0;
111
        bras    1b
112
2:
113
 
114
                                | /* copy bootinfo to end of bss */
115
        movel   a4,a1           | src = (u long *)memptr + kexec.a_text + kexec.a_data);
116
        addl    d2,a1
117
        addl    d3,a1           | dest = end of bss (already in a0)
118
        movel   d5,d7           | count = sizeof bi
119
        subql   #1,d7
120
1:      moveb   a1@+,a0@+       | while (--count > -1)
121
        dbra    d7,1b           |       *dest++ = *src++
122
 
123
 
124
                                | /* copy the ramdisk to the top of memory (from back to front) */
125
        movel   a5,a1           | dest = (u_long *)(start_mem + mem_size);
126
        addl    d0,a1
127
        movel   a4,a2           | limit = (u_long *)(memptr + kexec.a_text + kexec.a_data + sizeof bi);
128
        addl    d2,a2
129
        addl    d3,a2
130
        addl    d5,a2
131
        movel   a2,a0           | src = (u_long *)((u_long)limit + rd_size);
132
        addl    d1,a0
133
1:      cmpl    a0,a2
134
        beqs    2f              | while (src > limit)
135
        moveb   a0@-,a1@-       |       *--dest = *--src;
136
        bras    1b
137
2:
138
                                | /* jump to start of kernel */
139
        movel   a5,a0           | jump_to (START_MEM);
140
        jsr     a0@
141
_copyallend:
142
");
143
 
144
asm("
145
.text
146
.globl _maprommed
147
_maprommed:
148
        oriw    #0x0700,sr
149
        moveml  #0x3f20,sp@-
150
/* Save cache settings */
151
        .long   0x4e7a1002      /* movec cacr,d1 */
152
/* Save MMU settings */
153
        .long   0x4e7a2003      /* movec tc,d2 */
154
        .long   0x4e7a3004      /* movec itt0,d3 */
155
        .long   0x4e7a4005      /* movec itt1,d4 */
156
        .long   0x4e7a5006      /* movec dtt0,d5 */
157
        .long   0x4e7a6007      /* movec dtt1,d6 */
158
        moveq   #0,d0
159
        movel   d0,a2
160
/* Disable caches */
161
        .long   0x4e7b0002      /* movec d0,cacr */
162
/* Disable MMU */
163
        .long   0x4e7b0003      /* movec d0,tc */
164
        .long   0x4e7b0004      /* movec d0,itt0 */
165
        .long   0x4e7b0005      /* movec d0,itt1 */
166
        .long   0x4e7b0006      /* movec d0,dtt0 */
167
        .long   0x4e7b0007      /* movec d0,dtt1 */
168
        lea     0x07f80000,a0
169
        lea     0x00f80000,a1
170
        movel   a0@,d7
171
        cmpl    a1@,d7
172
        jnes    1f
173
        movel   d7,d0
174
        notl    d0
175
        movel   d0,a0@
176
        nop
177
        cmpl    a1@,d0
178
        jnes    1f
179
/* MapROMmed A3640 present */
180
        moveq   #-1,d0
181
        movel   d0,a2
182
1:      movel   d7,a0@
183
/* Restore MMU settings */
184
        .long   0x4e7b2003      /* movec d2,tc */
185
        .long   0x4e7b3004      /* movec d3,itt0 */
186
        .long   0x4e7b4005      /* movec d4,itt1 */
187
        .long   0x4e7b5006      /* movec d5,dtt0 */
188
        .long   0x4e7b6007      /* movec d6,dtt1 */
189
/* Restore cache settings */
190
        .long   0x4e7b1002      /* movec d1,cacr */
191
        movel   a2,d0
192
        moveml  sp@+,#0x04fc
193
        rte
194
");
195
 
196
extern unsigned long maprommed();
197
 
198
 
199
extern char copyall, copyallend;
200
 
201
int main(int argc, char *argv[])
202
{
203
        int ch, debugflag = 0, kfd, rfd = -1, i;
204
        long fast_total = 0;          /* total Fast RAM in system */
205
        struct MemHeader *mnp;
206
        struct ConfigDev *cdp = NULL;
207
        char *kernel_name = "vmlinux";
208
        char *ramdisk_name = NULL;
209
        char *memfile = NULL;
210
        u_long memreq;
211
        void (*startfunc)(void);
212
        long startcodesize;
213
        u_long *stack, text_offset;
214
        unsigned char *rb3_reg = NULL, *piccolo_reg = NULL, *sd64_reg = NULL;
215
 
216
        /* print the greet message */
217
        puts("Linux/68k Amiga Bootstrap version 1.11");
218
        puts("Copyright 1993,1994 by Hamish Macdonald and Greg Harp\n");
219
 
220
        /* machine is Amiga */
221
        bi.machtype = MACH_AMIGA;
222
 
223
        /* check arguments */
224
        while ((ch = getopt(argc, argv, "dk:r:m:")) != EOF)
225
                switch (ch) {
226
                    case 'd':
227
                        debugflag = 1;
228
                        break;
229
                    case 'k':
230
                        kernel_name = optarg;
231
                        break;
232
                    case 'r':
233
                        ramdisk_name = optarg;
234
                        break;
235
                    case 'm':
236
                        memfile = optarg;
237
                        break;
238
                    case '?':
239
                    default:
240
                        usage();
241
                }
242
        argc -= optind;
243
        argv += optind;
244
 
245
        SysBase = *(struct ExecBase **)4;
246
 
247
        /* Memory & AutoConfig based on 'unix_boot.c' by C= */
248
 
249
        /* open Expansion Library */
250
        ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library", 36);
251
        if (!ExpansionBase) {
252
                puts("Unable to open expansion.library V36 or greater!  Aborting...");
253
                exit(EXIT_FAILURE);
254
        }
255
 
256
        /* find all of the autoconfig boards in the system */
257
        cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1);
258
        for (i=0; (i < NUM_AUTO) && cdp; i++) {
259
                /* copy the contents of each structure into our boot info */
260
                memcpy(&bi.bi_amiga.autocon[i], cdp, sizeof(struct ConfigDev));
261
 
262
                /* count this device */
263
                bi.bi_amiga.num_autocon++;
264
 
265
                /* get next device */
266
                cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1);
267
        }
268
 
269
        /* find out the memory in the system */
270
        for (mnp = (struct MemHeader *)SysBase->MemList.l_head;
271
             (bi.num_memory < NUM_MEMINFO) && mnp->mh_Node.ln_Succ;
272
             mnp = (struct MemHeader *)mnp->mh_Node.ln_Succ)
273
        {
274
                struct MemHeader mh;
275
 
276
                /* copy the information */
277
                mh = *mnp;
278
 
279
                /* if we suspect that Kickstart is shadowed in an A3000,
280
                   modify the entry to show 512K more at the top of RAM
281
                   Check first for a MapROMmed A3640 board: overwriting the
282
                   Kickstart image causes an infinite lock-up on reboot! */
283
 
284
                if (mh.mh_Upper == (void *)0x07f80000)
285
                        if ((SysBase->AttnFlags & AFF_68040) && Supervisor(maprommed))
286
                                printf("A3640 MapROM detected.\n");
287
                        else {
288
                                mh.mh_Upper = (void *)0x08000000;
289
                                printf("A3000 shadowed Kickstart detected.\n");
290
                        }
291
 
292
                /* if we suspect that Kickstart is zkicked,
293
                   modify the entry to show 512K more at the bottom of RAM */
294
                if (mh.mh_Lower == (void *)0x00280020) {
295
                    mh.mh_Lower =  (void *)0x00200000;
296
                    printf("ZKick detected.\n");
297
                }
298
 
299
                /*
300
                 * If this machine has "LOCAL" memory between 0x07000000
301
                 * and 0x080000000, then we'll call it an A3000.
302
                 */
303
                if (mh.mh_Lower >= (void *)0x07000000 &&
304
                    mh.mh_Lower <  (void *)0x08000000 &&
305
                    (mh.mh_Attributes & MEMF_LOCAL))
306
                        bi.bi_amiga.model = AMI_3000;
307
 
308
                /* mask the memory limit values */
309
                mh.mh_Upper = (void *)((u_long)mh.mh_Upper & 0xfffff000);
310
                mh.mh_Lower = (void *)((u_long)mh.mh_Lower & 0xfffff000);
311
 
312
                /* if fast memory */
313
                if (mh.mh_Attributes & MEMF_FAST) {
314
                        unsigned long size;
315
 
316
                        /* record the start */
317
                        bi.memory[bi.num_memory].addr = (u_long)mh.mh_Lower;
318
 
319
                        /* set the size value to the size of this block */
320
                        size = (u_long)mh.mh_Upper - (u_long)mh.mh_Lower;
321
 
322
                        /* mask off to a 256K increment */
323
                        size &= 0xfffc0000;
324
 
325
                        fast_total += size;
326
 
327
                        if (size > 0)
328
                                /* count this block */
329
                                bi.memory[bi.num_memory++].size  = size;
330
 
331
                } else if (mh.mh_Attributes & MEMF_CHIP) {
332
                        /* if CHIP memory, record the size */
333
                        bi.bi_amiga.chip_size =
334
                                (u_long)mh.mh_Upper; /* - (u_long)mh.mh_Lower; */
335
                }
336
        }
337
 
338
        CloseLibrary((struct Library *)ExpansionBase);
339
 
340
        /*
341
         * if we have a memory file, read the memory information from it
342
         */
343
        if (memfile) {
344
            FILE *fp;
345
            int i;
346
 
347
            if ((fp = fopen (memfile, "r")) == NULL) {
348
                perror ("open memory file");
349
                fprintf (stderr, "Cannot open memory file %s\n", memfile);
350
                exit (EXIT_FAILURE);
351
            }
352
 
353
            if (fscanf (fp, "%lu", &bi.bi_amiga.chip_size) != 1) {
354
                fprintf (stderr, "memory file does not contain chip memory size\n");
355
                fclose (fp);
356
                exit (EXIT_FAILURE);
357
            }
358
 
359
            for (i = 0; i < NUM_MEMINFO; i++) {
360
                if (fscanf (fp, "%lx %lu", &bi.memory[i].addr,
361
                            &bi.memory[i].size) != 2)
362
                    break;
363
            }
364
 
365
            fclose (fp);
366
 
367
            if (i != bi.num_memory && i > 0)
368
                bi.num_memory = i;
369
        }
370
 
371
        /* get info from ExecBase */
372
        bi.bi_amiga.vblank = SysBase->VBlankFrequency;
373
        bi.bi_amiga.psfreq = SysBase->PowerSupplyFrequency;
374
        bi.bi_amiga.eclock = SysBase->EClockFrequency;
375
 
376
        /* open graphics library */
377
        GfxBase = (struct GfxBase *)OpenLibrary ("graphics.library", 0);
378
 
379
        /* determine chipset */
380
        bi.bi_amiga.chipset = CS_STONEAGE;
381
        if(GfxBase)
382
        {
383
            if(GfxBase->ChipRevBits0 & GFXG_AGA)
384
            {
385
                bi.bi_amiga.chipset = CS_AGA;
386
                /*
387
                 *  we considered this machine to be an A3000 because of its
388
                 *  local memory just beneath $8000000; now if it has AGA, it
389
                 *  must be an A4000
390
                 *  except the case no RAM is installed on the motherboard but
391
                 *  on an additional card like FastLane Z3 or on the processor
392
                 *  board itself. Gotta check this out.
393
                 */
394
                bi.bi_amiga.model =
395
                    (bi.bi_amiga.model == AMI_3000) ? AMI_4000 : AMI_1200;
396
            }
397
            else if(GfxBase->ChipRevBits0 & GFXG_ECS)
398
                bi.bi_amiga.chipset = CS_ECS;
399
            else if(GfxBase->ChipRevBits0 & GFXG_OCS)
400
                bi.bi_amiga.chipset = CS_OCS;
401
        }
402
 
403
        /* Display amiga model */
404
        switch (bi.bi_amiga.model) {
405
            case AMI_UNKNOWN:
406
                break;
407
            case AMI_500:
408
                printf ("Amiga 500 ");
409
                break;
410
            case AMI_2000:
411
                printf ("Amiga 2000 ");
412
                break;
413
            case AMI_3000:
414
                printf ("Amiga 3000 ");
415
                break;
416
            case AMI_4000:
417
                printf ("Amiga 4000 ");
418
                break;
419
            case AMI_1200:              /* this implies an upgraded model   */
420
                printf ("Amiga 1200 "); /* equipped with at least 68030 !!! */
421
                break;
422
        }
423
 
424
        /* display and set the CPU <type */
425
        printf("CPU: ");
426
        if (SysBase->AttnFlags & AFF_68040) {
427
                printf("68040");
428
                bi.cputype = CPU_68040;
429
                if (SysBase->AttnFlags & AFF_FPU40) {
430
                        printf(" with internal FPU");
431
                        bi.cputype |= FPU_68040;
432
                } else
433
                        printf(" without FPU");
434
        } else {
435
                if (SysBase->AttnFlags & AFF_68030) {
436
                        printf("68030");
437
                        bi.cputype = CPU_68030;
438
                } else if (SysBase->AttnFlags & AFF_68020) {
439
                        printf("68020 (Do you have an MMU?)");
440
                        bi.cputype = CPU_68020;
441
                } else {
442
                        puts("Insufficient for Linux.  Aborting...");
443
                        printf("SysBase->AttnFlags = %#x\n", SysBase->AttnFlags);
444
                        exit (EXIT_FAILURE);
445
                }
446
                if (SysBase->AttnFlags & AFF_68882) {
447
                        printf(" with 68882 FPU");
448
                        bi.cputype |= FPU_68882;
449
                } else if (SysBase->AttnFlags & AFF_68881) {
450
                        printf(" with 68881 FPU");
451
                        bi.cputype |= FPU_68881;
452
                } else
453
                        printf(" without FPU");
454
        }
455
 
456
        switch(bi.bi_amiga.chipset)
457
        {
458
            case CS_STONEAGE:
459
                printf(", old or unknown chipset");
460
                break;
461
            case CS_OCS:
462
                printf(", OCS");
463
                break;
464
            case CS_ECS:
465
                printf(", ECS");
466
                break;
467
            case CS_AGA:
468
                printf(", AGA chipset");
469
                break;
470
        }
471
 
472
        putchar ('\n');
473
        putchar ('\n');
474
 
475
        /*
476
         * Copy command line options into the kernel command line.
477
         */
478
        i = 0;
479
        while (argc--) {
480
                if ((i+strlen(*argv)+1) < CL_SIZE) {
481
                        i += strlen(*argv) + 1;
482
                        if (bi.command_line[0])
483
                                strcat (bi.command_line, " ");
484
                        strcat (bi.command_line, *argv++);
485
                }
486
        }
487
        printf ("Command line is '%s'\n", bi.command_line);
488
 
489
        /* display the clock statistics */
490
        printf("Vertical Blank Frequency: %dHz\nPower Supply Frequency: %dHz\n",
491
               bi.bi_amiga.vblank, bi.bi_amiga.psfreq);
492
        printf("EClock Frequency: %7.5fKHz\n\n",
493
               (float)bi.bi_amiga.eclock / 1000);
494
 
495
        /* display autoconfig devices */
496
        if (bi.bi_amiga.num_autocon) {
497
                printf("Found %d AutoConfig Device%s", bi.bi_amiga.num_autocon,
498
                       (bi.bi_amiga.num_autocon > 1)?"s\n":"\n");
499
                for (i=0; i<bi.bi_amiga.num_autocon; i++)
500
                {
501
                        printf("Device %d: addr = %08lx\n", i,
502
                               (u_long)bi.bi_amiga.autocon[i].cd_BoardAddr);
503
                        /* check for a Rainbow 3 and prepare to reset it if there is one */
504
                        if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH1) &&
505
                                 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_RAINBOW3) )
506
                        {
507
                                printf("(Found a Rainbow 3 board - will reset it at kernel boot time)\n");
508
                                rb3_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x01002000);
509
                        }
510
 
511
                        /* check for a Piccolo and prepare to reset it if there is one */
512
                        if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH2) &&
513
                                 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_PICCOLO_REG) )
514
                        {
515
                                printf("(Found a Piccolo board - will reset it at kernel boot time)\n");
516
                                piccolo_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x8000);
517
                        }
518
 
519
                        /* check for a SD64 and prepare to reset it if there is one */
520
                        if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH2) &&
521
                                 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_SD64_REG) )
522
                        {
523
                                printf("(Found a SD64 board - will reset it at kernel boot time)\n");
524
                                sd64_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x8000);
525
                        }
526
 
527
                        /* what this code lacks - what if there are several boards of  */
528
                        /* the same brand ? In that case I should reset them one after */
529
                        /* the other, which is currently not done - a rare case...FN   */
530
                        /* ok, MY amiga currently hosts all three of the above boards ;-) */
531
                }
532
        } else
533
                puts("No AutoConfig Devices Found");
534
 
535
        /* display memory */
536
        if (bi.num_memory) {
537
                printf("\n%d Block%sof Memory Found\n", bi.num_memory,
538
                       (bi.num_memory > 1)?"s ":" ");
539
                for (i=0; i<bi.num_memory; i++) {
540
                        printf("Block %d: %08lx to %08lx (%ldKB)\n",
541
                               i, bi.memory[i].addr,
542
                               bi.memory[i].addr + bi.memory[i].size,
543
                               bi.memory[i].size >> 10);
544
                }
545
        } else {
546
                puts("No memory found?!  Aborting...");
547
                exit(10);
548
        }
549
 
550
        /* display chip memory size */
551
        printf ("%ldK of CHIP memory\n", bi.bi_amiga.chip_size >> 10);
552
 
553
        start_mem = bi.memory[0].addr;
554
        mem_size = bi.memory[0].size;
555
 
556
        /* tell us where the kernel will go */
557
        printf("\nThe kernel will be located at %08lx\n", start_mem);
558
 
559
        /* verify that there is enough Chip RAM */
560
        if (bi.bi_amiga.chip_size < 512*1024) {
561
                puts("\nNot enough Chip RAM in this system.  Aborting...");
562
                exit(10);
563
        }
564
 
565
        /* verify that there is enough Fast RAM */
566
        if (fast_total < 2*1024*1024) {
567
                puts("\nNot enough Fast RAM in this system.  Aborting...");
568
                exit(10);
569
        }
570
 
571
        /* open kernel executable and read exec header */
572
        if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
573
                fprintf (stderr, "Unable to open kernel file %s\n", kernel_name);
574
                exit (EXIT_FAILURE);
575
        }
576
 
577
        if (read (kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
578
                fprintf (stderr, "Unable to read exec header from %s\n",
579
                         kernel_name);
580
                exit (EXIT_FAILURE);
581
        }
582
 
583
        switch (N_MAGIC(kexec)) {
584
          case ZMAGIC:
585
            text_offset = N_TXTOFF(kexec);
586
            break;
587
          case QMAGIC:
588
            text_offset = sizeof(kexec);
589
            /* the text size includes the exec header; remove this */
590
            kexec.a_text -= sizeof(kexec);
591
            break;
592
          default:
593
            fprintf (stderr, "Wrong magic number %lo in kernel header\n",
594
                     N_MAGIC(kexec));
595
            exit (EXIT_FAILURE);
596
        }
597
 
598
        /* Load the kernel at one page after start of mem */
599
        start_mem += PAGE_SIZE;
600
        mem_size -= PAGE_SIZE;
601
        /* Align bss size to multiple of four */
602
        kexec.a_bss = (kexec.a_bss + 3) & ~3;
603
 
604
        if (ramdisk_name) {
605
                if ((rfd = open (ramdisk_name, O_RDONLY)) == -1) {
606
                        fprintf (stderr, "Unable to open ramdisk file %s\n",
607
                                 ramdisk_name);
608
                        exit (EXIT_FAILURE);
609
                }
610
                /* record ramdisk size */
611
                bi.ramdisk_size = (lseek (rfd, 0, L_XTND) + 1023) >> 10;
612
        } else
613
                bi.ramdisk_size = 0;
614
 
615
        rd_size = bi.ramdisk_size << 10;
616
        bi.ramdisk_addr = (u_long)start_mem + mem_size - rd_size;
617
 
618
        memreq = kexec.a_text + kexec.a_data + sizeof(bi) + rd_size;
619
        if (!(memptr = (char *)AllocMem (memreq, MEMF_FAST | MEMF_CLEAR))) {
620
                fprintf (stderr, "Unable to allocate memory\n");
621
                exit (EXIT_FAILURE);
622
        }
623
 
624
        if (lseek (kfd, text_offset, L_SET) == -1) {
625
                fprintf (stderr, "Failed to seek to text\n");
626
                FreeMem ((void *)memptr, memreq);
627
                exit (EXIT_FAILURE);
628
        }
629
        if (read (kfd, memptr, kexec.a_text) != kexec.a_text) {
630
                fprintf (stderr, "Failed to read text\n");
631
                FreeMem ((void *)memptr, memreq);
632
                exit (EXIT_FAILURE);
633
        }
634
 
635
        /* data follows immediately after text */
636
        if (read (kfd, memptr + kexec.a_text, kexec.a_data) != kexec.a_data) {
637
                fprintf (stderr, "Failed to read data\n");
638
                FreeMem ((void *)memptr, memreq);
639
                exit (EXIT_FAILURE);
640
        }
641
        close (kfd);
642
 
643
        /* copy the boot_info struct to the end of the kernel image */
644
        memcpy ((void *)(memptr + kexec.a_text + kexec.a_data), &bi,
645
                sizeof(bi));
646
 
647
        if (rfd != -1) {
648
                if (lseek (rfd, 0, L_SET) == -1) {
649
                        fprintf (stderr, "Failed to seek to beginning of ramdisk file\n");
650
                        FreeMem ((void *)memptr, memreq);
651
                        exit (EXIT_FAILURE);
652
                }
653
                if (read (rfd, memptr + kexec.a_text + kexec.a_data
654
                          + sizeof(bi), rd_size) != rd_size) {
655
                        fprintf (stderr, "Failed to read ramdisk file\n");
656
                        FreeMem ((void *)memptr, memreq);
657
                        exit (EXIT_FAILURE);
658
                }
659
                close (rfd);
660
        }
661
 
662
        /* allocate temporary chip ram stack */
663
        stack = (u_long *)AllocMem( TEMP_STACKSIZE, MEMF_CHIP|MEMF_CLEAR);
664
        if (!stack) {
665
                fprintf (stderr, "Unable to allocate memory for stack\n");
666
                FreeMem ((void *)memptr, memreq);
667
                exit (EXIT_FAILURE);
668
        }
669
 
670
        /* allocate chip ram for copy of startup code */
671
        startcodesize = &copyallend - &copyall;
672
        startfunc = (void (*)(void))AllocMem( startcodesize, MEMF_CHIP);
673
        if (!startfunc) {
674
                fprintf (stderr, "Unable to allocate memory for code\n");
675
                FreeMem ((void *)memptr, memreq);
676
                FreeMem ((void *)stack, TEMP_STACKSIZE);
677
                exit (EXIT_FAILURE);
678
        }
679
 
680
        /* copy startup code to CHIP RAM */
681
        memcpy (startfunc, &copyall, startcodesize);
682
 
683
        if (debugflag) {
684
                if (bi.ramdisk_size)
685
                        printf ("RAM disk at %#lx, size is %ldK\n",
686
                                (u_long)memptr + kexec.a_text + kexec.a_data,
687
                                bi.ramdisk_size);
688
 
689
                printf ("\nKernel text at %#lx, code size %x\n",
690
                        start_mem, kexec.a_text);
691
                printf ("Kernel data at %#lx, data size %x\n",
692
                        start_mem + kexec.a_text, kexec.a_data );
693
                printf ("Kernel bss  at %#lx, bss  size %x\n",
694
                        start_mem + kexec.a_text + kexec.a_data,
695
                        kexec.a_bss );
696
                printf ("boot info at %#lx\n", start_mem + kexec.a_text
697
                        + kexec.a_data + kexec.a_bss);
698
 
699
                printf ("\nKernel entry is %#x\n", kexec.a_entry );
700
 
701
                printf ("ramdisk dest top is %#lx\n", start_mem + mem_size);
702
                printf ("ramdisk lower limit is %#lx\n",
703
                        (u_long)(memptr + kexec.a_text + kexec.a_data));
704
                printf ("ramdisk src top is %#lx\n",
705
                        (u_long)(memptr + kexec.a_text + kexec.a_data)
706
                        + rd_size);
707
 
708
                printf ("Type a key to continue the Linux boot...");
709
                fflush (stdout);
710
                getchar();
711
        }
712
 
713
        /* wait for things to settle down */
714
        sleep(2);
715
 
716
        /* FN: If a Rainbow III board is present, reset it to disable */
717
        /* its (possibly activated) vertical blank interrupts as the */
718
        /* kernel is not yet prepared to handle them (level 6). */
719
        if (rb3_reg != NULL)
720
        {
721
                /* set RESET bit in special function register */
722
                *rb3_reg = 0x01;
723
                /* actually, only a few cycles delay are required... */
724
                sleep(1);
725
                /* clear reset bit */
726
                *rb3_reg = 0x00;
727
        }
728
 
729
        /* the same stuff as above, for the Piccolo board. */
730
        /* this also has the side effect of resetting the board's */
731
        /* output selection logic to use the Amiga's display in single */
732
        /* monitor systems - which is currently what we want. */
733
        if (piccolo_reg != NULL)
734
        {
735
                /* set RESET bit in special function register */
736
                *piccolo_reg = 0x01;
737
                /* actually, only a few cycles delay are required... */
738
                sleep(1);
739
                /* clear reset bit */
740
                *piccolo_reg = 0x51;
741
        }
742
 
743
        /* the same stuff as above, for the SD64 board. */
744
        /* just as on the Piccolo, this also resets the monitor switch */
745
        if (sd64_reg != NULL)
746
        {
747
                /* set RESET bit in special function register */
748
                *sd64_reg = 0x1f;
749
                /* actually, only a few cycles delay are required... */
750
                sleep(1);
751
        /* clear reset bit AND switch monitor bit (0x20) */
752
        *sd64_reg = 0x4f;
753
        }
754
 
755
        if (GfxBase) {
756
                /* set graphics mode to a nice normal one */
757
                LoadView (NULL);
758
                CloseLibrary ((struct Library *)GfxBase);
759
        }
760
 
761
        Disable();
762
 
763
        /* Turn off all DMA */
764
        custom.dmacon = DMAF_ALL | DMAF_MASTER;
765
 
766
        /* turn off caches */
767
        CacheControl (0L, ~0L);
768
 
769
        /* Go into supervisor state */
770
        SuperState ();
771
 
772
        /* setup stack */
773
        change_stack ((char *) stack + TEMP_STACKSIZE);
774
 
775
        /* turn off any mmu translation */
776
        disable_mmu ();
777
 
778
        /* execute the copy-and-go code (from CHIP RAM) */
779
        startfunc();
780
 
781
        /* NOTREACHED */
782
}

powered by: WebSVN 2.1.0

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