1 /**@file
2
3 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 CpuIo.c
15
16 Abstract:
17
18 This is the code that publishes the CPU I/O Protocol.
19 The intent herein is to have a single I/O service that can load
20 as early as possible, extend into runtime, and be layered upon by
21 the implementations of architectural protocols and the PCI Root
22 Bridge I/O Protocol.
23
24 **/
25
26 #include <CpuDriver.h>
27
28 #define IA32_MAX_IO_ADDRESS 0xFFFF
29 #define IA32_MAX_MEM_ADDRESS 0xFFFFFFFF
30
31 EFI_STATUS
32 CpuIoCheckAddressRange (
33 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
34 IN UINT64 Address,
35 IN UINTN Count,
36 IN VOID *Buffer,
37 IN UINT64 Limit
38 );
39
40 EFI_STATUS
41 EFIAPI
CpuMemoryServiceRead(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)42 CpuMemoryServiceRead (
43 IN EFI_CPU_IO2_PROTOCOL *This,
44 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
45 IN UINT64 Address,
46 IN UINTN Count,
47 IN OUT VOID *Buffer
48 )
49 /*++
50
51 Routine Description:
52
53 Perform the Memory Access Read service for the CPU I/O Protocol
54
55 Arguments:
56
57 Pointer to an instance of the CPU I/O Protocol
58 Width of the Memory Access
59 Address of the Memory access
60 Count of the number of accesses to perform
61 Pointer to the buffer to read or write from memory
62
63 Returns:
64
65 Status
66
67 EFI_SUCCESS - The data was read from or written to the EFI
68 System.
69 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
70 EFI_INVALID_PARAMETER - Buffer is NULL.
71 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
72 EFI_UNSUPPORTED - The address range specified by Address, Width,
73 and Count is not valid for this EFI System.
74
75 --*/
76 // TODO: This - add argument and description to function comment
77 {
78 EFI_STATUS Status;
79
80 if (!Buffer) {
81 return EFI_INVALID_PARAMETER;
82 }
83
84 if ((Width < 0) || (Width >= EfiCpuIoWidthMaximum)) {
85 return EFI_INVALID_PARAMETER;
86 }
87
88 Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
89 if (EFI_ERROR (Status)) {
90 return Status;
91 }
92
93 //
94 // Do nothing for Nt32 version
95 //
96 return EFI_UNSUPPORTED;
97 }
98
99 EFI_STATUS
100 EFIAPI
CpuMemoryServiceWrite(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)101 CpuMemoryServiceWrite (
102 IN EFI_CPU_IO2_PROTOCOL *This,
103 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
104 IN UINT64 Address,
105 IN UINTN Count,
106 IN OUT VOID *Buffer
107 )
108 /*++
109
110 Routine Description:
111
112 Perform the Memory Access Read service for the CPU I/O Protocol
113
114 Arguments:
115
116 Pointer to an instance of the CPU I/O Protocol
117 Width of the Memory Access
118 Address of the Memory access
119 Count of the number of accesses to perform
120 Pointer to the buffer to read or write from memory
121
122 Returns:
123
124 Status
125
126 EFI_SUCCESS - The data was read from or written to the EFI System.
127 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
128 EFI_INVALID_PARAMETER - Buffer is NULL.
129 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
130 EFI_UNSUPPORTED - The address range specified by Address, Width, and
131 Count is not valid for this EFI System.
132
133 --*/
134 // TODO: This - add argument and description to function comment
135 {
136 EFI_STATUS Status;
137
138 if (!Buffer) {
139 return EFI_INVALID_PARAMETER;
140 }
141
142 if ((Width < 0) || (Width >= EfiCpuIoWidthMaximum)) {
143 return EFI_INVALID_PARAMETER;
144 }
145
146 Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
147 if (EFI_ERROR (Status)) {
148 return Status;
149 }
150
151 //
152 // Do nothing for Nt32 version
153 //
154 return EFI_UNSUPPORTED;
155 }
156
157 EFI_STATUS
158 EFIAPI
CpuIoServiceRead(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 UserAddress,IN UINTN Count,IN OUT VOID * UserBuffer)159 CpuIoServiceRead (
160 IN EFI_CPU_IO2_PROTOCOL *This,
161 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
162 IN UINT64 UserAddress,
163 IN UINTN Count,
164 IN OUT VOID *UserBuffer
165 )
166 /*++
167
168 Routine Description:
169
170 This is the service that implements the I/O read
171
172 Arguments:
173
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
179
180 Returns:
181
182 Status
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.
189 --*/
190 // TODO: This - add argument and description to function comment
191 // TODO: UserAddress - add argument and description to function comment
192 // TODO: UserBuffer - add argument and description to function comment
193 {
194 UINTN Address;
195 EFI_STATUS Status;
196
197 if (!UserBuffer) {
198 return EFI_INVALID_PARAMETER;
199 }
200
201 Address = (UINTN) UserAddress;
202
203 if ((Width < 0) || (Width >= EfiCpuIoWidthMaximum)) {
204 return EFI_INVALID_PARAMETER;
205 }
206
207 Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
208 if (EFI_ERROR (Status)) {
209 return Status;
210 }
211
212 //
213 // Do nothing for Nt32 version
214 //
215 return EFI_UNSUPPORTED;
216 }
217
218 EFI_STATUS
219 EFIAPI
CpuIoServiceWrite(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 UserAddress,IN UINTN Count,IN OUT VOID * UserBuffer)220 CpuIoServiceWrite (
221 IN EFI_CPU_IO2_PROTOCOL *This,
222 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
223 IN UINT64 UserAddress,
224 IN UINTN Count,
225 IN OUT VOID *UserBuffer
226 )
227 /*++
228
229 Routine Description:
230
231
232 This is the service that implements the I/O Write
233
234 Arguments:
235
236 Pointer to an instance of the CPU I/O Protocol
237 Width of the Memory Access
238 Address of the I/O access
239 Count of the number of accesses to perform
240 Pointer to the buffer to read or write from I/O space
241
242 Returns:
243
244 Status
245
246 Status
247 EFI_SUCCESS - The data was read from or written to the EFI System.
248 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
249 EFI_INVALID_PARAMETER - Buffer is NULL.
250 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
251 EFI_UNSUPPORTED - The address range specified by Address, Width, and
252 Count is not valid for this EFI System.
253
254 --*/
255 // TODO: This - add argument and description to function comment
256 // TODO: UserAddress - add argument and description to function comment
257 // TODO: UserBuffer - add argument and description to function comment
258 {
259 UINTN Address;
260 EFI_STATUS Status;
261
262 if (!UserBuffer) {
263 return EFI_INVALID_PARAMETER;
264 }
265
266 Address = (UINTN) UserAddress;
267
268 if ((Width < 0) || (Width >= EfiCpuIoWidthMaximum)) {
269 return EFI_INVALID_PARAMETER;
270 }
271
272 Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
273 if (EFI_ERROR (Status)) {
274 return Status;
275 }
276
277 //
278 // Do nothing for Nt32 version
279 //
280 return EFI_UNSUPPORTED;
281 }
282
283
284 EFI_STATUS
CpuIoCheckAddressRange(IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer,IN UINT64 Limit)285 CpuIoCheckAddressRange (
286 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
287 IN UINT64 Address,
288 IN UINTN Count,
289 IN VOID *Buffer,
290 IN UINT64 Limit
291 )
292 /*++
293
294 Routine Description:
295
296 TODO: Add function description
297
298 Arguments:
299
300 Width - TODO: add argument description
301 Address - TODO: add argument description
302 Count - TODO: add argument description
303 Buffer - TODO: add argument description
304 Limit - TODO: add argument description
305
306 Returns:
307
308 EFI_UNSUPPORTED - TODO: Add description for return value
309 EFI_UNSUPPORTED - TODO: Add description for return value
310 EFI_UNSUPPORTED - TODO: Add description for return value
311 EFI_SUCCESS - TODO: Add description for return value
312
313 --*/
314 {
315 UINTN AlignMask;
316
317 if (Address > Limit) {
318 return EFI_UNSUPPORTED;
319 }
320
321 //
322 // For FiFo type, the target address won't increase during the access, so treat count as 1
323 //
324 if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
325 Count = 1;
326 }
327
328 Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
329 if (Address - 1 + ((UINTN)1 << Width) * Count > Limit) {
330 return EFI_UNSUPPORTED;
331 }
332
333 AlignMask = ((UINTN)1 << Width) - 1;
334 if ((UINTN) Buffer & AlignMask) {
335 return EFI_UNSUPPORTED;
336 }
337
338 return EFI_SUCCESS;
339 }
340
341
342