]> git.proxmox.com Git - mirror_edk2.git/blob - EmulatorPkg/CpuRuntimeDxe/CpuIo.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / EmulatorPkg / CpuRuntimeDxe / CpuIo.c
1 /*++ @file
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
6 Bridge I/O Protocol.
7
8
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
12
13 **/
14
15 #include <PiDxe.h>
16 #include <Protocol/Cpu.h>
17 #include <Protocol/CpuIo2.h>
18
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>
28
29 #define IA32_MAX_IO_ADDRESS 0xFFFF
30 #define IA32_MAX_MEM_ADDRESS 0xFFFFFFFF
31
32 EFI_STATUS
33 CpuIoCheckAddressRange (
34 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
35 IN UINT64 Address,
36 IN UINTN Count,
37 IN VOID *Buffer,
38 IN UINT64 Limit
39 );
40
41 EFI_STATUS
42 EFIAPI
43 CpuMemoryServiceRead (
44 IN EFI_CPU_IO2_PROTOCOL *This,
45 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
46 IN UINT64 Address,
47 IN UINTN Count,
48 IN OUT VOID *Buffer
49 )
50
51 /*++
52
53 Routine Description:
54
55 Perform the Memory Access Read service for the CPU I/O Protocol
56
57 Arguments:
58
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
64
65 Returns:
66
67 Status
68
69 EFI_SUCCESS - The data was read from or written to the EFI
70 System.
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.
76
77 **/
78 {
79 EFI_STATUS Status;
80
81 if (!Buffer) {
82 return EFI_INVALID_PARAMETER;
83 }
84
85 Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
86 if (EFI_ERROR (Status)) {
87 return Status;
88 }
89
90 //
91 // Do nothing for Nt32 version
92 //
93 return EFI_SUCCESS;
94 }
95
96 EFI_STATUS
97 EFIAPI
98 CpuMemoryServiceWrite (
99 IN EFI_CPU_IO2_PROTOCOL *This,
100 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
101 IN UINT64 Address,
102 IN UINTN Count,
103 IN OUT VOID *Buffer
104 )
105
106 /*++
107
108 Routine Description:
109
110 Perform the Memory Access Read service for the CPU I/O Protocol
111
112 Arguments:
113
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
119
120 Returns:
121
122 Status
123
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.
130
131 **/
132 {
133 EFI_STATUS Status;
134
135 if (!Buffer) {
136 return EFI_INVALID_PARAMETER;
137 }
138
139 Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
140 if (EFI_ERROR (Status)) {
141 return Status;
142 }
143
144 //
145 // Do nothing for Nt32 version
146 //
147 return EFI_SUCCESS;
148 }
149
150 EFI_STATUS
151 EFIAPI
152 CpuIoServiceRead (
153 IN EFI_CPU_IO2_PROTOCOL *This,
154 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
155 IN UINT64 UserAddress,
156 IN UINTN Count,
157 IN OUT VOID *UserBuffer
158 )
159
160 /*++
161
162 Routine Description:
163
164 This is the service that implements the I/O read
165
166 Arguments:
167
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
173
174 Returns:
175
176 Status
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.
183 **/
184 {
185 UINTN Address;
186 EFI_STATUS Status;
187
188 if (!UserBuffer) {
189 return EFI_INVALID_PARAMETER;
190 }
191
192 Address = (UINTN)UserAddress;
193
194 if (Width >= EfiCpuIoWidthMaximum) {
195 return EFI_INVALID_PARAMETER;
196 }
197
198 Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
199 if (EFI_ERROR (Status)) {
200 return Status;
201 }
202
203 //
204 // Do nothing for Nt32 version
205 //
206 return EFI_SUCCESS;
207 }
208
209 EFI_STATUS
210 EFIAPI
211 CpuIoServiceWrite (
212 IN EFI_CPU_IO2_PROTOCOL *This,
213 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
214 IN UINT64 UserAddress,
215 IN UINTN Count,
216 IN OUT VOID *UserBuffer
217 )
218
219 /*++
220
221 Routine Description:
222
223
224 This is the service that implements the I/O Write
225
226 Arguments:
227
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
233
234 Returns:
235
236 Status
237
238 Status
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.
245
246 **/
247 {
248 UINTN Address;
249 EFI_STATUS Status;
250
251 if (!UserBuffer) {
252 return EFI_INVALID_PARAMETER;
253 }
254
255 Address = (UINTN)UserAddress;
256
257 if (Width >= EfiCpuIoWidthMaximum) {
258 return EFI_INVALID_PARAMETER;
259 }
260
261 Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
262 if (EFI_ERROR (Status)) {
263 return Status;
264 }
265
266 //
267 // Do nothing for Nt32 version
268 //
269 return EFI_SUCCESS;
270 }
271
272 /*++
273
274 Routine Description:
275
276 Arguments:
277
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
283
284 Returns:
285
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
290
291 **/
292 EFI_STATUS
293 CpuIoCheckAddressRange (
294 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
295 IN UINT64 Address,
296 IN UINTN Count,
297 IN VOID *Buffer,
298 IN UINT64 Limit
299 )
300 {
301 UINTN AlignMask;
302
303 if (Address > Limit) {
304 return EFI_UNSUPPORTED;
305 }
306
307 //
308 // For FiFo type, the target address won't increase during the access, so treat count as 1
309 //
310 if ((Width >= EfiCpuIoWidthFifoUint8) && (Width <= EfiCpuIoWidthFifoUint64)) {
311 Count = 1;
312 }
313
314 Width = Width & 0x03;
315 if ((Address - 1 + LShiftU64 (Count, Width)) > Limit) {
316 return EFI_UNSUPPORTED;
317 }
318
319 AlignMask = (1 << Width) - 1;
320 if ((UINTN)Buffer & AlignMask) {
321 return EFI_UNSUPPORTED;
322 }
323
324 return EFI_SUCCESS;
325 }