]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/CpuRuntimeDxe/CpuIo.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / EmulatorPkg / CpuRuntimeDxe / CpuIo.c
CommitLineData
949f388f 1/*++ @file\r
2 This is the code that publishes the CPU I/O Protocol.\r
3 The intent herein is to have a single I/O service that can load\r
d18d8a1d 4 as early as possible, extend into runtime, and be layered upon by\r
949f388f 5 the implementations of architectural protocols and the PCI Root\r
6 Bridge I/O Protocol.\r
7\r
8\r
e148512e 9Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
949f388f 10Portions copyright (c) 2011, Apple Inc. All rights reserved.\r
e3ba31da 11SPDX-License-Identifier: BSD-2-Clause-Patent\r
949f388f 12\r
13**/\r
14\r
a0af6b27 15#include <PiDxe.h>\r
949f388f 16#include <Protocol/Cpu.h>\r
949f388f 17#include <Protocol/CpuIo2.h>\r
949f388f 18\r
19#include <Library/BaseLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/HiiLib.h>\r
22#include <Library/UefiLib.h>\r
23#include <Library/UefiDriverEntryPoint.h>\r
24#include <Library/BaseMemoryLib.h>\r
25#include <Library/MemoryAllocationLib.h>\r
26#include <Library/UefiBootServicesTableLib.h>\r
27#include <CpuDriver.h>\r
28\r
29#define IA32_MAX_IO_ADDRESS 0xFFFF\r
30#define IA32_MAX_MEM_ADDRESS 0xFFFFFFFF\r
31\r
32EFI_STATUS\r
33CpuIoCheckAddressRange (\r
a550d468
MK
34 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
35 IN UINT64 Address,\r
36 IN UINTN Count,\r
37 IN VOID *Buffer,\r
38 IN UINT64 Limit\r
949f388f 39 );\r
40\r
41EFI_STATUS\r
42EFIAPI\r
43CpuMemoryServiceRead (\r
a550d468
MK
44 IN EFI_CPU_IO2_PROTOCOL *This,\r
45 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
46 IN UINT64 Address,\r
47 IN UINTN Count,\r
48 IN OUT VOID *Buffer\r
949f388f 49 )\r
a550d468 50\r
949f388f 51/*++\r
52\r
53Routine Description:\r
54\r
55 Perform the Memory Access Read service for the CPU I/O Protocol\r
56\r
57Arguments:\r
58\r
59 Pointer to an instance of the CPU I/O Protocol\r
60 Width of the Memory Access\r
61 Address of the Memory access\r
62 Count of the number of accesses to perform\r
63 Pointer to the buffer to read or write from memory\r
64\r
65Returns:\r
66\r
67 Status\r
68\r
d18d8a1d 69 EFI_SUCCESS - The data was read from or written to the EFI\r
949f388f 70 System.\r
71 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.\r
72 EFI_INVALID_PARAMETER - Buffer is NULL.\r
73 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
d18d8a1d 74 EFI_UNSUPPORTED - The address range specified by Address, Width,\r
949f388f 75 and Count is not valid for this EFI System.\r
76\r
77**/\r
78{\r
79 EFI_STATUS Status;\r
80\r
81 if (!Buffer) {\r
82 return EFI_INVALID_PARAMETER;\r
83 }\r
84\r
85 Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);\r
86 if (EFI_ERROR (Status)) {\r
87 return Status;\r
88 }\r
89\r
90 //\r
91 // Do nothing for Nt32 version\r
92 //\r
93 return EFI_SUCCESS;\r
94}\r
95\r
96EFI_STATUS\r
97EFIAPI\r
98CpuMemoryServiceWrite (\r
a550d468
MK
99 IN EFI_CPU_IO2_PROTOCOL *This,\r
100 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
101 IN UINT64 Address,\r
102 IN UINTN Count,\r
103 IN OUT VOID *Buffer\r
949f388f 104 )\r
a550d468 105\r
949f388f 106/*++\r
107\r
108Routine Description:\r
109\r
110 Perform the Memory Access Read service for the CPU I/O Protocol\r
111\r
112Arguments:\r
113\r
114 Pointer to an instance of the CPU I/O Protocol\r
115 Width of the Memory Access\r
116 Address of the Memory access\r
117 Count of the number of accesses to perform\r
118 Pointer to the buffer to read or write from memory\r
119\r
120Returns:\r
121\r
122 Status\r
123\r
124 EFI_SUCCESS - The data was read from or written to the EFI System.\r
125 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.\r
126 EFI_INVALID_PARAMETER - Buffer is NULL.\r
127 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
d18d8a1d 128 EFI_UNSUPPORTED - The address range specified by Address, Width, and\r
949f388f 129 Count is not valid for this EFI System.\r
130\r
131**/\r
132{\r
133 EFI_STATUS Status;\r
134\r
135 if (!Buffer) {\r
136 return EFI_INVALID_PARAMETER;\r
137 }\r
138\r
139 Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);\r
140 if (EFI_ERROR (Status)) {\r
141 return Status;\r
142 }\r
143\r
144 //\r
145 // Do nothing for Nt32 version\r
146 //\r
147 return EFI_SUCCESS;\r
148}\r
149\r
150EFI_STATUS\r
151EFIAPI\r
152CpuIoServiceRead (\r
a550d468
MK
153 IN EFI_CPU_IO2_PROTOCOL *This,\r
154 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
155 IN UINT64 UserAddress,\r
156 IN UINTN Count,\r
157 IN OUT VOID *UserBuffer\r
949f388f 158 )\r
a550d468 159\r
949f388f 160/*++\r
161\r
162Routine Description:\r
d18d8a1d 163\r
949f388f 164 This is the service that implements the I/O read\r
165\r
166Arguments:\r
167\r
168 Pointer to an instance of the CPU I/O Protocol\r
169 Width of the Memory Access\r
170 Address of the I/O access\r
171 Count of the number of accesses to perform\r
172 Pointer to the buffer to read or write from I/O space\r
173\r
174Returns:\r
175\r
176 Status\r
177 EFI_SUCCESS - The data was read from or written to the EFI System.\r
178 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.\r
179 EFI_INVALID_PARAMETER - Buffer is NULL.\r
180 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
d18d8a1d 181 EFI_UNSUPPORTED - The address range specified by Address, Width, and\r
949f388f 182 Count is not valid for this EFI System.\r
183**/\r
184{\r
185 UINTN Address;\r
186 EFI_STATUS Status;\r
187\r
188 if (!UserBuffer) {\r
189 return EFI_INVALID_PARAMETER;\r
190 }\r
191\r
a550d468 192 Address = (UINTN)UserAddress;\r
949f388f 193\r
194 if (Width >= EfiCpuIoWidthMaximum) {\r
195 return EFI_INVALID_PARAMETER;\r
196 }\r
197\r
198 Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);\r
199 if (EFI_ERROR (Status)) {\r
200 return Status;\r
201 }\r
202\r
203 //\r
204 // Do nothing for Nt32 version\r
205 //\r
206 return EFI_SUCCESS;\r
207}\r
208\r
209EFI_STATUS\r
210EFIAPI\r
211CpuIoServiceWrite (\r
a550d468
MK
212 IN EFI_CPU_IO2_PROTOCOL *This,\r
213 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
214 IN UINT64 UserAddress,\r
215 IN UINTN Count,\r
216 IN OUT VOID *UserBuffer\r
949f388f 217 )\r
a550d468 218\r
949f388f 219/*++\r
220\r
221Routine Description:\r
222\r
d18d8a1d 223\r
949f388f 224 This is the service that implements the I/O Write\r
225\r
226Arguments:\r
227\r
228 Pointer to an instance of the CPU I/O Protocol\r
229 Width of the Memory Access\r
230 Address of the I/O access\r
231 Count of the number of accesses to perform\r
232 Pointer to the buffer to read or write from I/O space\r
233\r
234Returns:\r
235\r
236 Status\r
237\r
238 Status\r
239 EFI_SUCCESS - The data was read from or written to the EFI System.\r
240 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.\r
241 EFI_INVALID_PARAMETER - Buffer is NULL.\r
242 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
d18d8a1d 243 EFI_UNSUPPORTED - The address range specified by Address, Width, and\r
949f388f 244 Count is not valid for this EFI System.\r
245\r
246**/\r
247{\r
248 UINTN Address;\r
249 EFI_STATUS Status;\r
250\r
251 if (!UserBuffer) {\r
252 return EFI_INVALID_PARAMETER;\r
253 }\r
254\r
a550d468 255 Address = (UINTN)UserAddress;\r
949f388f 256\r
257 if (Width >= EfiCpuIoWidthMaximum) {\r
258 return EFI_INVALID_PARAMETER;\r
259 }\r
260\r
261 Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);\r
262 if (EFI_ERROR (Status)) {\r
263 return Status;\r
264 }\r
265\r
266 //\r
267 // Do nothing for Nt32 version\r
268 //\r
269 return EFI_SUCCESS;\r
270}\r
271\r
949f388f 272/*++\r
273\r
274Routine Description:\r
275\r
276Arguments:\r
277\r
278 Width - TODO: add argument description\r
279 Address - TODO: add argument description\r
280 Count - TODO: add argument description\r
281 Buffer - TODO: add argument description\r
282 Limit - TODO: add argument description\r
283\r
284Returns:\r
285\r
286 EFI_UNSUPPORTED - TODO: Add description for return value\r
287 EFI_UNSUPPORTED - TODO: Add description for return value\r
288 EFI_UNSUPPORTED - TODO: Add description for return value\r
289 EFI_SUCCESS - TODO: Add description for return value\r
290\r
291**/\r
292EFI_STATUS\r
293CpuIoCheckAddressRange (\r
a550d468
MK
294 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
295 IN UINT64 Address,\r
296 IN UINTN Count,\r
297 IN VOID *Buffer,\r
298 IN UINT64 Limit\r
949f388f 299 )\r
300{\r
a550d468 301 UINTN AlignMask;\r
949f388f 302\r
303 if (Address > Limit) {\r
304 return EFI_UNSUPPORTED;\r
305 }\r
306\r
307 //\r
308 // For FiFo type, the target address won't increase during the access, so treat count as 1\r
309 //\r
a550d468 310 if ((Width >= EfiCpuIoWidthFifoUint8) && (Width <= EfiCpuIoWidthFifoUint64)) {\r
949f388f 311 Count = 1;\r
312 }\r
313\r
314 Width = Width & 0x03;\r
e148512e 315 if ((Address - 1 + LShiftU64 (Count, Width)) > Limit) {\r
949f388f 316 return EFI_UNSUPPORTED;\r
317 }\r
318\r
319 AlignMask = (1 << Width) - 1;\r
a550d468 320 if ((UINTN)Buffer & AlignMask) {\r
949f388f 321 return EFI_UNSUPPORTED;\r
322 }\r
323\r
324 return EFI_SUCCESS;\r
325}\r