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
,
54 Perform the Memory Access Read service for the CPU I/O Protocol
58 Pointer to an instance of the CPU I/O Protocol
59 Width of the Memory Access
60 Address of the Memory access
61 Count of the number of accesses to perform
62 Pointer to the buffer to read or write from memory
68 EFI_SUCCESS - The data was read from or written to the EFI
70 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
71 EFI_INVALID_PARAMETER - Buffer is NULL.
72 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
73 EFI_UNSUPPORTED - The address range specified by Address, Width,
74 and Count is not valid for this EFI System.
81 return EFI_INVALID_PARAMETER
;
84 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, Buffer
, IA32_MAX_MEM_ADDRESS
);
85 if (EFI_ERROR (Status
)) {
90 // Do nothing for Nt32 version
97 CpuMemoryServiceWrite (
98 IN EFI_CPU_IO2_PROTOCOL
*This
,
99 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
108 Perform the Memory Access Read service for the CPU I/O Protocol
112 Pointer to an instance of the CPU I/O Protocol
113 Width of the Memory Access
114 Address of the Memory access
115 Count of the number of accesses to perform
116 Pointer to the buffer to read or write from memory
122 EFI_SUCCESS - The data was read from or written to the EFI System.
123 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
124 EFI_INVALID_PARAMETER - Buffer is NULL.
125 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
126 EFI_UNSUPPORTED - The address range specified by Address, Width, and
127 Count is not valid for this EFI System.
134 return EFI_INVALID_PARAMETER
;
137 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, Buffer
, IA32_MAX_MEM_ADDRESS
);
138 if (EFI_ERROR (Status
)) {
143 // Do nothing for Nt32 version
151 IN EFI_CPU_IO2_PROTOCOL
*This
,
152 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
153 IN UINT64 UserAddress
,
155 IN OUT VOID
*UserBuffer
161 This is the service that implements the I/O read
165 Pointer to an instance of the CPU I/O Protocol
166 Width of the Memory Access
167 Address of the I/O access
168 Count of the number of accesses to perform
169 Pointer to the buffer to read or write from I/O space
174 EFI_SUCCESS - The data was read from or written to the EFI System.
175 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
176 EFI_INVALID_PARAMETER - Buffer is NULL.
177 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
178 EFI_UNSUPPORTED - The address range specified by Address, Width, and
179 Count is not valid for this EFI System.
186 return EFI_INVALID_PARAMETER
;
189 Address
= (UINTN
) UserAddress
;
191 if (Width
>= EfiCpuIoWidthMaximum
) {
192 return EFI_INVALID_PARAMETER
;
195 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, UserBuffer
, IA32_MAX_IO_ADDRESS
);
196 if (EFI_ERROR (Status
)) {
201 // Do nothing for Nt32 version
209 IN EFI_CPU_IO2_PROTOCOL
*This
,
210 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
211 IN UINT64 UserAddress
,
213 IN OUT VOID
*UserBuffer
220 This is the service that implements the I/O Write
224 Pointer to an instance of the CPU I/O Protocol
225 Width of the Memory Access
226 Address of the I/O access
227 Count of the number of accesses to perform
228 Pointer to the buffer to read or write from I/O space
235 EFI_SUCCESS - The data was read from or written to the EFI System.
236 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
237 EFI_INVALID_PARAMETER - Buffer is NULL.
238 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
239 EFI_UNSUPPORTED - The address range specified by Address, Width, and
240 Count is not valid for this EFI System.
248 return EFI_INVALID_PARAMETER
;
251 Address
= (UINTN
) UserAddress
;
253 if (Width
>= EfiCpuIoWidthMaximum
) {
254 return EFI_INVALID_PARAMETER
;
257 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, UserBuffer
, IA32_MAX_IO_ADDRESS
);
258 if (EFI_ERROR (Status
)) {
263 // Do nothing for Nt32 version
275 Width - TODO: add argument description
276 Address - TODO: add argument description
277 Count - TODO: add argument description
278 Buffer - TODO: add argument description
279 Limit - TODO: add argument description
283 EFI_UNSUPPORTED - TODO: Add description for return value
284 EFI_UNSUPPORTED - TODO: Add description for return value
285 EFI_UNSUPPORTED - TODO: Add description for return value
286 EFI_SUCCESS - TODO: Add description for return value
290 CpuIoCheckAddressRange (
291 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
300 if (Address
> Limit
) {
301 return EFI_UNSUPPORTED
;
305 // For FiFo type, the target address won't increase during the access, so treat count as 1
307 if (Width
>= EfiCpuIoWidthFifoUint8
&& Width
<= EfiCpuIoWidthFifoUint64
) {
311 Width
= Width
& 0x03;
312 if ((Address
- 1 + LShiftU64 (Count
, Width
)) > Limit
) {
313 return EFI_UNSUPPORTED
;
316 AlignMask
= (1 << Width
) - 1;
317 if ((UINTN
) Buffer
& AlignMask
) {
318 return EFI_UNSUPPORTED
;