Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / pkg / dhcp / tftp.fth
CommitLineData
920dae64
AT
1\ ========== Copyright Header Begin ==========================================
2\
3\ Hypervisor Software File: tftp.fth
4\
5\ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6\
7\ - Do no alter or remove copyright notices
8\
9\ - Redistribution and use of this software in source and binary forms, with
10\ or without modification, are permitted provided that the following
11\ conditions are met:
12\
13\ - Redistribution of source code must retain the above copyright notice,
14\ this list of conditions and the following disclaimer.
15\
16\ - Redistribution in binary form must reproduce the above copyright notice,
17\ this list of conditions and the following disclaimer in the
18\ documentation and/or other materials provided with the distribution.
19\
20\ Neither the name of Sun Microsystems, Inc. or the names of contributors
21\ may be used to endorse or promote products derived from this software
22\ without specific prior written permission.
23\
24\ This software is provided "AS IS," without a warranty of any kind.
25\ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
26\ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
27\ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
28\ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
29\ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
30\ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
31\ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
32\ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
33\ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
34\ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
35\ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
36\
37\ You acknowledge that this software is not designed, licensed or
38\ intended for use in the design, construction, operation or maintenance of
39\ any nuclear facility.
40\
41\ ========== Copyright Header End ============================================
42id: @(#)tftp.fth 2.24 02/08/22
43purpose: Trivial File Transfer Protocol (TFTP) implementation
44copyright: Copyright 1990-2002 Sun Microsystems, Inc. All Rights Reserved
45copyright: Use is subject to license terms.
46
47\ Trivial File Transfer Protocol
48
49decimal
50
51headerless
52
53d# 128 instance buffer: tftp-file-buf
54instance defer tftp-file
55' tftp-file-buf to tftp-file
56
571 constant rrq-pkt
582 constant wrq-pkt
593 constant data-pkt
604 constant ack-pkt
615 constant err-pkt
62
63struct ( tftp packet )
64 2 field >opcode
65 0 field >block#
66 0 field >filename
67 2 field >errorcode
68 0 field >errmsg
69d# 512 field >data
70constant /tftp-packet
71
72: opcode ( -- ) active-struct@ >opcode ;
73: block# ( -- ) active-struct@ >block# ;
74: filename ( -- ) active-struct@ >filename ;
75: errorcode ( -- ) active-struct@ >errorcode ;
76: errmsg ( -- ) active-struct@ >errmsg ;
77: data ( -- ) active-struct@ >data ;
78
79d# 69 constant UP_TFTP
80
81instance variable sid
82instance variable did
83instance variable this-block
84instance variable #retries
85instance variable #packet
86
87false instance value first-try?
88
89-1 instance value tftp-retries
90
91: too-many-tftp-retries? ( -- flag ) \ flag true if too many retries
92 #retries @ tftp-retries u>=
93;
94
95: .merror ( -- )
96 use-server? use-dhcp @ or if
97 ." TFTP Error: " errmsg dup cstrlen type
98 abort
99 then
100 UP_TFTP did ! \ Unlock from server
101;
102
103: $cstrput ( from-adr,len to-adr -- end-adr )
104 3dup swap move ( from-adr,len to-adr )
105 swap + nip ( end-adr-1 )
106 0 over c! ( end-adr-1 )
107 1+
108;
109
110: setup-request ( file-name-str rrq-pkt/wrq-pkt -- )
111 0 this-block !
112 packet-to-send active-struct !
113 1 sid +!
114 UP_TFTP did ! ( file-name rrq-pkt/wrq-pkt )
115 opcode be-w! ( file-name-str )
116 filename $cstrput ( mode-adr )
117 " octet" rot $cstrput
118 packet-to-send - #packet !
119;
120
121: setup-read-request ( file-name-string -- )
122 rrq-pkt setup-request
123 1 this-block +!
124;
125
126: setup-write-request ( file-name-string -- )
127 wrq-pkt setup-request
128;
129
130: setup-ack-packet ( -- )
131 packet-to-send active-struct !
132 ack-pkt opcode be-w!
133 this-block @ block# be-w!
134 4 #packet !
135 1 this-block +!
136;
137
138: send-packet ( tftp-adr tftp-len -- #sent )
139 did @ his-udp-port !
140 sid @ my-udp-port !
141 ( tftp-adr tftp-len ) prepare-udp-packet ( len )
142 transmit dup 0= if
143 ." TFTP send failed. Check Ethernet cable and transceiver" cr
144 then ( #sent )
145 d# 4000 set-timeout
146;
147
1480 instance value error-packet \ Buffer address
149
150: send-error-packet ( -- )
151 /tftp-packet alloc-mem to error-packet
152 did @ >r
153 udp-source-port be-w@ did ! \ set the udp-source-port to the port indicated
154 \ in the received error packet.
155 error-packet active-struct !
156 err-pkt opcode be-w!
157 5 ( Unknown transfer ID ) errorcode be-w!
158 " Unknown source address" errmsg $cstrput ( end-address )
159 error-packet tuck - ( packet-adr len )
160 send-packet drop
161 r> did ! \ restore the previous did
162 error-packet /tftp-packet free-mem
163;
164
165: unlock-dest-ip-en-addr ( -- )
166 use-server? use-router? use-dhcp @ or or if exit then
167 broadcast-ip-addr his-ip-addr 4 cmove
168 broadcast-en-addr his-en-addr 6 cmove
169;
170
171: lock-dest-ip-en-addr ( -- )
172 active-struct @
173 dup /ip-header - active-struct !
174 ip-source-addr his-ip-addr 4 cmove
175 /ether-header negate active-struct +!
176 en-source-addr his-en-addr 6 cmove
177 active-struct !
178 his-ip-addr server-ip-addr 4 cmove
179;
180
181\ Check source port against destination id.
182\ If it mismatches, error unless did is currently 69
183: bad-src-port? ( -- error ) \ assumes active-struct is udp
184 false
185 udp-source-port be-w@ did @ <> if
186 did @ UP_TFTP = if
187 udp-source-port be-w@ did ! \ Lock onto his port
188 his-ip-addr broadcast-ip-addr? if
189 lock-dest-ip-en-addr \ Lock onto dest ip & ether addresses
190 then
191 else drop true
192 then
193 then
194;
195
196\ Check block number. Assumes active-struct is tftp.
197: bad-block#? ( -- error? ) block# be-w@ this-block @ <> ;
198
199: send-current-packet ( -- #sent ) packet-to-send #packet @ send-packet ;
200
201: receive-tftp-packet ( -- [ tftp-pkt-adr tftp-pkt-len ] flag )
202 begin
203 receive-udp-packet 0= if false exit then ( udp-pkt udp-len )
204 drop active-struct ! ( )
205 udp-dest-port be-w@ sid @ =
206 until
207 bad-src-port? if send-error-packet false exit then
208 active-struct @ /udp-header + ( tftp-pkt-adr )
209 udp-length be-w@ /udp-header - ( tftp-pkt-adr tftp-len )
210 true
211;
212
213: receive-data-packet ( -- [ data-adr data-len ] flag )
214 begin
215 receive-tftp-packet 0= if false exit then ( tftp-adr tftp-len )
216 over active-struct ! ( tftp-adr tftp-len )
217 opcode be-w@ data-pkt <> bad-block#? or
218 while
219 opcode be-w@ err-pkt = if .merror then
220 2drop
221 repeat ( tftp-adr tftp-len )
222 false is first-try?
223 nip data swap 4 - true
224;
225
226: ?try-broadcast ( -- )
227 first-try? if
228 unlock-dest-ip-en-addr
229 \ Relock the destination port number
230 d# 69 did !
231 \ Give the server to come back up. Delay
232 \ re-broadcasting to avoid jaming up the net.
233 #retries @ if 5000 ms then
234 then
235;
236
237: get-data-packet ( adr -- adr' more? )
238 #retries off
239 begin
240 send-current-packet drop
241 receive-data-packet
242 0= while
243 ?try-broadcast
244 1 #retries +!
245 #retries @ d# 10 /mod drop 0= if
246 ." Retrying ... Check TFTP server and network setup" cr
247 then
248 too-many-tftp-retries? if
249 ." TFTP retry count exceeded" cr false exit
250 then
251 repeat
252
253 \ Copy data from packet to our buffer at addr
254 >r over r@ cmove ( adr )
255
256 r@ + ( adr' )
257 r> d# 512 = ( adr' more? )
258;
259
260: need-router? ( -- flag )
261 server-ip-addr be-l@ on-my-net? 0=
262;
263
264: tftp-init ( -- )
265 true is first-try?
266 packet-to-send 0= if
267 /tftp-packet alloc-mem to packet-to-send
268 /udp-pseudo-hdr alloc-mem to udp-pseudo-hdr
269 then
270 get-msecs h# 0ffff and sid ! \ "random" number
271;
272
273: tftp-close ( -- )
274 packet-to-send /tftp-packet free-mem
275 0 to packet-to-send
276 udp-pseudo-hdr /udp-pseudo-hdr free-mem
277 0 to udp-pseudo-hdr
278;
279
280headers
281: tftpread ( adr file-name -- size )
282 tftp-init ( adr file-name )
283 reserve-buffer ( adr file-name )
284 setup-read-request ( adr )
285 dup ( adr adr )
286 begin
287 get-data-packet ( adr adr' more? )
288 while
289 show-progress setup-ack-packet
290 repeat ( adr adr' )
291 \ Send the final acknowledge. Don't send if receive error.
292 too-many-tftp-retries? 0= if
293 setup-ack-packet
294 send-current-packet drop \ ignore errors
295 then
296 swap -
297 release-buffer
298 tftp-close too-many-tftp-retries? if ." tftp failed" abort then
299;
300
301headerless
302
303\ previous definitions
304
305\ *** New routines for tftpwrite ***
306
307: receive-ack-packet ( -- [ ack-packet-adr ack-len ] flag )
308 \ flag is true if good packet. other entries only if flag true
309 receive-tftp-packet ( [ tftp-packet-adr tftp-len ] flag )
310 0= if false exit then ( packet-adr len )
311 over active-struct !
312
313 \ Check packet type
314 opcode be-w@ err-pkt = if .merror 2drop false exit then
315 opcode be-w@ ack-pkt <> if
316 ." Got a non-ack packet" 2drop false exit
317 then
318
319 bad-block#? if 2drop false else nip data swap 4 - true then
320;
321
322: get-ack-packet ( -- ack-received? )
323 #retries off
324 begin
325 send-current-packet
326 receive-ack-packet ( [ ack-packet-adr ack-len ] flag )
327 0= while
328 1 #retries +!
329
330\ XXX we need to be able to retry the whole transaction at a higher
331\ level, so we should exit more gracefully than we do here.
332
333 too-many-tftp-retries? if ." receive failed" false exit then
334 repeat 2drop true
335;
336
337: setup-data-packet ( adr sizeleft -- adr' sizeleft' done? )
338 dup 0< if true exit then
339 packet-to-send active-struct !
340 data-pkt opcode be-w!
341 1 this-block +!
342 this-block @ block# be-w! ( adr sizeleft )
343 2dup d# 512 min ( adr sizeleft adr size<=512 )
344 dup 4 + #packet !
345 data swap cmove
346 d# 512 - \ decrease size remaining
347 swap d# 512 + swap \ adjust addr for remaining data
348 false
349;
350
351headers
352
353: tftpwrite ( adr size file-name -- )
354 tftp-init ( adr size )
355 reserve-buffer ( adr size )
356 setup-write-request ( adr size )
357 begin
358 get-ack-packet if
359 setup-data-packet ( adr' sizeleft' done? )
360 else true \ error exit from loop
361 then
362 until 2drop
363 release-buffer
364 tftp-close
365;