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