]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciHostBridgeDxe / PciRootBridgeIo.c
1 /** @file
2
3 PCI Root Bridge Io Protocol code.
4
5 Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "PciHostBridge.h"
11 #include "PciRootBridge.h"
12 #include "PciHostResource.h"
13
14 #define NO_MAPPING (VOID *) (UINTN) -1
15
16 #define RESOURCE_VALID(Resource) ((Resource)->Base <= (Resource)->Limit)
17
18 //
19 // Lookup table for increment values based on transfer widths
20 //
21 UINT8 mInStride[] = {
22 1, // EfiPciWidthUint8
23 2, // EfiPciWidthUint16
24 4, // EfiPciWidthUint32
25 8, // EfiPciWidthUint64
26 0, // EfiPciWidthFifoUint8
27 0, // EfiPciWidthFifoUint16
28 0, // EfiPciWidthFifoUint32
29 0, // EfiPciWidthFifoUint64
30 1, // EfiPciWidthFillUint8
31 2, // EfiPciWidthFillUint16
32 4, // EfiPciWidthFillUint32
33 8 // EfiPciWidthFillUint64
34 };
35
36 //
37 // Lookup table for increment values based on transfer widths
38 //
39 UINT8 mOutStride[] = {
40 1, // EfiPciWidthUint8
41 2, // EfiPciWidthUint16
42 4, // EfiPciWidthUint32
43 8, // EfiPciWidthUint64
44 1, // EfiPciWidthFifoUint8
45 2, // EfiPciWidthFifoUint16
46 4, // EfiPciWidthFifoUint32
47 8, // EfiPciWidthFifoUint64
48 0, // EfiPciWidthFillUint8
49 0, // EfiPciWidthFillUint16
50 0, // EfiPciWidthFillUint32
51 0 // EfiPciWidthFillUint64
52 };
53
54 /**
55 Construct the Pci Root Bridge instance.
56
57 @param Bridge The root bridge instance.
58
59 @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
60 or NULL if creation fails.
61 **/
62 PCI_ROOT_BRIDGE_INSTANCE *
63 CreateRootBridge (
64 IN PCI_ROOT_BRIDGE *Bridge
65 )
66 {
67 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
68 PCI_RESOURCE_TYPE Index;
69 CHAR16 *DevicePathStr;
70 PCI_ROOT_BRIDGE_APERTURE *Aperture;
71
72 DevicePathStr = NULL;
73
74 DEBUG ((EFI_D_INFO, "RootBridge: "));
75 DEBUG ((EFI_D_INFO, "%s\n", DevicePathStr = ConvertDevicePathToText (Bridge->DevicePath, FALSE, FALSE)));
76 DEBUG ((EFI_D_INFO, " Support/Attr: %lx / %lx\n", Bridge->Supports, Bridge->Attributes));
77 DEBUG ((EFI_D_INFO, " DmaAbove4G: %s\n", Bridge->DmaAbove4G ? L"Yes" : L"No"));
78 DEBUG ((EFI_D_INFO, "NoExtConfSpace: %s\n", Bridge->NoExtendedConfigSpace ? L"Yes" : L"No"));
79 DEBUG ((EFI_D_INFO, " AllocAttr: %lx (%s%s)\n", Bridge->AllocationAttributes,
80 (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 ? L"CombineMemPMem " : L"",
81 (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0 ? L"Mem64Decode" : L""
82 ));
83 DEBUG ((
84 EFI_D_INFO, " Bus: %lx - %lx Translation=%lx\n",
85 Bridge->Bus.Base, Bridge->Bus.Limit, Bridge->Bus.Translation
86 ));
87 //
88 // Translation for bus is not supported.
89 //
90 ASSERT (Bridge->Bus.Translation == 0);
91 if (Bridge->Bus.Translation != 0) {
92 return NULL;
93 }
94
95 DEBUG ((
96 DEBUG_INFO, " Io: %lx - %lx Translation=%lx\n",
97 Bridge->Io.Base, Bridge->Io.Limit, Bridge->Io.Translation
98 ));
99 DEBUG ((
100 DEBUG_INFO, " Mem: %lx - %lx Translation=%lx\n",
101 Bridge->Mem.Base, Bridge->Mem.Limit, Bridge->Mem.Translation
102 ));
103 DEBUG ((
104 DEBUG_INFO, " MemAbove4G: %lx - %lx Translation=%lx\n",
105 Bridge->MemAbove4G.Base, Bridge->MemAbove4G.Limit, Bridge->MemAbove4G.Translation
106 ));
107 DEBUG ((
108 DEBUG_INFO, " PMem: %lx - %lx Translation=%lx\n",
109 Bridge->PMem.Base, Bridge->PMem.Limit, Bridge->PMem.Translation
110 ));
111 DEBUG ((
112 DEBUG_INFO, " PMemAbove4G: %lx - %lx Translation=%lx\n",
113 Bridge->PMemAbove4G.Base, Bridge->PMemAbove4G.Limit, Bridge->PMemAbove4G.Translation
114 ));
115
116 //
117 // Make sure Mem and MemAbove4G apertures are valid
118 //
119 if (RESOURCE_VALID (&Bridge->Mem)) {
120 ASSERT (Bridge->Mem.Limit < SIZE_4GB);
121 if (Bridge->Mem.Limit >= SIZE_4GB) {
122 return NULL;
123 }
124 }
125 if (RESOURCE_VALID (&Bridge->MemAbove4G)) {
126 ASSERT (Bridge->MemAbove4G.Base >= SIZE_4GB);
127 if (Bridge->MemAbove4G.Base < SIZE_4GB) {
128 return NULL;
129 }
130 }
131 if (RESOURCE_VALID (&Bridge->PMem)) {
132 ASSERT (Bridge->PMem.Limit < SIZE_4GB);
133 if (Bridge->PMem.Limit >= SIZE_4GB) {
134 return NULL;
135 }
136 }
137 if (RESOURCE_VALID (&Bridge->PMemAbove4G)) {
138 ASSERT (Bridge->PMemAbove4G.Base >= SIZE_4GB);
139 if (Bridge->PMemAbove4G.Base < SIZE_4GB) {
140 return NULL;
141 }
142 }
143
144 //
145 // Ignore AllocationAttributes when resources were already assigned.
146 //
147 if (!Bridge->ResourceAssigned) {
148 if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {
149 //
150 // If this bit is set, then the PCI Root Bridge does not
151 // support separate windows for Non-prefetchable and Prefetchable
152 // memory.
153 //
154 ASSERT (!RESOURCE_VALID (&Bridge->PMem));
155 ASSERT (!RESOURCE_VALID (&Bridge->PMemAbove4G));
156 if (RESOURCE_VALID (&Bridge->PMem) || RESOURCE_VALID (&Bridge->PMemAbove4G)) {
157 return NULL;
158 }
159 }
160
161 if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) == 0) {
162 //
163 // If this bit is not set, then the PCI Root Bridge does not support
164 // 64 bit memory windows.
165 //
166 ASSERT (!RESOURCE_VALID (&Bridge->MemAbove4G));
167 ASSERT (!RESOURCE_VALID (&Bridge->PMemAbove4G));
168 if (RESOURCE_VALID (&Bridge->MemAbove4G) || RESOURCE_VALID (&Bridge->PMemAbove4G)) {
169 return NULL;
170 }
171 }
172 }
173
174 RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));
175 ASSERT (RootBridge != NULL);
176
177 RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
178 RootBridge->Supports = Bridge->Supports;
179 RootBridge->Attributes = Bridge->Attributes;
180 RootBridge->DmaAbove4G = Bridge->DmaAbove4G;
181 RootBridge->NoExtendedConfigSpace = Bridge->NoExtendedConfigSpace;
182 RootBridge->AllocationAttributes = Bridge->AllocationAttributes;
183 RootBridge->DevicePath = DuplicateDevicePath (Bridge->DevicePath);
184 RootBridge->DevicePathStr = DevicePathStr;
185 RootBridge->ConfigBuffer = AllocatePool (
186 TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
187 );
188 ASSERT (RootBridge->ConfigBuffer != NULL);
189 InitializeListHead (&RootBridge->Maps);
190
191 CopyMem (&RootBridge->Bus, &Bridge->Bus, sizeof (PCI_ROOT_BRIDGE_APERTURE));
192 CopyMem (&RootBridge->Io, &Bridge->Io, sizeof (PCI_ROOT_BRIDGE_APERTURE));
193 CopyMem (&RootBridge->Mem, &Bridge->Mem, sizeof (PCI_ROOT_BRIDGE_APERTURE));
194 CopyMem (&RootBridge->MemAbove4G, &Bridge->MemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));
195 CopyMem (&RootBridge->PMem, &Bridge->PMem, sizeof (PCI_ROOT_BRIDGE_APERTURE));
196 CopyMem (&RootBridge->PMemAbove4G, &Bridge->PMemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));
197
198 for (Index = TypeIo; Index < TypeMax; Index++) {
199 switch (Index) {
200 case TypeBus:
201 Aperture = &RootBridge->Bus;
202 break;
203 case TypeIo:
204 Aperture = &RootBridge->Io;
205 break;
206 case TypeMem32:
207 Aperture = &RootBridge->Mem;
208 break;
209 case TypeMem64:
210 Aperture = &RootBridge->MemAbove4G;
211 break;
212 case TypePMem32:
213 Aperture = &RootBridge->PMem;
214 break;
215 case TypePMem64:
216 Aperture = &RootBridge->PMemAbove4G;
217 break;
218 default:
219 ASSERT (FALSE);
220 Aperture = NULL;
221 break;
222 }
223 RootBridge->ResAllocNode[Index].Type = Index;
224 if (Bridge->ResourceAssigned && (Aperture->Limit >= Aperture->Base)) {
225 //
226 // Base in ResAllocNode is a host address, while Base in Aperture is a
227 // device address.
228 //
229 RootBridge->ResAllocNode[Index].Base = TO_HOST_ADDRESS (Aperture->Base,
230 Aperture->Translation);
231 RootBridge->ResAllocNode[Index].Length = Aperture->Limit - Aperture->Base + 1;
232 RootBridge->ResAllocNode[Index].Status = ResAllocated;
233 } else {
234 RootBridge->ResAllocNode[Index].Base = 0;
235 RootBridge->ResAllocNode[Index].Length = 0;
236 RootBridge->ResAllocNode[Index].Status = ResNone;
237 }
238 }
239
240 RootBridge->RootBridgeIo.SegmentNumber = Bridge->Segment;
241 RootBridge->RootBridgeIo.PollMem = RootBridgeIoPollMem;
242 RootBridge->RootBridgeIo.PollIo = RootBridgeIoPollIo;
243 RootBridge->RootBridgeIo.Mem.Read = RootBridgeIoMemRead;
244 RootBridge->RootBridgeIo.Mem.Write = RootBridgeIoMemWrite;
245 RootBridge->RootBridgeIo.Io.Read = RootBridgeIoIoRead;
246 RootBridge->RootBridgeIo.Io.Write = RootBridgeIoIoWrite;
247 RootBridge->RootBridgeIo.CopyMem = RootBridgeIoCopyMem;
248 RootBridge->RootBridgeIo.Pci.Read = RootBridgeIoPciRead;
249 RootBridge->RootBridgeIo.Pci.Write = RootBridgeIoPciWrite;
250 RootBridge->RootBridgeIo.Map = RootBridgeIoMap;
251 RootBridge->RootBridgeIo.Unmap = RootBridgeIoUnmap;
252 RootBridge->RootBridgeIo.AllocateBuffer = RootBridgeIoAllocateBuffer;
253 RootBridge->RootBridgeIo.FreeBuffer = RootBridgeIoFreeBuffer;
254 RootBridge->RootBridgeIo.Flush = RootBridgeIoFlush;
255 RootBridge->RootBridgeIo.GetAttributes = RootBridgeIoGetAttributes;
256 RootBridge->RootBridgeIo.SetAttributes = RootBridgeIoSetAttributes;
257 RootBridge->RootBridgeIo.Configuration = RootBridgeIoConfiguration;
258
259 return RootBridge;
260 }
261
262 /**
263 Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.
264
265 The I/O operations are carried out exactly as requested. The caller is
266 responsible for satisfying any alignment and I/O width restrictions that a PI
267 System on a platform might require. For example on some platforms, width
268 requests of EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other
269 hand, will be handled by the driver.
270
271 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
272
273 @param[in] OperationType I/O operation type: IO/MMIO/PCI.
274
275 @param[in] Width Signifies the width of the I/O or Memory operation.
276
277 @param[in] Address The base address of the I/O operation.
278
279 @param[in] Count The number of I/O operations to perform. The number
280 of bytes moved is Width size * Count, starting at
281 Address.
282
283 @param[in] Buffer For read operations, the destination buffer to
284 store the results. For write operations, the source
285 buffer from which to write data.
286
287 @retval EFI_SUCCESS The parameters for this request pass the
288 checks.
289
290 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
291
292 @retval EFI_INVALID_PARAMETER Buffer is NULL.
293
294 @retval EFI_INVALID_PARAMETER Address or Count is invalid.
295
296 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
297
298 @retval EFI_UNSUPPORTED The address range specified by Address, Width,
299 and Count is not valid for this PI system.
300 **/
301 EFI_STATUS
302 RootBridgeIoCheckParameter (
303 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
304 IN OPERATION_TYPE OperationType,
305 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
306 IN UINT64 Address,
307 IN UINTN Count,
308 IN VOID *Buffer
309 )
310 {
311 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
312 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciRbAddr;
313 UINT64 Base;
314 UINT64 Limit;
315 UINT32 Size;
316 UINT64 Length;
317
318 //
319 // Check to see if Buffer is NULL
320 //
321 if (Buffer == NULL) {
322 return EFI_INVALID_PARAMETER;
323 }
324
325 //
326 // Check to see if Width is in the valid range
327 //
328 if ((UINT32) Width >= EfiPciWidthMaximum) {
329 return EFI_INVALID_PARAMETER;
330 }
331
332 //
333 // For FIFO type, the device address won't increase during the access,
334 // so treat Count as 1
335 //
336 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
337 Count = 1;
338 }
339
340 Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
341 Size = 1 << Width;
342
343 //
344 // Make sure (Count * Size) doesn't exceed MAX_UINT64
345 //
346 if (Count > DivU64x32 (MAX_UINT64, Size)) {
347 return EFI_INVALID_PARAMETER;
348 }
349
350 //
351 // Check to see if Address is aligned
352 //
353 if ((Address & (Size - 1)) != 0) {
354 return EFI_UNSUPPORTED;
355 }
356
357 //
358 // Make sure (Address + Count * Size) doesn't exceed MAX_UINT64
359 //
360 Length = MultU64x32 (Count, Size);
361 if (Address > MAX_UINT64 - Length) {
362 return EFI_INVALID_PARAMETER;
363 }
364
365 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
366
367 //
368 // Check to see if any address associated with this transfer exceeds the
369 // maximum allowed address. The maximum address implied by the parameters
370 // passed in is Address + Size * Count. If the following condition is met,
371 // then the transfer is not supported.
372 //
373 // Address + Size * Count > Limit + 1
374 //
375 // Since Limit can be the maximum integer value supported by the CPU and
376 // Count can also be the maximum integer value supported by the CPU, this
377 // range check must be adjusted to avoid all oveflow conditions.
378 //
379 if (OperationType == IoOperation) {
380 //
381 // Allow Legacy IO access
382 //
383 if (Address + Length <= 0x1000) {
384 if ((RootBridge->Attributes & (
385 EFI_PCI_ATTRIBUTE_ISA_IO | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_ATTRIBUTE_VGA_IO |
386 EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
387 EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_ATTRIBUTE_VGA_IO_16)) != 0) {
388 return EFI_SUCCESS;
389 }
390 }
391 Base = RootBridge->Io.Base;
392 Limit = RootBridge->Io.Limit;
393 } else if (OperationType == MemOperation) {
394 //
395 // Allow Legacy MMIO access
396 //
397 if ((Address >= 0xA0000) && (Address + Length) <= 0xC0000) {
398 if ((RootBridge->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) != 0) {
399 return EFI_SUCCESS;
400 }
401 }
402 //
403 // By comparing the Address against Limit we know which range to be used
404 // for checking
405 //
406 if ((Address >= RootBridge->Mem.Base) && (Address + Length <= RootBridge->Mem.Limit + 1)) {
407 Base = RootBridge->Mem.Base;
408 Limit = RootBridge->Mem.Limit;
409 } else if ((Address >= RootBridge->PMem.Base) && (Address + Length <= RootBridge->PMem.Limit + 1)) {
410 Base = RootBridge->PMem.Base;
411 Limit = RootBridge->PMem.Limit;
412 } else if ((Address >= RootBridge->MemAbove4G.Base) && (Address + Length <= RootBridge->MemAbove4G.Limit + 1)) {
413 Base = RootBridge->MemAbove4G.Base;
414 Limit = RootBridge->MemAbove4G.Limit;
415 } else {
416 Base = RootBridge->PMemAbove4G.Base;
417 Limit = RootBridge->PMemAbove4G.Limit;
418 }
419 } else {
420 PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;
421 if (PciRbAddr->Bus < RootBridge->Bus.Base ||
422 PciRbAddr->Bus > RootBridge->Bus.Limit) {
423 return EFI_INVALID_PARAMETER;
424 }
425
426 if (PciRbAddr->Device > PCI_MAX_DEVICE ||
427 PciRbAddr->Function > PCI_MAX_FUNC) {
428 return EFI_INVALID_PARAMETER;
429 }
430
431 if (PciRbAddr->ExtendedRegister != 0) {
432 Address = PciRbAddr->ExtendedRegister;
433 } else {
434 Address = PciRbAddr->Register;
435 }
436 Base = 0;
437 Limit = RootBridge->NoExtendedConfigSpace ? 0xFF : 0xFFF;
438 }
439
440 if (Address < Base) {
441 return EFI_INVALID_PARAMETER;
442 }
443
444 if (Address + Length > Limit + 1) {
445 return EFI_INVALID_PARAMETER;
446 }
447
448 return EFI_SUCCESS;
449 }
450
451 /**
452 Use address to match apertures of memory type and then get the corresponding
453 translation.
454
455 @param RootBridge The root bridge instance.
456 @param Address The address used to match aperture.
457 @param Translation Pointer containing the output translation.
458
459 @return EFI_SUCCESS Get translation successfully.
460 @return EFI_INVALID_PARAMETER No matched memory aperture; the input Address
461 must be invalid.
462 **/
463 EFI_STATUS
464 RootBridgeIoGetMemTranslationByAddress (
465 IN PCI_ROOT_BRIDGE_INSTANCE *RootBridge,
466 IN UINT64 Address,
467 IN OUT UINT64 *Translation
468 )
469 {
470 if (Address >= RootBridge->Mem.Base && Address <= RootBridge->Mem.Limit) {
471 *Translation = RootBridge->Mem.Translation;
472 } else if (Address >= RootBridge->PMem.Base && Address <= RootBridge->PMem.Limit) {
473 *Translation = RootBridge->PMem.Translation;
474 } else if (Address >= RootBridge->MemAbove4G.Base && Address <= RootBridge->MemAbove4G.Limit) {
475 *Translation = RootBridge->MemAbove4G.Translation;
476 } else if (Address >= RootBridge->PMemAbove4G.Base && Address <= RootBridge->PMemAbove4G.Limit) {
477 *Translation = RootBridge->PMemAbove4G.Translation;
478 } else {
479 return EFI_INVALID_PARAMETER;
480 }
481
482 return EFI_SUCCESS;
483 }
484
485 /**
486 Return the result of (Multiplicand * Multiplier / Divisor).
487
488 @param Multiplicand A 64-bit unsigned value.
489 @param Multiplier A 64-bit unsigned value.
490 @param Divisor A 32-bit unsigned value.
491 @param Remainder A pointer to a 32-bit unsigned value. This parameter is
492 optional and may be NULL.
493
494 @return Multiplicand * Multiplier / Divisor.
495 **/
496 UINT64
497 MultThenDivU64x64x32 (
498 IN UINT64 Multiplicand,
499 IN UINT64 Multiplier,
500 IN UINT32 Divisor,
501 OUT UINT32 *Remainder OPTIONAL
502 )
503 {
504 UINT64 Uint64;
505 UINT32 LocalRemainder;
506 UINT32 Uint32;
507 if (Multiplicand > DivU64x64Remainder (MAX_UINT64, Multiplier, NULL)) {
508 //
509 // Make sure Multiplicand is the bigger one.
510 //
511 if (Multiplicand < Multiplier) {
512 Uint64 = Multiplicand;
513 Multiplicand = Multiplier;
514 Multiplier = Uint64;
515 }
516 //
517 // Because Multiplicand * Multiplier overflows,
518 // Multiplicand * Multiplier / Divisor
519 // = (2 * Multiplicand' + 1) * Multiplier / Divisor
520 // = 2 * (Multiplicand' * Multiplier / Divisor) + Multiplier / Divisor
521 //
522 Uint64 = MultThenDivU64x64x32 (RShiftU64 (Multiplicand, 1), Multiplier, Divisor, &LocalRemainder);
523 Uint64 = LShiftU64 (Uint64, 1);
524 Uint32 = 0;
525 if ((Multiplicand & 0x1) == 1) {
526 Uint64 += DivU64x32Remainder (Multiplier, Divisor, &Uint32);
527 }
528 return Uint64 + DivU64x32Remainder (Uint32 + LShiftU64 (LocalRemainder, 1), Divisor, Remainder);
529 } else {
530 return DivU64x32Remainder (MultU64x64 (Multiplicand, Multiplier), Divisor, Remainder);
531 }
532 }
533
534 /**
535 Return the elapsed tick count from CurrentTick.
536
537 @param CurrentTick On input, the previous tick count.
538 On output, the current tick count.
539 @param StartTick The value the performance counter starts with when it
540 rolls over.
541 @param EndTick The value that the performance counter ends with before
542 it rolls over.
543
544 @return The elapsed tick count from CurrentTick.
545 **/
546 UINT64
547 GetElapsedTick (
548 UINT64 *CurrentTick,
549 UINT64 StartTick,
550 UINT64 EndTick
551 )
552 {
553 UINT64 PreviousTick;
554
555 PreviousTick = *CurrentTick;
556 *CurrentTick = GetPerformanceCounter();
557 if (StartTick < EndTick) {
558 return *CurrentTick - PreviousTick;
559 } else {
560 return PreviousTick - *CurrentTick;
561 }
562 }
563
564 /**
565 Polls an address in memory mapped I/O space until an exit condition is met,
566 or a timeout occurs.
567
568 This function provides a standard way to poll a PCI memory location. A PCI
569 memory read operation is performed at the PCI memory address specified by
570 Address for the width specified by Width. The result of this PCI memory read
571 operation is stored in Result. This PCI memory read operation is repeated
572 until either a timeout of Delay 100 ns units has expired, or (Result & Mask)
573 is equal to Value.
574
575 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
576 @param[in] Width Signifies the width of the memory operations.
577 @param[in] Address The base address of the memory operations. The caller
578 is responsible for aligning Address if required.
579 @param[in] Mask Mask used for the polling criteria. Bytes above Width
580 in Mask are ignored. The bits in the bytes below Width
581 which are zero in Mask are ignored when polling the
582 memory address.
583 @param[in] Value The comparison value used for the polling exit
584 criteria.
585 @param[in] Delay The number of 100 ns units to poll. Note that timer
586 available may be of poorer granularity.
587 @param[out] Result Pointer to the last value read from the memory
588 location.
589
590 @retval EFI_SUCCESS The last data returned from the access matched
591 the poll exit criteria.
592 @retval EFI_INVALID_PARAMETER Width is invalid.
593 @retval EFI_INVALID_PARAMETER Result is NULL.
594 @retval EFI_TIMEOUT Delay expired before a match occurred.
595 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
596 lack of resources.
597 **/
598 EFI_STATUS
599 EFIAPI
600 RootBridgeIoPollMem (
601 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
602 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
603 IN UINT64 Address,
604 IN UINT64 Mask,
605 IN UINT64 Value,
606 IN UINT64 Delay,
607 OUT UINT64 *Result
608 )
609 {
610 EFI_STATUS Status;
611 UINT64 NumberOfTicks;
612 UINT32 Remainder;
613 UINT64 StartTick;
614 UINT64 EndTick;
615 UINT64 CurrentTick;
616 UINT64 ElapsedTick;
617 UINT64 Frequency;
618
619 if (Result == NULL) {
620 return EFI_INVALID_PARAMETER;
621 }
622
623 if ((UINT32)Width > EfiPciWidthUint64) {
624 return EFI_INVALID_PARAMETER;
625 }
626
627 //
628 // No matter what, always do a single poll.
629 //
630 Status = This->Mem.Read (This, Width, Address, 1, Result);
631 if (EFI_ERROR (Status)) {
632 return Status;
633 }
634
635 if ((*Result & Mask) == Value) {
636 return EFI_SUCCESS;
637 }
638
639 if (Delay == 0) {
640 return EFI_SUCCESS;
641
642 } else {
643 //
644 // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)
645 //
646 Frequency = GetPerformanceCounterProperties (&StartTick, &EndTick);
647 NumberOfTicks = MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_TIMER_PERIOD_SECONDS(1), &Remainder);
648 if (Remainder >= (UINTN)EFI_TIMER_PERIOD_SECONDS(1) / 2) {
649 NumberOfTicks++;
650 }
651 for ( ElapsedTick = 0, CurrentTick = GetPerformanceCounter()
652 ; ElapsedTick <= NumberOfTicks
653 ; ElapsedTick += GetElapsedTick (&CurrentTick, StartTick, EndTick)
654 ) {
655 Status = This->Mem.Read (This, Width, Address, 1, Result);
656 if (EFI_ERROR (Status)) {
657 return Status;
658 }
659
660 if ((*Result & Mask) == Value) {
661 return EFI_SUCCESS;
662 }
663 }
664 }
665 return EFI_TIMEOUT;
666 }
667
668 /**
669 Reads from the I/O space of a PCI Root Bridge. Returns when either the
670 polling exit criteria is satisfied or after a defined duration.
671
672 This function provides a standard way to poll a PCI I/O location. A PCI I/O
673 read operation is performed at the PCI I/O address specified by Address for
674 the width specified by Width.
675 The result of this PCI I/O read operation is stored in Result. This PCI I/O
676 read operation is repeated until either a timeout of Delay 100 ns units has
677 expired, or (Result & Mask) is equal to Value.
678
679 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
680 @param[in] Width Signifies the width of the I/O operations.
681 @param[in] Address The base address of the I/O operations. The caller is
682 responsible for aligning Address if required.
683 @param[in] Mask Mask used for the polling criteria. Bytes above Width in
684 Mask are ignored. The bits in the bytes below Width
685 which are zero in Mask are ignored when polling the I/O
686 address.
687 @param[in] Value The comparison value used for the polling exit criteria.
688 @param[in] Delay The number of 100 ns units to poll. Note that timer
689 available may be of poorer granularity.
690 @param[out] Result Pointer to the last value read from the memory location.
691
692 @retval EFI_SUCCESS The last data returned from the access matched
693 the poll exit criteria.
694 @retval EFI_INVALID_PARAMETER Width is invalid.
695 @retval EFI_INVALID_PARAMETER Result is NULL.
696 @retval EFI_TIMEOUT Delay expired before a match occurred.
697 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
698 lack of resources.
699 **/
700 EFI_STATUS
701 EFIAPI
702 RootBridgeIoPollIo (
703 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
704 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
705 IN UINT64 Address,
706 IN UINT64 Mask,
707 IN UINT64 Value,
708 IN UINT64 Delay,
709 OUT UINT64 *Result
710 )
711 {
712 EFI_STATUS Status;
713 UINT64 NumberOfTicks;
714 UINT32 Remainder;
715 UINT64 StartTick;
716 UINT64 EndTick;
717 UINT64 CurrentTick;
718 UINT64 ElapsedTick;
719 UINT64 Frequency;
720
721 //
722 // No matter what, always do a single poll.
723 //
724
725 if (Result == NULL) {
726 return EFI_INVALID_PARAMETER;
727 }
728
729 if ((UINT32)Width > EfiPciWidthUint64) {
730 return EFI_INVALID_PARAMETER;
731 }
732
733 Status = This->Io.Read (This, Width, Address, 1, Result);
734 if (EFI_ERROR (Status)) {
735 return Status;
736 }
737 if ((*Result & Mask) == Value) {
738 return EFI_SUCCESS;
739 }
740
741 if (Delay == 0) {
742 return EFI_SUCCESS;
743
744 } else {
745 //
746 // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)
747 //
748 Frequency = GetPerformanceCounterProperties (&StartTick, &EndTick);
749 NumberOfTicks = MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_TIMER_PERIOD_SECONDS(1), &Remainder);
750 if (Remainder >= (UINTN)EFI_TIMER_PERIOD_SECONDS(1) / 2) {
751 NumberOfTicks++;
752 }
753 for ( ElapsedTick = 0, CurrentTick = GetPerformanceCounter()
754 ; ElapsedTick <= NumberOfTicks
755 ; ElapsedTick += GetElapsedTick (&CurrentTick, StartTick, EndTick)
756 ) {
757 Status = This->Io.Read (This, Width, Address, 1, Result);
758 if (EFI_ERROR (Status)) {
759 return Status;
760 }
761
762 if ((*Result & Mask) == Value) {
763 return EFI_SUCCESS;
764 }
765 }
766 }
767 return EFI_TIMEOUT;
768 }
769
770 /**
771 Enables a PCI driver to access PCI controller registers in the PCI root
772 bridge memory space.
773
774 The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
775 controller registers in the PCI root bridge memory space.
776 The memory operations are carried out exactly as requested. The caller is
777 responsible for satisfying any alignment and memory width restrictions that a
778 PCI Root Bridge on a platform might require.
779
780 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
781 @param[in] Width Signifies the width of the memory operation.
782 @param[in] Address The base address of the memory operation. The caller
783 is responsible for aligning the Address if required.
784 @param[in] Count The number of memory operations to perform. Bytes
785 moved is Width size * Count, starting at Address.
786 @param[out] Buffer For read operations, the destination buffer to store
787 the results. For write operations, the source buffer
788 to write data from.
789
790 @retval EFI_SUCCESS The data was read from or written to the PCI
791 root bridge.
792 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
793 @retval EFI_INVALID_PARAMETER Buffer is NULL.
794 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
795 lack of resources.
796 **/
797 EFI_STATUS
798 EFIAPI
799 RootBridgeIoMemRead (
800 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
801 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
802 IN UINT64 Address,
803 IN UINTN Count,
804 OUT VOID *Buffer
805 )
806 {
807 EFI_STATUS Status;
808 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
809 UINT64 Translation;
810
811 Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,
812 Count, Buffer);
813 if (EFI_ERROR (Status)) {
814 return Status;
815 }
816
817 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
818 Status = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);
819 if (EFI_ERROR (Status)) {
820 return Status;
821 }
822
823 // Address passed to CpuIo->Mem.Read needs to be a host address instead of
824 // device address.
825 return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
826 TO_HOST_ADDRESS (Address, Translation), Count, Buffer);
827 }
828
829 /**
830 Enables a PCI driver to access PCI controller registers in the PCI root
831 bridge memory space.
832
833 The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
834 controller registers in the PCI root bridge memory space.
835 The memory operations are carried out exactly as requested. The caller is
836 responsible for satisfying any alignment and memory width restrictions that a
837 PCI Root Bridge on a platform might require.
838
839 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
840 @param[in] Width Signifies the width of the memory operation.
841 @param[in] Address The base address of the memory operation. The caller
842 is responsible for aligning the Address if required.
843 @param[in] Count The number of memory operations to perform. Bytes
844 moved is Width size * Count, starting at Address.
845 @param[in] Buffer For read operations, the destination buffer to store
846 the results. For write operations, the source buffer
847 to write data from.
848
849 @retval EFI_SUCCESS The data was read from or written to the PCI
850 root bridge.
851 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
852 @retval EFI_INVALID_PARAMETER Buffer is NULL.
853 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
854 lack of resources.
855 **/
856 EFI_STATUS
857 EFIAPI
858 RootBridgeIoMemWrite (
859 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
860 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
861 IN UINT64 Address,
862 IN UINTN Count,
863 IN VOID *Buffer
864 )
865 {
866 EFI_STATUS Status;
867 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
868 UINT64 Translation;
869
870 Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,
871 Count, Buffer);
872 if (EFI_ERROR (Status)) {
873 return Status;
874 }
875
876 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
877 Status = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);
878 if (EFI_ERROR (Status)) {
879 return Status;
880 }
881
882 // Address passed to CpuIo->Mem.Write needs to be a host address instead of
883 // device address.
884 return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
885 TO_HOST_ADDRESS (Address, Translation), Count, Buffer);
886 }
887
888 /**
889 Enables a PCI driver to access PCI controller registers in the PCI root
890 bridge I/O space.
891
892 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
893 @param[in] Width Signifies the width of the memory operations.
894 @param[in] Address The base address of the I/O operation. The caller is
895 responsible for aligning the Address if required.
896 @param[in] Count The number of I/O operations to perform. Bytes moved
897 is Width size * Count, starting at Address.
898 @param[out] Buffer For read operations, the destination buffer to store
899 the results. For write operations, the source buffer
900 to write data from.
901
902 @retval EFI_SUCCESS The data was read from or written to the PCI
903 root bridge.
904 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
905 @retval EFI_INVALID_PARAMETER Buffer is NULL.
906 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
907 lack of resources.
908 **/
909 EFI_STATUS
910 EFIAPI
911 RootBridgeIoIoRead (
912 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
913 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
914 IN UINT64 Address,
915 IN UINTN Count,
916 OUT VOID *Buffer
917 )
918 {
919 EFI_STATUS Status;
920 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
921
922 Status = RootBridgeIoCheckParameter (
923 This, IoOperation, Width,
924 Address, Count, Buffer
925 );
926 if (EFI_ERROR (Status)) {
927 return Status;
928 }
929
930 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
931
932 // Address passed to CpuIo->Io.Read needs to be a host address instead of
933 // device address.
934 return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
935 TO_HOST_ADDRESS (Address, RootBridge->Io.Translation), Count, Buffer);
936 }
937
938 /**
939 Enables a PCI driver to access PCI controller registers in the PCI root
940 bridge I/O space.
941
942 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
943 @param[in] Width Signifies the width of the memory operations.
944 @param[in] Address The base address of the I/O operation. The caller is
945 responsible for aligning the Address if required.
946 @param[in] Count The number of I/O operations to perform. Bytes moved
947 is Width size * Count, starting at Address.
948 @param[in] Buffer For read operations, the destination buffer to store
949 the results. For write operations, the source buffer
950 to write data from.
951
952 @retval EFI_SUCCESS The data was read from or written to the PCI
953 root bridge.
954 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
955 @retval EFI_INVALID_PARAMETER Buffer is NULL.
956 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
957 lack of resources.
958 **/
959 EFI_STATUS
960 EFIAPI
961 RootBridgeIoIoWrite (
962 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
963 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
964 IN UINT64 Address,
965 IN UINTN Count,
966 IN VOID *Buffer
967 )
968 {
969 EFI_STATUS Status;
970 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
971
972 Status = RootBridgeIoCheckParameter (
973 This, IoOperation, Width,
974 Address, Count, Buffer
975 );
976 if (EFI_ERROR (Status)) {
977 return Status;
978 }
979
980 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
981
982 // Address passed to CpuIo->Io.Write needs to be a host address instead of
983 // device address.
984 return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
985 TO_HOST_ADDRESS (Address, RootBridge->Io.Translation), Count, Buffer);
986 }
987
988 /**
989 Enables a PCI driver to copy one region of PCI root bridge memory space to
990 another region of PCI root bridge memory space.
991
992 The CopyMem() function enables a PCI driver to copy one region of PCI root
993 bridge memory space to another region of PCI root bridge memory space. This
994 is especially useful for video scroll operation on a memory mapped video
995 buffer.
996 The memory operations are carried out exactly as requested. The caller is
997 responsible for satisfying any alignment and memory width restrictions that a
998 PCI root bridge on a platform might require.
999
1000 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1001 instance.
1002 @param[in] Width Signifies the width of the memory operations.
1003 @param[in] DestAddress The destination address of the memory operation. The
1004 caller is responsible for aligning the DestAddress if
1005 required.
1006 @param[in] SrcAddress The source address of the memory operation. The caller
1007 is responsible for aligning the SrcAddress if
1008 required.
1009 @param[in] Count The number of memory operations to perform. Bytes
1010 moved is Width size * Count, starting at DestAddress
1011 and SrcAddress.
1012
1013 @retval EFI_SUCCESS The data was copied from one memory region
1014 to another memory region.
1015 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
1016 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1017 lack of resources.
1018 **/
1019 EFI_STATUS
1020 EFIAPI
1021 RootBridgeIoCopyMem (
1022 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1023 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
1024 IN UINT64 DestAddress,
1025 IN UINT64 SrcAddress,
1026 IN UINTN Count
1027 )
1028 {
1029 EFI_STATUS Status;
1030 BOOLEAN Forward;
1031 UINTN Stride;
1032 UINTN Index;
1033 UINT64 Result;
1034
1035 if ((UINT32) Width > EfiPciWidthUint64) {
1036 return EFI_INVALID_PARAMETER;
1037 }
1038
1039 if (DestAddress == SrcAddress) {
1040 return EFI_SUCCESS;
1041 }
1042
1043 Stride = (UINTN) (1 << Width);
1044
1045 Forward = TRUE;
1046 if ((DestAddress > SrcAddress) &&
1047 (DestAddress < (SrcAddress + Count * Stride))) {
1048 Forward = FALSE;
1049 SrcAddress = SrcAddress + (Count - 1) * Stride;
1050 DestAddress = DestAddress + (Count - 1) * Stride;
1051 }
1052
1053 for (Index = 0; Index < Count; Index++) {
1054 Status = RootBridgeIoMemRead (
1055 This,
1056 Width,
1057 SrcAddress,
1058 1,
1059 &Result
1060 );
1061 if (EFI_ERROR (Status)) {
1062 return Status;
1063 }
1064 Status = RootBridgeIoMemWrite (
1065 This,
1066 Width,
1067 DestAddress,
1068 1,
1069 &Result
1070 );
1071 if (EFI_ERROR (Status)) {
1072 return Status;
1073 }
1074 if (Forward) {
1075 SrcAddress += Stride;
1076 DestAddress += Stride;
1077 } else {
1078 SrcAddress -= Stride;
1079 DestAddress -= Stride;
1080 }
1081 }
1082 return EFI_SUCCESS;
1083 }
1084
1085
1086 /**
1087 PCI configuration space access.
1088
1089 @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1090 @param Read TRUE indicating it's a read operation.
1091 @param Width Signifies the width of the memory operation.
1092 @param Address The address within the PCI configuration space
1093 for the PCI controller.
1094 @param Count The number of PCI configuration operations
1095 to perform.
1096 @param Buffer The destination buffer to store the results.
1097
1098 @retval EFI_SUCCESS The data was read/written from/to the PCI root bridge.
1099 @retval EFI_INVALID_PARAMETER Invalid parameters found.
1100 **/
1101 EFI_STATUS
1102 EFIAPI
1103 RootBridgeIoPciAccess (
1104 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1105 IN BOOLEAN Read,
1106 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
1107 IN UINT64 Address,
1108 IN UINTN Count,
1109 IN OUT VOID *Buffer
1110 )
1111 {
1112 EFI_STATUS Status;
1113 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1114 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
1115 UINT8 *Uint8Buffer;
1116 UINT8 InStride;
1117 UINT8 OutStride;
1118 UINTN Size;
1119
1120 Status = RootBridgeIoCheckParameter (This, PciOperation, Width, Address, Count, Buffer);
1121 if (EFI_ERROR (Status)) {
1122 return Status;
1123 }
1124
1125 //
1126 // Read Pci configuration space
1127 //
1128 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
1129 CopyMem (&PciAddress, &Address, sizeof (PciAddress));
1130
1131 if (PciAddress.ExtendedRegister == 0) {
1132 PciAddress.ExtendedRegister = PciAddress.Register;
1133 }
1134
1135 Address = PCI_SEGMENT_LIB_ADDRESS (
1136 RootBridge->RootBridgeIo.SegmentNumber,
1137 PciAddress.Bus,
1138 PciAddress.Device,
1139 PciAddress.Function,
1140 PciAddress.ExtendedRegister
1141 );
1142
1143 //
1144 // Select loop based on the width of the transfer
1145 //
1146 InStride = mInStride[Width];
1147 OutStride = mOutStride[Width];
1148 Size = (UINTN) (1 << (Width & 0x03));
1149 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
1150 if (Read) {
1151 PciSegmentReadBuffer (Address, Size, Uint8Buffer);
1152 } else {
1153 PciSegmentWriteBuffer (Address, Size, Uint8Buffer);
1154 }
1155 }
1156 return EFI_SUCCESS;
1157 }
1158
1159 /**
1160 Allows read from PCI configuration space.
1161
1162 @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1163 @param Width Signifies the width of the memory operation.
1164 @param Address The address within the PCI configuration space
1165 for the PCI controller.
1166 @param Count The number of PCI configuration operations
1167 to perform.
1168 @param Buffer The destination buffer to store the results.
1169
1170 @retval EFI_SUCCESS The data was read from the PCI root bridge.
1171 @retval EFI_INVALID_PARAMETER Invalid parameters found.
1172 **/
1173 EFI_STATUS
1174 EFIAPI
1175 RootBridgeIoPciRead (
1176 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1177 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
1178 IN UINT64 Address,
1179 IN UINTN Count,
1180 IN OUT VOID *Buffer
1181 )
1182 {
1183 return RootBridgeIoPciAccess (This, TRUE, Width, Address, Count, Buffer);
1184 }
1185
1186 /**
1187 Allows write to PCI configuration space.
1188
1189 @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1190 @param Width Signifies the width of the memory operation.
1191 @param Address The address within the PCI configuration space
1192 for the PCI controller.
1193 @param Count The number of PCI configuration operations
1194 to perform.
1195 @param Buffer The source buffer to get the results.
1196
1197 @retval EFI_SUCCESS The data was written to the PCI root bridge.
1198 @retval EFI_INVALID_PARAMETER Invalid parameters found.
1199 **/
1200 EFI_STATUS
1201 EFIAPI
1202 RootBridgeIoPciWrite (
1203 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1204 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
1205 IN UINT64 Address,
1206 IN UINTN Count,
1207 IN OUT VOID *Buffer
1208 )
1209 {
1210 return RootBridgeIoPciAccess (This, FALSE, Width, Address, Count, Buffer);
1211 }
1212
1213 /**
1214 Provides the PCI controller-specific address needed to access
1215 system memory for DMA.
1216
1217 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1218 @param Operation Indicate if the bus master is going to read or write
1219 to system memory.
1220 @param HostAddress The system memory address to map on the PCI controller.
1221 @param NumberOfBytes On input the number of bytes to map.
1222 On output the number of bytes that were mapped.
1223 @param DeviceAddress The resulting map address for the bus master PCI
1224 controller to use to access the system memory's HostAddress.
1225 @param Mapping The value to pass to Unmap() when the bus master DMA
1226 operation is complete.
1227
1228 @retval EFI_SUCCESS Success.
1229 @retval EFI_INVALID_PARAMETER Invalid parameters found.
1230 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
1231 @retval EFI_DEVICE_ERROR The System hardware could not map the requested address.
1232 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of resources.
1233 **/
1234 EFI_STATUS
1235 EFIAPI
1236 RootBridgeIoMap (
1237 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1238 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
1239 IN VOID *HostAddress,
1240 IN OUT UINTN *NumberOfBytes,
1241 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
1242 OUT VOID **Mapping
1243 )
1244 {
1245 EFI_STATUS Status;
1246 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1247 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1248 MAP_INFO *MapInfo;
1249
1250 if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL ||
1251 Mapping == NULL) {
1252 return EFI_INVALID_PARAMETER;
1253 }
1254
1255 //
1256 // Make sure that Operation is valid
1257 //
1258 if ((UINT32) Operation >= EfiPciOperationMaximum) {
1259 return EFI_INVALID_PARAMETER;
1260 }
1261
1262 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
1263
1264 if (mIoMmu != NULL) {
1265 if (!RootBridge->DmaAbove4G) {
1266 //
1267 // Clear 64bit support
1268 //
1269 if (Operation > EfiPciOperationBusMasterCommonBuffer) {
1270 Operation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) (Operation - EfiPciOperationBusMasterRead64);
1271 }
1272 }
1273 Status = mIoMmu->Map (
1274 mIoMmu,
1275 (EDKII_IOMMU_OPERATION) Operation,
1276 HostAddress,
1277 NumberOfBytes,
1278 DeviceAddress,
1279 Mapping
1280 );
1281 return Status;
1282 }
1283
1284 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1285 if ((!RootBridge->DmaAbove4G ||
1286 (Operation != EfiPciOperationBusMasterRead64 &&
1287 Operation != EfiPciOperationBusMasterWrite64 &&
1288 Operation != EfiPciOperationBusMasterCommonBuffer64)) &&
1289 ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {
1290
1291 //
1292 // If the root bridge or the device cannot handle performing DMA above
1293 // 4GB but any part of the DMA transfer being mapped is above 4GB, then
1294 // map the DMA transfer to a buffer below 4GB.
1295 //
1296
1297 if (Operation == EfiPciOperationBusMasterCommonBuffer ||
1298 Operation == EfiPciOperationBusMasterCommonBuffer64) {
1299 //
1300 // Common Buffer operations can not be remapped. If the common buffer
1301 // if above 4GB, then it is not possible to generate a mapping, so return
1302 // an error.
1303 //
1304 return EFI_UNSUPPORTED;
1305 }
1306
1307 //
1308 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
1309 // called later.
1310 //
1311 MapInfo = AllocatePool (sizeof (MAP_INFO));
1312 if (MapInfo == NULL) {
1313 *NumberOfBytes = 0;
1314 return EFI_OUT_OF_RESOURCES;
1315 }
1316
1317 //
1318 // Initialize the MAP_INFO structure
1319 //
1320 MapInfo->Signature = MAP_INFO_SIGNATURE;
1321 MapInfo->Operation = Operation;
1322 MapInfo->NumberOfBytes = *NumberOfBytes;
1323 MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);
1324 MapInfo->HostAddress = PhysicalAddress;
1325 MapInfo->MappedHostAddress = SIZE_4GB - 1;
1326
1327 //
1328 // Allocate a buffer below 4GB to map the transfer to.
1329 //
1330 Status = gBS->AllocatePages (
1331 AllocateMaxAddress,
1332 EfiBootServicesData,
1333 MapInfo->NumberOfPages,
1334 &MapInfo->MappedHostAddress
1335 );
1336 if (EFI_ERROR (Status)) {
1337 FreePool (MapInfo);
1338 *NumberOfBytes = 0;
1339 return Status;
1340 }
1341
1342 //
1343 // If this is a read operation from the Bus Master's point of view,
1344 // then copy the contents of the real buffer into the mapped buffer
1345 // so the Bus Master can read the contents of the real buffer.
1346 //
1347 if (Operation == EfiPciOperationBusMasterRead ||
1348 Operation == EfiPciOperationBusMasterRead64) {
1349 CopyMem (
1350 (VOID *) (UINTN) MapInfo->MappedHostAddress,
1351 (VOID *) (UINTN) MapInfo->HostAddress,
1352 MapInfo->NumberOfBytes
1353 );
1354 }
1355
1356 InsertTailList (&RootBridge->Maps, &MapInfo->Link);
1357
1358 //
1359 // The DeviceAddress is the address of the maped buffer below 4GB
1360 //
1361 *DeviceAddress = MapInfo->MappedHostAddress;
1362 //
1363 // Return a pointer to the MAP_INFO structure in Mapping
1364 //
1365 *Mapping = MapInfo;
1366 } else {
1367 //
1368 // If the root bridge CAN handle performing DMA above 4GB or
1369 // the transfer is below 4GB, so the DeviceAddress is simply the
1370 // HostAddress
1371 //
1372 *DeviceAddress = PhysicalAddress;
1373 *Mapping = NO_MAPPING;
1374 }
1375
1376 return EFI_SUCCESS;
1377 }
1378
1379 /**
1380 Completes the Map() operation and releases any corresponding resources.
1381
1382 The Unmap() function completes the Map() operation and releases any
1383 corresponding resources.
1384 If the operation was an EfiPciOperationBusMasterWrite or
1385 EfiPciOperationBusMasterWrite64, the data is committed to the target system
1386 memory.
1387 Any resources used for the mapping are freed.
1388
1389 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1390 @param[in] Mapping The mapping value returned from Map().
1391
1392 @retval EFI_SUCCESS The range was unmapped.
1393 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
1394 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
1395 **/
1396 EFI_STATUS
1397 EFIAPI
1398 RootBridgeIoUnmap (
1399 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1400 IN VOID *Mapping
1401 )
1402 {
1403 MAP_INFO *MapInfo;
1404 LIST_ENTRY *Link;
1405 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1406 EFI_STATUS Status;
1407
1408 if (mIoMmu != NULL) {
1409 Status = mIoMmu->Unmap (
1410 mIoMmu,
1411 Mapping
1412 );
1413 return Status;
1414 }
1415
1416 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
1417
1418 //
1419 // See if the Map() operation associated with this Unmap() required a mapping
1420 // buffer. If a mapping buffer was not required, then this function simply
1421 // returns EFI_SUCCESS.
1422 //
1423 if (Mapping == NO_MAPPING) {
1424 return EFI_SUCCESS;
1425 }
1426
1427 MapInfo = NO_MAPPING;
1428 for (Link = GetFirstNode (&RootBridge->Maps)
1429 ; !IsNull (&RootBridge->Maps, Link)
1430 ; Link = GetNextNode (&RootBridge->Maps, Link)
1431 ) {
1432 MapInfo = MAP_INFO_FROM_LINK (Link);
1433 if (MapInfo == Mapping) {
1434 break;
1435 }
1436 }
1437 //
1438 // Mapping is not a valid value returned by Map()
1439 //
1440 if (MapInfo != Mapping) {
1441 return EFI_INVALID_PARAMETER;
1442 }
1443 RemoveEntryList (&MapInfo->Link);
1444
1445 //
1446 // If this is a write operation from the Bus Master's point of view,
1447 // then copy the contents of the mapped buffer into the real buffer
1448 // so the processor can read the contents of the real buffer.
1449 //
1450 if (MapInfo->Operation == EfiPciOperationBusMasterWrite ||
1451 MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
1452 CopyMem (
1453 (VOID *) (UINTN) MapInfo->HostAddress,
1454 (VOID *) (UINTN) MapInfo->MappedHostAddress,
1455 MapInfo->NumberOfBytes
1456 );
1457 }
1458
1459 //
1460 // Free the mapped buffer and the MAP_INFO structure.
1461 //
1462 gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
1463 FreePool (Mapping);
1464 return EFI_SUCCESS;
1465 }
1466
1467 /**
1468 Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer
1469 or EfiPciOperationBusMasterCommonBuffer64 mapping.
1470
1471 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1472 @param Type This parameter is not used and must be ignored.
1473 @param MemoryType The type of memory to allocate, EfiBootServicesData or
1474 EfiRuntimeServicesData.
1475 @param Pages The number of pages to allocate.
1476 @param HostAddress A pointer to store the base system memory address of the
1477 allocated range.
1478 @param Attributes The requested bit mask of attributes for the allocated
1479 range. Only the attributes
1480 EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
1481 EFI_PCI_ATTRIBUTE_MEMORY_CACHED, and
1482 EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this
1483 function.
1484
1485 @retval EFI_SUCCESS The requested memory pages were allocated.
1486 @retval EFI_INVALID_PARAMETER MemoryType is invalid.
1487 @retval EFI_INVALID_PARAMETER HostAddress is NULL.
1488 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal
1489 attribute bits are MEMORY_WRITE_COMBINE,
1490 MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
1491 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1492 **/
1493 EFI_STATUS
1494 EFIAPI
1495 RootBridgeIoAllocateBuffer (
1496 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1497 IN EFI_ALLOCATE_TYPE Type,
1498 IN EFI_MEMORY_TYPE MemoryType,
1499 IN UINTN Pages,
1500 OUT VOID **HostAddress,
1501 IN UINT64 Attributes
1502 )
1503 {
1504 EFI_STATUS Status;
1505 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1506 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1507 EFI_ALLOCATE_TYPE AllocateType;
1508
1509 //
1510 // Validate Attributes
1511 //
1512 if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
1513 return EFI_UNSUPPORTED;
1514 }
1515
1516 //
1517 // Check for invalid inputs
1518 //
1519 if (HostAddress == NULL) {
1520 return EFI_INVALID_PARAMETER;
1521 }
1522
1523 //
1524 // The only valid memory types are EfiBootServicesData and
1525 // EfiRuntimeServicesData
1526 //
1527 if (MemoryType != EfiBootServicesData &&
1528 MemoryType != EfiRuntimeServicesData) {
1529 return EFI_INVALID_PARAMETER;
1530 }
1531
1532 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
1533
1534 if (mIoMmu != NULL) {
1535 if (!RootBridge->DmaAbove4G) {
1536 //
1537 // Clear DUAL_ADDRESS_CYCLE
1538 //
1539 Attributes &= ~((UINT64) EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
1540 }
1541 Status = mIoMmu->AllocateBuffer (
1542 mIoMmu,
1543 Type,
1544 MemoryType,
1545 Pages,
1546 HostAddress,
1547 Attributes
1548 );
1549 return Status;
1550 }
1551
1552 AllocateType = AllocateAnyPages;
1553 if (!RootBridge->DmaAbove4G ||
1554 (Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {
1555 //
1556 // Limit allocations to memory below 4GB
1557 //
1558 AllocateType = AllocateMaxAddress;
1559 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1);
1560 }
1561 Status = gBS->AllocatePages (
1562 AllocateType,
1563 MemoryType,
1564 Pages,
1565 &PhysicalAddress
1566 );
1567 if (!EFI_ERROR (Status)) {
1568 *HostAddress = (VOID *) (UINTN) PhysicalAddress;
1569 }
1570
1571 return Status;
1572 }
1573
1574 /**
1575 Frees memory that was allocated with AllocateBuffer().
1576
1577 The FreeBuffer() function frees memory that was allocated with
1578 AllocateBuffer().
1579
1580 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1581 @param Pages The number of pages to free.
1582 @param HostAddress The base system memory address of the allocated range.
1583
1584 @retval EFI_SUCCESS The requested memory pages were freed.
1585 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
1586 Pages was not allocated with AllocateBuffer().
1587 **/
1588 EFI_STATUS
1589 EFIAPI
1590 RootBridgeIoFreeBuffer (
1591 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1592 IN UINTN Pages,
1593 OUT VOID *HostAddress
1594 )
1595 {
1596 EFI_STATUS Status;
1597
1598 if (mIoMmu != NULL) {
1599 Status = mIoMmu->FreeBuffer (
1600 mIoMmu,
1601 Pages,
1602 HostAddress
1603 );
1604 return Status;
1605 }
1606
1607 return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
1608 }
1609
1610 /**
1611 Flushes all PCI posted write transactions from a PCI host bridge to system
1612 memory.
1613
1614 The Flush() function flushes any PCI posted write transactions from a PCI
1615 host bridge to system memory. Posted write transactions are generated by PCI
1616 bus masters when they perform write transactions to target addresses in
1617 system memory.
1618 This function does not flush posted write transactions from any PCI bridges.
1619 A PCI controller specific action must be taken to guarantee that the posted
1620 write transactions have been flushed from the PCI controller and from all the
1621 PCI bridges into the PCI host bridge. This is typically done with a PCI read
1622 transaction from the PCI controller prior to calling Flush().
1623
1624 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1625
1626 @retval EFI_SUCCESS The PCI posted write transactions were flushed
1627 from the PCI host bridge to system memory.
1628 @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed
1629 from the PCI host bridge due to a hardware error.
1630 **/
1631 EFI_STATUS
1632 EFIAPI
1633 RootBridgeIoFlush (
1634 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
1635 )
1636 {
1637 return EFI_SUCCESS;
1638 }
1639
1640 /**
1641 Gets the attributes that a PCI root bridge supports setting with
1642 SetAttributes(), and the attributes that a PCI root bridge is currently
1643 using.
1644
1645 The GetAttributes() function returns the mask of attributes that this PCI
1646 root bridge supports and the mask of attributes that the PCI root bridge is
1647 currently using.
1648
1649 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1650 @param Supported A pointer to the mask of attributes that this PCI root
1651 bridge supports setting with SetAttributes().
1652 @param Attributes A pointer to the mask of attributes that this PCI root
1653 bridge is currently using.
1654
1655 @retval EFI_SUCCESS If Supports is not NULL, then the attributes
1656 that the PCI root bridge supports is returned
1657 in Supports. If Attributes is not NULL, then
1658 the attributes that the PCI root bridge is
1659 currently using is returned in Attributes.
1660 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
1661 **/
1662 EFI_STATUS
1663 EFIAPI
1664 RootBridgeIoGetAttributes (
1665 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1666 OUT UINT64 *Supported,
1667 OUT UINT64 *Attributes
1668 )
1669 {
1670 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1671
1672 if (Attributes == NULL && Supported == NULL) {
1673 return EFI_INVALID_PARAMETER;
1674 }
1675
1676 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
1677 //
1678 // Set the return value for Supported and Attributes
1679 //
1680 if (Supported != NULL) {
1681 *Supported = RootBridge->Supports;
1682 }
1683
1684 if (Attributes != NULL) {
1685 *Attributes = RootBridge->Attributes;
1686 }
1687
1688 return EFI_SUCCESS;
1689 }
1690
1691 /**
1692 Sets attributes for a resource range on a PCI root bridge.
1693
1694 The SetAttributes() function sets the attributes specified in Attributes for
1695 the PCI root bridge on the resource range specified by ResourceBase and
1696 ResourceLength. Since the granularity of setting these attributes may vary
1697 from resource type to resource type, and from platform to platform, the
1698 actual resource range and the one passed in by the caller may differ. As a
1699 result, this function may set the attributes specified by Attributes on a
1700 larger resource range than the caller requested. The actual range is returned
1701 in ResourceBase and ResourceLength. The caller is responsible for verifying
1702 that the actual range for which the attributes were set is acceptable.
1703
1704 @param This A pointer to the
1705 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1706 @param Attributes The mask of attributes to set. If the
1707 attribute bit MEMORY_WRITE_COMBINE,
1708 MEMORY_CACHED, or MEMORY_DISABLE is set,
1709 then the resource range is specified by
1710 ResourceBase and ResourceLength. If
1711 MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
1712 MEMORY_DISABLE are not set, then
1713 ResourceBase and ResourceLength are ignored,
1714 and may be NULL.
1715 @param ResourceBase A pointer to the base address of the
1716 resource range to be modified by the
1717 attributes specified by Attributes.
1718 @param ResourceLength A pointer to the length of the resource
1719 range to be modified by the attributes
1720 specified by Attributes.
1721
1722 @retval EFI_SUCCESS The current configuration of this PCI root bridge
1723 was returned in Resources.
1724 @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge
1725 could not be retrieved.
1726 **/
1727 EFI_STATUS
1728 EFIAPI
1729 RootBridgeIoSetAttributes (
1730 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1731 IN UINT64 Attributes,
1732 IN OUT UINT64 *ResourceBase,
1733 IN OUT UINT64 *ResourceLength
1734 )
1735 {
1736 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1737
1738 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
1739
1740 if ((Attributes & (~RootBridge->Supports)) != 0) {
1741 return EFI_UNSUPPORTED;
1742 }
1743
1744 RootBridge->Attributes = Attributes;
1745 return EFI_SUCCESS;
1746 }
1747
1748 /**
1749 Retrieves the current resource settings of this PCI root bridge in the form
1750 of a set of ACPI resource descriptors.
1751
1752 There are only two resource descriptor types from the ACPI Specification that
1753 may be used to describe the current resources allocated to a PCI root bridge.
1754 These are the QWORD Address Space Descriptor, and the End Tag. The QWORD
1755 Address Space Descriptor can describe memory, I/O, and bus number ranges for
1756 dynamic or fixed resources. The configuration of a PCI root bridge is described
1757 with one or more QWORD Address Space Descriptors followed by an End Tag.
1758
1759 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1760 @param[out] Resources A pointer to the resource descriptors that
1761 describe the current configuration of this PCI root
1762 bridge. The storage for the resource
1763 descriptors is allocated by this function. The
1764 caller must treat the return buffer as read-only
1765 data, and the buffer must not be freed by the
1766 caller.
1767
1768 @retval EFI_SUCCESS The current configuration of this PCI root bridge
1769 was returned in Resources.
1770 @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge
1771 could not be retrieved.
1772 **/
1773 EFI_STATUS
1774 EFIAPI
1775 RootBridgeIoConfiguration (
1776 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1777 OUT VOID **Resources
1778 )
1779 {
1780 PCI_RESOURCE_TYPE Index;
1781 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1782 PCI_RES_NODE *ResAllocNode;
1783 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
1784 EFI_ACPI_END_TAG_DESCRIPTOR *End;
1785
1786 //
1787 // Get this instance of the Root Bridge.
1788 //
1789 RootBridge = ROOT_BRIDGE_FROM_THIS (This);
1790 ZeroMem (
1791 RootBridge->ConfigBuffer,
1792 TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
1793 );
1794 Descriptor = RootBridge->ConfigBuffer;
1795 for (Index = TypeIo; Index < TypeMax; Index++) {
1796
1797 ResAllocNode = &RootBridge->ResAllocNode[Index];
1798
1799 if (ResAllocNode->Status != ResAllocated) {
1800 continue;
1801 }
1802
1803 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1804 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1805 // According to UEFI 2.7, RootBridgeIo->Configuration should return address
1806 // range in CPU view (host address), and ResAllocNode->Base is already a CPU
1807 // view address (host address).
1808 Descriptor->AddrRangeMin = ResAllocNode->Base;
1809 Descriptor->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
1810 Descriptor->AddrLen = ResAllocNode->Length;
1811 Descriptor->AddrTranslationOffset = GetTranslationByResourceType (
1812 RootBridge,
1813 ResAllocNode->Type
1814 );
1815
1816 switch (ResAllocNode->Type) {
1817
1818 case TypeIo:
1819 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1820 break;
1821
1822 case TypePMem32:
1823 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1824 case TypeMem32:
1825 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1826 Descriptor->AddrSpaceGranularity = 32;
1827 break;
1828
1829 case TypePMem64:
1830 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1831 case TypeMem64:
1832 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1833 Descriptor->AddrSpaceGranularity = 64;
1834 break;
1835
1836 case TypeBus:
1837 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
1838 break;
1839
1840 default:
1841 break;
1842 }
1843
1844 Descriptor++;
1845 }
1846 //
1847 // Terminate the entries.
1848 //
1849 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
1850 End->Desc = ACPI_END_TAG_DESCRIPTOR;
1851 End->Checksum = 0x0;
1852
1853 *Resources = RootBridge->ConfigBuffer;
1854 return EFI_SUCCESS;
1855 }