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