778 lines
21 KiB
C
778 lines
21 KiB
C
/* $NetBSD: bsdbooter.c,v 1.1 1996/01/31 23:18:08 mark Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 1994,1995 Mark Brinicombe.
|
|
* Copyright (c) 1994,1995 Brini.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software written for Brini by Mark Brinicombe
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by Mark Brinicombe.
|
|
* 4. The name of the company nor the name of the author may be used to
|
|
* endorse or promote products derived from this software without specific
|
|
* prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* RiscBSD kernel project
|
|
*
|
|
* bsdbooter.c
|
|
*
|
|
* RiscBSD boot loader
|
|
*
|
|
* Created : 12/09/94
|
|
* Last updated : 08/03/95
|
|
*
|
|
* Based on kate/boot/boot.c
|
|
*
|
|
* $Id: bsdbooter.c,v 1.1 1996/01/31 23:18:08 mark Exp $
|
|
*/
|
|
|
|
/* Include standard header files */
|
|
|
|
# include <stdlib.h>
|
|
# include <string.h>
|
|
# include <stdarg.h>
|
|
|
|
/* Include local headers */
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/exec.h>
|
|
#include <machine/cpu.h>
|
|
#include <machine/katelib.h>
|
|
#include <machine/bootconfig.h>
|
|
#include "swiv.h"
|
|
#include "swis.h"
|
|
|
|
/*
|
|
* Declare global variables
|
|
*/
|
|
|
|
# define VERSION "2.10"
|
|
|
|
# define USE_MODULEAREA
|
|
|
|
# define KERNAREA 512
|
|
# define KERNBASE 0xf0000000
|
|
|
|
# define TABLEAREA 513
|
|
# define LOADAREA 514
|
|
|
|
# define SCRATCHSIZE 0xc000
|
|
|
|
|
|
# define OS_DynamicArea 0x66
|
|
# define OS_Memory 0x68
|
|
# define OS_MMUControl 0x6b
|
|
|
|
# define FASTBOOT_FILENAME "<BtRiscBSD$Dir>.booter.fastboot"
|
|
|
|
/*
|
|
* Declare external variables
|
|
*/
|
|
|
|
extern char *__cli;
|
|
|
|
/*
|
|
* Local vars. Some of these have to be global because they are used after
|
|
* the processor has been switches to SVC mode local variables would be
|
|
* lost as they would be on the USR mode stack.
|
|
*/
|
|
|
|
typedef struct exec aout_t;
|
|
|
|
BootConfig bootconfig;
|
|
int in[3], out[3];
|
|
char kernelname[1024];
|
|
unsigned char *buffer;
|
|
static aout_t aout;
|
|
unsigned int kernelsize;
|
|
unsigned int logical;
|
|
unsigned int physical;
|
|
unsigned int filesize;
|
|
unsigned int copysize;
|
|
|
|
/*
|
|
* Local function prototypes
|
|
*/
|
|
|
|
void fatal(struct Error *error);
|
|
unsigned char *locate_memory_blocks(void);
|
|
void uprintf(char *formattoken, ...);
|
|
void _bsdboot(BootConfig *bootconfig, unsigned int address);
|
|
int vsprintf(char *buf, const char *fmt, va_list args);
|
|
|
|
/* Now for the main code */
|
|
|
|
extern int main (int, char **);
|
|
|
|
void __exit(int);
|
|
|
|
void _main(void)
|
|
{
|
|
uprintf("_main entered\n");
|
|
__exit (main (0, (char **)0)); /* ... ignition */
|
|
|
|
/* not reached */
|
|
}
|
|
|
|
/* The main booter code */
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char *cliptr;
|
|
int loop;
|
|
int filehandle;
|
|
unsigned char *arrangementtable;
|
|
|
|
uprintf("main entered\n");
|
|
|
|
/* Analyse the command line */
|
|
|
|
cliptr = __cli;
|
|
|
|
uprintf("command line is %s\n", cliptr);
|
|
|
|
/* Skip the command name */
|
|
|
|
while (*cliptr != ' ' && *cliptr != 0)
|
|
++cliptr;
|
|
|
|
/* Skip any spaces */
|
|
|
|
while (*cliptr == ' ')
|
|
++cliptr;
|
|
|
|
/* Check for another parameter */
|
|
|
|
if (*cliptr != 0)
|
|
{
|
|
for (loop = 0; *cliptr != ' ' && *cliptr != 0; ++loop,++cliptr)
|
|
{
|
|
kernelname[loop] = *cliptr;
|
|
}
|
|
kernelname[loop] = 0;
|
|
}
|
|
else
|
|
strcpy(kernelname, "riscbsd");
|
|
|
|
strcpy(bootconfig.kernelname, kernelname);
|
|
|
|
/* Write the command line used to a fastboot file. Execing or Obeying
|
|
* this file will boot RiscBSD. This can be used during the RiscOS bootup
|
|
* to enable a fast boot.
|
|
*/
|
|
|
|
/*
|
|
* Open the autoboot file. Just skip if file cannot be opened.
|
|
*/
|
|
|
|
swi(OS_Find, IN(R0|R1)|OUT(R0), 0x80, FASTBOOT_FILENAME, &filehandle);
|
|
if (filehandle != 0)
|
|
{
|
|
swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 2, filehandle, __cli,
|
|
strlen(__cli), 0);
|
|
swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 2, filehandle, "\n", 1, 0);
|
|
|
|
/* Close the file */
|
|
|
|
swi(OS_Find, IN(R0|R1), 0, filehandle);
|
|
|
|
swi(OS_File, IN(R0|R1|R2), 18, FASTBOOT_FILENAME, 0xfeb);
|
|
}
|
|
else
|
|
{
|
|
uprintf("Warning: Cannot write fastboot file %s\n\r", FASTBOOT_FILENAME);
|
|
}
|
|
|
|
/* Set the screen mode ... */
|
|
|
|
/* I know this is messy. It is currently just a hack to try things out
|
|
* Why didn't Acorn add a SWI call to interpret the mode string and return
|
|
* a mode specifer ?
|
|
*/
|
|
|
|
/* Also this is temporary as eventually the console driver will set the VIDC
|
|
* up as required.
|
|
* It sort of expects the screenmode= options to be at the end of the string.
|
|
*/
|
|
|
|
{
|
|
char *modeptr;
|
|
int modespec[6];
|
|
|
|
modeptr = strstr(__cli, "screenmode=");
|
|
if (modeptr)
|
|
{
|
|
modeptr += 11;
|
|
modespec[0] = 0x00000001;
|
|
modespec[1] = 0x00000000;
|
|
modespec[2] = 0x00000000;
|
|
modespec[3] = 0x00000003;
|
|
modespec[4] = 0x00000000;
|
|
modespec[5] = -1;
|
|
|
|
while (*modeptr)
|
|
{
|
|
switch (*modeptr)
|
|
{
|
|
case 'X':
|
|
case 'x':
|
|
++modeptr;
|
|
while (*modeptr >= '0' && *modeptr <= '9')
|
|
{
|
|
modespec[1] = (modespec[1] * 10) + (*modeptr - '0');
|
|
++modeptr;
|
|
}
|
|
break;
|
|
|
|
case 'Y':
|
|
case 'y':
|
|
++modeptr;
|
|
while (*modeptr >= '0' && *modeptr <= '9')
|
|
{
|
|
modespec[2] = (modespec[2] * 10) + (*modeptr - '0');
|
|
++modeptr;
|
|
}
|
|
break;
|
|
/*
|
|
case 'C':
|
|
case 'c':
|
|
case 'G':
|
|
case 'g':
|
|
++modeptr;
|
|
while (*modeptr >= '0' && *modeptr <= '9')
|
|
{
|
|
modespec[3] = (modespec[3] * 10) + (*modeptr - '0');
|
|
++modeptr;
|
|
}
|
|
break;
|
|
*/
|
|
case 'F':
|
|
case 'f':
|
|
++modeptr;
|
|
while (*modeptr >= '0' && *modeptr <= '9')
|
|
{
|
|
modespec[4] = (modespec[4] * 10) + (*modeptr - '0');
|
|
++modeptr;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
++modeptr;
|
|
break;
|
|
}
|
|
}
|
|
if (modespec[4] == 0) modespec[4] = -1;
|
|
/* uprintf("x=%d y=%d c=%d f=%d\n", modespec[1], modespec[2],
|
|
modespec[3], modespec[4]);*/
|
|
fatal(swix(Wimp_SetMode, IN(R0), &modespec));
|
|
bootconfig.framerate = modespec[4];
|
|
}
|
|
else
|
|
bootconfig.framerate = 0;
|
|
}
|
|
|
|
/* Announcement time .. */
|
|
/* Used to be above but now moved to after the mode change */
|
|
|
|
|
|
if (strstr(__cli, "verbose") != 0)
|
|
uprintf("RiscBSD BootLoader " VERSION " " __DATE__ "\n\r");
|
|
|
|
/* A bit of info */
|
|
|
|
if (strstr(__cli, "verbose") != 0)
|
|
uprintf("Kernel: %s\n\r", kernelname);
|
|
|
|
/* Get the machine id */
|
|
|
|
fatal(swix(OS_ReadSysInfo, IN(R0)|OUT(R3), 2, &bootconfig.machine_id));
|
|
|
|
/* Get the display variables. Failure on any of these will abort the boot */
|
|
|
|
in[0] = 149;
|
|
in[1] = 150;
|
|
in[2] = -1;
|
|
|
|
fatal(swix(OS_ReadVduVariables, IN(R0|R1), &in, &out));
|
|
|
|
bootconfig.display_start = out[0];
|
|
bootconfig.display_size = out[1];
|
|
|
|
fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 9,
|
|
&bootconfig.bitsperpixel));
|
|
fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 11,
|
|
&bootconfig.width));
|
|
fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 12,
|
|
&bootconfig.height));
|
|
|
|
/* Will the kernel support this mode ? */
|
|
|
|
if (bootconfig.bitsperpixel > 3)
|
|
{
|
|
swi(OS_Write0, IN(R0),
|
|
"Error: Only 1, 2, 4 or 8 bpp modes are currently supported\n\r");
|
|
return(0);
|
|
}
|
|
|
|
/* Get the arrangement table for the memory */
|
|
|
|
arrangementtable = locate_memory_blocks();
|
|
|
|
/*
|
|
* Ok we will support a.out files as well. This means that we need to
|
|
* identify the format.
|
|
*/
|
|
|
|
/* Get the size of the file */
|
|
|
|
fatal(swix(OS_File, IN(R0|R1)|OUT(R4), 5, kernelname, &filesize));
|
|
|
|
/*
|
|
* Read the start of the file so that we change check for the a.out
|
|
* magic number.
|
|
*/
|
|
|
|
swi(OS_Find, IN(R0|R1)|OUT(R0), 0x40, kernelname, &filehandle);
|
|
if (filehandle == 0)
|
|
{
|
|
uprintf("Error: Cannot read kernel file %s\n\r", kernelname);
|
|
return(0);
|
|
}
|
|
|
|
aout.a_midmag = 0;
|
|
|
|
fatal(swix(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, &aout,
|
|
sizeof(aout_t), 0));
|
|
|
|
/* Do we have an a.out file ? */
|
|
|
|
switch(N_GETMAGIC(aout)) {
|
|
case NMAGIC:
|
|
if (strstr(__cli, "verbose") != 0)
|
|
swi(OS_Write0, IN(R0), "Kernel binary is NMAGIC a.out format\n\r");
|
|
kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss);
|
|
copysize = (unsigned int)(aout.a_text + aout.a_data);
|
|
break;
|
|
case OMAGIC:
|
|
if (strstr(__cli, "verbose") != 0)
|
|
swi(OS_Write0, IN(R0), "Kernel binary is OMAGIC a.out format\n\r");
|
|
kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss);
|
|
copysize = (unsigned int)(aout.a_text + aout.a_data);
|
|
break;
|
|
case ZMAGIC:
|
|
if (strstr(__cli, "verbose") != 0)
|
|
swi(OS_Write0, IN(R0), "Kernel binary is ZMAGIC a.out format\n\r");
|
|
kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss);
|
|
copysize = (unsigned int)(aout.a_text + aout.a_data);
|
|
break;
|
|
default:
|
|
if (strstr(__cli, "verbose") != 0)
|
|
swi(OS_Write0, IN(R0), "Kernel binary is AIF format\n\r");
|
|
kernelsize = filesize;
|
|
copysize = filesize;
|
|
break;
|
|
}
|
|
|
|
/* Give ourselves 16K of spare space and round off to a page */
|
|
|
|
/*
|
|
* This is messy. We should read the memory info first, but I have not
|
|
* changed things yet. This is part of the hack to support a.out files
|
|
* as well
|
|
*/
|
|
|
|
kernelsize = (kernelsize + 0x4000) & ~(bootconfig.pagesize-1);
|
|
|
|
/* Set the virtual address of the kernel in the bootconfig structure */
|
|
|
|
bootconfig.kernvirtualbase = KERNBASE;
|
|
bootconfig.kernsize = kernelsize;
|
|
bootconfig.argvirtualbase = bootconfig.kernvirtualbase
|
|
+ bootconfig.kernsize;
|
|
bootconfig.argsize = bootconfig.pagesize;
|
|
bootconfig.scratchvirtualbase = bootconfig.argvirtualbase
|
|
+ bootconfig.argsize;
|
|
bootconfig.scratchsize = SCRATCHSIZE;
|
|
|
|
kernelsize += bootconfig.argsize;
|
|
|
|
kernelsize += bootconfig.scratchsize;
|
|
|
|
/* Verbose info to the user. This is mainly debugging */
|
|
|
|
if (strstr(__cli, "verbose") != 0)
|
|
{
|
|
uprintf("filesize = %08x\n\r", filesize);
|
|
uprintf("bootconfig.kernvirtualbase = %08x\n\r",
|
|
bootconfig.kernvirtualbase);
|
|
uprintf("bootconfig.kernsize = %08x\n\r", bootconfig.kernsize);
|
|
uprintf("bootconfig.argvirtualbase = %08x\n\r",
|
|
bootconfig.argvirtualbase);
|
|
uprintf("bootconfig.argsize = %08x\n\r", bootconfig.argsize);
|
|
uprintf("bootconfig.scratchvirtualbase = %08x\n\r",
|
|
bootconfig.scratchvirtualbase);
|
|
uprintf("bootconfig.scratchsize = %08x\n\r", bootconfig.scratchsize);
|
|
uprintf("kernelsize = %08x\n\r", kernelsize);
|
|
uprintf("copysize = %08x\n\r", copysize);
|
|
}
|
|
|
|
# ifdef USE_MODULEAREA
|
|
|
|
/* Allocate memory in module area to hold the data we are loading */
|
|
|
|
fatal(swix(OS_Module, IN(R0|R3)|OUT(R2), 6, filesize, &buffer));
|
|
|
|
# else
|
|
|
|
/* Allocate memory to hold the data we are loading */
|
|
|
|
swix(OS_DynamicArea, IN(R0|R1), 1, LOADAREA);
|
|
|
|
fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8)|OUT(R3), 0,
|
|
LOADAREA, filesize, -1, 0x80, filesize, 0, 0, "Kate Data", &buffer));
|
|
|
|
# endif
|
|
|
|
/* Load the appropriate part depending on the file type */
|
|
|
|
switch (N_GETMAGIC(aout)) {
|
|
case OMAGIC:
|
|
case NMAGIC:
|
|
swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, buffer,
|
|
filesize, sizeof(aout_t));
|
|
break;
|
|
case ZMAGIC:
|
|
default:
|
|
swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, buffer,
|
|
filesize, 0);
|
|
break;
|
|
}
|
|
|
|
/* Close the file */
|
|
|
|
fatal(swix(OS_Find, IN(R0|R1), 0, filehandle));
|
|
|
|
|
|
/* This is redundant at the moment */
|
|
|
|
swix(OS_DynamicArea, IN(R0|R1), 1, KERNAREA);
|
|
|
|
fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8), 0,
|
|
KERNAREA, 0, KERNBASE, 0x80, 0x1000, 0, 0, "Kate Kernel"));
|
|
|
|
/* Shutdown RiscOS cleanly ... */
|
|
|
|
/* Close all open files and shutdown filing systems */
|
|
|
|
swix(OS_FSControl, IN(R0), 23);
|
|
|
|
/* Issue a pre-reset service call to reset the podules */
|
|
|
|
swix(OS_ServiceCall, IN(R1), 0x45);
|
|
|
|
/* Kill the etherH module to avoid locks up on reboot */
|
|
|
|
swix(OS_Module, IN(R0|R1), 4, "EtherH");
|
|
|
|
/* More user information describing the memory found */
|
|
|
|
if (strstr(__cli, "verbose") != 0)
|
|
{
|
|
uprintf("DRAM bank 0a = %08x %08x\n\r", bootconfig.dram[0].address,
|
|
bootconfig.dram[0].pages * bootconfig.pagesize);
|
|
uprintf("DRAM bank 0b = %08x %08x\n\r", bootconfig.dram[1].address,
|
|
bootconfig.dram[1].pages * bootconfig.pagesize);
|
|
uprintf("DRAM bank 1a = %08x %08x\n\r", bootconfig.dram[2].address,
|
|
bootconfig.dram[2].pages * bootconfig.pagesize);
|
|
uprintf("DRAM bank 1b = %08x %08x\n\r", bootconfig.dram[3].address,
|
|
bootconfig.dram[3].pages * bootconfig.pagesize);
|
|
uprintf("VRAM bank 0 = %08x %08x\n\r", bootconfig.vram[0].address,
|
|
bootconfig.vram[0].pages * bootconfig.pagesize);
|
|
}
|
|
|
|
/* Hack for 2 Meg VRAM until the new console code is in place */
|
|
|
|
/* if (strstr(__cli, "vramhack") != 0)
|
|
{
|
|
bootconfig.display_size /= 1;
|
|
bootconfig.vram[0].pages /= 2;
|
|
|
|
uprintf("VRAM bank 0 = %08x %08x\n\r", bootconfig.vram[0].address,
|
|
bootconfig.vram[0].pages * bootconfig.pagesize);
|
|
}*/
|
|
|
|
/* Jump to SVC26 mode - remember we have no local vars now ! */
|
|
|
|
EnterOS();
|
|
|
|
/* Find the number of the upper most bank of DRAM available */
|
|
|
|
loop = 3;
|
|
while (bootconfig.dram[loop].address == 0)
|
|
--loop;
|
|
|
|
/* Allocate the physical addresses for the kernel in this bank */
|
|
|
|
physical = bootconfig.dram[loop].address - kernelsize
|
|
+ bootconfig.dram[loop].pages * bootconfig.pagesize;
|
|
bootconfig.kernphysicalbase = physical;
|
|
bootconfig.argphysicalbase = bootconfig.kernphysicalbase
|
|
+ bootconfig.kernsize;
|
|
bootconfig.scratchphysicalbase = bootconfig.argphysicalbase
|
|
+ bootconfig.argsize;
|
|
|
|
/* Yet more debugging info */
|
|
|
|
if (strstr(__cli, "verbose") != 0)
|
|
{
|
|
uprintf("buffer = %08x\n\r", buffer);
|
|
uprintf("physical = %08x\n\r", physical);
|
|
uprintf("bootconfig.kernphysicalbase = %08x\n\r",
|
|
bootconfig.kernphysicalbase);
|
|
uprintf("bootconfig.argphysicalbase = %08x\n\r",
|
|
bootconfig.argphysicalbase);
|
|
uprintf("bootconfig.scratchphysicalbase = %08x\n\r",
|
|
bootconfig.scratchphysicalbase);
|
|
}
|
|
|
|
/*
|
|
* Ok just check to see if anything is mapped where we are about to map
|
|
* the kernel.
|
|
*/
|
|
|
|
/*
|
|
for (logical = KERNBASE; logical < KERNBASE + kernelsize;
|
|
logical += bootconfig.pagesize)
|
|
{
|
|
if (ReadWord(0x02c00000 + (logical >> 10) & 0xfffffffc) != 0)
|
|
{
|
|
uprintf("Error: Memory required for RiscBSD boot not available\n\r");
|
|
return(0);
|
|
}
|
|
}
|
|
*/
|
|
/* Get out clause */
|
|
|
|
if (strstr(__cli, "noboot") != 0)
|
|
{
|
|
ExitOS();
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Hook the physical pages to the required virtual address directly by
|
|
* writing into RiscOS's page tables. This should be done via a
|
|
* dynamic area handler but I cannot get it to work as documented.
|
|
*/
|
|
|
|
for (logical = KERNBASE; logical < KERNBASE + kernelsize;
|
|
logical += bootconfig.pagesize)
|
|
{
|
|
WriteWord(0x02c00000 + (logical >> 10) & 0xfffffffc,
|
|
0x00000ffe | (physical & 0xfffff000));
|
|
physical += bootconfig.pagesize;
|
|
}
|
|
|
|
/* Map the IO up high so we can get at it */
|
|
|
|
WriteWord(0x02c0c000 + (0xf6000000 >> 18) & 0xfffffffc,
|
|
0x00000412 | (0x03200000 & 0xfffff000));
|
|
WriteWord(0x02c0c000 + (0xf6100000 >> 18) & 0xfffffffc,
|
|
0x00000412 | (0x03400000 & 0xfffff000));
|
|
|
|
memset((char *)bootconfig.display_start, 0xcc, 0x4000);
|
|
|
|
/* Disable IRQ and FIQ interrupts */
|
|
|
|
SetCPSR(I32_bit | F32_bit, I32_bit | F32_bit);
|
|
|
|
memset((char *)bootconfig.display_start + 0x4000, 0x55, 0x4000);
|
|
|
|
memcpy((char *)bootconfig.argvirtualbase, __cli, bootconfig.argsize);
|
|
|
|
memset((char *)bootconfig.display_start + 0x8000, 0x80, 0x4000);
|
|
|
|
memset((char *)bootconfig.argvirtualbase, SCRATCHSIZE, 0);
|
|
|
|
memset((char *)bootconfig.display_start + 0xC000, 0xbb, 0x4000);
|
|
|
|
memcpy((char *)bootconfig.kernvirtualbase, buffer, copysize);
|
|
|
|
memset((char *)bootconfig.display_start + 0x10000, 0xaa, 0x4000);
|
|
|
|
/* Real late debugging get out clause */
|
|
|
|
if (strstr(__cli, "nearboot") != 0)
|
|
{
|
|
SetCPSR(I32_bit | F32_bit, 0);
|
|
ExitOS();
|
|
return(0);
|
|
}
|
|
|
|
/* Punch into SVC32 mode */
|
|
|
|
SVC32();
|
|
|
|
/* Point of no return */
|
|
|
|
switch (N_GETMAGIC(aout)) {
|
|
case OMAGIC:
|
|
case NMAGIC:
|
|
case ZMAGIC:
|
|
_bsdboot(&bootconfig, (unsigned int)aout.a_entry);
|
|
break;
|
|
default:
|
|
_bsdboot(&bootconfig, KERNBASE);
|
|
break;
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Report an error */
|
|
|
|
void fatal(struct Error *error)
|
|
{
|
|
if (error)
|
|
{
|
|
swi(OS_GenerateError, IN(R0), error);
|
|
}
|
|
}
|
|
|
|
|
|
/* Locate all the blocks of memory in the system */
|
|
|
|
unsigned char *locate_memory_blocks(void)
|
|
{
|
|
int loop;
|
|
int page;
|
|
int currentpage;
|
|
int currentpages;
|
|
int currentaddr;
|
|
unsigned char *table;
|
|
unsigned int pagesize;
|
|
unsigned int tablesize;
|
|
int dramblocks = 0;
|
|
int vramblocks = 0;
|
|
|
|
/* Get table size and page size */
|
|
|
|
fatal(swix(OS_Memory, IN(R0)|OUT(R1|R2), 6, &tablesize, &pagesize));
|
|
|
|
/* Allocate memory for table */
|
|
|
|
/*# ifdef USE_MODULEAREA*/
|
|
|
|
fatal(swix(OS_Module, IN(R0|R3)|OUT(R2), 6, tablesize, &table));
|
|
|
|
/*# else*/
|
|
|
|
/* Allocate memory to hold the data we are loading */
|
|
|
|
/* swix(OS_DynamicArea, IN(R0|R1), 1, TABLEAREA);
|
|
|
|
fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8)|OUT(R3), 0,
|
|
TABLEAREA, tablesize, -1, 0x80, tablesize, 0, 0, "Kate Table", &table));
|
|
|
|
# endif*/
|
|
|
|
|
|
/* read the table */
|
|
|
|
fatal(swix(OS_Memory, IN(R0|R1), 7, table));
|
|
|
|
/* Loop round locating all the valid blocks of memory */
|
|
|
|
currentpage = -1;
|
|
|
|
for (loop = 0; loop < tablesize * 2; ++loop)
|
|
{
|
|
page = table[loop / 2];
|
|
if (loop % 2)
|
|
page = page >> 4;
|
|
|
|
page = page & 0x07;
|
|
|
|
if (page != currentpage)
|
|
{
|
|
switch (currentpage)
|
|
{
|
|
case 1:
|
|
bootconfig.dram[dramblocks].address = currentaddr * pagesize;
|
|
bootconfig.dram[dramblocks].pages = currentpages;
|
|
++dramblocks;
|
|
break;
|
|
|
|
case 2:
|
|
bootconfig.vram[vramblocks].address = currentaddr * pagesize;
|
|
bootconfig.vram[vramblocks].pages = currentpages;
|
|
++vramblocks;
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
|
|
currentpage = page;
|
|
currentaddr = loop;
|
|
currentpages = 0;
|
|
}
|
|
++currentpages;
|
|
}
|
|
|
|
/* Get the number of dram and vram pages */
|
|
|
|
fatal(swix(OS_Memory, IN(R0)|OUT(R1), 0x00000108, &bootconfig.drampages));
|
|
fatal(swix(OS_Memory, IN(R0)|OUT(R1), 0x00000208, &bootconfig.vrampages));
|
|
|
|
/* Fill in more bootconfig parameters */
|
|
|
|
bootconfig.pagesize = pagesize;
|
|
|
|
bootconfig.dramblocks = dramblocks;
|
|
bootconfig.vramblocks = vramblocks;
|
|
|
|
return(table);
|
|
}
|
|
|
|
|
|
/* printf ... */
|
|
|
|
void uprintf(char *formattoken, ...)
|
|
{
|
|
va_list ap;
|
|
char temp[1024];
|
|
|
|
temp[0] = '\0';
|
|
|
|
va_start(ap, formattoken);
|
|
vsprintf(temp, formattoken, ap);
|
|
va_end(ap);
|
|
|
|
swi(OS_Write0, IN(R0), temp);
|
|
}
|
|
|
|
/* End of bsdbooter.c */
|