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
WinNtSnpCreateMapping(IN EMU_SNP_PROTOCOL * This,IN EFI_SIMPLE_NETWORK_MODE * Mode)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
WinNtSnpStart(IN EMU_SNP_PROTOCOL * This)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
WinNtSnpStop(IN EMU_SNP_PROTOCOL * This)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
WinNtSnpInitialize(IN EMU_SNP_PROTOCOL * This,IN UINTN ExtraRxBufferSize OPTIONAL,IN UINTN ExtraTxBufferSize OPTIONAL)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
WinNtSnpReset(IN EMU_SNP_PROTOCOL * This,IN BOOLEAN ExtendedVerification)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
WinNtSnpShutdown(IN EMU_SNP_PROTOCOL * This)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
WinNtSnpReceiveFilters(IN EMU_SNP_PROTOCOL * This,IN UINT32 Enable,IN UINT32 Disable,IN BOOLEAN ResetMCastFilter,IN UINTN MCastFilterCnt OPTIONAL,IN EFI_MAC_ADDRESS * MCastFilter OPTIONAL)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
WinNtSnpStationAddress(IN EMU_SNP_PROTOCOL * This,IN BOOLEAN Reset,IN EFI_MAC_ADDRESS * New OPTIONAL)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
WinNtSnpStatistics(IN EMU_SNP_PROTOCOL * This,IN BOOLEAN Reset,IN OUT UINTN * StatisticsSize OPTIONAL,OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL)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
WinNtSnpMCastIpToMac(IN EMU_SNP_PROTOCOL * This,IN BOOLEAN IPv6,IN EFI_IP_ADDRESS * IP,OUT EFI_MAC_ADDRESS * MAC)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
WinNtSnpNvData(IN EMU_SNP_PROTOCOL * This,IN BOOLEAN ReadWrite,IN UINTN Offset,IN UINTN BufferSize,IN OUT VOID * Buffer)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
WinNtSnpGetStatus(IN EMU_SNP_PROTOCOL * This,OUT UINT32 * InterruptStatus OPTIONAL,OUT VOID ** TxBuf OPTIONAL)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
WinNtSnpTransmit(IN EMU_SNP_PROTOCOL * This,IN UINTN HeaderSize,IN UINTN BufferSize,IN VOID * Buffer,IN EFI_MAC_ADDRESS * SrcAddr OPTIONAL,IN EFI_MAC_ADDRESS * DestAddr OPTIONAL,IN UINT16 * Protocol OPTIONAL)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
WinNtSnpReceive(IN EMU_SNP_PROTOCOL * This,OUT UINTN * HeaderSize OPTIONAL,IN OUT UINTN * BufferSize,OUT VOID * Buffer,OUT EFI_MAC_ADDRESS * SrcAddr OPTIONAL,OUT EFI_MAC_ADDRESS * DestAddr OPTIONAL,OUT UINT16 * Protocol OPTIONAL)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
WinNtInitializeInstanceData(IN OUT WIN_NT_INSTANCE_DATA * Instance,IN NT_NET_INTERFACE_INFO * NetInfo)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
WintNtInitializeNetUtilityData(IN OUT WIN_NT_SNP_PRIVATE * Private,IN UINT8 ActiveInstance)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
WintNtReleaseNetUtilityData(IN OUT WIN_NT_SNP_PRIVATE * Private)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
WinNtSnpThunkOpen(IN EMU_IO_THUNK_PROTOCOL * This)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
WinNtSnpThunkClose(IN EMU_IO_THUNK_PROTOCOL * This)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 };
1136