Home | History | Annotate | Line # | Download | only in loadbsd
loadbsd.c revision 1.11
      1   1.7  chopps /*
      2  1.11  chopps  *	$Id: loadbsd.c,v 1.11 1994/06/13 08:13:16 chopps Exp $
      3   1.7  chopps  */
      4   1.7  chopps 
      5   1.1      mw #include <sys/types.h>
      6   1.1      mw #include <a.out.h>
      7   1.1      mw #include <stdio.h>
      8   1.8  chopps #include <unistd.h>
      9   1.1      mw 
     10   1.1      mw #include <exec/types.h>
     11   1.1      mw #include <exec/execbase.h>
     12   1.1      mw #include <exec/memory.h>
     13  1.10  chopps #include <exec/resident.h>
     14   1.1      mw #include <libraries/configregs.h>
     15   1.1      mw #include <libraries/expansionbase.h>
     16   1.5      mw #include <graphics/gfxbase.h>
     17   1.1      mw 
     18   1.1      mw #include <inline/exec.h>
     19   1.1      mw #include <inline/expansion.h>
     20   1.5      mw #include <inline/graphics.h>
     21   1.1      mw 
     22   1.3      mw /* Get definitions for boothowto */
     23   1.3      mw #include "reboot.h"
     24   1.3      mw 
     25   1.6  chopps static char usage[] =
     26   1.6  chopps "
     27   1.6  chopps NAME
     28   1.6  chopps \t%s - loads NetBSD from amiga dos.
     29   1.6  chopps SYNOPSIS
     30   1.6  chopps \t%s some-vmunix [-a] [-b] [-k] [-m memory] [-p] [-t] [-V]
     31   1.6  chopps OPTIONS
     32   1.6  chopps \t-a  Boot up to multiuser mode.
     33   1.6  chopps \t-b  Ask for which root device.
     34   1.6  chopps \t    Its possible to have multiple roots and choose between them.
     35   1.6  chopps \t-k  Reserve the first 4M of fast mem [Some one else
     36   1.6  chopps \t    is going to have to answer what that it is used for].
     37   1.6  chopps \t-m  Tweak amount of available memory, for finding minimum amount
     38   1.6  chopps \t    of memory required to run. Sets fastmem size to specified
     39   1.6  chopps \t    size in Kbytes.
     40   1.6  chopps \t-p  Use highest priority fastmem segement instead of the largest
     41   1.6  chopps \t    segment. The higher priority segment is usually faster
     42   1.6  chopps \t    (i.e. 32 bit memory), but some people have smaller amounts
     43   1.6  chopps \t    of 32 bit memory.
     44   1.6  chopps \t-t  This is a *test* option.  It prints out the memory
     45   1.6  chopps \t    list information being passed to the kernel and also
     46   1.6  chopps \t    exits without actually starting NetBSD.
     47   1.8  chopps \t-S  Include kernel symbol table.
     48  1.10  chopps \t-D  Enter debugger
     49   1.6  chopps \t-V  Version of loadbsd program.
     50  1.11  chopps \t-c  Set machine type.
     51   1.6  chopps HISTORY
     52   1.6  chopps       This version supports Kernel version 720 +
     53   1.6  chopps ";
     54   1.6  chopps 
     55   1.1      mw struct ExpansionBase *ExpansionBase;
     56   1.5      mw struct GfxBase *GfxBase;
     57   1.1      mw 
     58   1.1      mw #undef __LDPGSZ
     59   1.1      mw #define __LDPGSZ 8192
     60   1.1      mw 
     61   1.5      mw #define MAX_MEM_SEG	16
     62   1.5      mw 
     63   1.6  chopps /*
     64   1.6  chopps  * Kernel parameter passing version
     65   1.8  chopps  *	1:	first version of loadbsd
     66   1.8  chopps  *	2:	needs esym location passed in a4
     67   1.6  chopps  */
     68   1.8  chopps #define KERNEL_PARAMETER_VERSION	2
     69   1.6  chopps 
     70   1.9  chopps /*
     71   1.9  chopps  *	Version history:
     72  1.10  chopps  *	1.x	Kernel parameter passing version check.
     73  1.10  chopps  *	2.0	Added symbol table end address and symbol table support.
     74  1.10  chopps  *	2.1	03/23/94 - Round up end of fastram segment.
     75  1.10  chopps  *		Check fastram segment size for minimum of 2M.
     76  1.10  chopps  *		Use largest segment of highest priority if -p option.
     77  1.10  chopps  *		Print out fastram size in KB if not a multiple of MB.
     78  1.10  chopps  *	2.2	03/24/94 - Zero out all unused registers.
     79  1.10  chopps  *		Started version history comment.
     80  1.10  chopps  *	2.3	04/26/94 - Added -D option to enter debugger on boot.
     81  1.10  chopps  *	2.4	04/30/94 - Cpuid includes base machine type.
     82  1.10  chopps  *		Also check if CPU is capable of running NetBSD.
     83  1.11  chopps  *	2.5	05/17/94 - Add check for "A3000 bonus".
     84  1.11  chopps  *	2.6	06/05/94 - Added -c option to override machine type.
     85   1.9  chopps  */
     86   1.9  chopps 
     87   1.5      mw struct MEM_LIST {
     88   1.5      mw 	u_long	num_mem;
     89   1.5      mw 	struct MEM_SEG {
     90   1.5      mw 		u_long	mem_start;
     91   1.5      mw 		u_long	mem_size;
     92   1.5      mw 		u_short	mem_attrib;
     93   1.5      mw 		short	mem_prio;
     94   1.5      mw 	} mem_seg[MAX_MEM_SEG];
     95   1.5      mw } mem_list, *kmem_list;
     96   1.5      mw 
     97   1.5      mw int k_opt;
     98   1.5      mw int a_opt;
     99   1.5      mw int b_opt;
    100   1.5      mw int p_opt;
    101   1.5      mw int t_opt;
    102   1.6  chopps int m_opt;
    103   1.8  chopps int S_opt;
    104  1.10  chopps int D_opt;
    105  1.10  chopps 
    106  1.10  chopps u_long cpuid;
    107   1.5      mw 
    108   1.5      mw extern char *optarg;
    109   1.5      mw extern int optind;
    110   1.5      mw 
    111   1.1      mw void get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size);
    112  1.10  chopps void get_cpuid (void);
    113   1.6  chopps void Usage (char *program_name);
    114   1.6  chopps void Version (void);
    115   1.6  chopps 
    116  1.11  chopps static const char _version[] = "$VER: LoadBSD 2.6 (5.6.94)";
    117   1.1      mw 
    118  1.10  chopps int
    119   1.1      mw main (int argc, char *argv[])
    120   1.1      mw {
    121   1.1      mw   struct exec e;
    122   1.1      mw   int fd;
    123   1.3      mw   int boothowto = RB_SINGLE;
    124   1.1      mw 
    125   1.1      mw   if (argc >= 2)
    126   1.1      mw     {
    127   1.1      mw       if ((fd = open (argv[1], 0)) >= 0)
    128  1.10  chopps 	{
    129  1.10  chopps 	  if (read (fd, &e, sizeof (e)) == sizeof (e))
    130  1.10  chopps 	    {
    131  1.10  chopps 	      if (e.a_magic == NMAGIC)
    132  1.10  chopps 		{
    133  1.10  chopps 		  u_char *kernel;
    134  1.10  chopps 		  int kernel_size;
    135   1.1      mw 		  int text_size;
    136   1.1      mw 		  struct ConfigDev *cd;
    137   1.1      mw 		  int num_cd;
    138   1.5      mw 		  void *fastmem_start;
    139   1.5      mw 		  u_long fastmem_size, chipmem_size;
    140   1.5      mw 		  int i;
    141   1.6  chopps 		  u_short *kern_vers;
    142   1.8  chopps 		  char *esym;
    143   1.8  chopps 		  int string_size;
    144  1.10  chopps 
    145   1.5      mw 		  GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 0);
    146   1.5      mw 		  if (! GfxBase)	/* not supposed to fail... */
    147   1.5      mw 		    abort();
    148   1.1      mw 		  ExpansionBase= (struct ExpansionBase *) OpenLibrary ("expansion.library", 0);
    149   1.1      mw 		  if (! ExpansionBase)	/* not supposed to fail... */
    150   1.1      mw 		    abort();
    151   1.5      mw 		  optind = 2;
    152  1.11  chopps 		  while ((i = getopt (argc, argv, "kabptVm:SDc:")) != EOF)
    153   1.5      mw 		    switch (i) {
    154   1.5      mw 		    case 'k':
    155   1.5      mw 		      k_opt = 1;
    156   1.5      mw 		      break;
    157   1.5      mw 		    case 'a':
    158   1.5      mw 		      a_opt = 1;
    159   1.5      mw 		      break;
    160   1.5      mw 		    case 'b':
    161   1.5      mw 		      b_opt = 1;
    162   1.5      mw 		      break;
    163   1.5      mw 		    case 'p':
    164   1.5      mw 		      p_opt = 1;
    165   1.5      mw 		      break;
    166   1.5      mw 		    case 't':
    167   1.5      mw 		      t_opt = 1;
    168   1.5      mw 		      break;
    169   1.6  chopps 		    case 'm':
    170   1.6  chopps 		      m_opt = atoi (optarg) * 1024;
    171   1.6  chopps 		      break;
    172  1.10  chopps 		    case 'V':
    173  1.10  chopps 		      Version();
    174  1.10  chopps 		      break;
    175  1.10  chopps 		    case 'S':
    176  1.10  chopps 		      S_opt = 1;
    177  1.10  chopps 		      break;
    178  1.10  chopps 		    case 'D':
    179  1.10  chopps 		      D_opt = 1;
    180  1.10  chopps 		      break;
    181  1.11  chopps 		    case 'c':
    182  1.11  chopps 		      cpuid = atoi (optarg) << 16;
    183  1.11  chopps 		      break;
    184  1.10  chopps 		    default:
    185  1.10  chopps 		      Usage(argv[0]);
    186  1.10  chopps 		      fprintf(stderr,"Unrecognized option \n");
    187  1.10  chopps 		      exit(-1);
    188   1.5      mw 		    }
    189   1.5      mw 
    190   1.1      mw 		  for (cd = 0, num_cd = 0; cd = FindConfigDev (cd, -1, -1); num_cd++) ;
    191   1.5      mw 		  get_mem_config (&fastmem_start, &fastmem_size, &chipmem_size);
    192  1.10  chopps 		  get_cpuid ();
    193   1.1      mw 
    194   1.1      mw 		  text_size = (e.a_text + __LDPGSZ - 1) & (-__LDPGSZ);
    195   1.8  chopps 		  esym = NULL;
    196   1.8  chopps 		  kernel_size = text_size + e.a_data + e.a_bss
    197   1.8  chopps 		      + num_cd*sizeof(*cd) + 4
    198   1.8  chopps 		      + mem_list.num_mem*sizeof(struct MEM_SEG) + 4;
    199   1.8  chopps 		  /*
    200   1.8  chopps 		   * get symbol table size & string size
    201   1.8  chopps 		   * (should check kernel version to see if it will handle it)
    202   1.8  chopps 		   */
    203   1.8  chopps 		  if (S_opt && e.a_syms) {
    204   1.8  chopps 		    S_opt = 0;			/* prepare for failure */
    205   1.8  chopps 		    if (lseek(fd, e.a_text + e.a_data + e.a_syms, SEEK_CUR) > 0) {
    206   1.8  chopps 		      if (read (fd, &string_size, 4) == 4) {
    207   1.8  chopps 			if (lseek(fd, sizeof(e), SEEK_SET) < 0) {
    208   1.8  chopps 		      	  printf ("Error repositioning to text\n");
    209   1.8  chopps 		      	  exit(0);		/* Give up! */
    210   1.8  chopps 			}
    211   1.8  chopps 			kernel_size += e.a_syms + 4 + string_size;
    212   1.8  chopps 			S_opt = 1;		/* sucess!  Keep -S option */
    213   1.8  chopps 		      }
    214   1.8  chopps 		    }
    215  1.10  chopps 		  }
    216   1.8  chopps 
    217   1.8  chopps 		  kernel = (u_char *) malloc (kernel_size);
    218   1.5      mw 
    219   1.5      mw 		  if (t_opt)
    220   1.5      mw 		    for (i = 0; i < mem_list.num_mem; ++i) {
    221   1.5      mw 		      printf ("mem segment %d: start=%08lx size=%08lx attribute=%04lx pri=%d\n",
    222   1.5      mw 			i + 1, mem_list.mem_seg[i].mem_start,
    223   1.5      mw 			mem_list.mem_seg[i].mem_size,
    224   1.5      mw 			mem_list.mem_seg[i].mem_attrib,
    225   1.5      mw 			mem_list.mem_seg[i].mem_prio);
    226   1.5      mw 		    }
    227   1.1      mw 
    228  1.10  chopps 		  if (kernel)
    229  1.10  chopps 		    {
    230  1.10  chopps 		      if (read (fd, kernel, e.a_text) == e.a_text
    231   1.1      mw 			  && read (fd, kernel + text_size, e.a_data) == e.a_data)
    232   1.1      mw 			{
    233   1.1      mw 			  int *knum_cd;
    234   1.1      mw 			  struct ConfigDev *kcd;
    235   1.5      mw 			  int mem_ix;
    236   1.8  chopps 
    237   1.5      mw 			  if (k_opt)
    238   1.1      mw 			    {
    239   1.1      mw 			      fastmem_start += 4*1024*1024;
    240   1.1      mw 			      fastmem_size  -= 4*1024*1024;
    241   1.1      mw 			    }
    242   1.6  chopps 
    243   1.6  chopps 			  if (m_opt && m_opt <= fastmem_size)
    244   1.6  chopps 			    {
    245   1.6  chopps 			      fastmem_size = m_opt;
    246   1.6  chopps 			    }
    247  1.10  chopps 
    248   1.5      mw 			  if (a_opt)
    249   1.3      mw 			    {
    250   1.3      mw 			      printf("Autobooting...");
    251   1.3      mw 			      boothowto = RB_AUTOBOOT;
    252   1.3      mw 			    }
    253   1.5      mw 
    254   1.5      mw 			  if (b_opt)
    255   1.5      mw 			    {
    256   1.5      mw 			      printf("Askboot...");
    257   1.5      mw 			      boothowto |= RB_ASKNAME;
    258   1.5      mw 			    }
    259  1.10  chopps 
    260  1.10  chopps 			  if (D_opt)
    261  1.10  chopps 			    {
    262  1.10  chopps 			      boothowto |= RB_KDB;
    263  1.10  chopps 			    }
    264  1.10  chopps 
    265   1.9  chopps 			  printf ("Using %d%c FASTMEM at 0x%x, %dM CHIPMEM\n",
    266   1.9  chopps 				(fastmem_size & 0xfffff) ? fastmem_size>>10 :
    267   1.9  chopps 				fastmem_size>>20,
    268   1.9  chopps 				(fastmem_size & 0xfffff) ? 'K' : 'M',
    269   1.9  chopps 				  fastmem_start, chipmem_size>>20);
    270   1.6  chopps 			  kern_vers = (u_short *) (kernel + e.a_entry - 2);
    271   1.6  chopps 			  if (*kern_vers > KERNEL_PARAMETER_VERSION &&
    272   1.6  chopps 			      *kern_vers != 0x4e73)
    273   1.6  chopps 			    {
    274   1.6  chopps 			      printf ("This kernel requires a newer version of loadbsd: %d\n", *kern_vers);
    275   1.6  chopps 			      exit (0);
    276   1.6  chopps 			    }
    277  1.10  chopps 			  if ((cpuid & AFB_68020) == 0)
    278  1.10  chopps 			    {
    279  1.10  chopps 			      printf ("Hmmm... You don't seem to have a CPU capable\n");
    280  1.10  chopps 			      printf ("        of running NetBSD.  You need a 68020\n");
    281  1.10  chopps 			      printf ("        or better\n");
    282  1.10  chopps 			      exit (0);
    283  1.10  chopps 			    }
    284   1.1      mw 			  /* give them a chance to read the information... */
    285   1.1      mw 			  sleep(2);
    286   1.1      mw 
    287   1.1      mw 			  bzero (kernel + text_size + e.a_data, e.a_bss);
    288   1.8  chopps 			  /*
    289   1.8  chopps 			   * If symbols wanted (and kernel can handle them),
    290   1.8  chopps 			   * load symbol table & strings and set esym to end.
    291   1.8  chopps 			   */
    292   1.1      mw 			  knum_cd = (int *) (kernel + text_size + e.a_data + e.a_bss);
    293   1.8  chopps 			  if (*kern_vers != 0x4e73 && *kern_vers > 1 && S_opt && e.a_syms) {
    294   1.8  chopps 			    *knum_cd++ = e.a_syms;
    295   1.8  chopps 			    read(fd, (char *)knum_cd, e.a_syms);
    296   1.8  chopps 			    knum_cd = (int *)((char *)knum_cd + e.a_syms);
    297   1.8  chopps 			    read(fd, (char *)knum_cd, string_size);
    298   1.8  chopps 			    knum_cd = (int*)((char *)knum_cd + string_size);
    299   1.8  chopps 			    esym = (char *) (text_size + e.a_data + e.a_bss
    300   1.8  chopps 			      + e.a_syms + 4 + string_size);
    301   1.8  chopps 			  }
    302   1.1      mw 			  *knum_cd = num_cd;
    303   1.5      mw 			  for (kcd = (struct ConfigDev *) (knum_cd+1);
    304   1.5      mw 			       cd = FindConfigDev (cd, -1, -1);
    305   1.6  chopps 			       *kcd++ = *cd)
    306   1.6  chopps 				;
    307   1.5      mw 			  kmem_list = (struct MEM_LIST *)kcd;
    308   1.5      mw 			  kmem_list->num_mem = mem_list.num_mem;
    309   1.5      mw 			  for (mem_ix = 0; mem_ix < mem_list.num_mem; mem_ix++)
    310   1.5      mw 			  	kmem_list->mem_seg[mem_ix] = mem_list.mem_seg[mem_ix];
    311   1.8  chopps 			  if (t_opt)		/* if test option */
    312   1.8  chopps 			    exit (0);		/*   don't start kernel */
    313   1.8  chopps 			  /* AGA startup - may need more */
    314   1.5      mw 			  LoadView (NULL);
    315   1.8  chopps 			  startit (kernel, kernel_size,
    316   1.1      mw 				   e.a_entry, fastmem_start,
    317   1.3      mw 				   fastmem_size, chipmem_size,
    318  1.10  chopps 				   boothowto, esym, cpuid );
    319   1.1      mw 			}
    320   1.1      mw 		      else
    321   1.1      mw 			fprintf (stderr, "Executable corrupt!\n");
    322  1.10  chopps 		    }
    323  1.10  chopps 		  else
    324  1.10  chopps 		    fprintf (stderr, "Out of memory! (%d)\n", text_size + e.a_data + e.a_bss
    325   1.5      mw 				   + num_cd*sizeof(*cd) + 4
    326   1.5      mw 				   + mem_list.num_mem*sizeof(struct MEM_SEG) + 4);
    327  1.10  chopps 		}
    328   1.1      mw 	      else
    329  1.10  chopps 		fprintf (stderr, "Unsupported executable: %o\n", e.a_magic);
    330  1.10  chopps 	    }
    331  1.10  chopps 	  else
    332   1.1      mw 	    fprintf (stderr, "Can't read header of %s\n", argv[1]);
    333   1.1      mw 
    334   1.1      mw 	  close (fd);
    335  1.10  chopps 	}
    336   1.1      mw       else
    337   1.1      mw 	perror ("open");
    338   1.1      mw     }
    339   1.1      mw   else
    340   1.6  chopps     Usage(argv[0]);
    341   1.6  chopps   Version();
    342   1.6  chopps }/* main() */
    343   1.1      mw 
    344   1.1      mw void
    345   1.1      mw get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size)
    346   1.1      mw {
    347  1.10  chopps   extern struct ExecBase *SysBase;
    348   1.1      mw   struct MemHeader *mh, *nmh;
    349   1.5      mw   int num_mem = 0;
    350   1.5      mw   u_int seg_size;
    351   1.5      mw   u_int seg_start;
    352   1.5      mw   u_int seg_end;
    353   1.9  chopps   char mem_pri = -128;
    354  1.10  chopps 
    355   1.1      mw   *fastmem_size = 0;
    356   1.1      mw   *chipmem_size = 0;
    357  1.10  chopps 
    358   1.1      mw   /* walk thru the exec memory list */
    359   1.1      mw   Forbid ();
    360   1.1      mw   for (mh  = (struct MemHeader *) SysBase->MemList.lh_Head;
    361   1.1      mw        nmh = (struct MemHeader *) mh->mh_Node.ln_Succ;
    362   1.5      mw        mh  = nmh, num_mem++)
    363   1.1      mw     {
    364   1.5      mw       mem_list.mem_seg[num_mem].mem_attrib = mh->mh_Attributes;
    365   1.5      mw       mem_list.mem_seg[num_mem].mem_prio = mh->mh_Node.ln_Pri;
    366   1.5      mw       seg_start = (u_int)mh->mh_Lower;
    367   1.5      mw       seg_end = (u_int)mh->mh_Upper;
    368   1.5      mw       seg_size = seg_end - seg_start;
    369   1.5      mw       mem_list.mem_seg[num_mem].mem_size = seg_size;
    370   1.5      mw       mem_list.mem_seg[num_mem].mem_start = seg_start;
    371   1.5      mw 
    372   1.1      mw       if (mh->mh_Attributes & MEMF_CHIP)
    373  1.10  chopps 	{
    374   1.1      mw 	  /* there should hardly be more than one entry for chip mem, but
    375   1.1      mw 	     handle it the same nevertheless */
    376   1.5      mw 	  /* chipmem always starts at 0, so include vector area */
    377   1.6  chopps 	  mem_list.mem_seg[num_mem].mem_start = seg_start = 0;
    378   1.5      mw 	  /* round to multiple of 512K */
    379   1.5      mw 	  seg_size = (seg_size + 512*1024 - 1) & -(512*1024);
    380   1.5      mw 	  mem_list.mem_seg[num_mem].mem_size = seg_size;
    381   1.5      mw 	  if (seg_size > *chipmem_size)
    382   1.1      mw 	    {
    383   1.5      mw 	      *chipmem_size = seg_size;
    384   1.1      mw 	    }
    385  1.10  chopps 	}
    386   1.1      mw       else
    387   1.1      mw 	{
    388   1.5      mw 	  /* some heuristics.. */
    389   1.5      mw 	  seg_start &= -__LDPGSZ;
    390   1.9  chopps 	  seg_end = (seg_end + __LDPGSZ - 1) & -__LDPGSZ;
    391   1.5      mw 	  /* get the mem back stolen by incore kickstart on A3000 with
    392   1.5      mw 	     V36 bootrom. */
    393   1.5      mw 	  if (seg_end == 0x07f80000)
    394   1.5      mw 	    seg_end = 0x08000000;
    395   1.5      mw 
    396   1.5      mw 	  /* or by zkick on a A2000.  */
    397   1.5      mw 	  if (seg_start == 0x280000
    398   1.5      mw 	    && strcmp (mh->mh_Node.ln_Name, "zkick memory") == 0)
    399   1.5      mw 	      seg_start = 0x200000;
    400   1.5      mw 
    401   1.5      mw 	  seg_size = seg_end - seg_start;
    402   1.5      mw 	  mem_list.mem_seg[num_mem].mem_start = seg_start;
    403   1.5      mw 	  mem_list.mem_seg[num_mem].mem_size = seg_size;
    404   1.9  chopps 	  /*
    405   1.9  chopps 	   *  If this segment is smaller than 2M,
    406   1.9  chopps 	   *  don't use it to load the kernel
    407   1.9  chopps 	   */
    408   1.9  chopps 	  if (seg_size < 2 * 1024 * 1024)
    409   1.9  chopps 	    continue;
    410   1.5      mw /* if p_opt is set, select memory by priority instead of size */
    411   1.6  chopps 	  if ((!p_opt && seg_size > *fastmem_size) ||
    412  1.10  chopps 	    (p_opt && mem_pri <= mh->mh_Node.ln_Pri && seg_size > *fastmem_size))
    413   1.1      mw 	    {
    414   1.5      mw 	      *fastmem_size = seg_size;
    415   1.5      mw 	      *fastmem_start = (void *)seg_start;
    416   1.9  chopps 	      mem_pri = mh->mh_Node.ln_Pri;
    417   1.1      mw 	    }
    418   1.1      mw 	}
    419   1.1      mw     }
    420   1.5      mw   mem_list.num_mem = num_mem;
    421   1.1      mw   Permit();
    422   1.1      mw }
    423   1.1      mw 
    424  1.10  chopps /*
    425  1.10  chopps  * Try to determine the machine ID by searching the resident module list
    426  1.10  chopps  * for modules only present on specific machines.  (Thanks, Bill!)
    427  1.10  chopps  */
    428   1.1      mw 
    429  1.10  chopps void
    430  1.10  chopps get_cpuid ()
    431  1.10  chopps {
    432  1.10  chopps 	extern struct ExecBase *SysBase;
    433  1.10  chopps 	u_long *rl;
    434  1.10  chopps 	struct Resident *rm;
    435  1.10  chopps 
    436  1.11  chopps 	cpuid |= SysBase->AttnFlags;	/* get FPU and CPU flags */
    437  1.11  chopps 	if (cpuid & 0xffff0000) {
    438  1.11  chopps 		switch (cpuid >> 16) {
    439  1.11  chopps 		case 500:
    440  1.11  chopps 		case 600:
    441  1.11  chopps 		case 1000:
    442  1.11  chopps 		case 1200:
    443  1.11  chopps 		case 2000:
    444  1.11  chopps 		case 3000:
    445  1.11  chopps 		case 4000:
    446  1.11  chopps 			return;
    447  1.11  chopps 		default:
    448  1.11  chopps 			printf ("Machine type Amiga %d is not valid\n",
    449  1.11  chopps 			    cpuid >> 16);
    450  1.11  chopps 			exit (1);
    451  1.11  chopps 		}
    452  1.11  chopps 	}
    453  1.10  chopps 	rl = (u_long *) SysBase->ResModules;
    454  1.10  chopps 	if (rl == NULL)
    455  1.10  chopps 		return;
    456  1.10  chopps 
    457  1.10  chopps 	while (*rl) {
    458  1.10  chopps 		rm = (struct Resident *) *rl;
    459  1.10  chopps 		if (strcmp (rm->rt_Name, "A4000 Bonus") == 0 ||
    460  1.10  chopps 		    strcmp (rm->rt_Name, "A1000 Bonus") == 0) {
    461  1.10  chopps 			cpuid |= 4000 << 16;
    462  1.10  chopps 			break;
    463  1.10  chopps 		}
    464  1.11  chopps 		if (strcmp (rm->rt_Name, "A3000 bonus") == 0 ||
    465  1.11  chopps 		    strcmp (rm->rt_Name, "A3000 Bonus") == 0) {
    466  1.10  chopps 			cpuid |= 3000 << 16;
    467  1.10  chopps 			break;
    468  1.10  chopps 		}
    469  1.10  chopps 		if (strcmp (rm->rt_Name, "card.resource") == 0) {
    470  1.10  chopps 			cpuid |= 1200 << 16;	/* or A600 :-) */
    471  1.10  chopps 			break;
    472  1.10  chopps 		}
    473  1.10  chopps 		++rl;
    474  1.10  chopps 	}
    475  1.10  chopps 	if (*rl == 0)		/* Nothing found, it's probably an A2000 or A500 */
    476  1.10  chopps 		cpuid |= 2000 << 16;
    477  1.10  chopps }
    478   1.1      mw 
    479   1.1      mw 
    480   1.1      mw asm ("
    481   1.1      mw 	.set	ABSEXECBASE,4
    482   1.1      mw 
    483   1.1      mw 	.text
    484   1.1      mw 	.globl	_startit
    485   1.1      mw 
    486   1.1      mw _startit:
    487   1.1      mw 	movel	sp,a3
    488   1.1      mw 	movel	4:w,a6
    489   1.1      mw 	lea	pc@(start_super-.+2),a5
    490   1.1      mw 	jmp	a6@(-0x1e)		| supervisor-call
    491   1.1      mw 
    492   1.1      mw start_super:
    493   1.1      mw 	movew	#0x2700,sr
    494   1.1      mw 
    495   1.1      mw 	| the BSD kernel wants values into the following registers:
    496   1.1      mw 	| a0:  fastmem-start
    497   1.1      mw 	| d0:  fastmem-size
    498   1.1      mw 	| d1:  chipmem-size
    499   1.5      mw 	| d5:  AttnFlags (cpuid)
    500   1.3      mw 	| d7:  boothowto
    501   1.8  chopps 	| a4:  esym location
    502  1.10  chopps 	| All other registers zeroed for possible future requirements.
    503   1.1      mw 
    504   1.1      mw 	movel	a3@(4),a1		| loaded kernel
    505   1.1      mw 	movel	a3@(8),d2		| length of loaded kernel
    506   1.9  chopps 	movel	a3@(12),sp@-		| entry point [save on stack for rts]
    507   1.1      mw 	movel	a3@(16),a0		| fastmem-start
    508   1.1      mw 	movel	a3@(20),d0		| fastmem-size
    509   1.1      mw 	movel	a3@(24),d1		| chipmem-size
    510   1.3      mw 	movel	a3@(28),d7		| boothowto
    511   1.8  chopps 	movel	a3@(32),a4		| esym
    512  1.10  chopps 	movel	a3@(36),d5		| cpuid
    513   1.8  chopps 	subl	a5,a5			| target, load to 0
    514   1.1      mw 
    515   1.5      mw 	btst	#3,(ABSEXECBASE)@(0x129) | AFB_68040,SysBase->AttnFlags
    516   1.5      mw 	beq	not040
    517   1.5      mw 
    518   1.5      mw | Turn off 68040 MMU
    519   1.5      mw 
    520   1.8  chopps 	.word 0x4e7b,0xd003		| movec a5,tc
    521   1.8  chopps 	.word 0x4e7b,0xd806		| movec a5,urp
    522   1.8  chopps 	.word 0x4e7b,0xd807		| movec a5,srp
    523   1.8  chopps 	.word 0x4e7b,0xd004		| movec a5,itt0
    524   1.8  chopps 	.word 0x4e7b,0xd005		| movec a5,itt1
    525   1.8  chopps 	.word 0x4e7b,0xd006		| movec a5,dtt0
    526   1.8  chopps 	.word 0x4e7b,0xd007		| movec a5,dtt1
    527   1.5      mw 	bra	nott
    528   1.5      mw 
    529   1.5      mw not040:
    530   1.1      mw 	lea	pc@(zero-.+2),a3
    531   1.1      mw 	pmove	a3@,tc			| Turn off MMU
    532   1.1      mw 	lea	pc@(nullrp-.+2),a3
    533   1.1      mw 	pmove	a3@,crp			| Turn off MMU some more
    534   1.1      mw 	pmove	a3@,srp			| Really, really, turn off MMU
    535   1.1      mw 
    536   1.1      mw | Turn off 68030 TT registers
    537   1.1      mw 
    538   1.1      mw 	btst	#2,(ABSEXECBASE)@(0x129) | AFB_68030,SysBase->AttnFlags
    539   1.1      mw 	beq	nott			| Skip TT registers if not 68030
    540   1.1      mw 	lea	pc@(zero-.+2),a3
    541   1.1      mw 	.word 0xf013,0x0800		| pmove a3@,tt0 (gas only knows about 68851 ops..)
    542   1.1      mw 	.word 0xf013,0x0c00		| pmove a3@,tt1 (gas only knows about 68851 ops..)
    543   1.1      mw 
    544   1.1      mw nott:
    545   1.1      mw 
    546   1.1      mw 	movew	#(1<<9),0xdff096	| disable DMA
    547   1.1      mw 
    548   1.1      mw L0:
    549   1.8  chopps 	moveb	a1@+,a5@+
    550   1.1      mw 	subl	#1,d2
    551   1.1      mw 	bcc	L0
    552   1.1      mw 
    553   1.1      mw 
    554   1.9  chopps 	moveq	#0,d2			| zero out unused registers
    555   1.9  chopps 	moveq	#0,d3			| (might make future compatibility
    556   1.9  chopps 	moveq	#0,d4			|  a little easier, since all registers
    557   1.9  chopps 	moveq	#0,d6			|  would have known contents)
    558   1.9  chopps 	movel	d6,a1
    559   1.9  chopps 	movel	d6,a2
    560   1.9  chopps 	movel	d6,a3
    561   1.9  chopps 	movel	d6,a5
    562   1.9  chopps 	movel	d6,a6
    563   1.9  chopps 	rts				| return to kernel entry point
    564   1.1      mw 
    565   1.1      mw 
    566   1.1      mw | A do-nothing MMU root pointer (includes the following long as well)
    567   1.1      mw 
    568   1.1      mw nullrp:	.long	0x7fff0001
    569   1.1      mw zero:	.long	0
    570   1.1      mw 
    571   1.1      mw 
    572   1.1      mw ");
    573   1.1      mw 
    574   1.6  chopps void Usage(char *program_name)
    575   1.6  chopps {
    576   1.6  chopps    fprintf(stderr,usage,program_name,program_name);
    577   1.6  chopps }
    578   1.6  chopps 
    579   1.6  chopps void Version()
    580   1.6  chopps {
    581   1.6  chopps   fprintf(stderr,"%s\n",_version + 6);
    582   1.6  chopps }
    583