Definitive ATABoot patch

Key realisations:

1. The driver entry point only needs to be called once per disk,
   not once per bootable partition. Bootability is decided elsewhere.

2. As a result, my shim code does not need to access the disk at all.

3. None of the ROM-based ATADisk drivers support "slave" drives.

4. Apple drivers (contrary to the Monster Disk Driver Technote) only care
   about D5 (the drive ID and some flags) on entry.
This commit is contained in:
Elliot Nunn 2019-08-25 21:59:07 +08:00
parent 9351898fb5
commit a8c1a4de1c
4 changed files with 120 additions and 432 deletions

299
ATALoad.a
View File

@ -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

View File

@ -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 '/<DRVR' MOVE.L #$44525652,-(A7) ; 'DRVR'
00000054: 3F3C 0035 '?<.5' MOVE.W #$0035,-(A7)
00000058: A9A0 '..' _GetResource ; A9A0
0000005A: 245F '$_' MOVEA.L (A7)+,A2
0000005C: 4A8A 'J.' TST.L A2
0000005E: 6700 014A 'g..J' BEQ *+$014C ; 000001AA
00000062: 2452 '$R' MOVEA.L (A2),A2
00000064: 47EE FBF8 'G...' LEA -$0408(A6),A3
00000068: 49EE FB26 'I..&' LEA -$04DA(A6),A4
0000006C: 42AE FFF8 'B...' CLR.L -$0008(A6)
00000070: 4A2E 0013 'J...' TST.B $0013(A6)
00000074: 6606 'f.' BNE.S *+$0008 ; 0000007C
00000076: 002E 0080 FFF8 '......' ORI.B #$80,-$0008(A6)
0000007C: 4294 'B.' CLR.L (A4)
0000007E: 426C 0004 'Bl..' CLR.W $0004(A4)
00000082: 197C 0002 0006 '.|....' MOVE.B #$02,$0006(A4)
00000088: 422C 0013 'B,..' CLR.B $0013(A4)
0000008C: 322E 000A '2...' MOVE.W $000A(A6),D1
00000090: 48C1 'H.' EXT.L D1
00000092: 2941 0018 ')A..' MOVE.L D1,$0018(A4)
00000096: 42AC 0008 'B...' CLR.L $0008(A4)
0000009A: 297C 0000 4E20 ')|..N ' MOVE.L #$00004E20,$001C(A4)
001C
000000A2: 197C 0013 0012 '.|....' MOVE.B #$13,$0012(A4)
000000A8: 397C 2000 0014 '9| ...' MOVE.W #$2000,$0014(A4)
000000AE: 426C 0028 'Bl.(' CLR.W $0028(A4)
000000B2: 294B 0038 ')K.8' MOVE.L A3,$0038(A4)
000000B6: 558F 'U.' SUBQ.L #$2,A7
000000B8: 2F0C '/.' MOVE.L A4,-(A7)
000000BA: AAF1 '..' DC.W $AAF1 ; TB 02F1
000000BC: 301F '0.' MOVE.W (A7)+,D0
000000BE: 48C0 'H.' EXT.L D0
000000C0: 6600 00EE 'f...' BNE *+$00F0 ; 000001B0
000000C4: 3D6B 0002 FBDE '=k....' MOVE.W $0002(A3),-$0422(A6)
000000CA: 3D6B 0006 FBE0 '=k....' MOVE.W $0006(A3),-$0420(A6)
000000D0: 3D6B 000C FBE2 '=k....' MOVE.W $000C(A3),-$041E(A6)
000000D6: 302E FBE0 '0...' MOVE.W -$0420(A6),D0
000000DA: C0EE FBE2 '....' MULU.W -$041E(A6),D0
000000DE: 3D40 FBE4 '=@..' MOVE.W D0,-$041C(A6)
000000E2: 197C 0001 0012 '.|....' MOVE.B #$01,$0012(A4)
000000E8: 426C 0014 'Bl..' CLR.W $0014(A4)
000000EC: 426C 0028 'Bl.(' CLR.W $0028(A4)
000000F0: 197C 0091 004F '.|...O' MOVE.B #$91,$004F(A4)
000000F6: 202E 0008 ' ...' MOVE.L $0008(A6),D0
000000FA: E888 '..' LSR.L #$4,D0
000000FC: 0280 0000 0010 '......' ANDI.L #$00000010,D0
00000102: 0080 0000 00A0 '......' ORI.L #$000000A0,D0
00000108: 322E FBE0 '2...' MOVE.W -$0420(A6),D1
0000010C: 5341 'SA' SUBQ.W #$1,D1
0000010E: 8041 '.A' OR.W D1,D0
00000110: 1940 004E '.@.N' MOVE.B D0,$004E(A4)
00000114: 196E FBE3 0049 '.n...I' MOVE.B -$041D(A6),$0049(A4)
0000011A: 558F 'U.' SUBQ.L #$2,A7
0000011C: 2F0C '/.' MOVE.L A4,-(A7)
0000011E: AAF1 '..' DC.W $AAF1 ; TB 02F1
00000120: 301F '0.' MOVE.W (A7)+,D0
00000122: 3D7C 2000 FB3A '=| ..:' MOVE.W #$2000,-$04C6(A6)
00000128: 2D7C 0000 0200 '-|....' MOVE.L #$00000200,-$04A6(A6)
FB5A
00000130: 1D7C 0020 FB75 '.|. .u' MOVE.B #$20,-$048B(A6) ; ' '
00000136: 7A01 'z.' MOVEQ #$01,D5
00000138: 7C00 '|.' MOVEQ #$00,D6
0000013A: 2006 ' .' MOVE.L D6,D0
0000013C: 5286 'R.' ADDQ.L #$1,D6
0000013E: BA80 '..' CMP.L D0,D5
00000140: 6568 'eh' BCS.S *+$006A ; 000001AA
00000142: 2D4B FB5E '-K.^' MOVE.L A3,-$04A2(A6)
00000146: 2D7C 0000 0200 '-|....' MOVE.L #$00000200,-$049E(A6)
FB62
0000014E: 1D7C 0001 FB6F '.|...o' MOVE.B #$01,-$0491(A6)
00000154: 486E FBDE 'Hn..' PEA -$0422(A6)
00000158: 2F06 '/.' MOVE.L D6,-(A7)
0000015A: 486E FB26 'Hn.&' PEA -$04DA(A6)
0000015E: 6100 005A 'a..Z' BSR *+$005C ; 000001BA
00000162: 558F 'U.' SUBQ.L #$2,A7
00000164: 486E FB26 'Hn.&' PEA -$04DA(A6)
00000168: AAF1 '..' DC.W $AAF1 ; TB 02F1
0000016A: 3E1F '>.' 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 ' <Size' MOVE.L #$53697A65,D0 ; 'Size'
00000042: A51E '..' _NewPtr ,Sys ; A51E
00000044: 4A88 'J.' TST.L A0
00000046: 6736 'g6' BEQ.S *+$0038 ; 0000007E
00000048: 2248 '"H' MOVEA.L A0,A1
0000004A: 41FA 4174 'A.At' LEA *+$4176,A0 ; 000041C0
0000004E: 203C 5369 7A65 ' <Size' MOVE.L #$53697A65,D0 ; 'Size'
00000054: A02E '..' _BlockMove ; A02E
00000056: 2A2E 0008 '*...' MOVE.L $0008(A6),D5
0000005A: 0285 0000 FF00 '......' ANDI.L #$0000FF00,D5
00000060: 202E 0008 ' ...' MOVE.L $0008(A6),D0
00000064: 4840 'H@' SWAP D0
00000066: 0280 00FF 0000 '......' ANDI.L #$00FF0000,D0
0000006C: 8A80 '..' OR.L D0,D5
0000006E: 4A2E 0013 'J...' TST.B $0013(A6)
00000072: 6604 'f.' BNE.S *+$0006 ; 00000078
00000074: 08C5 001F '....' BSET #$1F,D5
00000078: 4EA8 0008 'N...' JSR $0008(A0)
0000007C: 6006 '`.' BRA.S *+$0008 ; 00000084
0000007E: 203C FFFF DB93 ' <....' MOVE.L #$FFFFDB93,D0
00000084: 4CEE 0020 FFFC 'L.. ..' MOVEM.L -$0004(A6),D5
0000008A: 4E5E 'N^' UNLK A6
0000008C: 4E75 'Nu' RTS
Size: Flags $00 ModuleSize 566
Size: Flags $00 ModuleSize 142
Last
Record Summary

View File

@ -11,28 +11,13 @@ import binascii
src, cleanup = patch_common.get_src(desc='''
Enable booting from ATA disks without an Apple_Driver_ATA partition. This is
done by patching the ROM-based .ATALoad DRVR to fall back on the ROM-based
.ATADisk DRVR when initially scanning a disk. The .ATADisk is added to the ROM
if missing. The disk still needs an Apple Partition Map.
Support ATA startup disks without an Apple_Driver_ATA partition. This allows Mac
OS to be installed on a disk without repartitioning it. Accomplished by
shoehorning the Drive Setup 2.1 ATA driver into the ROM ATALoad driver, to
replace missing driver partitions.
''')
# long BOOT(void *DRVR, void *PartMapEntry, long flags)
# C calling convention: args pushed in reverse order and not popped by function, return value in d0
def find_BOOT(code):
for i in range(0, len(code), 2):
if code[i:i+4] == b'BOOT': # MOVE.L 'BOOT',D0 --or-- MOVE.L 'BOOT',-(SP)
for j in reversed(range(0, i, 2)):
# Count backwards and look for the target of *any* JSR, which is the start of the func
for k in range(0, len(code), 2):
if code[k:k+2] == b'\x4E\xBA': # JSR opcode
if k+2 + struct.unpack('>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()