VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/SnpDxe/Snp.c

Last change on this file was 108794, checked in by vboxsync, 5 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette