home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / unix / riscbsd / datafile / _btriscbsd / booter / c / bsdbooter next >
Encoding:
Text File  |  1996-07-14  |  22.4 KB  |  842 lines

  1. /* $NetBSD$ */
  2.  
  3. /*
  4.  * Copyright (c) 1994-1996 Mark Brinicombe.
  5.  * Copyright (c) 1994-1996 Brini.
  6.  * All rights reserved.
  7.  *
  8.  * This code is derived from software written for Brini by Mark Brinicombe
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by Mark Brinicombe.
  21.  * 4. The name of the company nor the name of the author may be used to
  22.  *    endorse or promote products derived from this software without specific
  23.  *    prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  26.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  27.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  28.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  29.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  30.  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  31.  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  32.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  33.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  34.  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35.  *
  36.  * RiscBSD kernel project
  37.  *
  38.  * bsdbooter.c
  39.  *
  40.  * RiscBSD boot loader
  41.  *
  42.  * Created      : 12/09/94
  43.  * Last updated : 12/07/96
  44.  *
  45.  * Based on kate/boot/boot.c
  46.  *
  47.  *    $Id$
  48.  */
  49.  
  50. /* Include standard header files */
  51.  
  52. #include <stdarg.h>
  53.  
  54. /* Include local headers */
  55.  
  56. #include "katelib.h"
  57. #include "swiv.h"
  58. #include "swis.h"
  59. #include "arm.h"
  60. #include "stand.h"
  61.  
  62. #include "bootconfig.h"
  63.  
  64. /*
  65.  * Declare global variables
  66.  */
  67.  
  68. # define VERSION "2.80"
  69.  
  70. # define USE_MODULEAREA
  71.  
  72. # define KERNAREA 512
  73. # define KERNBASE 0xf0000000
  74.  
  75. # define TABLEAREA 513
  76. # define LOADAREA 514
  77.  
  78. # define SCRATCHSIZE 0xc000
  79.  
  80.  
  81. # define OS_DynamicArea 0x66
  82. # define OS_Memory      0x68
  83. # define OS_MMUControl  0x6b
  84.  
  85. # define FASTBOOT_FILENAME "<BtRiscBSD$Dir>.booter.fastboot"
  86.  
  87. /*
  88.  * Declare external variables
  89.  */
  90.  
  91. extern char *__cli;
  92.  
  93. /*
  94.  * Local vars. Some of these have to be global because they are used after
  95.  * the processor has been switches to SVC mode local variables would be
  96.  * lost as they would be on the USR mode stack.
  97.  */
  98.  
  99. BootConfig bootconfig;
  100. int in[3], out[3];
  101. char kernelname[1024];
  102. unsigned char *buffer;
  103. static aout_t aout;
  104. unsigned int stringtablesize;
  105. unsigned int kernelsize;
  106. unsigned int logical;
  107. unsigned int physical;
  108. unsigned int filesize;
  109. unsigned int copysize;
  110. unsigned int ptr;
  111. /*
  112.  * Local function prototypes
  113.  */
  114.  
  115. void fatal(struct Error *error);
  116. unsigned char *locate_memory_blocks(void);
  117. void _bsdboot(BootConfig *bootconfig, unsigned int address);
  118.  
  119. /* Now for the main code */
  120.  
  121. extern int main (int, char **);
  122.  
  123. void __exit(int);
  124.  
  125. void _main(void)
  126.   {
  127.     __exit (main (0, (char **)0));    /* ... ignition */
  128.  
  129. /* not reached */
  130.   }
  131.  
  132. /* The main booter code */
  133.  
  134. int main(int argc, char *argv[])
  135.   {
  136.     char *cliptr;
  137.     int loop;
  138.     int filehandle;
  139.     unsigned char *arrangementtable;
  140.     struct Error *error;
  141.  
  142. /* Analyse the command line */
  143.  
  144.     cliptr = __cli;
  145.  
  146. /* Skip the command name */
  147.  
  148.     while (*cliptr != ' ' && *cliptr != 0)
  149.       ++cliptr;
  150.  
  151. /* Skip any spaces */
  152.  
  153.     while (*cliptr == ' ')
  154.       ++cliptr;
  155.  
  156. /* Check for another parameter */
  157.  
  158.     if (*cliptr != 0)
  159.       {
  160.         for (loop = 0; *cliptr != ' ' && *cliptr != 0; ++loop,++cliptr)
  161.           {
  162.             kernelname[loop] = *cliptr;
  163.           }
  164.         kernelname[loop] = 0;
  165.       }
  166.     else
  167.       strcpy(kernelname, "netbsd");
  168.  
  169.     strcpy(bootconfig.kernelname, kernelname);
  170.  
  171. /* Write the command line used to a fastboot file. Execing or Obeying
  172.  * this file will boot RiscBSD. This can be used during the RiscOS bootup
  173.  * to enable a fast boot.
  174.  */
  175.  
  176. /*
  177.  * Open the autoboot file. Just skip if file cannot be opened.
  178.  */
  179.  
  180.     if (strstr(__cli, "nofb") == 0)
  181.       {
  182.         error = swix(OS_Find, IN(R0|R1)|OUT(R0), 0x80, FASTBOOT_FILENAME, &filehandle);
  183.         if (error == NULL && filehandle != 0)
  184.           {
  185.             swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 2, filehandle, __cli,
  186.               strlen(__cli), 0);
  187.             swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 2, filehandle, "\n", 1, 0);
  188.  
  189. /* Close the file */
  190.  
  191.             swi(OS_Find, IN(R0|R1), 0, filehandle);
  192.  
  193.             swi(OS_File, IN(R0|R1|R2), 18, FASTBOOT_FILENAME, 0xfeb);
  194.           }
  195.         else
  196.           {
  197.             printf("Warning: Cannot write fastboot file %s\n", FASTBOOT_FILENAME);
  198.           }
  199.       }
  200.  
  201. /* Set the screen mode ... */
  202.  
  203. /* I know this is messy. It is currently just a hack to try things out
  204.  * Why didn't Acorn add a SWI call to interpret the mode string and return
  205.  * a mode specifer ?
  206.  */
  207.  
  208. /* Also this is temporary as eventually the console driver will set the VIDC
  209.  * up as required.
  210.  * It sort of expects the screenmode= options to be at the end of the string.
  211.  */
  212.  
  213.     {
  214.       char *modeptr;
  215.       int modespec[6];
  216.  
  217.       modeptr = strstr(__cli, "screenmode=");
  218.       if (modeptr)
  219.         {
  220.           modeptr += 11;
  221.           modespec[0] = 0x00000001;
  222.           modespec[1] = 0x00000000;
  223.           modespec[2] = 0x00000000;
  224.           modespec[3] = 0x00000003;
  225.           modespec[4] = 0x00000000;
  226.           modespec[5] = -1;
  227.  
  228.           while (*modeptr)
  229.             {
  230.               switch (*modeptr)
  231.                 {
  232.                   case 'X':
  233.                   case 'x':
  234.                     ++modeptr;
  235.                     while (*modeptr >= '0' && *modeptr <= '9')
  236.                       {
  237.                         modespec[1] = (modespec[1] * 10) + (*modeptr - '0');
  238.                         ++modeptr;
  239.                       }
  240.                     break;
  241.  
  242.                   case 'Y':
  243.                   case 'y':
  244.                     ++modeptr;
  245.                     while (*modeptr >= '0' && *modeptr <= '9')
  246.                       {
  247.                         modespec[2] = (modespec[2] * 10) + (*modeptr - '0');
  248.                         ++modeptr;
  249.                       }
  250.                     break;
  251. /*
  252.                   case 'C':
  253.                   case 'c':
  254.                   case 'G':
  255.                   case 'g':
  256.                     ++modeptr;
  257.                     while (*modeptr >= '0' && *modeptr <= '9')
  258.                       {
  259.                         modespec[3] = (modespec[3] * 10) + (*modeptr - '0');
  260.                         ++modeptr;
  261.                       }
  262.                     break;
  263. */
  264.                   case 'F':
  265.                   case 'f':
  266.                     ++modeptr;
  267.                     while (*modeptr >= '0' && *modeptr <= '9')
  268.                       {
  269.                         modespec[4] = (modespec[4] * 10) + (*modeptr - '0');
  270.                         ++modeptr;
  271.                       }
  272.                     break;
  273.  
  274.                   default:
  275.                     ++modeptr;
  276.                     break;
  277.                 }
  278.             }
  279.           if (modespec[4] == 0) modespec[4] = -1;
  280. /*          printf("x=%d y=%d c=%d f=%d\n", modespec[1], modespec[2],
  281.             modespec[3], modespec[4]);*/
  282.           fatal(swix(Wimp_SetMode, IN(R0), &modespec));
  283.           bootconfig.framerate = modespec[4];
  284.         }
  285.       else
  286.         bootconfig.framerate = 0;
  287.     }
  288.  
  289. /* Announcement time .. */
  290.  
  291.     if (strstr(__cli, "verbose") != 0)
  292.       printf("RiscBSD BootLoader " VERSION " " __DATE__ "\n");
  293.  
  294. /* A bit of info */
  295.  
  296.     if (strstr(__cli, "verbose") != 0)
  297.       printf("Kernel: %s\n\r", kernelname);
  298.  
  299. /* Get the machine id */
  300.  
  301.     fatal(swix(OS_ReadSysInfo, IN(R0)|OUT(R3), 2, &bootconfig.machine_id));
  302.  
  303.     bootconfig.magic = BOOTCONFIG_MAGIC;
  304.  
  305. /* Get the display variables. Failure on any of these will abort the boot */
  306.  
  307.     in[0] = 149;
  308.     in[1] = 150;
  309.     in[2] = -1;
  310.  
  311.     fatal(swix(OS_ReadVduVariables, IN(R0|R1), &in, &out));
  312.  
  313.     bootconfig.display_start = out[0];
  314.     bootconfig.display_size = out[1];
  315.  
  316.     fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 9,
  317.       &bootconfig.bitsperpixel));
  318.     fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 11,
  319.       &bootconfig.width));
  320.     fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 12,
  321.       &bootconfig.height));
  322.  
  323.     {
  324.           int pageblock[3];
  325.  
  326.     pageblock[1] = bootconfig.display_start;
  327.     fatal(swix(OS_Memory, IN(R0|R1|R2) | OUT(R1), 0x2200,
  328.       pageblock, 1, pageblock));
  329.     bootconfig.vdram_phys = pageblock[2];
  330.    }
  331.  
  332. /* Will the kernel support this mode ? */
  333.  
  334.     if (bootconfig.bitsperpixel != 3)
  335.       {
  336.         printf("Error: Current kernels only support 8 bpp for booting.\n");
  337.         return(0);
  338.       }
  339.  
  340. /* Will the kernel support this mode ? */
  341.  
  342.     if (bootconfig.bitsperpixel > 3)
  343.       {
  344.         printf("Error: Only 1, 2, 4 or 8 bpp modes are currently supported\n");
  345.         return(0);
  346.       }
  347.  
  348. /* Get the arrangement table for the memory */
  349.  
  350.     arrangementtable = locate_memory_blocks();
  351.  
  352. /*
  353.  * Ok we support a.out files. This means that we need to
  354.  * identify the type.
  355.  */
  356.  
  357. /* Get the size of the file */
  358.  
  359.     filesize = 0;
  360.     fatal(swix(OS_File, IN(R0|R1)|OUT(R4), 5, kernelname, &filesize));
  361.  
  362. /* Verbose info to the user. This is mainly debugging */
  363.  
  364.     if (strstr(__cli, "verbose") != 0)
  365.       printf("filesize = %08x\n", filesize);
  366.  
  367.     if (filesize == 0) {
  368.       printf("Error: Kernel image too small\n");
  369.       return(0);
  370.     }
  371.  
  372. # ifdef USE_MODULEAREA
  373.  
  374. /* Allocate memory in module area to hold the data we are loading */
  375.  
  376.     fatal(swix(OS_Module, IN(R0|R3)|OUT(R2), 6, filesize, &buffer));
  377.  
  378. # else
  379.  
  380. /* Allocate memory to hold the data we are loading */
  381.  
  382.     swix(OS_DynamicArea, IN(R0|R1), 1, LOADAREA);
  383.  
  384.     fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8)|OUT(R3), 0,
  385.       LOADAREA, filesize, -1, 0x80, filesize, 0, 0, "Kate Data", &buffer));
  386.  
  387. # endif
  388.  
  389. /*
  390.  * Open the file.
  391.  */
  392.  
  393.     swi(OS_Find, IN(R0|R1)|OUT(R0), 0x40, kernelname, &filehandle);
  394.     if (filehandle == 0)
  395.       {
  396.         printf("Error: Cannot read kernel file %s\n", kernelname);
  397.         return(0);
  398.       }
  399.  
  400. /* Load the file into memory */
  401.  
  402.     swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, buffer, filesize, 0);
  403.  
  404. /* Close the file */
  405.  
  406.     fatal(swix(OS_Find, IN(R0|R1), 0, filehandle));
  407.  
  408. /* Take a copy of the possible a.out header */
  409.  
  410.     aout = *((aout_t *)buffer);
  411.  
  412. /* Do we have an a.out file ? */
  413.  
  414.     switch(aout.a_magic & MAGICMASK) {
  415.       case NMAGIC:
  416.         if (strstr(__cli, "verbose") != 0)
  417.           printf("Kernel binary is NMAGIC a.out format\n");
  418.         aout.a_syms = 0;
  419.         stringtablesize = 0;
  420.     break;
  421.       case OMAGIC:
  422.         if (strstr(__cli, "verbose") != 0)
  423.           printf("Kernel binary is OMAGIC a.out format\n");
  424.         aout.a_syms = 0;
  425.         stringtablesize = 0;
  426.     break;
  427.       case ZMAGIC:
  428.         if (strstr(__cli, "verbose") != 0)
  429.           printf("Kernel binary is ZMAGIC a.out format\n");
  430.         stringtablesize = filesize - (unsigned int)(aout.a_text +
  431.           aout.a_data + aout.a_syms);
  432.         if (aout.a_entry < KERNBASE || aout.a_entry > KERNBASE + 0x00100000) {
  433.           printf("Error: Kernel entry point out of range\n");
  434.           return(0);
  435.         }
  436.     break;
  437.       default:
  438.         if (strstr(__cli, "verbose") != 0)
  439.           printf("Kernel binary is unrecognised, guessing it is AIF format\n");
  440.     aout.a_text = filesize;
  441.     aout.a_data = 0;
  442.     aout.a_bss = 0;
  443.         aout.a_syms = 0;
  444.         stringtablesize = 0;
  445.         break;
  446.     }
  447.  
  448.     kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss);
  449.  
  450. /* Add symbol table size if required. */
  451.  
  452.     if (strstr(__cli, "symtab") != 0) {
  453.       kernelsize += (unsigned int)aout.a_syms + stringtablesize;
  454.     } else {
  455.       aout.a_syms = 0;
  456.       stringtablesize = 0;
  457.     }
  458.  
  459.     if (strstr(__cli, "verbose") != 0)
  460.       {
  461.         printf("a_text = %08x\n", aout.a_text);
  462.         printf("a_data = %08x\n", aout.a_data);
  463.         printf("a_bss  = %08x\n", aout.a_bss);
  464.         printf("a_syms = %08x\n", aout.a_syms);
  465.         printf("snames = %08x\n", stringtablesize);
  466.       }
  467.  
  468. /* Give ourselves 16K of spare space and round off to a page */
  469.  
  470.     kernelsize = (kernelsize + 0x4000) & ~(bootconfig.pagesize-1);
  471.  
  472. /* Set the virtual address of the kernel in the bootconfig structure */
  473.  
  474.     bootconfig.kernvirtualbase = KERNBASE;
  475.     bootconfig.kernsize = kernelsize;
  476.     bootconfig.argvirtualbase = bootconfig.kernvirtualbase
  477.                               + bootconfig.kernsize;
  478.     bootconfig.argsize = bootconfig.pagesize;
  479.     bootconfig.scratchvirtualbase = bootconfig.argvirtualbase
  480.                                   + bootconfig.argsize;
  481.     bootconfig.scratchsize = SCRATCHSIZE;
  482.  
  483.     kernelsize += bootconfig.argsize;
  484.  
  485.     kernelsize += bootconfig.scratchsize;
  486.  
  487. /* Verbose info to the user. This is mainly debugging */
  488.  
  489.     if (strstr(__cli, "verbose") != 0)
  490.       {
  491.         printf("filesize = %08x\n", filesize);
  492.         printf("bootconfig.kernvirtualbase = %08x\n",
  493.           bootconfig.kernvirtualbase);
  494.         printf("bootconfig.kernsize = %08x\n", bootconfig.kernsize);
  495.         printf("bootconfig.argvirtualbase = %08x\n",
  496.           bootconfig.argvirtualbase);
  497.         printf("bootconfig.argsize = %08x\n", bootconfig.argsize);
  498.         printf("bootconfig.scratchvirtualbase = %08x\n",
  499.           bootconfig.scratchvirtualbase);
  500.         printf("bootconfig.scratchsize = %08x\n", bootconfig.scratchsize);
  501.         printf("kernelsize = %08x\n", kernelsize);
  502.     printf("display_start = %08x\n", bootconfig.display_start);
  503.     printf("display_size = %08x\n", bootconfig.display_size);
  504.     printf("physical dstart = %08x\n", bootconfig.vdram_phys);
  505.       }
  506.  
  507. /* This is redundant at the moment */
  508.  
  509.     swix(OS_DynamicArea, IN(R0|R1), 1, KERNAREA);
  510.  
  511.     fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8), 0,
  512.       KERNAREA, 0, KERNBASE, 0x80, 0x1000, 0, 0, "Kate Kernel"));
  513.  
  514. /* Shutdown RiscOS cleanly ... */
  515.  
  516. /* Close all open files and shutdown filing systems */
  517.  
  518.     if (strstr(__cli, "noboot") == 0)
  519.       {
  520.         swix(OS_FSControl, IN(R0), 23);
  521.  
  522. /* Issue a pre-reset service call to reset the podules */
  523.  
  524.         swix(OS_ServiceCall, IN(R1), 0x45);
  525.  
  526. /* Kill the etherH module to avoid locks up on reboot */
  527.  
  528. /*        swix(OS_Module, IN(R0|R1), 4, "EtherH");*/
  529.       }
  530.  
  531. /* More user information describing the memory found */
  532.  
  533.     if (strstr(__cli, "verbose") != 0)
  534.       {
  535.         printf("DRAM bank 0a = %08x %08x\n", bootconfig.dram[0].address,
  536.           bootconfig.dram[0].pages * bootconfig.pagesize);
  537.         printf("DRAM bank 0b = %08x %08x\n", bootconfig.dram[1].address,
  538.           bootconfig.dram[1].pages * bootconfig.pagesize);
  539.         printf("DRAM bank 1a = %08x %08x\n", bootconfig.dram[2].address,
  540.           bootconfig.dram[2].pages * bootconfig.pagesize);
  541.         printf("DRAM bank 1b = %08x %08x\n", bootconfig.dram[3].address,
  542.           bootconfig.dram[3].pages * bootconfig.pagesize);
  543.         printf("VRAM bank 0  = %08x %08x\n", bootconfig.vram[0].address,
  544.           bootconfig.vram[0].pages * bootconfig.pagesize);
  545.     }
  546.  
  547. /* Jump to SVC26 mode - remember we have no local vars now ! */
  548.  
  549.     EnterOS();
  550.  
  551. /* Find the number of the upper most bank of DRAM available */
  552.  
  553.     loop = 3;
  554.     while (bootconfig.dram[loop].address == 0)
  555.       --loop;
  556.  
  557. /* Allocate the physical addresses for the kernel in this bank */
  558.  
  559.     physical = bootconfig.dram[loop].address - kernelsize
  560.              + bootconfig.dram[loop].pages * bootconfig.pagesize;
  561.     bootconfig.kernphysicalbase = physical;
  562.     bootconfig.argphysicalbase = bootconfig.kernphysicalbase
  563.                                + bootconfig.kernsize;
  564.     bootconfig.scratchphysicalbase = bootconfig.argphysicalbase
  565.                                    + bootconfig.argsize;
  566.  
  567. /* Yet more debugging info */
  568.  
  569.     if (strstr(__cli, "verbose") != 0)
  570.       {
  571.         printf("buffer = %08x\n", buffer);
  572.         printf("physical = %08x\n", physical);
  573.         printf("bootconfig.kernphysicalbase = %08x\n",
  574.           bootconfig.kernphysicalbase);
  575.         printf("bootconfig.argphysicalbase = %08x\n",
  576.           bootconfig.argphysicalbase);
  577.         printf("bootconfig.scratchphysicalbase = %08x\n",
  578.           bootconfig.scratchphysicalbase);
  579.       }
  580.  
  581. /*
  582.  * Ok just check to see if anything is mapped where we are about to map
  583.  * the kernel.
  584.  */
  585.  
  586. /*
  587.     for (logical = KERNBASE; logical < KERNBASE + kernelsize;
  588.      logical += bootconfig.pagesize)
  589.       {
  590.         if (ReadWord(0x02c00000 + (logical >> 10) & 0xfffffffc) != 0)
  591.           {
  592.             printf("Error: Memory required for RiscBSD boot not available\n\r");
  593.             return(0);
  594.           }
  595.       }
  596. */
  597. /* Get out clause */
  598.  
  599.     if (strstr(__cli, "noboot") != 0)
  600.       {
  601.         ExitOS();
  602. #ifdef USE_MODULEAREA
  603.  
  604. /* Free memory in module area to hold the data we were loading */
  605.  
  606.         fatal(swix(OS_Module, IN(R0|R2), 7, buffer));
  607.  
  608. #endif
  609.         return(0);
  610.       }
  611.  
  612. /*
  613.  * Hook the physical pages to the required virtual address directly by
  614.  * writing into RiscOS's page tables. This should be done via a
  615.  * dynamic area handler but I cannot get it to work as documented.
  616.  */
  617.  
  618.     for (logical = KERNBASE; logical < KERNBASE + kernelsize;
  619.      logical += bootconfig.pagesize)
  620.       {
  621.         WriteWord(0x02c00000 + (logical >> 10) & 0xfffffffc,
  622.           0x00000ffe | (physical & 0xfffff000));
  623.         physical += bootconfig.pagesize;
  624.       }
  625.  
  626. /* Map the IO up high so we can get at it */
  627.  
  628.     WriteWord(0x02c0c000 + (0xf6000000 >> 18) & 0xfffffffc,
  629.       0x00000412 | (0x03200000 & 0xfffff000));
  630.     WriteWord(0x02c0c000 + (0xf6100000 >> 18) & 0xfffffffc,
  631.       0x00000412 | (0x03400000 & 0xfffff000));
  632.  
  633.     memset((char *)bootconfig.display_start, 0xcc, 0x4000);
  634.  
  635. /* Disable IRQ and FIQ interrupts */
  636.  
  637.     SetCPSR(I32_bit | F32_bit, I32_bit | F32_bit);
  638.  
  639.     memset((char *)bootconfig.display_start + 0x4000, 0x55, 0x4000);
  640.  
  641.     memcpy((char *)bootconfig.argvirtualbase, __cli, bootconfig.argsize);
  642.  
  643.     memset((char *)bootconfig.display_start + 0x8000, 0x80, 0x4000);
  644.  
  645.     memset((char *)bootconfig.argvirtualbase, SCRATCHSIZE, 0);
  646.  
  647.     memset((char *)bootconfig.display_start + 0xC000, 0xbb, 0x4000);
  648.  
  649. /* Locate the start of the text area */
  650.  
  651.     switch (aout.a_magic & MAGICMASK) {
  652.       case OMAGIC:
  653.       case NMAGIC:
  654.         buffer += sizeof(aout_t);
  655.     break;
  656.       case ZMAGIC:
  657.       default:
  658.         break;
  659.     }
  660.  
  661.     switch (aout.a_magic & MAGICMASK) {
  662.       case OMAGIC:
  663.       case NMAGIC:
  664.       case ZMAGIC:
  665.         if (aout.a_syms == 0)
  666.           ((aout_t *)buffer)->a_syms = 0;
  667.         break;
  668.       default:
  669.         break;
  670.     }
  671.  
  672.     memcpy((char *)bootconfig.kernvirtualbase, buffer, (int)aout.a_text);
  673.  
  674.     memset((char *)(bootconfig.display_start + 0x10000), 0xee, 0x4000);
  675.  
  676.     memcpy((char *)(bootconfig.kernvirtualbase + aout.a_text),
  677.       (buffer + aout.a_text), (int)aout.a_data);
  678.  
  679.     memset((char *)(bootconfig.display_start + 0x14000), 0x66, 0x4000);
  680.  
  681.     if (aout.a_syms != 0) {
  682.       ptr = bootconfig.kernvirtualbase + (u_int)(aout.a_text
  683.         + aout.a_data + aout.a_bss);
  684.       *((int *)ptr) = (int)aout.a_syms;
  685.       ptr += sizeof(int);     
  686.       memcpy((char *)ptr, (buffer + aout.a_text
  687.         + aout.a_data), (int)aout.a_syms);
  688.       ptr += (int)aout.a_syms;
  689.       memcpy((char *)ptr, (buffer + aout.a_text
  690.         + aout.a_data + aout.a_syms), stringtablesize);
  691.       
  692.     }
  693.  
  694.     memset((char *)bootconfig.display_start + 0x18000, 0xaa, 0x4000);
  695.  
  696. /* Real late debugging get out clause */
  697.  
  698.     if (strstr(__cli, "nearboot") != 0)
  699.       {
  700.         SetCPSR(I32_bit | F32_bit, 0);
  701.         ExitOS();
  702.         return(0);
  703.       }
  704.  
  705. /* Punch into SVC32 mode */
  706.  
  707.     memset((char *)bootconfig.display_start + 0x1C000, 0xff, 0x4000);
  708.  
  709.     SVC32();
  710.  
  711. /* Point of no return */
  712.  
  713.     switch (aout.a_magic & MAGICMASK) {
  714.       case OMAGIC:
  715.       case NMAGIC:
  716.       case ZMAGIC:
  717.         _bsdboot(&bootconfig, (unsigned int)aout.a_entry);
  718.         break;
  719.       default:
  720.         _bsdboot(&bootconfig, KERNBASE);
  721.         break;
  722.     }
  723.  
  724.     return(0);
  725.   }
  726.  
  727.  
  728. /* Report an error */
  729.  
  730. void fatal(struct Error *error)
  731.   {
  732.     if (error)
  733.         swi(OS_GenerateError, IN(R0), error);
  734.   }
  735.  
  736.  
  737. /* Locate all the blocks of memory in the system */
  738.  
  739. unsigned char *locate_memory_blocks(void)
  740.   {
  741.     int loop;
  742.     int page;
  743.     int currentpage;
  744.     int currentpages;
  745.     int currentaddr;
  746.     unsigned char *table;
  747.     unsigned int pagesize;
  748.     unsigned int tablesize;
  749.     int dramblocks = 0;
  750.     int vramblocks = 0;
  751.  
  752. /* Get table size and page size */
  753.  
  754.     fatal(swix(OS_Memory, IN(R0)|OUT(R1|R2), 6, &tablesize, &pagesize));
  755.  
  756. /* Allocate memory for table */
  757.  
  758. /*# ifdef USE_MODULEAREA*/
  759.  
  760.     fatal(swix(OS_Module, IN(R0|R3)|OUT(R2), 6, tablesize, &table));
  761.  
  762. /*# else*/
  763.  
  764. /* Allocate memory to hold the data we are loading */
  765.  
  766. /*    swix(OS_DynamicArea, IN(R0|R1), 1, TABLEAREA);
  767.  
  768.     fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8)|OUT(R3), 0,
  769.       TABLEAREA, tablesize, -1, 0x80, tablesize, 0, 0, "Kate Table", &table));
  770.  
  771. # endif*/
  772.  
  773.  
  774. /* read the table */
  775.  
  776.     fatal(swix(OS_Memory, IN(R0|R1), 7, table));
  777.  
  778. /* Loop round locating all the valid blocks of memory */
  779.  
  780.     currentpage = -1;
  781.  
  782.     for (loop = 0; loop < tablesize * 2; ++loop)
  783.       {
  784.         page = table[loop / 2];
  785.         if (loop % 2)
  786.           page = page >> 4;
  787.  
  788.         page = page & 0x07;
  789.  
  790.         if (page != currentpage)
  791.           {
  792.             switch (currentpage)
  793.               {
  794.                 case 1:
  795.                   bootconfig.dram[dramblocks].address = currentaddr * pagesize;
  796.                   bootconfig.dram[dramblocks].pages = currentpages;
  797.                   ++dramblocks;
  798.                   break;
  799.  
  800.                 case 2:
  801.                   bootconfig.vram[vramblocks].address = currentaddr * pagesize;
  802.                   bootconfig.vram[vramblocks].pages = currentpages;
  803.                   ++vramblocks;
  804.                   break;
  805.  
  806.                 default :
  807.                   break;
  808.               }
  809.  
  810.             currentpage = page;
  811.             currentaddr = loop;
  812.             currentpages = 0;
  813.           }
  814.         ++currentpages;
  815.       }
  816.  
  817. /* Get the number of dram and vram pages */
  818.  
  819.     fatal(swix(OS_Memory, IN(R0)|OUT(R1), 0x00000108, &bootconfig.drampages));
  820.     fatal(swix(OS_Memory, IN(R0)|OUT(R1), 0x00000208, &bootconfig.vrampages));
  821.  
  822. /* Fill in more bootconfig parameters */
  823.  
  824.     bootconfig.pagesize = pagesize;
  825.  
  826.     bootconfig.dramblocks = dramblocks;
  827.     bootconfig.vramblocks = vramblocks;
  828.  
  829.     return(table);
  830.   }
  831.  
  832.  
  833. void putchar(int c)
  834.   {
  835.     if (c == '\n')
  836.       swi(OS_WriteC, IN(R0), '\r');
  837.     
  838.     swi(OS_WriteC, IN(R0), c);
  839.   }
  840.  
  841. /* End of bsdbooter.c */
  842.