1 /* $Id: loadbsd.c,v 1.3 1993/09/02 18:08:26 mw Exp $ */ 2 3 #include <sys/types.h> 4 #include <a.out.h> 5 #include <stdio.h> 6 7 #include <exec/types.h> 8 #include <exec/execbase.h> 9 #include <exec/memory.h> 10 #include <libraries/configregs.h> 11 #include <libraries/expansionbase.h> 12 13 #include <inline/exec.h> 14 #include <inline/expansion.h> 15 16 /* Get definitions for boothowto */ 17 #include "reboot.h" 18 19 struct ExpansionBase *ExpansionBase; 20 21 #undef __LDPGSZ 22 #define __LDPGSZ 8192 23 24 void get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size); 25 26 int 27 main (int argc, char *argv[]) 28 { 29 struct exec e; 30 int fd; 31 int boothowto = RB_SINGLE; 32 33 if (argc >= 2) 34 { 35 if ((fd = open (argv[1], 0)) >= 0) 36 { 37 if (read (fd, &e, sizeof (e)) == sizeof (e)) 38 { 39 if (e.a_magic == NMAGIC) 40 { 41 u_char *kernel; 42 int text_size; 43 struct ConfigDev *cd; 44 int num_cd; 45 46 ExpansionBase= (struct ExpansionBase *) OpenLibrary ("expansion.library", 0); 47 if (! ExpansionBase) /* not supposed to fail... */ 48 abort(); 49 for (cd = 0, num_cd = 0; cd = FindConfigDev (cd, -1, -1); num_cd++) ; 50 51 text_size = (e.a_text + __LDPGSZ - 1) & (-__LDPGSZ); 52 kernel = (u_char *) malloc (text_size + e.a_data + e.a_bss 53 + num_cd*sizeof(*cd) + 4); 54 55 if (kernel) 56 { 57 if (read (fd, kernel, e.a_text) == e.a_text 58 && read (fd, kernel + text_size, e.a_data) == e.a_data) 59 { 60 int *knum_cd; 61 struct ConfigDev *kcd; 62 void *fastmem_start; 63 u_long fastmem_size, chipmem_size; 64 65 get_mem_config (&fastmem_start, &fastmem_size, &chipmem_size); 66 67 if (argc >= 3 && (!strcmp (argv[2], "-k") 68 || !strcmp (argv[3], "-k")) ) 69 { 70 fastmem_start += 4*1024*1024; 71 fastmem_size -= 4*1024*1024; 72 } 73 74 if (argc >= 3 && (!strcmp (argv[2], "-a") 75 || !strcmp (argv[3], "-a")) ) 76 { 77 printf("Autobooting..."); 78 boothowto = RB_AUTOBOOT; 79 } 80 81 printf ("Using %dM FASTMEM at 0x%x, %dM CHIPMEM\n", 82 fastmem_size>>20, fastmem_start, chipmem_size>>20); 83 /* give them a chance to read the information... */ 84 sleep(2); 85 86 bzero (kernel + text_size + e.a_data, e.a_bss); 87 knum_cd = (int *) (kernel + text_size + e.a_data + e.a_bss); 88 *knum_cd = num_cd; 89 if (num_cd) 90 for (kcd = (struct ConfigDev *) (knum_cd+1); 91 cd = FindConfigDev (cd, -1, -1); 92 *kcd++ = *cd) ; 93 startit (kernel, 94 text_size + e.a_data + e.a_bss + num_cd*sizeof(*cd) + 4, 95 e.a_entry, fastmem_start, 96 fastmem_size, chipmem_size, 97 boothowto ); 98 } 99 else 100 fprintf (stderr, "Executable corrupt!\n"); 101 } 102 else 103 fprintf (stderr, "Out of memory! (%d)\n", text_size + e.a_data + e.a_bss 104 + num_cd*sizeof(*cd) + 4); 105 } 106 else 107 fprintf (stderr, "Unsupported executable: %o\n", e.a_magic); 108 } 109 else 110 fprintf (stderr, "Can't read header of %s\n", argv[1]); 111 112 close (fd); 113 } 114 else 115 perror ("open"); 116 } 117 else 118 fprintf (stderr, "%s some-vmunix [-a] [-k]\n", argv[0]); 119 } 120 121 122 void 123 get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size) 124 { 125 extern struct ExecBase *SysBase; 126 struct MemHeader *mh, *nmh; 127 128 *fastmem_size = 0; 129 *chipmem_size = 0; 130 131 /* walk thru the exec memory list */ 132 Forbid (); 133 for (mh = (struct MemHeader *) SysBase->MemList.lh_Head; 134 nmh = (struct MemHeader *) mh->mh_Node.ln_Succ; 135 mh = nmh) 136 { 137 if (mh->mh_Attributes & MEMF_CHIP) 138 { 139 /* there should hardly be more than one entry for chip mem, but 140 handle it the same nevertheless */ 141 if ((u_int)mh->mh_Upper - (u_int)mh->mh_Lower > *chipmem_size) 142 { 143 *chipmem_size = (u_int)mh->mh_Upper - (u_int)mh->mh_Lower; 144 /* round to multiple of 512K */ 145 *chipmem_size = (*chipmem_size + 512*1024 - 1) & -(512*1024); 146 147 /* chipmem always starts at 0, so don't remember start 148 address */ 149 } 150 } 151 else 152 { 153 if ((u_int)mh->mh_Upper - (u_int)mh->mh_Lower > *fastmem_size) 154 { 155 u_int start = (u_int) mh->mh_Lower; 156 u_int end = (u_int) mh->mh_Upper; 157 158 /* some heuristics.. */ 159 start &= -__LDPGSZ; 160 /* get the mem back stolen by incore kickstart on A3000 with 161 V36 bootrom. */ 162 if (end == 0x07f80000) 163 end = 0x08000000; 164 165 *fastmem_size = end - start; 166 *fastmem_start = (void *)start; 167 } 168 } 169 } 170 Permit(); 171 } 172 173 174 175 176 asm (" 177 .set ABSEXECBASE,4 178 179 .text 180 .globl _startit 181 182 _startit: 183 movel sp,a3 184 movel 4:w,a6 185 lea pc@(start_super-.+2),a5 186 jmp a6@(-0x1e) | supervisor-call 187 188 start_super: 189 movew #0x2700,sr 190 191 | the BSD kernel wants values into the following registers: 192 | a0: fastmem-start 193 | d0: fastmem-size 194 | d1: chipmem-size 195 | d7: boothowto 196 197 movel a3@(4),a1 | loaded kernel 198 movel a3@(8),d2 | length of loaded kernel 199 movel a3@(12),a2 | entry point 200 movel a3@(16),a0 | fastmem-start 201 movel a3@(20),d0 | fastmem-size 202 movel a3@(24),d1 | chipmem-size 203 movel a3@(28),d7 | boothowto 204 subl a4,a4 | target, load to 0 205 206 lea pc@(zero-.+2),a3 207 pmove a3@,tc | Turn off MMU 208 lea pc@(nullrp-.+2),a3 209 pmove a3@,crp | Turn off MMU some more 210 pmove a3@,srp | Really, really, turn off MMU 211 212 | Turn off 68030 TT registers 213 214 btst #2,(ABSEXECBASE)@(0x129) | AFB_68030,SysBase->AttnFlags 215 beq nott | Skip TT registers if not 68030 216 lea pc@(zero-.+2),a3 217 .word 0xf013,0x0800 | pmove a3@,tt0 (gas only knows about 68851 ops..) 218 .word 0xf013,0x0c00 | pmove a3@,tt1 (gas only knows about 68851 ops..) 219 220 nott: 221 222 movew #(1<<9),0xdff096 | disable DMA 223 224 L0: 225 moveb a1@+,a4@+ 226 subl #1,d2 227 bcc L0 228 229 230 jmp a2@ 231 232 233 | A do-nothing MMU root pointer (includes the following long as well) 234 235 nullrp: .long 0x7fff0001 236 zero: .long 0 237 238 239 "); 240 241