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