08285d84d501239b0bc6136bb2f937b3986369a7
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciHostBridgeDxe / PciHostBridge.c
1 /** @file
2
3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.
4
5 Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "PciHostBridge.h"
17 #include "PciRootBridge.h"
18 #include "PciHostResource.h"
19
20
21 EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
22 EFI_CPU_IO2_PROTOCOL *mCpuIo;
23
24 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {
25 L"Mem", L"I/O", L"Bus"
26 };
27 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {
28 L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"
29 };
30
31 /**
32
33 Entry point of this driver.
34
35 @param ImageHandle Image handle of this driver.
36 @param SystemTable Pointer to standard EFI system table.
37
38 @retval EFI_SUCCESS Succeed.
39 @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.
40
41 **/
42 EFI_STATUS
43 EFIAPI
44 InitializePciHostBridge (
45 IN EFI_HANDLE ImageHandle,
46 IN EFI_SYSTEM_TABLE *SystemTable
47 )
48 {
49 EFI_STATUS Status;
50 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
51 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
52 PCI_ROOT_BRIDGE *RootBridges;
53 UINTN RootBridgeCount;
54 UINTN Index;
55 PCI_ROOT_BRIDGE_APERTURE *MemApertures[4];
56 UINTN MemApertureIndex;
57
58 RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
59 if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
60 return EFI_UNSUPPORTED;
61 }
62
63 Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);
64 ASSERT_EFI_ERROR (Status);
65 Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) &mCpuIo);
66 ASSERT_EFI_ERROR (Status);
67
68 //
69 // Most systems in the world including complex servers have only one Host Bridge.
70 //
71 HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
72 ASSERT (HostBridge != NULL);
73
74 HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;
75 HostBridge->CanRestarted = TRUE;
76 InitializeListHead (&HostBridge->RootBridges);
77
78 HostBridge->ResAlloc.NotifyPhase = NotifyPhase;
79 HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;
80 HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;
81 HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;
82 HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;
83 HostBridge->ResAlloc.SubmitResources = SubmitResources;
84 HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
85 HostBridge->ResAlloc.PreprocessController = PreprocessController;
86
87 Status = gBS->InstallMultipleProtocolInterfaces (
88 &HostBridge->Handle,
89 &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
90 NULL
91 );
92 if (EFI_ERROR (Status)) {
93 FreePool (HostBridge);
94 PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
95 return Status;
96 }
97
98 //
99 // Create Root Bridge Device Handle in this Host Bridge
100 //
101 for (Index = 0; Index < RootBridgeCount; Index++) {
102 //
103 // Create Root Bridge Handle Instance
104 //
105 RootBridge = CreateRootBridge (&RootBridges[Index], HostBridge->Handle);
106 ASSERT (RootBridge != NULL);
107 if (RootBridge == NULL) {
108 continue;
109 }
110
111 if (RootBridges[Index].Io.Limit > RootBridges[Index].Io.Base) {
112 Status = gDS->AddIoSpace (
113 EfiGcdIoTypeIo,
114 RootBridges[Index].Io.Base,
115 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
116 );
117 ASSERT_EFI_ERROR (Status);
118 }
119
120 //
121 // Add all the Mem/PMem aperture to GCD
122 // Mem/PMem shouldn't overlap with each other
123 // Root bridge which needs to combine MEM and PMEM should only report
124 // the MEM aperture in Mem
125 //
126 MemApertures[0] = &RootBridges[Index].Mem;
127 MemApertures[1] = &RootBridges[Index].MemAbove4G;
128 MemApertures[2] = &RootBridges[Index].PMem;
129 MemApertures[3] = &RootBridges[Index].PMemAbove4G;
130
131 for (MemApertureIndex = 0; MemApertureIndex < sizeof (MemApertures) / sizeof (MemApertures[0]); MemApertureIndex++) {
132 if (MemApertures[MemApertureIndex]->Limit > MemApertures[MemApertureIndex]->Base) {
133 Status = gDS->AddMemorySpace (
134 EfiGcdMemoryTypeMemoryMappedIo,
135 MemApertures[MemApertureIndex]->Base,
136 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
137 EFI_MEMORY_UC
138 );
139 ASSERT_EFI_ERROR (Status);
140 Status = gDS->SetMemorySpaceAttributes (
141 MemApertures[MemApertureIndex]->Base,
142 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
143 EFI_MEMORY_UC
144 );
145 ASSERT_EFI_ERROR (Status);
146 }
147 }
148 //
149 // Insert Root Bridge Handle Instance
150 //
151 Status = gBS->InstallMultipleProtocolInterfaces (
152 &RootBridge->Handle,
153 &gEfiDevicePathProtocolGuid, RootBridge->DevicePath,
154 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->RootBridgeIo,
155 NULL
156 );
157 ASSERT_EFI_ERROR (Status);
158 InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
159 }
160 PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
161 return Status;
162 }
163
164 /**
165 This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().
166
167 @param HostBridge The Host Bridge Instance where the resource adjustment happens.
168 **/
169 VOID
170 ResourceConflict (
171 IN PCI_HOST_BRIDGE_INSTANCE *HostBridge
172 )
173 {
174 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;
175 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
176 EFI_ACPI_END_TAG_DESCRIPTOR *End;
177 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
178 LIST_ENTRY *Link;
179 UINTN RootBridgeCount;
180 PCI_RESOURCE_TYPE Index;
181 PCI_RES_NODE *ResAllocNode;
182
183 RootBridgeCount = 0;
184 for (Link = GetFirstNode (&HostBridge->RootBridges)
185 ; !IsNull (&HostBridge->RootBridges, Link)
186 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
187 ) {
188 RootBridgeCount++;
189 }
190
191 Resources = AllocatePool (
192 RootBridgeCount * (TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)) +
193 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
194 );
195 ASSERT (Resources != NULL);
196
197 for (Link = GetFirstNode (&HostBridge->RootBridges), Descriptor = Resources
198 ; !IsNull (&HostBridge->RootBridges, Link)
199 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
200 ) {
201 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
202 for (Index = TypeIo; Index < TypeMax; Index++) {
203 ResAllocNode = &RootBridge->ResAllocNode[Index];
204
205 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
206 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
207 Descriptor->AddrRangeMin = ResAllocNode->Base;
208 Descriptor->AddrRangeMax = ResAllocNode->Alignment;
209 Descriptor->AddrLen = ResAllocNode->Length;
210 switch (ResAllocNode->Type) {
211
212 case TypeIo:
213 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
214 break;
215
216 case TypePMem32:
217 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
218 case TypeMem32:
219 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
220 Descriptor->AddrSpaceGranularity = 32;
221 break;
222
223 case TypePMem64:
224 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
225 case TypeMem64:
226 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
227 Descriptor->AddrSpaceGranularity = 64;
228 break;
229
230 case TypeBus:
231 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
232 break;
233
234 default:
235 break;
236 }
237
238 Descriptor++;
239 }
240 //
241 // Terminate the root bridge resources.
242 //
243 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
244 End->Desc = ACPI_END_TAG_DESCRIPTOR;
245 End->Checksum = 0x0;
246
247 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (End + 1);
248 }
249 //
250 // Terminate the host bridge resources.
251 //
252 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
253 End->Desc = ACPI_END_TAG_DESCRIPTOR;
254 End->Checksum = 0x0;
255
256 DEBUG ((DEBUG_ERROR, "Call PciHostBridgeResourceConflict().\n"));
257 PciHostBridgeResourceConflict (HostBridge->Handle, Resources);
258 FreePool (Resources);
259 }
260
261 UINT64
262 AllocateResource (
263 BOOLEAN Mmio,
264 UINT64 Length,
265 UINTN BitsOfAlignment,
266 UINT64 BaseAddress,
267 UINT64 Limit
268 )
269 {
270 EFI_STATUS Status;
271
272 if (BaseAddress < Limit) {
273 //
274 // Have to make sure Aligment is handled since we are doing direct address allocation
275 //
276 BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));
277
278 while (BaseAddress + Length <= Limit + 1) {
279 if (Mmio) {
280 Status = gDS->AllocateMemorySpace (
281 EfiGcdAllocateAddress,
282 EfiGcdMemoryTypeMemoryMappedIo,
283 BitsOfAlignment,
284 Length,
285 &BaseAddress,
286 gImageHandle,
287 NULL
288 );
289 } else {
290 Status = gDS->AllocateIoSpace (
291 EfiGcdAllocateAddress,
292 EfiGcdIoTypeIo,
293 BitsOfAlignment,
294 Length,
295 &BaseAddress,
296 gImageHandle,
297 NULL
298 );
299 }
300
301 if (!EFI_ERROR (Status)) {
302 return BaseAddress;
303 }
304 BaseAddress += LShiftU64 (1, BitsOfAlignment);
305 }
306 }
307 return MAX_UINT64;
308 }
309 /**
310
311 Enter a certain phase of the PCI enumeration process.
312
313 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
314 @param Phase The phase during enumeration.
315
316 @retval EFI_SUCCESS Succeed.
317 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.
318 @retval EFI_NOT_READY Resources have not been submitted yet.
319
320 **/
321 EFI_STATUS
322 EFIAPI
323 NotifyPhase (
324 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
325 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
326 )
327 {
328 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
329 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
330 LIST_ENTRY *Link;
331 EFI_PHYSICAL_ADDRESS BaseAddress;
332 UINT64 AddrLen;
333 UINTN BitsOfAlignment;
334 UINT64 Alignment;
335 EFI_STATUS Status;
336 EFI_STATUS ReturnStatus;
337 PCI_RESOURCE_TYPE Index;
338 PCI_RESOURCE_TYPE Index1;
339 PCI_RESOURCE_TYPE Index2;
340 BOOLEAN ResNodeHandled[TypeMax];
341 UINT64 MaxAlignment;
342
343 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
344
345 switch (Phase) {
346 case EfiPciHostBridgeBeginEnumeration:
347 if (!HostBridge->CanRestarted) {
348 return EFI_NOT_READY;
349 }
350 //
351 // Reset Root Bridge
352 //
353 for (Link = GetFirstNode (&HostBridge->RootBridges)
354 ; !IsNull (&HostBridge->RootBridges, Link)
355 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
356 ) {
357 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
358 for (Index = TypeIo; Index < TypeMax; Index++) {
359 RootBridge->ResAllocNode[Index].Type = Index;
360 RootBridge->ResAllocNode[Index].Base = 0;
361 RootBridge->ResAllocNode[Index].Length = 0;
362 RootBridge->ResAllocNode[Index].Status = ResNone;
363
364 RootBridge->ResourceSubmitted = FALSE;
365 }
366 }
367
368 HostBridge->CanRestarted = TRUE;
369 break;
370
371 case EfiPciHostBridgeBeginBusAllocation:
372 //
373 // No specific action is required here, can perform any chipset specific programing
374 //
375 HostBridge->CanRestarted = FALSE;
376 break;
377
378 case EfiPciHostBridgeEndBusAllocation:
379 //
380 // No specific action is required here, can perform any chipset specific programing
381 //
382 break;
383
384 case EfiPciHostBridgeBeginResourceAllocation:
385 //
386 // No specific action is required here, can perform any chipset specific programing
387 //
388 break;
389
390 case EfiPciHostBridgeAllocateResources:
391 ReturnStatus = EFI_SUCCESS;
392
393 //
394 // Make sure the resource for all root bridges has been submitted.
395 //
396 for (Link = GetFirstNode (&HostBridge->RootBridges)
397 ; !IsNull (&HostBridge->RootBridges, Link)
398 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
399 ) {
400 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
401 if (!RootBridge->ResourceSubmitted) {
402 return EFI_NOT_READY;
403 }
404 }
405
406 DEBUG ((EFI_D_INFO, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
407 for (Link = GetFirstNode (&HostBridge->RootBridges)
408 ; !IsNull (&HostBridge->RootBridges, Link)
409 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
410 ) {
411 for (Index = TypeIo; Index < TypeBus; Index++) {
412 ResNodeHandled[Index] = FALSE;
413 }
414
415 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
416 DEBUG ((EFI_D_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));
417
418 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
419 if (RootBridge->ResAllocNode[Index1].Status == ResNone) {
420 ResNodeHandled[Index1] = TRUE;
421 } else {
422 //
423 // Allocate the resource node with max alignment at first
424 //
425 MaxAlignment = 0;
426 Index = TypeMax;
427 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {
428 if (ResNodeHandled[Index2]) {
429 continue;
430 }
431 if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {
432 MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;
433 Index = Index2;
434 }
435 }
436
437 ASSERT (Index < TypeMax);
438 ResNodeHandled[Index] = TRUE;
439 AddrLen = RootBridge->ResAllocNode[Index].Length;
440 Alignment = RootBridge->ResAllocNode[Index].Alignment;
441 BitsOfAlignment = LowBitSet64 (Alignment + 1);
442 BaseAddress = MAX_UINT64;
443
444 switch (Index) {
445 case TypeIo:
446 BaseAddress = AllocateResource (
447 FALSE,
448 RootBridge->ResAllocNode[Index].Length,
449 MIN (15, BitsOfAlignment),
450 ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),
451 RootBridge->Io.Limit
452 );
453 break;
454
455 case TypeMem64:
456 BaseAddress = AllocateResource (
457 TRUE,
458 RootBridge->ResAllocNode[Index].Length,
459 MIN (63, BitsOfAlignment),
460 ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),
461 RootBridge->MemAbove4G.Limit
462 );
463 if (BaseAddress != MAX_UINT64) {
464 break;
465 }
466 //
467 // If memory above 4GB is not available, try memory below 4GB
468 //
469
470 case TypeMem32:
471 BaseAddress = AllocateResource (
472 TRUE,
473 RootBridge->ResAllocNode[Index].Length,
474 MIN (31, BitsOfAlignment),
475 ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),
476 RootBridge->Mem.Limit
477 );
478 break;
479
480 case TypePMem64:
481 BaseAddress = AllocateResource (
482 TRUE,
483 RootBridge->ResAllocNode[Index].Length,
484 MIN (63, BitsOfAlignment),
485 ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),
486 RootBridge->PMemAbove4G.Limit
487 );
488 if (BaseAddress != MAX_UINT64) {
489 break;
490 }
491 //
492 // If memory above 4GB is not available, try memory below 4GB
493 //
494 case TypePMem32:
495 BaseAddress = AllocateResource (
496 TRUE,
497 RootBridge->ResAllocNode[Index].Length,
498 MIN (31, BitsOfAlignment),
499 ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),
500 RootBridge->PMem.Limit
501 );
502 break;
503
504 default:
505 ASSERT (FALSE);
506 break;
507 }
508
509 DEBUG ((DEBUG_INFO, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",
510 mPciResourceTypeStr[Index], BaseAddress, RootBridge->ResAllocNode[Index].Length, Alignment));
511 if (BaseAddress != MAX_UINT64) {
512 RootBridge->ResAllocNode[Index].Base = BaseAddress;
513 RootBridge->ResAllocNode[Index].Status = ResAllocated;
514 DEBUG ((DEBUG_INFO, "Success\n"));
515 } else {
516 ReturnStatus = EFI_OUT_OF_RESOURCES;
517 DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));
518 }
519 }
520 }
521 }
522
523 if (ReturnStatus == EFI_OUT_OF_RESOURCES) {
524 ResourceConflict (HostBridge);
525 }
526
527 //
528 // Set resource to zero for nodes where allocation fails
529 //
530 for (Link = GetFirstNode (&HostBridge->RootBridges)
531 ; !IsNull (&HostBridge->RootBridges, Link)
532 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
533 ) {
534 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
535 for (Index = TypeIo; Index < TypeBus; Index++) {
536 if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {
537 RootBridge->ResAllocNode[Index].Length = 0;
538 }
539 }
540 }
541 return ReturnStatus;
542
543 case EfiPciHostBridgeSetResources:
544 //
545 // HostBridgeInstance->CanRestarted = FALSE;
546 //
547 break;
548
549 case EfiPciHostBridgeFreeResources:
550 //
551 // HostBridgeInstance->CanRestarted = FALSE;
552 //
553 ReturnStatus = EFI_SUCCESS;
554 for (Link = GetFirstNode (&HostBridge->RootBridges)
555 ; !IsNull (&HostBridge->RootBridges, Link)
556 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
557 ) {
558 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
559 for (Index = TypeIo; Index < TypeBus; Index++) {
560 if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {
561 switch (Index) {
562 case TypeIo:
563 Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
564 if (EFI_ERROR (Status)) {
565 ReturnStatus = Status;
566 }
567 break;
568
569 case TypeMem32:
570 case TypePMem32:
571 case TypeMem64:
572 case TypePMem64:
573 Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
574 if (EFI_ERROR (Status)) {
575 ReturnStatus = Status;
576 }
577 break;
578
579 default:
580 ASSERT (FALSE);
581 break;
582 }
583
584 RootBridge->ResAllocNode[Index].Type = Index;
585 RootBridge->ResAllocNode[Index].Base = 0;
586 RootBridge->ResAllocNode[Index].Length = 0;
587 RootBridge->ResAllocNode[Index].Status = ResNone;
588 }
589 }
590
591 RootBridge->ResourceSubmitted = FALSE;
592 }
593
594 HostBridge->CanRestarted = TRUE;
595 return ReturnStatus;
596
597 case EfiPciHostBridgeEndResourceAllocation:
598 //
599 // The resource allocation phase is completed. No specific action is required
600 // here. This notification can be used to perform any chipset specific programming.
601 //
602 break;
603
604 case EfiPciHostBridgeEndEnumeration:
605 //
606 // The Host Bridge Enumeration is completed. No specific action is required here.
607 // This notification can be used to perform any chipset specific programming.
608 //
609 break;
610
611 default:
612 return EFI_INVALID_PARAMETER;
613 }
614
615 return EFI_SUCCESS;
616 }
617
618 /**
619
620 Return the device handle of the next PCI root bridge that is associated with
621 this Host Bridge.
622
623 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
624 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.
625 On input, it holds the RootBridgeHandle returned by the most
626 recent call to GetNextRootBridge().The handle for the first
627 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
628
629 @retval EFI_SUCCESS Succeed.
630 @retval EFI_NOT_FOUND Next PCI root bridge not found.
631 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.
632
633 **/
634 EFI_STATUS
635 EFIAPI
636 GetNextRootBridge (
637 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
638 IN OUT EFI_HANDLE *RootBridgeHandle
639 )
640 {
641 BOOLEAN ReturnNext;
642 LIST_ENTRY *Link;
643 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
644 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
645
646 if (RootBridgeHandle == NULL) {
647 return EFI_INVALID_PARAMETER;
648 }
649
650 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
651 ReturnNext = (BOOLEAN) (*RootBridgeHandle == NULL);
652
653 for (Link = GetFirstNode (&HostBridge->RootBridges)
654 ; !IsNull (&HostBridge->RootBridges, Link)
655 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
656 ) {
657 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
658 if (ReturnNext) {
659 *RootBridgeHandle = RootBridge->Handle;
660 return EFI_SUCCESS;
661 }
662
663 ReturnNext = (BOOLEAN) (*RootBridgeHandle == RootBridge->Handle);
664 }
665
666 if (ReturnNext) {
667 ASSERT (IsNull (&HostBridge->RootBridges, Link));
668 return EFI_NOT_FOUND;
669 } else {
670 return EFI_INVALID_PARAMETER;
671 }
672 }
673
674 /**
675
676 Returns the attributes of a PCI Root Bridge.
677
678 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
679 @param RootBridgeHandle The device handle of the PCI Root Bridge
680 that the caller is interested in.
681 @param Attributes The pointer to attributes of the PCI Root Bridge.
682
683 @retval EFI_SUCCESS Succeed.
684 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or
685 RootBridgeHandle is not an EFI_HANDLE
686 that was returned on a previous call to
687 GetNextRootBridge().
688
689 **/
690 EFI_STATUS
691 EFIAPI
692 GetAttributes (
693 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
694 IN EFI_HANDLE RootBridgeHandle,
695 OUT UINT64 *Attributes
696 )
697 {
698 LIST_ENTRY *Link;
699 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
700 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
701
702 if (Attributes == NULL) {
703 return EFI_INVALID_PARAMETER;
704 }
705
706 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
707 for (Link = GetFirstNode (&HostBridge->RootBridges)
708 ; !IsNull (&HostBridge->RootBridges, Link)
709 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
710 ) {
711 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
712 if (RootBridgeHandle == RootBridge->Handle) {
713 *Attributes = RootBridge->AllocationAttributes;
714 return EFI_SUCCESS;
715 }
716 }
717
718 return EFI_INVALID_PARAMETER;
719 }
720
721 /**
722
723 This is the request from the PCI enumerator to set up
724 the specified PCI Root Bridge for bus enumeration process.
725
726 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
727 @param RootBridgeHandle The PCI Root Bridge to be set up.
728 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.
729
730 @retval EFI_SUCCESS Succeed.
731 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
732 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
733
734 **/
735 EFI_STATUS
736 EFIAPI
737 StartBusEnumeration (
738 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
739 IN EFI_HANDLE RootBridgeHandle,
740 OUT VOID **Configuration
741 )
742 {
743 LIST_ENTRY *Link;
744 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
745 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
746 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
747 EFI_ACPI_END_TAG_DESCRIPTOR *End;
748
749 if (Configuration == NULL) {
750 return EFI_INVALID_PARAMETER;
751 }
752
753 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
754 for (Link = GetFirstNode (&HostBridge->RootBridges)
755 ; !IsNull (&HostBridge->RootBridges, Link)
756 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
757 ) {
758 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
759 if (RootBridgeHandle == RootBridge->Handle) {
760 *Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
761 if (*Configuration == NULL) {
762 return EFI_OUT_OF_RESOURCES;
763 }
764
765 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) *Configuration;
766 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
767 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
768 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
769 Descriptor->GenFlag = 0;
770 Descriptor->SpecificFlag = 0;
771 Descriptor->AddrSpaceGranularity = 0;
772 Descriptor->AddrRangeMin = RootBridge->Bus.Base;
773 Descriptor->AddrRangeMax = 0;
774 Descriptor->AddrTranslationOffset = 0;
775 Descriptor->AddrLen = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;
776
777 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
778 End->Desc = ACPI_END_TAG_DESCRIPTOR;
779 End->Checksum = 0x0;
780
781 return EFI_SUCCESS;
782 }
783 }
784
785 return EFI_INVALID_PARAMETER;
786 }
787
788 /**
789
790 This function programs the PCI Root Bridge hardware so that
791 it decodes the specified PCI bus range.
792
793 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
794 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.
795 @param Configuration The pointer to the PCI bus resource descriptor.
796
797 @retval EFI_SUCCESS Succeed.
798 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
799
800 **/
801 EFI_STATUS
802 EFIAPI
803 SetBusNumbers (
804 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
805 IN EFI_HANDLE RootBridgeHandle,
806 IN VOID *Configuration
807 )
808 {
809 LIST_ENTRY *Link;
810 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
811 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
812 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
813 EFI_ACPI_END_TAG_DESCRIPTOR *End;
814 UINTN BusStart;
815 UINTN BusEnd;
816 UINTN BusLen;
817
818 if (Configuration == NULL) {
819 return EFI_INVALID_PARAMETER;
820 }
821
822 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
823 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
824
825 //
826 // Check the Configuration is valid
827 //
828 if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||
829 (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||
830 (End->Desc != ACPI_END_TAG_DESCRIPTOR)
831 ) {
832 return EFI_INVALID_PARAMETER;
833 }
834
835 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
836 for (Link = GetFirstNode (&HostBridge->RootBridges)
837 ; !IsNull (&HostBridge->RootBridges, Link)
838 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
839 ) {
840 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
841 if (RootBridgeHandle == RootBridge->Handle) {
842 BusStart = (UINTN) Descriptor->AddrRangeMin;
843 BusLen = (UINTN) Descriptor->AddrLen;
844 BusEnd = BusStart + BusLen - 1;
845
846 if (Descriptor->AddrLen == 0) {
847 return EFI_INVALID_PARAMETER;
848 }
849
850 if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||
851 (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)
852 ) {
853 return EFI_INVALID_PARAMETER;
854 }
855 //
856 // Update the Bus Range
857 //
858 RootBridge->ResAllocNode[TypeBus].Base = Descriptor->AddrRangeMin;
859 RootBridge->ResAllocNode[TypeBus].Length = Descriptor->AddrLen;
860 RootBridge->ResAllocNode[TypeBus].Status = ResAllocated;
861 return EFI_SUCCESS;
862 }
863 }
864
865 return EFI_INVALID_PARAMETER;
866 }
867
868 /**
869
870 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
871
872 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
873 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.
874 are being submitted.
875 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
876
877 @retval EFI_SUCCESS Succeed.
878 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
879 **/
880 EFI_STATUS
881 EFIAPI
882 SubmitResources (
883 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
884 IN EFI_HANDLE RootBridgeHandle,
885 IN VOID *Configuration
886 )
887 {
888 LIST_ENTRY *Link;
889 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
890 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
891 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
892 PCI_RESOURCE_TYPE Type;
893
894 //
895 // Check the input parameter: Configuration
896 //
897 if (Configuration == NULL) {
898 return EFI_INVALID_PARAMETER;
899 }
900
901 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
902 for (Link = GetFirstNode (&HostBridge->RootBridges)
903 ; !IsNull (&HostBridge->RootBridges, Link)
904 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
905 ) {
906 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
907 if (RootBridgeHandle == RootBridge->Handle) {
908 DEBUG ((EFI_D_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));
909 //
910 // Check the resource descriptors.
911 // If the Configuration includes one or more invalid resource descriptors, all the resource
912 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
913 //
914 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
915 if (Descriptor->ResType > ACPI_ADDRESS_SPACE_TYPE_BUS) {
916 return EFI_INVALID_PARAMETER;
917 }
918
919 DEBUG ((EFI_D_INFO, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
920 mAcpiAddressSpaceTypeStr[Descriptor->ResType], Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
921 (Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0 ? L" (Prefetchable)" : L""
922 ));
923 DEBUG ((EFI_D_INFO, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor->AddrLen, Descriptor->AddrRangeMax));
924 switch (Descriptor->ResType) {
925 case ACPI_ADDRESS_SPACE_TYPE_MEM:
926 if (Descriptor->AddrSpaceGranularity != 32 && Descriptor->AddrSpaceGranularity != 64) {
927 return EFI_INVALID_PARAMETER;
928 }
929 if (Descriptor->AddrSpaceGranularity == 32 && Descriptor->AddrLen >= SIZE_4GB) {
930 return EFI_INVALID_PARAMETER;
931 }
932 //
933 // If the PCI root bridge does not support separate windows for nonprefetchable and
934 // prefetchable memory, then the PCI bus driver needs to include requests for
935 // prefetchable memory in the nonprefetchable memory pool.
936 //
937 if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&
938 ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)
939 ) {
940 return EFI_INVALID_PARAMETER;
941 }
942 case ACPI_ADDRESS_SPACE_TYPE_IO:
943 //
944 // Check aligment, it should be of the form 2^n-1
945 //
946 if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {
947 return EFI_INVALID_PARAMETER;
948 }
949 break;
950 default:
951 ASSERT (FALSE);
952 break;
953 }
954 }
955 if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {
956 return EFI_INVALID_PARAMETER;
957 }
958
959 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
960 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
961 if (Descriptor->AddrSpaceGranularity == 32) {
962 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {
963 Type = TypePMem32;
964 } else {
965 Type = TypeMem32;
966 }
967 } else {
968 ASSERT (Descriptor->AddrSpaceGranularity == 64);
969 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {
970 Type = TypePMem64;
971 } else {
972 Type = TypeMem64;
973 }
974 }
975 } else {
976 ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);
977 Type = TypeIo;
978 }
979 RootBridge->ResAllocNode[Type].Length = Descriptor->AddrLen;
980 RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;
981 RootBridge->ResAllocNode[Type].Status = ResSubmitted;
982 }
983 RootBridge->ResourceSubmitted = TRUE;
984 return EFI_SUCCESS;
985 }
986 }
987
988 return EFI_INVALID_PARAMETER;
989 }
990
991 /**
992
993 This function returns the proposed resource settings for the specified
994 PCI Root Bridge.
995
996 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
997 @param RootBridgeHandle The PCI Root Bridge handle.
998 @param Configuration The pointer to the pointer to the PCI I/O
999 and memory resource descriptor.
1000
1001 @retval EFI_SUCCESS Succeed.
1002 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1003 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1004
1005 **/
1006 EFI_STATUS
1007 EFIAPI
1008 GetProposedResources (
1009 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1010 IN EFI_HANDLE RootBridgeHandle,
1011 OUT VOID **Configuration
1012 )
1013 {
1014 LIST_ENTRY *Link;
1015 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1016 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1017 UINTN Index;
1018 UINTN Number;
1019 VOID *Buffer;
1020 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
1021 EFI_ACPI_END_TAG_DESCRIPTOR *End;
1022 UINT64 ResStatus;
1023
1024 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1025 for (Link = GetFirstNode (&HostBridge->RootBridges)
1026 ; !IsNull (&HostBridge->RootBridges, Link)
1027 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1028 ) {
1029 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1030 if (RootBridgeHandle == RootBridge->Handle) {
1031 for (Index = 0, Number = 0; Index < TypeBus; Index++) {
1032 if (RootBridge->ResAllocNode[Index].Status != ResNone) {
1033 Number++;
1034 }
1035 }
1036
1037 Buffer = AllocateZeroPool (Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1038 if (Buffer == NULL) {
1039 return EFI_OUT_OF_RESOURCES;
1040 }
1041
1042 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Buffer;
1043 for (Index = 0; Index < TypeBus; Index++) {
1044 ResStatus = RootBridge->ResAllocNode[Index].Status;
1045 if (ResStatus != ResNone) {
1046 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1047 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;
1048 Descriptor->GenFlag = 0;
1049 Descriptor->AddrRangeMin = RootBridge->ResAllocNode[Index].Base;
1050 Descriptor->AddrRangeMax = 0;
1051 Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;
1052 Descriptor->AddrLen = RootBridge->ResAllocNode[Index].Length;
1053
1054 switch (Index) {
1055
1056 case TypeIo:
1057 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1058 break;
1059
1060 case TypePMem32:
1061 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1062 case TypeMem32:
1063 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1064 Descriptor->AddrSpaceGranularity = 32;
1065 break;
1066
1067 case TypePMem64:
1068 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1069 case TypeMem64:
1070 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1071 Descriptor->AddrSpaceGranularity = 64;
1072 break;
1073 }
1074
1075 Descriptor++;
1076 }
1077 }
1078 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
1079 End->Desc = ACPI_END_TAG_DESCRIPTOR;
1080 End->Checksum = 0;
1081
1082 *Configuration = Buffer;
1083
1084 return EFI_SUCCESS;
1085 }
1086 }
1087
1088 return EFI_INVALID_PARAMETER;
1089 }
1090
1091 /**
1092
1093 This function is called for all the PCI controllers that the PCI
1094 bus driver finds. Can be used to Preprogram the controller.
1095
1096 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1097 @param RootBridgeHandle The PCI Root Bridge handle.
1098 @param PciAddress Address of the controller on the PCI bus.
1099 @param Phase The Phase during resource allocation.
1100
1101 @retval EFI_SUCCESS Succeed.
1102 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1103
1104 **/
1105 EFI_STATUS
1106 EFIAPI
1107 PreprocessController (
1108 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1109 IN EFI_HANDLE RootBridgeHandle,
1110 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
1111 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1112 )
1113 {
1114 LIST_ENTRY *Link;
1115 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1116 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1117
1118 if ((UINT32) Phase > EfiPciBeforeResourceCollection) {
1119 return EFI_INVALID_PARAMETER;
1120 }
1121
1122 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1123 for (Link = GetFirstNode (&HostBridge->RootBridges)
1124 ; !IsNull (&HostBridge->RootBridges, Link)
1125 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1126 ) {
1127 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1128 if (RootBridgeHandle == RootBridge->Handle) {
1129 return EFI_SUCCESS;
1130 }
1131 }
1132
1133 return EFI_INVALID_PARAMETER;
1134 }