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