2 This is the code that publishes the CPU I/O Protocol.
3 The intent herein is to have a single I/O service that can load
4 as early as possible, extend into runtime, and be layered upon by
5 the implementations of architectural protocols and the PCI Root
9 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
10 Portions copyright (c) 2011, Apple Inc. All rights reserved.
11 SPDX-License-Identifier: BSD-2-Clause-Patent
16 #include <Protocol/Cpu.h>
17 #include <Protocol/CpuIo2.h>
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/HiiLib.h>
22 #include <Library/UefiLib.h>
23 #include <Library/UefiDriverEntryPoint.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/MemoryAllocationLib.h>
26 #include <Library/UefiBootServicesTableLib.h>
27 #include <CpuDriver.h>
29 #define IA32_MAX_IO_ADDRESS 0xFFFF
30 #define IA32_MAX_MEM_ADDRESS 0xFFFFFFFF
33 CpuIoCheckAddressRange (
34 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
43 CpuMemoryServiceRead (
44 IN EFI_CPU_IO2_PROTOCOL
*This
,
45 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
55 Perform the Memory Access Read service for the CPU I/O Protocol
59 Pointer to an instance of the CPU I/O Protocol
60 Width of the Memory Access
61 Address of the Memory access
62 Count of the number of accesses to perform
63 Pointer to the buffer to read or write from memory
69 EFI_SUCCESS - The data was read from or written to the EFI
71 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
72 EFI_INVALID_PARAMETER - Buffer is NULL.
73 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
74 EFI_UNSUPPORTED - The address range specified by Address, Width,
75 and Count is not valid for this EFI System.
82 return EFI_INVALID_PARAMETER
;
85 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, Buffer
, IA32_MAX_MEM_ADDRESS
);
86 if (EFI_ERROR (Status
)) {
91 // Do nothing for Nt32 version
98 CpuMemoryServiceWrite (
99 IN EFI_CPU_IO2_PROTOCOL
*This
,
100 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
110 Perform the Memory Access Read service for the CPU I/O Protocol
114 Pointer to an instance of the CPU I/O Protocol
115 Width of the Memory Access
116 Address of the Memory access
117 Count of the number of accesses to perform
118 Pointer to the buffer to read or write from memory
124 EFI_SUCCESS - The data was read from or written to the EFI System.
125 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
126 EFI_INVALID_PARAMETER - Buffer is NULL.
127 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
128 EFI_UNSUPPORTED - The address range specified by Address, Width, and
129 Count is not valid for this EFI System.
136 return EFI_INVALID_PARAMETER
;
139 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, Buffer
, IA32_MAX_MEM_ADDRESS
);
140 if (EFI_ERROR (Status
)) {
145 // Do nothing for Nt32 version
153 IN EFI_CPU_IO2_PROTOCOL
*This
,
154 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
155 IN UINT64 UserAddress
,
157 IN OUT VOID
*UserBuffer
164 This is the service that implements the I/O read
168 Pointer to an instance of the CPU I/O Protocol
169 Width of the Memory Access
170 Address of the I/O access
171 Count of the number of accesses to perform
172 Pointer to the buffer to read or write from I/O space
177 EFI_SUCCESS - The data was read from or written to the EFI System.
178 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
179 EFI_INVALID_PARAMETER - Buffer is NULL.
180 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
181 EFI_UNSUPPORTED - The address range specified by Address, Width, and
182 Count is not valid for this EFI System.
189 return EFI_INVALID_PARAMETER
;
192 Address
= (UINTN
)UserAddress
;
194 if (Width
>= EfiCpuIoWidthMaximum
) {
195 return EFI_INVALID_PARAMETER
;
198 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, UserBuffer
, IA32_MAX_IO_ADDRESS
);
199 if (EFI_ERROR (Status
)) {
204 // Do nothing for Nt32 version
212 IN EFI_CPU_IO2_PROTOCOL
*This
,
213 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
214 IN UINT64 UserAddress
,
216 IN OUT VOID
*UserBuffer
224 This is the service that implements the I/O Write
228 Pointer to an instance of the CPU I/O Protocol
229 Width of the Memory Access
230 Address of the I/O access
231 Count of the number of accesses to perform
232 Pointer to the buffer to read or write from I/O space
239 EFI_SUCCESS - The data was read from or written to the EFI System.
240 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
241 EFI_INVALID_PARAMETER - Buffer is NULL.
242 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
243 EFI_UNSUPPORTED - The address range specified by Address, Width, and
244 Count is not valid for this EFI System.
252 return EFI_INVALID_PARAMETER
;
255 Address
= (UINTN
)UserAddress
;
257 if (Width
>= EfiCpuIoWidthMaximum
) {
258 return EFI_INVALID_PARAMETER
;
261 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, UserBuffer
, IA32_MAX_IO_ADDRESS
);
262 if (EFI_ERROR (Status
)) {
267 // Do nothing for Nt32 version
278 Width - TODO: add argument description
279 Address - TODO: add argument description
280 Count - TODO: add argument description
281 Buffer - TODO: add argument description
282 Limit - TODO: add argument description
286 EFI_UNSUPPORTED - TODO: Add description for return value
287 EFI_UNSUPPORTED - TODO: Add description for return value
288 EFI_UNSUPPORTED - TODO: Add description for return value
289 EFI_SUCCESS - TODO: Add description for return value
293 CpuIoCheckAddressRange (
294 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
303 if (Address
> Limit
) {
304 return EFI_UNSUPPORTED
;
308 // For FiFo type, the target address won't increase during the access, so treat count as 1
310 if ((Width
>= EfiCpuIoWidthFifoUint8
) && (Width
<= EfiCpuIoWidthFifoUint64
)) {
314 Width
= Width
& 0x03;
315 if ((Address
- 1 + LShiftU64 (Count
, Width
)) > Limit
) {
316 return EFI_UNSUPPORTED
;
319 AlignMask
= (1 << Width
) - 1;
320 if ((UINTN
)Buffer
& AlignMask
) {
321 return EFI_UNSUPPORTED
;