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, Intel Corporation. All rights reserved.<BR>
10 Portions copyright (c) 2011, Apple Inc. All rights reserved.
11 This program and the accompanying materials
12 are licensed and made available under the terms and conditions of the BSD License
13 which accompanies this distribution. The full text of the license may be found at
14 http://opensource.org/licenses/bsd-license.php
16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 #include <FrameworkDxe.h>
22 #include <Protocol/Cpu.h>
23 #include <Protocol/DataHub.h>
24 #include <Guid/DataHubRecords.h>
25 #include <Protocol/CpuIo2.h>
26 #include <Protocol/FrameworkHii.h>
28 #include <Library/BaseLib.h>
29 #include <Library/DebugLib.h>
30 #include <Library/HiiLib.h>
31 #include <Library/UefiLib.h>
32 #include <Library/UefiDriverEntryPoint.h>
33 #include <Library/BaseMemoryLib.h>
34 #include <Library/MemoryAllocationLib.h>
35 #include <Library/UefiBootServicesTableLib.h>
36 #include <CpuDriver.h>
38 #define IA32_MAX_IO_ADDRESS 0xFFFF
39 #define IA32_MAX_MEM_ADDRESS 0xFFFFFFFF
42 CpuIoCheckAddressRange (
43 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
52 CpuMemoryServiceRead (
53 IN EFI_CPU_IO2_PROTOCOL
*This
,
54 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
63 Perform the Memory Access Read service for the CPU I/O Protocol
67 Pointer to an instance of the CPU I/O Protocol
68 Width of the Memory Access
69 Address of the Memory access
70 Count of the number of accesses to perform
71 Pointer to the buffer to read or write from memory
77 EFI_SUCCESS - The data was read from or written to the EFI
79 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
80 EFI_INVALID_PARAMETER - Buffer is NULL.
81 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
82 EFI_UNSUPPORTED - The address range specified by Address, Width,
83 and Count is not valid for this EFI System.
90 return EFI_INVALID_PARAMETER
;
93 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, Buffer
, IA32_MAX_MEM_ADDRESS
);
94 if (EFI_ERROR (Status
)) {
99 // Do nothing for Nt32 version
106 CpuMemoryServiceWrite (
107 IN EFI_CPU_IO2_PROTOCOL
*This
,
108 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
117 Perform the Memory Access Read service for the CPU I/O Protocol
121 Pointer to an instance of the CPU I/O Protocol
122 Width of the Memory Access
123 Address of the Memory access
124 Count of the number of accesses to perform
125 Pointer to the buffer to read or write from memory
131 EFI_SUCCESS - The data was read from or written to the EFI System.
132 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
133 EFI_INVALID_PARAMETER - Buffer is NULL.
134 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
135 EFI_UNSUPPORTED - The address range specified by Address, Width, and
136 Count is not valid for this EFI System.
143 return EFI_INVALID_PARAMETER
;
146 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, Buffer
, IA32_MAX_MEM_ADDRESS
);
147 if (EFI_ERROR (Status
)) {
152 // Do nothing for Nt32 version
160 IN EFI_CPU_IO2_PROTOCOL
*This
,
161 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
162 IN UINT64 UserAddress
,
164 IN OUT VOID
*UserBuffer
170 This is the service that implements the I/O read
174 Pointer to an instance of the CPU I/O Protocol
175 Width of the Memory Access
176 Address of the I/O access
177 Count of the number of accesses to perform
178 Pointer to the buffer to read or write from I/O space
183 EFI_SUCCESS - The data was read from or written to the EFI System.
184 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
185 EFI_INVALID_PARAMETER - Buffer is NULL.
186 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
187 EFI_UNSUPPORTED - The address range specified by Address, Width, and
188 Count is not valid for this EFI System.
195 return EFI_INVALID_PARAMETER
;
198 Address
= (UINTN
) UserAddress
;
200 if (Width
>= EfiCpuIoWidthMaximum
) {
201 return EFI_INVALID_PARAMETER
;
204 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, UserBuffer
, IA32_MAX_IO_ADDRESS
);
205 if (EFI_ERROR (Status
)) {
210 // Do nothing for Nt32 version
218 IN EFI_CPU_IO2_PROTOCOL
*This
,
219 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
220 IN UINT64 UserAddress
,
222 IN OUT VOID
*UserBuffer
229 This is the service that implements the I/O Write
233 Pointer to an instance of the CPU I/O Protocol
234 Width of the Memory Access
235 Address of the I/O access
236 Count of the number of accesses to perform
237 Pointer to the buffer to read or write from I/O space
244 EFI_SUCCESS - The data was read from or written to the EFI System.
245 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
246 EFI_INVALID_PARAMETER - Buffer is NULL.
247 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
248 EFI_UNSUPPORTED - The address range specified by Address, Width, and
249 Count is not valid for this EFI System.
257 return EFI_INVALID_PARAMETER
;
260 Address
= (UINTN
) UserAddress
;
262 if (Width
>= EfiCpuIoWidthMaximum
) {
263 return EFI_INVALID_PARAMETER
;
266 Status
= CpuIoCheckAddressRange (Width
, Address
, Count
, UserBuffer
, IA32_MAX_IO_ADDRESS
);
267 if (EFI_ERROR (Status
)) {
272 // Do nothing for Nt32 version
284 Width - TODO: add argument description
285 Address - TODO: add argument description
286 Count - TODO: add argument description
287 Buffer - TODO: add argument description
288 Limit - TODO: add argument description
292 EFI_UNSUPPORTED - TODO: Add description for return value
293 EFI_UNSUPPORTED - TODO: Add description for return value
294 EFI_UNSUPPORTED - TODO: Add description for return value
295 EFI_SUCCESS - TODO: Add description for return value
299 CpuIoCheckAddressRange (
300 IN EFI_CPU_IO_PROTOCOL_WIDTH Width
,
309 if (Address
> Limit
) {
310 return EFI_UNSUPPORTED
;
314 // For FiFo type, the target address won't increase during the access, so treat count as 1
316 if (Width
>= EfiCpuIoWidthFifoUint8
&& Width
<= EfiCpuIoWidthFifoUint64
) {
320 Width
= Width
& 0x03;
321 if (Address
- 1 + (1 << Width
) * Count
> Limit
) {
322 return EFI_UNSUPPORTED
;
325 AlignMask
= (1 << Width
) - 1;
326 if ((UINTN
) Buffer
& AlignMask
) {
327 return EFI_UNSUPPORTED
;