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