diff --git a/ATALoad.a b/ATALoad.a index 9e889ea..c197f4e 100644 --- a/ATALoad.a +++ b/ATALoad.a @@ -1,6 +1,5 @@ ; Asm ATALoad.a -o ATALoad.a.o; DumpObj ATALoad.a.o > ATALoad.dmp ; The python script does the rest. -; This is messy and brittle. I got very, very sick of it! MAIN MACHINE MC68030 @@ -12,6 +11,11 @@ bsr.s OriginalFunc ; ... and call the function add.l #$C,sp ; pop those copied arguments, we don't need them +; move.l d0,-(sp) +; move.l d0,a0 +; bsr PrintHex +; move.l (sp)+,d0 + cmp.l #$FFFFDB93,d0 ; ATANoDriverErr -> try our method beq.s NewFunc cmp.l #$FFFFDB92,d0 ; ATANoDDMErr -> try our method @@ -21,247 +25,68 @@ OriginalFunc string asis - dc.b 'Nsrt' ; placeholder for script to insert the clobbered LINK instruction - bra *+2+'ID' ; placeholder for script to jump to remainder of original function - - - -var_regs equ -$4FA - -ataPB equ -$4DA ; to -ataPBQType equ -$4D6 -ataPBVers equ -$4D4 -ataPBReserved2 equ -$4CE -ataPBFunctionCode equ -$4C8 -ataPBIOSpeed equ -$4C7 -ataPBFlags equ -$4C6 -ataPBDeviceID equ -$4C2 -ataPBTimeOut equ -$4BE -ataPBState equ -$4B2 - -; common part of PB ends at offset $30 = -$4AA -; this part below is a bit tricky... - -ataPB34 equ -$4A6 ; 34 -ataPB38 equ -$4A2 ; 38 -ataPB3C equ -$49E ; 3c -ataPB40 equ -$49A ; 40 - -; -492...-48A = "task file" - -ataPBTaskFile_ataTFCount equ -$491 -ataPBTaskFile_ataTFSDH equ -$48C -ataPBTaskFile_ataTFCommand equ -$48B - -; entire PB ends at offset $30 = -$4AA - -; max possible PB size ends at $B8 = -$422 - -var_bstruct_0 equ -$422 -var_bstruct_2 equ -$420 -var_bstruct_4 equ -$41E -var_bstruct_6 equ -$41C - -var_ddmidx equ -$41A -var_drvrcnt equ -$418 -var_arg2 equ -$40E -var_ddmptr equ -$40C - -var_buf1 equ -$408 -var_buf2 equ -$208 - -var_flags equ -8 -var_4 equ -4 - -arg_dev equ 8 -arg_ddtype equ $C ; a long -arg_romdrvr equ $10 + dc.b 'Nsrt' ; LINKER SCRIPT + bra *+2+'ID' ; LINKER SCRIPT NewFunc - link a6,#-$4DA - movem.l d3-d7/a2-a4,-(sp) + link a6,#-4 + movem.l d5,-4(a6) + + ; 16(a6).L = !AfterSystemStartupTime + ; 12(a6).L = $0701, the DDMap ID for a Mac driver + ; 8(a6).L = device ID (i.e. devNum<<8 | busNum) + +; move.l 16(a6),a0 +; bsr PrintHex +; move.l 12(a6),a0 +; bsr PrintHex +; move.l 8(a6),a0 +; bsr PrintHex + + cmp.w #$0701,12+2(a6) + bne.s @fail + + move.l #'Size',d0 ; LINKER SCRIPT + dc.w $A51E ; _NewPtrSys + tst.l A0 + beq.s @fail + + move.l a0,a1 + lea *+2+'At',a0 ; LINKER SCRIPT + move.l #'Size',d0 ; LINKER SCRIPT + dc.w $A02E ; _BlockMove + + move.l 8(a6),d5 ; put device number in this byte + and.l #$0000FF00,d5 + + move.l 8(a6),d0 ; put bus number in this byte + swap d0 + and.l #$00FF0000,d0 + or.l d0,d5 + + tst.b 16+3(a6) + bne.s @rom + bset.l #31,d5 ; kAfterSystemStartupTime +@rom + + jsr 8(a0) ; ATAMgr v2 entry point + ; never mind the spec, only set d5 + +; move.l d0,a0 +; bsr PrintHex + + bra.s @return + +@fail + move.l #$FFFFDB93,d0 +@return + movem.l -4(a6),d5 + unlk a6 + rts -; Wipe the stack frame to be safe - lea -$4DA(A6),A0 -@lup clr.w (A0)+ - cmp.l A0,A6 - bne.s @lup - -; Check that we are asked for an ATA driver - cmp.l #$00000701,arg_ddtype(a6) ; kDriverTypeMacATA - bne itr_fail - -; Load the actual working driver - move.w #$FFFF,$B9E ; temp ROMMapInsert - move.l #'DRVR',-(SP) - move.w #53,-(SP) ; .ATADisk - dc.w $A9A0 - movea.l (SP)+,A2 - tst.l A2 - beq itr_fail - movea.l (A2),A2 - -; Set pointers to the 512-byte scratch buffer and the param block - lea var_buf1(a6),a3 - lea ataPB(a6),a4 - -; Set bit 31 ("RAM based driver at run time") in the d5 passed to DRVR - move.l #0,var_flags(a6) - tst.b arg_romdrvr+3(a6) - bne.s is_romdrvr - ori.b #$80,var_flags(a6) ; set the flag -is_romdrvr: - -; Get the "IDENTIFY DEVICE" block with CHS information - move.l #0, $00(a4) ; ataPBLink - move.w #0, $04(a4) ; ataPBQType - move.b #2, $06(a4) ; --> ataPBVers - move.b #0, $13(a4) ; --> ataPBIOSpeed - move.w arg_dev+2(a6),d1 - ext.l d1 - move.l d1, $18(a4) ; --> ataPBDeviceID - move.l #0, $08(a4) ; ? ataPBReserved2 - move.l #20000,$1C(a4) ; --> ataPBTimeOut - move.b #$13, $12(a4) ; --> ataPBFunctionCode = kATAMgrDriveIdentify - move.w #$2000,$14(a4) ; --> ataPBFlags = mATAFlagIORead - move.w #0, $28(a4) ; ? ataPBState - move.l a3, $38(a4) ; ataPBBuffer - - sub.l #2,sp - move.l a4,-(sp) - dc.w $AAF1 ; ATAManager - move.w (sp)+,d0 - ext.l d0 - bne itr_return - -; Parse the "IDENTIFY DEVICE" block - move.w 2(a3),var_bstruct_0(a6) ; typically 1041 - move.w 6(a3),var_bstruct_2(a6) ; typically 0010 - move.w $C(a3),var_bstruct_4(a6) ; typically 003f - move.w var_bstruct_2(a6),d0 ; can't safely get rid of these for some reason! - mulu.w var_bstruct_4(a6),d0 - move.w d0,var_bstruct_6(a6) - -; Send "Init drive parameters" - move.b #$1, $12(a4) ; --> ataPBFunctionCode = IO (not in headers) - move.w #0, $14(a4) ; --> ataPBFlags - move.w #0, $28(a4) ; ? ataPBState - move.b #$91, $48+$7(a4) ; ataPBTaskFile.ataTFCommand = kATAcmdInitDrive - move.l arg_dev(a6),d0 ; (leaving bit $40 as zero for CHS) - lsr.l #4,d0 - and.l #$10,d0 ; master/slave bit - or.l #$A0,d0 ; sector size ? 512 - move.w var_bstruct_2(a6),d1 - sub.w #1,d1 - or.w d1,d0 ; head number - move.b d0, $48+$6(a4) ; ataPBTaskFile.ataTFSDH - move.b var_bstruct_4+1(a6),$48+$1(a4); ataPBTaskFile.ataTFCount - - sub.l #2,sp - move.l a4,-(sp) - dc.w $AAF1 ; ATAManager - move.w (sp)+,d0 - -; Loop over all partitions, ask the driver to pick a bootable one - move.w #$2000,ataPBFlags(a6) - move.l #$200,ataPB34(a6) - move.b #$20,ataPBTaskFile_ataTFCommand(a6) - move.l #1,d5 ; Initially check only one partition, increase this number later - moveq #0,d6 ; Partition index counter -tellDriverAboutPartitionLoop: - - move.l d6,d0 - addq.l #1,d6 - cmp.l d0,d5 - bcs.s itr_fail - move.l a3,ataPB38(a6) - move.l #$200,ataPB3C(a6) - move.b #1,ataPBTaskFile_ataTFCount(a6) - pea var_bstruct_0(a6) - move.l d6,-(sp) - pea ataPB(a6) - bsr paramblk_helper_function - subq.l #2,sp - pea ataPB(a6) - dc.w $AAF1 ;;;;;;;;;;;;;;;;;;;;;;;;; kATAcmdRead again (get next PM entry) - move.w (sp)+,d7 - lea $C(sp),sp - moveq #0,d0 - move.w (a3),d0 - cmpi.l #'PM',d0 - bne.s tellDriverAboutPartitionLoop - move.l 4(a3),d5 ; update the *real* number of partitions, so we don't end early - move.l var_flags(a6),-(sp) ; var_flags, obviously - move.w var_arg2(a6),d0 - ext.l d0 - move.l d0,-(sp) ; arg_dev+2 extended to a long, pretty much always zero - move.l a3,-(sp) ; pointer to this partition map entry - move.l a2,-(sp) ; pointer to driver - bsr *+2+'BT' ; BOOT function - move.l d0,d4 - - lea $10(sp),sp - move.w d4,d7 ; -1 means try a different partition, 0 means succes, otherwise error - cmpi.w #$FFFF,d7 - beq.s tellDriverAboutPartitionLoop - - tst.w d7 - bne.s itr_fail - - move.l d4,d0 ; the final pathway for success - bra.s itr_return - -itr_fail: - move.l #$FFFFDB93,d0 ; ATANoDriverErr - -itr_return: - movem.l var_regs(a6),d3-d7/a2-a4 - unlk a6 - rts - - -paramblk_helper_function: - link a6,#0 - movem.l d6-d7/a3-a4,-(sp) - move.l $C(a6),d7 - movea.l $10(a6),a3 - movea.l $8(a6),a4 - move.l $18(a4),d0 - lsr.l #8,d0 - moveq #1,d6 - and.l d0,d6 - clr.w $28(a4) - moveq #0,d0 - move.w 6(a3),d0 - move.l d7,d1 - divu.l d0,d1 - move.w d1,$4C(a4) - moveq #0,d0 - move.w 4(a3),d0 - move.l d7,d1 - divu.l d0,d1 - moveq #0,d0 - move.w 2(a3),d0 - tst.l d0 - tdivs.l d0,d2:d1 - moveq #$F,d0 - and.l d2,d0 - move.b d0,$4E(a4) - move.l d6,d0 - lsl.l #4,d0 - or.b d0,$4E(a4) - ori.b #$A0,$4E(a4) - moveq #0,d0 - move.w 4(a3),d0 - move.l d7,d1 - tdivu.l d0,d2:d1 - addq.b #1,d2 - move.b d2,$4A(a4) - movem.l -$10(a6),d6-d7/a3-a4 - unlk a6 - rts + END string c diff --git a/ATALoad.dmp b/ATALoad.dmp index c79df73..ebe36e0 100644 --- a/ATALoad.dmp +++ b/ATALoad.dmp @@ -11,7 +11,7 @@ Pad Module: Flags=$10=(Main Local Code) Module="#0001"(1) Segment="Main"(2) Content: Flags $08 -Contents offset $0000 size $0236 +Contents offset $0000 size $008E 00000000: 41EF 0010 'A...' LEA $0010(A7),A0 00000004: 2F20 '/ ' MOVE.L -(A0),-(A7) 00000006: 2F20 '/ ' MOVE.L -(A0),-(A7) @@ -26,161 +26,35 @@ Contents offset $0000 size $0236 00000022: 4E73 'Ns' RTE 00000024: 7274 'rt' MOVEQ #$74,D1 ; 't' 00000026: 6000 4944 '`.ID' BRA *+$4946 ; 0000496C -0000002A: 4E56 FB26 'NV.&' LINK A6,#$FB26 -0000002E: 48E7 1F38 'H..8' MOVEM.L D3-D7/A2-A4,-(A7) -00000032: 41EE FB26 'A..&' LEA -$04DA(A6),A0 -00000036: 4258 'BX' CLR.W (A0)+ -00000038: BDC8 '..' CMPA.L A0,A6 -0000003A: 66FA 'f.' BNE.S *-$0004 ; 00000036 -0000003C: 0CAE 0000 0701 '......' CMPI.L #$00000701,$000C(A6) - 000C -00000044: 6600 0164 'f..d' BNE *+$0166 ; 000001AA -00000048: 31FC FFFF 0B9E '1.....' MOVE.W #$FFFF,$0B9E -0000004E: 2F3C 4452 5652 '/.' MOVE.W (A7)+,D7 -0000016C: 4FEF 000C 'O...' LEA $000C(A7),A7 -00000170: 7000 'p.' MOVEQ #$00,D0 -00000172: 3013 '0.' MOVE.W (A3),D0 -00000174: 0C80 0000 504D '....PM' CMPI.L #$0000504D,D0 -0000017A: 66BE 'f.' BNE.S *-$0040 ; 0000013A -0000017C: 2A2B 0004 '*+..' MOVE.L $0004(A3),D5 -00000180: 2F2E FFF8 '/...' MOVE.L -$0008(A6),-(A7) -00000184: 302E FBF2 '0...' MOVE.W -$040E(A6),D0 -00000188: 48C0 'H.' EXT.L D0 -0000018A: 2F00 '/.' MOVE.L D0,-(A7) -0000018C: 2F0B '/.' MOVE.L A3,-(A7) -0000018E: 2F0A '/.' MOVE.L A2,-(A7) -00000190: 6100 4254 'a.BT' BSR *+$4256 ; 000043E6 -00000194: 2800 '(.' MOVE.L D0,D4 -00000196: 4FEF 0010 'O...' LEA $0010(A7),A7 -0000019A: 3E04 '>.' MOVE.W D4,D7 -0000019C: 0C47 FFFF '.G..' CMPI.W #$FFFF,D7 -000001A0: 6798 'g.' BEQ.S *-$0066 ; 0000013A -000001A2: 4A47 'JG' TST.W D7 -000001A4: 6604 'f.' BNE.S *+$0006 ; 000001AA -000001A6: 2004 ' .' MOVE.L D4,D0 -000001A8: 6006 '`.' BRA.S *+$0008 ; 000001B0 -000001AA: 203C FFFF DB93 ' <....' MOVE.L #$FFFFDB93,D0 -000001B0: 4CEE 1CF8 FB06 'L.....' MOVEM.L -$04FA(A6),D3-D7/A2-A4 -000001B6: 4E5E 'N^' UNLK A6 -000001B8: 4E75 'Nu' RTS -000001BA: 4E56 0000 'NV..' LINK A6,#$0000 -000001BE: 48E7 0318 'H...' MOVEM.L D6/D7/A3/A4,-(A7) -000001C2: 2E2E 000C '....' MOVE.L $000C(A6),D7 -000001C6: 266E 0010 '&n..' MOVEA.L $0010(A6),A3 -000001CA: 286E 0008 '(n..' MOVEA.L $0008(A6),A4 -000001CE: 202C 0018 ' ,..' MOVE.L $0018(A4),D0 -000001D2: E088 '..' LSR.L #$8,D0 -000001D4: 7C01 '|.' MOVEQ #$01,D6 -000001D6: CC80 '..' AND.L D0,D6 -000001D8: 426C 0028 'Bl.(' CLR.W $0028(A4) -000001DC: 7000 'p.' MOVEQ #$00,D0 -000001DE: 302B 0006 '0+..' MOVE.W $0006(A3),D0 -000001E2: 2207 '".' MOVE.L D7,D1 -000001E4: 4C40 1001 'L@..' DIVU.L D0,D1 -000001E8: 3941 004C '9A.L' MOVE.W D1,$004C(A4) -000001EC: 7000 'p.' MOVEQ #$00,D0 -000001EE: 302B 0004 '0+..' MOVE.W $0004(A3),D0 -000001F2: 2207 '".' MOVE.L D7,D1 -000001F4: 4C40 1001 'L@..' DIVU.L D0,D1 -000001F8: 7000 'p.' MOVEQ #$00,D0 -000001FA: 302B 0002 '0+..' MOVE.W $0002(A3),D0 -000001FE: 4A80 'J.' TST.L D0 -00000200: 4C40 1802 'L@..' TDIVS.L D0,D2:D1 -00000204: 700F 'p.' MOVEQ #$0F,D0 -00000206: C082 '..' AND.L D2,D0 -00000208: 1940 004E '.@.N' MOVE.B D0,$004E(A4) -0000020C: 2006 ' .' MOVE.L D6,D0 -0000020E: E988 '..' LSL.L #$4,D0 -00000210: 812C 004E '.,.N' OR.B D0,$004E(A4) -00000214: 002C 00A0 004E '.,...N' ORI.B #$A0,$004E(A4) -0000021A: 7000 'p.' MOVEQ #$00,D0 -0000021C: 302B 0004 '0+..' MOVE.W $0004(A3),D0 -00000220: 2207 '".' MOVE.L D7,D1 -00000222: 4C40 1002 'L@..' TDIVU.L D0,D2:D1 -00000226: 5202 'R.' ADDQ.B #$1,D2 -00000228: 1942 004A '.B.J' MOVE.B D2,$004A(A4) -0000022C: 4CEE 18C0 FFF0 'L.....' MOVEM.L -$0010(A6),D6/D7/A3/A4 -00000232: 4E5E 'N^' UNLK A6 -00000234: 4E75 'Nu' RTS +0000002A: 4E56 FFFC 'NV..' LINK A6,#$FFFC +0000002E: 48EE 0020 FFFC 'H.. ..' MOVEM.L D5,-$0004(A6) +00000034: 0C6E 0701 000E '.n....' CMPI.W #$0701,$000E(A6) +0000003A: 6642 'fB' BNE.S *+$0044 ; 0000007E +0000003C: 203C 5369 7A65 ' h', code[k+2:k+4])[0] == j: - return j - - raise ValueError('Function BOOT not found') - - def find_InitDevice(code): for i in range(0, len(code), 2): # checking Driver Descriptor Map magic number (there are two but this one always first) @@ -46,7 +31,7 @@ def find_InitDevice(code): def patch_ataload(code): code = bytearray(code) - new = len(code) # boundary between old and new code + cut1 = len(code) # boundary between original and glue # Parse the DumpObj'd file with open(path.join(path.dirname(__file__), 'ATALoad.dmp')) as f: @@ -55,46 +40,50 @@ def patch_ataload(code): if m: code.extend(binascii.unhexlify(m.group(1).replace(' ', ''))) - InitDevice = find_InitDevice(code[:new]) - BOOT = find_BOOT(code[:new]) + cut2 = len(code) # boundary between glue and driver - print('ATALoad patch: InitDevice=0x%X, NewInitDevice=0x%X, BOOT=0x%X' % (InitDevice, new, BOOT)) + with open(path.join(path.dirname(__file__), 'AppleATADisk'), 'rb') as f: + code.extend(f.read()) + + InitDevice = find_InitDevice(code[:cut1]) + + print('ATALoad patch: InitDevice=0x%X, glue=0x%X, driver=0x%X' % (InitDevice, cut1, cut2)) # "Link" the new code into the old - for i in range(new, len(code), 2): + for i in range(cut1, len(code), 2): if code[i:i+4] == b'Nsrt': code[i:i+4] = code[InitDevice:InitDevice+4] # copy the first LINK from the original function code[InitDevice:InitDevice+2] = b'\x60\x00' # BRA.W opcode, to... - code[InitDevice+2:InitDevice+4] = struct.pack('>h', new - (InitDevice+2)) # ...the start of the new code + code[InitDevice+2:InitDevice+4] = struct.pack('>h', cut1 - (InitDevice+2)) # ...the start of the new code + + if code[i:i+2] == b'At': + code[i:i+2] = struct.pack('>h', cut2 - i) + + if code[i:i+4] == b'Size': + code[i:i+4] = struct.pack('>l', cut2 - cut1) if code[i:i+2] == b'ID': # reference to original InitDevice, skipping the mangled 4-byte LINK code[i:i+2] = struct.pack('>h', (InitDevice+4) - i) - if code[i:i+2] == b'BT': # reference to BOOT function - code[i:i+2] = struct.pack('>h', BOOT - i) - return bytes(code) +found_drvr = False + for (parent, folders, files) in os.walk(src): folders.sort(); files.sort() # make it kinda deterministic for filename in files: full = path.join(src, parent, filename) - if filename == 'Romfile': - ataload = path.join(src, parent, 'Rsrc', 'DRVR_-20175_ATALoad') - atadisk = path.join(src, parent, 'Rsrc', 'DRVR_53_ATADisk') + if filename == 'DRVR_-20175_ATALoad': + code = open(full, 'rb').read() + code = patch_ataload(code) + open(full, 'wb').write(code) + found_drvr = True - if path.exists(ataload): - code = open(ataload, 'rb').read() - code = patch_ataload(code) - open(ataload, 'wb').write(code) - if not path.exists(atadisk): - with open(full, 'a') as f: # append to Romfile - f.write('\ntype=DRVR id=53 name=.ATADisk src=Rsrc/DRVR_53_ATADisk # inserted by ataboot.py\n') - print('ATALoad patch: using .ATADisk DRVR from Drive Setup 2.1') - shutil.copy(path.join(path.dirname(__file__), 'DRVR_53_ATADisk'), atadisk) +if not found_drvr: + raise ValueError('ATALoad DRVR not found') cleanup()