TianoCore EDK2 master
CpuIo2Dxe.c
Go to the documentation of this file.
1
11#include "CpuIo2Dxe.h"
12
13//
14// Handle for the CPU I/O 2 Protocol
15//
17
18//
19// CPU I/O 2 Protocol instance
20//
21EFI_CPU_IO2_PROTOCOL mCpuIo2 = {
22 {
25 },
26 {
29 }
30};
31
32//
33// Lookup table for increment values based on transfer widths
34//
35UINT8 mInStride[] = {
36 1, // EfiCpuIoWidthUint8
37 2, // EfiCpuIoWidthUint16
38 4, // EfiCpuIoWidthUint32
39 8, // EfiCpuIoWidthUint64
40 0, // EfiCpuIoWidthFifoUint8
41 0, // EfiCpuIoWidthFifoUint16
42 0, // EfiCpuIoWidthFifoUint32
43 0, // EfiCpuIoWidthFifoUint64
44 1, // EfiCpuIoWidthFillUint8
45 2, // EfiCpuIoWidthFillUint16
46 4, // EfiCpuIoWidthFillUint32
47 8 // EfiCpuIoWidthFillUint64
48};
49
50//
51// Lookup table for increment values based on transfer widths
52//
53UINT8 mOutStride[] = {
54 1, // EfiCpuIoWidthUint8
55 2, // EfiCpuIoWidthUint16
56 4, // EfiCpuIoWidthUint32
57 8, // EfiCpuIoWidthUint64
58 1, // EfiCpuIoWidthFifoUint8
59 2, // EfiCpuIoWidthFifoUint16
60 4, // EfiCpuIoWidthFifoUint32
61 8, // EfiCpuIoWidthFifoUint64
62 0, // EfiCpuIoWidthFillUint8
63 0, // EfiCpuIoWidthFillUint16
64 0, // EfiCpuIoWidthFillUint32
65 0 // EfiCpuIoWidthFillUint64
66};
67
95 IN BOOLEAN MmioOperation,
97 IN UINT64 Address,
98 IN UINTN Count,
99 IN VOID *Buffer
100 )
101{
102 UINT64 MaxCount;
103 UINT64 Limit;
104
105 //
106 // Check to see if Buffer is NULL
107 //
108 if (Buffer == NULL) {
109 return EFI_INVALID_PARAMETER;
110 }
111
112 //
113 // Check to see if Width is in the valid range
114 //
115 if ((UINT32)Width >= EfiCpuIoWidthMaximum) {
116 return EFI_INVALID_PARAMETER;
117 }
118
119 //
120 // For FIFO type, the target address won't increase during the access,
121 // so treat Count as 1
122 //
123 if ((Width >= EfiCpuIoWidthFifoUint8) && (Width <= EfiCpuIoWidthFifoUint64)) {
124 Count = 1;
125 }
126
127 //
128 // Check to see if Width is in the valid range for I/O Port operations
129 //
130 Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
131 if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {
132 return EFI_INVALID_PARAMETER;
133 }
134
135 //
136 // Check to see if Address is aligned
137 //
138 if ((Address & ((UINT64)mInStride[Width] - 1)) != 0) {
139 return EFI_UNSUPPORTED;
140 }
141
142 //
143 // Check to see if any address associated with this transfer exceeds the maximum
144 // allowed address. The maximum address implied by the parameters passed in is
145 // Address + Size * Count. If the following condition is met, then the transfer
146 // is not supported.
147 //
148 // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
149 //
150 // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
151 // can also be the maximum integer value supported by the CPU, this range
152 // check must be adjusted to avoid all oveflow conditions.
153 //
154 // The following form of the range check is equivalent but assumes that
155 // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
156 //
157 Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
158 if (Count == 0) {
159 if (Address > Limit) {
160 return EFI_UNSUPPORTED;
161 }
162 } else {
163 MaxCount = RShiftU64 (Limit, Width);
164 if (MaxCount < (Count - 1)) {
165 return EFI_UNSUPPORTED;
166 }
167
168 if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
169 return EFI_UNSUPPORTED;
170 }
171 }
172
173 //
174 // Check to see if Buffer is aligned
175 // (IA-32 allows UINT64 and INT64 data types to be 32-bit aligned.)
176 //
177 if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) {
178 return EFI_UNSUPPORTED;
179 }
180
181 return EFI_SUCCESS;
182}
183
224EFIAPI
228 IN UINT64 Address,
229 IN UINTN Count,
230 OUT VOID *Buffer
231 )
232{
233 EFI_STATUS Status;
234 UINT8 InStride;
235 UINT8 OutStride;
236 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
237 UINT8 *Uint8Buffer;
238
239 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
240 if (EFI_ERROR (Status)) {
241 return Status;
242 }
243
244 //
245 // Select loop based on the width of the transfer
246 //
247 InStride = mInStride[Width];
248 OutStride = mOutStride[Width];
249 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
250 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
251 if (OperationWidth == EfiCpuIoWidthUint8) {
252 *Uint8Buffer = MmioRead8 ((UINTN)Address);
253 } else if (OperationWidth == EfiCpuIoWidthUint16) {
254 *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
255 } else if (OperationWidth == EfiCpuIoWidthUint32) {
256 *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
257 } else if (OperationWidth == EfiCpuIoWidthUint64) {
258 *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
259 }
260 }
261
262 return EFI_SUCCESS;
263}
264
305EFIAPI
309 IN UINT64 Address,
310 IN UINTN Count,
311 IN VOID *Buffer
312 )
313{
314 EFI_STATUS Status;
315 UINT8 InStride;
316 UINT8 OutStride;
317 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
318 UINT8 *Uint8Buffer;
319
320 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
321 if (EFI_ERROR (Status)) {
322 return Status;
323 }
324
325 //
326 // Select loop based on the width of the transfer
327 //
328 InStride = mInStride[Width];
329 OutStride = mOutStride[Width];
330 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
331 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
332 if (OperationWidth == EfiCpuIoWidthUint8) {
333 MmioWrite8 ((UINTN)Address, *Uint8Buffer);
334 } else if (OperationWidth == EfiCpuIoWidthUint16) {
335 MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
336 } else if (OperationWidth == EfiCpuIoWidthUint32) {
337 MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
338 } else if (OperationWidth == EfiCpuIoWidthUint64) {
339 MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
340 }
341 }
342
343 return EFI_SUCCESS;
344}
345
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 //
407 // Select loop based on the width of the transfer
408 //
409 InStride = mInStride[Width];
410 OutStride = mOutStride[Width];
411 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
412
413 //
414 // Fifo operations supported for (mInStride[Width] == 0)
415 //
416 if (InStride == 0) {
417 switch (OperationWidth) {
418 case EfiCpuIoWidthUint8:
419 IoReadFifo8 ((UINTN)Address, Count, Buffer);
420 return EFI_SUCCESS;
421 case EfiCpuIoWidthUint16:
422 IoReadFifo16 ((UINTN)Address, Count, Buffer);
423 return EFI_SUCCESS;
424 case EfiCpuIoWidthUint32:
425 IoReadFifo32 ((UINTN)Address, Count, Buffer);
426 return EFI_SUCCESS;
427 default:
428 //
429 // The CpuIoCheckParameter call above will ensure that this
430 // path is not taken.
431 //
432 ASSERT (FALSE);
433 break;
434 }
435 }
436
437 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
438 if (OperationWidth == EfiCpuIoWidthUint8) {
439 *Uint8Buffer = IoRead8 ((UINTN)Address);
440 } else if (OperationWidth == EfiCpuIoWidthUint16) {
441 *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
442 } else if (OperationWidth == EfiCpuIoWidthUint32) {
443 *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
444 }
445 }
446
447 return EFI_SUCCESS;
448}
449
490EFIAPI
494 IN UINT64 Address,
495 IN UINTN Count,
496 IN VOID *Buffer
497 )
498{
499 EFI_STATUS Status;
500 UINT8 InStride;
501 UINT8 OutStride;
502 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
503 UINT8 *Uint8Buffer;
504
505 //
506 // Make sure the parameters are valid
507 //
508 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
509 if (EFI_ERROR (Status)) {
510 return Status;
511 }
512
513 //
514 // Select loop based on the width of the transfer
515 //
516 InStride = mInStride[Width];
517 OutStride = mOutStride[Width];
518 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
519
520 //
521 // Fifo operations supported for (mInStride[Width] == 0)
522 //
523 if (InStride == 0) {
524 switch (OperationWidth) {
525 case EfiCpuIoWidthUint8:
526 IoWriteFifo8 ((UINTN)Address, Count, Buffer);
527 return EFI_SUCCESS;
528 case EfiCpuIoWidthUint16:
529 IoWriteFifo16 ((UINTN)Address, Count, Buffer);
530 return EFI_SUCCESS;
531 case EfiCpuIoWidthUint32:
532 IoWriteFifo32 ((UINTN)Address, Count, Buffer);
533 return EFI_SUCCESS;
534 default:
535 //
536 // The CpuIoCheckParameter call above will ensure that this
537 // path is not taken.
538 //
539 ASSERT (FALSE);
540 break;
541 }
542 }
543
544 for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
545 if (OperationWidth == EfiCpuIoWidthUint8) {
546 IoWrite8 ((UINTN)Address, *Uint8Buffer);
547 } else if (OperationWidth == EfiCpuIoWidthUint16) {
548 IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
549 } else if (OperationWidth == EfiCpuIoWidthUint32) {
550 IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
551 }
552 }
553
554 return EFI_SUCCESS;
555}
556
568EFIAPI
570 IN EFI_HANDLE ImageHandle,
571 IN EFI_SYSTEM_TABLE *SystemTable
572 )
573{
574 EFI_STATUS Status;
575
576 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);
577 Status = gBS->InstallMultipleProtocolInterfaces (
578 &mHandle,
579 &gEfiCpuIo2ProtocolGuid,
580 &mCpuIo2,
581 NULL
582 );
583 ASSERT_EFI_ERROR (Status);
584
585 return Status;
586}
UINT64 UINTN
#define MAX_ADDRESS
#define NULL
Definition: Base.h:312
#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
EFI_STATUS CpuIoCheckParameter(IN BOOLEAN MmioOperation, IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN VOID *Buffer)
Definition: CpuIo2Dxe.c:94
EFI_STATUS EFIAPI CpuIo2Initialize(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: CpuIo2Dxe.c:569
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: CpuIo2Dxe.c:491
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: CpuIo2Dxe.c:306
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: CpuIo2Dxe.c:225
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: CpuIo2Dxe.c:387
EFI_HANDLE mHandle
Definition: CpuIo2Dxe.c:16
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:440
#define ASSERT_PROTOCOL_ALREADY_INSTALLED(Handle, Guid)
Definition: DebugLib.h:503
#define ASSERT(Expression)
Definition: DebugLib.h:391
UINT8 EFIAPI IoWrite8(IN UINTN Port, IN UINT8 Value)
Definition: IoLibArmVirt.c:200
UINT64 EFIAPI MmioWrite64(IN UINTN Address, IN UINT64 Value)
Definition: IoLib.c:400
VOID EFIAPI IoWriteFifo32(IN UINTN Port, IN UINTN Count, IN VOID *Buffer)
Definition: IoLibArmVirt.c:520
VOID EFIAPI IoReadFifo8(IN UINTN Port, IN UINTN Count, OUT VOID *Buffer)
Definition: IoLibArmVirt.c:380
VOID EFIAPI IoReadFifo16(IN UINTN Port, IN UINTN Count, OUT VOID *Buffer)
Definition: IoLibArmVirt.c:436
VOID EFIAPI IoWriteFifo16(IN UINTN Port, IN UINTN Count, IN VOID *Buffer)
Definition: IoLibArmVirt.c:464
UINT64 EFIAPI MmioRead64(IN UINTN Address)
Definition: IoLib.c:355
VOID EFIAPI IoReadFifo32(IN UINTN Port, IN UINTN Count, OUT VOID *Buffer)
Definition: IoLibArmVirt.c:492
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
UINT8 EFIAPI IoRead8(IN UINTN Port)
Definition: IoLibArmVirt.c:175
UINT32 EFIAPI MmioRead32(IN UINTN Address)
Definition: IoLib.c:262
VOID EFIAPI IoWriteFifo8(IN UINTN Port, IN UINTN Count, IN VOID *Buffer)
Definition: IoLibArmVirt.c:408
UINT16 EFIAPI IoRead16(IN UINTN Port)
Definition: IoLibArmVirt.c:225
UINT16 EFIAPI MmioWrite16(IN UINTN Address, IN UINT16 Value)
Definition: IoLib.c:216
UINT32 EFIAPI IoRead32(IN UINTN Port)
Definition: IoLibArmVirt.c:275
UINT32 EFIAPI IoWrite32(IN UINTN Port, IN UINT32 Value)
Definition: IoLibArmVirt.c:300
UINT16 EFIAPI IoWrite16(IN UINTN Port, IN UINT16 Value)
Definition: IoLibArmVirt.c:250
UINT32 EFIAPI MmioWrite32(IN UINTN Address, IN UINT32 Value)
Definition: IoLib.c:309
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