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

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. getcookie
  2. usage
  3. test_medusa
  4. get_medusa_bank_sizes
  5. boot_exit
  6. main
  7. get_default_args

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

/* [<][>][^][v][top][bottom][index][help] */