]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Network/SnpDxe/Snp.c
SecurityPkg : Tpm2DeviceLibDTpm : Rename TisTpmCommand to avoid name collision
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Snp.c
... / ...
CommitLineData
1/** @file\r
2 Implementation of driver entry point and driver binding protocol.\r
3\r
4Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials are licensed\r
6and made available under the terms and conditions of the BSD License which\r
7accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Snp.h"\r
16\r
17/**\r
18 One notified function to stop UNDI device when gBS->ExitBootServices() called.\r
19\r
20 @param Event Pointer to this event\r
21 @param Context Event handler private data\r
22\r
23**/\r
24VOID\r
25EFIAPI\r
26SnpNotifyExitBootServices (\r
27 EFI_EVENT Event,\r
28 VOID *Context\r
29 )\r
30{\r
31 SNP_DRIVER *Snp;\r
32\r
33 Snp = (SNP_DRIVER *)Context;\r
34\r
35 //\r
36 // Shutdown and stop UNDI driver\r
37 //\r
38 PxeShutdown (Snp);\r
39 PxeStop (Snp);\r
40}\r
41\r
42/**\r
43 Send command to UNDI. It does nothing currently.\r
44\r
45 @param Cdb command to be sent to UNDI.\r
46\r
47 @retval EFI_INVALID_PARAMETER The command is 0.\r
48 @retval EFI_UNSUPPORTED Default return status because it's not\r
49 supported currently.\r
50\r
51**/\r
52EFI_STATUS\r
53EFIAPI\r
54IssueHwUndiCommand (\r
55 UINT64 Cdb\r
56 )\r
57{\r
58 DEBUG ((EFI_D_ERROR, "\nIssueHwUndiCommand() - This should not be called!"));\r
59\r
60 if (Cdb == 0) {\r
61 return EFI_INVALID_PARAMETER;\r
62\r
63 }\r
64 //\r
65 // %%TBD - For now, nothing is done.\r
66 //\r
67 return EFI_UNSUPPORTED;\r
68}\r
69\r
70\r
71/**\r
72 Compute 8-bit checksum of a buffer.\r
73\r
74 @param Buffer Pointer to buffer.\r
75 @param Length Length of buffer in bytes.\r
76\r
77 @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len\r
78 is zero.\r
79\r
80**/\r
81UINT8\r
82Calc8BitCksum (\r
83 VOID *Buffer,\r
84 UINTN Length\r
85 )\r
86{\r
87 UINT8 *Ptr;\r
88 UINT8 Cksum;\r
89\r
90 Ptr = Buffer;\r
91 Cksum = 0;\r
92\r
93 if (Ptr == NULL || Length == 0) {\r
94 return 0;\r
95 }\r
96\r
97 while (Length-- != 0) {\r
98 Cksum = (UINT8) (Cksum + *Ptr++);\r
99 }\r
100\r
101 return Cksum;\r
102}\r
103\r
104/**\r
105 Test to see if this driver supports ControllerHandle. This service\r
106 is called by the EFI boot service ConnectController(). In\r
107 order to make drivers as small as possible, there are a few calling\r
108 restrictions for this service. ConnectController() must\r
109 follow these calling restrictions. If any other agent wishes to call\r
110 Supported() it must also follow these calling restrictions.\r
111\r
112 @param This Protocol instance pointer.\r
113 @param ControllerHandle Handle of device to test.\r
114 @param RemainingDevicePath Optional parameter use to pick a specific child\r
115 device to start.\r
116\r
117 @retval EFI_SUCCESS This driver supports this device.\r
118 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
119 @retval other This driver does not support this device.\r
120\r
121**/\r
122EFI_STATUS\r
123EFIAPI\r
124SimpleNetworkDriverSupported (\r
125 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
126 IN EFI_HANDLE Controller,\r
127 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
128 )\r
129{\r
130 EFI_STATUS Status;\r
131 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol;\r
132 PXE_UNDI *Pxe;\r
133\r
134 Status = gBS->OpenProtocol (\r
135 Controller,\r
136 &gEfiDevicePathProtocolGuid,\r
137 NULL,\r
138 This->DriverBindingHandle,\r
139 Controller,\r
140 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
141 );\r
142 if (EFI_ERROR (Status)) {\r
143 return Status;\r
144 }\r
145\r
146 Status = gBS->OpenProtocol (\r
147 Controller,\r
148 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
149 (VOID **) &NiiProtocol,\r
150 This->DriverBindingHandle,\r
151 Controller,\r
152 EFI_OPEN_PROTOCOL_BY_DRIVER\r
153 );\r
154\r
155 if (EFI_ERROR (Status)) {\r
156 if (Status == EFI_ALREADY_STARTED) {\r
157 DEBUG ((EFI_D_INFO, "Support(): Already Started. on handle %p\n", Controller));\r
158 }\r
159 return Status;\r
160 }\r
161\r
162 DEBUG ((EFI_D_INFO, "Support(): UNDI3.1 found on handle %p\n", Controller));\r
163\r
164 //\r
165 // check the version, we don't want to connect to the undi16\r
166 //\r
167 if (NiiProtocol->Type != EfiNetworkInterfaceUndi) {\r
168 Status = EFI_UNSUPPORTED;\r
169 goto Done;\r
170 }\r
171 //\r
172 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.\r
173 //\r
174 if ((NiiProtocol->Id & 0x0F) != 0) {\r
175 DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n"));\r
176 Status = EFI_UNSUPPORTED;\r
177 goto Done;\r
178 }\r
179\r
180 Pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->Id);\r
181\r
182 //\r
183 // Verify !PXE revisions.\r
184 //\r
185 if (Pxe->hw.Signature != PXE_ROMID_SIGNATURE) {\r
186 DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n"));\r
187 Status = EFI_UNSUPPORTED;\r
188 goto Done;\r
189 }\r
190\r
191 if (Pxe->hw.Rev < PXE_ROMID_REV) {\r
192 DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n"));\r
193 Status = EFI_UNSUPPORTED;\r
194 goto Done;\r
195 }\r
196\r
197 if (Pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {\r
198\r
199 DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n"));\r
200 Status = EFI_UNSUPPORTED;\r
201 goto Done;\r
202\r
203 } else if (Pxe->hw.MajorVer == PXE_ROMID_MAJORVER && Pxe->hw.MinorVer < PXE_ROMID_MINORVER) {\r
204 DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported."));\r
205 Status = EFI_UNSUPPORTED;\r
206 goto Done;\r
207 }\r
208 //\r
209 // Do S/W UNDI specific checks.\r
210 //\r
211 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {\r
212 if (Pxe->sw.EntryPoint < Pxe->sw.Len) {\r
213 DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid."));\r
214 Status = EFI_UNSUPPORTED;\r
215 goto Done;\r
216 }\r
217\r
218 if (Pxe->sw.BusCnt == 0) {\r
219 DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero."));\r
220 Status = EFI_UNSUPPORTED;\r
221 goto Done;\r
222 }\r
223 }\r
224\r
225 Status = EFI_SUCCESS;\r
226 DEBUG ((EFI_D_INFO, "Support(): supported on %p\n", Controller));\r
227\r
228Done:\r
229 gBS->CloseProtocol (\r
230 Controller,\r
231 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
232 This->DriverBindingHandle,\r
233 Controller\r
234 );\r
235\r
236 return Status;\r
237}\r
238\r
239/**\r
240 Start this driver on ControllerHandle. This service is called by the\r
241 EFI boot service ConnectController(). In order to make\r
242 drivers as small as possible, there are a few calling restrictions for\r
243 this service. ConnectController() must follow these\r
244 calling restrictions. If any other agent wishes to call Start() it\r
245 must also follow these calling restrictions.\r
246\r
247 @param This Protocol instance pointer.\r
248 @param ControllerHandle Handle of device to bind driver to.\r
249 @param RemainingDevicePath Optional parameter use to pick a specific child\r
250 device to start.\r
251\r
252 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
253 @retval EFI_DEVICE_ERROR This driver could not be started due to a device error\r
254 @retval other This driver does not support this device\r
255\r
256**/\r
257EFI_STATUS\r
258EFIAPI\r
259SimpleNetworkDriverStart (\r
260 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
261 IN EFI_HANDLE Controller,\r
262 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
263 )\r
264{\r
265 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;\r
266 EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath;\r
267 EFI_STATUS Status;\r
268 PXE_UNDI *Pxe;\r
269 SNP_DRIVER *Snp;\r
270 VOID *Address;\r
271 EFI_HANDLE Handle;\r
272 UINT8 BarIndex;\r
273 PXE_STATFLAGS InitStatFlags;\r
274 EFI_PCI_IO_PROTOCOL *PciIo;\r
275 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;\r
276 BOOLEAN FoundIoBar;\r
277 BOOLEAN FoundMemoryBar;\r
278 \r
279 DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));\r
280\r
281 Status = gBS->OpenProtocol (\r
282 Controller,\r
283 &gEfiDevicePathProtocolGuid,\r
284 (VOID **) &NiiDevicePath,\r
285 This->DriverBindingHandle,\r
286 Controller,\r
287 EFI_OPEN_PROTOCOL_BY_DRIVER\r
288 );\r
289\r
290 if (EFI_ERROR (Status)) {\r
291 return Status;\r
292 }\r
293\r
294 Status = gBS->LocateDevicePath (\r
295 &gEfiPciIoProtocolGuid,\r
296 &NiiDevicePath,\r
297 &Handle\r
298 );\r
299\r
300 if (EFI_ERROR (Status)) {\r
301 return Status;\r
302 }\r
303\r
304 Status = gBS->OpenProtocol (\r
305 Handle,\r
306 &gEfiPciIoProtocolGuid,\r
307 (VOID **) &PciIo,\r
308 This->DriverBindingHandle,\r
309 Controller,\r
310 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
311 );\r
312 if (EFI_ERROR (Status)) {\r
313 return Status;\r
314 }\r
315 //\r
316 // Get the NII interface.\r
317 //\r
318 Status = gBS->OpenProtocol (\r
319 Controller,\r
320 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
321 (VOID **) &Nii,\r
322 This->DriverBindingHandle,\r
323 Controller,\r
324 EFI_OPEN_PROTOCOL_BY_DRIVER\r
325 );\r
326 if (EFI_ERROR (Status)) {\r
327 gBS->CloseProtocol (\r
328 Controller,\r
329 &gEfiDevicePathProtocolGuid,\r
330 This->DriverBindingHandle,\r
331 Controller\r
332 );\r
333 return Status;\r
334 }\r
335\r
336 DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n"));\r
337\r
338 Pxe = (PXE_UNDI *) (UINTN) (Nii->Id);\r
339\r
340 if (Calc8BitCksum (Pxe, Pxe->hw.Len) != 0) {\r
341 DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n"));\r
342 goto NiiError;\r
343 }\r
344\r
345 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
346 //\r
347 // We can get any packets.\r
348 //\r
349 } else if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
350 //\r
351 // We need to be able to get broadcast packets for DHCP.\r
352 // If we do not have promiscuous support, we must at least have\r
353 // broadcast support or we cannot do DHCP!\r
354 //\r
355 } else {\r
356 DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support."));\r
357 goto NiiError;\r
358 }\r
359 //\r
360 // OK, we like this UNDI, and we know snp is not already there on this handle\r
361 // Allocate and initialize a new simple network protocol structure.\r
362 //\r
363 Status = PciIo->AllocateBuffer (\r
364 PciIo,\r
365 AllocateAnyPages,\r
366 EfiBootServicesData,\r
367 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
368 &Address,\r
369 0\r
370 );\r
371\r
372 if (Status != EFI_SUCCESS) {\r
373 DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));\r
374 goto NiiError;\r
375 }\r
376\r
377 Snp = (SNP_DRIVER *) (UINTN) Address;\r
378\r
379 ZeroMem (Snp, sizeof (SNP_DRIVER));\r
380\r
381 Snp->PciIo = PciIo;\r
382 Snp->Signature = SNP_DRIVER_SIGNATURE;\r
383\r
384 EfiInitializeLock (&Snp->Lock, TPL_NOTIFY);\r
385\r
386 Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;\r
387 Snp->Snp.Start = SnpUndi32Start;\r
388 Snp->Snp.Stop = SnpUndi32Stop;\r
389 Snp->Snp.Initialize = SnpUndi32Initialize;\r
390 Snp->Snp.Reset = SnpUndi32Reset;\r
391 Snp->Snp.Shutdown = SnpUndi32Shutdown;\r
392 Snp->Snp.ReceiveFilters = SnpUndi32ReceiveFilters;\r
393 Snp->Snp.StationAddress = SnpUndi32StationAddress;\r
394 Snp->Snp.Statistics = SnpUndi32Statistics;\r
395 Snp->Snp.MCastIpToMac = SnpUndi32McastIpToMac;\r
396 Snp->Snp.NvData = SnpUndi32NvData;\r
397 Snp->Snp.GetStatus = SnpUndi32GetStatus;\r
398 Snp->Snp.Transmit = SnpUndi32Transmit;\r
399 Snp->Snp.Receive = SnpUndi32Receive;\r
400 Snp->Snp.WaitForPacket = NULL;\r
401\r
402 Snp->Snp.Mode = &Snp->Mode;\r
403\r
404 Snp->TxRxBufferSize = 0;\r
405 Snp->TxRxBuffer = NULL;\r
406 \r
407 if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) {\r
408 Snp->IfNum = Nii->IfNum;\r
409\r
410 } else {\r
411 Snp->IfNum = (UINT8) (Nii->IfNum & 0xFF);\r
412 }\r
413\r
414 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {\r
415 Snp->IsSwUndi = FALSE;\r
416 Snp->IssueUndi32Command = &IssueHwUndiCommand;\r
417 } else {\r
418 Snp->IsSwUndi = TRUE;\r
419\r
420 if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {\r
421 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) Pxe->sw.EntryPoint;\r
422 } else {\r
423 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) ((UINT8) (UINTN) Pxe + Pxe->sw.EntryPoint);\r
424 }\r
425 }\r
426 //\r
427 // Allocate a global CPB and DB buffer for this UNDI interface.\r
428 // we do this because:\r
429 //\r
430 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be\r
431 // within 2GB limit, create them here and map them so that when undi calls\r
432 // v2p callback to check if the physical address is < 2gb, we will pass.\r
433 //\r
434 // -This is not a requirement for 3.1 or later UNDIs but the code looks\r
435 // simpler if we use the same cpb, db variables for both old and new undi\r
436 // interfaces from all the SNP interface calls (we don't map the buffers\r
437 // for the newer undi interfaces though)\r
438 // .\r
439 // -it is OK to allocate one global set of CPB, DB pair for each UNDI\r
440 // interface as EFI does not multi-task and so SNP will not be re-entered!\r
441 //\r
442 Status = PciIo->AllocateBuffer (\r
443 PciIo,\r
444 AllocateAnyPages,\r
445 EfiBootServicesData,\r
446 SNP_MEM_PAGES (4096),\r
447 &Address,\r
448 0\r
449 );\r
450\r
451 if (Status != EFI_SUCCESS) {\r
452 DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));\r
453 goto Error_DeleteSNP;\r
454 }\r
455\r
456 Snp->Cpb = (VOID *) (UINTN) Address;\r
457 Snp->Db = (VOID *) ((UINTN) Address + 2048);\r
458\r
459 //\r
460 // Find the correct BAR to do IO.\r
461 //\r
462 // Enumerate through the PCI BARs for the device to determine which one is\r
463 // the IO BAR. Save the index of the BAR into the adapter info structure.\r
464 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped\r
465 //\r
466 Snp->MemoryBarIndex = 0;\r
467 Snp->IoBarIndex = 1;\r
468 FoundMemoryBar = FALSE;\r
469 FoundIoBar = FALSE;\r
470 for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {\r
471 Status = PciIo->GetBarAttributes (\r
472 PciIo,\r
473 BarIndex,\r
474 NULL,\r
475 (VOID**) &BarDesc\r
476 );\r
477 if (Status == EFI_UNSUPPORTED) {\r
478 continue;\r
479 } else if (EFI_ERROR (Status)) {\r
480 goto Error_DeleteSNP;\r
481 }\r
482\r
483 if ((!FoundMemoryBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) {\r
484 Snp->MemoryBarIndex = BarIndex;\r
485 FoundMemoryBar = TRUE;\r
486 } else if ((!FoundIoBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) {\r
487 Snp->IoBarIndex = BarIndex;\r
488 FoundIoBar = TRUE;\r
489 }\r
490\r
491 FreePool (BarDesc);\r
492\r
493 if (FoundMemoryBar && FoundIoBar) {\r
494 break;\r
495 }\r
496 }\r
497\r
498 Status = PxeStart (Snp);\r
499\r
500 if (Status != EFI_SUCCESS) {\r
501 goto Error_DeleteSNP;\r
502 }\r
503\r
504 Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;\r
505 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
506\r
507 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
508 Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
509\r
510 Snp->Cdb.DBsize = (UINT16) sizeof (Snp->InitInfo);\r
511 Snp->Cdb.DBaddr = (UINT64)(UINTN) (&Snp->InitInfo);\r
512\r
513 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
514 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
515\r
516 Snp->Cdb.IFnum = Snp->IfNum;\r
517 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
518\r
519 DEBUG ((EFI_D_NET, "\nSnp->undi.get_init_info() "));\r
520\r
521 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
522\r
523 //\r
524 // Save the INIT Stat Code...\r
525 //\r
526 InitStatFlags = Snp->Cdb.StatFlags;\r
527\r
528 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
529 DEBUG ((EFI_D_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));\r
530 PxeStop (Snp);\r
531 goto Error_DeleteSNP;\r
532 }\r
533\r
534 //\r
535 // Initialize simple network protocol mode structure\r
536 //\r
537 Snp->Mode.State = EfiSimpleNetworkStopped;\r
538 Snp->Mode.HwAddressSize = Snp->InitInfo.HWaddrLen;\r
539 Snp->Mode.MediaHeaderSize = Snp->InitInfo.MediaHeaderLen;\r
540 Snp->Mode.MaxPacketSize = Snp->InitInfo.FrameDataLen;\r
541 Snp->Mode.NvRamAccessSize = Snp->InitInfo.NvWidth;\r
542 Snp->Mode.NvRamSize = Snp->InitInfo.NvCount * Snp->Mode.NvRamAccessSize;\r
543 Snp->Mode.IfType = Snp->InitInfo.IFtype;\r
544 Snp->Mode.MaxMCastFilterCount = Snp->InitInfo.MCastFilterCnt;\r
545 Snp->Mode.MCastFilterCount = 0;\r
546\r
547 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {\r
548 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:\r
549 Snp->Mode.MediaPresentSupported = TRUE;\r
550 break;\r
551\r
552 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:\r
553 default:\r
554 Snp->Mode.MediaPresentSupported = FALSE;\r
555 }\r
556\r
557 switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) {\r
558 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED:\r
559 Snp->MediaStatusSupported = TRUE;\r
560 break;\r
561\r
562 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED:\r
563 default:\r
564 Snp->MediaStatusSupported = FALSE;\r
565 }\r
566\r
567 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {\r
568 Snp->Mode.MacAddressChangeable = TRUE;\r
569 } else {\r
570 Snp->Mode.MacAddressChangeable = FALSE;\r
571 }\r
572\r
573 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {\r
574 Snp->Mode.MultipleTxSupported = TRUE;\r
575 } else {\r
576 Snp->Mode.MultipleTxSupported = FALSE;\r
577 }\r
578\r
579 Snp->Mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
580\r
581 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {\r
582 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
583\r
584 }\r
585\r
586 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
587 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
588\r
589 }\r
590\r
591 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
592 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
593\r
594 }\r
595\r
596 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {\r
597 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
598\r
599 }\r
600\r
601 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {\r
602 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
603\r
604 }\r
605\r
606 Snp->Mode.ReceiveFilterSetting = 0;\r
607\r
608 //\r
609 // need to get the station address to save in the mode structure. we need to\r
610 // initialize the UNDI first for this.\r
611 //\r
612 Snp->TxRxBufferSize = Snp->InitInfo.MemoryRequired;\r
613 Status = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);\r
614\r
615 if (EFI_ERROR (Status)) {\r
616 PxeStop (Snp);\r
617 goto Error_DeleteSNP;\r
618 }\r
619\r
620 Status = PxeGetStnAddr (Snp);\r
621\r
622 if (Status != EFI_SUCCESS) {\r
623 DEBUG ((EFI_D_ERROR, "\nSnp->undi.get_station_addr() failed.\n"));\r
624 PxeShutdown (Snp);\r
625 PxeStop (Snp);\r
626 goto Error_DeleteSNP;\r
627 }\r
628\r
629 Snp->Mode.MediaPresent = FALSE;\r
630\r
631 //\r
632 // We should not leave UNDI started and initialized here. this DriverStart()\r
633 // routine must only find and attach the SNP interface to UNDI layer that it\r
634 // finds on the given handle!\r
635 // The UNDI layer will be started when upper layers call Snp->start.\r
636 // How ever, this DriverStart() must fill up the snp mode structure which\r
637 // contains the MAC address of the NIC. For this reason we started and\r
638 // initialized UNDI here, now we are done, do a shutdown and stop of the\r
639 // UNDI interface!\r
640 //\r
641 PxeShutdown (Snp);\r
642 PxeStop (Snp);\r
643\r
644 //\r
645 // Create EXIT_BOOT_SERIVES Event\r
646 //\r
647 Status = gBS->CreateEventEx (\r
648 EVT_NOTIFY_SIGNAL,\r
649 TPL_NOTIFY,\r
650 SnpNotifyExitBootServices,\r
651 Snp,\r
652 &gEfiEventExitBootServicesGuid,\r
653 &Snp->ExitBootServicesEvent\r
654 );\r
655 if (EFI_ERROR (Status)) {\r
656 goto Error_DeleteSNP;\r
657 }\r
658\r
659 //\r
660 // add SNP to the undi handle\r
661 //\r
662 Status = gBS->InstallProtocolInterface (\r
663 &Controller,\r
664 &gEfiSimpleNetworkProtocolGuid,\r
665 EFI_NATIVE_INTERFACE,\r
666 &(Snp->Snp)\r
667 );\r
668\r
669 if (!EFI_ERROR (Status)) {\r
670 return Status;\r
671 }\r
672\r
673 PciIo->FreeBuffer (\r
674 PciIo,\r
675 SNP_MEM_PAGES (4096),\r
676 Snp->Cpb\r
677 );\r
678\r
679Error_DeleteSNP:\r
680\r
681 PciIo->FreeBuffer (\r
682 PciIo,\r
683 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
684 Snp\r
685 );\r
686NiiError:\r
687 gBS->CloseProtocol (\r
688 Controller,\r
689 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
690 This->DriverBindingHandle,\r
691 Controller\r
692 );\r
693\r
694 gBS->CloseProtocol (\r
695 Controller,\r
696 &gEfiDevicePathProtocolGuid,\r
697 This->DriverBindingHandle,\r
698 Controller\r
699 );\r
700\r
701 //\r
702 // If we got here that means we are in error state.\r
703 //\r
704 if (!EFI_ERROR (Status)) {\r
705 Status = EFI_DEVICE_ERROR;\r
706 }\r
707\r
708 return Status;\r
709}\r
710\r
711/**\r
712 Stop this driver on ControllerHandle. This service is called by the\r
713 EFI boot service DisconnectController(). In order to\r
714 make drivers as small as possible, there are a few calling\r
715 restrictions for this service. DisconnectController()\r
716 must follow these calling restrictions. If any other agent wishes\r
717 to call Stop() it must also follow these calling restrictions.\r
718\r
719 @param This Protocol instance pointer.\r
720 @param ControllerHandle Handle of device to stop driver on\r
721 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
722 children is zero stop the entire bus driver.\r
723 @param ChildHandleBuffer List of Child Handles to Stop.\r
724\r
725 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
726 @retval other This driver was not removed from this device\r
727\r
728**/\r
729EFI_STATUS\r
730EFIAPI\r
731SimpleNetworkDriverStop (\r
732 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
733 IN EFI_HANDLE Controller,\r
734 IN UINTN NumberOfChildren,\r
735 IN EFI_HANDLE *ChildHandleBuffer\r
736 )\r
737{\r
738 EFI_STATUS Status;\r
739 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;\r
740 SNP_DRIVER *Snp;\r
741 EFI_PCI_IO_PROTOCOL *PciIo;\r
742\r
743 //\r
744 // Get our context back.\r
745 //\r
746 Status = gBS->OpenProtocol (\r
747 Controller,\r
748 &gEfiSimpleNetworkProtocolGuid,\r
749 (VOID **) &SnpProtocol,\r
750 This->DriverBindingHandle,\r
751 Controller,\r
752 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
753 );\r
754\r
755 if (EFI_ERROR (Status)) {\r
756 return EFI_UNSUPPORTED;\r
757 }\r
758\r
759 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);\r
760\r
761 Status = gBS->UninstallProtocolInterface (\r
762 Controller,\r
763 &gEfiSimpleNetworkProtocolGuid,\r
764 &Snp->Snp\r
765 );\r
766\r
767 if (EFI_ERROR (Status)) {\r
768 return Status;\r
769 }\r
770\r
771 //\r
772 // Close EXIT_BOOT_SERIVES Event\r
773 //\r
774 gBS->CloseEvent (Snp->ExitBootServicesEvent);\r
775\r
776 Status = gBS->CloseProtocol (\r
777 Controller,\r
778 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
779 This->DriverBindingHandle,\r
780 Controller\r
781 );\r
782\r
783 Status = gBS->CloseProtocol (\r
784 Controller,\r
785 &gEfiDevicePathProtocolGuid,\r
786 This->DriverBindingHandle,\r
787 Controller\r
788 );\r
789\r
790 PxeShutdown (Snp);\r
791 PxeStop (Snp);\r
792\r
793 PciIo = Snp->PciIo;\r
794 PciIo->FreeBuffer (\r
795 PciIo,\r
796 SNP_MEM_PAGES (4096),\r
797 Snp->Cpb\r
798 );\r
799\r
800 PciIo->FreeBuffer (\r
801 PciIo,\r
802 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
803 Snp\r
804 );\r
805\r
806 return Status;\r
807}\r
808\r
809//\r
810// Simple Network Protocol Driver Global Variables\r
811//\r
812EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = {\r
813 SimpleNetworkDriverSupported,\r
814 SimpleNetworkDriverStart,\r
815 SimpleNetworkDriverStop,\r
816 0xa,\r
817 NULL,\r
818 NULL\r
819};\r
820\r
821/**\r
822 The SNP driver entry point.\r
823\r
824 @param ImageHandle The driver image handle.\r
825 @param SystemTable The system table.\r
826\r
827 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,\r
828 loaded it's ROM, and installed a notify event for\r
829 the Network Indentifier Interface Protocol\r
830 successfully.\r
831 @retval Other Return value from HandleProtocol for\r
832 DeviceIoProtocol or LoadedImageProtocol\r
833\r
834**/\r
835EFI_STATUS\r
836EFIAPI\r
837InitializeSnpNiiDriver (\r
838 IN EFI_HANDLE ImageHandle,\r
839 IN EFI_SYSTEM_TABLE *SystemTable\r
840 )\r
841{\r
842 return EfiLibInstallDriverBindingComponentName2 (\r
843 ImageHandle,\r
844 SystemTable,\r
845 &gSimpleNetworkDriverBinding,\r
846 ImageHandle,\r
847 &gSimpleNetworkComponentName,\r
848 &gSimpleNetworkComponentName2\r
849 );\r
850}\r