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