1| file: boot.S 2| author: chapuni(webmaster@chapuni.com) 3| Yasha(itohy@netbsd.org) 4| 5| $NetBSD: boot.S,v 1.4 2001/11/24 16:22:54 minoura Exp $ 6 7#include <machine/asm.h> 8#include "iocscall.h" 9 10#define BASEOFF 0x8000 11#define BASEPTR_A (TEXTADDR+BASEOFF) 12#define BASEPTR_R %pc@(top+BASEOFF:W) 13 14#define SRAM 0x00ED0000 /* SRAM stat addr */ 15#define SRAM_MEMSZ (SRAM + 8) /* (L) size of main memory */ 16#define MINMEM 0x00400000 /* at least 4MB required */ 17 18#define BOOT_ERROR(s) jbsr boot_error; .asciz s; .even 19 20 .globl _C_LABEL(bootufs) 21 .text 22ASENTRY_NOPROFILE(start) 23ASENTRY_NOPROFILE(top) 24 bras _ASM_LABEL(entry0) 25 .ascii "SHARP/" 26 .ascii "X680x0" 27 .word 0x8199,0x94e6,0x82ea,0x82bd 28 .word 0x8e9e,0x82c9,0x82cd,0x8cbb 29 .word 0x8ec0,0x93a6,0x94f0,0x8149 30 .word 0 31| 0x2000 (FD), 0x2400 (SASI/SCSI) (�⤷���� 0x0f0000) 32| d4 �ˤϤ��Ǥ� SCSI ID �����äƤ��� 33| �������� jmp �ޤǤϥ�������֥�˽ͤФʤ�ʤ��� 34ASENTRY_NOPROFILE(entry0) 35 moveml %d0-%d7/%a0-%a7,_C_LABEL(startregs) 36 lea BASEPTR_A:l,%a5 | set base ptr 37#define _RELOC(adr) %a5@(((adr)-(BASEPTR_A&0xffff)):W) 38#define ASRELOC(var) _RELOC(_ASM_LABEL(var)) 39#define RELOC(var) _RELOC(_C_LABEL(var)) 40 41 lea RELOC(edata),%a1 42 bra _ASM_LABEL(entry) 43 44| Disklabel= 404bytes 45| Since LABELLOFFSET in <machine/disklabel.h> is 0x40, 46| entry must be after 0x000001d4 (0x000f01d4) 47disklabel: 48 .space 406 49 50ASENTRY_NOPROFILE(entry) 51 movew #_end-1,%d0 | bss end (low word only) 52 53 | clear out bss (must be <= 64KB) 54 subw %a1,%d0 55clrbss: clrb %a1@+ 56 dbra %d0,clrbss 57 58 movel %d4,RELOC(ID) | SCSI ID (if booted from SCSI) 59 60 | set system stack 61 lea ASRELOC(top),%a1 | set stack pointer to 0x000F0000 62 lea %a1@,%sp | a1 will be used later for IOCS calls 63 64 | we use 68020 instructions, and check MPU beforehand 65 | 66 | here d1.w = -1, and the above "subw a1,d0" = 0x9049, and 67 | if MPU <= 010 loads 0x49, 68 | if MPU >= 020 loads 0x90. 69 | This is a move, not a tst instruction 70 | because pc-relative tsts are not availble on 000/010. 71chkmpu: moveb %pc@(clrbss-chkmpu-2:B,%d0:W:2),%d0 | 103B 02xx 72 jmi mpuok | MC68020 or later 73 BOOT_ERROR("MPU 68000?") 74mpuok: | XXX check for MMU? 75 76 IOCS(__BOOTINF) 77 lsll #8,%d0 | clear MSByte 78 lsrl #8,%d0 | 79 movel %d0,RELOC(BOOT_INFO) 80 81 | 82 | 0x80...0x8F SASI 83 | 0x90...0x93 Floppy 84 | 0xED0000...0xED3FFE SRAM 85 | others ROM (SCSI?) 86 | 87 movel %d0,%d1 88 clrb %d1 89 tstl %d1 90 jne boot_ram_rom 91 | 92 | SASI or Floppy 93 | 94 movel %d0,%d2 95 andib #0xFC,%d0 96 cmpib #0x90,%d0 97 jne boot_dev_unsupported | boot from SASI? 98 | 99 | Floppy 100 | 101 moveb %d2,%d0 102 andib #0x03,%d0 | drive # (head=0) 103 jbsr check_fd_format 104 moveml %d0-%d1,RELOC(FDSECMINMAX) | min and max sec # 105 lslw #8,%d2 106 moveq #0x70,%d1 107 orw %d2,%d1 | PDA*256 + MODE 108 movel %d1,RELOC(FDMODE) 109 movel %d0,%d2 | read position (first sector) 110 movel #8192,%d3 | read bytes 111 IOCS(__B_READ) 112 jra boot_read_done 113 114#include "chkfmt.s" 115 116boot_ram_rom: 117 movel %d0,%d1 118 swap %d1 119 cmpiw #0x00ED,%d1 120 jne boot_SCSI 121 | boot from SRAM? 122 123boot_dev_unsupported: 124 BOOT_ERROR("unsupported boot device") 125 126| 127| volatile void BOOT_ERROR(const char *msg); 128| print error message, wait for key press and reboot 129| 130booterr_msg: .ascii "\r\n\n" 131 .ascii BOOT 132 .asciz ": " 133reboot_msg: .asciz "\r\n[Hit key to reboot]" 134 .even 135 136ENTRY_NOPROFILE(BOOT_ERROR) 137 addql #4,%sp 138 139boot_error: lea %pc@(booterr_msg),%a1 140 IOCS(__B_PRINT) 141 moveal %sp@+,%a1 142 IOCS(__B_PRINT) 143 lea %pc@(reboot_msg),%a1 144 IOCS(__B_PRINT) 145 146 | wait for a key press (or release of a modifier) 147 IOCS(__B_KEYINP) 148 149 | issue software reset 150 trap #10 151 | NOTREACHED 152 153 154 | 155 | ROM boot ... probably from SCSI 156 | 157boot_SCSI: 158#ifdef SCSI_ADHOC_BOOTPART 159 | 160 | Find out boot partition in an ad hoc manner. 161 | 162 163 | get block length of the SCSI disk 164 SCSIIOCS(__S_READCAP) | using buffer at a1 165 tstl %d0 166 jeq 1f 167 BOOT_ERROR("READCAP failed") 1681: moveq #0,%d5 169 moveb %a1@(6),%d5 | 1: 256, 2: 512, 4: 1024 170 lsrb #1,%d5 | 0: 256, 1: 512, 2: 1024 171 movel %d5,RELOC(SCSI_BLKLEN) 172 173 | find out the start position of the boot partition 174 | XXX VERY AD HOC 175 | 176 | ROM firmware: 177 | pass read pos (in block #) in d2 178 | Human68k-style partition table does not exist 179 | d2 is 4 at the maximum 180 | SCSI IPLs (genuine and SxSI): 181 | pass read pos (in kilobytes) in d2 182 | d2 is bigger than 0x20 183 | partition table on the memory is destroyed 184 | BOOT MENU Ver.2.22: 185 | passes partition table entry address in a0 186 | d2 is cleared to zero 187 | No other IPL is supported. XXX FIXME 188 tstl %d2 189 jne sc1 190 | no information in d2 -- probably from BOOT MENU 191 | a0 points the partiion table entry 192 movel %a0@(0x0008),%d2 | in KByte 193sc1: cmpl #0x20,%d2 194 jcs sc2 195 lsll #8,%d2 | clear MSByte 196 lsrl #6,%d2 | 197 lsrl %d5,%d2 | in sector 198sc2: 199 | read entire boot 200 moveq #8192/256,%d3 | size is 8KB 201 lsrl %d5,%d3 | in sector 202 jbsr scsiread | read at %a1 203 204 cmpil #5,%d2 205 bcc sc3 206 movql #0,%d2 207sc3: movel %d2,RELOC(SCSI_PARTTOP) 208#else 209 moveq #1,%d5 | 512bytes/sec 210 movel %d5,%sp@- 211 moveq #8192/512,%d3 | �ɤ߹������祵���� 212 moveq #0x40,%d2 | ���������Ǥ�(sd*a �Τ�) 213 SCSIIOCS(__S_READ) 214#endif 215 216boot_read_done: 217 jmp first_kbyte 218 219read_error: BOOT_ERROR("read error") 220 221#undef RELOC /* base register a5 is no longer available */ 222#undef ASRELOC 223#undef _RELOC 224 225| 226| read SCSI 227| 228| input: d2.l: pos in sector 229| d3.l: len in sector 230| d4: target SCSI ID 231| d5: sector length (0: 256, 1: 512, 2: 1024) 232| a1: buffer address 233| destroy: 234| d0, d1, a1 235| 236scsiread: 237 moveml %d2-%d3/%d6-%d7/%a2,%sp@- 238 | if (pos >= 0x200000 || (len > 255 && pos + len >= 0x200000)) 239 | use READEXT 240 | else 241 | use READ 242 moveq #0x20,%d0 243 swap %d0 | d0.l = 0x00200000 244 moveq #0,%d6 245 subqb #1,%d6 | d6.l = 255 246 moveq #8,%d7 247 addb %d5,%d7 | d7.b = (sector length: 0-2) + 8 248 cmpl %d0,%d2 249 jcc scsiread_ext 250 moveq #__S_READ,%d1 251 cmpl %d3,%d6 252 jcc scsiread_noext 253 subl %d2,%d0 | d0.0 = 0x200000 - pos 254 cmpl %d0,%d3 | <= len 255 jcs scsiread_noext | no 256 257scsiread_ext: | use READEXT 258 extw %d6 | d6.l = 65535 259 moveq #__S_READEXT,%d1 260 261scsiread_noext: | use READ 262loop_scsiread: 263 | d1: SCSI IOCS call # 264 | d6: max sector count at a time 265 movel %d3,%a2 | save original len in a2 266 cmpl %d3,%d6 267 jcc 1f 268 movel %d6,%d3 2691: IOCS(__SCSIDRV) | SCSIIOCS(d1) 270 tstl %d0 271 jne read_error 272 movel %d3,%d0 | addr += read count << (8 + sec len) 273 asll %d7,%d0 274 addl %d0,%a1 275 exg %d3,%a2 | restore original len to d3 276 addl %a2,%d2 | pos += read count 277 subl %a2,%d3 | len -= read count 278 jne loop_scsiread 279 moveml %sp@+,%d2-%d3/%d6-%d7/%a2 280 rts 281 282| 283| The former part must reside in the first 1KB. 284| 285 .globl first_kbyte 286first_kbyte: 287|-------------------------------------------------------------------------- 288| 289| The latter text+data part is not accessible at the first boot time. 290| PC-relative can be used from here. 291| 292 jmp _C_LABEL(bootufs) | 0x0Fxxxx ������Ǥ椯 293 294 .word 0 295 296| int badbaddr __P((caddr_t adr)); 297| check if the given address is valid for byte read 298| return: 0: valid, 1: not valid 299 300ENTRY_NOPROFILE(badbaddr) 301 lea 0x0008:W,%a1 | MPU Bus Error vector 302 moveq #1,%d0 303 lea %pc@(badr1),%a0 304 movew %sr,%sp@- 305 oriw #0x0700,%sr | keep out interrupts 306 movel %a1@,%sp@- 307 movel %a0,%a1@ | set bus error vector 308 movel %sp,%d1 | save sp 309 moveal %sp@(10),%a0 310 tstb %a0@ | try read... 311 moveq #0,%d0 | this is skipped on bus error 312badr1: moveal %d1,%sp | restore sp 313 movel %sp@+,%a1@ 314 movew %sp@+,%sr 315 rts 316 317| void RAW_READ __P((void *buf, u_int32_t blkpos, size_t bytelen)); 318| inputs: 319| buf: input buffer address 320| blkpos: read start position in the partition in 512byte-blocks 321| bytelen: read length in bytes 322 323Lraw_read_buf=4+(4*11) 324Lraw_read_pos_=Lraw_read_buf+4 325Lraw_read_len=Lraw_read_buf+8 326 327#ifdef SCSI_ADHOC_BOOTPART 328| RAW_READ of physical disk 329ENTRY_NOPROFILE(RAW_READ0) 330 moveq #0,%d0 331 jra raw_read1 332#endif 333 334ENTRY_NOPROFILE(RAW_READ) 335#ifdef SCSI_ADHOC_BOOTPART 336 movel _C_LABEL(SCSI_PARTTOP),%d0 337raw_read1: 338#endif 339 moveml %d2-%d7/%a2-%a6,%sp@- 340 moveml %sp@(Lraw_read_buf),%d1-%d3 341 movel %d1,%a1 342 | d2.l: pos in 512byte-blocks 343 | d3.l: length in bytes 344 | a1 (=d1): buffer address 345 346 lea BASEPTR_R,%a5 | set base ptr 347#define _RELOC(adr) %a5@(((adr)-(BASEPTR_A&0xffff)):W) 348#define ASRELOC(var) _RELOC(_ASM_LABEL(var)) 349#define RELOC(var) _RELOC(_C_LABEL(var)) 350 351 tstb _RELOC(_C_LABEL(BOOT_INFO)+1) | simple check. may be incorrect! 352 beqs raw_read_floppy 353 354raw_read_scsi: 355 movel RELOC(ID),%d4 | SCSI ID 356#ifdef SCSI_ADHOC_BOOTPART 357 movel RELOC(SCSI_BLKLEN),%d5 | sector size: 0-2 358 | XXX length must be sector aligned 359 lsrl #8,%d3 | size in 256byte-blocks 360 lsrl %d5,%d3 | size in sector 361 bcss read_half | minimal error check 362 lsll #1,%d2 | X flag and d2: pos in 256byte-blocks 363 roxrl %d5,%d2 | pos in sector 364 addl %d0,%d2 | physical pos in sector 365#else 366 moveq #1,%d5 | 512bytes/sec 367 moveq #9,%d0 | shift count 368 addl #511,%d3 369 lsrl %d0,%d3 370 bcss read_half | minimal error check 371 372 addl #0x40,%d2 | 'a' partition starts here 373#endif 374| jcc 1f 375| BOOT_ERROR("out of seek") | pos exceeds 32bit 376|1: 377 jbsr scsiread 378 bras raw_read_end 379 380raw_read_floppy: 381 | 382 | Floppy read routine 383 | 384 385 | convert to seek position 386 387 asll #2,%d2 | size in 128byte-blocks 388 389 | sec = raw_read_pos (d2) 390 | sec >>= 7 + (sector length: 0-3) 391 392 lea RELOC(FDSECMINMAX),%a0 393 moveq #0,%d1 394 moveb %a0@,%d1 | d1: sector length (0-3) 395 lsrl %d1,%d2 | d2: pos in sector 396 bcss read_half | error check 397 398 | trk = sec / (# sectors) 399 | sec = sec % (# sectors) 400 401 moveb %a0@(7),%d1 | d1: max sector # 402 subb %a0@(3),%d1 | - min sector # 403 addqb #1,%d1 | d1: # sectors 404 divu %d1,%d2 | d2: (sec << 16) | track 405 406 | position = (sec length << 24) | (track/2 << 16) 407 | | (track%2 << 8) | (min sec # + sec) 408 409 movel %a0@,%d0 | d0: (sec len << 24) | min sec # 410 lsrw #1,%d2 | d2: (sec << 16) | (track / 2) 411 jcc 1f 412 bset #8,%d0 | |= (track % 2) << 8 4131: swap %d2 | d2: ((track / 2) << 16) | sec 414 addl %d0,%d2 | d2: position 415 416 | read 417 movel RELOC(FDMODE),%d1 | PDA*256 + MODE 418 419 | B_READ (for floppy) 420 | d1.w: PDA x 256 + MODE 421 | PDA: 0x90 (drive 0) ... 0x93 (drive 3) 422 | MODE: bit6: MFM 423 | bit5: retry 424 | bit4: seek 425 | d2.l: position 426 | bit31-24: sector length (0: 128, 1: 256, 2: 512, 3: 1K) 427 | bit23-16: track # (0-79) 428 | bit15-08: side (0 or 1) 429 | bit07-00: sector # (1-) 430 | d3.l: read bytes 431 | a1: read address 432 | return: 433 | d0: bit 31-24 ST0 434 | bit 23-16 ST1 435 | bit 15- 8 ST2 436 | bit 7- 0 C 437 | -1 on parameter error 438 | destroy: d0, d2, d3, a1 439 IOCS(__B_READ) 440 andil #0xf8ffff00,%d0 | check status (must be zero) 441 jne read_error 442 443raw_read_end: 444 moveml %sp@+,%a2-%a6/%d2-%d7 445 rts 446#undef _RELOC /* base register a5 is no longer available */ 447#undef ASRELOC 448#undef RELOC 449 450read_half: BOOT_ERROR("read half of block") 451 452 453ENTRY_NOPROFILE(B_KEYINP) 454 IOCS(__B_KEYINP) 455 rts 456 457ENTRY_NOPROFILE(B_PUTC) 458 movel %sp@(4),%d1 459 IOCS(__B_PUTC) 460 rts 461 462ENTRY_NOPROFILE(B_PRINT) 463 movel %sp@(4),%a1 464 IOCS(__B_PRINT) 465 rts 466 467| 468| void memcpy(void *dst, const void *src, size_t count); 469| void memmove(void *dst, const void *src, size_t count); 470| 471| small and slow memcpy... 472| THIS FUNCTION DOES NOT CONFORM THE ANSI STANDARD 473| 474ENTRY_NOPROFILE(memcpy) 475ENTRY_NOPROFILE(memmove) 476 lea %sp@(12),%a1 477 movel %a1@,%d1 | count 478 jeq Lmcpret 479 moveal %a1@-,%a0 | src 480 moveal %a1@-,%a1 | dest 481 cmpl %a1,%a0 482 jcc Lmcpfw 483 | copy backward 484 addal %d1,%a0 485 addal %d1,%a1 4861: moveb %a0@-,%a1@- 487 subql #1,%d1 488 jne 1b 489 jra Lmcpret 490Lmcpfw: | copy forward 4911: moveb %a0@+,%a1@+ 492 subql #1,%d1 493 jne 1b 494Lmcpret: 495| movel %sp@(8),%d0 | uncomment this to conform ANSI 496 rts 497 498 499| 500| global variables 501| 502 BSS(ID, 4) | SCSI ID 503 BSS(BOOT_INFO, 4) | result of IOCS(__BOOTINF) 504 BSS(FDMODE, 4) | Floppy access mode: PDA x 256 + MODE 505 BSS(FDSECMINMAX, 8) | +0: (min sector) sector length 506 | +1: (min sector) track # 507 | +2: (min sector) side 508 | +3: (min sector) sector # 509 | +4: (max sector) sector length 510 | +5: (max sector) track # 511 | +6: (max sector) side 512 | +7: (max sector) sector # 513#ifdef SCSI_ADHOC_BOOTPART 514 BSS(SCSI_PARTTOP, 4) | start sector of boot partition 515 BSS(SCSI_BLKLEN ,4) | sector len 0: 256, 1: 512, 2: 1024 516#endif 517