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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [boot/] [amiga/] [bootstrap.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
** bootstrap.c -- This program loads the Linux/68k kernel into an Amiga
** bootstrap.c -- This program loads the Linux/68k kernel into an Amiga
**                and launches it.
**                and launches it.
**
**
** Copyright 1993,1994 by Hamish Macdonald, Greg Harp
** Copyright 1993,1994 by Hamish Macdonald, Greg Harp
**
**
** Modified 11-May-94 by Geert Uytterhoeven
** Modified 11-May-94 by Geert Uytterhoeven
**                      (Geert.Uytterhoeven@cs.kuleuven.ac.be)
**                      (Geert.Uytterhoeven@cs.kuleuven.ac.be)
**     - A3640 MapROM check
**     - A3640 MapROM check
** Modified 31-May-94 by Geert Uytterhoeven
** Modified 31-May-94 by Geert Uytterhoeven
**     - Memory thrash problem solved
**     - Memory thrash problem solved
** Modified 07-March-95 by Geert Uytterhoeven
** Modified 07-March-95 by Geert Uytterhoeven
**     - Memory block sizes are rounded to a multiple of 256K instead of 1M
**     - Memory block sizes are rounded to a multiple of 256K instead of 1M
**       This _requires_ >0.9pl5 to work!
**       This _requires_ >0.9pl5 to work!
**       (unless all block sizes are multiples of 1M :-)
**       (unless all block sizes are multiples of 1M :-)
**
**
** This file is subject to the terms and conditions of the GNU General Public
** This file is subject to the terms and conditions of the GNU General Public
** License.  See the file COPYING in the main directory of this archive
** License.  See the file COPYING in the main directory of this archive
** for more details.
** for more details.
**
**
*/
*/
 
 
#include <stddef.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <sys/file.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>
 
 
/* Amiga bootstrap include file */
/* Amiga bootstrap include file */
#include "bootstrap.h"
#include "bootstrap.h"
 
 
/* required Linux/68k include files */
/* required Linux/68k include files */
#include <linux/a.out.h>
#include <linux/a.out.h>
#include <asm/bootinfo.h>
#include <asm/bootinfo.h>
 
 
/* temporary stack size */
/* temporary stack size */
#define TEMP_STACKSIZE  256
#define TEMP_STACKSIZE  256
 
 
/* Exec Base */
/* Exec Base */
extern struct ExecBase *SysBase;
extern struct ExecBase *SysBase;
 
 
extern char *optarg;
extern char *optarg;
 
 
struct exec kexec;
struct exec kexec;
char *memptr;
char *memptr;
u_long start_mem;
u_long start_mem;
u_long mem_size;
u_long mem_size;
u_long rd_size;
u_long rd_size;
 
 
struct ExpansionBase *ExpansionBase;
struct ExpansionBase *ExpansionBase;
struct GfxBase *GfxBase;
struct GfxBase *GfxBase;
 
 
struct bootinfo bi;
struct bootinfo bi;
u_long bi_size = sizeof bi;
u_long bi_size = sizeof bi;
 
 
caddr_t CustomBase = (caddr_t)CUSTOM_PHYSADDR;
caddr_t CustomBase = (caddr_t)CUSTOM_PHYSADDR;
 
 
void usage(void)
void usage(void)
{
{
        fprintf (stderr, "Usage:\n"
        fprintf (stderr, "Usage:\n"
                 "\tbootstrap [-d] [-k kernel_executable] [-r ramdisk_file]"
                 "\tbootstrap [-d] [-k kernel_executable] [-r ramdisk_file]"
                 " [option...]\n");
                 " [option...]\n");
        exit (EXIT_FAILURE);
        exit (EXIT_FAILURE);
}
}
 
 
/*
/*
 * This assembler code is copied to chip ram, and
 * This assembler code is copied to chip ram, and
 * then executed.
 * then executed.
 * It copies the kernel (and ramdisk) to their
 * It copies the kernel (and ramdisk) to their
 * final resting place.
 * final resting place.
 */
 */
#ifndef __GNUC__
#ifndef __GNUC__
#error GNU CC is required to compile the bootstrap program
#error GNU CC is required to compile the bootstrap program
#endif
#endif
asm("
asm("
.text
.text
.globl _copyall, _copyallend
.globl _copyall, _copyallend
_copyall:
_copyall:
                                | /* put variables in registers because they may */
                                | /* put variables in registers because they may */
        lea     _kexec,a3       | /* be overwritten by kernel/ramdisk copy!! - G.U. */
        lea     _kexec,a3       | /* be overwritten by kernel/ramdisk copy!! - G.U. */
        movel   _memptr,a4
        movel   _memptr,a4
        movel   _start_mem,a5
        movel   _start_mem,a5
        movel   _mem_size,d0
        movel   _mem_size,d0
        movel   _rd_size,d1
        movel   _rd_size,d1
        movel   _bi_size,d5
        movel   _bi_size,d5
        movel   a3@(4),d2       | kexec.a_text
        movel   a3@(4),d2       | kexec.a_text
        movel   a3@(8),d3       | kexec.a_data
        movel   a3@(8),d3       | kexec.a_data
        movel   a3@(12),d4      | kexec.a_bss
        movel   a3@(12),d4      | kexec.a_bss
 
 
                                | /* copy kernel text and data */
                                | /* copy kernel text and data */
        movel   a4,a0           | src = (u_long *)memptr;
        movel   a4,a0           | src = (u_long *)memptr;
        movel   a0,a2           | limit = (u_long *)(memptr + kexec.a_text + kexec.a_data);
        movel   a0,a2           | limit = (u_long *)(memptr + kexec.a_text + kexec.a_data);
        addl    d2,a2
        addl    d2,a2
        addl    d3,a2
        addl    d3,a2
        movel   a5,a1           | dest = (u_long *)start_mem;
        movel   a5,a1           | dest = (u_long *)start_mem;
1:      cmpl    a0,a2
1:      cmpl    a0,a2
        beqs    2f              | while (src < limit)
        beqs    2f              | while (src < limit)
        moveb   a0@+,a1@+       |       *dest++ = *src++;
        moveb   a0@+,a1@+       |       *dest++ = *src++;
        bras    1b
        bras    1b
2:
2:
 
 
                                | /* clear kernel bss */
                                | /* clear kernel bss */
        movel   a1,a0           | dest = (u_long *)(start_mem + kexec.a_text + kexec.a_data);
        movel   a1,a0           | dest = (u_long *)(start_mem + kexec.a_text + kexec.a_data);
        movel   a1,a2           | limit = dest + kexec.a_bss / sizeof(u_long);
        movel   a1,a2           | limit = dest + kexec.a_bss / sizeof(u_long);
        addl    d4,a2
        addl    d4,a2
1:      cmpl    a0,a2
1:      cmpl    a0,a2
        beqs    2f              | while (dest < limit)
        beqs    2f              | while (dest < limit)
        clrb    a0@+            |       *dest++ = 0;
        clrb    a0@+            |       *dest++ = 0;
        bras    1b
        bras    1b
2:
2:
 
 
                                | /* copy bootinfo to end of bss */
                                | /* copy bootinfo to end of bss */
        movel   a4,a1           | src = (u long *)memptr + kexec.a_text + kexec.a_data);
        movel   a4,a1           | src = (u long *)memptr + kexec.a_text + kexec.a_data);
        addl    d2,a1
        addl    d2,a1
        addl    d3,a1           | dest = end of bss (already in a0)
        addl    d3,a1           | dest = end of bss (already in a0)
        movel   d5,d7           | count = sizeof bi
        movel   d5,d7           | count = sizeof bi
        subql   #1,d7
        subql   #1,d7
1:      moveb   a1@+,a0@+       | while (--count > -1)
1:      moveb   a1@+,a0@+       | while (--count > -1)
        dbra    d7,1b           |       *dest++ = *src++
        dbra    d7,1b           |       *dest++ = *src++
 
 
 
 
                                | /* copy the ramdisk to the top of memory (from back to front) */
                                | /* copy the ramdisk to the top of memory (from back to front) */
        movel   a5,a1           | dest = (u_long *)(start_mem + mem_size);
        movel   a5,a1           | dest = (u_long *)(start_mem + mem_size);
        addl    d0,a1
        addl    d0,a1
        movel   a4,a2           | limit = (u_long *)(memptr + kexec.a_text + kexec.a_data + sizeof bi);
        movel   a4,a2           | limit = (u_long *)(memptr + kexec.a_text + kexec.a_data + sizeof bi);
        addl    d2,a2
        addl    d2,a2
        addl    d3,a2
        addl    d3,a2
        addl    d5,a2
        addl    d5,a2
        movel   a2,a0           | src = (u_long *)((u_long)limit + rd_size);
        movel   a2,a0           | src = (u_long *)((u_long)limit + rd_size);
        addl    d1,a0
        addl    d1,a0
1:      cmpl    a0,a2
1:      cmpl    a0,a2
        beqs    2f              | while (src > limit)
        beqs    2f              | while (src > limit)
        moveb   a0@-,a1@-       |       *--dest = *--src;
        moveb   a0@-,a1@-       |       *--dest = *--src;
        bras    1b
        bras    1b
2:
2:
                                | /* jump to start of kernel */
                                | /* jump to start of kernel */
        movel   a5,a0           | jump_to (START_MEM);
        movel   a5,a0           | jump_to (START_MEM);
        jsr     a0@
        jsr     a0@
_copyallend:
_copyallend:
");
");
 
 
asm("
asm("
.text
.text
.globl _maprommed
.globl _maprommed
_maprommed:
_maprommed:
        oriw    #0x0700,sr
        oriw    #0x0700,sr
        moveml  #0x3f20,sp@-
        moveml  #0x3f20,sp@-
/* Save cache settings */
/* Save cache settings */
        .long   0x4e7a1002      /* movec cacr,d1 */
        .long   0x4e7a1002      /* movec cacr,d1 */
/* Save MMU settings */
/* Save MMU settings */
        .long   0x4e7a2003      /* movec tc,d2 */
        .long   0x4e7a2003      /* movec tc,d2 */
        .long   0x4e7a3004      /* movec itt0,d3 */
        .long   0x4e7a3004      /* movec itt0,d3 */
        .long   0x4e7a4005      /* movec itt1,d4 */
        .long   0x4e7a4005      /* movec itt1,d4 */
        .long   0x4e7a5006      /* movec dtt0,d5 */
        .long   0x4e7a5006      /* movec dtt0,d5 */
        .long   0x4e7a6007      /* movec dtt1,d6 */
        .long   0x4e7a6007      /* movec dtt1,d6 */
        moveq   #0,d0
        moveq   #0,d0
        movel   d0,a2
        movel   d0,a2
/* Disable caches */
/* Disable caches */
        .long   0x4e7b0002      /* movec d0,cacr */
        .long   0x4e7b0002      /* movec d0,cacr */
/* Disable MMU */
/* Disable MMU */
        .long   0x4e7b0003      /* movec d0,tc */
        .long   0x4e7b0003      /* movec d0,tc */
        .long   0x4e7b0004      /* movec d0,itt0 */
        .long   0x4e7b0004      /* movec d0,itt0 */
        .long   0x4e7b0005      /* movec d0,itt1 */
        .long   0x4e7b0005      /* movec d0,itt1 */
        .long   0x4e7b0006      /* movec d0,dtt0 */
        .long   0x4e7b0006      /* movec d0,dtt0 */
        .long   0x4e7b0007      /* movec d0,dtt1 */
        .long   0x4e7b0007      /* movec d0,dtt1 */
        lea     0x07f80000,a0
        lea     0x07f80000,a0
        lea     0x00f80000,a1
        lea     0x00f80000,a1
        movel   a0@,d7
        movel   a0@,d7
        cmpl    a1@,d7
        cmpl    a1@,d7
        jnes    1f
        jnes    1f
        movel   d7,d0
        movel   d7,d0
        notl    d0
        notl    d0
        movel   d0,a0@
        movel   d0,a0@
        nop
        nop
        cmpl    a1@,d0
        cmpl    a1@,d0
        jnes    1f
        jnes    1f
/* MapROMmed A3640 present */
/* MapROMmed A3640 present */
        moveq   #-1,d0
        moveq   #-1,d0
        movel   d0,a2
        movel   d0,a2
1:      movel   d7,a0@
1:      movel   d7,a0@
/* Restore MMU settings */
/* Restore MMU settings */
        .long   0x4e7b2003      /* movec d2,tc */
        .long   0x4e7b2003      /* movec d2,tc */
        .long   0x4e7b3004      /* movec d3,itt0 */
        .long   0x4e7b3004      /* movec d3,itt0 */
        .long   0x4e7b4005      /* movec d4,itt1 */
        .long   0x4e7b4005      /* movec d4,itt1 */
        .long   0x4e7b5006      /* movec d5,dtt0 */
        .long   0x4e7b5006      /* movec d5,dtt0 */
        .long   0x4e7b6007      /* movec d6,dtt1 */
        .long   0x4e7b6007      /* movec d6,dtt1 */
/* Restore cache settings */
/* Restore cache settings */
        .long   0x4e7b1002      /* movec d1,cacr */
        .long   0x4e7b1002      /* movec d1,cacr */
        movel   a2,d0
        movel   a2,d0
        moveml  sp@+,#0x04fc
        moveml  sp@+,#0x04fc
        rte
        rte
");
");
 
 
extern unsigned long maprommed();
extern unsigned long maprommed();
 
 
 
 
extern char copyall, copyallend;
extern char copyall, copyallend;
 
 
int main(int argc, char *argv[])
int main(int argc, char *argv[])
{
{
        int ch, debugflag = 0, kfd, rfd = -1, i;
        int ch, debugflag = 0, kfd, rfd = -1, i;
        long fast_total = 0;          /* total Fast RAM in system */
        long fast_total = 0;          /* total Fast RAM in system */
        struct MemHeader *mnp;
        struct MemHeader *mnp;
        struct ConfigDev *cdp = NULL;
        struct ConfigDev *cdp = NULL;
        char *kernel_name = "vmlinux";
        char *kernel_name = "vmlinux";
        char *ramdisk_name = NULL;
        char *ramdisk_name = NULL;
        char *memfile = NULL;
        char *memfile = NULL;
        u_long memreq;
        u_long memreq;
        void (*startfunc)(void);
        void (*startfunc)(void);
        long startcodesize;
        long startcodesize;
        u_long *stack, text_offset;
        u_long *stack, text_offset;
        unsigned char *rb3_reg = NULL, *piccolo_reg = NULL, *sd64_reg = NULL;
        unsigned char *rb3_reg = NULL, *piccolo_reg = NULL, *sd64_reg = NULL;
 
 
        /* print the greet message */
        /* print the greet message */
        puts("Linux/68k Amiga Bootstrap version 1.11");
        puts("Linux/68k Amiga Bootstrap version 1.11");
        puts("Copyright 1993,1994 by Hamish Macdonald and Greg Harp\n");
        puts("Copyright 1993,1994 by Hamish Macdonald and Greg Harp\n");
 
 
        /* machine is Amiga */
        /* machine is Amiga */
        bi.machtype = MACH_AMIGA;
        bi.machtype = MACH_AMIGA;
 
 
        /* check arguments */
        /* check arguments */
        while ((ch = getopt(argc, argv, "dk:r:m:")) != EOF)
        while ((ch = getopt(argc, argv, "dk:r:m:")) != EOF)
                switch (ch) {
                switch (ch) {
                    case 'd':
                    case 'd':
                        debugflag = 1;
                        debugflag = 1;
                        break;
                        break;
                    case 'k':
                    case 'k':
                        kernel_name = optarg;
                        kernel_name = optarg;
                        break;
                        break;
                    case 'r':
                    case 'r':
                        ramdisk_name = optarg;
                        ramdisk_name = optarg;
                        break;
                        break;
                    case 'm':
                    case 'm':
                        memfile = optarg;
                        memfile = optarg;
                        break;
                        break;
                    case '?':
                    case '?':
                    default:
                    default:
                        usage();
                        usage();
                }
                }
        argc -= optind;
        argc -= optind;
        argv += optind;
        argv += optind;
 
 
        SysBase = *(struct ExecBase **)4;
        SysBase = *(struct ExecBase **)4;
 
 
        /* Memory & AutoConfig based on 'unix_boot.c' by C= */
        /* Memory & AutoConfig based on 'unix_boot.c' by C= */
 
 
        /* open Expansion Library */
        /* open Expansion Library */
        ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library", 36);
        ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library", 36);
        if (!ExpansionBase) {
        if (!ExpansionBase) {
                puts("Unable to open expansion.library V36 or greater!  Aborting...");
                puts("Unable to open expansion.library V36 or greater!  Aborting...");
                exit(EXIT_FAILURE);
                exit(EXIT_FAILURE);
        }
        }
 
 
        /* find all of the autoconfig boards in the system */
        /* find all of the autoconfig boards in the system */
        cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1);
        cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1);
        for (i=0; (i < NUM_AUTO) && cdp; i++) {
        for (i=0; (i < NUM_AUTO) && cdp; i++) {
                /* copy the contents of each structure into our boot info */
                /* copy the contents of each structure into our boot info */
                memcpy(&bi.bi_amiga.autocon[i], cdp, sizeof(struct ConfigDev));
                memcpy(&bi.bi_amiga.autocon[i], cdp, sizeof(struct ConfigDev));
 
 
                /* count this device */
                /* count this device */
                bi.bi_amiga.num_autocon++;
                bi.bi_amiga.num_autocon++;
 
 
                /* get next device */
                /* get next device */
                cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1);
                cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1);
        }
        }
 
 
        /* find out the memory in the system */
        /* find out the memory in the system */
        for (mnp = (struct MemHeader *)SysBase->MemList.l_head;
        for (mnp = (struct MemHeader *)SysBase->MemList.l_head;
             (bi.num_memory < NUM_MEMINFO) && mnp->mh_Node.ln_Succ;
             (bi.num_memory < NUM_MEMINFO) && mnp->mh_Node.ln_Succ;
             mnp = (struct MemHeader *)mnp->mh_Node.ln_Succ)
             mnp = (struct MemHeader *)mnp->mh_Node.ln_Succ)
        {
        {
                struct MemHeader mh;
                struct MemHeader mh;
 
 
                /* copy the information */
                /* copy the information */
                mh = *mnp;
                mh = *mnp;
 
 
                /* if we suspect that Kickstart is shadowed in an A3000,
                /* if we suspect that Kickstart is shadowed in an A3000,
                   modify the entry to show 512K more at the top of RAM
                   modify the entry to show 512K more at the top of RAM
                   Check first for a MapROMmed A3640 board: overwriting the
                   Check first for a MapROMmed A3640 board: overwriting the
                   Kickstart image causes an infinite lock-up on reboot! */
                   Kickstart image causes an infinite lock-up on reboot! */
 
 
                if (mh.mh_Upper == (void *)0x07f80000)
                if (mh.mh_Upper == (void *)0x07f80000)
                        if ((SysBase->AttnFlags & AFF_68040) && Supervisor(maprommed))
                        if ((SysBase->AttnFlags & AFF_68040) && Supervisor(maprommed))
                                printf("A3640 MapROM detected.\n");
                                printf("A3640 MapROM detected.\n");
                        else {
                        else {
                                mh.mh_Upper = (void *)0x08000000;
                                mh.mh_Upper = (void *)0x08000000;
                                printf("A3000 shadowed Kickstart detected.\n");
                                printf("A3000 shadowed Kickstart detected.\n");
                        }
                        }
 
 
                /* if we suspect that Kickstart is zkicked,
                /* if we suspect that Kickstart is zkicked,
                   modify the entry to show 512K more at the bottom of RAM */
                   modify the entry to show 512K more at the bottom of RAM */
                if (mh.mh_Lower == (void *)0x00280020) {
                if (mh.mh_Lower == (void *)0x00280020) {
                    mh.mh_Lower =  (void *)0x00200000;
                    mh.mh_Lower =  (void *)0x00200000;
                    printf("ZKick detected.\n");
                    printf("ZKick detected.\n");
                }
                }
 
 
                /*
                /*
                 * If this machine has "LOCAL" memory between 0x07000000
                 * If this machine has "LOCAL" memory between 0x07000000
                 * and 0x080000000, then we'll call it an A3000.
                 * and 0x080000000, then we'll call it an A3000.
                 */
                 */
                if (mh.mh_Lower >= (void *)0x07000000 &&
                if (mh.mh_Lower >= (void *)0x07000000 &&
                    mh.mh_Lower <  (void *)0x08000000 &&
                    mh.mh_Lower <  (void *)0x08000000 &&
                    (mh.mh_Attributes & MEMF_LOCAL))
                    (mh.mh_Attributes & MEMF_LOCAL))
                        bi.bi_amiga.model = AMI_3000;
                        bi.bi_amiga.model = AMI_3000;
 
 
                /* mask the memory limit values */
                /* mask the memory limit values */
                mh.mh_Upper = (void *)((u_long)mh.mh_Upper & 0xfffff000);
                mh.mh_Upper = (void *)((u_long)mh.mh_Upper & 0xfffff000);
                mh.mh_Lower = (void *)((u_long)mh.mh_Lower & 0xfffff000);
                mh.mh_Lower = (void *)((u_long)mh.mh_Lower & 0xfffff000);
 
 
                /* if fast memory */
                /* if fast memory */
                if (mh.mh_Attributes & MEMF_FAST) {
                if (mh.mh_Attributes & MEMF_FAST) {
                        unsigned long size;
                        unsigned long size;
 
 
                        /* record the start */
                        /* record the start */
                        bi.memory[bi.num_memory].addr = (u_long)mh.mh_Lower;
                        bi.memory[bi.num_memory].addr = (u_long)mh.mh_Lower;
 
 
                        /* set the size value to the size of this block */
                        /* set the size value to the size of this block */
                        size = (u_long)mh.mh_Upper - (u_long)mh.mh_Lower;
                        size = (u_long)mh.mh_Upper - (u_long)mh.mh_Lower;
 
 
                        /* mask off to a 256K increment */
                        /* mask off to a 256K increment */
                        size &= 0xfffc0000;
                        size &= 0xfffc0000;
 
 
                        fast_total += size;
                        fast_total += size;
 
 
                        if (size > 0)
                        if (size > 0)
                                /* count this block */
                                /* count this block */
                                bi.memory[bi.num_memory++].size  = size;
                                bi.memory[bi.num_memory++].size  = size;
 
 
                } else if (mh.mh_Attributes & MEMF_CHIP) {
                } else if (mh.mh_Attributes & MEMF_CHIP) {
                        /* if CHIP memory, record the size */
                        /* if CHIP memory, record the size */
                        bi.bi_amiga.chip_size =
                        bi.bi_amiga.chip_size =
                                (u_long)mh.mh_Upper; /* - (u_long)mh.mh_Lower; */
                                (u_long)mh.mh_Upper; /* - (u_long)mh.mh_Lower; */
                }
                }
        }
        }
 
 
        CloseLibrary((struct Library *)ExpansionBase);
        CloseLibrary((struct Library *)ExpansionBase);
 
 
        /*
        /*
         * if we have a memory file, read the memory information from it
         * if we have a memory file, read the memory information from it
         */
         */
        if (memfile) {
        if (memfile) {
            FILE *fp;
            FILE *fp;
            int i;
            int i;
 
 
            if ((fp = fopen (memfile, "r")) == NULL) {
            if ((fp = fopen (memfile, "r")) == NULL) {
                perror ("open memory file");
                perror ("open memory file");
                fprintf (stderr, "Cannot open memory file %s\n", memfile);
                fprintf (stderr, "Cannot open memory file %s\n", memfile);
                exit (EXIT_FAILURE);
                exit (EXIT_FAILURE);
            }
            }
 
 
            if (fscanf (fp, "%lu", &bi.bi_amiga.chip_size) != 1) {
            if (fscanf (fp, "%lu", &bi.bi_amiga.chip_size) != 1) {
                fprintf (stderr, "memory file does not contain chip memory size\n");
                fprintf (stderr, "memory file does not contain chip memory size\n");
                fclose (fp);
                fclose (fp);
                exit (EXIT_FAILURE);
                exit (EXIT_FAILURE);
            }
            }
 
 
            for (i = 0; i < NUM_MEMINFO; i++) {
            for (i = 0; i < NUM_MEMINFO; i++) {
                if (fscanf (fp, "%lx %lu", &bi.memory[i].addr,
                if (fscanf (fp, "%lx %lu", &bi.memory[i].addr,
                            &bi.memory[i].size) != 2)
                            &bi.memory[i].size) != 2)
                    break;
                    break;
            }
            }
 
 
            fclose (fp);
            fclose (fp);
 
 
            if (i != bi.num_memory && i > 0)
            if (i != bi.num_memory && i > 0)
                bi.num_memory = i;
                bi.num_memory = i;
        }
        }
 
 
        /* get info from ExecBase */
        /* get info from ExecBase */
        bi.bi_amiga.vblank = SysBase->VBlankFrequency;
        bi.bi_amiga.vblank = SysBase->VBlankFrequency;
        bi.bi_amiga.psfreq = SysBase->PowerSupplyFrequency;
        bi.bi_amiga.psfreq = SysBase->PowerSupplyFrequency;
        bi.bi_amiga.eclock = SysBase->EClockFrequency;
        bi.bi_amiga.eclock = SysBase->EClockFrequency;
 
 
        /* open graphics library */
        /* open graphics library */
        GfxBase = (struct GfxBase *)OpenLibrary ("graphics.library", 0);
        GfxBase = (struct GfxBase *)OpenLibrary ("graphics.library", 0);
 
 
        /* determine chipset */
        /* determine chipset */
        bi.bi_amiga.chipset = CS_STONEAGE;
        bi.bi_amiga.chipset = CS_STONEAGE;
        if(GfxBase)
        if(GfxBase)
        {
        {
            if(GfxBase->ChipRevBits0 & GFXG_AGA)
            if(GfxBase->ChipRevBits0 & GFXG_AGA)
            {
            {
                bi.bi_amiga.chipset = CS_AGA;
                bi.bi_amiga.chipset = CS_AGA;
                /*
                /*
                 *  we considered this machine to be an A3000 because of its
                 *  we considered this machine to be an A3000 because of its
                 *  local memory just beneath $8000000; now if it has AGA, it
                 *  local memory just beneath $8000000; now if it has AGA, it
                 *  must be an A4000
                 *  must be an A4000
                 *  except the case no RAM is installed on the motherboard but
                 *  except the case no RAM is installed on the motherboard but
                 *  on an additional card like FastLane Z3 or on the processor
                 *  on an additional card like FastLane Z3 or on the processor
                 *  board itself. Gotta check this out.
                 *  board itself. Gotta check this out.
                 */
                 */
                bi.bi_amiga.model =
                bi.bi_amiga.model =
                    (bi.bi_amiga.model == AMI_3000) ? AMI_4000 : AMI_1200;
                    (bi.bi_amiga.model == AMI_3000) ? AMI_4000 : AMI_1200;
            }
            }
            else if(GfxBase->ChipRevBits0 & GFXG_ECS)
            else if(GfxBase->ChipRevBits0 & GFXG_ECS)
                bi.bi_amiga.chipset = CS_ECS;
                bi.bi_amiga.chipset = CS_ECS;
            else if(GfxBase->ChipRevBits0 & GFXG_OCS)
            else if(GfxBase->ChipRevBits0 & GFXG_OCS)
                bi.bi_amiga.chipset = CS_OCS;
                bi.bi_amiga.chipset = CS_OCS;
        }
        }
 
 
        /* Display amiga model */
        /* Display amiga model */
        switch (bi.bi_amiga.model) {
        switch (bi.bi_amiga.model) {
            case AMI_UNKNOWN:
            case AMI_UNKNOWN:
                break;
                break;
            case AMI_500:
            case AMI_500:
                printf ("Amiga 500 ");
                printf ("Amiga 500 ");
                break;
                break;
            case AMI_2000:
            case AMI_2000:
                printf ("Amiga 2000 ");
                printf ("Amiga 2000 ");
                break;
                break;
            case AMI_3000:
            case AMI_3000:
                printf ("Amiga 3000 ");
                printf ("Amiga 3000 ");
                break;
                break;
            case AMI_4000:
            case AMI_4000:
                printf ("Amiga 4000 ");
                printf ("Amiga 4000 ");
                break;
                break;
            case AMI_1200:              /* this implies an upgraded model   */
            case AMI_1200:              /* this implies an upgraded model   */
                printf ("Amiga 1200 "); /* equipped with at least 68030 !!! */
                printf ("Amiga 1200 "); /* equipped with at least 68030 !!! */
                break;
                break;
        }
        }
 
 
        /* display and set the CPU <type */
        /* display and set the CPU <type */
        printf("CPU: ");
        printf("CPU: ");
        if (SysBase->AttnFlags & AFF_68040) {
        if (SysBase->AttnFlags & AFF_68040) {
                printf("68040");
                printf("68040");
                bi.cputype = CPU_68040;
                bi.cputype = CPU_68040;
                if (SysBase->AttnFlags & AFF_FPU40) {
                if (SysBase->AttnFlags & AFF_FPU40) {
                        printf(" with internal FPU");
                        printf(" with internal FPU");
                        bi.cputype |= FPU_68040;
                        bi.cputype |= FPU_68040;
                } else
                } else
                        printf(" without FPU");
                        printf(" without FPU");
        } else {
        } else {
                if (SysBase->AttnFlags & AFF_68030) {
                if (SysBase->AttnFlags & AFF_68030) {
                        printf("68030");
                        printf("68030");
                        bi.cputype = CPU_68030;
                        bi.cputype = CPU_68030;
                } else if (SysBase->AttnFlags & AFF_68020) {
                } else if (SysBase->AttnFlags & AFF_68020) {
                        printf("68020 (Do you have an MMU?)");
                        printf("68020 (Do you have an MMU?)");
                        bi.cputype = CPU_68020;
                        bi.cputype = CPU_68020;
                } else {
                } else {
                        puts("Insufficient for Linux.  Aborting...");
                        puts("Insufficient for Linux.  Aborting...");
                        printf("SysBase->AttnFlags = %#x\n", SysBase->AttnFlags);
                        printf("SysBase->AttnFlags = %#x\n", SysBase->AttnFlags);
                        exit (EXIT_FAILURE);
                        exit (EXIT_FAILURE);
                }
                }
                if (SysBase->AttnFlags & AFF_68882) {
                if (SysBase->AttnFlags & AFF_68882) {
                        printf(" with 68882 FPU");
                        printf(" with 68882 FPU");
                        bi.cputype |= FPU_68882;
                        bi.cputype |= FPU_68882;
                } else if (SysBase->AttnFlags & AFF_68881) {
                } else if (SysBase->AttnFlags & AFF_68881) {
                        printf(" with 68881 FPU");
                        printf(" with 68881 FPU");
                        bi.cputype |= FPU_68881;
                        bi.cputype |= FPU_68881;
                } else
                } else
                        printf(" without FPU");
                        printf(" without FPU");
        }
        }
 
 
        switch(bi.bi_amiga.chipset)
        switch(bi.bi_amiga.chipset)
        {
        {
            case CS_STONEAGE:
            case CS_STONEAGE:
                printf(", old or unknown chipset");
                printf(", old or unknown chipset");
                break;
                break;
            case CS_OCS:
            case CS_OCS:
                printf(", OCS");
                printf(", OCS");
                break;
                break;
            case CS_ECS:
            case CS_ECS:
                printf(", ECS");
                printf(", ECS");
                break;
                break;
            case CS_AGA:
            case CS_AGA:
                printf(", AGA chipset");
                printf(", AGA chipset");
                break;
                break;
        }
        }
 
 
        putchar ('\n');
        putchar ('\n');
        putchar ('\n');
        putchar ('\n');
 
 
        /*
        /*
         * Copy command line options into the kernel command line.
         * Copy command line options into the kernel command line.
         */
         */
        i = 0;
        i = 0;
        while (argc--) {
        while (argc--) {
                if ((i+strlen(*argv)+1) < CL_SIZE) {
                if ((i+strlen(*argv)+1) < CL_SIZE) {
                        i += strlen(*argv) + 1;
                        i += strlen(*argv) + 1;
                        if (bi.command_line[0])
                        if (bi.command_line[0])
                                strcat (bi.command_line, " ");
                                strcat (bi.command_line, " ");
                        strcat (bi.command_line, *argv++);
                        strcat (bi.command_line, *argv++);
                }
                }
        }
        }
        printf ("Command line is '%s'\n", bi.command_line);
        printf ("Command line is '%s'\n", bi.command_line);
 
 
        /* display the clock statistics */
        /* display the clock statistics */
        printf("Vertical Blank Frequency: %dHz\nPower Supply Frequency: %dHz\n",
        printf("Vertical Blank Frequency: %dHz\nPower Supply Frequency: %dHz\n",
               bi.bi_amiga.vblank, bi.bi_amiga.psfreq);
               bi.bi_amiga.vblank, bi.bi_amiga.psfreq);
        printf("EClock Frequency: %7.5fKHz\n\n",
        printf("EClock Frequency: %7.5fKHz\n\n",
               (float)bi.bi_amiga.eclock / 1000);
               (float)bi.bi_amiga.eclock / 1000);
 
 
        /* display autoconfig devices */
        /* display autoconfig devices */
        if (bi.bi_amiga.num_autocon) {
        if (bi.bi_amiga.num_autocon) {
                printf("Found %d AutoConfig Device%s", bi.bi_amiga.num_autocon,
                printf("Found %d AutoConfig Device%s", bi.bi_amiga.num_autocon,
                       (bi.bi_amiga.num_autocon > 1)?"s\n":"\n");
                       (bi.bi_amiga.num_autocon > 1)?"s\n":"\n");
                for (i=0; i<bi.bi_amiga.num_autocon; i++)
                for (i=0; i<bi.bi_amiga.num_autocon; i++)
                {
                {
                        printf("Device %d: addr = %08lx\n", i,
                        printf("Device %d: addr = %08lx\n", i,
                               (u_long)bi.bi_amiga.autocon[i].cd_BoardAddr);
                               (u_long)bi.bi_amiga.autocon[i].cd_BoardAddr);
                        /* check for a Rainbow 3 and prepare to reset it if there is one */
                        /* check for a Rainbow 3 and prepare to reset it if there is one */
                        if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH1) &&
                        if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH1) &&
                                 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_RAINBOW3) )
                                 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_RAINBOW3) )
                        {
                        {
                                printf("(Found a Rainbow 3 board - will reset it at kernel boot time)\n");
                                printf("(Found a Rainbow 3 board - will reset it at kernel boot time)\n");
                                rb3_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x01002000);
                                rb3_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x01002000);
                        }
                        }
 
 
                        /* check for a Piccolo and prepare to reset it if there is one */
                        /* check for a Piccolo and prepare to reset it if there is one */
                        if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH2) &&
                        if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH2) &&
                                 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_PICCOLO_REG) )
                                 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_PICCOLO_REG) )
                        {
                        {
                                printf("(Found a Piccolo board - will reset it at kernel boot time)\n");
                                printf("(Found a Piccolo board - will reset it at kernel boot time)\n");
                                piccolo_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x8000);
                                piccolo_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x8000);
                        }
                        }
 
 
                        /* check for a SD64 and prepare to reset it if there is one */
                        /* check for a SD64 and prepare to reset it if there is one */
                        if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH2) &&
                        if ( (bi.bi_amiga.autocon[i].cd_Rom.er_Manufacturer == MANUF_HELFRICH2) &&
                                 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_SD64_REG) )
                                 (bi.bi_amiga.autocon[i].cd_Rom.er_Product == PROD_SD64_REG) )
                        {
                        {
                                printf("(Found a SD64 board - will reset it at kernel boot time)\n");
                                printf("(Found a SD64 board - will reset it at kernel boot time)\n");
                                sd64_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x8000);
                                sd64_reg = (unsigned char *)(bi.bi_amiga.autocon[i].cd_BoardAddr + 0x8000);
                        }
                        }
 
 
                        /* what this code lacks - what if there are several boards of  */
                        /* what this code lacks - what if there are several boards of  */
                        /* the same brand ? In that case I should reset them one after */
                        /* the same brand ? In that case I should reset them one after */
                        /* the other, which is currently not done - a rare case...FN   */
                        /* the other, which is currently not done - a rare case...FN   */
                        /* ok, MY amiga currently hosts all three of the above boards ;-) */
                        /* ok, MY amiga currently hosts all three of the above boards ;-) */
                }
                }
        } else
        } else
                puts("No AutoConfig Devices Found");
                puts("No AutoConfig Devices Found");
 
 
        /* display memory */
        /* display memory */
        if (bi.num_memory) {
        if (bi.num_memory) {
                printf("\n%d Block%sof Memory Found\n", bi.num_memory,
                printf("\n%d Block%sof Memory Found\n", bi.num_memory,
                       (bi.num_memory > 1)?"s ":" ");
                       (bi.num_memory > 1)?"s ":" ");
                for (i=0; i<bi.num_memory; i++) {
                for (i=0; i<bi.num_memory; i++) {
                        printf("Block %d: %08lx to %08lx (%ldKB)\n",
                        printf("Block %d: %08lx to %08lx (%ldKB)\n",
                               i, bi.memory[i].addr,
                               i, bi.memory[i].addr,
                               bi.memory[i].addr + bi.memory[i].size,
                               bi.memory[i].addr + bi.memory[i].size,
                               bi.memory[i].size >> 10);
                               bi.memory[i].size >> 10);
                }
                }
        } else {
        } else {
                puts("No memory found?!  Aborting...");
                puts("No memory found?!  Aborting...");
                exit(10);
                exit(10);
        }
        }
 
 
        /* display chip memory size */
        /* display chip memory size */
        printf ("%ldK of CHIP memory\n", bi.bi_amiga.chip_size >> 10);
        printf ("%ldK of CHIP memory\n", bi.bi_amiga.chip_size >> 10);
 
 
        start_mem = bi.memory[0].addr;
        start_mem = bi.memory[0].addr;
        mem_size = bi.memory[0].size;
        mem_size = bi.memory[0].size;
 
 
        /* tell us where the kernel will go */
        /* tell us where the kernel will go */
        printf("\nThe kernel will be located at %08lx\n", start_mem);
        printf("\nThe kernel will be located at %08lx\n", start_mem);
 
 
        /* verify that there is enough Chip RAM */
        /* verify that there is enough Chip RAM */
        if (bi.bi_amiga.chip_size < 512*1024) {
        if (bi.bi_amiga.chip_size < 512*1024) {
                puts("\nNot enough Chip RAM in this system.  Aborting...");
                puts("\nNot enough Chip RAM in this system.  Aborting...");
                exit(10);
                exit(10);
        }
        }
 
 
        /* verify that there is enough Fast RAM */
        /* verify that there is enough Fast RAM */
        if (fast_total < 2*1024*1024) {
        if (fast_total < 2*1024*1024) {
                puts("\nNot enough Fast RAM in this system.  Aborting...");
                puts("\nNot enough Fast RAM in this system.  Aborting...");
                exit(10);
                exit(10);
        }
        }
 
 
        /* open kernel executable and read exec header */
        /* open kernel executable and read exec header */
        if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
        if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
                fprintf (stderr, "Unable to open kernel file %s\n", kernel_name);
                fprintf (stderr, "Unable to open kernel file %s\n", kernel_name);
                exit (EXIT_FAILURE);
                exit (EXIT_FAILURE);
        }
        }
 
 
        if (read (kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
        if (read (kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
                fprintf (stderr, "Unable to read exec header from %s\n",
                fprintf (stderr, "Unable to read exec header from %s\n",
                         kernel_name);
                         kernel_name);
                exit (EXIT_FAILURE);
                exit (EXIT_FAILURE);
        }
        }
 
 
        switch (N_MAGIC(kexec)) {
        switch (N_MAGIC(kexec)) {
          case ZMAGIC:
          case ZMAGIC:
            text_offset = N_TXTOFF(kexec);
            text_offset = N_TXTOFF(kexec);
            break;
            break;
          case QMAGIC:
          case QMAGIC:
            text_offset = sizeof(kexec);
            text_offset = sizeof(kexec);
            /* the text size includes the exec header; remove this */
            /* the text size includes the exec header; remove this */
            kexec.a_text -= sizeof(kexec);
            kexec.a_text -= sizeof(kexec);
            break;
            break;
          default:
          default:
            fprintf (stderr, "Wrong magic number %lo in kernel header\n",
            fprintf (stderr, "Wrong magic number %lo in kernel header\n",
                     N_MAGIC(kexec));
                     N_MAGIC(kexec));
            exit (EXIT_FAILURE);
            exit (EXIT_FAILURE);
        }
        }
 
 
        /* Load the kernel at one page after start of mem */
        /* Load the kernel at one page after start of mem */
        start_mem += PAGE_SIZE;
        start_mem += PAGE_SIZE;
        mem_size -= PAGE_SIZE;
        mem_size -= PAGE_SIZE;
        /* Align bss size to multiple of four */
        /* Align bss size to multiple of four */
        kexec.a_bss = (kexec.a_bss + 3) & ~3;
        kexec.a_bss = (kexec.a_bss + 3) & ~3;
 
 
        if (ramdisk_name) {
        if (ramdisk_name) {
                if ((rfd = open (ramdisk_name, O_RDONLY)) == -1) {
                if ((rfd = open (ramdisk_name, O_RDONLY)) == -1) {
                        fprintf (stderr, "Unable to open ramdisk file %s\n",
                        fprintf (stderr, "Unable to open ramdisk file %s\n",
                                 ramdisk_name);
                                 ramdisk_name);
                        exit (EXIT_FAILURE);
                        exit (EXIT_FAILURE);
                }
                }
                /* record ramdisk size */
                /* record ramdisk size */
                bi.ramdisk_size = (lseek (rfd, 0, L_XTND) + 1023) >> 10;
                bi.ramdisk_size = (lseek (rfd, 0, L_XTND) + 1023) >> 10;
        } else
        } else
                bi.ramdisk_size = 0;
                bi.ramdisk_size = 0;
 
 
        rd_size = bi.ramdisk_size << 10;
        rd_size = bi.ramdisk_size << 10;
        bi.ramdisk_addr = (u_long)start_mem + mem_size - rd_size;
        bi.ramdisk_addr = (u_long)start_mem + mem_size - rd_size;
 
 
        memreq = kexec.a_text + kexec.a_data + sizeof(bi) + rd_size;
        memreq = kexec.a_text + kexec.a_data + sizeof(bi) + rd_size;
        if (!(memptr = (char *)AllocMem (memreq, MEMF_FAST | MEMF_CLEAR))) {
        if (!(memptr = (char *)AllocMem (memreq, MEMF_FAST | MEMF_CLEAR))) {
                fprintf (stderr, "Unable to allocate memory\n");
                fprintf (stderr, "Unable to allocate memory\n");
                exit (EXIT_FAILURE);
                exit (EXIT_FAILURE);
        }
        }
 
 
        if (lseek (kfd, text_offset, L_SET) == -1) {
        if (lseek (kfd, text_offset, L_SET) == -1) {
                fprintf (stderr, "Failed to seek to text\n");
                fprintf (stderr, "Failed to seek to text\n");
                FreeMem ((void *)memptr, memreq);
                FreeMem ((void *)memptr, memreq);
                exit (EXIT_FAILURE);
                exit (EXIT_FAILURE);
        }
        }
        if (read (kfd, memptr, kexec.a_text) != kexec.a_text) {
        if (read (kfd, memptr, kexec.a_text) != kexec.a_text) {
                fprintf (stderr, "Failed to read text\n");
                fprintf (stderr, "Failed to read text\n");
                FreeMem ((void *)memptr, memreq);
                FreeMem ((void *)memptr, memreq);
                exit (EXIT_FAILURE);
                exit (EXIT_FAILURE);
        }
        }
 
 
        /* data follows immediately after text */
        /* data follows immediately after text */
        if (read (kfd, memptr + kexec.a_text, kexec.a_data) != kexec.a_data) {
        if (read (kfd, memptr + kexec.a_text, kexec.a_data) != kexec.a_data) {
                fprintf (stderr, "Failed to read data\n");
                fprintf (stderr, "Failed to read data\n");
                FreeMem ((void *)memptr, memreq);
                FreeMem ((void *)memptr, memreq);
                exit (EXIT_FAILURE);
                exit (EXIT_FAILURE);
        }
        }
        close (kfd);
        close (kfd);
 
 
        /* copy the boot_info struct to the end of the kernel image */
        /* copy the boot_info struct to the end of the kernel image */
        memcpy ((void *)(memptr + kexec.a_text + kexec.a_data), &bi,
        memcpy ((void *)(memptr + kexec.a_text + kexec.a_data), &bi,
                sizeof(bi));
                sizeof(bi));
 
 
        if (rfd != -1) {
        if (rfd != -1) {
                if (lseek (rfd, 0, L_SET) == -1) {
                if (lseek (rfd, 0, L_SET) == -1) {
                        fprintf (stderr, "Failed to seek to beginning of ramdisk file\n");
                        fprintf (stderr, "Failed to seek to beginning of ramdisk file\n");
                        FreeMem ((void *)memptr, memreq);
                        FreeMem ((void *)memptr, memreq);
                        exit (EXIT_FAILURE);
                        exit (EXIT_FAILURE);
                }
                }
                if (read (rfd, memptr + kexec.a_text + kexec.a_data
                if (read (rfd, memptr + kexec.a_text + kexec.a_data
                          + sizeof(bi), rd_size) != rd_size) {
                          + sizeof(bi), rd_size) != rd_size) {
                        fprintf (stderr, "Failed to read ramdisk file\n");
                        fprintf (stderr, "Failed to read ramdisk file\n");
                        FreeMem ((void *)memptr, memreq);
                        FreeMem ((void *)memptr, memreq);
                        exit (EXIT_FAILURE);
                        exit (EXIT_FAILURE);
                }
                }
                close (rfd);
                close (rfd);
        }
        }
 
 
        /* allocate temporary chip ram stack */
        /* allocate temporary chip ram stack */
        stack = (u_long *)AllocMem( TEMP_STACKSIZE, MEMF_CHIP|MEMF_CLEAR);
        stack = (u_long *)AllocMem( TEMP_STACKSIZE, MEMF_CHIP|MEMF_CLEAR);
        if (!stack) {
        if (!stack) {
                fprintf (stderr, "Unable to allocate memory for stack\n");
                fprintf (stderr, "Unable to allocate memory for stack\n");
                FreeMem ((void *)memptr, memreq);
                FreeMem ((void *)memptr, memreq);
                exit (EXIT_FAILURE);
                exit (EXIT_FAILURE);
        }
        }
 
 
        /* allocate chip ram for copy of startup code */
        /* allocate chip ram for copy of startup code */
        startcodesize = &copyallend - &copyall;
        startcodesize = &copyallend - &copyall;
        startfunc = (void (*)(void))AllocMem( startcodesize, MEMF_CHIP);
        startfunc = (void (*)(void))AllocMem( startcodesize, MEMF_CHIP);
        if (!startfunc) {
        if (!startfunc) {
                fprintf (stderr, "Unable to allocate memory for code\n");
                fprintf (stderr, "Unable to allocate memory for code\n");
                FreeMem ((void *)memptr, memreq);
                FreeMem ((void *)memptr, memreq);
                FreeMem ((void *)stack, TEMP_STACKSIZE);
                FreeMem ((void *)stack, TEMP_STACKSIZE);
                exit (EXIT_FAILURE);
                exit (EXIT_FAILURE);
        }
        }
 
 
        /* copy startup code to CHIP RAM */
        /* copy startup code to CHIP RAM */
        memcpy (startfunc, &copyall, startcodesize);
        memcpy (startfunc, &copyall, startcodesize);
 
 
        if (debugflag) {
        if (debugflag) {
                if (bi.ramdisk_size)
                if (bi.ramdisk_size)
                        printf ("RAM disk at %#lx, size is %ldK\n",
                        printf ("RAM disk at %#lx, size is %ldK\n",
                                (u_long)memptr + kexec.a_text + kexec.a_data,
                                (u_long)memptr + kexec.a_text + kexec.a_data,
                                bi.ramdisk_size);
                                bi.ramdisk_size);
 
 
                printf ("\nKernel text at %#lx, code size %x\n",
                printf ("\nKernel text at %#lx, code size %x\n",
                        start_mem, kexec.a_text);
                        start_mem, kexec.a_text);
                printf ("Kernel data at %#lx, data size %x\n",
                printf ("Kernel data at %#lx, data size %x\n",
                        start_mem + kexec.a_text, kexec.a_data );
                        start_mem + kexec.a_text, kexec.a_data );
                printf ("Kernel bss  at %#lx, bss  size %x\n",
                printf ("Kernel bss  at %#lx, bss  size %x\n",
                        start_mem + kexec.a_text + kexec.a_data,
                        start_mem + kexec.a_text + kexec.a_data,
                        kexec.a_bss );
                        kexec.a_bss );
                printf ("boot info at %#lx\n", start_mem + kexec.a_text
                printf ("boot info at %#lx\n", start_mem + kexec.a_text
                        + kexec.a_data + kexec.a_bss);
                        + kexec.a_data + kexec.a_bss);
 
 
                printf ("\nKernel entry is %#x\n", kexec.a_entry );
                printf ("\nKernel entry is %#x\n", kexec.a_entry );
 
 
                printf ("ramdisk dest top is %#lx\n", start_mem + mem_size);
                printf ("ramdisk dest top is %#lx\n", start_mem + mem_size);
                printf ("ramdisk lower limit is %#lx\n",
                printf ("ramdisk lower limit is %#lx\n",
                        (u_long)(memptr + kexec.a_text + kexec.a_data));
                        (u_long)(memptr + kexec.a_text + kexec.a_data));
                printf ("ramdisk src top is %#lx\n",
                printf ("ramdisk src top is %#lx\n",
                        (u_long)(memptr + kexec.a_text + kexec.a_data)
                        (u_long)(memptr + kexec.a_text + kexec.a_data)
                        + rd_size);
                        + rd_size);
 
 
                printf ("Type a key to continue the Linux boot...");
                printf ("Type a key to continue the Linux boot...");
                fflush (stdout);
                fflush (stdout);
                getchar();
                getchar();
        }
        }
 
 
        /* wait for things to settle down */
        /* wait for things to settle down */
        sleep(2);
        sleep(2);
 
 
        /* FN: If a Rainbow III board is present, reset it to disable */
        /* FN: If a Rainbow III board is present, reset it to disable */
        /* its (possibly activated) vertical blank interrupts as the */
        /* its (possibly activated) vertical blank interrupts as the */
        /* kernel is not yet prepared to handle them (level 6). */
        /* kernel is not yet prepared to handle them (level 6). */
        if (rb3_reg != NULL)
        if (rb3_reg != NULL)
        {
        {
                /* set RESET bit in special function register */
                /* set RESET bit in special function register */
                *rb3_reg = 0x01;
                *rb3_reg = 0x01;
                /* actually, only a few cycles delay are required... */
                /* actually, only a few cycles delay are required... */
                sleep(1);
                sleep(1);
                /* clear reset bit */
                /* clear reset bit */
                *rb3_reg = 0x00;
                *rb3_reg = 0x00;
        }
        }
 
 
        /* the same stuff as above, for the Piccolo board. */
        /* the same stuff as above, for the Piccolo board. */
        /* this also has the side effect of resetting the board's */
        /* this also has the side effect of resetting the board's */
        /* output selection logic to use the Amiga's display in single */
        /* output selection logic to use the Amiga's display in single */
        /* monitor systems - which is currently what we want. */
        /* monitor systems - which is currently what we want. */
        if (piccolo_reg != NULL)
        if (piccolo_reg != NULL)
        {
        {
                /* set RESET bit in special function register */
                /* set RESET bit in special function register */
                *piccolo_reg = 0x01;
                *piccolo_reg = 0x01;
                /* actually, only a few cycles delay are required... */
                /* actually, only a few cycles delay are required... */
                sleep(1);
                sleep(1);
                /* clear reset bit */
                /* clear reset bit */
                *piccolo_reg = 0x51;
                *piccolo_reg = 0x51;
        }
        }
 
 
        /* the same stuff as above, for the SD64 board. */
        /* the same stuff as above, for the SD64 board. */
        /* just as on the Piccolo, this also resets the monitor switch */
        /* just as on the Piccolo, this also resets the monitor switch */
        if (sd64_reg != NULL)
        if (sd64_reg != NULL)
        {
        {
                /* set RESET bit in special function register */
                /* set RESET bit in special function register */
                *sd64_reg = 0x1f;
                *sd64_reg = 0x1f;
                /* actually, only a few cycles delay are required... */
                /* actually, only a few cycles delay are required... */
                sleep(1);
                sleep(1);
        /* clear reset bit AND switch monitor bit (0x20) */
        /* clear reset bit AND switch monitor bit (0x20) */
        *sd64_reg = 0x4f;
        *sd64_reg = 0x4f;
        }
        }
 
 
        if (GfxBase) {
        if (GfxBase) {
                /* set graphics mode to a nice normal one */
                /* set graphics mode to a nice normal one */
                LoadView (NULL);
                LoadView (NULL);
                CloseLibrary ((struct Library *)GfxBase);
                CloseLibrary ((struct Library *)GfxBase);
        }
        }
 
 
        Disable();
        Disable();
 
 
        /* Turn off all DMA */
        /* Turn off all DMA */
        custom.dmacon = DMAF_ALL | DMAF_MASTER;
        custom.dmacon = DMAF_ALL | DMAF_MASTER;
 
 
        /* turn off caches */
        /* turn off caches */
        CacheControl (0L, ~0L);
        CacheControl (0L, ~0L);
 
 
        /* Go into supervisor state */
        /* Go into supervisor state */
        SuperState ();
        SuperState ();
 
 
        /* setup stack */
        /* setup stack */
        change_stack ((char *) stack + TEMP_STACKSIZE);
        change_stack ((char *) stack + TEMP_STACKSIZE);
 
 
        /* turn off any mmu translation */
        /* turn off any mmu translation */
        disable_mmu ();
        disable_mmu ();
 
 
        /* execute the copy-and-go code (from CHIP RAM) */
        /* execute the copy-and-go code (from CHIP RAM) */
        startfunc();
        startfunc();
 
 
        /* NOTREACHED */
        /* NOTREACHED */
}
}
 
 

powered by: WebSVN 2.1.0

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