]> git.proxmox.com Git - mirror_edk2.git/blame - OptionRomPkg/UndiRuntimeDxe/Init.c
EmulatorPkg: Remove framework pkgs dependency from EmulatorPkg
[mirror_edk2.git] / OptionRomPkg / UndiRuntimeDxe / Init.c
CommitLineData
51ebae6b 1/** @file\r
2 Initialization functions for EFI UNDI32 driver.\r
3\r
7db61f68 4Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
96ae5934 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
51ebae6b 6\r
7**/\r
8\r
9#include "Undi32.h"\r
10//\r
11// Global Variables\r
12//\r
13\r
14PXE_SW_UNDI *pxe_31 = NULL; // 3.1 entry\r
15UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES];\r
c1ff10ec 16UNDI_CONFIG_TABLE *UndiDataPointer = NULL;\r
51ebae6b 17\r
18//\r
19// UNDI Class Driver Global Variables\r
20//\r
21EFI_DRIVER_BINDING_PROTOCOL gUndiDriverBinding = {\r
22 UndiDriverSupported,\r
23 UndiDriverStart,\r
24 UndiDriverStop,\r
25 0xa,\r
26 NULL,\r
27 NULL\r
28};\r
29\r
30\r
31/**\r
32 When address mapping changes to virtual this should make the appropriate\r
33 address conversions.\r
34\r
35 (Standard Event handler)\r
36\r
37 @return None\r
38\r
39**/\r
40VOID\r
41EFIAPI\r
42UndiNotifyVirtual (\r
43 EFI_EVENT Event,\r
44 VOID *Context\r
45 )\r
46{\r
47 UINT16 Index;\r
48 VOID *Pxe31Pointer;\r
49\r
50 if (pxe_31 != NULL) {\r
51 Pxe31Pointer = (VOID *) pxe_31;\r
52\r
53 EfiConvertPointer (\r
54 EFI_OPTIONAL_PTR,\r
55 (VOID **) &Pxe31Pointer\r
56 );\r
57\r
58 //\r
59 // UNDI32DeviceList is an array of pointers\r
60 //\r
61f2ab90 61 for (Index = 0; Index < (pxe_31->IFcnt | pxe_31->IFcntExt << 8); Index++) {\r
51ebae6b 62 UNDI32DeviceList[Index]->NIIProtocol_31.Id = (UINT64) (UINTN) Pxe31Pointer;\r
63 EfiConvertPointer (\r
64 EFI_OPTIONAL_PTR,\r
65 (VOID **) &(UNDI32DeviceList[Index])\r
66 );\r
67 }\r
68\r
69 EfiConvertPointer (\r
70 EFI_OPTIONAL_PTR,\r
71 (VOID **) &(pxe_31->EntryPoint)\r
72 );\r
73 pxe_31 = Pxe31Pointer;\r
74 }\r
75\r
76 for (Index = 0; Index <= PXE_OPCODE_LAST_VALID; Index++) {\r
77 EfiConvertPointer (\r
78 EFI_OPTIONAL_PTR,\r
79 (VOID **) &api_table[Index].api_ptr\r
80 );\r
81 }\r
82}\r
83\r
84\r
85/**\r
86 When EFI is shuting down the boot services, we need to install a\r
87 configuration table for UNDI to work at runtime!\r
88\r
89 (Standard Event handler)\r
90\r
91 @return None\r
92\r
93**/\r
94VOID\r
95EFIAPI\r
7db61f68 96UndiNotifyReadyToBoot (\r
51ebae6b 97 EFI_EVENT Event,\r
98 VOID *Context\r
99 )\r
100{\r
101 InstallConfigTable ();\r
102}\r
103\r
104\r
105/**\r
106 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
107 than contains a DevicePath, PciIo protocol, Class code of 2, Vendor ID of 0x8086,\r
108 and DeviceId of (D100_DEVICE_ID || D102_DEVICE_ID || ICH3_DEVICE_ID_1 ||\r
109 ICH3_DEVICE_ID_2 || ICH3_DEVICE_ID_3 || ICH3_DEVICE_ID_4 || ICH3_DEVICE_ID_5 ||\r
110 ICH3_DEVICE_ID_6 || ICH3_DEVICE_ID_7 || ICH3_DEVICE_ID_8) can be supported.\r
111\r
112 @param This Protocol instance pointer.\r
113 @param Controller Handle of device to test.\r
114 @param RemainingDevicePath Not used.\r
115\r
116 @retval EFI_SUCCESS This driver supports this device.\r
117 @retval other This driver does not support this device.\r
118\r
119**/\r
120EFI_STATUS\r
121EFIAPI\r
122UndiDriverSupported (\r
123 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
124 IN EFI_HANDLE Controller,\r
125 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
126 )\r
127{\r
128 EFI_STATUS Status;\r
129 EFI_PCI_IO_PROTOCOL *PciIo;\r
130 PCI_TYPE00 Pci;\r
131\r
132 Status = gBS->OpenProtocol (\r
133 Controller,\r
134 &gEfiDevicePathProtocolGuid,\r
135 NULL,\r
136 This->DriverBindingHandle,\r
137 Controller,\r
138 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
139 );\r
140 if (EFI_ERROR (Status)) {\r
141 return Status;\r
142 }\r
143\r
144 Status = gBS->OpenProtocol (\r
145 Controller,\r
146 &gEfiPciIoProtocolGuid,\r
147 (VOID **) &PciIo,\r
148 This->DriverBindingHandle,\r
149 Controller,\r
150 EFI_OPEN_PROTOCOL_BY_DRIVER\r
151 );\r
152 if (EFI_ERROR (Status)) {\r
153 return Status;\r
154 }\r
155\r
156 Status = PciIo->Pci.Read (\r
157 PciIo,\r
158 EfiPciIoWidthUint8,\r
159 0,\r
160 sizeof (PCI_CONFIG_HEADER),\r
161 &Pci\r
162 );\r
163\r
164 if (!EFI_ERROR (Status)) {\r
165 Status = EFI_UNSUPPORTED;\r
166\r
167 if (Pci.Hdr.ClassCode[2] == 0x02 && Pci.Hdr.VendorId == PCI_VENDOR_ID_INTEL) {\r
168 switch (Pci.Hdr.DeviceId) {\r
169 case D100_DEVICE_ID:\r
170 case D102_DEVICE_ID:\r
171 case ICH3_DEVICE_ID_1:\r
172 case ICH3_DEVICE_ID_2:\r
173 case ICH3_DEVICE_ID_3:\r
174 case ICH3_DEVICE_ID_4:\r
175 case ICH3_DEVICE_ID_5:\r
176 case ICH3_DEVICE_ID_6:\r
177 case ICH3_DEVICE_ID_7:\r
178 case ICH3_DEVICE_ID_8:\r
179 case 0x1039:\r
180 case 0x103A:\r
181 case 0x103B:\r
182 case 0x103C:\r
183 case 0x103D:\r
184 case 0x103E:\r
185 case 0x1050:\r
186 case 0x1051:\r
187 case 0x1052:\r
188 case 0x1053:\r
189 case 0x1054:\r
190 case 0x1055:\r
191 case 0x1056:\r
192 case 0x1057:\r
193 case 0x1059:\r
194 case 0x1064:\r
195 Status = EFI_SUCCESS;\r
196 }\r
197 }\r
198 }\r
199\r
200 gBS->CloseProtocol (\r
201 Controller,\r
202 &gEfiPciIoProtocolGuid,\r
203 This->DriverBindingHandle,\r
204 Controller\r
205 );\r
206\r
207 return Status;\r
208}\r
209\r
210\r
211/**\r
212 Start this driver on Controller by opening PciIo and DevicePath protocol.\r
213 Initialize PXE structures, create a copy of the Controller Device Path with the\r
214 NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol\r
215 on the newly created Device Path.\r
216\r
217 @param This Protocol instance pointer.\r
218 @param Controller Handle of device to work with.\r
219 @param RemainingDevicePath Not used, always produce all possible children.\r
220\r
221 @retval EFI_SUCCESS This driver is added to Controller.\r
222 @retval other This driver does not support this device.\r
223\r
224**/\r
225EFI_STATUS\r
226EFIAPI\r
227UndiDriverStart (\r
228 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
229 IN EFI_HANDLE Controller,\r
230 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
231 )\r
232{\r
233 EFI_STATUS Status;\r
234 EFI_DEVICE_PATH_PROTOCOL *UndiDevicePath;\r
235 PCI_CONFIG_HEADER *CfgHdr;\r
236 UNDI32_DEV *UNDI32Device;\r
237 UINT16 NewCommand;\r
238 UINT8 *TmpPxePointer;\r
239 EFI_PCI_IO_PROTOCOL *PciIoFncs;\r
240 UINTN Len;\r
241 UINT64 Supports;\r
242 BOOLEAN PciAttributesSaved;\r
243\r
244 Status = gBS->OpenProtocol (\r
245 Controller,\r
246 &gEfiPciIoProtocolGuid,\r
247 (VOID **) &PciIoFncs,\r
248 This->DriverBindingHandle,\r
249 Controller,\r
250 EFI_OPEN_PROTOCOL_BY_DRIVER\r
251 );\r
252\r
253 if (EFI_ERROR (Status)) {\r
254 return Status;\r
255 }\r
256\r
257 Status = gBS->OpenProtocol (\r
258 Controller,\r
259 &gEfiDevicePathProtocolGuid,\r
260 (VOID **) &UndiDevicePath,\r
261 This->DriverBindingHandle,\r
262 Controller,\r
263 EFI_OPEN_PROTOCOL_BY_DRIVER\r
264 );\r
265\r
266 if (EFI_ERROR (Status)) {\r
267 gBS->CloseProtocol (\r
268 Controller,\r
269 &gEfiPciIoProtocolGuid,\r
270 This->DriverBindingHandle,\r
271 Controller\r
272 );\r
273\r
274 return Status;\r
275 }\r
276\r
277 PciAttributesSaved = FALSE;\r
278\r
279 Status = gBS->AllocatePool (\r
280 EfiRuntimeServicesData,\r
281 sizeof (UNDI32_DEV),\r
282 (VOID **) &UNDI32Device\r
283 );\r
284\r
285 if (EFI_ERROR (Status)) {\r
286 goto UndiError;\r
287 }\r
288\r
289 ZeroMem ((CHAR8 *) UNDI32Device, sizeof (UNDI32_DEV));\r
290\r
291 //\r
292 // Get original PCI attributes\r
293 //\r
294 Status = PciIoFncs->Attributes (\r
295 PciIoFncs,\r
296 EfiPciIoAttributeOperationGet,\r
297 0,\r
298 &UNDI32Device->NicInfo.OriginalPciAttributes\r
299 );\r
300\r
301 if (EFI_ERROR (Status)) {\r
302 goto UndiErrorDeleteDevice;\r
303 }\r
304 PciAttributesSaved = TRUE;\r
305\r
306 //\r
307 // allocate and initialize both (old and new) the !pxe structures here,\r
308 // there should only be one copy of each of these structure for any number\r
309 // of NICs this undi supports. Also, these structures need to be on a\r
310 // paragraph boundary as per the spec. so, while allocating space for these,\r
311 // make sure that there is space for 2 !pxe structures (old and new) and a\r
312 // 32 bytes padding for alignment adjustment (in case)\r
313 //\r
314 TmpPxePointer = NULL;\r
315 if (pxe_31 == NULL) {\r
316 Status = gBS->AllocatePool (\r
317 EfiRuntimeServicesData,\r
318 (sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32),\r
319 (VOID **) &TmpPxePointer\r
320 );\r
321\r
322 if (EFI_ERROR (Status)) {\r
323 goto UndiErrorDeleteDevice;\r
324 }\r
325\r
326 ZeroMem (\r
327 TmpPxePointer,\r
328 sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32\r
329 );\r
330 //\r
331 // check for paragraph alignment here, assuming that the pointer is\r
332 // already 8 byte aligned.\r
333 //\r
334 if (((UINTN) TmpPxePointer & 0x0F) != 0) {\r
335 pxe_31 = (PXE_SW_UNDI *) ((UINTN) (TmpPxePointer + 8));\r
336 } else {\r
337 pxe_31 = (PXE_SW_UNDI *) TmpPxePointer;\r
338 }\r
339\r
340 PxeStructInit (pxe_31);\r
341 }\r
342\r
343 UNDI32Device->NIIProtocol_31.Id = (UINT64) (UINTN) (pxe_31);\r
344\r
345 Status = PciIoFncs->Attributes (\r
346 PciIoFncs,\r
347 EfiPciIoAttributeOperationSupported,\r
348 0,\r
349 &Supports\r
350 );\r
351 if (!EFI_ERROR (Status)) {\r
352 Supports &= EFI_PCI_DEVICE_ENABLE;\r
353 Status = PciIoFncs->Attributes (\r
354 PciIoFncs,\r
355 EfiPciIoAttributeOperationEnable,\r
356 Supports,\r
357 NULL\r
358 );\r
359 }\r
360 //\r
361 // Read all the registers from device's PCI Configuration space\r
362 //\r
363 Status = PciIoFncs->Pci.Read (\r
364 PciIoFncs,\r
365 EfiPciIoWidthUint32,\r
366 0,\r
367 MAX_PCI_CONFIG_LEN,\r
368 &UNDI32Device->NicInfo.Config\r
369 );\r
370\r
371 CfgHdr = (PCI_CONFIG_HEADER *) &(UNDI32Device->NicInfo.Config[0]);\r
372\r
373 //\r
374 // make sure that this device is a PCI bus master\r
375 //\r
376\r
377 NewCommand = (UINT16) (CfgHdr->Command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);\r
378 if (CfgHdr->Command != NewCommand) {\r
379 PciIoFncs->Pci.Write (\r
380 PciIoFncs,\r
381 EfiPciIoWidthUint16,\r
382 PCI_COMMAND,\r
383 1,\r
384 &NewCommand\r
385 );\r
386 CfgHdr->Command = NewCommand;\r
387 }\r
388\r
389 //\r
390 // make sure that the latency timer is at least 32\r
391 //\r
392 if (CfgHdr->LatencyTimer < 32) {\r
393 CfgHdr->LatencyTimer = 32;\r
394 PciIoFncs->Pci.Write (\r
395 PciIoFncs,\r
396 EfiPciIoWidthUint8,\r
397 PCI_LATENCY_TIMER,\r
398 1,\r
399 &CfgHdr->LatencyTimer\r
400 );\r
401 }\r
402 //\r
403 // the IfNum index for the current interface will be the total number\r
404 // of interfaces initialized so far\r
405 //\r
61f2ab90 406 UNDI32Device->NIIProtocol_31.IfNum = pxe_31->IFcnt | pxe_31->IFcntExt << 8;\r
51ebae6b 407\r
408 PxeUpdate (&UNDI32Device->NicInfo, pxe_31);\r
409\r
410 UNDI32Device->NicInfo.Io_Function = PciIoFncs;\r
411 UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = UNDI32Device;\r
412 UNDI32Device->Undi32BaseDevPath = UndiDevicePath;\r
413\r
414 Status = AppendMac2DevPath (\r
415 &UNDI32Device->Undi32DevPath,\r
416 UNDI32Device->Undi32BaseDevPath,\r
417 &UNDI32Device->NicInfo\r
418 );\r
419\r
420 if (Status != 0) {\r
421 goto UndiErrorDeletePxe;\r
422 }\r
423\r
424 UNDI32Device->Signature = UNDI_DEV_SIGNATURE;\r
425\r
426 UNDI32Device->NIIProtocol_31.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31;\r
427 UNDI32Device->NIIProtocol_31.Type = EfiNetworkInterfaceUndi;\r
428 UNDI32Device->NIIProtocol_31.MajorVer = PXE_ROMID_MAJORVER;\r
429 UNDI32Device->NIIProtocol_31.MinorVer = PXE_ROMID_MINORVER_31;\r
430 UNDI32Device->NIIProtocol_31.ImageSize = 0;\r
431 UNDI32Device->NIIProtocol_31.ImageAddr = 0;\r
2bbe9553 432 UNDI32Device->NIIProtocol_31.Ipv6Supported = TRUE;\r
51ebae6b 433\r
434 UNDI32Device->NIIProtocol_31.StringId[0] = 'U';\r
435 UNDI32Device->NIIProtocol_31.StringId[1] = 'N';\r
436 UNDI32Device->NIIProtocol_31.StringId[2] = 'D';\r
437 UNDI32Device->NIIProtocol_31.StringId[3] = 'I';\r
438\r
439 UNDI32Device->DeviceHandle = NULL;\r
440\r
2bbe9553
YT
441 UNDI32Device->Aip.GetInformation = UndiAipGetInfo;\r
442 UNDI32Device->Aip.SetInformation = UndiAipSetInfo;\r
443 UNDI32Device->Aip.GetSupportedTypes = UndiAipGetSupportedTypes;\r
444\r
51ebae6b 445 //\r
446 // install both the 3.0 and 3.1 NII protocols.\r
447 //\r
448 Status = gBS->InstallMultipleProtocolInterfaces (\r
449 &UNDI32Device->DeviceHandle,\r
450 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
451 &UNDI32Device->NIIProtocol_31,\r
452 &gEfiDevicePathProtocolGuid,\r
453 UNDI32Device->Undi32DevPath,\r
2bbe9553
YT
454 &gEfiAdapterInformationProtocolGuid,\r
455 &UNDI32Device->Aip,\r
51ebae6b 456 NULL\r
457 );\r
458\r
459 if (EFI_ERROR (Status)) {\r
460 goto UndiErrorDeleteDevicePath;\r
461 }\r
462\r
463 //\r
464 // if the table exists, free it and alloc again, or alloc it directly\r
465 //\r
466 if (UndiDataPointer != NULL) {\r
467 Status = gBS->FreePool(UndiDataPointer);\r
468 }\r
469 if (EFI_ERROR (Status)) {\r
470 goto UndiErrorDeleteDevicePath;\r
471 }\r
472\r
61f2ab90 473 Len = ((pxe_31->IFcnt|pxe_31->IFcntExt << 8)* sizeof (UndiDataPointer->NII_entry)) + sizeof (UndiDataPointer);\r
51ebae6b 474 Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UndiDataPointer);\r
475\r
476 if (EFI_ERROR (Status)) {\r
477 goto UndiErrorAllocDataPointer;\r
478 }\r
479\r
480 //\r
481 // Open For Child Device\r
482 //\r
483 Status = gBS->OpenProtocol (\r
484 Controller,\r
485 &gEfiPciIoProtocolGuid,\r
486 (VOID **) &PciIoFncs,\r
487 This->DriverBindingHandle,\r
488 UNDI32Device->DeviceHandle,\r
489 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
490 );\r
491\r
492 return EFI_SUCCESS;\r
493UndiErrorAllocDataPointer:\r
494 gBS->UninstallMultipleProtocolInterfaces (\r
495 &UNDI32Device->DeviceHandle,\r
496 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
497 &UNDI32Device->NIIProtocol_31,\r
498 &gEfiDevicePathProtocolGuid,\r
499 UNDI32Device->Undi32DevPath,\r
2bbe9553
YT
500 &gEfiAdapterInformationProtocolGuid,\r
501 &UNDI32Device->Aip,\r
51ebae6b 502 NULL\r
503 );\r
504\r
505UndiErrorDeleteDevicePath:\r
506 UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = NULL;\r
507 gBS->FreePool (UNDI32Device->Undi32DevPath);\r
508\r
509UndiErrorDeletePxe:\r
510 PxeUpdate (NULL, pxe_31);\r
511 if (TmpPxePointer != NULL) {\r
512 gBS->FreePool (TmpPxePointer);\r
513\r
514 }\r
515\r
516UndiErrorDeleteDevice:\r
517 if (PciAttributesSaved) {\r
518 //\r
519 // Restore original PCI attributes\r
520 //\r
521 PciIoFncs->Attributes (\r
522 PciIoFncs,\r
523 EfiPciIoAttributeOperationSet,\r
524 UNDI32Device->NicInfo.OriginalPciAttributes,\r
525 NULL\r
526 );\r
527 }\r
528\r
529 gBS->FreePool (UNDI32Device);\r
530\r
531UndiError:\r
532 gBS->CloseProtocol (\r
533 Controller,\r
534 &gEfiDevicePathProtocolGuid,\r
535 This->DriverBindingHandle,\r
536 Controller\r
537 );\r
538\r
539 gBS->CloseProtocol (\r
540 Controller,\r
541 &gEfiPciIoProtocolGuid,\r
542 This->DriverBindingHandle,\r
543 Controller\r
544 );\r
545\r
546 return Status;\r
547}\r
548\r
549\r
550/**\r
551 Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and\r
552 closing the DevicePath and PciIo protocols on Controller.\r
553\r
554 @param This Protocol instance pointer.\r
555 @param Controller Handle of device to stop driver on.\r
556 @param NumberOfChildren How many children need to be stopped.\r
557 @param ChildHandleBuffer Not used.\r
558\r
559 @retval EFI_SUCCESS This driver is removed Controller.\r
560 @retval other This driver was not removed from this device.\r
561\r
562**/\r
563// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
564EFI_STATUS\r
565EFIAPI\r
566UndiDriverStop (\r
567 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
568 IN EFI_HANDLE Controller,\r
569 IN UINTN NumberOfChildren,\r
570 IN EFI_HANDLE *ChildHandleBuffer\r
571 )\r
572{\r
573 EFI_STATUS Status;\r
574 BOOLEAN AllChildrenStopped;\r
575 UINTN Index;\r
576 UNDI32_DEV *UNDI32Device;\r
577 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NIIProtocol;\r
51ebae6b 578\r
579 //\r
580 // Complete all outstanding transactions to Controller.\r
581 // Don't allow any new transaction to Controller to be started.\r
582 //\r
583 if (NumberOfChildren == 0) {\r
584\r
585 //\r
586 // Close the bus driver\r
587 //\r
588 Status = gBS->CloseProtocol (\r
589 Controller,\r
590 &gEfiDevicePathProtocolGuid,\r
591 This->DriverBindingHandle,\r
592 Controller\r
593 );\r
594\r
595 Status = gBS->CloseProtocol (\r
596 Controller,\r
597 &gEfiPciIoProtocolGuid,\r
598 This->DriverBindingHandle,\r
599 Controller\r
600 );\r
601\r
602 return Status;\r
603 }\r
604\r
605 AllChildrenStopped = TRUE;\r
606\r
607 for (Index = 0; Index < NumberOfChildren; Index++) {\r
608\r
609 Status = gBS->OpenProtocol (\r
610 ChildHandleBuffer[Index],\r
611 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
612 (VOID **) &NIIProtocol,\r
613 This->DriverBindingHandle,\r
614 Controller,\r
615 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
616 );\r
617 if (!EFI_ERROR (Status)) {\r
618\r
619 UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol);\r
620\r
4a823e23 621 Status = gBS->CloseProtocol (\r
622 Controller,\r
623 &gEfiPciIoProtocolGuid,\r
624 This->DriverBindingHandle,\r
625 ChildHandleBuffer[Index]\r
51ebae6b 626 );\r
f415234b 627 if (!EFI_ERROR (Status)) {\r
4a823e23 628 Status = gBS->UninstallMultipleProtocolInterfaces (\r
629 ChildHandleBuffer[Index],\r
630 &gEfiDevicePathProtocolGuid,\r
631 UNDI32Device->Undi32DevPath,\r
632 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
633 &UNDI32Device->NIIProtocol_31,\r
634 NULL\r
f415234b 635 );\r
4a823e23 636 if (!EFI_ERROR (Status)) {\r
637 //\r
638 // Restore original PCI attributes\r
639 //\r
640 Status = UNDI32Device->NicInfo.Io_Function->Attributes (\r
641 UNDI32Device->NicInfo.Io_Function,\r
642 EfiPciIoAttributeOperationSet,\r
643 UNDI32Device->NicInfo.OriginalPciAttributes,\r
644 NULL\r
645 );\r
646\r
647 ASSERT_EFI_ERROR (Status);\r
648\r
649 gBS->FreePool (UNDI32Device->Undi32DevPath);\r
650 gBS->FreePool (UNDI32Device);\r
651\r
652 }\r
51ebae6b 653 }\r
654 }\r
655\r
656 if (EFI_ERROR (Status)) {\r
657 AllChildrenStopped = FALSE;\r
658 }\r
659 }\r
660\r
661 if (!AllChildrenStopped) {\r
662 return EFI_DEVICE_ERROR;\r
663 }\r
664\r
665 return EFI_SUCCESS;\r
666\r
667}\r
668\r
669\r
670/**\r
671 Use the EFI boot services to produce a pause. This is also the routine which\r
672 gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can\r
673 do it's own pause.\r
674\r
675 @param UnqId Runtime O/S routine might use this, this temp\r
676 routine does not use it\r
677 @param MicroSeconds Determines the length of pause.\r
678\r
679 @return none\r
680\r
681**/\r
682VOID\r
683TmpDelay (\r
684 IN UINT64 UnqId,\r
685 IN UINTN MicroSeconds\r
686 )\r
687{\r
688 gBS->Stall ((UINT32) MicroSeconds);\r
689}\r
690\r
691\r
692/**\r
693 Use the PCI IO abstraction to issue memory or I/O reads and writes. This is also the routine which\r
694 gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can do it's own I/O abstractions.\r
695\r
696 @param UnqId Runtime O/S routine may use this field, this temp\r
697 routine does not.\r
698 @param ReadWrite Determine if it is an I/O or Memory Read/Write\r
699 Operation.\r
700 @param Len Determines the width of the data operation.\r
701 @param Port What port to Read/Write from.\r
702 @param BuffAddr Address to read to or write from.\r
703\r
704 @return none\r
705\r
706**/\r
707VOID\r
708TmpMemIo (\r
709 IN UINT64 UnqId,\r
710 IN UINT8 ReadWrite,\r
711 IN UINT8 Len,\r
712 IN UINT64 Port,\r
713 IN UINT64 BuffAddr\r
714 )\r
715{\r
716 EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
717 NIC_DATA_INSTANCE *AdapterInfo;\r
718\r
719 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;\r
720 AdapterInfo = (NIC_DATA_INSTANCE *) (UINTN) UnqId;\r
721 switch (Len) {\r
722 case 2:\r
723 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;\r
724 break;\r
725\r
726 case 4:\r
727 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;\r
728 break;\r
729\r
730 case 8:\r
731 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;\r
732 break;\r
733 }\r
734\r
735 switch (ReadWrite) {\r
736 case PXE_IO_READ:\r
737 AdapterInfo->Io_Function->Io.Read (\r
738 AdapterInfo->Io_Function,\r
739 Width,\r
740 1,\r
741 Port,\r
742 1,\r
743 (VOID *) (UINTN) (BuffAddr)\r
744 );\r
745 break;\r
746\r
747 case PXE_IO_WRITE:\r
748 AdapterInfo->Io_Function->Io.Write (\r
749 AdapterInfo->Io_Function,\r
750 Width,\r
751 1,\r
752 Port,\r
753 1,\r
754 (VOID *) (UINTN) (BuffAddr)\r
755 );\r
756 break;\r
757\r
758 case PXE_MEM_READ:\r
759 AdapterInfo->Io_Function->Mem.Read (\r
760 AdapterInfo->Io_Function,\r
761 Width,\r
762 0,\r
763 Port,\r
764 1,\r
765 (VOID *) (UINTN) (BuffAddr)\r
766 );\r
767 break;\r
768\r
769 case PXE_MEM_WRITE:\r
770 AdapterInfo->Io_Function->Mem.Write (\r
771 AdapterInfo->Io_Function,\r
772 Width,\r
773 0,\r
774 Port,\r
775 1,\r
776 (VOID *) (UINTN) (BuffAddr)\r
777 );\r
778 break;\r
779 }\r
780\r
781 return ;\r
782}\r
783\r
784\r
785/**\r
786 Using the NIC data structure information, read the EEPROM to get the MAC address and then allocate space\r
787 for a new devicepath (**DevPtr) which will contain the original device path the NIC was found on (*BaseDevPtr)\r
788 and an added MAC node.\r
789\r
790 @param DevPtr Pointer which will point to the newly created device\r
791 path with the MAC node attached.\r
792 @param BaseDevPtr Pointer to the device path which the UNDI device\r
793 driver is latching on to.\r
794 @param AdapterInfo Pointer to the NIC data structure information which\r
795 the UNDI driver is layering on..\r
796\r
797 @retval EFI_SUCCESS A MAC address was successfully appended to the Base\r
798 Device Path.\r
799 @retval other Not enough resources available to create new Device\r
800 Path node.\r
801\r
802**/\r
803EFI_STATUS\r
804AppendMac2DevPath (\r
805 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPtr,\r
806 IN EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr,\r
807 IN NIC_DATA_INSTANCE *AdapterInfo\r
808 )\r
809{\r
810 EFI_MAC_ADDRESS MACAddress;\r
811 PCI_CONFIG_HEADER *CfgHdr;\r
812 INT32 Val;\r
813 INT32 Index;\r
814 INT32 Index2;\r
815 UINT8 AddrLen;\r
816 MAC_ADDR_DEVICE_PATH MacAddrNode;\r
817 EFI_DEVICE_PATH_PROTOCOL *EndNode;\r
818 UINT8 *DevicePtr;\r
819 UINT16 TotalPathLen;\r
820 UINT16 BasePathLen;\r
821 EFI_STATUS Status;\r
822\r
823 //\r
824 // set the environment ready (similar to UNDI_Start call) so that we can\r
825 // execute the other UNDI_ calls to get the mac address\r
826 // we are using undi 3.1 style\r
827 //\r
828 AdapterInfo->Delay = TmpDelay;\r
829 AdapterInfo->Virt2Phys = (VOID *) 0;\r
830 AdapterInfo->Block = (VOID *) 0;\r
831 AdapterInfo->Map_Mem = (VOID *) 0;\r
832 AdapterInfo->UnMap_Mem = (VOID *) 0;\r
833 AdapterInfo->Sync_Mem = (VOID *) 0;\r
834 AdapterInfo->Mem_Io = TmpMemIo;\r
835 //\r
836 // these tmp call-backs follow 3.1 undi style\r
837 // i.e. they have the unique_id parameter.\r
838 //\r
839 AdapterInfo->VersionFlag = 0x31;\r
840 AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo;\r
841\r
842 //\r
843 // undi init portion\r
844 //\r
845 CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]);\r
846 AdapterInfo->ioaddr = 0;\r
847 AdapterInfo->RevID = CfgHdr->RevID;\r
848\r
849 AddrLen = E100bGetEepromAddrLen (AdapterInfo);\r
850\r
851 for (Index = 0, Index2 = 0; Index < 3; Index++) {\r
852 Val = E100bReadEeprom (AdapterInfo, Index, AddrLen);\r
853 MACAddress.Addr[Index2++] = (UINT8) Val;\r
854 MACAddress.Addr[Index2++] = (UINT8) (Val >> 8);\r
855 }\r
856\r
857 SetMem (MACAddress.Addr + Index2, sizeof (EFI_MAC_ADDRESS) - Index2, 0);\r
858 //for (; Index2 < sizeof (EFI_MAC_ADDRESS); Index2++) {\r
859 // MACAddress.Addr[Index2] = 0;\r
860 //}\r
861 //\r
862 // stop undi\r
863 //\r
864 AdapterInfo->Delay = (VOID *) 0;\r
865 AdapterInfo->Mem_Io = (VOID *) 0;\r
866\r
867 //\r
868 // fill the mac address node first\r
869 //\r
870 ZeroMem ((CHAR8 *) &MacAddrNode, sizeof MacAddrNode);\r
871 CopyMem (\r
872 (CHAR8 *) &MacAddrNode.MacAddress,\r
873 (CHAR8 *) &MACAddress,\r
874 sizeof (EFI_MAC_ADDRESS)\r
875 );\r
876\r
877 MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH;\r
878 MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP;\r
80448f6c 879 MacAddrNode.Header.Length[0] = (UINT8) sizeof (MacAddrNode);\r
51ebae6b 880 MacAddrNode.Header.Length[1] = 0;\r
881\r
882 //\r
883 // find the size of the base dev path.\r
884 //\r
885 EndNode = BaseDevPtr;\r
886\r
887 while (!IsDevicePathEnd (EndNode)) {\r
888 EndNode = NextDevicePathNode (EndNode);\r
889 }\r
890\r
891 BasePathLen = (UINT16) ((UINTN) (EndNode) - (UINTN) (BaseDevPtr));\r
892\r
893 //\r
894 // create space for full dev path\r
895 //\r
896 TotalPathLen = (UINT16) (BasePathLen + sizeof (MacAddrNode) + sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
897\r
898 Status = gBS->AllocatePool (\r
899 EfiRuntimeServicesData,\r
900 TotalPathLen,\r
901 (VOID **) &DevicePtr\r
902 );\r
903\r
904 if (Status != EFI_SUCCESS) {\r
905 return Status;\r
906 }\r
907 //\r
908 // copy the base path, mac addr and end_dev_path nodes\r
909 //\r
910 *DevPtr = (EFI_DEVICE_PATH_PROTOCOL *) DevicePtr;\r
911 CopyMem (DevicePtr, (CHAR8 *) BaseDevPtr, BasePathLen);\r
912 DevicePtr += BasePathLen;\r
913 CopyMem (DevicePtr, (CHAR8 *) &MacAddrNode, sizeof (MacAddrNode));\r
914 DevicePtr += sizeof (MacAddrNode);\r
915 CopyMem (DevicePtr, (CHAR8 *) EndNode, sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
916\r
917 return EFI_SUCCESS;\r
918}\r
919\r
920\r
921/**\r
922 Install a GUID/Pointer pair into the system's configuration table.\r
923\r
924 none\r
925\r
926 @retval EFI_SUCCESS Install a GUID/Pointer pair into the system's\r
927 configuration table.\r
928 @retval other Did not successfully install the GUID/Pointer pair\r
929 into the configuration table.\r
930\r
931**/\r
932// TODO: VOID - add argument and description to function comment\r
933EFI_STATUS\r
934InstallConfigTable (\r
935 IN VOID\r
936 )\r
937{\r
938 EFI_STATUS Status;\r
939 EFI_CONFIGURATION_TABLE *CfgPtr;\r
c1ff10ec 940 UNDI_CONFIG_TABLE *TmpData;\r
51ebae6b 941 UINT16 Index;\r
c1ff10ec 942 UNDI_CONFIG_TABLE *UndiData;\r
51ebae6b 943\r
944 if (pxe_31 == NULL) {\r
945 return EFI_SUCCESS;\r
946 }\r
947\r
948 if(UndiDataPointer == NULL) {\r
949 return EFI_SUCCESS;\r
950 }\r
951\r
c1ff10ec 952 UndiData = (UNDI_CONFIG_TABLE *)UndiDataPointer;\r
51ebae6b 953\r
61f2ab90 954 UndiData->NumberOfInterfaces = (pxe_31->IFcnt | pxe_31->IFcntExt << 8);\r
c1ff10ec 955 UndiData->nextlink = NULL;\r
51ebae6b 956\r
61f2ab90 957 for (Index = 0; Index < (pxe_31->IFcnt | pxe_31->IFcntExt << 8); Index++) {\r
c1ff10ec 958 UndiData->NII_entry[Index].NII_InterfacePointer = &UNDI32DeviceList[Index]->NIIProtocol_31;\r
959 UndiData->NII_entry[Index].DevicePathPointer = UNDI32DeviceList[Index]->Undi32DevPath;\r
51ebae6b 960 }\r
961\r
962 //\r
963 // see if there is an entry in the config table already\r
964 //\r
965 CfgPtr = gST->ConfigurationTable;\r
966\r
967 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {\r
968 Status = CompareGuid (\r
969 &CfgPtr->VendorGuid,\r
970 &gEfiNetworkInterfaceIdentifierProtocolGuid_31\r
971 );\r
972 if (Status != EFI_SUCCESS) {\r
973 break;\r
974 }\r
975\r
976 CfgPtr++;\r
977 }\r
978\r
979 if (Index < gST->NumberOfTableEntries) {\r
c1ff10ec 980 TmpData = (UNDI_CONFIG_TABLE *) CfgPtr->VendorTable;\r
51ebae6b 981\r
982 //\r
983 // go to the last link\r
984 //\r
c1ff10ec 985 while (TmpData->nextlink != NULL) {\r
986 TmpData = TmpData->nextlink;\r
51ebae6b 987 }\r
988\r
c1ff10ec 989 TmpData->nextlink = UndiData;\r
51ebae6b 990\r
991 //\r
992 // 1st one in chain\r
993 //\r
c1ff10ec 994 UndiData = (UNDI_CONFIG_TABLE *) CfgPtr->VendorTable;\r
51ebae6b 995 }\r
996\r
997 //\r
998 // create an entry in the configuration table for our GUID\r
999 //\r
1000 Status = gBS->InstallConfigurationTable (\r
1001 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
1002 UndiData\r
1003 );\r
1004 return Status;\r
1005}\r
1006\r
1007/**\r
1008\r
1009**/\r
1010EFI_STATUS\r
1011EFIAPI\r
1012InitializeUndi(\r
1013 IN EFI_HANDLE ImageHandle,\r
1014 IN EFI_SYSTEM_TABLE *SystemTable\r
1015 )\r
1016{\r
1017 EFI_EVENT Event;\r
1018 EFI_STATUS Status;\r
1019\r
906e1cb7 1020 Status = EfiLibInstallDriverBindingComponentName2 (\r
51ebae6b 1021 ImageHandle,\r
1022 SystemTable,\r
1023 &gUndiDriverBinding,\r
906e1cb7 1024 ImageHandle,\r
1025 &gUndiComponentName,\r
1026 &gUndiComponentName2\r
51ebae6b 1027 );\r
1028 ASSERT_EFI_ERROR (Status);\r
1029\r
1030 Status = gBS->CreateEventEx (\r
1031 EVT_NOTIFY_SIGNAL,\r
1032 TPL_NOTIFY,\r
7db61f68 1033 UndiNotifyReadyToBoot,\r
51ebae6b 1034 NULL,\r
7db61f68 1035 &gEfiEventReadyToBootGuid,\r
51ebae6b 1036 &Event\r
1037 );\r
1038 ASSERT_EFI_ERROR (Status);\r
1039\r
1040 Status = gBS->CreateEventEx (\r
1041 EVT_NOTIFY_SIGNAL,\r
1042 TPL_NOTIFY,\r
1043 UndiNotifyVirtual,\r
1044 NULL,\r
1045 &gEfiEventVirtualAddressChangeGuid,\r
1046 &Event\r
1047 );\r
1048 ASSERT_EFI_ERROR (Status);\r
1049\r
1050 return Status;\r
1051}\r