1
1
// SPDX-License-Identifier: MIT OR Apache-2.0
2
2
3
- use uefi:: proto:: network:: snp:: { InterruptStatus , ReceiveFlags , SimpleNetwork } ;
4
- use uefi:: proto:: network:: MacAddress ;
3
+ use crate :: proto:: network:: build_ipv4_udp_packet;
4
+ use alloc:: string:: ToString ;
5
+ use core:: net:: Ipv4Addr ;
6
+ use uefi:: boot:: { OpenProtocolAttributes , OpenProtocolParams } ;
7
+ use uefi:: proto:: device_path:: text:: { AllowShortcuts , DisplayOnly } ;
8
+ use uefi:: proto:: device_path:: DevicePath ;
9
+ use uefi:: proto:: network:: snp:: { InterruptStatus , NetworkState , ReceiveFlags , SimpleNetwork } ;
5
10
use uefi:: { boot, Status } ;
6
11
12
+ fn compute_ipv4_checksum ( header : & [ u8 ] ) -> u16 {
13
+ assert_eq ! ( header. len( ) % 2 , 0 ) ;
14
+ let sum = header
15
+ . chunks ( 2 )
16
+ . map ( |chunk| u16:: from_be_bytes ( [ chunk[ 0 ] , chunk[ 1 ] ] ) as u32 )
17
+ . sum :: < u32 > ( ) ;
18
+
19
+ let carry_add = ( sum & 0xFFFF ) + ( sum >> 16 ) ;
20
+ !( carry_add as u16 )
21
+ }
22
+
23
+ fn build_ipv4_packet_with_payload (
24
+ src_ip : Ipv4Addr ,
25
+ dest_ip : Ipv4Addr ,
26
+ payload : [ u8 ; 2 ] ,
27
+ ) -> [ u8 ; 22 ] {
28
+ let mut packet = [ 0u8 ; 22 ] ;
29
+ let len = packet. len ( ) as u16 ;
30
+
31
+ // IPv4 header
32
+ // Version = 4, IHL = 5
33
+ packet[ 0 ] = 0x45 ;
34
+ // DSCP/ECN
35
+ packet[ 1 ] = 0x00 ;
36
+ // Total length
37
+ packet[ 2 ..4 ] . copy_from_slice ( & ( len. to_be_bytes ( ) ) ) ;
38
+ // Identification
39
+ packet[ 4 ..6 ] . copy_from_slice ( & 0u16 . to_be_bytes ( ) ) ;
40
+ // Flags (DF), Fragment offset
41
+ packet[ 6 ..8 ] . copy_from_slice ( & 0x4000u16 . to_be_bytes ( ) ) ;
42
+ // TTL
43
+ packet[ 8 ] = 0x40 ;
44
+ // Protocol (UDP)
45
+ packet[ 9 ] = 0x11 ;
46
+ // Checksum placeholder at [10..12]
47
+ packet[ 12 ..16 ] . copy_from_slice ( & src_ip. octets ( ) ) ; // Source IP
48
+ packet[ 16 ..20 ] . copy_from_slice ( & dest_ip. octets ( ) ) ; // Destination IP
49
+
50
+ // Calculate checksum
51
+ let checksum = compute_ipv4_checksum ( & packet[ 0 ..20 ] ) ;
52
+ packet[ 10 ..12 ] . copy_from_slice ( & checksum. to_be_bytes ( ) ) ;
53
+
54
+ // Payload
55
+ packet[ 20 ] = payload[ 0 ] ;
56
+ packet[ 21 ] = payload[ 1 ] ;
57
+
58
+ packet
59
+ }
60
+
7
61
pub fn test ( ) {
8
62
info ! ( "Testing the simple network protocol" ) ;
9
63
10
- let handles = boot:: find_handles :: < SimpleNetwork > ( ) . unwrap_or_default ( ) ;
64
+ let handles = boot:: find_handles :: < SimpleNetwork > ( ) . unwrap ( ) ;
11
65
12
66
for handle in handles {
13
- let simple_network = boot:: open_protocol_exclusive :: < SimpleNetwork > ( handle) ;
14
- if simple_network. is_err ( ) {
15
- continue ;
16
- }
17
- let simple_network = simple_network. unwrap ( ) ;
67
+ // Buggy firmware; although it should be there, we have to test if the
68
+ // protocol is actually installed.
69
+ let simple_network = match boot:: open_protocol_exclusive :: < SimpleNetwork > ( handle) {
70
+ Ok ( snp) => snp,
71
+ Err ( e) => {
72
+ log:: debug!( "Handle {handle:?} doesn't actually support SNP; skipping" ) ;
73
+ continue ;
74
+ }
75
+ } ;
76
+ let simple_network_dvp = boot:: open_protocol_exclusive :: < DevicePath > ( handle) . unwrap ( ) ;
77
+ debug ! (
78
+ "Testing network device: {}" ,
79
+ simple_network_dvp
80
+ . to_string( DisplayOnly ( false ) , AllowShortcuts ( false ) )
81
+ . unwrap( )
82
+ ) ;
18
83
19
- // Check shutdown
20
- let res = simple_network. shutdown ( ) ;
21
- assert ! ( res == Ok ( ( ) ) || res == Err ( Status :: NOT_STARTED . into( ) ) ) ;
84
+ // Check media
85
+ assert ! (
86
+ simple_network. mode( ) . media_present && simple_network. mode( ) . media_present_supported
87
+ ) ;
22
88
23
- // Check stop
24
- let res = simple_network . stop ( ) ;
25
- assert ! ( res == Ok ( ( ) ) || res == Err ( Status :: NOT_STARTED . into ( ) ) ) ;
89
+ // Ensure network is not started yet. If it is started, another test
90
+ // didn't clean up properly.
91
+ assert_eq ! ( simple_network . mode ( ) . state , NetworkState :: STOPPED ) ;
26
92
27
93
// Check start
28
94
simple_network
@@ -52,41 +118,32 @@ pub fn test() {
52
118
)
53
119
. expect ( "Failed to set receive filters" ) ;
54
120
55
- // Check media
56
- if !simple_network. mode ( ) . media_present_supported || !simple_network. mode ( ) . media_present {
57
- continue ;
58
- }
59
-
60
- let payload = b"\0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \
61
- \x45 \x00 \
62
- \x00 \x21 \
63
- \x00 \x01 \
64
- \x00 \x00 \
65
- \x10 \
66
- \x11 \
67
- \x07 \x6a \
68
- \xc0 \xa8 \x11 \x0f \
69
- \xc0 \xa8 \x11 \x02 \
70
- \x54 \x45 \
71
- \x54 \x44 \
72
- \x00 \x0d \
73
- \xa9 \xe4 \
74
- \x04 \x01 \x02 \x03 \x04 ";
75
-
76
- let dest_addr = MacAddress ( [ 0xffu8 ; 32 ] ) ;
77
121
assert ! ( !simple_network
78
122
. get_interrupt_status( )
79
123
. unwrap( )
80
124
. contains( InterruptStatus :: TRANSMIT ) ) ;
81
125
82
- // Send the frame
126
+ // Broadcast address (send to self)
127
+ let src_addr = simple_network. mode ( ) . current_address ;
128
+ let dest_addr = simple_network. mode ( ) . broadcast_address ;
129
+ const ETHER_TYPE_IPV4 : u16 = 0x0800 ;
130
+
131
+ // IPv4 can be arbitrary, not used for routing here.
132
+ let src_ip = Ipv4Addr :: new ( 192 , 168 , 17 , 15 ) ;
133
+ let dst_ip = Ipv4Addr :: new ( 192 , 168 , 17 , 2 ) ;
134
+ let src_port = 0x5445 ; // "TE"
135
+ let dst_port = 0x5444 ; // "TD"
136
+ let payload = 0x1337_u16 . to_ne_bytes ( ) ;
137
+ let packet = build_ipv4_udp_packet ( src_ip, dst_ip, src_port, dst_port, & payload) ;
138
+
139
+ // Send the frame to ourselves
83
140
simple_network
84
141
. transmit (
85
142
simple_network. mode ( ) . media_header_size as usize ,
86
- payload ,
87
- None ,
143
+ & packet ,
144
+ Some ( src_addr ) ,
88
145
Some ( dest_addr) ,
89
- Some ( 0x0800 ) ,
146
+ Some ( ETHER_TYPE_IPV4 ) ,
90
147
)
91
148
. expect ( "Failed to transmit frame" ) ;
92
149
@@ -98,21 +155,19 @@ pub fn test() {
98
155
{ }
99
156
100
157
// Attempt to receive a frame
101
- let mut buffer = [ 0u8 ; 1500 ] ;
158
+ let mut recv_buffer = [ 0u8 ; 1500 ] ;
102
159
103
160
info ! ( "Waiting for the reception" ) ;
104
- if simple_network. receive ( & mut buffer , None , None , None , None )
161
+ if simple_network. receive ( & mut recv_buffer , None , None , None , None )
105
162
== Err ( Status :: NOT_READY . into ( ) )
106
163
{
107
164
boot:: stall ( 1_000_000 ) ;
108
165
109
166
simple_network
110
- . receive ( & mut buffer , None , None , None , None )
167
+ . receive ( & mut recv_buffer , None , None , None , None )
111
168
. unwrap ( ) ;
112
169
}
113
170
114
- assert_eq ! ( buffer[ 42 ..47 ] , [ 4 , 4 , 3 , 2 , 1 ] ) ;
115
-
116
171
// Get stats
117
172
let res = simple_network. collect_statistics ( ) ;
118
173
match res {
0 commit comments