]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
OvmfPkg: PciHostBridgeDxe: eliminate nominal support for multiple host bridges
[mirror_edk2.git] / OvmfPkg / PciHostBridgeDxe / PciHostBridge.c
1 /** @file
2 Provides the basic interfaces to abstract a PCI Host Bridge Resource
3 Allocation
4
5 Copyright (C) 2015, Red Hat, Inc.
6 Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
7
8 This program and the accompanying materials are licensed and made available
9 under the terms and conditions of the BSD License which accompanies this
10 distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include "PciHostBridge.h"
19
20 //
21 // Hard code: Root Bridge Number within the host bridge
22 // Root Bridge's attribute
23 // Root Bridge's device path
24 // Root Bridge's resource aperture
25 //
26 UINTN RootBridgeNumber = 1;
27
28 UINT64 RootBridgeAttribute[1] = {
29 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
30 };
31
32 EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1] = {
33 {
34 {
35 {
36 ACPI_DEVICE_PATH,
37 ACPI_DP,
38 {
39 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
40 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
41 }
42 },
43 EISA_PNP_ID(0x0A03),
44 0
45 },
46
47 {
48 END_DEVICE_PATH_TYPE,
49 END_ENTIRE_DEVICE_PATH_SUBTYPE,
50 {
51 END_DEVICE_PATH_LENGTH,
52 0
53 }
54 }
55 }
56 };
57
58 PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1] = {
59 {0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}
60 };
61
62 EFI_HANDLE mDriverImageHandle;
63
64 PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
65 PCI_HOST_BRIDGE_SIGNATURE, // Signature
66 NULL, // HostBridgeHandle
67 0, // RootBridgeNumber
68 {NULL, NULL}, // Head
69 FALSE, // ResourceSubiteed
70 TRUE, // CanRestarted
71 {
72 NotifyPhase,
73 GetNextRootBridge,
74 GetAttributes,
75 StartBusEnumeration,
76 SetBusNumbers,
77 SubmitResources,
78 GetProposedResources,
79 PreprocessController
80 }
81 };
82
83 //
84 // Implementation
85 //
86
87 /**
88 Entry point of this driver
89
90 @param ImageHandle Handle of driver image
91 @param SystemTable Point to EFI_SYSTEM_TABLE
92
93 @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
94 @retval EFI_DEVICE_ERROR Can not install the protocol instance
95 @retval EFI_SUCCESS Success to initialize the Pci host bridge.
96 **/
97 EFI_STATUS
98 EFIAPI
99 InitializePciHostBridge (
100 IN EFI_HANDLE ImageHandle,
101 IN EFI_SYSTEM_TABLE *SystemTable
102 )
103 {
104 EFI_STATUS Status;
105 UINTN Loop2;
106 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
107 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
108
109 mDriverImageHandle = ImageHandle;
110
111 //
112 // Create Host Bridge Device Handle
113 //
114 HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE),
115 &mPciHostBridgeInstanceTemplate);
116 if (HostBridge == NULL) {
117 return EFI_OUT_OF_RESOURCES;
118 }
119
120 HostBridge->RootBridgeNumber = RootBridgeNumber;
121 InitializeListHead (&HostBridge->Head);
122
123 Status = gBS->InstallMultipleProtocolInterfaces (
124 &HostBridge->HostBridgeHandle,
125 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
126 &HostBridge->ResAlloc,
127 NULL
128 );
129 if (EFI_ERROR (Status)) {
130 FreePool (HostBridge);
131 return EFI_DEVICE_ERROR;
132 }
133
134 //
135 // Create Root Bridge Device Handle in this Host Bridge
136 //
137
138 for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
139 PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));
140 if (PrivateData == NULL) {
141 return EFI_OUT_OF_RESOURCES;
142 }
143
144 PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
145 PrivateData->DevicePath =
146 (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop2];
147
148 RootBridgeConstructor (
149 &PrivateData->Io,
150 HostBridge->HostBridgeHandle,
151 RootBridgeAttribute[Loop2],
152 &mResAperture[Loop2]
153 );
154
155 Status = gBS->InstallMultipleProtocolInterfaces(
156 &PrivateData->Handle,
157 &gEfiDevicePathProtocolGuid,
158 PrivateData->DevicePath,
159 &gEfiPciRootBridgeIoProtocolGuid,
160 &PrivateData->Io,
161 NULL
162 );
163 if (EFI_ERROR (Status)) {
164 FreePool(PrivateData);
165 return EFI_DEVICE_ERROR;
166 }
167
168 InsertTailList (&HostBridge->Head, &PrivateData->Link);
169 }
170
171 return EFI_SUCCESS;
172 }
173
174
175 /**
176 These are the notifications from the PCI bus driver that it is about to enter
177 a certain phase of the PCI enumeration process.
178
179 This member function can be used to notify the host bridge driver to perform
180 specific actions, including any chipset-specific initialization, so that the
181 chipset is ready to enter the next phase. Eight notification points are
182 defined at this time. See belows:
183
184 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures
185 and internal data structures. The PCI
186 enumerator should issue this
187 notification before starting a fresh
188 enumeration process. Enumeration
189 cannot be restarted after sending any
190 other notification such as
191 EfiPciHostBridgeBeginBusAllocation.
192
193 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to
194 begin. No specific action is required
195 here. This notification can be used to
196 perform any chipset-specific
197 programming.
198
199 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming
200 phase is complete. No specific action
201 is required here. This notification
202 can be used to perform any
203 chipset-specific programming.
204
205 EfiPciHostBridgeBeginResourceAllocation
206 The resource allocation phase is about
207 to begin. No specific action is
208 required here. This notification can
209 be used to perform any
210 chipset-specific programming.
211
212 EfiPciHostBridgeAllocateResources Allocates resources per previously
213 submitted requests for all the PCI
214 root bridges. These resource settings
215 are returned on the next call to
216 GetProposedResources(). Before calling
217 NotifyPhase() with a Phase of
218 EfiPciHostBridgeAllocateResource, the
219 PCI bus enumerator is responsible for
220 gathering I/O and memory requests for
221 all the PCI root bridges and
222 submitting these requests using
223 SubmitResources(). This function pads
224 the resource amount to suit the root
225 bridge hardware, takes care of
226 dependencies between the PCI root
227 bridges, and calls the Global
228 Coherency Domain (GCD) with the
229 allocation request. In the case of
230 padding, the allocated range could be
231 bigger than what was requested.
232
233 EfiPciHostBridgeSetResources Programs the host bridge hardware to
234 decode previously allocated resources
235 (proposed resources) for all the PCI
236 root bridges. After the hardware is
237 programmed, reassigning resources will
238 not be supported. The bus settings are
239 not affected.
240
241 EfiPciHostBridgeFreeResources Deallocates resources that were
242 previously allocated for all the PCI
243 root bridges and resets the I/O and
244 memory apertures to their initial
245 state. The bus settings are not
246 affected. If the request to allocate
247 resources fails, the PCI enumerator
248 can use this notification to
249 deallocate previous resources, adjust
250 the requests, and retry allocation.
251
252 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is
253 completed. No specific action is
254 required here. This notification can
255 be used to perform any chipsetspecific
256 programming.
257
258 @param[in] This The instance pointer of
259 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
260
261 @param[in] Phase The phase during enumeration
262
263 @retval EFI_NOT_READY This phase cannot be entered at this time. For
264 example, this error is valid for a Phase of
265 EfiPciHostBridgeAllocateResources if
266 SubmitResources() has not been called for one
267 or more PCI root bridges before this call
268
269 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
270 This error is valid for a Phase of
271 EfiPciHostBridgeSetResources.
272
273 @retval EFI_INVALID_PARAMETER Invalid phase parameter
274
275 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
276 lack of resources. This error is valid for a
277 Phase of EfiPciHostBridgeAllocateResources if
278 the previously submitted resource requests
279 cannot be fulfilled or were only partially
280 fulfilled.
281
282 @retval EFI_SUCCESS The notification was accepted without any
283 errors.
284 **/
285 EFI_STATUS
286 EFIAPI
287 NotifyPhase(
288 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
289 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
290 )
291 {
292 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
293 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
294 PCI_RESOURCE_TYPE Index;
295 LIST_ENTRY *List;
296 EFI_PHYSICAL_ADDRESS BaseAddress;
297 UINT64 AddrLen;
298 UINTN BitsOfAlignment;
299 EFI_STATUS Status;
300 EFI_STATUS ReturnStatus;
301
302 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
303
304 switch (Phase) {
305
306 case EfiPciHostBridgeBeginEnumeration:
307 if (HostBridgeInstance->CanRestarted) {
308 //
309 // Reset the Each Root Bridge
310 //
311 List = HostBridgeInstance->Head.ForwardLink;
312
313 while (List != &HostBridgeInstance->Head) {
314 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
315 for (Index = TypeIo; Index < TypeMax; Index++) {
316 RootBridgeInstance->ResAllocNode[Index].Type = Index;
317 RootBridgeInstance->ResAllocNode[Index].Base = 0;
318 RootBridgeInstance->ResAllocNode[Index].Length = 0;
319 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
320 }
321
322 List = List->ForwardLink;
323 }
324
325 HostBridgeInstance->ResourceSubmited = FALSE;
326 HostBridgeInstance->CanRestarted = TRUE;
327 } else {
328 //
329 // Can not restart
330 //
331 return EFI_NOT_READY;
332 }
333 break;
334
335 case EfiPciHostBridgeEndEnumeration:
336 break;
337
338 case EfiPciHostBridgeBeginBusAllocation:
339 //
340 // No specific action is required here, can perform any chipset specific
341 // programing
342 //
343 HostBridgeInstance->CanRestarted = FALSE;
344 break;
345
346 case EfiPciHostBridgeEndBusAllocation:
347 //
348 // No specific action is required here, can perform any chipset specific
349 // programing
350 //
351 //HostBridgeInstance->CanRestarted = FALSE;
352 break;
353
354 case EfiPciHostBridgeBeginResourceAllocation:
355 //
356 // No specific action is required here, can perform any chipset specific
357 // programing
358 //
359 //HostBridgeInstance->CanRestarted = FALSE;
360 break;
361
362 case EfiPciHostBridgeAllocateResources:
363 ReturnStatus = EFI_SUCCESS;
364 if (HostBridgeInstance->ResourceSubmited) {
365 //
366 // Take care of the resource dependencies between the root bridges
367 //
368 List = HostBridgeInstance->Head.ForwardLink;
369
370 while (List != &HostBridgeInstance->Head) {
371 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
372 for (Index = TypeIo; Index < TypeBus; Index++) {
373 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
374
375 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
376
377 //
378 // Get the number of '1' in Alignment.
379 //
380 BitsOfAlignment =
381 (UINTN)(HighBitSet64 (
382 RootBridgeInstance->ResAllocNode[Index].Alignment
383 ) + 1);
384
385 switch (Index) {
386
387 case TypeIo:
388 //
389 // It is impossible for this chipset to align 0xFFFF for IO16
390 // So clear it
391 //
392 if (BitsOfAlignment >= 16) {
393 BitsOfAlignment = 0;
394 }
395
396 Status = gDS->AllocateIoSpace (
397 EfiGcdAllocateAnySearchBottomUp,
398 EfiGcdIoTypeIo,
399 BitsOfAlignment,
400 AddrLen,
401 &BaseAddress,
402 mDriverImageHandle,
403 NULL
404 );
405
406 if (!EFI_ERROR (Status)) {
407 RootBridgeInstance->ResAllocNode[Index].Base =
408 (UINTN)BaseAddress;
409 RootBridgeInstance->ResAllocNode[Index].Status =
410 ResAllocated;
411 } else {
412 ReturnStatus = Status;
413 if (Status != EFI_OUT_OF_RESOURCES) {
414 RootBridgeInstance->ResAllocNode[Index].Length = 0;
415 }
416 }
417
418 break;
419
420
421 case TypeMem32:
422 //
423 // It is impossible for this chipset to align 0xFFFFFFFF for
424 // Mem32
425 // So clear it
426 //
427
428 if (BitsOfAlignment >= 32) {
429 BitsOfAlignment = 0;
430 }
431
432 Status = gDS->AllocateMemorySpace (
433 EfiGcdAllocateAnySearchBottomUp,
434 EfiGcdMemoryTypeMemoryMappedIo,
435 BitsOfAlignment,
436 AddrLen,
437 &BaseAddress,
438 mDriverImageHandle,
439 NULL
440 );
441
442 if (!EFI_ERROR (Status)) {
443 // We were able to allocate the PCI memory
444 RootBridgeInstance->ResAllocNode[Index].Base =
445 (UINTN)BaseAddress;
446 RootBridgeInstance->ResAllocNode[Index].Status =
447 ResAllocated;
448
449 } else {
450 // Not able to allocate enough PCI memory
451 ReturnStatus = Status;
452
453 if (Status != EFI_OUT_OF_RESOURCES) {
454 RootBridgeInstance->ResAllocNode[Index].Length = 0;
455 }
456 ASSERT (FALSE);
457 }
458 break;
459
460 case TypePMem32:
461 case TypeMem64:
462 case TypePMem64:
463 ReturnStatus = EFI_ABORTED;
464 break;
465 default:
466 ASSERT (FALSE);
467 break;
468 }; //end switch
469 }
470 }
471
472 List = List->ForwardLink;
473 }
474
475 return ReturnStatus;
476
477 } else {
478 return EFI_NOT_READY;
479 }
480 break;
481
482 case EfiPciHostBridgeSetResources:
483 break;
484
485 case EfiPciHostBridgeFreeResources:
486 ReturnStatus = EFI_SUCCESS;
487 List = HostBridgeInstance->Head.ForwardLink;
488 while (List != &HostBridgeInstance->Head) {
489 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
490 for (Index = TypeIo; Index < TypeBus; Index++) {
491 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
492 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
493 BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
494 switch (Index) {
495
496 case TypeIo:
497 Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
498 if (EFI_ERROR (Status)) {
499 ReturnStatus = Status;
500 }
501 break;
502
503 case TypeMem32:
504 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
505 if (EFI_ERROR (Status)) {
506 ReturnStatus = Status;
507 }
508 break;
509
510 case TypePMem32:
511 break;
512
513 case TypeMem64:
514 break;
515
516 case TypePMem64:
517 break;
518
519 default:
520 ASSERT (FALSE);
521 break;
522
523 }; //end switch
524 RootBridgeInstance->ResAllocNode[Index].Type = Index;
525 RootBridgeInstance->ResAllocNode[Index].Base = 0;
526 RootBridgeInstance->ResAllocNode[Index].Length = 0;
527 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
528 }
529 }
530
531 List = List->ForwardLink;
532 }
533
534 HostBridgeInstance->ResourceSubmited = FALSE;
535 HostBridgeInstance->CanRestarted = TRUE;
536 return ReturnStatus;
537
538 case EfiPciHostBridgeEndResourceAllocation:
539 HostBridgeInstance->CanRestarted = FALSE;
540 break;
541
542 default:
543 return EFI_INVALID_PARAMETER;
544 }
545
546 return EFI_SUCCESS;
547 }
548
549 /**
550 Return the device handle of the next PCI root bridge that is associated with
551 this Host Bridge.
552
553 This function is called multiple times to retrieve the device handles of all
554 the PCI root bridges that are associated with this PCI host bridge. Each PCI
555 host bridge is associated with one or more PCI root bridges. On each call,
556 the handle that was returned by the previous call is passed into the
557 interface, and on output the interface returns the device handle of the next
558 PCI root bridge. The caller can use the handle to obtain the instance of the
559 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL for that root bridge. When there are no more
560 PCI root bridges to report, the interface returns EFI_NOT_FOUND. A PCI
561 enumerator must enumerate the PCI root bridges in the order that they are
562 returned by this function.
563
564 For D945 implementation, there is only one root bridge in PCI host bridge.
565
566 @param[in] This The instance pointer of
567 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
568
569 @param[in, out] RootBridgeHandle Returns the device handle of the next PCI
570 root bridge.
571
572 @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then
573 return the first Rootbridge handle of the
574 specific Host bridge and return EFI_SUCCESS.
575
576 @retval EFI_NOT_FOUND Can not find the any more root bridge in
577 specific host bridge.
578
579 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
580 returned on a previous call to
581 GetNextRootBridge().
582 **/
583 EFI_STATUS
584 EFIAPI
585 GetNextRootBridge(
586 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
587 IN OUT EFI_HANDLE *RootBridgeHandle
588 )
589 {
590 BOOLEAN NoRootBridge;
591 LIST_ENTRY *List;
592 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
593 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
594
595 NoRootBridge = TRUE;
596 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
597 List = HostBridgeInstance->Head.ForwardLink;
598
599
600 while (List != &HostBridgeInstance->Head) {
601 NoRootBridge = FALSE;
602 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
603 if (*RootBridgeHandle == NULL) {
604 //
605 // Return the first Root Bridge Handle of the Host Bridge
606 //
607 *RootBridgeHandle = RootBridgeInstance->Handle;
608 return EFI_SUCCESS;
609 } else {
610 if (*RootBridgeHandle == RootBridgeInstance->Handle) {
611 //
612 // Get next if have
613 //
614 List = List->ForwardLink;
615 if (List!=&HostBridgeInstance->Head) {
616 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
617 *RootBridgeHandle = RootBridgeInstance->Handle;
618 return EFI_SUCCESS;
619 } else {
620 return EFI_NOT_FOUND;
621 }
622 }
623 }
624
625 List = List->ForwardLink;
626 } //end while
627
628 if (NoRootBridge) {
629 return EFI_NOT_FOUND;
630 } else {
631 return EFI_INVALID_PARAMETER;
632 }
633 }
634
635 /**
636 Returns the allocation attributes of a PCI root bridge.
637
638 The function returns the allocation attributes of a specific PCI root bridge.
639 The attributes can vary from one PCI root bridge to another. These attributes
640 are different from the decode-related attributes that are returned by the
641 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
642 RootBridgeHandle parameter is used to specify the instance of the PCI root
643 bridge. The device handles of all the root bridges that are associated with
644 this host bridge must be obtained by calling GetNextRootBridge(). The
645 attributes are static in the sense that they do not change during or after
646 the enumeration process. The hardware may provide mechanisms to change the
647 attributes on the fly, but such changes must be completed before
648 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is installed. The permitted
649 values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
650 "Related Definitions" below. The caller uses these attributes to combine
651 multiple resource requests.
652
653 For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI
654 bus enumerator needs to include requests for the prefetchable memory in the
655 nonprefetchable memory pool and not request any prefetchable memory.
656
657 Attribute Description
658 ------------------------------------ ---------------------------------------
659 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root
660 bridge does not support separate
661 windows for nonprefetchable and
662 prefetchable memory. A PCI bus driver
663 needs to include requests for
664 prefetchable memory in the
665 nonprefetchable memory pool.
666
667 EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root
668 bridge supports 64-bit memory windows.
669 If this bit is not set, the PCI bus
670 driver needs to include requests for a
671 64-bit memory address in the
672 corresponding 32-bit memory pool.
673
674 @param[in] This The instance pointer of
675 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
676
677 @param[in] RootBridgeHandle The device handle of the PCI root bridge in
678 which the caller is interested. Type
679 EFI_HANDLE is defined in
680 InstallProtocolInterface() in the UEFI 2.0
681 Specification.
682
683 @param[out] Attributes The pointer to attribte of root bridge, it is
684 output parameter
685
686 @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
687
688 @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
689
690 @retval EFI_SUCCESS Success to get attribute of interested root
691 bridge.
692 **/
693 EFI_STATUS
694 EFIAPI
695 GetAttributes(
696 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
697 IN EFI_HANDLE RootBridgeHandle,
698 OUT UINT64 *Attributes
699 )
700 {
701 LIST_ENTRY *List;
702 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
703 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
704
705 if (Attributes == NULL) {
706 return EFI_INVALID_PARAMETER;
707 }
708
709 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
710 List = HostBridgeInstance->Head.ForwardLink;
711
712 while (List != &HostBridgeInstance->Head) {
713 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
714 if (RootBridgeHandle == RootBridgeInstance->Handle) {
715 *Attributes = RootBridgeInstance->RootBridgeAttrib;
716 return EFI_SUCCESS;
717 }
718 List = List->ForwardLink;
719 }
720
721 //
722 // RootBridgeHandle is not an EFI_HANDLE
723 // that was returned on a previous call to GetNextRootBridge()
724 //
725 return EFI_INVALID_PARAMETER;
726 }
727
728 /**
729 Sets up the specified PCI root bridge for the bus enumeration process.
730
731 This member function sets up the root bridge for bus enumeration and returns
732 the PCI bus range over which the search should be performed in ACPI 2.0
733 resource descriptor format.
734
735 @param[in] This The
736 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
737 instance.
738
739 @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
740
741 @param[out] Configuration Pointer to the pointer to the PCI bus resource
742 descriptor.
743
744 @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
745
746 @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
747
748 @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
749 **/
750 EFI_STATUS
751 EFIAPI
752 StartBusEnumeration(
753 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
754 IN EFI_HANDLE RootBridgeHandle,
755 OUT VOID **Configuration
756 )
757 {
758 LIST_ENTRY *List;
759 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
760 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
761 VOID *Buffer;
762 UINT8 *Temp;
763 UINT64 BusStart;
764 UINT64 BusEnd;
765
766 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
767 List = HostBridgeInstance->Head.ForwardLink;
768
769 while (List != &HostBridgeInstance->Head) {
770 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
771 if (RootBridgeHandle == RootBridgeInstance->Handle) {
772 //
773 // Set up the Root Bridge for Bus Enumeration
774 //
775 BusStart = RootBridgeInstance->BusBase;
776 BusEnd = RootBridgeInstance->BusLimit;
777 //
778 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
779 //
780
781 Buffer = AllocatePool (
782 sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
783 sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
784 );
785 if (Buffer == NULL) {
786 return EFI_OUT_OF_RESOURCES;
787 }
788
789 Temp = (UINT8 *)Buffer;
790
791 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;
792 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B;
793 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;
794 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
795 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;
796 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;
797 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;
798 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;
799 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
800 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen =
801 BusEnd - BusStart + 1;
802
803 Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
804 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
805 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
806
807 *Configuration = Buffer;
808 return EFI_SUCCESS;
809 }
810 List = List->ForwardLink;
811 }
812
813 return EFI_INVALID_PARAMETER;
814 }
815
816 /**
817 Programs the PCI root bridge hardware so that it decodes the specified PCI
818 bus range.
819
820 This member function programs the specified PCI root bridge to decode the bus
821 range that is specified by the input parameter Configuration.
822 The bus range information is specified in terms of the ACPI 2.0 resource
823 descriptor format.
824
825 @param[in] This The
826 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
827 instance
828
829 @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be
830 programmed
831
832 @param[in] Configuration The pointer to the PCI bus resource descriptor
833
834 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
835 handle.
836
837 @retval EFI_INVALID_PARAMETER Configuration is NULL.
838
839 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
840 2.0 resource descriptor.
841
842 @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI
843 2.0 bus resource descriptor.
844
845 @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource
846 descriptors other than bus descriptors.
847
848 @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid
849 ACPI resource descriptors.
850
851 @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this
852 root bridge.
853
854 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this
855 root bridge.
856
857 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
858
859 @retval EFI_SUCCESS The bus range for the PCI root bridge was
860 programmed.
861 **/
862 EFI_STATUS
863 EFIAPI
864 SetBusNumbers(
865 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
866 IN EFI_HANDLE RootBridgeHandle,
867 IN VOID *Configuration
868 )
869 {
870 LIST_ENTRY *List;
871 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
872 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
873 UINT8 *Ptr;
874 UINTN BusStart;
875 UINTN BusEnd;
876 UINTN BusLen;
877
878 if (Configuration == NULL) {
879 return EFI_INVALID_PARAMETER;
880 }
881
882 Ptr = Configuration;
883
884 //
885 // Check the Configuration is valid
886 //
887 if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
888 return EFI_INVALID_PARAMETER;
889 }
890
891 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
892 return EFI_INVALID_PARAMETER;
893 }
894
895 Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
896 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
897 return EFI_INVALID_PARAMETER;
898 }
899
900 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
901 List = HostBridgeInstance->Head.ForwardLink;
902
903 Ptr = Configuration;
904
905 while (List != &HostBridgeInstance->Head) {
906 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
907 if (RootBridgeHandle == RootBridgeInstance->Handle) {
908 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
909
910 Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
911 BusStart = (UINTN)Desc->AddrRangeMin;
912 BusLen = (UINTN)Desc->AddrLen;
913 BusEnd = BusStart + BusLen - 1;
914
915 if (BusStart > BusEnd) {
916 return EFI_INVALID_PARAMETER;
917 }
918
919 if ((BusStart < RootBridgeInstance->BusBase) ||
920 (BusEnd > RootBridgeInstance->BusLimit)) {
921 return EFI_INVALID_PARAMETER;
922 }
923
924 //
925 // Update the Bus Range
926 //
927 RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;
928 RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
929 RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
930
931 //
932 // Program the Root Bridge Hardware
933 //
934
935 return EFI_SUCCESS;
936 }
937
938 List = List->ForwardLink;
939 }
940
941 return EFI_INVALID_PARAMETER;
942 }
943
944
945 /**
946 Submits the I/O and memory resource requirements for the specified PCI root
947 bridge.
948
949 This function is used to submit all the I/O and memory resources that are
950 required by the specified PCI root bridge. The input parameter Configuration
951 is used to specify the following:
952 - The various types of resources that are required
953 - The associated lengths in terms of ACPI 2.0 resource descriptor format
954
955 @param[in] This Pointer to the
956 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
957 instance.
958
959 @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory
960 resource requirements are being submitted.
961
962 @param[in] Configuration The pointer to the PCI I/O and PCI memory
963 resource descriptor.
964
965 @retval EFI_SUCCESS The I/O and memory resource requests for a PCI
966 root bridge were accepted.
967
968 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
969 handle.
970
971 @retval EFI_INVALID_PARAMETER Configuration is NULL.
972
973 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
974 2.0 resource descriptor.
975
976 @retval EFI_INVALID_PARAMETER Configuration includes requests for one or
977 more resource types that are not supported by
978 this PCI root bridge. This error will happen
979 if the caller did not combine resources
980 according to Attributes that were returned by
981 GetAllocAttributes().
982
983 @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
984
985 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI
986 root bridge.
987
988 @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for
989 this PCI root bridge.
990 **/
991 EFI_STATUS
992 EFIAPI
993 SubmitResources(
994 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
995 IN EFI_HANDLE RootBridgeHandle,
996 IN VOID *Configuration
997 )
998 {
999 LIST_ENTRY *List;
1000 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1001 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1002 UINT8 *Temp;
1003 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1004 UINT64 AddrLen;
1005 UINT64 Alignment;
1006
1007 //
1008 // Check the input parameter: Configuration
1009 //
1010 if (Configuration == NULL) {
1011 return EFI_INVALID_PARAMETER;
1012 }
1013
1014 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1015 List = HostBridgeInstance->Head.ForwardLink;
1016
1017 Temp = (UINT8 *)Configuration;
1018 while ( *Temp == 0x8A) {
1019 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
1020 }
1021 if (*Temp != 0x79) {
1022 return EFI_INVALID_PARAMETER;
1023 }
1024
1025 Temp = (UINT8 *)Configuration;
1026 while (List != &HostBridgeInstance->Head) {
1027 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1028 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1029 while ( *Temp == 0x8A) {
1030 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
1031
1032 //
1033 // Check Address Length
1034 //
1035 if (Ptr->AddrLen > 0xffffffff) {
1036 return EFI_INVALID_PARAMETER;
1037 }
1038
1039 //
1040 // Check address range alignment
1041 //
1042 if (Ptr->AddrRangeMax >= 0xffffffff ||
1043 Ptr->AddrRangeMax != (GetPowerOfTwo64 (
1044 Ptr->AddrRangeMax + 1) - 1)) {
1045 return EFI_INVALID_PARAMETER;
1046 }
1047
1048 switch (Ptr->ResType) {
1049
1050 case 0:
1051
1052 //
1053 // Check invalid Address Sapce Granularity
1054 //
1055 if (Ptr->AddrSpaceGranularity != 32) {
1056 return EFI_INVALID_PARAMETER;
1057 }
1058
1059 //
1060 // check the memory resource request is supported by PCI root bridge
1061 //
1062 if (RootBridgeInstance->RootBridgeAttrib ==
1063 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
1064 Ptr->SpecificFlag == 0x06) {
1065 return EFI_INVALID_PARAMETER;
1066 }
1067
1068 AddrLen = Ptr->AddrLen;
1069 Alignment = Ptr->AddrRangeMax;
1070 if (Ptr->AddrSpaceGranularity == 32) {
1071 if (Ptr->SpecificFlag == 0x06) {
1072 //
1073 // Apply from GCD
1074 //
1075 RootBridgeInstance->ResAllocNode[TypePMem32].Status =
1076 ResSubmitted;
1077 } else {
1078 RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
1079 RootBridgeInstance->ResAllocNode[TypeMem32].Alignment =
1080 Alignment;
1081 RootBridgeInstance->ResAllocNode[TypeMem32].Status =
1082 ResRequested;
1083 HostBridgeInstance->ResourceSubmited = TRUE;
1084 }
1085 }
1086
1087 if (Ptr->AddrSpaceGranularity == 64) {
1088 if (Ptr->SpecificFlag == 0x06) {
1089 RootBridgeInstance->ResAllocNode[TypePMem64].Status =
1090 ResSubmitted;
1091 } else {
1092 RootBridgeInstance->ResAllocNode[TypeMem64].Status =
1093 ResSubmitted;
1094 }
1095 }
1096 break;
1097
1098 case 1:
1099 AddrLen = (UINTN) Ptr->AddrLen;
1100 Alignment = (UINTN) Ptr->AddrRangeMax;
1101 RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;
1102 RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
1103 RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;
1104 HostBridgeInstance->ResourceSubmited = TRUE;
1105 break;
1106
1107 default:
1108 break;
1109 };
1110
1111 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
1112 }
1113
1114 return EFI_SUCCESS;
1115 }
1116
1117 List = List->ForwardLink;
1118 }
1119
1120 return EFI_INVALID_PARAMETER;
1121 }
1122
1123 /**
1124 Returns the proposed resource settings for the specified PCI root bridge.
1125
1126 This member function returns the proposed resource settings for the
1127 specified PCI root bridge. The proposed resource settings are prepared when
1128 NotifyPhase() is called with a Phase of EfiPciHostBridgeAllocateResources.
1129 The output parameter Configuration specifies the following:
1130 - The various types of resources, excluding bus resources, that are
1131 allocated
1132 - The associated lengths in terms of ACPI 2.0 resource descriptor format
1133
1134 @param[in] This Pointer to the
1135 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1136 instance.
1137
1138 @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is
1139 defined in InstallProtocolInterface() in the
1140 UEFI 2.0 Specification.
1141
1142 @param[out] Configuration The pointer to the pointer to the PCI I/O and
1143 memory resource descriptor.
1144
1145 @retval EFI_SUCCESS The requested parameters were returned.
1146
1147 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
1148 handle.
1149
1150 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
1151
1152 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1153 lack of resources.
1154 **/
1155 EFI_STATUS
1156 EFIAPI
1157 GetProposedResources(
1158 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1159 IN EFI_HANDLE RootBridgeHandle,
1160 OUT VOID **Configuration
1161 )
1162 {
1163 LIST_ENTRY *List;
1164 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1165 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1166 UINTN Index;
1167 UINTN Number;
1168 VOID *Buffer;
1169 UINT8 *Temp;
1170 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1171 UINT64 ResStatus;
1172
1173 Buffer = NULL;
1174 Number = 0;
1175 //
1176 // Get the Host Bridge Instance from the resource allocation protocol
1177 //
1178 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1179 List = HostBridgeInstance->Head.ForwardLink;
1180
1181 //
1182 // Enumerate the root bridges in this host bridge
1183 //
1184 while (List != &HostBridgeInstance->Head) {
1185 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1186 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1187 for (Index = 0; Index < TypeBus; Index ++) {
1188 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
1189 Number ++;
1190 }
1191 }
1192
1193 if (Number == 0) {
1194 return EFI_INVALID_PARAMETER;
1195 }
1196
1197 Buffer = AllocateZeroPool (
1198 Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
1199 sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
1200 );
1201 if (Buffer == NULL) {
1202 return EFI_OUT_OF_RESOURCES;
1203 }
1204
1205 Temp = Buffer;
1206 for (Index = 0; Index < TypeBus; Index ++) {
1207 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
1208 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
1209 ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
1210
1211 switch (Index) {
1212
1213 case TypeIo:
1214 //
1215 // Io
1216 //
1217 Ptr->Desc = 0x8A;
1218 Ptr->Len = 0x2B;
1219 Ptr->ResType = 1;
1220 Ptr->GenFlag = 0;
1221 Ptr->SpecificFlag = 0;
1222 Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
1223 Ptr->AddrRangeMax = 0;
1224 Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
1225 EFI_RESOURCE_SATISFIED :
1226 EFI_RESOURCE_LESS;
1227 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
1228 break;
1229
1230 case TypeMem32:
1231 //
1232 // Memory 32
1233 //
1234 Ptr->Desc = 0x8A;
1235 Ptr->Len = 0x2B;
1236 Ptr->ResType = 0;
1237 Ptr->GenFlag = 0;
1238 Ptr->SpecificFlag = 0;
1239 Ptr->AddrSpaceGranularity = 32;
1240 Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
1241 Ptr->AddrRangeMax = 0;
1242 Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
1243 EFI_RESOURCE_SATISFIED :
1244 EFI_RESOURCE_LESS;
1245 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
1246 break;
1247
1248 case TypePMem32:
1249 //
1250 // Prefetch memory 32
1251 //
1252 Ptr->Desc = 0x8A;
1253 Ptr->Len = 0x2B;
1254 Ptr->ResType = 0;
1255 Ptr->GenFlag = 0;
1256 Ptr->SpecificFlag = 6;
1257 Ptr->AddrSpaceGranularity = 32;
1258 Ptr->AddrRangeMin = 0;
1259 Ptr->AddrRangeMax = 0;
1260 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1261 Ptr->AddrLen = 0;
1262 break;
1263
1264 case TypeMem64:
1265 //
1266 // Memory 64
1267 //
1268 Ptr->Desc = 0x8A;
1269 Ptr->Len = 0x2B;
1270 Ptr->ResType = 0;
1271 Ptr->GenFlag = 0;
1272 Ptr->SpecificFlag = 0;
1273 Ptr->AddrSpaceGranularity = 64;
1274 Ptr->AddrRangeMin = 0;
1275 Ptr->AddrRangeMax = 0;
1276 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1277 Ptr->AddrLen = 0;
1278 break;
1279
1280 case TypePMem64:
1281 //
1282 // Prefetch memory 64
1283 //
1284 Ptr->Desc = 0x8A;
1285 Ptr->Len = 0x2B;
1286 Ptr->ResType = 0;
1287 Ptr->GenFlag = 0;
1288 Ptr->SpecificFlag = 6;
1289 Ptr->AddrSpaceGranularity = 64;
1290 Ptr->AddrRangeMin = 0;
1291 Ptr->AddrRangeMax = 0;
1292 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1293 Ptr->AddrLen = 0;
1294 break;
1295 };
1296
1297 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1298 }
1299 }
1300
1301 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
1302 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
1303
1304 *Configuration = Buffer;
1305
1306 return EFI_SUCCESS;
1307 }
1308
1309 List = List->ForwardLink;
1310 }
1311
1312 return EFI_INVALID_PARAMETER;
1313 }
1314
1315 /**
1316 Provides the hooks from the PCI bus driver to every PCI controller
1317 (device/function) at various stages of the PCI enumeration process that allow
1318 the host bridge driver to preinitialize individual PCI controllers before
1319 enumeration.
1320
1321 This function is called during the PCI enumeration process. No specific
1322 action is expected from this member function. It allows the host bridge
1323 driver to preinitialize individual PCI controllers before enumeration.
1324
1325 @param This Pointer to the
1326 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1327 instance.
1328
1329 @param RootBridgeHandle The associated PCI root bridge handle. Type
1330 EFI_HANDLE is defined in InstallProtocolInterface()
1331 in the UEFI 2.0 Specification.
1332
1333 @param PciAddress The address of the PCI device on the PCI bus. This
1334 address can be passed to the
1335 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to
1336 access the PCI configuration space of the device.
1337 See Table 12-1 in the UEFI 2.0 Specification for the
1338 definition of
1339 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
1340
1341 @param Phase The phase of the PCI device enumeration.
1342
1343 @retval EFI_SUCCESS The requested parameters were returned.
1344
1345 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
1346 handle.
1347
1348 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined
1349 in
1350 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1351
1352 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
1353 The PCI enumerator should not enumerate this
1354 device, including its child devices if it is
1355 a PCI-to-PCI bridge.
1356 **/
1357 EFI_STATUS
1358 EFIAPI
1359 PreprocessController (
1360 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1361 IN EFI_HANDLE RootBridgeHandle,
1362 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
1363 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1364 )
1365 {
1366 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1367 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1368 LIST_ENTRY *List;
1369
1370 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1371 List = HostBridgeInstance->Head.ForwardLink;
1372
1373 //
1374 // Enumerate the root bridges in this host bridge
1375 //
1376 while (List != &HostBridgeInstance->Head) {
1377 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1378 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1379 break;
1380 }
1381 List = List->ForwardLink;
1382 }
1383 if (List == &HostBridgeInstance->Head) {
1384 return EFI_INVALID_PARAMETER;
1385 }
1386
1387 if ((UINT32)Phase > EfiPciBeforeResourceCollection) {
1388 return EFI_INVALID_PARAMETER;
1389 }
1390
1391 return EFI_SUCCESS;
1392 }