This commit is contained in:
Elliot Nunn 2020-10-24 10:07:45 +08:00
parent 34e139a963
commit e06a86901a
10 changed files with 320 additions and 838498 deletions

3
.gitignore vendored
View File

@ -2,6 +2,7 @@
edit.rom
.DS_Store
BootstrapFloppy/System.rdump
Bootstrap.bin
BootstrapFloppy.dsk
BootServer.INIT*
*.bin
payload

View File

@ -18,25 +18,31 @@ DrvrBase
DrvrOpen
; TODO: Move this somewhere that it can respond to AppleTalk going up/down
; Don't care about the caller PB, so use A0 for our AppleTalk PB instead
move.l A0,-(SP)
lea PB,A0
; Don't care about the caller PB, so use A0 as a scratch register
movem.l A0-A1,-(SP)
; Modify the socket listener code for quick access to driver globals
lea editLeaDCE+2,A0
move.l A1,(A0)
; Open .MPP
; TODO: check globals on old ROMs before trying
lea PB,A0
clr.b $1B(A0) ; IOPermssn = whatever is allowed
lea MPPString,A1 ; IOFileName = .MPP
move.l A1,$12(A0)
lea MPPString,A2 ; IOFileName = .MPP
move.l A2,$12(A0)
dc.w $A000 ; _Open
bne.s openFail
move.w $18(A0),$16(A1) ; save MPP refnum in dctlStorage
; Open a DDP socket: "POpenSkt" via direct call to .MPP
move.w #248,$1A(A0) ; csCode = openSkt
clr.b $1C(A0) ; socket = auto-assign
lea SocketListener,A1
move.l A1,$1E(A0) ; listener
lea SocketListener,A2
move.l A2,$1E(A0) ; listener
dc.w $A004 ; _Control
bne.s openFail
move.b $1C(A0),$14(A1) ; save socket number in dCtlStorage
; Prepare a Name Table Entry for NBP
; TODO: replace with static Name Table Entry struct below
@ -53,14 +59,14 @@ DrvrOpen
move.w #253,$1A(A0) ; csCode = registerName
move.b #7,$1C(A0) ; interval = ~1sec
move.b #5,$1D(A0) ; count = 5
lea NTE,A1
move.l A1,$1E(A0) ; entityPtr = our NTE
move.b #0,$22(A0) ; verifyFlag = don't
lea NTE,A2
move.l A2,$1E(A0) ; entityPtr = our NTE
move.b #1,$22(A0) ; verifyFlag = do
dc.w $A004 ; _Control
openFail
move.w $10(A0),D0 ; Just return whatever error we got
move.l (SP)+,A0
movem.l (SP)+,A0-A1
move.w D0,$10(A0)
rts
@ -73,36 +79,252 @@ DrvrClose
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DrvrControl
move.w #-18,$10(A0) ; ioResult
bra DrvrFinish
cmp.w #65,$1A(A0)
beq.s accRun
move.w #-17,$10(A0) ; ioResult = controlErr
rts
accRun
move.w #0,$10(A0) ; ioResult = noErr (never need to return an error)
; figure out the packet
lea ReceivedPacket,A2
move.w (A2)+,D0 ; length
cmp.b #1,(A2)
beq ReplyToUserRecordRequest
cmp.b #3,(A2)
beq ReplyToImageRequest
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PushReturnAddress
clr.l -(SP)
clr.l -(SP)
clr.l -(SP)
clr.l -(SP)
clr.w -(SP)
move.l ReturnAddress,D0
move.b #10,1+15(SP)
move.b D0,1+13(SP)
asr.w #4,D0
asr.w #4,D0
move.b D0,1+11(SP)
swap D0
move.w D0,1+7(SP)
move.l 18(SP),-(SP)
rts
ReplyToUserRecordRequest ; A0=iopb A1=dce A2=pkt
bclr.b #5,4(A1) ; clear dNeedTime: done with this packet
move.l SP,A3
move.w #586/2-1,D0 ; Push the whole packet
clrloop clr.w -(SP)
dbra D0,clrloop
move.w #$0201,(SP) ; user record reply v1
move.w 2(A2),2(SP) ; copy osID
move.l 4(A2),4(SP) ; copy userData (timestamp)
move.w #512,8(SP) ; blockSize
move.w #0,10(SP) ; imageID
move.w #0,12(SP) ; result (error code)
move.l #(EndOfPayload-StartOfPayload+511)>>9,14(SP)
move.l SP,A4
; This code should be deduplicated
bsr PushReturnAddress
lea 1(SP),A5 ; the "odd" base of the address struct
move.w #0,-(SP) ; Push the WriteDataStructure
move.l A4,-(SP)
move.w #586,-(SP)
move.l A5,-(SP) ; the first odd address of the WDS
move.w #16,-(SP)
move.l SP,A4
bsr WriteDDP
move.l A3,SP
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The money shot
; Send as many packets as we can in six ticks
; Also be fairly canny with the bitmap
; Internally: D7=ticks D6=whichblock D5=scratch
ReplyToImageRequest ; A0=iopb A1=dce A2=pkt D0=pktlen
moveq #0,D4
move.w D0,D4
subq #8,D4
asl.l #3,D4
cmp.w #(EndOfPayload-StartOfPayload+511)>>9,D4
blo.s dontsubtract
move.l #(EndOfPayload-StartOfPayload+511)>>9,D4
dontsubtract
move.l $16A,D7 ; Ticks
moveq.l #-1,D6 ; Block counter
blockloop addq.l #1,D6
cmp.w D4,D6
bhs endsend
move.w D6,D5
asr.w #3,D5
bclr.b D6,8(A2,D5.W)
beq.s blockloop
; okay, so I am committed to sending this packet
move.l SP,A3
; This code should be deduplicated
bsr PushReturnAddress
lea 1(SP),A5 ; the "odd" base of the address struct
move.w D6,-(SP) ; blocknum (first chunk of packet)
move.w 2(A2),-(SP) ; image ID
move.w #$0401,-(SP) ; image data v1
move.l SP,A4
move.w #0,-(SP) ; Push the WriteDataStructure
lea StartOfPayload,A0
moveq #0,D5
move.w D6,D5
lsl.l #4,D5
lsl.l #5,D5
add.l D5,A0
move.l A0,-(SP)
move.w #512,-(SP)
move.l A4,-(SP)
move.w #6,-(SP)
move.l A5,-(SP) ; the first odd address of the WDS
move.w #16,-(SP)
move.l SP,A4
bsr WriteDDP
move.l A3,SP
; check whether we need to yield time
move.l $16A,D5
sub.l D7,D5
cmp.l #6,D5
bhi.s defersend
bra blockloop
endsend
bclr.b #5,4(A1) ; clear dNeedTime: done with this packet
defersend
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WriteDDP ; pass in the WDS as a4
move.l A0,-(SP)
lea -$32(SP),SP
move.l SP,A0
move.w $16(A1),$18(A0) ; IORefNum = dctlStorage.low
move.w #246,$1A(A0) ; csCode = writeDDP
clr.l $C(A0) ; IOCompletion = NULL
move.b $14(A1),$1C(A0) ; get socket number from dCtlStorage
move.b #1,$1D(A0) ; set checksumFlag
move.l A4,$1E(A0) ; wdsPointer to our WriteDataStructure
dc.w $A004 ; _Control
lea $32(SP),SP
move.l (SP)+,A0
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DrvrStatus
move.w #-18,$10(A0) ; ioResult
bra DrvrFinish
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Elliot: this can probably be cleaned up, because all our calls are synchronous
DrvrFinish
move.w 6(A0),D1 ; iopb.ioTrap
btst #9,D1 ; noQueueBit
bne.s DrvrNoIoDone
move.l $8FC,-(SP) ; jIODone
DrvrNoIoDone
rts
SocketListener
dc.w $A9FF
; A0 Reserved for internal use by the .MPP driver. You must preserve this register until after the ReadRest routine has completed execution.
; A1 Reserved for internal use by the .MPP driver. You must preserve this register until after the ReadRest routine has completed execution.
; A2 Pointer to the .MPP driver's local variables. Elliot says: the frame and packet header ("RHA") are at offset 1 from A2 (keeps the 2-byte fields aligned)
; A3 Pointer to the first byte in the RHA past the DDP header bytes (the first byte after the DDP protocol type field).
; A4 Pointer to the ReadPacket routine. The ReadRest routine starts 2 bytes after the start of the ReadPacket routine.
; A5 Free for your use before and until your socket listener calls the ReadRest routine.
; D0 Lower byte is the destination socket number of the packet.
; D1 Word indicating the number of bytes in the DDP packet left to be read (that is, the number of bytes following the DDP header).
; D2 Free for your use.
; D3 Free for your use.
; Parse the packet at accRun time
editLeaDCE lea $12345678,A5 ; live-edited to point to DCE
bset.b #5,4(A5) ; raise dNeedTime in dCtlFlags
; Parse the "return address" from the header
cmp.b #1,1+2(A2) ; test DDP header type
bne.s longhdr
shorthdr moveq.l #0,D2 ; network number = 0
move.w 1+1(A2),D2 ; node number
move.b 1+6(A2),D2 ; socket numder
bra.s doneWithHeader
longhdr move.w 1+9(A2),D2 ; network number
swap D2
move.b 1+12(A2),D2 ; node number
asl.w #4,D2
asl.w #4,D2
move.b 1+14(A2),D2 ; socket number
doneWithHeader
; Save the return address in a standard format
lea ReturnAddress,A5
move.l D2,(A5)
; Save the return address and packet body
lea ReceivedPacket,A3
move.w D1,D3 ; odd that I need to use this register?
move.w D3,(A3)+
jmp 2(A4) ; ReadRest (to A3)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MPPString dc.b 4, ".MPP", 0
@ -111,6 +333,9 @@ TypStr dc.b 10, "BootServer", 0
ZonStr dc.b 1, "*"
ReturnAddress dc.l 0
ReceivedPacket dcb.b 2+586
; Names table entry for NBP
PB
@ -198,3 +423,8 @@ MoveAstring
DC.W $A22E ; _BlockMoveData
RTS
align 9
StartOfPayload
incbin "../payload"
EndOfPayload

View File

@ -13,13 +13,18 @@ myDRefNum equ ~myUnitNum
dc.w $A9FF ; _Debugger
noGetResErr
move.l A4,A0
dc.w $A025 ; _GetHandleSize
sub.l D0,$10C ; BufPtr
move.l (A4),A0
move.l $10C,A1
dc.w $A02E ; _BlockMove
move.l A4,-(SP)
dc.w $A992 ; _DetachResource
move.l A4,A0
dc.w $A029 ; _HLock
move.l (A4),A4
move.l $10C,A4
; Install the driver in the unit table
move.l A4,A0

View File

@ -52,15 +52,16 @@ while 1:
elif llap_proto_type == 2:
# ddp, long (what should we do with this extra information?)
if len(data) < 13: continue
ddp_len, ddp_cksum, ddp_dest_net, ddp_src_net, ddp_dest_node, ddp_src_node, ddp_dest_socket, ddp_src_socket = struct.unpack_from('>4H5B', data)
ddp_len, ddp_cksum, ddp_dest_net, ddp_src_net, ddp_dest_node, ddp_src_node, ddp_dest_socket, ddp_src_socket, ddp_proto_type = struct.unpack_from('>4H5B', data)
ddp_hop_count = (ddp_len >> 10) & 0xF
ddp_len &= 0x3FF
data = data[13:ddp_len]
print(ddp_src_net, ddp_dest_net)
else:
# llap control packet -- can probably ignore!
continue
print(f'datagram {llap_src_node}:{ddp_src_socket}->{llap_dest_node}:{ddp_dest_socket}')
print(f'datagram {llap_proto_type} {llap_src_node}:{ddp_src_socket}->{llap_dest_node}:{ddp_dest_socket}')
if ddp_proto_type == 2: # NBP
if len(data) < 2: continue
@ -85,15 +86,23 @@ while 1:
print(f' net:node:sock={t[0]}:{t[1]}:{t[2]} enum={t[3]} object:type@zone={t[4]}:{t[5]}@{t[6]}')
elif ddp_proto_type == 10: # ATBOOT
if len(data) < 2: continue
if len(data) < 2:
print('malformed short packet %r' % data.hex())
continue
boot_type, boot_vers = struct.unpack_from('>BB', data)
data = data[2:]
if boot_type == 1:
print(' ATBOOT "syn"')
if boot_type == 2:
print(' ATBOOT "ack"')
print(' ATBOOT "syn"', data.hex())
elif boot_type == 2:
print(' ATBOOT "ack"', data.hex())
elif boot_type == 3:
print(' ATBOOT image request')
print(' ATBOOT image request', data.hex())
elif boot_type == 4:
print(' ATBOOT image reply')
print(' ATBOOT image reply', data.hex())
else:
print(' ' + data.hex())
else:
print('Totally unknown DDP type', ddp_proto_type)
print(' ' + data.hex())

View File

@ -17,21 +17,16 @@ image: systools607.dsk.a Makefile
Mini\ vMac\ Classic.app/Co*/Ma*/* xo.rom /tmp/system6.dsk
systools607.dsk.a: systools607.dsk
python3 -c 'for b in open("systools607.dsk","rb").read(): print(" dc.b $$%02X" % b)' >systools607.dsk.a
Bootstrap.bin: Bootstrap.a
vasm-1/vasmm68k_mot -quiet -Fbin -pic -o $@ $<
BootstrapFloppy/System.rdump: Bootstrap.bin
rfx cp $< $@//boot/1
BootstrapFloppy.dsk: BootstrapFloppy/System.rdump
MakeHFS -n 'NetBoot Enabler' -i BootstrapFloppy -s 1440k -d now $@
testflop: BootstrapFloppy.dsk
testclient: BootstrapFloppy.dsk
Mini\ vMac\ Classic.app/Co*/Ma*/* xo.rom $<
@ -40,7 +35,17 @@ testflop: BootstrapFloppy.dsk
BootServer.INIT: FORCE
BootWrapper.bin: BootWrapper.a
vasm-1/vasmm68k_mot -quiet -Fbin -pic -o $@ $<
payload: BootWrapper.bin
#echo ' dcb.w 10000, $$A9FF' >/tmp/xasm
#vasm-1/vasmm68k_mot -quiet -Fbin -pic -o /tmp/yasm /tmp/xasm
#cat /tmp/yasm >payload
cat BootWrapper.bin systools607.dsk >payload
python3 snefru_hash.py payload
BootServer.INIT: payload FORCE
./buildapp.bash BootServer
testserver: BootServer.INIT
@ -49,9 +54,12 @@ testserver: BootServer.INIT
DumpHFS systools607.dsk /tmp/bootserv
cp MacsBug\ 6.2.2/* /tmp/bootserv/System\ Folder
cp BootServer.INIT* /tmp/bootserv/System\ Folder
MakeHFS -i /tmp/bootserv -s 1440k bootserv.tmp
MakeHFS -i /tmp/bootserv -s 10m bootserv.tmp
Mini\ vMac\ Classic.app/Co*/Ma*/* xo.rom bootserv.tmp
pyserver: payload FORCE
./NetBoot.py payload

View File

@ -19,32 +19,8 @@ my_unique_ltoudp_id = b'El' + (os.getpid() & 0xFFFF).to_bytes(2, 'big')
disk_image = open(path.join(path.dirname(path.abspath(__file__)), 'systools607.dsk'), 'rb').read()
# Strip the Disk Copy header
if disk_image[0x54:0x56] == b'LK' or disk_image[0x454:0x456] == b'BD':
disk_image = disk_image[0x54:]
print('Stripped Disk Copy header from image')
def assemble(the_code):
with open('/tmp/vasm.bootblocks', 'w') as f:
f.write(the_code)
try:
os.remove('/tmp/vasm.bootblocks.bin')
except FileNotFoundError:
pass
assembler = path.join(path.dirname(path.abspath(__file__)), 'vasm-1/vasmm68k_mot')
os.system(f'{assembler} -quiet -Fbin -pic -o /tmp/vasm.bootblocks.bin /tmp/vasm.bootblocks')
with open('/tmp/vasm.bootblocks.bin', 'rb') as f:
return f.read()
import sys
image = open(sys.argv[1], 'rb').read()
# typedef short (*j_code)( short command, # SP+4 (sign-extend to long)
# DGlobals *g, # SP+8
@ -53,19 +29,6 @@ def assemble(the_code):
# We return our OSErr in d0, and leave the 16 bytes of arguments on the stack for the caller to clean
image = assemble(open(path.join(path.dirname(path.abspath(__file__)), 'BootServer/PROC128.a')).read()) + disk_image
image = bytearray(image)
while len(image) % 512 != 512 - 64: image.append(0)
the_hash = snefru(image)
while len(image) % 512 != 512 - 16: image.append(0)
image.extend(the_hash)
print('Sig:', ''.join(('%02X' % b) for b in image[-16:]))
ANY = "0.0.0.0"
MCAST_ADDR = "239.192.76.84"

View File

@ -1,7 +0,0 @@
#!/bin/bash
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
make BootstrapFloppy.dsk
Mini\ vMac\ Classic.app/Contents/MacOS/minivmac xo.rom BootstrapFloppy.dsk && kill %1

View File

@ -354,8 +354,21 @@ def snefru(inbytes):
if __name__ == '__main__':
import binascii
the_plain = b''.join(n.to_bytes(4, 'big') for n in range(32*1024//4))
the_hash = snefru(the_plain)
import sys
for p in sys.argv[1:]:
try:
x = open(p, 'rb').read()
print(binascii.hexlify(the_hash))
if len(x) % 512 == 0:
maybe_already = snefru(x[:-64])
if x[-16:] == maybe_already: continue
while len(x) % 512 != 512 - 64: x += b'\0'
the_hash = snefru(x)
while len(x) % 512 != 512 - 16: x += b'\0'
x += the_hash
open(p, 'wb').write(x)
except Exception as e:
print(e)

File diff suppressed because it is too large Load Diff