TianoCore EDK2 master
ArmPciCpuIo2Dxe.c
Go to the documentation of this file.
1
11#include <PiDxe.h>
12
13#include <Protocol/CpuIo2.h>
14
15#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
17#include <Library/IoLib.h>
18#include <Library/PcdLib.h>
20
21#define MAX_IO_PORT_ADDRESS 0xFFFF
22
23//
24// Handle for the CPU I/O 2 Protocol
25//
27
28//
29// Lookup table for increment values based on transfer widths
30//
31STATIC CONST UINT8 mInStride[] = {
32 1, // EfiCpuIoWidthUint8
33 2, // EfiCpuIoWidthUint16
34 4, // EfiCpuIoWidthUint32
35 8, // EfiCpuIoWidthUint64
36 0, // EfiCpuIoWidthFifoUint8
37 0, // EfiCpuIoWidthFifoUint16
38 0, // EfiCpuIoWidthFifoUint32
39 0, // EfiCpuIoWidthFifoUint64
40 1, // EfiCpuIoWidthFillUint8
41 2, // EfiCpuIoWidthFillUint16
42 4, // EfiCpuIoWidthFillUint32
43 8 // EfiCpuIoWidthFillUint64
44};
45
46//
47// Lookup table for increment values based on transfer widths
48//
49STATIC CONST UINT8 mOutStride[] = {
50 1, // EfiCpuIoWidthUint8
51 2, // EfiCpuIoWidthUint16
52 4, // EfiCpuIoWidthUint32
53 8, // EfiCpuIoWidthUint64
54 1, // EfiCpuIoWidthFifoUint8
55 2, // EfiCpuIoWidthFifoUint16
56 4, // EfiCpuIoWidthFifoUint32
57 8, // EfiCpuIoWidthFifoUint64
58 0, // EfiCpuIoWidthFillUint8
59 0, // EfiCpuIoWidthFillUint16
60 0, // EfiCpuIoWidthFillUint32
61 0 // EfiCpuIoWidthFillUint64
62};
63
92 IN BOOLEAN MmioOperation,
94 IN UINT64 Address,
95 IN UINTN Count,
96 IN VOID *Buffer
97 )
98{
99 UINT64 MaxCount;
100 UINT64 Limit;
101
102 //
103 // Check to see if Buffer is NULL
104 //
105 if (Buffer == NULL) {
106 return EFI_INVALID_PARAMETER;
107 }
108
109 //
110 // Check to see if Width is in the valid range
111 //
112 if ((UINT32)Width >= EfiCpuIoWidthMaximum) {
113 return EFI_INVALID_PARAMETER;
114 }
115
116 //
117 // For FIFO type, the target address won't increase during the access,
118 // so treat Count as 1
119 //
120 if ((Width >= EfiCpuIoWidthFifoUint8) && (Width <= EfiCpuIoWidthFifoUint64)) {
121 Count = 1;
122 }
123
124 //
125 // Check to see if Width is in the valid range for I/O Port operations
126 //
127 Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
128 if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {
129 return EFI_INVALID_PARAMETER;
130 }
131
132 //
133 // Check to see if Address is aligned
134 //
135 if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {
136 return EFI_UNSUPPORTED;
137 }
138
139 //
140 // Check to see if any address associated with this transfer exceeds the maximum
141 // allowed address. The maximum address implied by the parameters passed in is
142 // Address + Size * Count. If the following condition is met, then the transfer
143 // is not supported.
144 //
145 // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
146 //
147 // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
148 // can also be the maximum integer value supported by the CPU, this range
149 // check must be adjusted to avoid all overflow conditions.
150 //
151 // The following form of the range check is equivalent but assumes that
152 // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
153 //
154 Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
155 if (Count == 0) {
156 if (Address > Limit) {
157 return EFI_UNSUPPORTED;
158 }
159 } else {
160 MaxCount = RShiftU64 (Limit, Width);
161 if (MaxCount < (Count - 1)) {
162 return EFI_UNSUPPORTED;
163 }
164
165 if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
166 return EFI_UNSUPPORTED;
167 }
168 }
169
170 //
171 // Check to see if Buffer is aligned
172 //
173 if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) {
174 return EFI_UNSUPPORTED;
175 }
176
177 return EFI_SUCCESS;
178}
179
219STATIC
221EFIAPI
225 IN UINT64 Address,
226 IN UINTN Count,
227 OUT VOID *Buffer
228 )
229{
230 EFI_STATUS Status;
231 UINT8 InStride;
232 UINT8 OutStride;
233 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
234 UINT8 *Uint8Buffer;
235
236 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
237 if (EFI_ERROR (Status)) {
238 return Status;
239 }
240
241 //
242 // Select loop based on the width of the transfer
243 //
244 InStride = mInStride[Width];
245 OutStride = mOutStride[Width];
246 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
247 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
248 if (OperationWidth == EfiCpuIoWidthUint8) {
249 *Uint8Buffer = MmioRead8 ((UINTN)Address);
250 } else if (OperationWidth == EfiCpuIoWidthUint16) {
251 *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
252 } else if (OperationWidth == EfiCpuIoWidthUint32) {
253 *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
254 } else if (OperationWidth == EfiCpuIoWidthUint64) {
255 *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
256 }
257 }
258
259 return EFI_SUCCESS;
260}
261
301STATIC
303EFIAPI
307 IN UINT64 Address,
308 IN UINTN Count,
309 IN VOID *Buffer
310 )
311{
312 EFI_STATUS Status;
313 UINT8 InStride;
314 UINT8 OutStride;
315 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
316 UINT8 *Uint8Buffer;
317
318 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
319 if (EFI_ERROR (Status)) {
320 return Status;
321 }
322
323 //
324 // Select loop based on the width of the transfer
325 //
326 InStride = mInStride[Width];
327 OutStride = mOutStride[Width];
328 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
329 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
330 if (OperationWidth == EfiCpuIoWidthUint8) {
331 MmioWrite8 ((UINTN)Address, *Uint8Buffer);
332 } else if (OperationWidth == EfiCpuIoWidthUint16) {
333 MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
334 } else if (OperationWidth == EfiCpuIoWidthUint32) {
335 MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
336 } else if (OperationWidth == EfiCpuIoWidthUint64) {
337 MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
338 }
339 }
340
341 return EFI_SUCCESS;
342}
343
383STATIC
385EFIAPI
389 IN UINT64 Address,
390 IN UINTN Count,
391 OUT VOID *Buffer
392 )
393{
394 EFI_STATUS Status;
395 UINT8 InStride;
396 UINT8 OutStride;
397 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
398 UINT8 *Uint8Buffer;
399
400 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
401 if (EFI_ERROR (Status)) {
402 return Status;
403 }
404
405 Address += PcdGet64 (PcdPciIoTranslation);
406
407 //
408 // Select loop based on the width of the transfer
409 //
410 InStride = mInStride[Width];
411 OutStride = mOutStride[Width];
412 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
413
414 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
415 if (OperationWidth == EfiCpuIoWidthUint8) {
416 *Uint8Buffer = MmioRead8 ((UINTN)Address);
417 } else if (OperationWidth == EfiCpuIoWidthUint16) {
418 *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
419 } else if (OperationWidth == EfiCpuIoWidthUint32) {
420 *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
421 }
422 }
423
424 return EFI_SUCCESS;
425}
426
466STATIC
468EFIAPI
472 IN UINT64 Address,
473 IN UINTN Count,
474 IN VOID *Buffer
475 )
476{
477 EFI_STATUS Status;
478 UINT8 InStride;
479 UINT8 OutStride;
480 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
481 UINT8 *Uint8Buffer;
482
483 //
484 // Make sure the parameters are valid
485 //
486 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
487 if (EFI_ERROR (Status)) {
488 return Status;
489 }
490
491 Address += PcdGet64 (PcdPciIoTranslation);
492
493 //
494 // Select loop based on the width of the transfer
495 //
496 InStride = mInStride[Width];
497 OutStride = mOutStride[Width];
498 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
499
500 for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
501 if (OperationWidth == EfiCpuIoWidthUint8) {
502 MmioWrite8 ((UINTN)Address, *Uint8Buffer);
503 } else if (OperationWidth == EfiCpuIoWidthUint16) {
504 MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
505 } else if (OperationWidth == EfiCpuIoWidthUint32) {
506 MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
507 }
508 }
509
510 return EFI_SUCCESS;
511}
512
513//
514// CPU I/O 2 Protocol instance
515//
517 {
520 },
521 {
524 }
525};
526
538EFIAPI
540 IN EFI_HANDLE ImageHandle,
541 IN EFI_SYSTEM_TABLE *SystemTable
542 )
543{
544 EFI_STATUS Status;
545
546 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);
547 Status = gBS->InstallMultipleProtocolInterfaces (
548 &mHandle,
549 &gEfiCpuIo2ProtocolGuid,
550 &mCpuIo2,
551 NULL
552 );
553 ASSERT_EFI_ERROR (Status);
554
555 return Status;
556}
UINT64 UINTN
#define MAX_ADDRESS
STATIC EFI_STATUS EFIAPI CpuMemoryServiceRead(IN EFI_CPU_IO2_PROTOCOL *This, IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, OUT VOID *Buffer)
STATIC EFI_STATUS EFIAPI CpuIoServiceWrite(IN EFI_CPU_IO2_PROTOCOL *This, IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN VOID *Buffer)
EFI_STATUS EFIAPI ArmPciCpuIo2Initialize(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
STATIC EFI_STATUS EFIAPI CpuMemoryServiceWrite(IN EFI_CPU_IO2_PROTOCOL *This, IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN VOID *Buffer)
STATIC EFI_STATUS EFIAPI CpuIoServiceRead(IN EFI_CPU_IO2_PROTOCOL *This, IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, OUT VOID *Buffer)
STATIC EFI_STATUS CpuIoCheckParameter(IN BOOLEAN MmioOperation, IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN VOID *Buffer)
#define NULL
Definition: Base.h:312
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define MIN(a, b)
Definition: Base.h:903
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
EFI_CPU_IO_PROTOCOL_WIDTH
Definition: CpuIo2.h:37
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:440
#define ASSERT_PROTOCOL_ALREADY_INSTALLED(Handle, Guid)
Definition: DebugLib.h:503
UINT64 EFIAPI MmioWrite64(IN UINTN Address, IN UINT64 Value)
Definition: IoLib.c:400
UINT64 EFIAPI MmioRead64(IN UINTN Address)
Definition: IoLib.c:355
UINT16 EFIAPI MmioRead16(IN UINTN Address)
Definition: IoLib.c:170
UINT8 EFIAPI MmioRead8(IN UINTN Address)
Definition: IoLib.c:82
UINT8 EFIAPI MmioWrite8(IN UINTN Address, IN UINT8 Value)
Definition: IoLib.c:126
UINT32 EFIAPI MmioRead32(IN UINTN Address)
Definition: IoLib.c:262
UINT16 EFIAPI MmioWrite16(IN UINTN Address, IN UINT16 Value)
Definition: IoLib.c:216
UINT32 EFIAPI MmioWrite32(IN UINTN Address, IN UINT32 Value)
Definition: IoLib.c:309
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:28
VOID * EFI_HANDLE
Definition: UefiBaseType.h:32
#define EFI_SUCCESS
Definition: UefiBaseType.h:111
EFI_BOOT_SERVICES * gBS