Home | History | Annotate | Line # | Download | only in loadbsd
loadbsd.c revision 1.5
      1  1.1  mw #include <sys/types.h>
      2  1.1  mw #include <a.out.h>
      3  1.1  mw #include <stdio.h>
      4  1.1  mw 
      5  1.1  mw #include <exec/types.h>
      6  1.1  mw #include <exec/execbase.h>
      7  1.1  mw #include <exec/memory.h>
      8  1.1  mw #include <libraries/configregs.h>
      9  1.1  mw #include <libraries/expansionbase.h>
     10  1.5  mw #include <graphics/gfxbase.h>
     11  1.1  mw 
     12  1.1  mw #include <inline/exec.h>
     13  1.1  mw #include <inline/expansion.h>
     14  1.5  mw #include <inline/graphics.h>
     15  1.1  mw 
     16  1.3  mw /* Get definitions for boothowto */
     17  1.3  mw #include "reboot.h"
     18  1.3  mw 
     19  1.1  mw struct ExpansionBase *ExpansionBase;
     20  1.5  mw struct GfxBase *GfxBase;
     21  1.1  mw 
     22  1.1  mw #undef __LDPGSZ
     23  1.1  mw #define __LDPGSZ 8192
     24  1.1  mw 
     25  1.5  mw #define MAX_MEM_SEG	16
     26  1.5  mw 
     27  1.5  mw struct MEM_LIST {
     28  1.5  mw 	u_long	num_mem;
     29  1.5  mw 	struct MEM_SEG {
     30  1.5  mw 		u_long	mem_start;
     31  1.5  mw 		u_long	mem_size;
     32  1.5  mw 		u_short	mem_attrib;
     33  1.5  mw 		short	mem_prio;
     34  1.5  mw 	} mem_seg[MAX_MEM_SEG];
     35  1.5  mw } mem_list, *kmem_list;
     36  1.5  mw 
     37  1.5  mw int k_opt;
     38  1.5  mw int a_opt;
     39  1.5  mw int b_opt;
     40  1.5  mw int p_opt;
     41  1.5  mw int t_opt;
     42  1.5  mw 
     43  1.5  mw extern char *optarg;
     44  1.5  mw extern int optind;
     45  1.5  mw 
     46  1.1  mw void get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size);
     47  1.1  mw 
     48  1.1  mw int
     49  1.1  mw main (int argc, char *argv[])
     50  1.1  mw {
     51  1.1  mw   struct exec e;
     52  1.1  mw   int fd;
     53  1.3  mw   int boothowto = RB_SINGLE;
     54  1.1  mw 
     55  1.1  mw   if (argc >= 2)
     56  1.1  mw     {
     57  1.1  mw       if ((fd = open (argv[1], 0)) >= 0)
     58  1.1  mw         {
     59  1.1  mw           if (read (fd, &e, sizeof (e)) == sizeof (e))
     60  1.1  mw             {
     61  1.1  mw               if (e.a_magic == NMAGIC)
     62  1.1  mw                 {
     63  1.1  mw                   u_char *kernel;
     64  1.1  mw 		  int text_size;
     65  1.1  mw 		  struct ConfigDev *cd;
     66  1.1  mw 		  int num_cd;
     67  1.5  mw 		  void *fastmem_start;
     68  1.5  mw 		  u_long fastmem_size, chipmem_size;
     69  1.5  mw 		  int i;
     70  1.1  mw 
     71  1.5  mw 		  GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 0);
     72  1.5  mw 		  if (! GfxBase)	/* not supposed to fail... */
     73  1.5  mw 		    abort();
     74  1.1  mw 		  ExpansionBase= (struct ExpansionBase *) OpenLibrary ("expansion.library", 0);
     75  1.1  mw 		  if (! ExpansionBase)	/* not supposed to fail... */
     76  1.1  mw 		    abort();
     77  1.5  mw 		  optind = 2;
     78  1.5  mw 		  while ((i = getopt (argc, argv, "kabpt")) != EOF)
     79  1.5  mw 		    switch (i) {
     80  1.5  mw 		    case 'k':
     81  1.5  mw 		      k_opt = 1;
     82  1.5  mw 		      break;
     83  1.5  mw 		    case 'a':
     84  1.5  mw 		      a_opt = 1;
     85  1.5  mw 		      break;
     86  1.5  mw 		    case 'b':
     87  1.5  mw 		      b_opt = 1;
     88  1.5  mw 		      break;
     89  1.5  mw 		    case 'p':
     90  1.5  mw 		      p_opt = 1;
     91  1.5  mw 		      break;
     92  1.5  mw 		    case 't':
     93  1.5  mw 		      t_opt = 1;
     94  1.5  mw 		      break;
     95  1.5  mw 		    }
     96  1.5  mw 
     97  1.1  mw 		  for (cd = 0, num_cd = 0; cd = FindConfigDev (cd, -1, -1); num_cd++) ;
     98  1.5  mw 		  get_mem_config (&fastmem_start, &fastmem_size, &chipmem_size);
     99  1.1  mw 
    100  1.1  mw 		  text_size = (e.a_text + __LDPGSZ - 1) & (-__LDPGSZ);
    101  1.1  mw 		  kernel = (u_char *) malloc (text_size + e.a_data + e.a_bss
    102  1.5  mw 				              + num_cd*sizeof(*cd) + 4
    103  1.5  mw 					      + mem_list.num_mem*sizeof(struct MEM_SEG) + 4);
    104  1.5  mw 
    105  1.5  mw 		  if (t_opt)
    106  1.5  mw 		    for (i = 0; i < mem_list.num_mem; ++i) {
    107  1.5  mw 		      printf ("mem segment %d: start=%08lx size=%08lx attribute=%04lx pri=%d\n",
    108  1.5  mw 			i + 1, mem_list.mem_seg[i].mem_start,
    109  1.5  mw 			mem_list.mem_seg[i].mem_size,
    110  1.5  mw 			mem_list.mem_seg[i].mem_attrib,
    111  1.5  mw 			mem_list.mem_seg[i].mem_prio);
    112  1.5  mw 		    }
    113  1.1  mw 
    114  1.1  mw                   if (kernel)
    115  1.1  mw                     {
    116  1.1  mw 		      if (read (fd, kernel, e.a_text) == e.a_text
    117  1.1  mw 			  && read (fd, kernel + text_size, e.a_data) == e.a_data)
    118  1.1  mw 			{
    119  1.1  mw 			  int *knum_cd;
    120  1.1  mw 			  struct ConfigDev *kcd;
    121  1.5  mw 			  int mem_ix;
    122  1.1  mw 
    123  1.5  mw 			  if (k_opt)
    124  1.1  mw 			    {
    125  1.1  mw 			      fastmem_start += 4*1024*1024;
    126  1.1  mw 			      fastmem_size  -= 4*1024*1024;
    127  1.1  mw 			    }
    128  1.1  mw 
    129  1.5  mw 			  if (a_opt)
    130  1.3  mw 			    {
    131  1.3  mw 			      printf("Autobooting...");
    132  1.3  mw 			      boothowto = RB_AUTOBOOT;
    133  1.3  mw 			    }
    134  1.5  mw 
    135  1.5  mw 			  if (b_opt)
    136  1.5  mw 			    {
    137  1.5  mw 			      printf("Askboot...");
    138  1.5  mw 			      boothowto |= RB_ASKNAME;
    139  1.5  mw 			    }
    140  1.3  mw 
    141  1.1  mw 			  printf ("Using %dM FASTMEM at 0x%x, %dM CHIPMEM\n",
    142  1.1  mw 				  fastmem_size>>20, fastmem_start, chipmem_size>>20);
    143  1.5  mw 			  if (t_opt)
    144  1.5  mw 			    exit (0);
    145  1.1  mw 			  /* give them a chance to read the information... */
    146  1.1  mw 			  sleep(2);
    147  1.1  mw 
    148  1.1  mw 			  bzero (kernel + text_size + e.a_data, e.a_bss);
    149  1.1  mw 			  knum_cd = (int *) (kernel + text_size + e.a_data + e.a_bss);
    150  1.1  mw 			  *knum_cd = num_cd;
    151  1.5  mw 			  cd = 0;
    152  1.5  mw 			  for (kcd = (struct ConfigDev *) (knum_cd+1);
    153  1.5  mw 			       cd = FindConfigDev (cd, -1, -1);
    154  1.5  mw 			       *kcd++ = *cd) ;
    155  1.5  mw 			  kmem_list = (struct MEM_LIST *)kcd;
    156  1.5  mw 			  kmem_list->num_mem = mem_list.num_mem;
    157  1.5  mw 			  for (mem_ix = 0; mem_ix < mem_list.num_mem; mem_ix++)
    158  1.5  mw 			  	kmem_list->mem_seg[mem_ix] = mem_list.mem_seg[mem_ix];
    159  1.5  mw 			  /* AGA startup - probably needs more */
    160  1.5  mw 			  LoadView (NULL);
    161  1.1  mw 			  startit (kernel,
    162  1.5  mw 				   text_size + e.a_data + e.a_bss + num_cd*sizeof(*cd) + 4
    163  1.5  mw 				     + mem_list.num_mem*sizeof(struct MEM_SEG) + 4,
    164  1.1  mw 				   e.a_entry, fastmem_start,
    165  1.3  mw 				   fastmem_size, chipmem_size,
    166  1.3  mw 				   boothowto );
    167  1.1  mw 			}
    168  1.1  mw 		      else
    169  1.1  mw 			fprintf (stderr, "Executable corrupt!\n");
    170  1.1  mw                     }
    171  1.1  mw                   else
    172  1.1  mw 		    fprintf (stderr, "Out of memory! (%d)\n", text_size + e.a_data + e.a_bss
    173  1.5  mw 				   + num_cd*sizeof(*cd) + 4
    174  1.5  mw 				   + mem_list.num_mem*sizeof(struct MEM_SEG) + 4);
    175  1.1  mw                 }
    176  1.1  mw 	      else
    177  1.1  mw 	        fprintf (stderr, "Unsupported executable: %o\n", e.a_magic);
    178  1.1  mw             }
    179  1.1  mw           else
    180  1.1  mw 	    fprintf (stderr, "Can't read header of %s\n", argv[1]);
    181  1.1  mw 
    182  1.1  mw 	  close (fd);
    183  1.1  mw         }
    184  1.1  mw       else
    185  1.1  mw 	perror ("open");
    186  1.1  mw     }
    187  1.1  mw   else
    188  1.5  mw     fprintf (stderr, "%s some-vmunix [-a] [-b] [-k] [-p] [-t]\n", argv[0]);
    189  1.1  mw }
    190  1.1  mw 
    191  1.1  mw 
    192  1.1  mw void
    193  1.1  mw get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size)
    194  1.1  mw {
    195  1.1  mw   extern struct ExecBase *SysBase;
    196  1.1  mw   struct MemHeader *mh, *nmh;
    197  1.5  mw   int num_mem = 0;
    198  1.5  mw   u_int seg_size;
    199  1.5  mw   u_int seg_start;
    200  1.5  mw   u_int seg_end;
    201  1.1  mw 
    202  1.1  mw   *fastmem_size = 0;
    203  1.1  mw   *chipmem_size = 0;
    204  1.1  mw 
    205  1.1  mw   /* walk thru the exec memory list */
    206  1.1  mw   Forbid ();
    207  1.1  mw   for (mh  = (struct MemHeader *) SysBase->MemList.lh_Head;
    208  1.1  mw        nmh = (struct MemHeader *) mh->mh_Node.ln_Succ;
    209  1.5  mw        mh  = nmh, num_mem++)
    210  1.1  mw     {
    211  1.5  mw       mem_list.mem_seg[num_mem].mem_attrib = mh->mh_Attributes;
    212  1.5  mw       mem_list.mem_seg[num_mem].mem_prio = mh->mh_Node.ln_Pri;
    213  1.5  mw       seg_start = (u_int)mh->mh_Lower;
    214  1.5  mw       seg_end = (u_int)mh->mh_Upper;
    215  1.5  mw       seg_size = seg_end - seg_start;
    216  1.5  mw       mem_list.mem_seg[num_mem].mem_size = seg_size;
    217  1.5  mw       mem_list.mem_seg[num_mem].mem_start = seg_start;
    218  1.5  mw 
    219  1.1  mw       if (mh->mh_Attributes & MEMF_CHIP)
    220  1.1  mw         {
    221  1.1  mw 	  /* there should hardly be more than one entry for chip mem, but
    222  1.1  mw 	     handle it the same nevertheless */
    223  1.5  mw 	  /* chipmem always starts at 0, so include vector area */
    224  1.5  mw 	  if (seg_start < 0x500)
    225  1.5  mw 	  	mem_list.mem_seg[num_mem].mem_start = seg_start = 0;
    226  1.5  mw 	  /* round to multiple of 512K */
    227  1.5  mw 	  seg_size = (seg_size + 512*1024 - 1) & -(512*1024);
    228  1.5  mw 	  mem_list.mem_seg[num_mem].mem_size = seg_size;
    229  1.5  mw 	  if (seg_size > *chipmem_size)
    230  1.1  mw 	    {
    231  1.5  mw 	      *chipmem_size = seg_size;
    232  1.1  mw 	    }
    233  1.1  mw         }
    234  1.1  mw       else
    235  1.1  mw 	{
    236  1.5  mw 	  /* some heuristics.. */
    237  1.5  mw 	  seg_start &= -__LDPGSZ;
    238  1.5  mw 	  /* get the mem back stolen by incore kickstart on A3000 with
    239  1.5  mw 	     V36 bootrom. */
    240  1.5  mw 	  if (seg_end == 0x07f80000)
    241  1.5  mw 	    seg_end = 0x08000000;
    242  1.5  mw 
    243  1.5  mw 	  /* or by zkick on a A2000.  */
    244  1.5  mw 	  if (seg_start == 0x280000
    245  1.5  mw 	    && strcmp (mh->mh_Node.ln_Name, "zkick memory") == 0)
    246  1.5  mw 	      seg_start = 0x200000;
    247  1.5  mw 
    248  1.5  mw 	  seg_size = seg_end - seg_start;
    249  1.5  mw 	  mem_list.mem_seg[num_mem].mem_start = seg_start;
    250  1.5  mw 	  mem_list.mem_seg[num_mem].mem_size = seg_size;
    251  1.5  mw /* if p_opt is set, select memory by priority instead of size */
    252  1.5  mw 	  if (seg_size > *fastmem_size)
    253  1.1  mw 	    {
    254  1.5  mw 	      *fastmem_size = seg_size;
    255  1.5  mw 	      *fastmem_start = (void *)seg_start;
    256  1.1  mw 	    }
    257  1.1  mw 	}
    258  1.1  mw     }
    259  1.5  mw   mem_list.num_mem = num_mem;
    260  1.1  mw   Permit();
    261  1.1  mw }
    262  1.1  mw 
    263  1.1  mw 
    264  1.1  mw 
    265  1.1  mw 
    266  1.1  mw asm ("
    267  1.1  mw 	.set	ABSEXECBASE,4
    268  1.1  mw 
    269  1.1  mw 	.text
    270  1.1  mw 	.globl	_startit
    271  1.1  mw 
    272  1.1  mw _startit:
    273  1.1  mw 	movel	sp,a3
    274  1.1  mw 	movel	4:w,a6
    275  1.1  mw 	lea	pc@(start_super-.+2),a5
    276  1.1  mw 	jmp	a6@(-0x1e)		| supervisor-call
    277  1.1  mw 
    278  1.1  mw start_super:
    279  1.1  mw 	movew	#0x2700,sr
    280  1.1  mw 
    281  1.1  mw 	| the BSD kernel wants values into the following registers:
    282  1.1  mw 	| a0:  fastmem-start
    283  1.1  mw 	| d0:  fastmem-size
    284  1.1  mw 	| d1:  chipmem-size
    285  1.5  mw 	| d5:  AttnFlags (cpuid)
    286  1.3  mw 	| d7:  boothowto
    287  1.1  mw 
    288  1.1  mw 	movel	a3@(4),a1		| loaded kernel
    289  1.1  mw 	movel	a3@(8),d2		| length of loaded kernel
    290  1.1  mw 	movel	a3@(12),a2		| entry point
    291  1.1  mw 	movel	a3@(16),a0		| fastmem-start
    292  1.1  mw 	movel	a3@(20),d0		| fastmem-size
    293  1.1  mw 	movel	a3@(24),d1		| chipmem-size
    294  1.5  mw 	movel	#0,d5
    295  1.5  mw 	movew	(ABSEXECBASE)@(0x128),d5 | SysBase->AttnFlags
    296  1.3  mw 	movel	a3@(28),d7		| boothowto
    297  1.1  mw 	subl	a4,a4			| target, load to 0
    298  1.1  mw 
    299  1.5  mw 	btst	#3,(ABSEXECBASE)@(0x129) | AFB_68040,SysBase->AttnFlags
    300  1.5  mw 	beq	not040
    301  1.5  mw 
    302  1.5  mw | Turn off 68040 MMU
    303  1.5  mw 
    304  1.5  mw 	.word 0x4e7b,0xc003		| movec a4,tc
    305  1.5  mw 	.word 0x4e7b,0xc806		| movec a4,urp
    306  1.5  mw 	.word 0x4e7b,0xc807		| movec a4,srp
    307  1.5  mw 	.word 0x4e7b,0xc004		| movec a4,itt0
    308  1.5  mw 	.word 0x4e7b,0xc005		| movec a4,itt1
    309  1.5  mw 	.word 0x4e7b,0xc006		| movec a4,dtt0
    310  1.5  mw 	.word 0x4e7b,0xc007		| movec a4,dtt1
    311  1.5  mw 	bra	nott
    312  1.5  mw 
    313  1.5  mw not040:
    314  1.1  mw 	lea	pc@(zero-.+2),a3
    315  1.1  mw 	pmove	a3@,tc			| Turn off MMU
    316  1.1  mw 	lea	pc@(nullrp-.+2),a3
    317  1.1  mw 	pmove	a3@,crp			| Turn off MMU some more
    318  1.1  mw 	pmove	a3@,srp			| Really, really, turn off MMU
    319  1.1  mw 
    320  1.1  mw | Turn off 68030 TT registers
    321  1.1  mw 
    322  1.1  mw 	btst	#2,(ABSEXECBASE)@(0x129) | AFB_68030,SysBase->AttnFlags
    323  1.1  mw 	beq	nott			| Skip TT registers if not 68030
    324  1.1  mw 	lea	pc@(zero-.+2),a3
    325  1.1  mw 	.word 0xf013,0x0800		| pmove a3@,tt0 (gas only knows about 68851 ops..)
    326  1.1  mw 	.word 0xf013,0x0c00		| pmove a3@,tt1 (gas only knows about 68851 ops..)
    327  1.1  mw 
    328  1.1  mw nott:
    329  1.1  mw 
    330  1.1  mw 	movew	#(1<<9),0xdff096	| disable DMA
    331  1.1  mw 
    332  1.1  mw L0:
    333  1.1  mw 	moveb	a1@+,a4@+
    334  1.1  mw 	subl	#1,d2
    335  1.1  mw 	bcc	L0
    336  1.1  mw 
    337  1.1  mw 
    338  1.1  mw 	jmp	a2@
    339  1.1  mw 
    340  1.1  mw 
    341  1.1  mw | A do-nothing MMU root pointer (includes the following long as well)
    342  1.1  mw 
    343  1.1  mw nullrp:	.long	0x7fff0001
    344  1.1  mw zero:	.long	0
    345  1.1  mw 
    346  1.1  mw 
    347  1.1  mw ");
    348  1.1  mw 
    349