OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcPciIoU.c
Go to the documentation of this file.
1
10#include "OcPciIoU.h"
11
12STATIC EFI_CPU_IO2_PROTOCOL *mCpuIo = NULL;
13
14STATIC CONST UINT8 mInStride[] = {
15 1, // EfiCpuIoWidthUint8
16 2, // EfiCpuIoWidthUint16
17 4, // EfiCpuIoWidthUint32
18 8, // EfiCpuIoWidthUint64
19 0, // EfiCpuIoWidthFifoUint8
20 0, // EfiCpuIoWidthFifoUint16
21 0, // EfiCpuIoWidthFifoUint32
22 0, // EfiCpuIoWidthFifoUint64
23 1, // EfiCpuIoWidthFillUint8
24 2, // EfiCpuIoWidthFillUint16
25 4, // EfiCpuIoWidthFillUint32
26 8 // EfiCpuIoWidthFillUint64
27};
28
29//
30// Lookup table for increment values based on transfer widths
31//
32STATIC CONST UINT8 mOutStride[] = {
33 1, // EfiCpuIoWidthUint8
34 2, // EfiCpuIoWidthUint16
35 4, // EfiCpuIoWidthUint32
36 8, // EfiCpuIoWidthUint64
37 1, // EfiCpuIoWidthFifoUint8
38 2, // EfiCpuIoWidthFifoUint16
39 4, // EfiCpuIoWidthFifoUint32
40 8, // EfiCpuIoWidthFifoUint64
41 0, // EfiCpuIoWidthFillUint8
42 0, // EfiCpuIoWidthFillUint16
43 0, // EfiCpuIoWidthFillUint32
44 0 // EfiCpuIoWidthFillUint64
45};
46
47EFI_CPU_IO2_PROTOCOL *
49 VOID
50 )
51{
52 EFI_STATUS Status;
53
54 if (mCpuIo != NULL) {
55 return mCpuIo;
56 }
57
58 Status = gBS->LocateProtocol (
59 &gEfiCpuIo2ProtocolGuid,
60 NULL,
61 (VOID **)&mCpuIo
62 );
63
64 if (EFI_ERROR (Status)) {
65 return NULL;
66 }
67
68 return mCpuIo;
69}
70
96EFI_STATUS
98 IN BOOLEAN MmioOperation,
100 IN UINT64 Address,
101 IN UINTN Count,
102 IN VOID *Buffer
103 )
104{
105 UINT64 MaxCount;
106 UINT64 Limit;
107
108 //
109 // Check to see if Buffer is NULL
110 //
111 if (Buffer == NULL) {
112 return EFI_INVALID_PARAMETER;
113 }
114
115 //
116 // Check to see if Width is in the valid range
117 //
118 if ((UINT32)Width >= EfiCpuIoWidthMaximum) {
119 return EFI_INVALID_PARAMETER;
120 }
121
122 //
123 // For FIFO type, the target address won't increase during the access,
124 // so treat Count as 1
125 //
126 if ((Width >= EfiCpuIoWidthFifoUint8) && (Width <= EfiCpuIoWidthFifoUint64)) {
127 Count = 1;
128 }
129
130 //
131 // Check to see if Width is in the valid range for I/O Port operations
132 //
133 Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
134 if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {
135 return EFI_INVALID_PARAMETER;
136 }
137
138 //
139 // Check to see if Address is aligned
140 //
141 if ((Address & ((UINT64)mInStride[Width] - 1)) != 0) {
142 return EFI_UNSUPPORTED;
143 }
144
145 //
146 // Check to see if any address associated with this transfer exceeds the maximum
147 // allowed address. The maximum address implied by the parameters passed in is
148 // Address + Size * Count. If the following condition is met, then the transfer
149 // is not supported.
150 //
151 // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
152 //
153 // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
154 // can also be the maximum integer value supported by the CPU, this range
155 // check must be adjusted to avoid all oveflow conditions.
156 //
157 // The following form of the range check is equivalent but assumes that
158 // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
159 //
160 Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
161 if (Count == 0) {
162 if (Address > Limit) {
163 return EFI_UNSUPPORTED;
164 }
165 } else {
166 MaxCount = RShiftU64 (Limit, Width);
167 if (MaxCount < (Count - 1)) {
168 return EFI_UNSUPPORTED;
169 }
170
171 if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
172 return EFI_UNSUPPORTED;
173 }
174 }
175
176 //
177 // Check to see if Buffer is aligned
178 // (IA-32 allows UINT64 and INT64 data types to be 32-bit aligned.)
179 //
180 if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) {
181 return EFI_UNSUPPORTED;
182 }
183
184 return EFI_SUCCESS;
185}
186
226EFI_STATUS
227EFIAPI
229 IN EFI_CPU_IO2_PROTOCOL *This,
231 IN UINT64 Address,
232 IN UINTN Count,
233 OUT VOID *Buffer
234 )
235{
236 EFI_STATUS Status;
237 UINT8 InStride;
238 UINT8 OutStride;
239 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
240 UINT8 *Uint8Buffer;
241
242 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
243 if (EFI_ERROR (Status)) {
244 return Status;
245 }
246
247 //
248 // Select loop based on the width of the transfer
249 //
250 InStride = mInStride[Width];
251 OutStride = mOutStride[Width];
252 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
253 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
254 if (OperationWidth == EfiCpuIoWidthUint8) {
255 *((UINT8 *)Uint8Buffer) = *((UINT8 *)(UINTN)Address);
256 } else if (OperationWidth == EfiCpuIoWidthUint16) {
257 WriteUnaligned16 ((VOID *)Uint8Buffer, ReadUnaligned16 ((VOID *)(UINTN)Address));
258 } else if (OperationWidth == EfiCpuIoWidthUint32) {
259 WriteUnaligned32 ((VOID *)Uint8Buffer, ReadUnaligned32 ((VOID *)(UINTN)Address));
260 } else if (OperationWidth == EfiCpuIoWidthUint64) {
261 WriteUnaligned64 ((VOID *)Uint8Buffer, ReadUnaligned64 ((VOID *)(UINTN)Address));
262 }
263 }
264
265 return EFI_SUCCESS;
266}
267
307EFI_STATUS
308EFIAPI
310 IN EFI_CPU_IO2_PROTOCOL *This,
312 IN UINT64 Address,
313 IN UINTN Count,
314 IN VOID *Buffer
315 )
316{
317 EFI_STATUS Status;
318 UINT8 InStride;
319 UINT8 OutStride;
320 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
321 UINT8 *Uint8Buffer;
322
323 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
324 if (EFI_ERROR (Status)) {
325 return Status;
326 }
327
328 //
329 // Select loop based on the width of the transfer
330 //
331 InStride = mInStride[Width];
332 OutStride = mOutStride[Width];
333 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
334 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
335 if (OperationWidth == EfiCpuIoWidthUint8) {
336 *((UINT8 *)(UINTN)Address) = *((UINT8 *)Uint8Buffer);
337 } else if (OperationWidth == EfiCpuIoWidthUint16) {
338 WriteUnaligned16 ((VOID *)(UINTN)Address, ReadUnaligned16 ((VOID *)Uint8Buffer));
339 } else if (OperationWidth == EfiCpuIoWidthUint32) {
340 WriteUnaligned32 ((VOID *)(UINTN)Address, ReadUnaligned32 ((VOID *)Uint8Buffer));
341 } else if (OperationWidth == EfiCpuIoWidthUint64) {
342 WriteUnaligned64 ((VOID *)(UINTN)Address, ReadUnaligned64 ((VOID *)Uint8Buffer));
343 }
344 }
345
346 return EFI_SUCCESS;
347}
348
376EFI_STATUS
377EFIAPI
379 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
380 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
381 IN UINT64 Address,
382 IN UINTN Count,
383 OUT VOID *Buffer
384 )
385{
386 if (Buffer == NULL) {
387 return EFI_INVALID_PARAMETER;
388 }
389
390 if ((Width < 0) || (Width >= EfiPciWidthMaximum)) {
391 return EFI_INVALID_PARAMETER;
392 }
393
394 // Don't check check memory access limit because firmware data is incorrect
395 return mCpuIo->Mem.Read (
396 mCpuIo,
398 Address,
399 Count,
400 Buffer
401 );
402}
403
431EFI_STATUS
432EFIAPI
434 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
435 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
436 IN UINT64 Address,
437 IN UINTN Count,
438 IN VOID *Buffer
439 )
440{
441 if (Buffer == NULL) {
442 return EFI_INVALID_PARAMETER;
443 }
444
445 if ((Width < 0) || (Width >= EfiPciWidthMaximum)) {
446 return EFI_INVALID_PARAMETER;
447 }
448
449 // Don't check check memory access limit because firmware data is incorrect
450 return mCpuIo->Mem.Write (
451 mCpuIo,
453 Address,
454 Count,
455 Buffer
456 );
457}
EFI_CPU_IO_PROTOCOL_WIDTH
Definition CpuIo.h:39
@ EfiCpuIoWidthUint8
Definition CpuIo.h:40
@ EfiCpuIoWidthUint32
Definition CpuIo.h:42
@ EfiCpuIoWidthUint64
Definition CpuIo.h:43
@ EfiCpuIoWidthFifoUint64
Definition CpuIo.h:47
@ EfiCpuIoWidthMaximum
Definition CpuIo.h:52
@ EfiCpuIoWidthFifoUint8
Definition CpuIo.h:44
@ EfiCpuIoWidthUint16
Definition CpuIo.h:41
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI RootBridgeIoMemRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, OUT VOID *Buffer)
Definition OcPciIoU.c:378
EFI_STATUS CpuIoCheckParameter(IN BOOLEAN MmioOperation, IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN VOID *Buffer)
Definition OcPciIoU.c:97
EFI_CPU_IO2_PROTOCOL * InitializeCpuIo2(VOID)
Definition OcPciIoU.c:48
STATIC CONST UINT8 mInStride[]
Definition OcPciIoU.c:14
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 OcPciIoU.c:309
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 OcPciIoU.c:228
STATIC CONST UINT8 mOutStride[]
Definition OcPciIoU.c:32
EFI_STATUS EFIAPI RootBridgeIoMemWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN VOID *Buffer)
Definition OcPciIoU.c:433
STATIC EFI_CPU_IO2_PROTOCOL * mCpuIo
Definition OcPciIoU.c:12
#define MAX_IO_PORT_ADDRESS
Definition OcPciIoU.h:25
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
UINT64 EFIAPI ReadUnaligned64(IN CONST UINT64 *Buffer)
UINT16 EFIAPI ReadUnaligned16(IN CONST UINT16 *Buffer)
UINT32 EFIAPI WriteUnaligned32(OUT UINT32 *Buffer, IN UINT32 Value)
UINT16 EFIAPI WriteUnaligned16(OUT UINT16 *Buffer, IN UINT16 Value)
UINT64 EFIAPI WriteUnaligned64(OUT UINT64 *Buffer, IN UINT64 Value)
UINT32 EFIAPI ReadUnaligned32(IN CONST UINT32 *Buffer)
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition UserMath.c:86
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition UserMath.c:76
#define MIN(a, b)
Definition deflate.c:1673