1 //! Simple Network Protocol 2 //! 3 //! Provides a packet level interface to a network adapter. 4 //! Once the adapter is initialized, the protocol provides services that allows 5 //! packets to be transmitted and received. 6 //! 7 //! No interface function must be called until `SimpleNetwork.start` is successfully 8 //! called first. 9 10 use super::{IpAddress, MacAddress}; 11 use crate::data_types::Event; 12 use crate::proto::unsafe_protocol; 13 use crate::{Result, Status, StatusExt}; 14 use bitflags::bitflags; 15 use core::ffi::c_void; 16 use core::ptr; 17 use core::ptr::NonNull; 18 19 /// The Simple Network Protocol 20 #[derive(Debug)] 21 #[repr(C)] 22 #[unsafe_protocol("a19832b9-ac25-11d3-9a2d-0090273fc14d")] 23 pub struct SimpleNetwork { 24 revision: u64, 25 start: extern "efiapi" fn(this: &Self) -> Status, 26 stop: extern "efiapi" fn(this: &Self) -> Status, 27 initialize: extern "efiapi" fn( 28 this: &Self, 29 extra_recv_buffer_size: usize, 30 extra_transmit_buffer_size: usize, 31 ) -> Status, 32 reset: extern "efiapi" fn(this: &Self, extended_verification: bool) -> Status, 33 shutdown: extern "efiapi" fn(this: &Self) -> Status, 34 receive_filters: extern "efiapi" fn( 35 this: &Self, 36 enable: u32, 37 disable: u32, 38 reset_mcast_filter: bool, 39 mcast_filter_count: usize, 40 mcast_filter: Option<NonNull<MacAddress>>, 41 ) -> Status, 42 station_address: 43 extern "efiapi" fn(this: &Self, reset: bool, new: Option<&MacAddress>) -> Status, 44 statistics: extern "efiapi" fn( 45 this: &Self, 46 reset: bool, 47 stats_size: Option<&mut usize>, 48 stats_table: Option<&mut NetworkStats>, 49 ) -> Status, 50 mcast_ip_to_mac: 51 extern "efiapi" fn(this: &Self, ipv6: bool, ip: &IpAddress, mac: &mut MacAddress) -> Status, 52 nv_data: extern "efiapi" fn( 53 this: &Self, 54 read_write: bool, 55 offset: usize, 56 buffer_size: usize, 57 buffer: *mut c_void, 58 ) -> Status, 59 get_status: extern "efiapi" fn( 60 this: &Self, 61 interrupt_status: Option<&mut InterruptStatus>, 62 tx_buf: Option<&mut *mut c_void>, 63 ) -> Status, 64 transmit: extern "efiapi" fn( 65 this: &Self, 66 header_size: usize, 67 buffer_size: usize, 68 buffer: *const c_void, 69 src_addr: Option<&MacAddress>, 70 dest_addr: Option<&MacAddress>, 71 protocol: Option<&u16>, 72 ) -> Status, 73 receive: extern "efiapi" fn( 74 this: &Self, 75 header_size: Option<&mut usize>, 76 buffer_size: &mut usize, 77 buffer: *mut c_void, 78 src_addr: Option<&mut MacAddress>, 79 dest_addr: Option<&mut MacAddress>, 80 protocol: Option<&mut u16>, 81 ) -> Status, 82 // On QEMU, this event seems to never fire. 83 wait_for_packet: Event, 84 mode: *const NetworkMode, 85 } 86 87 impl SimpleNetwork { 88 /// Change the state of a network from "Stopped" to "Started". start(&self) -> Result89 pub fn start(&self) -> Result { 90 (self.start)(self).to_result() 91 } 92 93 /// Change the state of a network interface from "Started" to "Stopped". stop(&self) -> Result94 pub fn stop(&self) -> Result { 95 (self.stop)(self).to_result() 96 } 97 98 /// Reset a network adapter and allocate the transmit and receive buffers 99 /// required by the network interface; optionally, also request allocation of 100 /// additional transmit and receive buffers. initialize(&self, extra_rx_buffer_size: usize, extra_tx_buffer_size: usize) -> Result101 pub fn initialize(&self, extra_rx_buffer_size: usize, extra_tx_buffer_size: usize) -> Result { 102 (self.initialize)(self, extra_rx_buffer_size, extra_tx_buffer_size).to_result() 103 } 104 105 /// Reset a network adapter and reinitialize it with the parameters that were 106 /// provided in the previous call to `initialize`. reset(&self, extended_verification: bool) -> Result107 pub fn reset(&self, extended_verification: bool) -> Result { 108 (self.reset)(self, extended_verification).to_result() 109 } 110 111 /// Reset a network adapter, leaving it in a state that is safe 112 /// for another driver to initialize shutdown(&self) -> Result113 pub fn shutdown(&self) -> Result { 114 (self.shutdown)(self).to_result() 115 } 116 117 /// Manage the multicast receive filters of a network. receive_filters( &self, enable: ReceiveFlags, disable: ReceiveFlags, reset_mcast_filter: bool, mcast_filter: Option<&[MacAddress]>, ) -> Result118 pub fn receive_filters( 119 &self, 120 enable: ReceiveFlags, 121 disable: ReceiveFlags, 122 reset_mcast_filter: bool, 123 mcast_filter: Option<&[MacAddress]>, 124 ) -> Result { 125 if let Some(mcast_filter) = mcast_filter { 126 (self.receive_filters)( 127 self, 128 enable.bits(), 129 disable.bits(), 130 reset_mcast_filter, 131 mcast_filter.len(), 132 NonNull::new(mcast_filter.as_ptr() as *mut _), 133 ) 134 .to_result() 135 } else { 136 (self.receive_filters)( 137 self, 138 enable.bits(), 139 disable.bits(), 140 reset_mcast_filter, 141 0, 142 None, 143 ) 144 .to_result() 145 } 146 } 147 148 /// Modify or reset the current station address, if supported. station_address(&self, reset: bool, new: Option<&MacAddress>) -> Result149 pub fn station_address(&self, reset: bool, new: Option<&MacAddress>) -> Result { 150 (self.station_address)(self, reset, new).to_result() 151 } 152 153 /// Reset statistics on a network interface. reset_statistics(&self) -> Result154 pub fn reset_statistics(&self) -> Result { 155 (self.statistics)(self, true, None, None).to_result() 156 } 157 158 /// Collect statistics on a network interface. collect_statistics(&self) -> Result<NetworkStats>159 pub fn collect_statistics(&self) -> Result<NetworkStats> { 160 let mut stats_table: NetworkStats = Default::default(); 161 let mut stats_size = core::mem::size_of::<NetworkStats>(); 162 let status = (self.statistics)(self, false, Some(&mut stats_size), Some(&mut stats_table)); 163 status.to_result_with_val(|| stats_table) 164 } 165 166 /// Convert a multicast IP address to a multicast HW MAC Address. mcast_ip_to_mac(&self, ipv6: bool, ip: IpAddress) -> Result<MacAddress>167 pub fn mcast_ip_to_mac(&self, ipv6: bool, ip: IpAddress) -> Result<MacAddress> { 168 let mut mac_address = MacAddress([0; 32]); 169 let status = (self.mcast_ip_to_mac)(self, ipv6, &ip, &mut mac_address); 170 status.to_result_with_val(|| mac_address) 171 } 172 173 /// Perform read operations on the NVRAM device attached to 174 /// a network interface. read_nv_data(&self, offset: usize, buffer: &[u8]) -> Result175 pub fn read_nv_data(&self, offset: usize, buffer: &[u8]) -> Result { 176 (self.nv_data)( 177 self, 178 true, 179 offset, 180 buffer.len(), 181 buffer.as_ptr() as *mut c_void, 182 ) 183 .to_result() 184 } 185 186 /// Perform write operations on the NVRAM device attached to a network interface. write_nv_data(&self, offset: usize, buffer: &mut [u8]) -> Result187 pub fn write_nv_data(&self, offset: usize, buffer: &mut [u8]) -> Result { 188 (self.nv_data)( 189 self, 190 false, 191 offset, 192 buffer.len(), 193 buffer.as_mut_ptr().cast(), 194 ) 195 .to_result() 196 } 197 198 /// Read the current interrupt status and recycled transmit buffer 199 /// status from a network interface. get_interrupt_status(&self) -> Result<InterruptStatus>200 pub fn get_interrupt_status(&self) -> Result<InterruptStatus> { 201 let mut interrupt_status = InterruptStatus::empty(); 202 let status = (self.get_status)(self, Some(&mut interrupt_status), None); 203 status.to_result_with_val(|| interrupt_status) 204 } 205 206 /// Read the current recycled transmit buffer status from a 207 /// network interface. get_recycled_transmit_buffer_status(&self) -> Result<Option<NonNull<u8>>>208 pub fn get_recycled_transmit_buffer_status(&self) -> Result<Option<NonNull<u8>>> { 209 let mut tx_buf: *mut c_void = ptr::null_mut(); 210 let status = (self.get_status)(self, None, Some(&mut tx_buf)); 211 status.to_result_with_val(|| NonNull::new(tx_buf.cast())) 212 } 213 214 /// Place a packet in the transmit queue of a network interface. transmit( &self, header_size: usize, buffer: &[u8], src_addr: Option<MacAddress>, dest_addr: Option<MacAddress>, protocol: Option<u16>, ) -> Result215 pub fn transmit( 216 &self, 217 header_size: usize, 218 buffer: &[u8], 219 src_addr: Option<MacAddress>, 220 dest_addr: Option<MacAddress>, 221 protocol: Option<u16>, 222 ) -> Result { 223 (self.transmit)( 224 self, 225 header_size, 226 buffer.len() + header_size, 227 buffer.as_ptr().cast(), 228 src_addr.as_ref(), 229 dest_addr.as_ref(), 230 protocol.as_ref(), 231 ) 232 .to_result() 233 } 234 235 /// Receive a packet from a network interface. 236 /// 237 /// On success, returns the size of bytes of the received packet. receive( &self, buffer: &mut [u8], header_size: Option<&mut usize>, src_addr: Option<&mut MacAddress>, dest_addr: Option<&mut MacAddress>, protocol: Option<&mut u16>, ) -> Result<usize>238 pub fn receive( 239 &self, 240 buffer: &mut [u8], 241 header_size: Option<&mut usize>, 242 src_addr: Option<&mut MacAddress>, 243 dest_addr: Option<&mut MacAddress>, 244 protocol: Option<&mut u16>, 245 ) -> Result<usize> { 246 let mut buffer_size = buffer.len(); 247 let status = (self.receive)( 248 self, 249 header_size, 250 &mut buffer_size, 251 buffer.as_mut_ptr().cast(), 252 src_addr, 253 dest_addr, 254 protocol, 255 ); 256 status.to_result_with_val(|| buffer_size) 257 } 258 259 /// Event that fires once a packet is available to be received. 260 /// 261 /// On QEMU, this event seems to never fire; it is suggested to verify that your implementation 262 /// of UEFI properly implements this event before using it. 263 #[must_use] wait_for_packet(&self) -> &Event264 pub const fn wait_for_packet(&self) -> &Event { 265 &self.wait_for_packet 266 } 267 268 /// Returns a reference to the Simple Network mode. 269 #[must_use] mode(&self) -> &NetworkMode270 pub const fn mode(&self) -> &NetworkMode { 271 unsafe { &*self.mode } 272 } 273 } 274 275 bitflags! { 276 /// Flags to pass to receive_filters to enable/disable reception of some kinds of packets. 277 #[repr(transparent)] 278 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] 279 pub struct ReceiveFlags : u32 { 280 /// Receive unicast packets. 281 const UNICAST = 0x01; 282 /// Receive multicast packets. 283 const MULTICAST = 0x02; 284 /// Receive broadcast packets. 285 const BROADCAST = 0x04; 286 /// Receive packets in promiscuous mode. 287 const PROMISCUOUS = 0x08; 288 /// Receive packets in promiscuous multicast mode. 289 const PROMISCUOUS_MULTICAST = 0x10; 290 } 291 } 292 293 bitflags! { 294 /// Flags returned by get_interrupt_status to indicate which interrupts have fired on the 295 /// interface since the last call. 296 #[repr(transparent)] 297 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] 298 pub struct InterruptStatus : u32 { 299 /// Packet received. 300 const RECEIVE = 0x01; 301 /// Packet transmitted. 302 const TRANSMIT = 0x02; 303 /// Command interrupt fired. 304 const COMMAND = 0x04; 305 /// Software interrupt fired. 306 const SOFTWARE = 0x08; 307 } 308 } 309 310 /// Network Statistics 311 /// 312 /// The description of statistics on the network with the SNP's `statistics` function 313 /// is returned in this structure 314 /// 315 /// Any of these statistics may or may not be available on the device. So, all the 316 /// retriever functions of the statistics return `None` when a statistic is not supported 317 #[repr(C)] 318 #[derive(Default, Debug)] 319 pub struct NetworkStats { 320 rx_total_frames: u64, 321 rx_good_frames: u64, 322 rx_undersize_frames: u64, 323 rx_oversize_frames: u64, 324 rx_dropped_frames: u64, 325 rx_unicast_frames: u64, 326 rx_broadcast_frames: u64, 327 rx_multicast_frames: u64, 328 rx_crc_error_frames: u64, 329 rx_total_bytes: u64, 330 tx_total_frames: u64, 331 tx_good_frames: u64, 332 tx_undersize_frames: u64, 333 tx_oversize_frames: u64, 334 tx_dropped_frames: u64, 335 tx_unicast_frames: u64, 336 tx_broadcast_frames: u64, 337 tx_multicast_frames: u64, 338 tx_crc_error_frames: u64, 339 tx_total_bytes: u64, 340 collisions: u64, 341 unsupported_protocol: u64, 342 rx_duplicated_frames: u64, 343 rx_decrypt_error_frames: u64, 344 tx_error_frames: u64, 345 tx_retry_frames: u64, 346 } 347 348 impl NetworkStats { 349 /// Any statistic value of -1 is not available available(&self, stat: u64) -> bool350 const fn available(&self, stat: u64) -> bool { 351 stat as i64 != -1 352 } 353 354 /// Takes a statistic and converts it to an option 355 /// 356 /// When the statistic is not available, `None` is returned to_option(&self, stat: u64) -> Option<u64>357 const fn to_option(&self, stat: u64) -> Option<u64> { 358 match self.available(stat) { 359 true => Some(stat), 360 false => None, 361 } 362 } 363 364 /// The total number of frames received, including error frames 365 /// and dropped frames 366 #[must_use] rx_total_frames(&self) -> Option<u64>367 pub const fn rx_total_frames(&self) -> Option<u64> { 368 self.to_option(self.rx_total_frames) 369 } 370 371 /// The total number of good frames received and copied 372 /// into receive buffers 373 #[must_use] rx_good_frames(&self) -> Option<u64>374 pub const fn rx_good_frames(&self) -> Option<u64> { 375 self.to_option(self.rx_good_frames) 376 } 377 378 /// The number of frames below the minimum length for the 379 /// communications device 380 #[must_use] rx_undersize_frames(&self) -> Option<u64>381 pub const fn rx_undersize_frames(&self) -> Option<u64> { 382 self.to_option(self.rx_undersize_frames) 383 } 384 385 /// The number of frames longer than the maximum length for 386 /// the communications length device 387 #[must_use] rx_oversize_frames(&self) -> Option<u64>388 pub const fn rx_oversize_frames(&self) -> Option<u64> { 389 self.to_option(self.rx_oversize_frames) 390 } 391 392 /// The number of valid frames that were dropped because 393 /// the receive buffers were full 394 #[must_use] rx_dropped_frames(&self) -> Option<u64>395 pub const fn rx_dropped_frames(&self) -> Option<u64> { 396 self.to_option(self.rx_dropped_frames) 397 } 398 399 /// The number of valid unicast frames received and not dropped 400 #[must_use] rx_unicast_frames(&self) -> Option<u64>401 pub const fn rx_unicast_frames(&self) -> Option<u64> { 402 self.to_option(self.rx_unicast_frames) 403 } 404 405 /// The number of valid broadcast frames received and not dropped 406 #[must_use] rx_broadcast_frames(&self) -> Option<u64>407 pub const fn rx_broadcast_frames(&self) -> Option<u64> { 408 self.to_option(self.rx_broadcast_frames) 409 } 410 411 /// The number of valid multicast frames received and not dropped 412 #[must_use] rx_multicast_frames(&self) -> Option<u64>413 pub const fn rx_multicast_frames(&self) -> Option<u64> { 414 self.to_option(self.rx_multicast_frames) 415 } 416 417 /// Number of frames with CRC or alignment errors 418 #[must_use] rx_crc_error_frames(&self) -> Option<u64>419 pub const fn rx_crc_error_frames(&self) -> Option<u64> { 420 self.to_option(self.rx_crc_error_frames) 421 } 422 423 /// The total number of bytes received including frames with errors 424 /// and dropped frames 425 #[must_use] rx_total_bytes(&self) -> Option<u64>426 pub const fn rx_total_bytes(&self) -> Option<u64> { 427 self.to_option(self.rx_total_bytes) 428 } 429 430 /// The total number of frames transmitted including frames 431 /// with errors and dropped frames 432 #[must_use] tx_total_frames(&self) -> Option<u64>433 pub const fn tx_total_frames(&self) -> Option<u64> { 434 self.to_option(self.tx_total_frames) 435 } 436 437 /// The total number of valid frames transmitted and copied 438 /// into receive buffers 439 #[must_use] tx_good_frames(&self) -> Option<u64>440 pub const fn tx_good_frames(&self) -> Option<u64> { 441 self.to_option(self.tx_good_frames) 442 } 443 444 /// The number of frames below the minimum length for 445 /// the media. This would be less than 64 for Ethernet 446 #[must_use] tx_undersize_frames(&self) -> Option<u64>447 pub const fn tx_undersize_frames(&self) -> Option<u64> { 448 self.to_option(self.tx_undersize_frames) 449 } 450 451 /// The number of frames longer than the maximum length for 452 /// the media. This would be 1500 for Ethernet 453 #[must_use] tx_oversize_frames(&self) -> Option<u64>454 pub const fn tx_oversize_frames(&self) -> Option<u64> { 455 self.to_option(self.tx_oversize_frames) 456 } 457 458 /// The number of valid frames that were dropped because 459 /// received buffers were full 460 #[must_use] tx_dropped_frames(&self) -> Option<u64>461 pub const fn tx_dropped_frames(&self) -> Option<u64> { 462 self.to_option(self.tx_dropped_frames) 463 } 464 465 /// The number of valid unicast frames transmitted and not 466 /// dropped 467 #[must_use] tx_unicast_frames(&self) -> Option<u64>468 pub const fn tx_unicast_frames(&self) -> Option<u64> { 469 self.to_option(self.tx_unicast_frames) 470 } 471 472 /// The number of valid broadcast frames transmitted and 473 /// not dropped 474 #[must_use] tx_broadcast_frames(&self) -> Option<u64>475 pub const fn tx_broadcast_frames(&self) -> Option<u64> { 476 self.to_option(self.tx_broadcast_frames) 477 } 478 479 /// The number of valid multicast frames transmitted 480 /// and not dropped 481 #[must_use] tx_multicast_frames(&self) -> Option<u64>482 pub const fn tx_multicast_frames(&self) -> Option<u64> { 483 self.to_option(self.tx_multicast_frames) 484 } 485 486 /// The number of transmitted frames with CRC or 487 /// alignment errors 488 #[must_use] tx_crc_error_frames(&self) -> Option<u64>489 pub const fn tx_crc_error_frames(&self) -> Option<u64> { 490 self.to_option(self.tx_crc_error_frames) 491 } 492 493 /// The total number of bytes transmitted including 494 /// error frames and dropped frames 495 #[must_use] tx_total_bytes(&self) -> Option<u64>496 pub const fn tx_total_bytes(&self) -> Option<u64> { 497 self.to_option(self.tx_total_bytes) 498 } 499 500 /// The number of collisions detected on this subnet 501 #[must_use] collisions(&self) -> Option<u64>502 pub const fn collisions(&self) -> Option<u64> { 503 self.to_option(self.collisions) 504 } 505 506 /// The number of frames destined for unsupported protocol 507 #[must_use] unsupported_protocol(&self) -> Option<u64>508 pub const fn unsupported_protocol(&self) -> Option<u64> { 509 self.to_option(self.unsupported_protocol) 510 } 511 512 /// The number of valid frames received that were duplicated 513 #[must_use] rx_duplicated_frames(&self) -> Option<u64>514 pub const fn rx_duplicated_frames(&self) -> Option<u64> { 515 self.to_option(self.rx_duplicated_frames) 516 } 517 518 /// The number of encrypted frames received that failed 519 /// to decrypt 520 #[must_use] rx_decrypt_error_frames(&self) -> Option<u64>521 pub const fn rx_decrypt_error_frames(&self) -> Option<u64> { 522 self.to_option(self.rx_decrypt_error_frames) 523 } 524 525 /// The number of frames that failed to transmit after 526 /// exceeding the retry limit 527 #[must_use] tx_error_frames(&self) -> Option<u64>528 pub const fn tx_error_frames(&self) -> Option<u64> { 529 self.to_option(self.tx_error_frames) 530 } 531 532 /// The number of frames that transmitted successfully 533 /// after more than one attempt 534 #[must_use] tx_retry_frames(&self) -> Option<u64>535 pub const fn tx_retry_frames(&self) -> Option<u64> { 536 self.to_option(self.tx_retry_frames) 537 } 538 } 539 540 /// The Simple Network Mode 541 #[repr(C)] 542 #[derive(Debug)] 543 pub struct NetworkMode { 544 /// Reports the current state of the network interface 545 pub state: NetworkState, 546 /// The size of the network interface's hardware address in bytes 547 pub hw_address_size: u32, 548 /// The size of the network interface's media header in bytes 549 pub media_header_size: u32, 550 /// The maximum size of the packets supported by the network interface in bytes 551 pub max_packet_size: u32, 552 /// The size of the NVRAM device attached to the network interface in bytes 553 pub nv_ram_size: u32, 554 /// The size that must be used for all NVRAM reads and writes 555 pub nv_ram_access_size: u32, 556 /// The multicast receive filter settings supported by the network interface 557 pub receive_filter_mask: u32, 558 /// The current multicast receive filter settings 559 pub receive_filter_setting: u32, 560 /// The maximum number of multicast address receive filters supported by the driver 561 pub max_mcast_filter_count: u32, 562 /// The current number of multicast address receive filters 563 pub mcast_filter_count: u32, 564 /// The array containing the addresses of the current multicast address receive filters 565 pub mcast_filter: [MacAddress; 16], 566 /// The current hardware MAC address for the network interface 567 pub current_address: MacAddress, 568 /// The current hardware MAC address for broadcast packets 569 pub broadcast_address: MacAddress, 570 /// The permanent hardware MAC address for the network interface 571 pub permanent_address: MacAddress, 572 /// The interface type of the network interface 573 pub if_type: u8, 574 /// Tells if the MAC address can be changed 575 pub mac_address_changeable: bool, 576 /// Tells if the network interface can transmit more than one packet at a time 577 pub multiple_tx_supported: bool, 578 /// Tells if the presence of the media can be determined 579 pub media_present_supported: bool, 580 /// Tells if media are connected to the network interface 581 pub media_present: bool, 582 } 583 584 newtype_enum! { 585 /// The state of a network interface. 586 pub enum NetworkState: u32 => { 587 /// The interface has been stopped 588 STOPPED = 0, 589 /// The interface has been started 590 STARTED = 1, 591 /// The interface has been initialized 592 INITIALIZED = 2, 593 /// No state can have a number higher than this 594 MAX_STATE = 4, 595 } 596 } 597