root/arch/m68k/boot/amiga/bootstrap.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usage
  2. main

   1 /*
   2 ** bootstrap.c -- This program loads the Linux/68k kernel into an Amiga
   3 **                and 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 README.legal 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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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[])
     /* [previous][next][first][last][top][bottom][index][help] */
 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 botton 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 }

/* [previous][next][first][last][top][bottom][index][help] */