diff --git a/ChainBoot.py b/ChainBoot.py index 64728b6..14fab3d 100755 --- a/ChainBoot.py +++ b/ChainBoot.py @@ -10,12 +10,17 @@ import struct import sys import time +import random from snefru_hash import append_snefru +UNRELIABILITY_PERCENT = 1 +def failchance(): + return (random.random() < UNRELIABILITY_PERCENT/100) + my_unique_ltoudp_id = b'El' + (os.getpid() & 0xFFFF).to_bytes(2, 'big') @@ -83,6 +88,11 @@ def mk_ddp(dest_node, dest_socket, src_node, src_socket, proto_type, data): return data +def send(ddp): + if failchance(): return + sock.sendto(ddp, (MCAST_ADDR, MCAST_PORT)) + + def pstring(x): @@ -164,7 +174,7 @@ while 1: # NBP LkUp if len(nbp_tuples) == 1 and nbp_tuples[0][5] == 'BootServer': # Looking for us - sock.sendto(mk_ddp( + send(mk_ddp( dest_node=llap_src_node, dest_socket=ddp_src_socket, src_node=99, src_socket=99, proto_type=2, @@ -176,8 +186,7 @@ while 1: 0, # (My) Enumerator (i.e. which of many possible names for 99/99 is this?) ) + pstring(nbp_tuples[0][4]) + pstring('BootServer') + pstring('*') - ), - (MCAST_ADDR, MCAST_PORT)) + )) elif ddp_proto_type == 10: # Mysterious ATBOOT protocol @@ -234,13 +243,12 @@ while 1: # }BootPktRply; # Ignore the silly user record. Just make the fucker work! - sock.sendto(mk_ddp( + send(mk_ddp( dest_node=llap_src_node, dest_socket=ddp_src_socket, src_node=99, src_socket=99, proto_type=10, data=struct.pack('>BBHLHHhL', 2, 1, boot_machine_id, boot_timestamp, 512, 0, 0, len(image) // 512).ljust(586, b'\0') - ), - (MCAST_ADDR, MCAST_PORT)) + )) elif boot_type == 3: # It seems to want part of the boot image! @@ -274,13 +282,12 @@ while 1: # } BootBlock,*BootBlockPtr; # print(f' {blocknum}', end='', flush=True) - sock.sendto(mk_ddp( + send(mk_ddp( dest_node=llap_src_node, dest_socket=ddp_src_socket, src_node=99, src_socket=99, proto_type=10, data=struct.pack('>BBHH', 4, 1, boot_image_id, blocknum) + image[blocknum*512:blocknum*512+512] - ), - (MCAST_ADDR, MCAST_PORT)) + )) # time.sleep(0.5) # break # wait for another request, you mofo! @@ -291,13 +298,12 @@ while 1: boot_imgname = boot_imgname.decode('mac_roman') for blk in range(boot_blkoffset, boot_blkoffset + boot_blkcnt): thisblk = writable_image[blk*512:blk*512+512] - sock.sendto(mk_ddp( + send(mk_ddp( dest_node=llap_src_node, dest_socket=ddp_src_socket, src_node=99, src_socket=99, proto_type=10, data=struct.pack('>BBH', 129, blk-boot_blkoffset, boot_seq) + thisblk - ), - (MCAST_ADDR, MCAST_PORT)) + )) elif boot_type == 130: boot_type, blk, seq, boot_imgnum, hunk_start = struct.unpack_from('>BBHLL', whole_data) @@ -312,13 +318,12 @@ while 1: del buf[(blk % 32) * 512 + 512:] writable_image[hunk_start*512:hunk_start*512+len(buf)] = buf - sock.sendto(mk_ddp( + send(mk_ddp( dest_node=llap_src_node, dest_socket=ddp_src_socket, src_node=99, src_socket=99, proto_type=10, data=struct.pack('>BBH', 131, 0, seq) - ), - (MCAST_ADDR, MCAST_PORT)) + )) else: print(f'ATBOOT type={boot_type} vers={boot_vers} contents={repr(data)}') diff --git a/ChainLoader.a b/ChainLoader.a index 7561e6f..cfd1734 100644 --- a/ChainLoader.a +++ b/ChainLoader.a @@ -1,4 +1,6 @@ kUserRecLen equ 568 +kInitialWaitMsec equ 10000 +kSubsequentWaitMsec equ 1000 Code @@ -185,6 +187,12 @@ gSaveAddr dcb.b 16 gAddr dcb.b 16 even +; Time Manager task +tmLink dc.l 0 +tmType dc.w 0 +tmAddr dc.l 0 +tmCount dc.l 0 + ; Drive queue element dqFlags dc.l $00080000 dqLink dc.l 0 @@ -231,8 +239,20 @@ DrvrPrime ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DrvrReSendRead +; Time Manager task + lea tmLink,A0 + dc.w $A059 ; _RmvTime + + move.l gMyDCE,A1 ; get Device Mgr registers + move.l 6+2(A1),A0 + + ; truncate ioActCount + and.l #-32*512,$28(A0) ; truncate ioActCount + DrvrSendRead -; Called from Prime routine or socket listener: PB/DCE in A0/A1 must be preserved (but we only require A0) +; Called from Prime routine, socket listener or Time Manager: +; PB/DCE in A0/A1 must be preserved (but we only require A0) lea gExpectHdr,A2 clr.w (A2)+ addq.w #1,(A2) ; packet filter sequence word @@ -294,15 +314,38 @@ DrvrCopyAddrStruct DrvrDidSendRead ; Called as completion routine: PB/result in A0/D0, must preserve all registers other than A0/A1/D0-D2 - lea gExpectHdr,A2 - move.w #$8100,(A2) ; Enable packet reception + lea gExpectHdr,A0 + move.w #$8100,(A0) ; Enable packet reception + move.l #kInitialWaitMsec,D0 - rts ; TODO: set up a timeout/retry task +DrvrInstallReSendRead +; Called from anywhere, D0=waittime, can clobber anything + lea tmLink,A0 + pea DrvrReSendRead + move.l (SP)+,tmAddr-tmLink(A0) + move.l D0,-(SP) + dc.w $A058 ; _InsTime + move.l (SP)+,D0 + dc.w $A05A ; _PrimeTime + rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +DrvrReSendWrite +; Time Manager task + lea tmLink,A0 + dc.w $A059 ; _RmvTime + + move.l gMyDCE,A1 ; get Device Mgr registers + move.l 6+2(A1),A0 + + ; truncate ioActCount + sub.l #512,$28(A0) + and.l #-32*512,$28(A0) ; truncate ioActCount + DrvrSendWrite -; Called from Prime routine or socket listener: PB/DCE in A0/A1 must be preserved (but we only require A0) +; Called from Prime routine, socket listener or Time Manager: +; PB/DCE in A0/A1 must be preserved (but we only require A0) ; D1 = block index within chunk move.l $28(A0),D1 @@ -329,7 +372,7 @@ DrvrSendWrite addq.w #1,(A2) ; packet filter sequence word .notFirstBlockOfChunk - bsr.s DrvrCopyAddrStruct + bsr DrvrCopyAddrStruct lea gQuery,A2 move.b #$82,(A2)+ ; Means a polite request @@ -381,13 +424,19 @@ DrvrDidSendWrite ; completion routine for the above control call.. move.l D1,$28(A0) cmp.l D0,D1 - beq.s .sentAllOfChunk + beq.s DrvrInstallReSendWrite and.l #(32-1)*512,D0 - beq.s .sentAllOfChunk + beq.s DrvrInstallReSendWrite bra DrvrSendWrite -.sentAllOfChunk - rts ; TODO: set up a timeout/retry task +DrvrInstallReSendWrite + lea tmLink,A0 + pea DrvrReSendWrite + move.l (SP)+,tmAddr-tmLink(A0) + dc.w $A058 ; _InsTime + move.l #kInitialWaitMsec,D0 + dc.w $A05A ; _PrimeTime + rts DrvrClearBlock move.w #$32/2-1,D0 @@ -463,6 +512,11 @@ DrvrSockListener clr.b D3 bne DrvrTrashPacket + movem.l A0-A1/D0-D2,-(SP) + lea tmLink,A0 + dc.w $A059 ; _RmvTime + movem.l (SP)+,A0-A1/D0-D2 + btst #25,D2 bne.s DrvrDidReceiveWrite @@ -506,7 +560,8 @@ DrvrDidReceiveRead addq.l #1,D1 ; If bitmap=$FFFFFFFF then get the next chunk of 32 beq DrvrSendRead ; A0 must be the PB - rts ; Just return to await more packets. + move.l #kSubsequentWaitMsec,D0 + bra DrvrInstallReSendRead ; Just return to await more packets. DrvrDidReceiveWrite moveq.l #0,D3