]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / EmulatorPkg / Unix / Host / BerkeleyPacketFilter.c
CommitLineData
2b59fcd5 1/**@file\r
d18d8a1d 2 Berkeley Packet Filter implementation of the EMU_SNP_PROTOCOL that allows the\r
2b59fcd5 3 emulator to get on real networks.\r
4\r
d18d8a1d 5 Tested on Mac OS X.\r
2b59fcd5 6\r
9e3ab94d 7Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>\r
26cfe2c6 8Portions copyright (c) 2011, Apple Inc. All rights reserved.\r
2b59fcd5 9\r
e3ba31da 10SPDX-License-Identifier: BSD-2-Clause-Patent\r
2b59fcd5 11\r
12**/\r
13\r
59ad461d 14#include "Host.h"\r
2b59fcd5 15\r
16#ifdef __APPLE__\r
17\r
a550d468 18 #include <Library/NetLib.h>\r
2b59fcd5 19\r
a550d468 20#define EMU_SNP_PRIVATE_SIGNATURE SIGNATURE_32('E', 'M', 's', 'n')\r
2b59fcd5 21typedef struct {\r
a550d468 22 UINTN Signature;\r
2b59fcd5 23\r
a550d468
MK
24 EMU_IO_THUNK_PROTOCOL *Thunk;\r
25 EMU_SNP_PROTOCOL EmuSnp;\r
26 EFI_SIMPLE_NETWORK_MODE *Mode;\r
2b59fcd5 27\r
a550d468
MK
28 int BpfFd;\r
29 char *InterfaceName;\r
30 EFI_MAC_ADDRESS MacAddress;\r
31 u_int ReadBufferSize;\r
32 VOID *ReadBuffer;\r
2b59fcd5 33\r
34 //\r
35 // Two walking pointers to manage the multiple packets that can be returned\r
36 // in a single read.\r
37 //\r
a550d468
MK
38 VOID *CurrentReadPointer;\r
39 VOID *EndReadPointer;\r
2b59fcd5 40\r
a550d468
MK
41 UINT32 ReceivedPackets;\r
42 UINT32 DroppedPackets;\r
2b59fcd5 43} EMU_SNP_PRIVATE;\r
44\r
45#define EMU_SNP_PRIVATE_DATA_FROM_THIS(a) \\r
46 CR(a, EMU_SNP_PRIVATE, EmuSnp, EMU_SNP_PRIVATE_SIGNATURE)\r
47\r
2b59fcd5 48//\r
49// Strange, but there doesn't appear to be any structure for the Ethernet header in edk2...\r
50//\r
51\r
52typedef struct {\r
a550d468
MK
53 UINT8 DstAddr[NET_ETHER_ADDR_LEN];\r
54 UINT8 SrcAddr[NET_ETHER_ADDR_LEN];\r
55 UINT16 Type;\r
2b59fcd5 56} ETHERNET_HEADER;\r
57\r
58/**\r
59 Register storage for SNP Mode.\r
60\r
61 @param This Protocol instance pointer.\r
62 @param Mode SimpleNetworkProtocol Mode structure passed into driver.\r
63\r
64 @retval EFI_SUCCESS The network interface was started.\r
65 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
66\r
67**/\r
68EFI_STATUS\r
69EmuSnpCreateMapping (\r
70 IN EMU_SNP_PROTOCOL *This,\r
71 IN EFI_SIMPLE_NETWORK_MODE *Mode\r
72 )\r
73{\r
a550d468 74 EMU_SNP_PRIVATE *Private;\r
2b59fcd5 75\r
76 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
77\r
78 Private->Mode = Mode;\r
d18d8a1d 79\r
2b59fcd5 80 //\r
81 // Set the broadcast address.\r
82 //\r
83 SetMem (&Mode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);\r
84\r
85 CopyMem (&Mode->CurrentAddress, &Private->MacAddress, sizeof (EFI_MAC_ADDRESS));\r
86 CopyMem (&Mode->PermanentAddress, &Private->MacAddress, sizeof (EFI_MAC_ADDRESS));\r
87\r
88 //\r
89 // Since the fake SNP is based on a real NIC, to avoid conflict with the host NIC\r
90 // network stack, we use a different MAC address.\r
91 // So just change the last byte of the MAC address for the real NIC.\r
92 //\r
93 Mode->CurrentAddress.Addr[NET_ETHER_ADDR_LEN - 1]++;\r
94\r
95 return EFI_SUCCESS;\r
96}\r
97\r
a550d468 98static struct bpf_insn mFilterInstructionTemplate[] = {\r
2b59fcd5 99 // Load 4 bytes from the destination MAC address.\r
a550d468 100 BPF_STMT (BPF_LD + BPF_W + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[0])),\r
2b59fcd5 101\r
102 // Compare to first 4 bytes of fake MAC address.\r
a550d468 103 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x12345678, 0, 3),\r
2b59fcd5 104\r
105 // Load remaining 2 bytes from the destination MAC address.\r
a550d468 106 BPF_STMT (BPF_LD + BPF_H + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[4])),\r
2b59fcd5 107\r
108 // Compare to remaining 2 bytes of fake MAC address.\r
a550d468 109 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x9ABC, 5, 0),\r
2b59fcd5 110\r
111 // Load 4 bytes from the destination MAC address.\r
a550d468 112 BPF_STMT (BPF_LD + BPF_W + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[0])),\r
2b59fcd5 113\r
114 // Compare to first 4 bytes of broadcast MAC address.\r
a550d468 115 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0xFFFFFFFF, 0, 2),\r
2b59fcd5 116\r
117 // Load remaining 2 bytes from the destination MAC address.\r
a550d468 118 BPF_STMT (BPF_LD + BPF_H + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[4])),\r
2b59fcd5 119\r
120 // Compare to remaining 2 bytes of broadcast MAC address.\r
a550d468 121 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0xFFFF, 1, 0),\r
2b59fcd5 122\r
123 // Reject packet.\r
a550d468 124 BPF_STMT (BPF_RET + BPF_K, 0),\r
2b59fcd5 125\r
126 // Receive entire packet.\r
a550d468 127 BPF_STMT (BPF_RET + BPF_K, -1)\r
2b59fcd5 128};\r
129\r
2b59fcd5 130EFI_STATUS\r
131OpenBpfFileDescriptor (\r
132 IN EMU_SNP_PRIVATE *Private,\r
133 OUT int *Fd\r
134 )\r
135{\r
136 char BfpDeviceName[256];\r
137 int Index;\r
138\r
139 //\r
140 // Open a Berkeley Packet Filter device. This must be done as root, so this is probably\r
141 // the place which is most likely to fail...\r
142 //\r
143 for (Index = 0; TRUE; Index++ ) {\r
144 snprintf (BfpDeviceName, sizeof (BfpDeviceName), "/dev/bpf%d", Index);\r
145\r
146 *Fd = open (BfpDeviceName, O_RDWR, 0);\r
147 if ( *Fd >= 0 ) {\r
148 return EFI_SUCCESS;\r
149 }\r
150\r
151 if (errno == EACCES) {\r
152 printf (\r
153 "SNP: Permissions on '%s' are incorrect. Fix with 'sudo chmod 666 %s'.\n",\r
d18d8a1d 154 BfpDeviceName,\r
155 BfpDeviceName\r
2b59fcd5 156 );\r
157 }\r
d18d8a1d 158\r
2b59fcd5 159 if (errno != EBUSY) {\r
160 break;\r
161 }\r
162 }\r
163\r
164 return EFI_OUT_OF_RESOURCES;\r
165}\r
166\r
2b59fcd5 167/**\r
168 Changes the state of a network interface from "stopped" to "started".\r
169\r
170 @param This Protocol instance pointer.\r
171\r
172 @retval EFI_SUCCESS The network interface was started.\r
173 @retval EFI_ALREADY_STARTED The network interface is already in the started state.\r
174 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
175 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
176 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
177\r
178**/\r
179EFI_STATUS\r
180EmuSnpStart (\r
181 IN EMU_SNP_PROTOCOL *This\r
182 )\r
183{\r
a550d468
MK
184 EFI_STATUS Status;\r
185 EMU_SNP_PRIVATE *Private;\r
186 struct ifreq BoundIf;\r
187 struct bpf_program BpfProgram;\r
188 struct bpf_insn *FilterProgram;\r
79e4f2a5
RN
189 u_int Value;\r
190 u_int ReadBufferSize;\r
a550d468
MK
191 UINT16 Temp16;\r
192 UINT32 Temp32;\r
2b59fcd5 193\r
194 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
195\r
196 switch (Private->Mode->State) {\r
197 case EfiSimpleNetworkStopped:\r
198 break;\r
199\r
200 case EfiSimpleNetworkStarted:\r
201 case EfiSimpleNetworkInitialized:\r
202 return EFI_ALREADY_STARTED;\r
203 break;\r
204\r
205 default:\r
206 return EFI_DEVICE_ERROR;\r
207 break;\r
208 }\r
209\r
a550d468 210 Status = EFI_SUCCESS;\r
97a1b9f4 211 Private->ReadBuffer = NULL;\r
2b59fcd5 212 if (Private->BpfFd == 0) {\r
213 Status = OpenBpfFileDescriptor (Private, &Private->BpfFd);\r
214 if (EFI_ERROR (Status)) {\r
215 goto DeviceErrorExit;\r
216 }\r
217\r
218 //\r
79e4f2a5
RN
219 // Get the read buffer size.\r
220 //\r
221 if (ioctl (Private->BpfFd, BIOCGBLEN, &ReadBufferSize) < 0) {\r
222 goto DeviceErrorExit;\r
223 }\r
224\r
225 //\r
226 // Default value from BIOCGBLEN is usually too small, so use a much larger size, if necessary.\r
227 //\r
228 if (ReadBufferSize < FixedPcdGet32 (PcdNetworkPacketFilterSize)) {\r
229 ReadBufferSize = FixedPcdGet32 (PcdNetworkPacketFilterSize);\r
230 if (ioctl (Private->BpfFd, BIOCSBLEN, &ReadBufferSize) < 0) {\r
231 goto DeviceErrorExit;\r
232 }\r
233 }\r
234\r
235 //\r
2b59fcd5 236 // Associate our interface with this BPF file descriptor.\r
237 //\r
9e3ab94d 238 AsciiStrCpyS (BoundIf.ifr_name, sizeof (BoundIf.ifr_name), Private->InterfaceName);\r
2b59fcd5 239 if (ioctl (Private->BpfFd, BIOCSETIF, &BoundIf) < 0) {\r
240 goto DeviceErrorExit;\r
241 }\r
242\r
243 //\r
79e4f2a5 244 // Enable immediate mode.\r
2b59fcd5 245 //\r
246 Value = 1;\r
247 if (ioctl (Private->BpfFd, BIOCIMMEDIATE, &Value) < 0) {\r
248 goto DeviceErrorExit;\r
249 }\r
250\r
251 //\r
252 // Enable non-blocking I/O.\r
253 //\r
254 if (fcntl (Private->BpfFd, F_GETFL, 0) == -1) {\r
255 goto DeviceErrorExit;\r
256 }\r
257\r
258 Value |= O_NONBLOCK;\r
259\r
260 if (fcntl (Private->BpfFd, F_SETFL, Value) == -1) {\r
261 goto DeviceErrorExit;\r
262 }\r
263\r
264 //\r
265 // Disable "header complete" flag. This means the supplied source MAC address is\r
266 // what goes on the wire.\r
267 //\r
268 Value = 1;\r
269 if (ioctl (Private->BpfFd, BIOCSHDRCMPLT, &Value) < 0) {\r
270 goto DeviceErrorExit;\r
271 }\r
272\r
273 //\r
274 // Allocate read buffer.\r
275 //\r
79e4f2a5 276 Private->ReadBufferSize = ReadBufferSize;\r
a550d468 277 Private->ReadBuffer = malloc (Private->ReadBufferSize);\r
2b59fcd5 278 if (Private->ReadBuffer == NULL) {\r
279 goto ErrorExit;\r
280 }\r
281\r
282 Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer;\r
283\r
284 //\r
79e4f2a5 285 // Install our packet filter: successful reads should only produce broadcast or unicast\r
2b59fcd5 286 // packets directed to our fake MAC address.\r
287 //\r
a550d468 288 FilterProgram = malloc (sizeof (mFilterInstructionTemplate));\r
2b59fcd5 289 if ( FilterProgram == NULL ) {\r
290 goto ErrorExit;\r
291 }\r
d18d8a1d 292\r
2b59fcd5 293 CopyMem (FilterProgram, &mFilterInstructionTemplate, sizeof (mFilterInstructionTemplate));\r
294\r
295 //\r
296 // Insert out fake MAC address into the filter. The data has to be host endian.\r
297 //\r
298 CopyMem (&Temp32, &Private->Mode->CurrentAddress.Addr[0], sizeof (UINT32));\r
299 FilterProgram[1].k = NTOHL (Temp32);\r
300 CopyMem (&Temp16, &Private->Mode->CurrentAddress.Addr[4], sizeof (UINT16));\r
301 FilterProgram[3].k = NTOHS (Temp16);\r
302\r
a550d468 303 BpfProgram.bf_len = sizeof (mFilterInstructionTemplate) / sizeof (struct bpf_insn);\r
2b59fcd5 304 BpfProgram.bf_insns = FilterProgram;\r
305\r
306 if (ioctl (Private->BpfFd, BIOCSETF, &BpfProgram) < 0) {\r
307 goto DeviceErrorExit;\r
308 }\r
309\r
310 free (FilterProgram);\r
311\r
312 //\r
313 // Enable promiscuous mode.\r
314 //\r
315 if (ioctl (Private->BpfFd, BIOCPROMISC, 0) < 0) {\r
316 goto DeviceErrorExit;\r
317 }\r
318\r
d18d8a1d 319 Private->Mode->State = EfiSimpleNetworkStarted;\r
2b59fcd5 320 }\r
321\r
322 return Status;\r
323\r
324DeviceErrorExit:\r
325 Status = EFI_DEVICE_ERROR;\r
326ErrorExit:\r
327 if (Private->ReadBuffer != NULL) {\r
328 free (Private->ReadBuffer);\r
329 Private->ReadBuffer = NULL;\r
330 }\r
a550d468 331\r
2b59fcd5 332 return Status;\r
333}\r
334\r
2b59fcd5 335/**\r
336 Changes the state of a network interface from "started" to "stopped".\r
337\r
338 @param This Protocol instance pointer.\r
339\r
340 @retval EFI_SUCCESS The network interface was stopped.\r
341 @retval EFI_ALREADY_STARTED The network interface is already in the stopped state.\r
342 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
343 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
344 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
345\r
346**/\r
347EFI_STATUS\r
348EmuSnpStop (\r
349 IN EMU_SNP_PROTOCOL *This\r
350 )\r
351{\r
a550d468 352 EMU_SNP_PRIVATE *Private;\r
2b59fcd5 353\r
354 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
355\r
356 switch ( Private->Mode->State ) {\r
357 case EfiSimpleNetworkStarted:\r
358 break;\r
359\r
360 case EfiSimpleNetworkStopped:\r
361 return EFI_NOT_STARTED;\r
362 break;\r
363\r
364 default:\r
365 return EFI_DEVICE_ERROR;\r
366 break;\r
367 }\r
368\r
369 if (Private->BpfFd != 0) {\r
370 close (Private->BpfFd);\r
371 Private->BpfFd = 0;\r
372 }\r
373\r
374 if (Private->ReadBuffer != NULL) {\r
a550d468 375 free (Private->ReadBuffer);\r
2b59fcd5 376 Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer = NULL;\r
377 }\r
378\r
379 Private->Mode->State = EfiSimpleNetworkStopped;\r
380\r
381 return EFI_SUCCESS;\r
382}\r
383\r
2b59fcd5 384/**\r
d18d8a1d 385 Resets a network adapter and allocates the transmit and receive buffers\r
386 required by the network interface; optionally, also requests allocation\r
2b59fcd5 387 of additional transmit and receive buffers.\r
388\r
389 @param This The protocol instance pointer.\r
390 @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space\r
391 that the driver should allocate for the network interface.\r
392 Some network interfaces will not be able to use the extra\r
393 buffer, and the caller will not know if it is actually\r
394 being used.\r
395 @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space\r
396 that the driver should allocate for the network interface.\r
397 Some network interfaces will not be able to use the extra\r
398 buffer, and the caller will not know if it is actually\r
399 being used.\r
400\r
401 @retval EFI_SUCCESS The network interface was initialized.\r
402 @retval EFI_NOT_STARTED The network interface has not been started.\r
403 @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and\r
404 receive buffers.\r
405 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
406 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
407 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
408\r
409**/\r
410EFI_STATUS\r
411EmuSnpInitialize (\r
a550d468
MK
412 IN EMU_SNP_PROTOCOL *This,\r
413 IN UINTN ExtraRxBufferSize OPTIONAL,\r
414 IN UINTN ExtraTxBufferSize OPTIONAL\r
2b59fcd5 415 )\r
416{\r
a550d468 417 EMU_SNP_PRIVATE *Private;\r
2b59fcd5 418\r
419 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
420\r
421 switch ( Private->Mode->State ) {\r
422 case EfiSimpleNetworkStarted:\r
423 break;\r
424\r
425 case EfiSimpleNetworkStopped:\r
426 return EFI_NOT_STARTED;\r
427 break;\r
428\r
429 default:\r
430 return EFI_DEVICE_ERROR;\r
431 break;\r
432 }\r
433\r
a550d468 434 Private->Mode->MCastFilterCount = 0;\r
2b59fcd5 435 Private->Mode->ReceiveFilterSetting = 0;\r
436 ZeroMem (Private->Mode->MCastFilter, sizeof (Private->Mode->MCastFilter));\r
437\r
438 Private->Mode->State = EfiSimpleNetworkInitialized;\r
439\r
440 return EFI_SUCCESS;\r
441}\r
442\r
2b59fcd5 443/**\r
d18d8a1d 444 Resets a network adapter and re-initializes it with the parameters that were\r
445 provided in the previous call to Initialize().\r
2b59fcd5 446\r
447 @param This The protocol instance pointer.\r
448 @param ExtendedVerification Indicates that the driver may perform a more\r
449 exhaustive verification operation of the device\r
450 during reset.\r
451\r
452 @retval EFI_SUCCESS The network interface was reset.\r
453 @retval EFI_NOT_STARTED The network interface has not been started.\r
454 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
455 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
456 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
457\r
458**/\r
459EFI_STATUS\r
460EmuSnpReset (\r
a550d468
MK
461 IN EMU_SNP_PROTOCOL *This,\r
462 IN BOOLEAN ExtendedVerification\r
2b59fcd5 463 )\r
464{\r
a550d468 465 EMU_SNP_PRIVATE *Private;\r
2b59fcd5 466\r
467 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
468\r
469 switch ( Private->Mode->State ) {\r
470 case EfiSimpleNetworkInitialized:\r
471 break;\r
472\r
473 case EfiSimpleNetworkStopped:\r
474 return EFI_NOT_STARTED;\r
475 break;\r
476\r
477 default:\r
478 return EFI_DEVICE_ERROR;\r
479 break;\r
480 }\r
481\r
482 return EFI_SUCCESS;\r
483}\r
484\r
2b59fcd5 485/**\r
d18d8a1d 486 Resets a network adapter and leaves it in a state that is safe for\r
2b59fcd5 487 another driver to initialize.\r
488\r
489 @param This Protocol instance pointer.\r
490\r
491 @retval EFI_SUCCESS The network interface was shutdown.\r
492 @retval EFI_NOT_STARTED The network interface has not been started.\r
493 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
494 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
495 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
496\r
497**/\r
498EFI_STATUS\r
499EmuSnpShutdown (\r
500 IN EMU_SNP_PROTOCOL *This\r
501 )\r
502{\r
a550d468 503 EMU_SNP_PRIVATE *Private;\r
2b59fcd5 504\r
505 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
506\r
507 switch ( Private->Mode->State ) {\r
508 case EfiSimpleNetworkInitialized:\r
509 break;\r
510\r
511 case EfiSimpleNetworkStopped:\r
512 return EFI_NOT_STARTED;\r
513 break;\r
514\r
515 default:\r
516 return EFI_DEVICE_ERROR;\r
517 break;\r
518 }\r
519\r
520 Private->Mode->State = EfiSimpleNetworkStarted;\r
521\r
522 Private->Mode->ReceiveFilterSetting = 0;\r
a550d468 523 Private->Mode->MCastFilterCount = 0;\r
2b59fcd5 524 ZeroMem (Private->Mode->MCastFilter, sizeof (Private->Mode->MCastFilter));\r
525\r
526 if (Private->BpfFd != 0) {\r
527 close (Private->BpfFd);\r
528 Private->BpfFd = 0;\r
529 }\r
530\r
531 if (Private->ReadBuffer != NULL) {\r
532 free (Private->ReadBuffer);\r
533 Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer = NULL;\r
534 }\r
535\r
536 return EFI_SUCCESS;\r
537}\r
538\r
539/**\r
540 Manages the multicast receive filters of a network interface.\r
541\r
542 @param This The protocol instance pointer.\r
543 @param Enable A bit mask of receive filters to enable on the network interface.\r
544 @param Disable A bit mask of receive filters to disable on the network interface.\r
545 @param ResetMCastFilter Set to TRUE to reset the contents of the multicast receive\r
546 filters on the network interface to their default values.\r
547 @param McastFilterCnt Number of multicast HW MAC addresses in the new\r
548 MCastFilter list. This value must be less than or equal to\r
549 the MCastFilterCnt field of EMU_SNP_MODE. This\r
550 field is optional if ResetMCastFilter is TRUE.\r
551 @param MCastFilter A pointer to a list of new multicast receive filter HW MAC\r
552 addresses. This list will replace any existing multicast\r
553 HW MAC address list. This field is optional if\r
554 ResetMCastFilter is TRUE.\r
555\r
556 @retval EFI_SUCCESS The multicast receive filter list was updated.\r
557 @retval EFI_NOT_STARTED The network interface has not been started.\r
558 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
559 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
560 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
561\r
562**/\r
563EFI_STATUS\r
564EmuSnpReceiveFilters (\r
a550d468
MK
565 IN EMU_SNP_PROTOCOL *This,\r
566 IN UINT32 Enable,\r
567 IN UINT32 Disable,\r
568 IN BOOLEAN ResetMCastFilter,\r
569 IN UINTN MCastFilterCnt OPTIONAL,\r
570 IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL\r
2b59fcd5 571 )\r
572{\r
a550d468 573 EMU_SNP_PRIVATE *Private;\r
2b59fcd5 574\r
575 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
576\r
577 // For now, just succeed...\r
578 return EFI_SUCCESS;\r
579}\r
580\r
2b59fcd5 581/**\r
582 Modifies or resets the current station address, if supported.\r
583\r
584 @param This The protocol instance pointer.\r
585 @param Reset Flag used to reset the station address to the network interfaces\r
586 permanent address.\r
587 @param New The new station address to be used for the network interface.\r
588\r
589 @retval EFI_SUCCESS The network interfaces station address was updated.\r
590 @retval EFI_NOT_STARTED The network interface has not been started.\r
591 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
592 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
593 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
594\r
595**/\r
596EFI_STATUS\r
597EmuSnpStationAddress (\r
a550d468
MK
598 IN EMU_SNP_PROTOCOL *This,\r
599 IN BOOLEAN Reset,\r
600 IN EFI_MAC_ADDRESS *New OPTIONAL\r
2b59fcd5 601 )\r
602{\r
a550d468 603 EMU_SNP_PRIVATE *Private;\r
2b59fcd5 604\r
605 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
606\r
607 return EFI_UNSUPPORTED;\r
608}\r
609\r
2b59fcd5 610/**\r
611 Resets or collects the statistics on a network interface.\r
612\r
613 @param This Protocol instance pointer.\r
614 @param Reset Set to TRUE to reset the statistics for the network interface.\r
615 @param StatisticsSize On input the size, in bytes, of StatisticsTable. On\r
616 output the size, in bytes, of the resulting table of\r
617 statistics.\r
618 @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that\r
619 contains the statistics.\r
620\r
621 @retval EFI_SUCCESS The statistics were collected from the network interface.\r
622 @retval EFI_NOT_STARTED The network interface has not been started.\r
623 @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer\r
624 size needed to hold the statistics is returned in\r
625 StatisticsSize.\r
626 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
627 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
628 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
629\r
630**/\r
631EFI_STATUS\r
632EmuSnpStatistics (\r
a550d468
MK
633 IN EMU_SNP_PROTOCOL *This,\r
634 IN BOOLEAN Reset,\r
635 IN OUT UINTN *StatisticsSize OPTIONAL,\r
636 OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL\r
2b59fcd5 637 )\r
638{\r
a550d468 639 EMU_SNP_PRIVATE *Private;\r
2b59fcd5 640\r
641 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
642\r
643 return EFI_UNSUPPORTED;\r
644}\r
645\r
2b59fcd5 646/**\r
647 Converts a multicast IP address to a multicast HW MAC address.\r
648\r
649 @param This The protocol instance pointer.\r
650 @param IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460]. Set\r
651 to FALSE if the multicast IP address is IPv4 [RFC 791].\r
652 @param IP The multicast IP address that is to be converted to a multicast\r
653 HW MAC address.\r
654 @param MAC The multicast HW MAC address that is to be generated from IP.\r
655\r
656 @retval EFI_SUCCESS The multicast IP address was mapped to the multicast\r
657 HW MAC address.\r
658 @retval EFI_NOT_STARTED The network interface has not been started.\r
659 @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer\r
660 size needed to hold the statistics is returned in\r
661 StatisticsSize.\r
662 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
663 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
664 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
665\r
666**/\r
667EFI_STATUS\r
668EmuSnpMCastIpToMac (\r
a550d468
MK
669 IN EMU_SNP_PROTOCOL *This,\r
670 IN BOOLEAN IPv6,\r
671 IN EFI_IP_ADDRESS *IP,\r
672 OUT EFI_MAC_ADDRESS *MAC\r
2b59fcd5 673 )\r
674{\r
a550d468 675 EMU_SNP_PRIVATE *Private;\r
2b59fcd5 676\r
677 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
678\r
679 return EFI_UNSUPPORTED;\r
680}\r
681\r
2b59fcd5 682/**\r
d18d8a1d 683 Performs read and write operations on the NVRAM device attached to a\r
2b59fcd5 684 network interface.\r
685\r
686 @param This The protocol instance pointer.\r
687 @param ReadWrite TRUE for read operations, FALSE for write operations.\r
688 @param Offset Byte offset in the NVRAM device at which to start the read or\r
689 write operation. This must be a multiple of NvRamAccessSize and\r
690 less than NvRamSize.\r
691 @param BufferSize The number of bytes to read or write from the NVRAM device.\r
692 This must also be a multiple of NvramAccessSize.\r
693 @param Buffer A pointer to the data buffer.\r
694\r
695 @retval EFI_SUCCESS The NVRAM access was performed.\r
696 @retval EFI_NOT_STARTED The network interface has not been started.\r
697 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
698 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
699 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
700\r
701**/\r
702EFI_STATUS\r
703EmuSnpNvData (\r
a550d468
MK
704 IN EMU_SNP_PROTOCOL *This,\r
705 IN BOOLEAN ReadWrite,\r
706 IN UINTN Offset,\r
707 IN UINTN BufferSize,\r
708 IN OUT VOID *Buffer\r
2b59fcd5 709 )\r
710{\r
a550d468 711 EMU_SNP_PRIVATE *Private;\r
2b59fcd5 712\r
713 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
714\r
715 return EFI_UNSUPPORTED;\r
716}\r
717\r
718/**\r
d18d8a1d 719 Reads the current interrupt status and recycled transmit buffer status from\r
2b59fcd5 720 a network interface.\r
721\r
722 @param This The protocol instance pointer.\r
723 @param InterruptStatus A pointer to the bit mask of the currently active interrupts\r
724 If this is NULL, the interrupt status will not be read from\r
725 the device. If this is not NULL, the interrupt status will\r
726 be read from the device. When the interrupt status is read,\r
727 it will also be cleared. Clearing the transmit interrupt\r
728 does not empty the recycled transmit buffer array.\r
729 @param TxBuf Recycled transmit buffer address. The network interface will\r
730 not transmit if its internal recycled transmit buffer array\r
731 is full. Reading the transmit buffer does not clear the\r
732 transmit interrupt. If this is NULL, then the transmit buffer\r
733 status will not be read. If there are no transmit buffers to\r
734 recycle and TxBuf is not NULL, * TxBuf will be set to NULL.\r
735\r
736 @retval EFI_SUCCESS The status of the network interface was retrieved.\r
737 @retval EFI_NOT_STARTED The network interface has not been started.\r
738 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
739 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
740 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
741\r
742**/\r
743EFI_STATUS\r
744EmuSnpGetStatus (\r
a550d468
MK
745 IN EMU_SNP_PROTOCOL *This,\r
746 OUT UINT32 *InterruptStatus OPTIONAL,\r
747 OUT VOID **TxBuf OPTIONAL\r
2b59fcd5 748 )\r
749{\r
a550d468 750 EMU_SNP_PRIVATE *Private;\r
2b59fcd5 751\r
752 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
753\r
2b59fcd5 754 if ( InterruptStatus != NULL ) {\r
755 *InterruptStatus = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;\r
756 }\r
757\r
758 return EFI_SUCCESS;\r
759}\r
760\r
2b59fcd5 761/**\r
762 Places a packet in the transmit queue of a network interface.\r
763\r
764 @param This The protocol instance pointer.\r
765 @param HeaderSize The size, in bytes, of the media header to be filled in by\r
766 the Transmit() function. If HeaderSize is non-zero, then it\r
767 must be equal to This->Mode->MediaHeaderSize and the DestAddr\r
768 and Protocol parameters must not be NULL.\r
769 @param BufferSize The size, in bytes, of the entire packet (media header and\r
770 data) to be transmitted through the network interface.\r
771 @param Buffer A pointer to the packet (media header followed by data) to be\r
772 transmitted. This parameter cannot be NULL. If HeaderSize is zero,\r
773 then the media header in Buffer must already be filled in by the\r
774 caller. If HeaderSize is non-zero, then the media header will be\r
775 filled in by the Transmit() function.\r
776 @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter\r
777 is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then\r
778 This->Mode->CurrentAddress is used for the source HW MAC address.\r
779 @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this\r
780 parameter is ignored.\r
781 @param Protocol The type of header to build. If HeaderSize is zero, then this\r
782 parameter is ignored. See RFC 1700, section "Ether Types", for\r
783 examples.\r
784\r
785 @retval EFI_SUCCESS The packet was placed on the transmit queue.\r
786 @retval EFI_NOT_STARTED The network interface has not been started.\r
d18d8a1d 787 @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.\r
2b59fcd5 788 @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
789 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
790 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
791 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
792\r
793**/\r
794EFI_STATUS\r
795EmuSnpTransmit (\r
a550d468
MK
796 IN EMU_SNP_PROTOCOL *This,\r
797 IN UINTN HeaderSize,\r
798 IN UINTN BufferSize,\r
799 IN VOID *Buffer,\r
800 IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
801 IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
802 IN UINT16 *Protocol OPTIONAL\r
2b59fcd5 803 )\r
804{\r
a550d468
MK
805 EMU_SNP_PRIVATE *Private;\r
806 ETHERNET_HEADER *EnetHeader;\r
2b59fcd5 807\r
808 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
809\r
810 if (Private->Mode->State < EfiSimpleNetworkStarted) {\r
811 return EFI_NOT_STARTED;\r
812 }\r
813\r
814 if ( HeaderSize != 0 ) {\r
815 if ((DestAddr == NULL) || (Protocol == NULL) || (HeaderSize != Private->Mode->MediaHeaderSize)) {\r
816 return EFI_INVALID_PARAMETER;\r
817 }\r
818\r
819 if (SrcAddr == NULL) {\r
820 SrcAddr = &Private->Mode->CurrentAddress;\r
821 }\r
822\r
a550d468 823 EnetHeader = (ETHERNET_HEADER *)Buffer;\r
2b59fcd5 824\r
825 CopyMem (EnetHeader->DstAddr, DestAddr, NET_ETHER_ADDR_LEN);\r
826 CopyMem (EnetHeader->SrcAddr, SrcAddr, NET_ETHER_ADDR_LEN);\r
827\r
a550d468 828 EnetHeader->Type = HTONS (*Protocol);\r
2b59fcd5 829 }\r
830\r
a550d468 831 if (write (Private->BpfFd, Buffer, BufferSize) < 0) {\r
2b59fcd5 832 return EFI_DEVICE_ERROR;\r
833 }\r
d18d8a1d 834\r
2b59fcd5 835 return EFI_SUCCESS;\r
836}\r
837\r
838/**\r
839 Receives a packet from a network interface.\r
840\r
841 @param This The protocol instance pointer.\r
842 @param HeaderSize The size, in bytes, of the media header received on the network\r
843 interface. If this parameter is NULL, then the media header size\r
844 will not be returned.\r
845 @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in\r
846 bytes, of the packet that was received on the network interface.\r
847 @param Buffer A pointer to the data buffer to receive both the media header and\r
848 the data.\r
849 @param SrcAddr The source HW MAC address. If this parameter is NULL, the\r
850 HW MAC source address will not be extracted from the media\r
851 header.\r
852 @param DestAddr The destination HW MAC address. If this parameter is NULL,\r
853 the HW MAC destination address will not be extracted from the\r
854 media header.\r
855 @param Protocol The media header type. If this parameter is NULL, then the\r
856 protocol will not be extracted from the media header. See\r
857 RFC 1700 section "Ether Types" for examples.\r
858\r
859 @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has\r
860 been updated to the number of bytes received.\r
861 @retval EFI_NOT_STARTED The network interface has not been started.\r
862 @retval EFI_NOT_READY The network interface is too busy to accept this transmit\r
863 request.\r
864 @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
865 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
866 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
867 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
868\r
869**/\r
870EFI_STATUS\r
871EmuSnpReceive (\r
a550d468
MK
872 IN EMU_SNP_PROTOCOL *This,\r
873 OUT UINTN *HeaderSize OPTIONAL,\r
874 IN OUT UINTN *BufferSize,\r
875 OUT VOID *Buffer,\r
876 OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
877 OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
878 OUT UINT16 *Protocol OPTIONAL\r
2b59fcd5 879 )\r
880{\r
a550d468
MK
881 EMU_SNP_PRIVATE *Private;\r
882 struct bpf_hdr *BpfHeader;\r
883 struct bpf_stat BpfStats;\r
884 ETHERNET_HEADER *EnetHeader;\r
885 ssize_t Result;\r
2b59fcd5 886\r
887 Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);\r
888\r
889 if (Private->Mode->State < EfiSimpleNetworkStarted) {\r
890 return EFI_NOT_STARTED;\r
891 }\r
892\r
a550d468 893 ZeroMem (&BpfStats, sizeof (BpfStats));\r
d18d8a1d 894\r
79e4f2a5
RN
895 if (ioctl (Private->BpfFd, BIOCGSTATS, &BpfStats) == 0) {\r
896 Private->ReceivedPackets += BpfStats.bs_recv;\r
897 if (BpfStats.bs_drop > Private->DroppedPackets) {\r
898 printf (\r
899 "SNP: STATS: RCVD = %d DROPPED = %d. Probably need to increase BPF PcdNetworkPacketFilterSize?\n",\r
900 BpfStats.bs_recv,\r
901 BpfStats.bs_drop - Private->DroppedPackets\r
902 );\r
903 Private->DroppedPackets = BpfStats.bs_drop;\r
904 }\r
905 }\r
2b59fcd5 906\r
907 //\r
908 // Do we have any remaining packets from the previous read?\r
909 //\r
910 if (Private->CurrentReadPointer >= Private->EndReadPointer) {\r
911 Result = read (Private->BpfFd, Private->ReadBuffer, Private->ReadBufferSize);\r
912 if (Result < 0) {\r
913 // EAGAIN means that there's no I/O outstanding against this file descriptor.\r
914 return (errno == EAGAIN) ? EFI_NOT_READY : EFI_DEVICE_ERROR;\r
915 }\r
916\r
917 if (Result == 0) {\r
918 return EFI_NOT_READY;\r
919 }\r
920\r
921 Private->CurrentReadPointer = Private->ReadBuffer;\r
a550d468 922 Private->EndReadPointer = Private->CurrentReadPointer + Result;\r
2b59fcd5 923 }\r
924\r
a550d468 925 BpfHeader = Private->CurrentReadPointer;\r
2b59fcd5 926 EnetHeader = Private->CurrentReadPointer + BpfHeader->bh_hdrlen;\r
927\r
928 if (BpfHeader->bh_caplen > *BufferSize) {\r
929 *BufferSize = BpfHeader->bh_caplen;\r
930 return EFI_BUFFER_TOO_SMALL;\r
931 }\r
932\r
933 CopyMem (Buffer, EnetHeader, BpfHeader->bh_caplen);\r
934 *BufferSize = BpfHeader->bh_caplen;\r
935\r
936 if (HeaderSize != NULL) {\r
937 *HeaderSize = sizeof (ETHERNET_HEADER);\r
938 }\r
939\r
940 if (DestAddr != NULL) {\r
941 ZeroMem (DestAddr, sizeof (EFI_MAC_ADDRESS));\r
942 CopyMem (DestAddr, EnetHeader->DstAddr, NET_ETHER_ADDR_LEN);\r
943 }\r
944\r
945 if (SrcAddr != NULL) {\r
946 ZeroMem (SrcAddr, sizeof (EFI_MAC_ADDRESS));\r
947 CopyMem (SrcAddr, EnetHeader->SrcAddr, NET_ETHER_ADDR_LEN);\r
948 }\r
949\r
950 if (Protocol != NULL) {\r
951 *Protocol = NTOHS (EnetHeader->Type);\r
952 }\r
953\r
954 Private->CurrentReadPointer += BPF_WORDALIGN (BpfHeader->bh_hdrlen + BpfHeader->bh_caplen);\r
955 return EFI_SUCCESS;\r
956}\r
957\r
a550d468 958EMU_SNP_PROTOCOL gEmuSnpProtocol = {\r
2b59fcd5 959 GasketSnpCreateMapping,\r
960 GasketSnpStart,\r
961 GasketSnpStop,\r
962 GasketSnpInitialize,\r
963 GasketSnpReset,\r
964 GasketSnpShutdown,\r
965 GasketSnpReceiveFilters,\r
966 GasketSnpStationAddress,\r
967 GasketSnpStatistics,\r
968 GasketSnpMCastIpToMac,\r
969 GasketSnpNvData,\r
970 GasketSnpGetStatus,\r
971 GasketSnpTransmit,\r
972 GasketSnpReceive\r
973};\r
974\r
975EFI_STATUS\r
976GetInterfaceMacAddr (\r
a550d468 977 EMU_SNP_PRIVATE *Private\r
2b59fcd5 978 )\r
979{\r
79e4f2a5 980 EFI_STATUS Status;\r
2b59fcd5 981 struct ifaddrs *IfAddrs;\r
982 struct ifaddrs *If;\r
983 struct sockaddr_dl *IfSdl;\r
984\r
985 if (getifaddrs (&IfAddrs) != 0) {\r
986 return EFI_UNSUPPORTED;\r
987 }\r
988\r
989 //\r
990 // Convert the interface name to ASCII so we can find it.\r
991 //\r
992 Private->InterfaceName = malloc (StrSize (Private->Thunk->ConfigString));\r
993 if (Private->InterfaceName == NULL) {\r
994 Status = EFI_OUT_OF_RESOURCES;\r
995 goto Exit;\r
996 }\r
997\r
9e3ab94d
MK
998 UnicodeStrToAsciiStrS (\r
999 Private->Thunk->ConfigString,\r
1000 Private->InterfaceName,\r
1001 StrSize (Private->Thunk->ConfigString)\r
1002 );\r
2b59fcd5 1003\r
1004 Status = EFI_NOT_FOUND;\r
a550d468 1005 If = IfAddrs;\r
2b59fcd5 1006 while (If != NULL) {\r
1007 IfSdl = (struct sockaddr_dl *)If->ifa_addr;\r
1008\r
1009 if (IfSdl->sdl_family == AF_LINK) {\r
a550d468 1010 if (!AsciiStrCmp (Private->InterfaceName, If->ifa_name)) {\r
2b59fcd5 1011 CopyMem (&Private->MacAddress, LLADDR (IfSdl), NET_ETHER_ADDR_LEN);\r
1012\r
1013 Status = EFI_SUCCESS;\r
1014 break;\r
1015 }\r
1016 }\r
1017\r
1018 If = If->ifa_next;\r
1019 }\r
1020\r
1021Exit:\r
1022 freeifaddrs (IfAddrs);\r
1023 return Status;\r
1024}\r
1025\r
2b59fcd5 1026EFI_STATUS\r
1027EmuSnpThunkOpen (\r
a550d468 1028 IN EMU_IO_THUNK_PROTOCOL *This\r
2b59fcd5 1029 )\r
1030{\r
1031 EMU_SNP_PRIVATE *Private;\r
d18d8a1d 1032\r
2b59fcd5 1033 if (This->Private != NULL) {\r
1034 return EFI_ALREADY_STARTED;\r
1035 }\r
d18d8a1d 1036\r
2b59fcd5 1037 if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) {\r
1038 return EFI_UNSUPPORTED;\r
1039 }\r
d18d8a1d 1040\r
2b59fcd5 1041 Private = malloc (sizeof (EMU_SNP_PRIVATE));\r
1042 if (Private == NULL) {\r
1043 return EFI_OUT_OF_RESOURCES;\r
1044 }\r
1045\r
2b59fcd5 1046 Private->Signature = EMU_SNP_PRIVATE_SIGNATURE;\r
1047 Private->Thunk = This;\r
1048 CopyMem (&Private->EmuSnp, &gEmuSnpProtocol, sizeof (gEmuSnpProtocol));\r
1049 GetInterfaceMacAddr (Private);\r
d18d8a1d 1050\r
2b59fcd5 1051 This->Interface = &Private->EmuSnp;\r
1052 This->Private = Private;\r
1053 return EFI_SUCCESS;\r
1054}\r
1055\r
2b59fcd5 1056EFI_STATUS\r
1057EmuSnpThunkClose (\r
a550d468 1058 IN EMU_IO_THUNK_PROTOCOL *This\r
2b59fcd5 1059 )\r
1060{\r
1061 EMU_SNP_PRIVATE *Private;\r
1062\r
1063 if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) {\r
1064 return EFI_UNSUPPORTED;\r
1065 }\r
d18d8a1d 1066\r
2b59fcd5 1067 Private = This->Private;\r
1068 free (Private);\r
d18d8a1d 1069\r
2b59fcd5 1070 return EFI_SUCCESS;\r
1071}\r
1072\r
a550d468 1073EMU_IO_THUNK_PROTOCOL gSnpThunkIo = {\r
2b59fcd5 1074 &gEmuSnpProtocolGuid,\r
1075 NULL,\r
1076 NULL,\r
1077 0,\r
1078 GasketSnpThunkOpen,\r
1079 GasketSnpThunkClose,\r
1080 NULL\r
1081};\r
1082\r
1083#endif\r