mirror of
https://github.com/elliotnunn/NetBoot.git
synced 2024-07-27 11:29:05 +00:00
Basic dropped-packet tolerance
This commit is contained in:
parent
c16fa09c3d
commit
5c97e31336
35
ChainBoot.py
35
ChainBoot.py
@ -10,12 +10,17 @@ import struct
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
import random
|
||||||
|
|
||||||
from snefru_hash import append_snefru
|
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')
|
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
|
return data
|
||||||
|
|
||||||
|
def send(ddp):
|
||||||
|
if failchance(): return
|
||||||
|
sock.sendto(ddp, (MCAST_ADDR, MCAST_PORT))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def pstring(x):
|
def pstring(x):
|
||||||
@ -164,7 +174,7 @@ while 1:
|
|||||||
# NBP LkUp
|
# NBP LkUp
|
||||||
|
|
||||||
if len(nbp_tuples) == 1 and nbp_tuples[0][5] == 'BootServer': # Looking for us
|
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,
|
dest_node=llap_src_node, dest_socket=ddp_src_socket,
|
||||||
src_node=99, src_socket=99,
|
src_node=99, src_socket=99,
|
||||||
proto_type=2,
|
proto_type=2,
|
||||||
@ -176,8 +186,7 @@ while 1:
|
|||||||
0, # (My) Enumerator (i.e. which of many possible names for 99/99 is this?)
|
0, # (My) Enumerator (i.e. which of many possible names for 99/99 is this?)
|
||||||
) +
|
) +
|
||||||
pstring(nbp_tuples[0][4]) + pstring('BootServer') + pstring('*')
|
pstring(nbp_tuples[0][4]) + pstring('BootServer') + pstring('*')
|
||||||
),
|
))
|
||||||
(MCAST_ADDR, MCAST_PORT))
|
|
||||||
|
|
||||||
elif ddp_proto_type == 10:
|
elif ddp_proto_type == 10:
|
||||||
# Mysterious ATBOOT protocol
|
# Mysterious ATBOOT protocol
|
||||||
@ -234,13 +243,12 @@ while 1:
|
|||||||
# }BootPktRply;
|
# }BootPktRply;
|
||||||
|
|
||||||
# Ignore the silly user record. Just make the fucker work!
|
# 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,
|
dest_node=llap_src_node, dest_socket=ddp_src_socket,
|
||||||
src_node=99, src_socket=99,
|
src_node=99, src_socket=99,
|
||||||
proto_type=10,
|
proto_type=10,
|
||||||
data=struct.pack('>BBHLHHhL', 2, 1, boot_machine_id, boot_timestamp, 512, 0, 0, len(image) // 512).ljust(586, b'\0')
|
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:
|
elif boot_type == 3:
|
||||||
# It seems to want part of the boot image!
|
# It seems to want part of the boot image!
|
||||||
@ -274,13 +282,12 @@ while 1:
|
|||||||
# } BootBlock,*BootBlockPtr;
|
# } BootBlock,*BootBlockPtr;
|
||||||
|
|
||||||
# print(f' {blocknum}', end='', flush=True)
|
# print(f' {blocknum}', end='', flush=True)
|
||||||
sock.sendto(mk_ddp(
|
send(mk_ddp(
|
||||||
dest_node=llap_src_node, dest_socket=ddp_src_socket,
|
dest_node=llap_src_node, dest_socket=ddp_src_socket,
|
||||||
src_node=99, src_socket=99,
|
src_node=99, src_socket=99,
|
||||||
proto_type=10,
|
proto_type=10,
|
||||||
data=struct.pack('>BBHH', 4, 1, boot_image_id, blocknum) + image[blocknum*512:blocknum*512+512]
|
data=struct.pack('>BBHH', 4, 1, boot_image_id, blocknum) + image[blocknum*512:blocknum*512+512]
|
||||||
),
|
))
|
||||||
(MCAST_ADDR, MCAST_PORT))
|
|
||||||
|
|
||||||
# time.sleep(0.5)
|
# time.sleep(0.5)
|
||||||
# break # wait for another request, you mofo!
|
# break # wait for another request, you mofo!
|
||||||
@ -291,13 +298,12 @@ while 1:
|
|||||||
boot_imgname = boot_imgname.decode('mac_roman')
|
boot_imgname = boot_imgname.decode('mac_roman')
|
||||||
for blk in range(boot_blkoffset, boot_blkoffset + boot_blkcnt):
|
for blk in range(boot_blkoffset, boot_blkoffset + boot_blkcnt):
|
||||||
thisblk = writable_image[blk*512:blk*512+512]
|
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,
|
dest_node=llap_src_node, dest_socket=ddp_src_socket,
|
||||||
src_node=99, src_socket=99,
|
src_node=99, src_socket=99,
|
||||||
proto_type=10,
|
proto_type=10,
|
||||||
data=struct.pack('>BBH', 129, blk-boot_blkoffset, boot_seq) + thisblk
|
data=struct.pack('>BBH', 129, blk-boot_blkoffset, boot_seq) + thisblk
|
||||||
),
|
))
|
||||||
(MCAST_ADDR, MCAST_PORT))
|
|
||||||
|
|
||||||
elif boot_type == 130:
|
elif boot_type == 130:
|
||||||
boot_type, blk, seq, boot_imgnum, hunk_start = struct.unpack_from('>BBHLL', whole_data)
|
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:]
|
del buf[(blk % 32) * 512 + 512:]
|
||||||
writable_image[hunk_start*512:hunk_start*512+len(buf)] = buf
|
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,
|
dest_node=llap_src_node, dest_socket=ddp_src_socket,
|
||||||
src_node=99, src_socket=99,
|
src_node=99, src_socket=99,
|
||||||
proto_type=10,
|
proto_type=10,
|
||||||
data=struct.pack('>BBH', 131, 0, seq)
|
data=struct.pack('>BBH', 131, 0, seq)
|
||||||
),
|
))
|
||||||
(MCAST_ADDR, MCAST_PORT))
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(f'ATBOOT type={boot_type} vers={boot_vers} contents={repr(data)}')
|
print(f'ATBOOT type={boot_type} vers={boot_vers} contents={repr(data)}')
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
kUserRecLen equ 568
|
kUserRecLen equ 568
|
||||||
|
kInitialWaitMsec equ 10000
|
||||||
|
kSubsequentWaitMsec equ 1000
|
||||||
|
|
||||||
Code
|
Code
|
||||||
|
|
||||||
@ -185,6 +187,12 @@ gSaveAddr dcb.b 16
|
|||||||
gAddr dcb.b 16
|
gAddr dcb.b 16
|
||||||
even
|
even
|
||||||
|
|
||||||
|
; Time Manager task
|
||||||
|
tmLink dc.l 0
|
||||||
|
tmType dc.w 0
|
||||||
|
tmAddr dc.l 0
|
||||||
|
tmCount dc.l 0
|
||||||
|
|
||||||
; Drive queue element
|
; Drive queue element
|
||||||
dqFlags dc.l $00080000
|
dqFlags dc.l $00080000
|
||||||
dqLink dc.l 0
|
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
|
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
|
lea gExpectHdr,A2
|
||||||
clr.w (A2)+
|
clr.w (A2)+
|
||||||
addq.w #1,(A2) ; packet filter sequence word
|
addq.w #1,(A2) ; packet filter sequence word
|
||||||
@ -294,15 +314,38 @@ DrvrCopyAddrStruct
|
|||||||
|
|
||||||
DrvrDidSendRead
|
DrvrDidSendRead
|
||||||
; Called as completion routine: PB/result in A0/D0, must preserve all registers other than A0/A1/D0-D2
|
; Called as completion routine: PB/result in A0/D0, must preserve all registers other than A0/A1/D0-D2
|
||||||
lea gExpectHdr,A2
|
lea gExpectHdr,A0
|
||||||
move.w #$8100,(A2) ; Enable packet reception
|
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
|
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
|
; D1 = block index within chunk
|
||||||
move.l $28(A0),D1
|
move.l $28(A0),D1
|
||||||
@ -329,7 +372,7 @@ DrvrSendWrite
|
|||||||
addq.w #1,(A2) ; packet filter sequence word
|
addq.w #1,(A2) ; packet filter sequence word
|
||||||
.notFirstBlockOfChunk
|
.notFirstBlockOfChunk
|
||||||
|
|
||||||
bsr.s DrvrCopyAddrStruct
|
bsr DrvrCopyAddrStruct
|
||||||
|
|
||||||
lea gQuery,A2
|
lea gQuery,A2
|
||||||
move.b #$82,(A2)+ ; Means a polite request
|
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)
|
move.l D1,$28(A0)
|
||||||
|
|
||||||
cmp.l D0,D1
|
cmp.l D0,D1
|
||||||
beq.s .sentAllOfChunk
|
beq.s DrvrInstallReSendWrite
|
||||||
and.l #(32-1)*512,D0
|
and.l #(32-1)*512,D0
|
||||||
beq.s .sentAllOfChunk
|
beq.s DrvrInstallReSendWrite
|
||||||
bra DrvrSendWrite
|
bra DrvrSendWrite
|
||||||
|
|
||||||
.sentAllOfChunk
|
DrvrInstallReSendWrite
|
||||||
rts ; TODO: set up a timeout/retry task
|
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
|
DrvrClearBlock
|
||||||
move.w #$32/2-1,D0
|
move.w #$32/2-1,D0
|
||||||
@ -463,6 +512,11 @@ DrvrSockListener
|
|||||||
clr.b D3
|
clr.b D3
|
||||||
bne DrvrTrashPacket
|
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
|
btst #25,D2
|
||||||
bne.s DrvrDidReceiveWrite
|
bne.s DrvrDidReceiveWrite
|
||||||
|
|
||||||
@ -506,7 +560,8 @@ DrvrDidReceiveRead
|
|||||||
addq.l #1,D1 ; If bitmap=$FFFFFFFF then get the next chunk of 32
|
addq.l #1,D1 ; If bitmap=$FFFFFFFF then get the next chunk of 32
|
||||||
beq DrvrSendRead ; A0 must be the PB
|
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
|
DrvrDidReceiveWrite
|
||||||
moveq.l #0,D3
|
moveq.l #0,D3
|
||||||
|
Loading…
Reference in New Issue
Block a user