2 Produces the CPU I/O 2 Protocol.
4 Copyright (c) 2009, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "CpuIo2Dxe.h"
17 EFI_HANDLE mHandle
= NULL
;
18 EFI_CPU_IO2_PROTOCOL mCpuIo
= {
30 Worker function to check the validation of parameters for CPU I/O interface functions.
32 This function check the validation of parameters for CPU I/O interface functions.
34 @param Width Width of the Mmio/Io operation
35 @param Address Base address of the Mmio/Io operation
36 @param Count Count of the number of accesses to perform
37 @param Buffer Pointer to the buffer to read from memory
38 @param Limit Maximum address supported
40 @retval EFI_INVALID_PARAMETER Buffer is NULL
41 @retval EFI_UNSUPPORTED The address range specified by Width, Address and Count is invalid
42 @retval EFI_UNSUPPORTED The memory buffer is not aligned
43 @retval EFI_SUCCESS Parameters are valid
48 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
58 return EFI_INVALID_PARAMETER
;
61 if (Address
> Limit
) {
62 return EFI_UNSUPPORTED
;
66 // For FiFo type, the target address won't increase during the access,
67 // so treat count as 1
69 if (Width
>= EfiCpuIoWidthFifoUint8
&& Width
<= EfiCpuIoWidthFifoUint64
) {
73 Width
= (EFI_CPU_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
74 if (Address
- 1 + (UINT32
)(1 << Width
) * Count
> Limit
) {
75 return EFI_UNSUPPORTED
;
78 AlignMask
= (1 << Width
) - 1;
79 if ((UINTN
) Buffer
& AlignMask
) {
80 return EFI_UNSUPPORTED
;
87 Worker function to update access width and count for access to the unaligned address.
88 Unaligned Io/MmIo address access, break up the request into word by word or byte by byte.
90 @param Address Base address of the Mmio/Io operation
91 @param PtrWidth Pointer to width of the Mmio/Io operation
92 Out, this value will be updated for access to the unaligned address.
93 @param PtrCount Pointer to count of the number of accesses to perform
94 Out, this value will be updated for access to the unaligned address.
97 CpuIoUpdateWidthCount (
99 IN OUT EFI_CPU_IO_PROTOCOL_WIDTH
*PtrWidth
,
100 IN OUT UINTN
*PtrCount
103 EFI_CPU_IO_PROTOCOL_WIDTH BufferWidth
;
106 BufferWidth
= *PtrWidth
;
107 BufferCount
= *PtrCount
;
109 switch (BufferWidth
) {
110 case EfiCpuIoWidthUint8
:
113 case EfiCpuIoWidthUint16
:
114 if ((Address
& 0x01) == 0) {
117 BufferCount
= BufferCount
* 2;
118 BufferWidth
= EfiCpuIoWidthUint8
;
122 case EfiCpuIoWidthUint32
:
123 if ((Address
& 0x03) == 0) {
125 } else if ((Address
& 0x01) == 0) {
126 BufferCount
= BufferCount
* 2;
127 BufferWidth
= EfiCpuIoWidthUint16
;
129 BufferCount
= BufferCount
* 4;
130 BufferWidth
= EfiCpuIoWidthUint8
;
134 case EfiCpuIoWidthUint64
:
135 if ((Address
& 0x07) == 0) {
137 } else if ((Address
& 0x03) == 0) {
138 BufferCount
= BufferCount
* 2;
139 BufferWidth
= EfiCpuIoWidthUint32
;
140 } else if ((Address
& 0x01) == 0) {
141 BufferCount
= BufferCount
* 4;
142 BufferWidth
= EfiCpuIoWidthUint16
;
144 BufferCount
= BufferCount
* 8;
145 BufferWidth
= EfiCpuIoWidthUint8
;
153 *PtrWidth
= BufferWidth
;
154 *PtrCount
= BufferCount
;
160 Worker function to perform memory mapped I/O read/write
162 This function provides private services to perform memory mapped I/O read/write.
164 @param Width Width of the memory mapped I/O operation
165 @param Count Count of the number of accesses to perform
166 @param DestinationStrideFlag Boolean flag indicates if the destination is to be incremented
167 @param Destination Destination of the memory mapped I/O operation
168 @param SourceStrideFlag Boolean flag indicates if the source is to be incremented
169 @param Source Source of the memory mapped I/O operation
171 @retval EFI_SUCCESS Successful operation
172 @retval EFI_INVALID_PARAMETER Width is invalid
177 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
179 IN BOOLEAN DestinationStrideFlag
,
181 IN BOOLEAN SourceStrideFlag
,
186 UINTN DestinationStride
;
189 Width
= (EFI_CPU_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
190 Stride
= (UINT32
)(1 << Width
);
191 DestinationStride
= DestinationStrideFlag
? Stride
: 0;
192 SourceStride
= SourceStrideFlag
? Stride
: 0;
195 // Loop for each iteration and move the data
198 case EfiCpuIoWidthUint8
:
199 for (; Count
> 0; Count
--, Destination
.Buf
+= DestinationStride
, Source
.Buf
+= SourceStride
) {
200 MmioWrite8((UINTN
)Destination
.Ui8
, MmioRead8((UINTN
)Source
.Ui8
));
204 case EfiCpuIoWidthUint16
:
205 for (; Count
> 0; Count
--, Destination
.Buf
+= DestinationStride
, Source
.Buf
+= SourceStride
) {
206 MmioWrite16((UINTN
)Destination
.Ui16
, MmioRead16((UINTN
)Source
.Ui16
));
210 case EfiCpuIoWidthUint32
:
211 for (; Count
> 0; Count
--, Destination
.Buf
+= DestinationStride
, Source
.Buf
+= SourceStride
) {
212 MmioWrite32((UINTN
)Destination
.Ui32
, MmioRead32((UINTN
)Source
.Ui32
));
216 case EfiCpuIoWidthUint64
:
217 for (; Count
> 0; Count
--, Destination
.Buf
+= DestinationStride
, Source
.Buf
+= SourceStride
) {
218 MmioWrite64((UINTN
)Destination
.Ui64
, MmioRead64((UINTN
)Source
.Ui64
));
223 return EFI_INVALID_PARAMETER
;
230 Enables a driver to read memory-mapped registers in the PI System memory space.
232 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
233 @param[in] Width Signifies the width of the memory operation.
234 @param[in] Address The base address of the memory operation.
235 @param[in] Count The number of memory operations to perform. The number of bytes moved
236 is Width size * Count, starting at Address.
237 @param[out] Buffer The destination buffer to store the results.
239 @retval EFI_SUCCESS The data was read from or written to the EFI system.
240 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. Or Buffer is NULL.
241 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
242 Or,The address range specified by Address, Width, and Count is not valid for this EFI system.
247 CpuMemoryServiceRead (
248 IN EFI_CPU_IO2_PROTOCOL
*This
,
249 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
258 EFI_CPU_IO_PROTOCOL_WIDTH BufferWidth
;
260 Status
= CpuIoCheckParameter (Width
, Address
, Count
, Buffer
, MAX_ADDRESS
);
261 if (EFI_ERROR (Status
)) {
265 Destination
.Buf
= Buffer
;
266 Source
.Buf
= (VOID
*) (UINTN
) Address
;
269 // Support access to unaligned mmio address.
270 // Break up the request into byte by byte
272 BufferWidth
= (EFI_CPU_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
273 CpuIoUpdateWidthCount (Address
, &BufferWidth
, &Count
);
275 if (Width
>= EfiCpuIoWidthUint8
&& Width
<= EfiCpuIoWidthUint64
) {
276 return CpuIoMemRW (BufferWidth
, Count
, TRUE
, Destination
, TRUE
, Source
);
279 if (Width
>= EfiCpuIoWidthFifoUint8
&& Width
<= EfiCpuIoWidthFifoUint64
) {
280 return CpuIoMemRW (BufferWidth
, Count
, TRUE
, Destination
, FALSE
, Source
);
283 if (Width
>= EfiCpuIoWidthFillUint8
&& Width
<= EfiCpuIoWidthFillUint64
) {
284 return CpuIoMemRW (BufferWidth
, Count
, FALSE
, Destination
, TRUE
, Source
);
287 return EFI_INVALID_PARAMETER
;
291 Enables a driver to write memory-mapped registers in the PI System memory space.
293 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
294 @param[in] Width Signifies the width of the memory operation.
295 @param[in] Address The base address of the memory operation.
296 @param[in] Count The number of memory operations to perform. The number of bytes moved
297 is Width size * Count, starting at Address.
298 @param[in] Buffer The source buffer from which to write data.
300 @retval EFI_SUCCESS The data was read from or written to the EFI system.
301 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. Or Buffer is NULL.
302 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
303 Or,The address range specified by Address, Width, and Count is not valid for this EFI system.
308 CpuMemoryServiceWrite (
309 IN EFI_CPU_IO2_PROTOCOL
*This
,
310 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
319 EFI_CPU_IO_PROTOCOL_WIDTH BufferWidth
;
321 Status
= CpuIoCheckParameter (Width
, Address
, Count
, Buffer
, MAX_ADDRESS
);
322 if (EFI_ERROR (Status
)) {
326 Destination
.Buf
= (VOID
*) (UINTN
) Address
;
330 // Support access to unaligned mmio address.
331 // Break up the request into byte by byte
333 BufferWidth
= (EFI_CPU_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
334 CpuIoUpdateWidthCount (Address
, &BufferWidth
, &Count
);
336 if (Width
>= EfiCpuIoWidthUint8
&& Width
<= EfiCpuIoWidthUint64
) {
337 return CpuIoMemRW (BufferWidth
, Count
, TRUE
, Destination
, TRUE
, Source
);
340 if (Width
>= EfiCpuIoWidthFifoUint8
&& Width
<= EfiCpuIoWidthFifoUint64
) {
341 return CpuIoMemRW (BufferWidth
, Count
, FALSE
, Destination
, TRUE
, Source
);
344 if (Width
>= EfiCpuIoWidthFillUint8
&& Width
<= EfiCpuIoWidthFillUint64
) {
345 return CpuIoMemRW (BufferWidth
, Count
, TRUE
, Destination
, FALSE
, Source
);
348 return EFI_INVALID_PARAMETER
;
352 Enables a driver to read registers in the PI CPU I/O space.
354 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
355 @param[in] Width Signifies the width of the I/O operation.
356 @param[in] UserAddress The base address of the I/O operation. The caller is responsible
357 for aligning the Address if required.
358 @param[in] Count The number of I/O operations to perform. The number of bytes moved
359 is Width size * Count, starting at Address.
360 @param[out] UserBuffer The destination buffer to store the results.
362 @retval EFI_SUCCESS The data was read from or written to the EFI system.
363 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. Or Buffer is NULL.
364 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
365 Or,The address range specified by Address, Width, and Count is not valid for this EFI system.
371 IN EFI_CPU_IO2_PROTOCOL
*This
,
372 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
373 IN UINT64 UserAddress
,
383 EFI_CPU_IO_PROTOCOL_WIDTH BufferWidth
;
385 Buffer
.Buf
= (UINT8
*) UserBuffer
;
387 if (Width
>= EfiCpuIoWidthMaximum
) {
388 return EFI_INVALID_PARAMETER
;
391 Status
= CpuIoCheckParameter (Width
, UserAddress
, Count
, UserBuffer
, IA32_MAX_IO_ADDRESS
);
392 if (EFI_ERROR (Status
)) {
397 // Support access to unaligned IO address.
398 // Break up the request into byte by byte
400 BufferWidth
= (EFI_CPU_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
401 CpuIoUpdateWidthCount (UserAddress
, &BufferWidth
, &Count
);
403 Address
= (UINTN
) UserAddress
;
404 InStride
= (UINT32
)(1 << (BufferWidth
& 0x03));
405 OutStride
= InStride
;
406 if (Width
>= EfiCpuIoWidthFifoUint8
&& Width
<= EfiCpuIoWidthFifoUint64
) {
410 if (Width
>= EfiCpuIoWidthFillUint8
&& Width
<= EfiCpuIoWidthFillUint64
) {
415 // Loop for each iteration and move the data
417 switch (BufferWidth
) {
418 case EfiCpuIoWidthUint8
:
419 for (; Count
> 0; Count
--, Buffer
.Buf
+= OutStride
, Address
+= InStride
) {
420 *Buffer
.Ui8
= IoRead8 (Address
);
424 case EfiCpuIoWidthUint16
:
425 for (; Count
> 0; Count
--, Buffer
.Buf
+= OutStride
, Address
+= InStride
) {
426 *Buffer
.Ui16
= IoRead16 (Address
);
430 case EfiCpuIoWidthUint32
:
431 for (; Count
> 0; Count
--, Buffer
.Buf
+= OutStride
, Address
+= InStride
) {
432 *Buffer
.Ui32
= IoRead32 (Address
);
437 return EFI_INVALID_PARAMETER
;
444 Enables a driver to write registers in the PI CPU I/O space.
446 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
447 @param[in] Width Signifies the width of the I/O operation.
448 @param[in] UserAddress The base address of the I/O operation. The caller is responsible
449 for aligning the Address if required.
450 @param[in] Count The number of I/O operations to perform. The number of bytes moved
451 is Width size * Count, starting at Address.
452 @param[in] UserBuffer The source buffer from which to write data.
454 @retval EFI_SUCCESS The data was read from or written to the EFI system.
455 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. Or Buffer is NULL.
456 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
457 Or,The address range specified by Address, Width, and Count is not valid for this EFI system.
463 IN EFI_CPU_IO2_PROTOCOL
*This
,
464 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
465 IN UINT64 UserAddress
,
475 EFI_CPU_IO_PROTOCOL_WIDTH BufferWidth
;
477 Buffer
.Buf
= (UINT8
*) UserBuffer
;
479 if (Width
>= EfiCpuIoWidthMaximum
) {
480 return EFI_INVALID_PARAMETER
;
483 Status
= CpuIoCheckParameter (Width
, UserAddress
, Count
, UserBuffer
, IA32_MAX_IO_ADDRESS
);
484 if (EFI_ERROR (Status
)) {
489 // Support access to unaligned IO address.
490 // Break up the request into byte by byte
492 BufferWidth
= (EFI_CPU_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
493 CpuIoUpdateWidthCount (UserAddress
, &BufferWidth
, &Count
);
495 Address
= (UINTN
) UserAddress
;
496 InStride
= (UINT32
)(1 << (BufferWidth
& 0x03));
497 OutStride
= InStride
;
498 if (Width
>= EfiCpuIoWidthFifoUint8
&& Width
<= EfiCpuIoWidthFifoUint64
) {
502 if (Width
>= EfiCpuIoWidthFillUint8
&& Width
<= EfiCpuIoWidthFillUint64
) {
507 // Loop for each iteration and move the data
509 switch (BufferWidth
) {
510 case EfiCpuIoWidthUint8
:
511 for (; Count
> 0; Count
--, Buffer
.Buf
+= OutStride
, Address
+= InStride
) {
512 IoWrite8 (Address
, *Buffer
.Ui8
);
516 case EfiCpuIoWidthUint16
:
517 for (; Count
> 0; Count
--, Buffer
.Buf
+= OutStride
, Address
+= InStride
) {
518 IoWrite16 (Address
, *Buffer
.Ui16
);
522 case EfiCpuIoWidthUint32
:
523 for (; Count
> 0; Count
--, Buffer
.Buf
+= OutStride
, Address
+= InStride
) {
524 IoWrite32 (Address
, *Buffer
.Ui32
);
529 return EFI_INVALID_PARAMETER
;
536 Entrypoint of CPU I/O 2 DXE module.
538 @param ImageHandle The firmware allocated handle for the EFI image.
539 @param SystemTable A pointer to the EFI System Table.
541 @retval EFI_SUCCESS The entry point is executed successfully.
547 IN EFI_HANDLE ImageHandle
,
548 IN EFI_SYSTEM_TABLE
*SystemTable
553 Status
= gBS
->InstallProtocolInterface (
555 &gEfiCpuIo2ProtocolGuid
,
556 EFI_NATIVE_INTERFACE
,
559 ASSERT_EFI_ERROR (Status
);