1. Import SnpNt32Dxe. That is a thunk driver could produce SNP protocol on NT32 platf...
[people/mcb30/edk2.git] / edk2 / Nt32Pkg / SnpNt32Dxe / SnpNt32.c
1 /** @file\r
2 \r
3 Copyright (c) 2006 - 2007, Intel Corporation\r
4 All rights reserved. This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution.  The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8 \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 \r
12 Module Name:\r
13 \r
14   SnpNt32.c\r
15 \r
16 Abstract:\r
17 \r
18 -**/\r
19 \r
20 #include "SnpNt32.h"\r
21 \r
22 EFI_DRIVER_BINDING_PROTOCOL gSnpNt32DriverBinding = {\r
23   SnpNt32DriverBindingSupported,\r
24   SnpNt32DriverBindingStart,\r
25   SnpNt32DriverBindingStop,\r
26   0xa,\r
27   NULL,\r
28   NULL\r
29 };\r
30 \r
31 SNPNT32_GLOBAL_DATA         gSnpNt32GlobalData = {\r
32   SNP_NT32_DRIVER_SIGNATURE,  //  Signature\r
33   {\r
34     NULL,\r
35     NULL\r
36   },                          //  InstanceList\r
37   NULL,                       //  WinNtThunk\r
38   NULL,                       //  NetworkLibraryHandle\r
39   {\r
40     0\r
41   },                          //  NtNetUtilityTable\r
42   {\r
43     0,\r
44     0,\r
45     0\r
46   },                          //  Lock\r
47   //\r
48   //  Private functions\r
49   //\r
50   SnpNt32InitializeGlobalData,            //  InitializeGlobalData\r
51   SnpNt32InitializeInstanceData,          //  InitializeInstanceData\r
52   SnpNt32CloseInstance                    //  CloseInstance\r
53 };\r
54 \r
55 \r
56 /**\r
57   Test to see if this driver supports ControllerHandle.\r
58 \r
59   @param  This                  Protocol instance pointer.\r
60   @param  ControllerHandle      Handle of device to test.\r
61   @param  RemainingDevicePath   Optional parameter use to pick a specific child\r
62                                 device to start.\r
63 \r
64   @retval EFI_SUCCES            This driver supports this device.\r
65   @retval other                 This driver does not support this device.\r
66 \r
67 **/\r
68 EFI_STATUS\r
69 EFIAPI\r
70 SnpNt32DriverBindingSupported (\r
71   IN EFI_DRIVER_BINDING_PROTOCOL  * This,\r
72   IN EFI_HANDLE                   ControllerHandle,\r
73   IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL\r
74   )\r
75 {\r
76 \r
77   SNPNT32_GLOBAL_DATA   *GlobalData;\r
78   NET_LIST_ENTRY        *Entry;\r
79   SNPNT32_INSTANCE_DATA *Instance;\r
80 \r
81   GlobalData = &gSnpNt32GlobalData;\r
82 \r
83   NET_LIST_FOR_EACH (Entry, &GlobalData->InstanceList) {\r
84 \r
85     Instance = NET_LIST_USER_STRUCT_S (Entry, SNPNT32_INSTANCE_DATA, Entry, SNP_NT32_INSTANCE_SIGNATURE);\r
86 \r
87     if (Instance->DeviceHandle == ControllerHandle) {\r
88       return EFI_SUCCESS;\r
89     }\r
90 \r
91   }\r
92 \r
93   return EFI_UNSUPPORTED;\r
94 }\r
95 \r
96 \r
97 /**\r
98   Start this driver on ControllerHandle.\r
99 \r
100   @param  This                  Protocol instance pointer.\r
101   @param  ControllerHandle      Handle of device to bind driver to.\r
102   @param  RemainingDevicePath   Optional parameter use to pick a specific child\r
103                                 device to start.\r
104 \r
105   @retval EFI_SUCCES            This driver is added to ControllerHandle.\r
106 \r
107 **/\r
108 EFI_STATUS\r
109 EFIAPI\r
110 SnpNt32DriverBindingStart (\r
111   IN EFI_DRIVER_BINDING_PROTOCOL  * This,\r
112   IN EFI_HANDLE                   ControllerHandle,\r
113   IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL\r
114   )\r
115 {\r
116   return EFI_SUCCESS;\r
117 }\r
118 \r
119 \r
120 /**\r
121   Stop this driver on ControllerHandle.\r
122 \r
123   @param  This                  Protocol instance pointer.\r
124   @param  ControllerHandle      Handle of device to stop driver on.\r
125   @param  NumberOfChildren      Number of Handles in ChildHandleBuffer. If number\r
126                                 of children is zero stop the entire bus driver.\r
127   @param  ChildHandleBuffer     List of Child Handles to Stop.\r
128 \r
129   @retval EFI_SUCCES            This driver is removed ControllerHandle.\r
130 \r
131 **/\r
132 EFI_STATUS\r
133 EFIAPI\r
134 SnpNt32DriverBindingStop (\r
135   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
136   IN  EFI_HANDLE                   ControllerHandle,\r
137   IN  UINTN                        NumberOfChildren,\r
138   IN  EFI_HANDLE                   *ChildHandleBuffer\r
139   )\r
140 {\r
141 \r
142   return EFI_SUCCESS;\r
143 }\r
144 \r
145 \r
146 /**\r
147   Start the SnpNt32 interface.\r
148 \r
149   @param  This                  Context pointer.\r
150 \r
151   @retval EFI_SUCCESS           The interface is started.\r
152 \r
153 **/\r
154 EFI_STATUS\r
155 SnpNt32Start (\r
156   IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
157   )\r
158 {\r
159   return EFI_SUCCESS;\r
160 }\r
161 \r
162 \r
163 /**\r
164   Stop the SnpNt32 interface.\r
165 \r
166   @param  This                  Context pointer.\r
167 \r
168   @retval EFI_SUCCESS           The interface is stopped.\r
169 \r
170 **/\r
171 EFI_STATUS\r
172 SnpNt32Stop (\r
173   IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
174   )\r
175 {\r
176   return EFI_SUCCESS;\r
177 }\r
178 \r
179 \r
180 /**\r
181   Initialize the SnpNt32 interface.\r
182 \r
183   @param  This                  Context pointer.\r
184   @param  ExtraRxBufferSize     Number of extra receive buffer.\r
185   @param  ExtraTxBufferSize     Number of extra transmit buffer.\r
186 \r
187   @retval EFI_SUCCESS           The interface is initialized.\r
188 \r
189 **/\r
190 EFI_STATUS\r
191 SnpNt32Initialize (\r
192   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
193   IN UINTN                       ExtraRxBufferSize OPTIONAL,\r
194   IN UINTN                       ExtraTxBufferSize OPTIONAL\r
195   )\r
196 {\r
197   return EFI_SUCCESS;\r
198 }\r
199 \r
200 \r
201 /**\r
202   Reset the snpnt32 interface.\r
203 \r
204   @param  This                  Context pointer.\r
205   @param  ExtendedVerification  Not implemented.\r
206 \r
207   @retval EFI_SUCCESS           The interface is reseted.\r
208 \r
209 **/\r
210 EFI_STATUS\r
211 SnpNt32Reset (\r
212   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,\r
213   IN BOOLEAN                      ExtendedVerification\r
214   )\r
215 {\r
216   return EFI_SUCCESS;\r
217 }\r
218 \r
219 \r
220 /**\r
221   Shut down the snpnt32 interface.\r
222 \r
223   @param  This                  Context pointer.\r
224 \r
225   @retval EFI_SUCCESS           The interface is shut down.\r
226 \r
227 **/\r
228 EFI_STATUS\r
229 SnpNt32Shutdown (\r
230   IN EFI_SIMPLE_NETWORK_PROTOCOL *This\r
231   )\r
232 {\r
233   return EFI_SUCCESS;\r
234 }\r
235 \r
236 \r
237 /**\r
238   Change the interface's receive filter setting.\r
239 \r
240   @param  This                  Context pointer.\r
241   @param  EnableBits            The receive filters to enable.\r
242   @param  DisableBits           The receive filters to disable\r
243   @param  ResetMcastFilter      Reset the multicast filters or not.\r
244   @param  McastFilterCount      The count of multicast filter to set.\r
245   @param  McastFilter           Pointer to the arrya of multicast addresses to set.\r
246 \r
247   @retval EFI_SUCCESS           The receive filter is updated.\r
248   @retval EFI_ACCESS_DENIED     The snpnt32 lock is already owned by another\r
249                                 routine.\r
250   @retval EFI_DEVICE_ERROR      Failed to update the receive filter.\r
251 \r
252 **/\r
253 EFI_STATUS\r
254 SnpNt32ReceiveFilters (\r
255   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
256   IN UINT32                      EnableBits,\r
257   IN UINT32                      DisableBits,\r
258   IN BOOLEAN                     ResetMcastFilter,\r
259   IN UINTN                       McastFilterCount OPTIONAL,\r
260   IN EFI_MAC_ADDRESS             *McastFilter OPTIONAL\r
261   )\r
262 {\r
263   SNPNT32_INSTANCE_DATA *Instance;\r
264   SNPNT32_GLOBAL_DATA   *GlobalData;\r
265   INT32                 ReturnValue;\r
266 \r
267   Instance    = SNP_NT32_INSTANCE_DATA_FROM_SNP_THIS (This);\r
268 \r
269   GlobalData  = Instance->GlobalData;\r
270 \r
271   if (EFI_ERROR (NET_TRYLOCK (&GlobalData->Lock))) {\r
272     return EFI_ACCESS_DENIED;\r
273   }\r
274 \r
275   ReturnValue = GlobalData->NtNetUtilityTable.SetReceiveFilter (\r
276                                                 Instance->InterfaceInfo.InterfaceIndex,\r
277                                                 EnableBits,\r
278                                                 McastFilterCount,\r
279                                                 McastFilter\r
280                                                 );\r
281 \r
282   NET_UNLOCK (&GlobalData->Lock);\r
283 \r
284   if (ReturnValue <= 0) {\r
285     return EFI_DEVICE_ERROR;\r
286   }\r
287 \r
288   return EFI_SUCCESS;\r
289 }\r
290 \r
291 \r
292 /**\r
293   Change or reset the mac address of the interface.\r
294 \r
295   @param  This                  Context pointer.\r
296   @param  reset                 Reset the mac address to the original one or not.\r
297   @param  NewMacAddr            Pointer to the new mac address to set.\r
298 \r
299   @retval EFI_UNSUPPORTED       Not supported yet.\r
300 \r
301 **/\r
302 EFI_STATUS\r
303 SnpNt32StationAddress (\r
304   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
305   IN BOOLEAN                     Reset,\r
306   IN EFI_MAC_ADDRESS             *NewMacAddr OPTIONAL\r
307   )\r
308 {\r
309   return EFI_UNSUPPORTED;\r
310 }\r
311 \r
312 \r
313 /**\r
314   Get or reset the statistics data.\r
315 \r
316   @param  This                  Context pointer.\r
317   @param  Reset                 Reset the statistics or not.\r
318   @param  StatisticsSize        The size of the buffer used to receive the\r
319                                 statistics data.\r
320   @param  StatisticsTable       Pointer to the table used to receive the statistics\r
321                                 data.\r
322 \r
323   @retval EFI_UNSUPPORTED       Not supported yet.\r
324 \r
325 **/\r
326 EFI_STATUS\r
327 SnpNt32Statistics (\r
328   IN EFI_SIMPLE_NETWORK_PROTOCOL  * This,\r
329   IN BOOLEAN                      Reset,\r
330   IN OUT UINTN                    *StatisticsSize OPTIONAL,\r
331   IN OUT EFI_NETWORK_STATISTICS   *StatisticsTable OPTIONAL\r
332   )\r
333 {\r
334   return EFI_UNSUPPORTED;\r
335 }\r
336 \r
337 \r
338 /**\r
339   Convert a multicast ip address to the multicast mac address.\r
340 \r
341   @param  This                  Context pointer.\r
342   @param  Ipv6                  The Ip is an Ipv6 address or not.\r
343   @param  Ip                    Pointer to the Ip address to convert.\r
344   @param  Mac                   Pointer to the buffer used to hold the converted\r
345                                 mac address.\r
346 \r
347   @retval EFI_UNSUPPORTED       Not supported yet.\r
348 \r
349 **/\r
350 EFI_STATUS\r
351 SnpNt32McastIptoMac (\r
352   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
353   IN BOOLEAN                     Ipv6,\r
354   IN EFI_IP_ADDRESS              *Ip,\r
355   OUT EFI_MAC_ADDRESS            *Mac\r
356   )\r
357 {\r
358   return EFI_UNSUPPORTED;\r
359 }\r
360 \r
361 \r
362 /**\r
363   Read or write the nv data.\r
364 \r
365   @param  This                  Context pinter.\r
366   @param  ReadOrWrite           Read or write the nv data.\r
367   @param  Offset                The offset to the start of the nv data.\r
368   @param  BufferSize            Size of the buffer.\r
369   @param  Buffer                Pointer to the buffer containing the data to write\r
370                                 or used to receive the data read.\r
371 \r
372   @retval EFI_UNSUPPORTED       Not supported yet.\r
373 \r
374 **/\r
375 EFI_STATUS\r
376 SnpNt32Nvdata (\r
377   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
378   IN BOOLEAN                     ReadOrWrite,\r
379   IN UINTN                       Offset,\r
380   IN UINTN                       BufferSize,\r
381   IN OUT VOID                    *Buffer\r
382   )\r
383 {\r
384   return EFI_UNSUPPORTED;\r
385 }\r
386 \r
387 \r
388 /**\r
389   Get the status information of the interface.\r
390 \r
391   @param  This                  Context pointer.\r
392   @param  InterruptStatus       The storage to hold the interrupt status.\r
393   @param  TxBuffer              Pointer to get the list of pointers of previously\r
394                                 transmitted buffers whose transmission was\r
395                                 completed asynchrnously.\r
396 \r
397   @retval EFI_SUCCESS           The status is got.\r
398 \r
399 **/\r
400 EFI_STATUS\r
401 SnpNt32GetStatus (\r
402   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
403   OUT UINT32                     *InterruptStatus,\r
404   OUT VOID                       **TxBuffer\r
405   )\r
406 {\r
407 \r
408   if (TxBuffer != NULL) {\r
409     *((UINT8 **) TxBuffer) = (UINT8 *) 1;\r
410   }\r
411 \r
412   if (InterruptStatus != NULL) {\r
413     *InterruptStatus = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;\r
414   }\r
415 \r
416   return EFI_SUCCESS;\r
417 }\r
418 \r
419 \r
420 /**\r
421   Transmit a packet.\r
422 \r
423   @param  This                  Context pointer.\r
424   @param  HeaderSize            The media header size contained in the packet\r
425                                 buffer.\r
426   @param  BufferSize            The size of the packet buffer.\r
427   @param  Buffer                Pointer to the buffer containing the packet data.\r
428   @param  SrcAddr               If non null, points to the source address of this\r
429                                 packet.\r
430   @param  DestAddr              If non null, points to the destination address of\r
431                                 this packet.\r
432   @param  Protocol              The protocol type of this packet.\r
433 \r
434   @retval EFI_SUCCESS           The packet is transmitted or put into the transmit\r
435                                 queue.\r
436   @retval other                 Some error occurs.\r
437 \r
438 **/\r
439 EFI_STATUS\r
440 SnpNt32Transmit (\r
441   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
442   IN UINTN                       HeaderSize,\r
443   IN UINTN                       BufferSize,\r
444   IN VOID                        *Buffer,\r
445   IN EFI_MAC_ADDRESS             *SrcAddr OPTIONAL,\r
446   IN EFI_MAC_ADDRESS             *DestAddr OPTIONAL,\r
447   IN UINT16                      *Protocol OPTIONAL\r
448   )\r
449 {\r
450   SNPNT32_INSTANCE_DATA *Instance;\r
451   SNPNT32_GLOBAL_DATA   *GlobalData;\r
452   INT32                 ReturnValue;\r
453 \r
454   Instance    = SNP_NT32_INSTANCE_DATA_FROM_SNP_THIS (This);\r
455 \r
456   GlobalData  = Instance->GlobalData;\r
457 \r
458   if ((HeaderSize != 0) && (SrcAddr == NULL)) {\r
459     SrcAddr = &Instance->Mode.CurrentAddress;\r
460   }\r
461 \r
462   if (EFI_ERROR (NET_TRYLOCK (&GlobalData->Lock))) {\r
463     return EFI_ACCESS_DENIED;\r
464   }\r
465 \r
466   ReturnValue = GlobalData->NtNetUtilityTable.Transmit (\r
467                                                 Instance->InterfaceInfo.InterfaceIndex,\r
468                                                 HeaderSize,\r
469                                                 BufferSize,\r
470                                                 Buffer,\r
471                                                 SrcAddr,\r
472                                                 DestAddr,\r
473                                                 Protocol\r
474                                                 );\r
475 \r
476   NET_UNLOCK (&GlobalData->Lock);\r
477 \r
478   if (ReturnValue < 0) {\r
479     return EFI_DEVICE_ERROR;\r
480   }\r
481 \r
482   return EFI_SUCCESS;\r
483 }\r
484 \r
485 \r
486 /**\r
487   Receive network data.\r
488 \r
489   @param  This                  Context pointer.\r
490   @param  HeaderSize            Optional parameter and is a pointer to the header\r
491                                 portion of the data received.\r
492   @param  BuffSize              Pointer to the length of the Buffer on entry and\r
493                                 contains the length of the received data on return\r
494   @param  Buffer                Pointer to the memory for the received data\r
495   @param  SourceAddr            Optional parameter, is a pointer to contain the\r
496                                 source ethernet address on return\r
497   @param  DestinationAddr       Optional parameter, is a pointer to contain the\r
498                                 destination ethernet address on return.\r
499   @param  Protocol              Optional parameter, is a pointer to contain the\r
500                                 Protocol type from the ethernet header on return.\r
501 \r
502   @retval EFI_SUCCESS           A packet is received and put into the buffer.\r
503   @retval EFI_BUFFER_TOO_SMALL  The provided buffer is too small to receive the\r
504                                 packet.\r
505   @retval EFI_NOT_READY         There is no packet received.\r
506 \r
507 **/\r
508 EFI_STATUS\r
509 SnpNt32Receive (\r
510   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
511   OUT UINTN                      *HeaderSize,\r
512   IN OUT UINTN                   *BuffSize,\r
513   OUT VOID                       *Buffer,\r
514   OUT EFI_MAC_ADDRESS            *SourceAddr,\r
515   OUT EFI_MAC_ADDRESS            *DestinationAddr,\r
516   OUT UINT16                     *Protocol\r
517   )\r
518 {\r
519   SNPNT32_INSTANCE_DATA *Instance;\r
520   SNPNT32_GLOBAL_DATA   *GlobalData;\r
521   INT32                 ReturnValue;\r
522 \r
523   Instance    = SNP_NT32_INSTANCE_DATA_FROM_SNP_THIS (This);\r
524 \r
525   GlobalData  = Instance->GlobalData;\r
526 \r
527   ASSERT (GlobalData->NtNetUtilityTable.Receive != NULL);\r
528 \r
529   if (EFI_ERROR (NET_TRYLOCK (&GlobalData->Lock))) {\r
530     return EFI_ACCESS_DENIED;\r
531   }\r
532 \r
533   ReturnValue = GlobalData->NtNetUtilityTable.Receive (\r
534                                                 Instance->InterfaceInfo.InterfaceIndex,\r
535                                                 BuffSize,\r
536                                                 Buffer\r
537                                                 );\r
538 \r
539   NET_UNLOCK (&GlobalData->Lock);\r
540 \r
541   if (ReturnValue < 0) {\r
542     if (ReturnValue == -100) {\r
543       return EFI_BUFFER_TOO_SMALL;\r
544     }\r
545 \r
546     return EFI_DEVICE_ERROR;\r
547   } else if (ReturnValue == 0) {\r
548     return EFI_NOT_READY;\r
549   }\r
550 \r
551   if (HeaderSize != NULL) {\r
552     *HeaderSize = 14;\r
553   }\r
554 \r
555   if (SourceAddr != NULL) {\r
556     NetZeroMem (SourceAddr, sizeof (EFI_MAC_ADDRESS));\r
557     NetCopyMem (SourceAddr, ((UINT8 *) Buffer) + 6, 6);\r
558   }\r
559 \r
560   if (DestinationAddr != NULL) {\r
561     NetZeroMem (DestinationAddr, sizeof (EFI_MAC_ADDRESS));\r
562     NetCopyMem (DestinationAddr, ((UINT8 *) Buffer), 6);\r
563   }\r
564 \r
565   if (Protocol != NULL) {\r
566     *Protocol = NTOHS (*((UINT16 *) (((UINT8 *) Buffer) + 12)));\r
567   }\r
568 \r
569   return EFI_SUCCESS;\r
570 }\r
571 \r
572 SNPNT32_INSTANCE_DATA gSnpNt32InstanceTemplate = {\r
573   SNP_NT32_INSTANCE_SIGNATURE,            //  Signature\r
574   {\r
575     NULL,\r
576     NULL\r
577   },                                      //  Entry\r
578   NULL,                                   //  GlobalData\r
579   NULL,                                   //  DeviceHandle\r
580   NULL,                                   //  DevicePath\r
581   {                                       //  Snp\r
582     EFI_SIMPLE_NETWORK_PROTOCOL_REVISION, //  Revision\r
583     SnpNt32Start,                         //  Start\r
584     SnpNt32Stop,                          //  Stop\r
585     SnpNt32Initialize,                    //  Initialize\r
586     SnpNt32Reset,                         //  Reset\r
587     SnpNt32Shutdown,                      //  Shutdown\r
588     SnpNt32ReceiveFilters,                //  ReceiveFilters\r
589     SnpNt32StationAddress,                //  StationAddress\r
590     SnpNt32Statistics,                    //  Statistics\r
591     SnpNt32McastIptoMac,                  //  MCastIpToMac\r
592     SnpNt32Nvdata,                        //  NvData\r
593     SnpNt32GetStatus,                     //  GetStatus\r
594     SnpNt32Transmit,                      //  Transmit\r
595     SnpNt32Receive,                       //  Receive\r
596     NULL,                                 //  WaitForPacket\r
597     NULL                                  //  Mode\r
598   },\r
599   {                                       //  Mode\r
600     EfiSimpleNetworkInitialized,          //  State\r
601     NET_ETHER_ADDR_LEN,                   //  HwAddressSize\r
602     NET_ETHER_HEADER_SIZE,                //  MediaHeaderSize\r
603     1500,                                 //  MaxPacketSize\r
604     0,                                    //  NvRamSize\r
605     0,                                    //  NvRamAccessSize\r
606     0,                                    //  ReceiveFilterMask\r
607     0,                                    //  ReceiveFilterSetting\r
608     MAX_MCAST_FILTER_CNT,                 //  MaxMCastFilterCount\r
609     0,                                    //  MCastFilterCount\r
610     {\r
611       0\r
612     },                                    //  MCastFilter\r
613     {\r
614       0\r
615     },                                    //  CurrentAddress\r
616     {\r
617       0\r
618     },                                    //  BroadcastAddress\r
619     {\r
620       0\r
621     },                                    //  PermanentAddress\r
622     NET_IFTYPE_ETHERNET,                  //  IfType\r
623     FALSE,                                //  MacAddressChangeable\r
624     FALSE,                                //  MultipleTxSupported\r
625     FALSE,                                //  MediaPresentSupported\r
626     TRUE                                  //  MediaPresent\r
627   },\r
628   {\r
629     0\r
630   }                                       //  InterfaceInfo\r
631 };\r
632 \r
633 \r
634 /**\r
635   Initialize the driver's global data.\r
636 \r
637   @param  This                  Pointer to the global context data.\r
638 \r
639   @retval EFI_SUCCESS           The global data is initialized.\r
640   @retval EFI_NOT_FOUND         The required DLL is not found.\r
641 \r
642 **/\r
643 EFI_STATUS\r
644 SnpNt32InitializeGlobalData (\r
645   IN SNPNT32_GLOBAL_DATA *This\r
646   )\r
647 {\r
648   EFI_STATUS            Status;\r
649   CHAR16                *DllFileNameU;\r
650   UINT32                Index;\r
651   INT32                 ReturnValue;\r
652   BOOLEAN               NetUtilityLibInitDone;\r
653   NT_NET_INTERFACE_INFO NetInterfaceInfoBuffer[MAX_INTERFACE_INFO_NUMBER];\r
654   SNPNT32_INSTANCE_DATA *Instance;\r
655   NET_LIST_ENTRY        *Entry;\r
656   UINT32                InterfaceCount;\r
657 \r
658   ASSERT (This != NULL);\r
659 \r
660   NetUtilityLibInitDone = FALSE;\r
661   InterfaceCount        = MAX_INTERFACE_INFO_NUMBER;\r
662 \r
663   NetListInit (&This->InstanceList);\r
664   NET_LOCK_INIT (&This->Lock);\r
665 \r
666   //\r
667   //  Get the WinNT thunk\r
668   //\r
669   Status = gBS->LocateProtocol (&gEfiWinNtThunkProtocolGuid, NULL, &This->WinNtThunk);\r
670 \r
671   if (EFI_ERROR (Status)) {\r
672     return Status;\r
673   }\r
674 \r
675   ASSERT (This->WinNtThunk != NULL);\r
676 \r
677   DllFileNameU = NETWORK_LIBRARY_NAME_U;\r
678 \r
679   //\r
680   //  Load network utility library\r
681   //\r
682   This->NetworkLibraryHandle = This->WinNtThunk->LoadLibraryEx (DllFileNameU, NULL, 0);\r
683 \r
684   if (NULL == This->NetworkLibraryHandle) {\r
685     return EFI_NOT_FOUND;\r
686   }\r
687 \r
688   This->NtNetUtilityTable.Initialize = (NT_NET_INITIALIZE) This->WinNtThunk->GetProcAddress (\r
689                                                                               This->NetworkLibraryHandle,\r
690                                                                               NETWORK_LIBRARY_INITIALIZE\r
691                                                                               );\r
692 \r
693   if (NULL == This->NtNetUtilityTable.Initialize) {\r
694     Status = EFI_NOT_FOUND;\r
695     goto ErrorReturn;\r
696   }\r
697 \r
698   This->NtNetUtilityTable.Finalize = (NT_NET_FINALIZE) This->WinNtThunk->GetProcAddress (\r
699                                                                           This->NetworkLibraryHandle,\r
700                                                                           NETWORK_LIBRARY_FINALIZE\r
701                                                                           );\r
702 \r
703   if (NULL == This->NtNetUtilityTable.Finalize) {\r
704     Status = EFI_NOT_FOUND;\r
705     goto ErrorReturn;\r
706   }\r
707 \r
708   This->NtNetUtilityTable.SetReceiveFilter = (NT_NET_SET_RECEIVE_FILTER) This->WinNtThunk->GetProcAddress (\r
709                                                                                             This->NetworkLibraryHandle,\r
710                                                                                             NETWORK_LIBRARY_SET_RCV_FILTER\r
711                                                                                             );\r
712 \r
713   if (NULL == This->NtNetUtilityTable.SetReceiveFilter) {\r
714     Status = EFI_NOT_FOUND;\r
715     goto ErrorReturn;\r
716   }\r
717 \r
718   This->NtNetUtilityTable.Receive = (NT_NET_RECEIVE) This->WinNtThunk->GetProcAddress (\r
719                                                                         This->NetworkLibraryHandle,\r
720                                                                         NETWORK_LIBRARY_RECEIVE\r
721                                                                         );\r
722 \r
723   if (NULL == This->NtNetUtilityTable.Receive) {\r
724     Status = EFI_NOT_FOUND;\r
725     goto ErrorReturn;\r
726   }\r
727 \r
728   This->NtNetUtilityTable.Transmit = (NT_NET_TRANSMIT) This->WinNtThunk->GetProcAddress (\r
729                                                                           This->NetworkLibraryHandle,\r
730                                                                           NETWORK_LIBRARY_TRANSMIT\r
731                                                                           );\r
732 \r
733   if (NULL == This->NtNetUtilityTable.Transmit) {\r
734     Status = EFI_NOT_FOUND;\r
735     goto ErrorReturn;\r
736   }\r
737   //\r
738   //  Initialize the network utility library\r
739   //  And enumerate the interfaces in NT32 host\r
740   //\r
741   ReturnValue = This->NtNetUtilityTable.Initialize (&InterfaceCount, &NetInterfaceInfoBuffer[0]);\r
742   if (ReturnValue <= 0) {\r
743     Status = EFI_DEVICE_ERROR;\r
744     goto ErrorReturn;\r
745   }\r
746 \r
747   NetUtilityLibInitDone = TRUE;\r
748 \r
749   if (InterfaceCount == 0) {\r
750     Status = EFI_NOT_FOUND;\r
751     goto ErrorReturn;\r
752   }\r
753   //\r
754   //  Create fake SNP instances\r
755   //\r
756   for (Index = 0; Index < InterfaceCount; Index++) {\r
757 \r
758     Instance = NetAllocatePool (sizeof (SNPNT32_INSTANCE_DATA));\r
759 \r
760     if (NULL == Instance) {\r
761       Status = EFI_OUT_OF_RESOURCES;\r
762       goto ErrorReturn;\r
763     }\r
764     //\r
765     //  Copy the content from a template\r
766     //\r
767     NetCopyMem (Instance, &gSnpNt32InstanceTemplate, sizeof (SNPNT32_INSTANCE_DATA));\r
768 \r
769     //\r
770     //  Set the interface information.\r
771     //\r
772     Instance->InterfaceInfo = NetInterfaceInfoBuffer[Index];\r
773     //\r
774     //  Initialize this instance\r
775     //\r
776     Status = This->InitializeInstanceData (This, Instance);\r
777     if (EFI_ERROR (Status)) {\r
778 \r
779       NetFreePool (Instance);\r
780       goto ErrorReturn;\r
781     }\r
782     //\r
783     //  Insert this instance into the instance list\r
784     //\r
785     NetListInsertTail (&This->InstanceList, &Instance->Entry);\r
786   }\r
787 \r
788   return EFI_SUCCESS;\r
789 \r
790 ErrorReturn:\r
791 \r
792   while (!NetListIsEmpty (&This->InstanceList)) {\r
793 \r
794     Entry     = This->InstanceList.ForwardLink;\r
795 \r
796     Instance  = NET_LIST_USER_STRUCT_S (Entry, SNPNT32_INSTANCE_DATA, Entry, SNP_NT32_INSTANCE_SIGNATURE);\r
797 \r
798     NetListRemoveEntry (Entry);\r
799 \r
800     This->CloseInstance (This, Instance);\r
801     NetFreePool (Instance);\r
802   }\r
803 \r
804   if (NetUtilityLibInitDone) {\r
805 \r
806     ASSERT (This->WinNtThunk != NULL);\r
807 \r
808     if (This->NtNetUtilityTable.Finalize != NULL) {\r
809       This->NtNetUtilityTable.Finalize ();\r
810       This->NtNetUtilityTable.Finalize = NULL;\r
811     }\r
812   }\r
813 \r
814   return Status;\r
815 }\r
816 \r
817 \r
818 /**\r
819   Initialize the snpnt32 driver instance.\r
820 \r
821   @param  This                  Pointer to the SnpNt32 global data.\r
822   @param  Instance              Pointer to the instance context data.\r
823 \r
824   @retval EFI_SUCCESS           The driver instance is initialized.\r
825 \r
826 **/\r
827 EFI_STATUS\r
828 SnpNt32InitializeInstanceData (\r
829   IN SNPNT32_GLOBAL_DATA    *This,\r
830   IN SNPNT32_INSTANCE_DATA  *Instance\r
831   )\r
832 {\r
833   EFI_STATUS    Status;\r
834   EFI_DEV_PATH  EndNode;\r
835   EFI_DEV_PATH  Node;\r
836 \r
837   Instance->GlobalData  = This;\r
838   Instance->Snp.Mode    = &Instance->Mode;\r
839   //\r
840   //  Set broadcast address\r
841   //\r
842   SetMem (&Instance->Mode.BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);\r
843 \r
844   //\r
845   //  Copy Current/PermanentAddress MAC address\r
846   //\r
847   Instance->Mode.CurrentAddress   = Instance->InterfaceInfo.MacAddr;\r
848   Instance->Mode.PermanentAddress = Instance->InterfaceInfo.MacAddr;\r
849 \r
850   //\r
851   //  Since the fake SNP is based on a real NIC, to avoid conflict with the host\r
852   //  NIC network stack, we use a different MAC address.\r
853   //  So just change the last byte of the MAC address for the real NIC.\r
854   //\r
855   Instance->Mode.CurrentAddress.Addr[NET_ETHER_ADDR_LEN - 1]++;\r
856 \r
857   //\r
858   //  Create a fake device path for the instance\r
859   //\r
860   NetZeroMem (&Node, sizeof (Node));\r
861 \r
862   Node.DevPath.Type     = MESSAGING_DEVICE_PATH;\r
863   Node.DevPath.SubType  = MSG_MAC_ADDR_DP;\r
864   SetDevicePathNodeLength (&Node.DevPath, sizeof (MAC_ADDR_DEVICE_PATH));\r
865 \r
866   NetCopyMem (\r
867     &Node.MacAddr.MacAddress,\r
868     &Instance->Mode.CurrentAddress,\r
869     sizeof (EFI_MAC_ADDRESS)\r
870     );\r
871 \r
872   Node.MacAddr.IfType = Instance->Mode.IfType;\r
873 \r
874   SetDevicePathEndNode (&EndNode.DevPath);\r
875 \r
876   Instance->DevicePath = AppendDevicePathNode (\r
877                           &EndNode.DevPath,\r
878                           &Node.DevPath\r
879                           );\r
880 \r
881   //\r
882   //  Create a fake device handle for the fake SNP\r
883   //\r
884   Status = gBS->InstallMultipleProtocolInterfaces (\r
885                   &Instance->DeviceHandle,\r
886                   &gEfiSimpleNetworkProtocolGuid,\r
887                   &Instance->Snp,\r
888                   &gEfiDevicePathProtocolGuid,\r
889                   Instance->DevicePath,\r
890                   NULL\r
891                   );\r
892   if (EFI_ERROR (Status)) {\r
893     goto ErrorReturn;\r
894   }\r
895 \r
896   return EFI_SUCCESS;\r
897 \r
898 ErrorReturn:\r
899   return Status;\r
900 }\r
901 \r
902 \r
903 /**\r
904   Close the SnpNt32 driver instance.\r
905 \r
906   @param  This                  Pointer to the SnpNt32 global data.\r
907   @param  Instance              Pointer to the instance context data.\r
908 \r
909   @retval EFI_SUCCESS           The instance is closed.\r
910 \r
911 **/\r
912 EFI_STATUS\r
913 SnpNt32CloseInstance (\r
914   IN SNPNT32_GLOBAL_DATA    *This,\r
915   IN SNPNT32_INSTANCE_DATA  *Instance\r
916   )\r
917 {\r
918   ASSERT (This != NULL);\r
919   ASSERT (Instance != NULL);\r
920 \r
921   gBS->UninstallMultipleProtocolInterfaces (\r
922         Instance->DeviceHandle,\r
923         &gEfiSimpleNetworkProtocolGuid,\r
924         &Instance->Snp,\r
925         &gEfiDevicePathProtocolGuid,\r
926         Instance->DevicePath,\r
927         NULL\r
928         );\r
929 \r
930   if (Instance->DevicePath != NULL) {\r
931     gBS->FreePool (Instance->DevicePath);\r
932   }\r
933 \r
934   return EFI_SUCCESS;\r
935 }\r
936 \r
937 \r
938 /**\r
939   Unload the SnpNt32 driver.\r
940 \r
941   @param  ImageHandle           The handle of the driver image.\r
942 \r
943   @retval EFI_SUCCESS           The driver is unloaded.\r
944   @retval other                 Some error occurs.\r
945 \r
946 **/\r
947 EFI_STATUS\r
948 EFIAPI\r
949 SnpNt32Unload (\r
950   IN EFI_HANDLE  ImageHandle\r
951   )\r
952 {\r
953   EFI_STATUS            Status;\r
954   SNPNT32_GLOBAL_DATA   *This;\r
955   NET_LIST_ENTRY        *Entry;\r
956   SNPNT32_INSTANCE_DATA *Instance;\r
957 \r
958   This    = &gSnpNt32GlobalData;\r
959 \r
960   Status  = NetLibDefaultUnload (ImageHandle);\r
961 \r
962   if (EFI_ERROR (Status)) {\r
963     return Status;\r
964   }\r
965 \r
966   while (!NetListIsEmpty (&This->InstanceList)) {\r
967     //\r
968     //  Walkthrough the interfaces and remove all the SNP instance\r
969     //\r
970     Entry     = This->InstanceList.ForwardLink;\r
971 \r
972     Instance  = NET_LIST_USER_STRUCT_S (Entry, SNPNT32_INSTANCE_DATA, Entry, SNP_NT32_INSTANCE_SIGNATURE);\r
973 \r
974     NetListRemoveEntry (Entry);\r
975 \r
976     This->CloseInstance (This, Instance);\r
977     NetFreePool (Instance);\r
978   }\r
979 \r
980   if (This->NtNetUtilityTable.Finalize != NULL) {\r
981     This->NtNetUtilityTable.Finalize ();\r
982   }\r
983 \r
984   This->WinNtThunk->FreeLibrary (This->NetworkLibraryHandle);\r
985 \r
986   return EFI_SUCCESS;\r
987 }\r
988 \r
989 \r
990 EFI_STATUS\r
991 InitializeSnpNt32river (\r
992   IN EFI_HANDLE        ImageHandle,\r
993   IN EFI_SYSTEM_TABLE  *SystemTable\r
994   )\r
995 /*++\r
996 \r
997 Routine Description:\r
998 \r
999   Install DriverBinding Protocol for the Win NT Bus driver on the drivers\r
1000   image handle.\r
1001 \r
1002 Arguments:\r
1003 \r
1004   ImageHandle - The handle of this image.\r
1005   SystemTable - Pointer to the EFI system table.\r
1006 \r
1007 Returns:\r
1008 \r
1009   EFI_SUCEESS -  The protocols are installed and the SnpNt32 is initialized.\r
1010   other       -  Some error occurs.\r
1011 \r
1012 --*/\r
1013 {\r
1014 \r
1015   EFI_STATUS  Status;\r
1016 \r
1017   //\r
1018   // Install the Driver Protocols\r
1019   //\r
1020 \r
1021   Status = NetLibInstallAllDriverProtocolsWithUnload (\r
1022             ImageHandle,\r
1023             SystemTable,\r
1024             &gSnpNt32DriverBinding,\r
1025             ImageHandle,\r
1026             &gSnpNt32DriverComponentName,\r
1027             NULL,\r
1028             NULL,\r
1029             SnpNt32Unload\r
1030             );\r
1031   if (EFI_ERROR (Status)) {\r
1032     return Status;\r
1033   }\r
1034 \r
1035   //\r
1036   //  Initialize the global data\r
1037   //\r
1038   Status = SnpNt32InitializeGlobalData (&gSnpNt32GlobalData);\r
1039   if (EFI_ERROR (Status)) {\r
1040     SnpNt32Unload (ImageHandle);\r
1041   }\r
1042 \r
1043   return Status;\r
1044 }\r