]> git.proxmox.com Git - mirror_edk2.git/blob - EmulatorPkg/Win/Host/WinPacketFilter.c
EmulatorPkg/WinHost: Enable network support.
[mirror_edk2.git] / EmulatorPkg / Win / Host / WinPacketFilter.c
1 /**@file
2 Windows Packet Filter implementation of the EMU_SNP_PROTOCOL that allows the
3 emulator to get on real networks.
4
5 Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
6 Portions copyright (c) 2011, Apple Inc. All rights reserved.
7 (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
8
9 SPDX-License-Identifier: BSD-2-Clause-Patent
10
11 **/
12 #include "WinHost.h"
13
14 #define NETWORK_LIBRARY_NAME_U L"SnpNt32Io.dll"
15 #define NETWORK_LIBRARY_INITIALIZE "SnpInitialize"
16 #define NETWORK_LIBRARY_FINALIZE "SnpFinalize"
17 #define NETWORK_LIBRARY_SET_RCV_FILTER "SnpSetReceiveFilter"
18 #define NETWORK_LIBRARY_RECEIVE "SnpReceive"
19 #define NETWORK_LIBRARY_TRANSMIT "SnpTransmit"
20
21 #pragma pack(1)
22 typedef struct _NT_NET_INTERFACE_INFO {
23 UINT32 InterfaceIndex;
24 EFI_MAC_ADDRESS MacAddr;
25 } NT_NET_INTERFACE_INFO;
26 #pragma pack()
27
28 #define NET_ETHER_HEADER_SIZE 14
29 #define MAX_INTERFACE_INFO_NUMBER 16
30 #define SNP_MAX_TX_BUFFER_NUM 65536
31 #define SNP_TX_BUFFER_INCREASEMENT 32
32 #define DEFAULT_SELECTED_NIC_INDEX 0
33
34 //
35 // Functions in Net Library
36 //
37 typedef
38 INT32
39 (*NT_NET_INITIALIZE) (
40 IN OUT UINT32 *InterfaceCount,
41 IN OUT NT_NET_INTERFACE_INFO * InterfaceInfoBuffer
42 );
43
44 typedef
45 INT32
46 (*NT_NET_FINALIZE) (
47 VOID
48 );
49
50 typedef
51 INT32
52 (*NT_NET_SET_RECEIVE_FILTER) (
53 IN UINT32 Index,
54 IN UINT32 EnableFilter,
55 IN UINT32 MCastFilterCnt,
56 IN EFI_MAC_ADDRESS * MCastFilter
57 );
58
59 typedef
60 INT32
61 (*NT_NET_RECEIVE) (
62 IN UINT32 Index,
63 IN OUT UINT32 *BufferSize,
64 OUT VOID *Buffer
65 );
66
67 typedef
68 INT32
69 (*NT_NET_TRANSMIT) (
70 IN UINT32 Index,
71 IN UINT32 HeaderSize,
72 IN UINT32 BufferSize,
73 IN VOID *Buffer,
74 IN EFI_MAC_ADDRESS * SrcAddr,
75 IN EFI_MAC_ADDRESS * DestAddr,
76 IN UINT16 *Protocol
77 );
78
79 typedef struct _NT_NET_UTILITY_TABLE {
80 NT_NET_INITIALIZE Initialize;
81 NT_NET_FINALIZE Finalize;
82 NT_NET_SET_RECEIVE_FILTER SetReceiveFilter;
83 NT_NET_RECEIVE Receive;
84 NT_NET_TRANSMIT Transmit;
85 } NT_NET_UTILITY_TABLE;
86
87 //
88 // Instance data for each fake SNP instance
89 //
90 #define WIN_NT_INSTANCE_SIGNATURE SIGNATURE_32 ('N', 'T', 'I', 'S')
91
92 typedef struct {
93 UINT32 Signature;
94
95 //
96 // Array of the recycled transmit buffer address.
97 //
98 UINT64 *RecycledTxBuf;
99
100 //
101 // Current number of recycled buffer pointers in RecycledTxBuf.
102 //
103 UINT32 RecycledTxBufCount;
104
105 //
106 // The maximum number of recycled buffer pointers in RecycledTxBuf.
107 //
108 UINT32 MaxRecycledTxBuf;
109 EFI_SIMPLE_NETWORK_MODE Mode;
110 NT_NET_INTERFACE_INFO InterfaceInfo;
111 } WIN_NT_INSTANCE_DATA;
112
113 //
114 // Instance data for each SNP private instance
115 //
116 #define WIN_NT_SIMPLE_NETWORK_PRIVATE_SIGNATURE SIGNATURE_32 ('N', 'T', 's', 'n')
117
118 typedef struct {
119 UINTN Signature;
120 EMU_IO_THUNK_PROTOCOL *Thunk;
121 EMU_SNP_PROTOCOL EmuSnp;
122 EFI_SIMPLE_NETWORK_MODE *Mode;
123 HMODULE NetworkLibraryHandle;
124 NT_NET_UTILITY_TABLE NtNetUtilityTable;
125 WIN_NT_INSTANCE_DATA Instance;
126 } WIN_NT_SNP_PRIVATE;
127
128 #define WIN_NT_SNP_PRIVATE_DATA_FROM_THIS(a) \
129 CR(a, WIN_NT_SNP_PRIVATE, EmuSnp, WIN_NT_SIMPLE_NETWORK_PRIVATE_SIGNATURE)
130
131
132 /**
133 Register storage for SNP Mode.
134
135 @param This Protocol instance pointer.
136 @param Mode SimpleNetworkProtocol Mode structure passed into driver.
137
138 @retval EFI_SUCCESS The network interface was started.
139 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
140
141 **/
142 EFI_STATUS
143 WinNtSnpCreateMapping (
144 IN EMU_SNP_PROTOCOL *This,
145 IN EFI_SIMPLE_NETWORK_MODE *Mode
146 )
147 {
148 WIN_NT_SNP_PRIVATE *Private;
149
150 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
151
152 Private->Mode = Mode;
153
154 //
155 // Set the broadcast address.
156 //
157 CopyMem (&Mode->BroadcastAddress, &Private->Instance.Mode.BroadcastAddress, sizeof (EFI_MAC_ADDRESS));
158 //
159 // Set the MAC address.
160 //
161 CopyMem (&Mode->CurrentAddress, &Private->Instance.Mode.CurrentAddress, sizeof (EFI_MAC_ADDRESS));
162 CopyMem (&Mode->PermanentAddress, &Private->Instance.Mode.PermanentAddress, sizeof (EFI_MAC_ADDRESS));
163
164 return EFI_SUCCESS;
165 }
166
167 /**
168 Changes the state of a network interface from "stopped" to "started".
169
170 @param This Protocol instance pointer.
171
172 @retval EFI_SUCCESS The network interface was started.
173 @retval EFI_ALREADY_STARTED The network interface is already in the started state.
174 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
175 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
176 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
177
178 **/
179 EFI_STATUS
180 WinNtSnpStart (
181 IN EMU_SNP_PROTOCOL *This
182 )
183 {
184 WIN_NT_SNP_PRIVATE *Private;
185
186 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
187
188 switch (Private->Mode->State) {
189 case EfiSimpleNetworkStopped:
190 break;
191
192 case EfiSimpleNetworkStarted:
193 case EfiSimpleNetworkInitialized:
194 return EFI_ALREADY_STARTED;
195 break;
196
197 default:
198 return EFI_DEVICE_ERROR;
199 break;
200 }
201
202 Private->Mode->State = EfiSimpleNetworkStarted;
203
204 return EFI_SUCCESS;
205 }
206
207 /**
208 Changes the state of a network interface from "started" to "stopped".
209
210 @param This Protocol instance pointer.
211
212 @retval EFI_SUCCESS The network interface was stopped.
213 @retval EFI_ALREADY_STARTED The network interface is already in the stopped state.
214 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
215 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
216 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
217
218 **/
219 EFI_STATUS
220 WinNtSnpStop (
221 IN EMU_SNP_PROTOCOL *This
222 )
223 {
224 WIN_NT_SNP_PRIVATE *Private;
225
226 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
227
228 switch ( Private->Mode->State ) {
229 case EfiSimpleNetworkStarted:
230 break;
231
232 case EfiSimpleNetworkStopped:
233 return EFI_NOT_STARTED;
234 break;
235
236 default:
237 return EFI_DEVICE_ERROR;
238 break;
239 }
240
241 Private->Mode->State = EfiSimpleNetworkStopped;
242
243 return EFI_SUCCESS;
244 }
245
246 /**
247 Resets a network adapter and allocates the transmit and receive buffers
248 required by the network interface; optionally, also requests allocation
249 of additional transmit and receive buffers.
250
251 @param This The protocol instance pointer.
252 @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space
253 that the driver should allocate for the network interface.
254 Some network interfaces will not be able to use the extra
255 buffer, and the caller will not know if it is actually
256 being used.
257 @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space
258 that the driver should allocate for the network interface.
259 Some network interfaces will not be able to use the extra
260 buffer, and the caller will not know if it is actually
261 being used.
262
263 @retval EFI_SUCCESS The network interface was initialized.
264 @retval EFI_NOT_STARTED The network interface has not been started.
265 @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and
266 receive buffers.
267 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
268 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
269 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
270
271 **/
272 EFI_STATUS
273 WinNtSnpInitialize (
274 IN EMU_SNP_PROTOCOL *This,
275 IN UINTN ExtraRxBufferSize OPTIONAL,
276 IN UINTN ExtraTxBufferSize OPTIONAL
277 )
278 {
279 WIN_NT_SNP_PRIVATE *Private;
280
281 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
282
283 switch ( Private->Mode->State ) {
284 case EfiSimpleNetworkStarted:
285 break;
286
287 case EfiSimpleNetworkStopped:
288 return EFI_NOT_STARTED;
289 break;
290
291 default:
292 return EFI_DEVICE_ERROR;
293 break;
294 }
295
296 Private->Mode->MCastFilterCount = 0;
297 Private->Mode->ReceiveFilterSetting = 0;
298 ZeroMem (Private->Mode->MCastFilter, sizeof (Private->Mode->MCastFilter));
299
300 Private->Mode->State = EfiSimpleNetworkInitialized;
301
302 return EFI_SUCCESS;
303 }
304
305 /**
306 Resets a network adapter and re-initializes it with the parameters that were
307 provided in the previous call to Initialize().
308
309 @param This The protocol instance pointer.
310 @param ExtendedVerification Indicates that the driver may perform a more
311 exhaustive verification operation of the device
312 during reset.
313
314 @retval EFI_SUCCESS The network interface was reset.
315 @retval EFI_NOT_STARTED The network interface has not been started.
316 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
317 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
318 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
319
320 **/
321 EFI_STATUS
322 WinNtSnpReset (
323 IN EMU_SNP_PROTOCOL *This,
324 IN BOOLEAN ExtendedVerification
325 )
326 {
327 WIN_NT_SNP_PRIVATE *Private;
328
329 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
330
331 switch ( Private->Mode->State ) {
332 case EfiSimpleNetworkInitialized:
333 break;
334
335 case EfiSimpleNetworkStopped:
336 return EFI_NOT_STARTED;
337 break;
338
339 default:
340 return EFI_DEVICE_ERROR;
341 break;
342 }
343
344 return EFI_SUCCESS;
345 }
346
347 /**
348 Resets a network adapter and leaves it in a state that is safe for
349 another driver to initialize.
350
351 @param This Protocol instance pointer.
352
353 @retval EFI_SUCCESS The network interface was shutdown.
354 @retval EFI_NOT_STARTED The network interface has not been started.
355 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
356 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
357 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
358
359 **/
360 EFI_STATUS
361 WinNtSnpShutdown (
362 IN EMU_SNP_PROTOCOL *This
363 )
364 {
365 WIN_NT_SNP_PRIVATE *Private;
366
367 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
368
369 switch ( Private->Mode->State ) {
370 case EfiSimpleNetworkInitialized:
371 break;
372
373 case EfiSimpleNetworkStopped:
374 return EFI_NOT_STARTED;
375 break;
376
377 default:
378 return EFI_DEVICE_ERROR;
379 break;
380 }
381
382 Private->Mode->State = EfiSimpleNetworkStarted;
383
384 Private->Mode->ReceiveFilterSetting = 0;
385 Private->Mode->MCastFilterCount = 0;
386 ZeroMem (Private->Mode->MCastFilter, sizeof (Private->Mode->MCastFilter));
387
388 return EFI_SUCCESS;
389 }
390
391 /**
392 Manages the multicast receive filters of a network interface.
393
394 @param This The protocol instance pointer.
395 @param Enable A bit mask of receive filters to enable on the network interface.
396 @param Disable A bit mask of receive filters to disable on the network interface.
397 @param ResetMCastFilter Set to TRUE to reset the contents of the multicast receive
398 filters on the network interface to their default values.
399 @param McastFilterCnt Number of multicast HW MAC addresses in the new
400 MCastFilter list. This value must be less than or equal to
401 the MCastFilterCnt field of EMU_SNP_MODE. This
402 field is optional if ResetMCastFilter is TRUE.
403 @param MCastFilter A pointer to a list of new multicast receive filter HW MAC
404 addresses. This list will replace any existing multicast
405 HW MAC address list. This field is optional if
406 ResetMCastFilter is TRUE.
407
408 @retval EFI_SUCCESS The multicast receive filter list was updated.
409 @retval EFI_NOT_STARTED The network interface has not been started.
410 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
411 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
412 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
413
414 **/
415 EFI_STATUS
416 WinNtSnpReceiveFilters (
417 IN EMU_SNP_PROTOCOL *This,
418 IN UINT32 Enable,
419 IN UINT32 Disable,
420 IN BOOLEAN ResetMCastFilter,
421 IN UINTN MCastFilterCnt OPTIONAL,
422 IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL
423 )
424 {
425 WIN_NT_SNP_PRIVATE *Private;
426 INT32 ReturnValue;
427
428 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
429
430 ReturnValue = Private->NtNetUtilityTable.SetReceiveFilter (
431 Private->Instance.InterfaceInfo.InterfaceIndex,
432 Enable,
433 (UINT32)MCastFilterCnt,
434 MCastFilter
435 );
436
437 if (ReturnValue <= 0) {
438 return EFI_DEVICE_ERROR;
439 }
440
441 return EFI_SUCCESS;
442 }
443
444 /**
445 Modifies or resets the current station address, if supported.
446
447 @param This The protocol instance pointer.
448 @param Reset Flag used to reset the station address to the network interfaces
449 permanent address.
450 @param New The new station address to be used for the network interface.
451
452 @retval EFI_SUCCESS The network interfaces station address was updated.
453 @retval EFI_NOT_STARTED The network interface has not been started.
454 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
455 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
456 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
457
458 **/
459 EFI_STATUS
460 WinNtSnpStationAddress (
461 IN EMU_SNP_PROTOCOL *This,
462 IN BOOLEAN Reset,
463 IN EFI_MAC_ADDRESS *New OPTIONAL
464 )
465 {
466 WIN_NT_SNP_PRIVATE *Private;
467
468 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
469
470 return EFI_UNSUPPORTED;
471 }
472
473 /**
474 Resets or collects the statistics on a network interface.
475
476 @param This Protocol instance pointer.
477 @param Reset Set to TRUE to reset the statistics for the network interface.
478 @param StatisticsSize On input the size, in bytes, of StatisticsTable. On
479 output the size, in bytes, of the resulting table of
480 statistics.
481 @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
482 contains the statistics.
483
484 @retval EFI_SUCCESS The statistics were collected from the network interface.
485 @retval EFI_NOT_STARTED The network interface has not been started.
486 @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer
487 size needed to hold the statistics is returned in
488 StatisticsSize.
489 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
490 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
491 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
492
493 **/
494 EFI_STATUS
495 WinNtSnpStatistics (
496 IN EMU_SNP_PROTOCOL *This,
497 IN BOOLEAN Reset,
498 IN OUT UINTN *StatisticsSize OPTIONAL,
499 OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL
500 )
501 {
502 WIN_NT_SNP_PRIVATE *Private;
503
504 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
505
506 return EFI_UNSUPPORTED;
507 }
508
509 /**
510 Converts a multicast IP address to a multicast HW MAC address.
511
512 @param This The protocol instance pointer.
513 @param IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460]. Set
514 to FALSE if the multicast IP address is IPv4 [RFC 791].
515 @param IP The multicast IP address that is to be converted to a multicast
516 HW MAC address.
517 @param MAC The multicast HW MAC address that is to be generated from IP.
518
519 @retval EFI_SUCCESS The multicast IP address was mapped to the multicast
520 HW MAC address.
521 @retval EFI_NOT_STARTED The network interface has not been started.
522 @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer
523 size needed to hold the statistics is returned in
524 StatisticsSize.
525 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
526 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
527 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
528
529 **/
530 EFI_STATUS
531 WinNtSnpMCastIpToMac (
532 IN EMU_SNP_PROTOCOL *This,
533 IN BOOLEAN IPv6,
534 IN EFI_IP_ADDRESS *IP,
535 OUT EFI_MAC_ADDRESS *MAC
536 )
537 {
538 WIN_NT_SNP_PRIVATE *Private;
539
540 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
541
542 return EFI_UNSUPPORTED;
543 }
544
545 /**
546 Performs read and write operations on the NVRAM device attached to a
547 network interface.
548
549 @param This The protocol instance pointer.
550 @param ReadWrite TRUE for read operations, FALSE for write operations.
551 @param Offset Byte offset in the NVRAM device at which to start the read or
552 write operation. This must be a multiple of NvRamAccessSize and
553 less than NvRamSize.
554 @param BufferSize The number of bytes to read or write from the NVRAM device.
555 This must also be a multiple of NvramAccessSize.
556 @param Buffer A pointer to the data buffer.
557
558 @retval EFI_SUCCESS The NVRAM access was performed.
559 @retval EFI_NOT_STARTED The network interface has not been started.
560 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
561 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
562 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
563
564 **/
565 EFI_STATUS
566 WinNtSnpNvData (
567 IN EMU_SNP_PROTOCOL *This,
568 IN BOOLEAN ReadWrite,
569 IN UINTN Offset,
570 IN UINTN BufferSize,
571 IN OUT VOID *Buffer
572 )
573 {
574 WIN_NT_SNP_PRIVATE *Private;
575
576 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
577
578 return EFI_UNSUPPORTED;
579 }
580
581 /**
582 Reads the current interrupt status and recycled transmit buffer status from
583 a network interface.
584
585 @param This The protocol instance pointer.
586 @param InterruptStatus A pointer to the bit mask of the currently active interrupts
587 If this is NULL, the interrupt status will not be read from
588 the device. If this is not NULL, the interrupt status will
589 be read from the device. When the interrupt status is read,
590 it will also be cleared. Clearing the transmit interrupt
591 does not empty the recycled transmit buffer array.
592 @param TxBuf Recycled transmit buffer address. The network interface will
593 not transmit if its internal recycled transmit buffer array
594 is full. Reading the transmit buffer does not clear the
595 transmit interrupt. If this is NULL, then the transmit buffer
596 status will not be read. If there are no transmit buffers to
597 recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
598
599 @retval EFI_SUCCESS The status of the network interface was retrieved.
600 @retval EFI_NOT_STARTED The network interface has not been started.
601 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
602 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
603 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
604
605 **/
606 EFI_STATUS
607 WinNtSnpGetStatus (
608 IN EMU_SNP_PROTOCOL *This,
609 OUT UINT32 *InterruptStatus OPTIONAL,
610 OUT VOID **TxBuf OPTIONAL
611 )
612 {
613 WIN_NT_SNP_PRIVATE *Private;
614
615 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
616
617 if (TxBuf != NULL) {
618 if (Private->Instance.RecycledTxBufCount != 0) {
619 Private->Instance.RecycledTxBufCount --;
620 *((UINT8 **) TxBuf) = (UINT8 *) (UINTN)Private->Instance.RecycledTxBuf[Private->Instance.RecycledTxBufCount];
621 } else {
622 *((UINT8 **) TxBuf) = NULL;
623 }
624 }
625
626 if (InterruptStatus != NULL) {
627 *InterruptStatus = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
628 }
629
630 return EFI_SUCCESS;
631 }
632
633 /**
634 Places a packet in the transmit queue of a network interface.
635
636 @param This The protocol instance pointer.
637 @param HeaderSize The size, in bytes, of the media header to be filled in by
638 the Transmit() function. If HeaderSize is non-zero, then it
639 must be equal to This->Mode->MediaHeaderSize and the DestAddr
640 and Protocol parameters must not be NULL.
641 @param BufferSize The size, in bytes, of the entire packet (media header and
642 data) to be transmitted through the network interface.
643 @param Buffer A pointer to the packet (media header followed by data) to be
644 transmitted. This parameter cannot be NULL. If HeaderSize is zero,
645 then the media header in Buffer must already be filled in by the
646 caller. If HeaderSize is non-zero, then the media header will be
647 filled in by the Transmit() function.
648 @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter
649 is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
650 This->Mode->CurrentAddress is used for the source HW MAC address.
651 @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this
652 parameter is ignored.
653 @param Protocol The type of header to build. If HeaderSize is zero, then this
654 parameter is ignored. See RFC 1700, section "Ether Types", for
655 examples.
656
657 @retval EFI_SUCCESS The packet was placed on the transmit queue.
658 @retval EFI_NOT_STARTED The network interface has not been started.
659 @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.
660 @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
661 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
662 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
663 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
664
665 **/
666 EFI_STATUS
667 WinNtSnpTransmit (
668 IN EMU_SNP_PROTOCOL *This,
669 IN UINTN HeaderSize,
670 IN UINTN BufferSize,
671 IN VOID *Buffer,
672 IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
673 IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,
674 IN UINT16 *Protocol OPTIONAL
675 )
676 {
677 WIN_NT_SNP_PRIVATE *Private;
678 INT32 ReturnValue;
679 UINT64 *Tmp;
680
681 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
682
683 if ((HeaderSize != 0) && (SrcAddr == NULL)) {
684 SrcAddr = &Private->Instance.Mode.CurrentAddress;
685 }
686
687 ReturnValue = Private->NtNetUtilityTable.Transmit (
688 Private->Instance.InterfaceInfo.InterfaceIndex,
689 (UINT32)HeaderSize,
690 (UINT32)BufferSize,
691 Buffer,
692 SrcAddr,
693 DestAddr,
694 Protocol
695 );
696
697 if (ReturnValue < 0) {
698 return EFI_DEVICE_ERROR;
699 } else {
700 if ((Private->Instance.MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT) >= SNP_MAX_TX_BUFFER_NUM) {
701 return EFI_NOT_READY;
702 }
703
704 if (Private->Instance.RecycledTxBufCount < Private->Instance.MaxRecycledTxBuf) {
705 Private->Instance.RecycledTxBuf[Private->Instance.RecycledTxBufCount] = (UINT64) Buffer;
706 Private->Instance.RecycledTxBufCount ++;
707 } else {
708 Tmp = malloc (sizeof (UINT64) * (Private->Instance.MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT));
709 if (Tmp == NULL) {
710 return EFI_DEVICE_ERROR;
711 }
712 CopyMem (Tmp, Private->Instance.RecycledTxBuf, sizeof (UINT64) * Private->Instance.RecycledTxBufCount);
713 free (Private->Instance.RecycledTxBuf);
714 Private->Instance.RecycledTxBuf = Tmp;
715 Private->Instance.MaxRecycledTxBuf += SNP_TX_BUFFER_INCREASEMENT;
716 }
717 }
718
719 return EFI_SUCCESS;
720 }
721
722 /**
723 Receives a packet from a network interface.
724
725 @param This The protocol instance pointer.
726 @param HeaderSize The size, in bytes, of the media header received on the network
727 interface. If this parameter is NULL, then the media header size
728 will not be returned.
729 @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
730 bytes, of the packet that was received on the network interface.
731 @param Buffer A pointer to the data buffer to receive both the media header and
732 the data.
733 @param SrcAddr The source HW MAC address. If this parameter is NULL, the
734 HW MAC source address will not be extracted from the media
735 header.
736 @param DestAddr The destination HW MAC address. If this parameter is NULL,
737 the HW MAC destination address will not be extracted from the
738 media header.
739 @param Protocol The media header type. If this parameter is NULL, then the
740 protocol will not be extracted from the media header. See
741 RFC 1700 section "Ether Types" for examples.
742
743 @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has
744 been updated to the number of bytes received.
745 @retval EFI_NOT_STARTED The network interface has not been started.
746 @retval EFI_NOT_READY The network interface is too busy to accept this transmit
747 request.
748 @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
749 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
750 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
751 @retval EFI_UNSUPPORTED This function is not supported by the network interface.
752
753 **/
754 EFI_STATUS
755 WinNtSnpReceive (
756 IN EMU_SNP_PROTOCOL *This,
757 OUT UINTN *HeaderSize OPTIONAL,
758 IN OUT UINTN *BufferSize,
759 OUT VOID *Buffer,
760 OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
761 OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,
762 OUT UINT16 *Protocol OPTIONAL
763 )
764 {
765 WIN_NT_SNP_PRIVATE *Private;
766 INT32 ReturnValue;
767 UINTN BufSize;
768
769 Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);
770
771 BufSize = *BufferSize;
772
773 ASSERT (Private->NtNetUtilityTable.Receive != NULL);
774
775 ReturnValue = Private->NtNetUtilityTable.Receive (
776 Private->Instance.InterfaceInfo.InterfaceIndex,
777 BufferSize,
778 Buffer
779 );
780
781 if (ReturnValue < 0) {
782 if (ReturnValue == -100) {
783 return EFI_BUFFER_TOO_SMALL;
784 }
785
786 return EFI_DEVICE_ERROR;
787 } else if (ReturnValue == 0) {
788 return EFI_NOT_READY;
789 }
790
791 if (HeaderSize != NULL) {
792 *HeaderSize = 14;
793 }
794
795 if (SrcAddr != NULL) {
796 ZeroMem (SrcAddr, sizeof (EFI_MAC_ADDRESS));
797 CopyMem (SrcAddr, ((UINT8 *) Buffer) + 6, 6);
798 }
799
800 if (DestAddr != NULL) {
801 ZeroMem (DestAddr, sizeof (EFI_MAC_ADDRESS));
802 CopyMem (DestAddr, ((UINT8 *) Buffer), 6);
803 }
804
805 if (Protocol != NULL) {
806 *Protocol = NTOHS (*((UINT16 *) (((UINT8 *) Buffer) + 12)));
807 }
808
809 return (*BufferSize <= BufSize) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;
810 }
811
812 /**
813 Initialize the snpnt32 driver instance.
814
815 @param Instance Pointer to the instance context data.
816 @param NetInfo Pointer to the interface info.
817
818 @retval EFI_SUCCESS The driver instance is initialized.
819 @retval other Initialization errors.
820
821 **/
822 EFI_STATUS
823 WinNtInitializeInstanceData (
824 IN OUT WIN_NT_INSTANCE_DATA *Instance,
825 IN NT_NET_INTERFACE_INFO *NetInfo
826 )
827 {
828 if (Instance == NULL || NetInfo == NULL) {
829 return EFI_INVALID_PARAMETER;
830 }
831
832 ZeroMem (Instance, sizeof (WIN_NT_INSTANCE_DATA));
833
834 Instance->Signature = WIN_NT_INSTANCE_SIGNATURE;
835 Instance->RecycledTxBufCount = 0;
836 Instance->MaxRecycledTxBuf = 32;
837 Instance->Mode.State = EfiSimpleNetworkInitialized;
838 Instance->Mode.HwAddressSize = NET_ETHER_ADDR_LEN;
839 Instance->Mode.MediaHeaderSize = NET_ETHER_HEADER_SIZE;
840 Instance->Mode.MaxPacketSize = 1500;
841 Instance->Mode.MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
842 Instance->Mode.IfType = NET_IFTYPE_ETHERNET;
843 Instance->Mode.MediaPresentSupported = TRUE;
844 Instance->Mode.MediaPresent = TRUE;
845
846 //
847 // Allocate the RecycledTxBuf.
848 //
849 Instance->RecycledTxBuf = malloc (sizeof (UINT64) * Instance->MaxRecycledTxBuf);
850 if (Instance->RecycledTxBuf == NULL) {
851 return EFI_OUT_OF_RESOURCES;
852 }
853
854 //
855 // Set the interface information.
856 //
857 CopyMem (&Instance->InterfaceInfo, NetInfo, sizeof (Instance->InterfaceInfo));
858
859
860 //
861 // Set broadcast address
862 //
863 SetMem (&Instance->Mode.BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);
864
865 //
866 // Copy Current/PermanentAddress MAC address
867 //
868 CopyMem (&Instance->Mode.CurrentAddress, &Instance->InterfaceInfo.MacAddr, sizeof(Instance->Mode.CurrentAddress));
869 CopyMem (&Instance->Mode.PermanentAddress, &Instance->InterfaceInfo.MacAddr, sizeof(Instance->Mode.PermanentAddress));
870
871 //
872 // Since the fake SNP is based on a real NIC, to avoid conflict with the host
873 // NIC network stack, we use a different MAC address.
874 // So just change the last byte of the MAC address for the real NIC.
875 //
876 Instance->Mode.CurrentAddress.Addr[NET_ETHER_ADDR_LEN - 1]++;
877
878 return EFI_SUCCESS;
879 }
880
881 /**
882 Initialize the net utility data.
883
884 @param This Pointer to the private data.
885 @param ActiveInstance The active network interface.
886
887 @retval EFI_SUCCESS The global data is initialized.
888 @retval EFI_NOT_FOUND The required DLL is not found.
889 @retval EFI_DEVICE_ERROR Error initialize network utility library.
890 @retval other Other errors.
891
892 **/
893 EFI_STATUS
894 WintNtInitializeNetUtilityData (
895 IN OUT WIN_NT_SNP_PRIVATE *Private,
896 IN UINT8 ActiveInstance
897 )
898 {
899 EFI_STATUS Status;
900 CHAR16 *DllFileNameU;
901 INT32 ReturnValue;
902 BOOLEAN NetUtilityLibInitDone;
903 NT_NET_INTERFACE_INFO NetInterfaceInfoBuffer[MAX_INTERFACE_INFO_NUMBER];
904 UINT32 InterfaceCount;
905 UINT8 ActiveInterfaceIndex;
906
907 if (Private == NULL) {
908 return EFI_INVALID_PARAMETER;
909 }
910
911 NetUtilityLibInitDone = FALSE;
912 InterfaceCount = MAX_INTERFACE_INFO_NUMBER;
913 DllFileNameU = NETWORK_LIBRARY_NAME_U;
914
915 //
916 // Load network utility library
917 //
918 Private->NetworkLibraryHandle = LoadLibraryEx (DllFileNameU, NULL, 0);
919 if (NULL == Private->NetworkLibraryHandle) {
920 return EFI_NOT_FOUND;
921 }
922
923 Private->NtNetUtilityTable.Initialize = (NT_NET_INITIALIZE) GetProcAddress (Private->NetworkLibraryHandle, NETWORK_LIBRARY_INITIALIZE);
924 if (NULL == Private->NtNetUtilityTable.Initialize) {
925 Status = EFI_NOT_FOUND;
926 goto ErrorReturn;
927 }
928
929 Private->NtNetUtilityTable.Finalize = (NT_NET_FINALIZE) GetProcAddress (Private->NetworkLibraryHandle, NETWORK_LIBRARY_FINALIZE);
930 if (NULL == Private->NtNetUtilityTable.Finalize) {
931 Status = EFI_NOT_FOUND;
932 goto ErrorReturn;
933 }
934
935 Private->NtNetUtilityTable.SetReceiveFilter = (NT_NET_SET_RECEIVE_FILTER) GetProcAddress (Private->NetworkLibraryHandle, NETWORK_LIBRARY_SET_RCV_FILTER);
936 if (NULL == Private->NtNetUtilityTable.SetReceiveFilter) {
937 Status = EFI_NOT_FOUND;
938 goto ErrorReturn;
939 }
940
941 Private->NtNetUtilityTable.Receive = (NT_NET_RECEIVE) GetProcAddress (Private->NetworkLibraryHandle, NETWORK_LIBRARY_RECEIVE);
942 if (NULL == Private->NtNetUtilityTable.Receive) {
943 Status = EFI_NOT_FOUND;
944 goto ErrorReturn;
945 }
946
947 Private->NtNetUtilityTable.Transmit = (NT_NET_TRANSMIT) GetProcAddress (Private->NetworkLibraryHandle, NETWORK_LIBRARY_TRANSMIT);
948 if (NULL == Private->NtNetUtilityTable.Transmit) {
949 Status = EFI_NOT_FOUND;
950 goto ErrorReturn;
951 }
952
953 //
954 // Initialize the network utility library
955 // And enumerate the interfaces in emulator host
956 //
957 ReturnValue = Private->NtNetUtilityTable.Initialize (&InterfaceCount, &NetInterfaceInfoBuffer[0]);
958 if (ReturnValue <= 0) {
959 Status = EFI_DEVICE_ERROR;
960 goto ErrorReturn;
961 }
962
963 NetUtilityLibInitDone = TRUE;
964
965 if (InterfaceCount == 0) {
966 Status = EFI_NOT_FOUND;
967 goto ErrorReturn;
968 }
969
970 DEBUG ((DEBUG_INFO, "%a, total %d interface(s) found\n", __FUNCTION__, InterfaceCount));
971 //
972 // Active interface index is set to first interface if given instance does
973 // not exist.
974 //
975 ActiveInterfaceIndex = (ActiveInstance >= InterfaceCount ? DEFAULT_SELECTED_NIC_INDEX : ActiveInstance);
976
977 //
978 // Initialize instance
979 //
980 Status = WinNtInitializeInstanceData (&Private->Instance, &NetInterfaceInfoBuffer[ActiveInterfaceIndex]);
981 if (EFI_ERROR (Status)) {
982 goto ErrorReturn;
983 }
984
985 return EFI_SUCCESS;
986
987 ErrorReturn:
988
989 if (Private->Instance.RecycledTxBuf != NULL) {
990 free (Private->Instance.RecycledTxBuf);
991 }
992
993 if (NetUtilityLibInitDone) {
994 if (Private->NtNetUtilityTable.Finalize != NULL) {
995 Private->NtNetUtilityTable.Finalize ();
996 Private->NtNetUtilityTable.Finalize = NULL;
997 }
998 }
999
1000 return Status;
1001 }
1002
1003 /**
1004 Release the net utility data.
1005
1006 @param This Pointer to the private data.
1007
1008 @retval EFI_SUCCESS The global data is released.
1009 @retval other Other errors.
1010
1011 **/
1012 EFI_STATUS
1013 WintNtReleaseNetUtilityData (
1014 IN OUT WIN_NT_SNP_PRIVATE *Private
1015 )
1016 {
1017 if (Private == NULL) {
1018 return EFI_INVALID_PARAMETER;
1019 }
1020
1021 if (Private->Instance.RecycledTxBuf != NULL) {
1022 free (Private->Instance.RecycledTxBuf);
1023 }
1024
1025 if (Private->NtNetUtilityTable.Finalize != NULL) {
1026 Private->NtNetUtilityTable.Finalize ();
1027 }
1028
1029 FreeLibrary (Private->NetworkLibraryHandle);
1030
1031 return EFI_SUCCESS;
1032 }
1033
1034 EMU_SNP_PROTOCOL mWinNtSnpProtocol = {
1035 WinNtSnpCreateMapping,
1036 WinNtSnpStart,
1037 WinNtSnpStop,
1038 WinNtSnpInitialize,
1039 WinNtSnpReset,
1040 WinNtSnpShutdown,
1041 WinNtSnpReceiveFilters,
1042 WinNtSnpStationAddress,
1043 WinNtSnpStatistics,
1044 WinNtSnpMCastIpToMac,
1045 WinNtSnpNvData,
1046 WinNtSnpGetStatus,
1047 WinNtSnpTransmit,
1048 WinNtSnpReceive
1049 };
1050
1051 /**
1052 Open SNP thunk protocol.
1053
1054 @param This Pointer to the thunk protocol instance.
1055
1056 @retval EFI_SUCCESS SNP thunk protocol is opened successfully.
1057 @retval EFI_UNSUPPORTED This is not SNP thunk protocol.
1058 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1059 @retval other Other errors.
1060
1061 **/
1062 EFI_STATUS
1063 WinNtSnpThunkOpen (
1064 IN EMU_IO_THUNK_PROTOCOL *This
1065 )
1066 {
1067 WIN_NT_SNP_PRIVATE *Private;
1068 UINT8 HostInterfaceIndex;
1069
1070 HostInterfaceIndex = 0;
1071
1072 if (This->Private != NULL) {
1073 return EFI_ALREADY_STARTED;
1074 }
1075
1076 if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) {
1077 return EFI_UNSUPPORTED;
1078 }
1079
1080 Private = malloc (sizeof (WIN_NT_SNP_PRIVATE));
1081 if (Private == NULL) {
1082 return EFI_OUT_OF_RESOURCES;
1083 }
1084
1085 Private->Signature = WIN_NT_SIMPLE_NETWORK_PRIVATE_SIGNATURE;
1086 Private->Thunk = This;
1087 CopyMem (&Private->EmuSnp, &mWinNtSnpProtocol, sizeof (mWinNtSnpProtocol));
1088
1089 This->Interface = &Private->EmuSnp;
1090 This->Private = Private;
1091
1092 if (This->ConfigString != NULL && This->ConfigString[0] != '\0') {
1093 HostInterfaceIndex = (UINT8)StrDecimalToUintn (This->ConfigString);
1094 }
1095
1096 return WintNtInitializeNetUtilityData (Private, HostInterfaceIndex);
1097 }
1098
1099 /**
1100 Close SNP thunk protocol.
1101
1102 @param This Pointer to the thunk protocol instance.
1103
1104 @retval EFI_SUCCESS SNP thunk protocol is closed successfully.
1105 @retval EFI_UNSUPPORTED This is not SNP thunk protocol.
1106 @retval other Other errors.
1107
1108 **/
1109 EFI_STATUS
1110 WinNtSnpThunkClose (
1111 IN EMU_IO_THUNK_PROTOCOL *This
1112 )
1113 {
1114 WIN_NT_SNP_PRIVATE *Private;
1115
1116 if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) {
1117 return EFI_UNSUPPORTED;
1118 }
1119
1120 Private = This->Private;
1121 WintNtReleaseNetUtilityData (Private);
1122 free (Private);
1123
1124 return EFI_SUCCESS;
1125 }
1126
1127 EMU_IO_THUNK_PROTOCOL mWinNtSnpThunkIo = {
1128 &gEmuSnpProtocolGuid,
1129 NULL,
1130 NULL,
1131 0,
1132 WinNtSnpThunkOpen,
1133 WinNtSnpThunkClose,
1134 NULL
1135 };