Home | History | Annotate | Line # | Download | only in loadbsd
loadbsd.c revision 1.6
      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.6  chopps static char usage[] =
     20  1.6  chopps "
     21  1.6  chopps NAME
     22  1.6  chopps \t%s - loads NetBSD from amiga dos.
     23  1.6  chopps SYNOPSIS
     24  1.6  chopps \t%s some-vmunix [-a] [-b] [-k] [-m memory] [-p] [-t] [-V]
     25  1.6  chopps OPTIONS
     26  1.6  chopps \t-a  Boot up to multiuser mode.
     27  1.6  chopps \t-b  Ask for which root device.
     28  1.6  chopps \t    Its possible to have multiple roots and choose between them.
     29  1.6  chopps \t-k  Reserve the first 4M of fast mem [Some one else
     30  1.6  chopps \t    is going to have to answer what that it is used for].
     31  1.6  chopps \t-m  Tweak amount of available memory, for finding minimum amount
     32  1.6  chopps \t    of memory required to run. Sets fastmem size to specified
     33  1.6  chopps \t    size in Kbytes.
     34  1.6  chopps \t-p  Use highest priority fastmem segement instead of the largest
     35  1.6  chopps \t    segment. The higher priority segment is usually faster
     36  1.6  chopps \t    (i.e. 32 bit memory), but some people have smaller amounts
     37  1.6  chopps \t    of 32 bit memory.
     38  1.6  chopps \t-t  This is a *test* option.  It prints out the memory
     39  1.6  chopps \t    list information being passed to the kernel and also
     40  1.6  chopps \t    exits without actually starting NetBSD.
     41  1.6  chopps \t-V  Version of loadbsd program.
     42  1.6  chopps HISTORY
     43  1.6  chopps       This version supports Kernel version 720 +
     44  1.6  chopps ";
     45  1.6  chopps 
     46  1.1      mw struct ExpansionBase *ExpansionBase;
     47  1.5      mw struct GfxBase *GfxBase;
     48  1.1      mw 
     49  1.1      mw #undef __LDPGSZ
     50  1.1      mw #define __LDPGSZ 8192
     51  1.1      mw 
     52  1.5      mw #define MAX_MEM_SEG	16
     53  1.5      mw 
     54  1.6  chopps /*
     55  1.6  chopps  * Kernel parameter passing version
     56  1.6  chopps  */
     57  1.6  chopps #define KERNEL_PARAMETER_VERSION	1
     58  1.6  chopps 
     59  1.5      mw struct MEM_LIST {
     60  1.5      mw 	u_long	num_mem;
     61  1.5      mw 	struct MEM_SEG {
     62  1.5      mw 		u_long	mem_start;
     63  1.5      mw 		u_long	mem_size;
     64  1.5      mw 		u_short	mem_attrib;
     65  1.5      mw 		short	mem_prio;
     66  1.5      mw 	} mem_seg[MAX_MEM_SEG];
     67  1.5      mw } mem_list, *kmem_list;
     68  1.5      mw 
     69  1.5      mw int k_opt;
     70  1.5      mw int a_opt;
     71  1.5      mw int b_opt;
     72  1.5      mw int p_opt;
     73  1.5      mw int t_opt;
     74  1.6  chopps int m_opt;
     75  1.5      mw 
     76  1.5      mw extern char *optarg;
     77  1.5      mw extern int optind;
     78  1.5      mw 
     79  1.1      mw void get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size);
     80  1.6  chopps void Usage (char *program_name);
     81  1.6  chopps void Version (void);
     82  1.6  chopps 
     83  1.6  chopps static const char _version[] = "$VER: LoadBSD 1.744 (28.1.94)";
     84  1.1      mw 
     85  1.1      mw int
     86  1.1      mw main (int argc, char *argv[])
     87  1.1      mw {
     88  1.1      mw   struct exec e;
     89  1.1      mw   int fd;
     90  1.3      mw   int boothowto = RB_SINGLE;
     91  1.1      mw 
     92  1.1      mw   if (argc >= 2)
     93  1.1      mw     {
     94  1.1      mw       if ((fd = open (argv[1], 0)) >= 0)
     95  1.1      mw         {
     96  1.1      mw           if (read (fd, &e, sizeof (e)) == sizeof (e))
     97  1.1      mw             {
     98  1.1      mw               if (e.a_magic == NMAGIC)
     99  1.1      mw                 {
    100  1.1      mw                   u_char *kernel;
    101  1.1      mw 		  int text_size;
    102  1.1      mw 		  struct ConfigDev *cd;
    103  1.1      mw 		  int num_cd;
    104  1.5      mw 		  void *fastmem_start;
    105  1.5      mw 		  u_long fastmem_size, chipmem_size;
    106  1.5      mw 		  int i;
    107  1.6  chopps 		  u_short *kern_vers;
    108  1.1      mw 
    109  1.5      mw 		  GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 0);
    110  1.5      mw 		  if (! GfxBase)	/* not supposed to fail... */
    111  1.5      mw 		    abort();
    112  1.1      mw 		  ExpansionBase= (struct ExpansionBase *) OpenLibrary ("expansion.library", 0);
    113  1.1      mw 		  if (! ExpansionBase)	/* not supposed to fail... */
    114  1.1      mw 		    abort();
    115  1.5      mw 		  optind = 2;
    116  1.6  chopps 		  while ((i = getopt (argc, argv, "kabptVm:")) != EOF)
    117  1.5      mw 		    switch (i) {
    118  1.5      mw 		    case 'k':
    119  1.5      mw 		      k_opt = 1;
    120  1.5      mw 		      break;
    121  1.5      mw 		    case 'a':
    122  1.5      mw 		      a_opt = 1;
    123  1.5      mw 		      break;
    124  1.5      mw 		    case 'b':
    125  1.5      mw 		      b_opt = 1;
    126  1.5      mw 		      break;
    127  1.5      mw 		    case 'p':
    128  1.5      mw 		      p_opt = 1;
    129  1.5      mw 		      break;
    130  1.5      mw 		    case 't':
    131  1.5      mw 		      t_opt = 1;
    132  1.5      mw 		      break;
    133  1.6  chopps 		    case 'm':
    134  1.6  chopps 		      m_opt = atoi (optarg) * 1024;
    135  1.6  chopps 		      break;
    136  1.6  chopps                     case 'V':
    137  1.6  chopps                       Version();
    138  1.6  chopps                       break;
    139  1.6  chopps                     default:
    140  1.6  chopps                       Usage(argv[0]);
    141  1.6  chopps                       fprintf(stderr,"Unrecognized option \n");
    142  1.6  chopps                       exit(-1);
    143  1.5      mw 		    }
    144  1.5      mw 
    145  1.1      mw 		  for (cd = 0, num_cd = 0; cd = FindConfigDev (cd, -1, -1); num_cd++) ;
    146  1.5      mw 		  get_mem_config (&fastmem_start, &fastmem_size, &chipmem_size);
    147  1.1      mw 
    148  1.1      mw 		  text_size = (e.a_text + __LDPGSZ - 1) & (-__LDPGSZ);
    149  1.1      mw 		  kernel = (u_char *) malloc (text_size + e.a_data + e.a_bss
    150  1.5      mw 				              + num_cd*sizeof(*cd) + 4
    151  1.5      mw 					      + mem_list.num_mem*sizeof(struct MEM_SEG) + 4);
    152  1.5      mw 
    153  1.5      mw 		  if (t_opt)
    154  1.5      mw 		    for (i = 0; i < mem_list.num_mem; ++i) {
    155  1.5      mw 		      printf ("mem segment %d: start=%08lx size=%08lx attribute=%04lx pri=%d\n",
    156  1.5      mw 			i + 1, mem_list.mem_seg[i].mem_start,
    157  1.5      mw 			mem_list.mem_seg[i].mem_size,
    158  1.5      mw 			mem_list.mem_seg[i].mem_attrib,
    159  1.5      mw 			mem_list.mem_seg[i].mem_prio);
    160  1.5      mw 		    }
    161  1.1      mw 
    162  1.1      mw                   if (kernel)
    163  1.1      mw                     {
    164  1.1      mw 		      if (read (fd, kernel, e.a_text) == e.a_text
    165  1.1      mw 			  && read (fd, kernel + text_size, e.a_data) == e.a_data)
    166  1.1      mw 			{
    167  1.1      mw 			  int *knum_cd;
    168  1.1      mw 			  struct ConfigDev *kcd;
    169  1.5      mw 			  int mem_ix;
    170  1.1      mw 
    171  1.5      mw 			  if (k_opt)
    172  1.1      mw 			    {
    173  1.1      mw 			      fastmem_start += 4*1024*1024;
    174  1.1      mw 			      fastmem_size  -= 4*1024*1024;
    175  1.1      mw 			    }
    176  1.6  chopps 
    177  1.6  chopps 			  if (m_opt && m_opt <= fastmem_size)
    178  1.6  chopps 			    {
    179  1.6  chopps 			      fastmem_size = m_opt;
    180  1.6  chopps 			    }
    181  1.1      mw 
    182  1.5      mw 			  if (a_opt)
    183  1.3      mw 			    {
    184  1.3      mw 			      printf("Autobooting...");
    185  1.3      mw 			      boothowto = RB_AUTOBOOT;
    186  1.3      mw 			    }
    187  1.5      mw 
    188  1.5      mw 			  if (b_opt)
    189  1.5      mw 			    {
    190  1.5      mw 			      printf("Askboot...");
    191  1.5      mw 			      boothowto |= RB_ASKNAME;
    192  1.5      mw 			    }
    193  1.3      mw 
    194  1.1      mw 			  printf ("Using %dM FASTMEM at 0x%x, %dM CHIPMEM\n",
    195  1.1      mw 				  fastmem_size>>20, fastmem_start, chipmem_size>>20);
    196  1.6  chopps 			  kern_vers = (u_short *) (kernel + e.a_entry - 2);
    197  1.6  chopps 			  if (*kern_vers > KERNEL_PARAMETER_VERSION &&
    198  1.6  chopps 			      *kern_vers != 0x4e73)
    199  1.6  chopps 			    {
    200  1.6  chopps 			      printf ("This kernel requires a newer version of loadbsd: %d\n", *kern_vers);
    201  1.6  chopps 			      exit (0);
    202  1.6  chopps 			    }
    203  1.6  chopps 			  if (t_opt)		/* if test option */
    204  1.6  chopps 			    exit (0);		/*   don't start kernel */
    205  1.1      mw 			  /* give them a chance to read the information... */
    206  1.1      mw 			  sleep(2);
    207  1.1      mw 
    208  1.1      mw 			  bzero (kernel + text_size + e.a_data, e.a_bss);
    209  1.1      mw 			  knum_cd = (int *) (kernel + text_size + e.a_data + e.a_bss);
    210  1.1      mw 			  *knum_cd = num_cd;
    211  1.5      mw 			  for (kcd = (struct ConfigDev *) (knum_cd+1);
    212  1.5      mw 			       cd = FindConfigDev (cd, -1, -1);
    213  1.6  chopps 			       *kcd++ = *cd)
    214  1.6  chopps 				;
    215  1.5      mw 			  kmem_list = (struct MEM_LIST *)kcd;
    216  1.5      mw 			  kmem_list->num_mem = mem_list.num_mem;
    217  1.5      mw 			  for (mem_ix = 0; mem_ix < mem_list.num_mem; mem_ix++)
    218  1.5      mw 			  	kmem_list->mem_seg[mem_ix] = mem_list.mem_seg[mem_ix];
    219  1.5      mw 			  /* AGA startup - probably needs more */
    220  1.5      mw 			  LoadView (NULL);
    221  1.1      mw 			  startit (kernel,
    222  1.5      mw 				   text_size + e.a_data + e.a_bss + num_cd*sizeof(*cd) + 4
    223  1.5      mw 				     + mem_list.num_mem*sizeof(struct MEM_SEG) + 4,
    224  1.1      mw 				   e.a_entry, fastmem_start,
    225  1.3      mw 				   fastmem_size, chipmem_size,
    226  1.3      mw 				   boothowto );
    227  1.1      mw 			}
    228  1.1      mw 		      else
    229  1.1      mw 			fprintf (stderr, "Executable corrupt!\n");
    230  1.1      mw                     }
    231  1.1      mw                   else
    232  1.1      mw 		    fprintf (stderr, "Out of memory! (%d)\n", text_size + e.a_data + e.a_bss
    233  1.5      mw 				   + num_cd*sizeof(*cd) + 4
    234  1.5      mw 				   + mem_list.num_mem*sizeof(struct MEM_SEG) + 4);
    235  1.1      mw                 }
    236  1.1      mw 	      else
    237  1.1      mw 	        fprintf (stderr, "Unsupported executable: %o\n", e.a_magic);
    238  1.1      mw             }
    239  1.1      mw           else
    240  1.1      mw 	    fprintf (stderr, "Can't read header of %s\n", argv[1]);
    241  1.1      mw 
    242  1.1      mw 	  close (fd);
    243  1.1      mw         }
    244  1.1      mw       else
    245  1.1      mw 	perror ("open");
    246  1.1      mw     }
    247  1.1      mw   else
    248  1.6  chopps     Usage(argv[0]);
    249  1.6  chopps   Version();
    250  1.6  chopps }/* main() */
    251  1.1      mw 
    252  1.1      mw void
    253  1.1      mw get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size)
    254  1.1      mw {
    255  1.1      mw   extern struct ExecBase *SysBase;
    256  1.1      mw   struct MemHeader *mh, *nmh;
    257  1.5      mw   int num_mem = 0;
    258  1.5      mw   u_int seg_size;
    259  1.5      mw   u_int seg_start;
    260  1.5      mw   u_int seg_end;
    261  1.1      mw 
    262  1.1      mw   *fastmem_size = 0;
    263  1.1      mw   *chipmem_size = 0;
    264  1.1      mw 
    265  1.1      mw   /* walk thru the exec memory list */
    266  1.1      mw   Forbid ();
    267  1.1      mw   for (mh  = (struct MemHeader *) SysBase->MemList.lh_Head;
    268  1.1      mw        nmh = (struct MemHeader *) mh->mh_Node.ln_Succ;
    269  1.5      mw        mh  = nmh, num_mem++)
    270  1.1      mw     {
    271  1.5      mw       mem_list.mem_seg[num_mem].mem_attrib = mh->mh_Attributes;
    272  1.5      mw       mem_list.mem_seg[num_mem].mem_prio = mh->mh_Node.ln_Pri;
    273  1.5      mw       seg_start = (u_int)mh->mh_Lower;
    274  1.5      mw       seg_end = (u_int)mh->mh_Upper;
    275  1.5      mw       seg_size = seg_end - seg_start;
    276  1.5      mw       mem_list.mem_seg[num_mem].mem_size = seg_size;
    277  1.5      mw       mem_list.mem_seg[num_mem].mem_start = seg_start;
    278  1.5      mw 
    279  1.1      mw       if (mh->mh_Attributes & MEMF_CHIP)
    280  1.1      mw         {
    281  1.1      mw 	  /* there should hardly be more than one entry for chip mem, but
    282  1.1      mw 	     handle it the same nevertheless */
    283  1.5      mw 	  /* chipmem always starts at 0, so include vector area */
    284  1.6  chopps 	  mem_list.mem_seg[num_mem].mem_start = seg_start = 0;
    285  1.5      mw 	  /* round to multiple of 512K */
    286  1.5      mw 	  seg_size = (seg_size + 512*1024 - 1) & -(512*1024);
    287  1.5      mw 	  mem_list.mem_seg[num_mem].mem_size = seg_size;
    288  1.5      mw 	  if (seg_size > *chipmem_size)
    289  1.1      mw 	    {
    290  1.5      mw 	      *chipmem_size = seg_size;
    291  1.1      mw 	    }
    292  1.1      mw         }
    293  1.1      mw       else
    294  1.1      mw 	{
    295  1.5      mw 	  /* some heuristics.. */
    296  1.5      mw 	  seg_start &= -__LDPGSZ;
    297  1.5      mw 	  /* get the mem back stolen by incore kickstart on A3000 with
    298  1.5      mw 	     V36 bootrom. */
    299  1.5      mw 	  if (seg_end == 0x07f80000)
    300  1.5      mw 	    seg_end = 0x08000000;
    301  1.5      mw 
    302  1.5      mw 	  /* or by zkick on a A2000.  */
    303  1.5      mw 	  if (seg_start == 0x280000
    304  1.5      mw 	    && strcmp (mh->mh_Node.ln_Name, "zkick memory") == 0)
    305  1.5      mw 	      seg_start = 0x200000;
    306  1.5      mw 
    307  1.5      mw 	  seg_size = seg_end - seg_start;
    308  1.5      mw 	  mem_list.mem_seg[num_mem].mem_start = seg_start;
    309  1.5      mw 	  mem_list.mem_seg[num_mem].mem_size = seg_size;
    310  1.5      mw /* if p_opt is set, select memory by priority instead of size */
    311  1.6  chopps 	  if ((!p_opt && seg_size > *fastmem_size) ||
    312  1.6  chopps             (p_opt && *fastmem_size == 0))
    313  1.1      mw 	    {
    314  1.5      mw 	      *fastmem_size = seg_size;
    315  1.5      mw 	      *fastmem_start = (void *)seg_start;
    316  1.1      mw 	    }
    317  1.1      mw 	}
    318  1.1      mw     }
    319  1.5      mw   mem_list.num_mem = num_mem;
    320  1.1      mw   Permit();
    321  1.1      mw }
    322  1.1      mw 
    323  1.1      mw 
    324  1.1      mw 
    325  1.1      mw 
    326  1.1      mw asm ("
    327  1.1      mw 	.set	ABSEXECBASE,4
    328  1.1      mw 
    329  1.1      mw 	.text
    330  1.1      mw 	.globl	_startit
    331  1.1      mw 
    332  1.1      mw _startit:
    333  1.1      mw 	movel	sp,a3
    334  1.1      mw 	movel	4:w,a6
    335  1.1      mw 	lea	pc@(start_super-.+2),a5
    336  1.1      mw 	jmp	a6@(-0x1e)		| supervisor-call
    337  1.1      mw 
    338  1.1      mw start_super:
    339  1.1      mw 	movew	#0x2700,sr
    340  1.1      mw 
    341  1.1      mw 	| the BSD kernel wants values into the following registers:
    342  1.1      mw 	| a0:  fastmem-start
    343  1.1      mw 	| d0:  fastmem-size
    344  1.1      mw 	| d1:  chipmem-size
    345  1.5      mw 	| d5:  AttnFlags (cpuid)
    346  1.3      mw 	| d7:  boothowto
    347  1.1      mw 
    348  1.1      mw 	movel	a3@(4),a1		| loaded kernel
    349  1.1      mw 	movel	a3@(8),d2		| length of loaded kernel
    350  1.1      mw 	movel	a3@(12),a2		| entry point
    351  1.1      mw 	movel	a3@(16),a0		| fastmem-start
    352  1.1      mw 	movel	a3@(20),d0		| fastmem-size
    353  1.1      mw 	movel	a3@(24),d1		| chipmem-size
    354  1.5      mw 	movel	#0,d5
    355  1.5      mw 	movew	(ABSEXECBASE)@(0x128),d5 | SysBase->AttnFlags
    356  1.3      mw 	movel	a3@(28),d7		| boothowto
    357  1.1      mw 	subl	a4,a4			| target, load to 0
    358  1.1      mw 
    359  1.5      mw 	btst	#3,(ABSEXECBASE)@(0x129) | AFB_68040,SysBase->AttnFlags
    360  1.5      mw 	beq	not040
    361  1.5      mw 
    362  1.5      mw | Turn off 68040 MMU
    363  1.5      mw 
    364  1.5      mw 	.word 0x4e7b,0xc003		| movec a4,tc
    365  1.5      mw 	.word 0x4e7b,0xc806		| movec a4,urp
    366  1.5      mw 	.word 0x4e7b,0xc807		| movec a4,srp
    367  1.5      mw 	.word 0x4e7b,0xc004		| movec a4,itt0
    368  1.5      mw 	.word 0x4e7b,0xc005		| movec a4,itt1
    369  1.5      mw 	.word 0x4e7b,0xc006		| movec a4,dtt0
    370  1.5      mw 	.word 0x4e7b,0xc007		| movec a4,dtt1
    371  1.5      mw 	bra	nott
    372  1.5      mw 
    373  1.5      mw not040:
    374  1.1      mw 	lea	pc@(zero-.+2),a3
    375  1.1      mw 	pmove	a3@,tc			| Turn off MMU
    376  1.1      mw 	lea	pc@(nullrp-.+2),a3
    377  1.1      mw 	pmove	a3@,crp			| Turn off MMU some more
    378  1.1      mw 	pmove	a3@,srp			| Really, really, turn off MMU
    379  1.1      mw 
    380  1.1      mw | Turn off 68030 TT registers
    381  1.1      mw 
    382  1.1      mw 	btst	#2,(ABSEXECBASE)@(0x129) | AFB_68030,SysBase->AttnFlags
    383  1.1      mw 	beq	nott			| Skip TT registers if not 68030
    384  1.1      mw 	lea	pc@(zero-.+2),a3
    385  1.1      mw 	.word 0xf013,0x0800		| pmove a3@,tt0 (gas only knows about 68851 ops..)
    386  1.1      mw 	.word 0xf013,0x0c00		| pmove a3@,tt1 (gas only knows about 68851 ops..)
    387  1.1      mw 
    388  1.1      mw nott:
    389  1.1      mw 
    390  1.1      mw 	movew	#(1<<9),0xdff096	| disable DMA
    391  1.1      mw 
    392  1.1      mw L0:
    393  1.1      mw 	moveb	a1@+,a4@+
    394  1.1      mw 	subl	#1,d2
    395  1.1      mw 	bcc	L0
    396  1.1      mw 
    397  1.1      mw 
    398  1.1      mw 	jmp	a2@
    399  1.1      mw 
    400  1.1      mw 
    401  1.1      mw | A do-nothing MMU root pointer (includes the following long as well)
    402  1.1      mw 
    403  1.1      mw nullrp:	.long	0x7fff0001
    404  1.1      mw zero:	.long	0
    405  1.1      mw 
    406  1.1      mw 
    407  1.1      mw ");
    408  1.1      mw 
    409  1.6  chopps void Usage(char *program_name)
    410  1.6  chopps {
    411  1.6  chopps    fprintf(stderr,usage,program_name,program_name);
    412  1.6  chopps }
    413  1.6  chopps 
    414  1.6  chopps void Version()
    415  1.6  chopps {
    416  1.6  chopps   fprintf(stderr,"%s\n",_version + 6);
    417  1.6  chopps }
    418