67b79053935710f1c2deb2a403cc45bfc5b0cceb
[mirror_edk2.git] / UefiCpuPkg / CpuIoPei / CpuIoPei.c
1 /** @file
2 Produces the CPU I/O PPI.
3
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "CpuIoPei.h"
16
17 //
18 // Instance of CPU I/O PPI
19 //
20 EFI_PEI_CPU_IO_PPI gCpuIoPpi = {
21 {
22 CpuMemoryServiceRead,
23 CpuMemoryServiceWrite
24 },
25 {
26 CpuIoServiceRead,
27 CpuIoServiceWrite
28 },
29 CpuIoRead8,
30 CpuIoRead16,
31 CpuIoRead32,
32 CpuIoRead64,
33 CpuIoWrite8,
34 CpuIoWrite16,
35 CpuIoWrite32,
36 CpuIoWrite64,
37 CpuMemRead8,
38 CpuMemRead16,
39 CpuMemRead32,
40 CpuMemRead64,
41 CpuMemWrite8,
42 CpuMemWrite16,
43 CpuMemWrite32,
44 CpuMemWrite64
45 };
46
47 //
48 // PPI Descriptor used to install the CPU I/O PPI
49 //
50 EFI_PEI_PPI_DESCRIPTOR gPpiList = {
51 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
52 &gEfiPeiCpuIoPpiInstalledGuid,
53 NULL
54 };
55
56 //
57 // Lookup table for increment values based on transfer widths
58 //
59 UINT8 mInStride[] = {
60 1, // EfiPeiCpuIoWidthUint8
61 2, // EfiPeiCpuIoWidthUint16
62 4, // EfiPeiCpuIoWidthUint32
63 8, // EfiPeiCpuIoWidthUint64
64 0, // EfiPeiCpuIoWidthFifoUint8
65 0, // EfiPeiCpuIoWidthFifoUint16
66 0, // EfiPeiCpuIoWidthFifoUint32
67 0, // EfiPeiCpuIoWidthFifoUint64
68 1, // EfiPeiCpuIoWidthFillUint8
69 2, // EfiPeiCpuIoWidthFillUint16
70 4, // EfiPeiCpuIoWidthFillUint32
71 8 // EfiPeiCpuIoWidthFillUint64
72 };
73
74 //
75 // Lookup table for increment values based on transfer widths
76 //
77 UINT8 mOutStride[] = {
78 1, // EfiPeiCpuIoWidthUint8
79 2, // EfiPeiCpuIoWidthUint16
80 4, // EfiPeiCpuIoWidthUint32
81 8, // EfiPeiCpuIoWidthUint64
82 1, // EfiPeiCpuIoWidthFifoUint8
83 2, // EfiPeiCpuIoWidthFifoUint16
84 4, // EfiPeiCpuIoWidthFifoUint32
85 8, // EfiPeiCpuIoWidthFifoUint64
86 0, // EfiPeiCpuIoWidthFillUint8
87 0, // EfiPeiCpuIoWidthFillUint16
88 0, // EfiPeiCpuIoWidthFillUint32
89 0 // EfiPeiCpuIoWidthFillUint64
90 };
91
92 /**
93 Check parameters to a CPU I/O PPI service request.
94
95 @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.
96 @param[in] Width The width of the access. Enumerated in bytes.
97 @param[in] Address The physical address of the access.
98 @param[in] Count The number of accesses to perform.
99 @param[in] Buffer A pointer to the buffer of data.
100
101 @retval EFI_SUCCESS The parameters for this request pass the checks.
102 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
103 @retval EFI_INVALID_PARAMETER Buffer is NULL.
104 @retval EFI_UNSUPPORTED The address range specified by Address, Width,
105 and Count is not valid for this EFI system.
106
107 **/
108 EFI_STATUS
109 CpuIoCheckParameter (
110 IN BOOLEAN MmioOperation,
111 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
112 IN UINT64 Address,
113 IN UINTN Count,
114 IN VOID *Buffer
115 )
116 {
117 UINT64 MaxCount;
118 UINT64 Limit;
119
120 //
121 // Check to see if Buffer is NULL
122 //
123 if (Buffer == NULL) {
124 return EFI_INVALID_PARAMETER;
125 }
126
127 //
128 // Check to see if Width is in the valid range
129 //
130 if (Width < 0 || Width >= EfiPeiCpuIoWidthMaximum) {
131 return EFI_INVALID_PARAMETER;
132 }
133
134 //
135 // For FIFO type, the target address won't increase during the access,
136 // so treat Count as 1
137 //
138 if (Width >= EfiPeiCpuIoWidthFifoUint8 && Width <= EfiPeiCpuIoWidthFifoUint64) {
139 Count = 1;
140 }
141
142 //
143 // Check to see if Width is in the valid range for I/O Port operations
144 //
145 Width = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
146 if (!MmioOperation && (Width == EfiPeiCpuIoWidthUint64)) {
147 return EFI_INVALID_PARAMETER;
148 }
149
150 //
151 // Check to see if any address associated with this transfer exceeds the maximum
152 // allowed address. The maximum address implied by the parameters passed in is
153 // Address + Size * Count. If the following condition is met, then the transfer
154 // is not supported.
155 //
156 // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
157 //
158 // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
159 // can also be the maximum integer value supported by the CPU, this range
160 // check must be adjusted to avoid all overflow conditions.
161 //
162 // The following form of the range check is equivalent but assumes that
163 // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
164 //
165 Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
166 if (Count == 0) {
167 if (Address > Limit) {
168 return EFI_UNSUPPORTED;
169 }
170 } else {
171 MaxCount = RShiftU64 (Limit, Width);
172 if (MaxCount < (Count - 1)) {
173 return EFI_UNSUPPORTED;
174 }
175 if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
176 return EFI_UNSUPPORTED;
177 }
178 }
179
180 return EFI_SUCCESS;
181 }
182
183 /**
184 Reads memory-mapped registers.
185
186 @param[in] PeiServices An indirect pointer to the PEI Services Table
187 published by the PEI Foundation.
188 @param[in] This Pointer to local data for the interface.
189 @param[in] Width The width of the access. Enumerated in bytes.
190 @param[in] Address The physical address of the access.
191 @param[in] Count The number of accesses to perform.
192 @param[out] Buffer A pointer to the buffer of data.
193
194 @retval EFI_SUCCESS The function completed successfully.
195 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
196 @retval EFI_INVALID_PARAMETER Buffer is NULL.
197 @retval EFI_UNSUPPORTED The address range specified by Address, Width,
198 and Count is not valid for this EFI system.
199
200 **/
201 EFI_STATUS
202 EFIAPI
203 CpuMemoryServiceRead (
204 IN CONST EFI_PEI_SERVICES **PeiServices,
205 IN CONST EFI_PEI_CPU_IO_PPI *This,
206 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
207 IN UINT64 Address,
208 IN UINTN Count,
209 OUT VOID *Buffer
210 )
211 {
212 EFI_STATUS Status;
213 UINT8 InStride;
214 UINT8 OutStride;
215 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
216 BOOLEAN Aligned;
217 UINT8 *Uint8Buffer;
218
219 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
220 if (EFI_ERROR (Status)) {
221 return Status;
222 }
223
224 //
225 // Select loop based on the width of the transfer
226 //
227 InStride = mInStride[Width];
228 OutStride = mOutStride[Width];
229 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
230 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
231 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
232 if (OperationWidth == EfiPeiCpuIoWidthUint8) {
233 *Uint8Buffer = MmioRead8 ((UINTN)Address);
234 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
235 if (Aligned) {
236 *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
237 } else {
238 WriteUnaligned16 ((UINT16 *)Uint8Buffer, MmioRead16 ((UINTN)Address));
239 }
240 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
241 if (Aligned) {
242 *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
243 } else {
244 WriteUnaligned32 ((UINT32 *)Uint8Buffer, MmioRead32 ((UINTN)Address));
245 }
246 } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
247 if (Aligned) {
248 *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
249 } else {
250 WriteUnaligned64 ((UINT64 *)Uint8Buffer, MmioRead64 ((UINTN)Address));
251 }
252 }
253 }
254 return EFI_SUCCESS;
255 }
256
257 /**
258 Writes memory-mapped registers.
259
260 @param[in] PeiServices An indirect pointer to the PEI Services Table
261 published by the PEI Foundation.
262 @param[in] This Pointer to local data for the interface.
263 @param[in] Width The width of the access. Enumerated in bytes.
264 @param[in] Address The physical address of the access.
265 @param[in] Count The number of accesses to perform.
266 @param[in] Buffer A pointer to the buffer of data.
267
268 @retval EFI_SUCCESS The function completed successfully.
269 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
270 @retval EFI_INVALID_PARAMETER Buffer is NULL.
271 @retval EFI_UNSUPPORTED The address range specified by Address, Width,
272 and Count is not valid for this EFI system.
273
274 **/
275 EFI_STATUS
276 EFIAPI
277 CpuMemoryServiceWrite (
278 IN CONST EFI_PEI_SERVICES **PeiServices,
279 IN CONST EFI_PEI_CPU_IO_PPI *This,
280 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
281 IN UINT64 Address,
282 IN UINTN Count,
283 IN VOID *Buffer
284 )
285 {
286 EFI_STATUS Status;
287 UINT8 InStride;
288 UINT8 OutStride;
289 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
290 BOOLEAN Aligned;
291 UINT8 *Uint8Buffer;
292
293 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
294 if (EFI_ERROR (Status)) {
295 return Status;
296 }
297
298 //
299 // Select loop based on the width of the transfer
300 //
301 InStride = mInStride[Width];
302 OutStride = mOutStride[Width];
303 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
304 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
305 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
306 if (OperationWidth == EfiPeiCpuIoWidthUint8) {
307 MmioWrite8 ((UINTN)Address, *Uint8Buffer);
308 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
309 if (Aligned) {
310 MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
311 } else {
312 MmioWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
313 }
314 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
315 if (Aligned) {
316 MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
317 } else {
318 MmioWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
319 }
320 } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
321 if (Aligned) {
322 MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
323 } else {
324 MmioWrite64 ((UINTN)Address, ReadUnaligned64 ((UINT64 *)Uint8Buffer));
325 }
326 }
327 }
328 return EFI_SUCCESS;
329 }
330
331 /**
332 Reads I/O registers.
333
334 @param[in] PeiServices An indirect pointer to the PEI Services Table
335 published by the PEI Foundation.
336 @param[in] This Pointer to local data for the interface.
337 @param[in] Width The width of the access. Enumerated in bytes.
338 @param[in] Address The physical address of the access.
339 @param[in] Count The number of accesses to perform.
340 @param[out] Buffer A pointer to the buffer of data.
341
342 @retval EFI_SUCCESS The function completed successfully.
343 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
344 @retval EFI_INVALID_PARAMETER Buffer is NULL.
345 @retval EFI_UNSUPPORTED The address range specified by Address, Width,
346 and Count is not valid for this EFI system.
347
348 **/
349 EFI_STATUS
350 EFIAPI
351 CpuIoServiceRead (
352 IN CONST EFI_PEI_SERVICES **PeiServices,
353 IN CONST EFI_PEI_CPU_IO_PPI *This,
354 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
355 IN UINT64 Address,
356 IN UINTN Count,
357 OUT VOID *Buffer
358 )
359 {
360 EFI_STATUS Status;
361 UINT8 InStride;
362 UINT8 OutStride;
363 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
364 BOOLEAN Aligned;
365 UINT8 *Uint8Buffer;
366
367 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
368 if (EFI_ERROR (Status)) {
369 return Status;
370 }
371
372 //
373 // Select loop based on the width of the transfer
374 //
375 InStride = mInStride[Width];
376 OutStride = mOutStride[Width];
377 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
378 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
379 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
380 if (OperationWidth == EfiPeiCpuIoWidthUint8) {
381 *Uint8Buffer = IoRead8 ((UINTN)Address);
382 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
383 if (Aligned) {
384 *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
385 } else {
386 WriteUnaligned16 ((UINT16 *)Uint8Buffer, IoRead16 ((UINTN)Address));
387 }
388 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
389 if (Aligned) {
390 *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
391 } else {
392 WriteUnaligned32 ((UINT32 *)Uint8Buffer, IoRead32 ((UINTN)Address));
393 }
394 }
395 }
396
397 return EFI_SUCCESS;
398 }
399
400 /**
401 Write I/O registers.
402
403 @param[in] PeiServices An indirect pointer to the PEI Services Table
404 published by the PEI Foundation.
405 @param[in] This Pointer to local data for the interface.
406 @param[in] Width The width of the access. Enumerated in bytes.
407 @param[in] Address The physical address of the access.
408 @param[in] Count The number of accesses to perform.
409 @param[in] Buffer A pointer to the buffer of data.
410
411 @retval EFI_SUCCESS The function completed successfully.
412 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
413 @retval EFI_INVALID_PARAMETER Buffer is NULL.
414 @retval EFI_UNSUPPORTED The address range specified by Address, Width,
415 and Count is not valid for this EFI system.
416
417 **/
418 EFI_STATUS
419 EFIAPI
420 CpuIoServiceWrite (
421 IN CONST EFI_PEI_SERVICES **PeiServices,
422 IN CONST EFI_PEI_CPU_IO_PPI *This,
423 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
424 IN UINT64 Address,
425 IN UINTN Count,
426 IN VOID *Buffer
427 )
428 {
429 EFI_STATUS Status;
430 UINT8 InStride;
431 UINT8 OutStride;
432 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
433 BOOLEAN Aligned;
434 UINT8 *Uint8Buffer;
435
436 //
437 // Make sure the parameters are valid
438 //
439 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
440 if (EFI_ERROR (Status)) {
441 return Status;
442 }
443
444 //
445 // Select loop based on the width of the transfer
446 //
447 InStride = mInStride[Width];
448 OutStride = mOutStride[Width];
449 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
450 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
451 for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
452 if (OperationWidth == EfiPeiCpuIoWidthUint8) {
453 IoWrite8 ((UINTN)Address, *Uint8Buffer);
454 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
455 if (Aligned) {
456 IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
457 } else {
458 IoWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
459 }
460 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
461 if (Aligned) {
462 IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
463 } else {
464 IoWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
465 }
466 }
467 }
468
469 return EFI_SUCCESS;
470 }
471
472 /**
473 8-bit I/O read operations.
474
475 @param[in] PeiServices An indirect pointer to the PEI Services Table published
476 by the PEI Foundation.
477 @param[in] This Pointer to local data for the interface.
478 @param[in] Address The physical address of the access.
479
480 @return An 8-bit value returned from the I/O space.
481 **/
482 UINT8
483 EFIAPI
484 CpuIoRead8 (
485 IN CONST EFI_PEI_SERVICES **PeiServices,
486 IN CONST EFI_PEI_CPU_IO_PPI *This,
487 IN UINT64 Address
488 )
489 {
490 return IoRead8 ((UINTN)Address);
491 }
492
493 /**
494 16-bit I/O read operations.
495
496 @param[in] PeiServices An indirect pointer to the PEI Services Table published
497 by the PEI Foundation.
498 @param[in] This Pointer to local data for the interface.
499 @param[in] Address The physical address of the access.
500
501 @return A 16-bit value returned from the I/O space.
502
503 **/
504 UINT16
505 EFIAPI
506 CpuIoRead16 (
507 IN CONST EFI_PEI_SERVICES **PeiServices,
508 IN CONST EFI_PEI_CPU_IO_PPI *This,
509 IN UINT64 Address
510 )
511 {
512 return IoRead16 ((UINTN)Address);
513 }
514
515 /**
516 32-bit I/O read operations.
517
518 @param[in] PeiServices An indirect pointer to the PEI Services Table published
519 by the PEI Foundation.
520 @param[in] This Pointer to local data for the interface.
521 @param[in] Address The physical address of the access.
522
523 @return A 32-bit value returned from the I/O space.
524
525 **/
526 UINT32
527 EFIAPI
528 CpuIoRead32 (
529 IN CONST EFI_PEI_SERVICES **PeiServices,
530 IN CONST EFI_PEI_CPU_IO_PPI *This,
531 IN UINT64 Address
532 )
533 {
534 return IoRead32 ((UINTN)Address);
535 }
536
537 /**
538 64-bit I/O read operations.
539
540 @param[in] PeiServices An indirect pointer to the PEI Services Table published
541 by the PEI Foundation.
542 @param[in] This Pointer to local data for the interface.
543 @param[in] Address The physical address of the access.
544
545 @return A 64-bit value returned from the I/O space.
546
547 **/
548 UINT64
549 EFIAPI
550 CpuIoRead64 (
551 IN CONST EFI_PEI_SERVICES **PeiServices,
552 IN CONST EFI_PEI_CPU_IO_PPI *This,
553 IN UINT64 Address
554 )
555 {
556 return IoRead64 ((UINTN)Address);
557 }
558
559 /**
560 8-bit I/O write operations.
561
562 @param[in] PeiServices An indirect pointer to the PEI Services Table published
563 by the PEI Foundation.
564 @param[in] This Pointer to local data for the interface.
565 @param[in] Address The physical address of the access.
566 @param[in] Data The data to write.
567
568 **/
569 VOID
570 EFIAPI
571 CpuIoWrite8 (
572 IN CONST EFI_PEI_SERVICES **PeiServices,
573 IN CONST EFI_PEI_CPU_IO_PPI *This,
574 IN UINT64 Address,
575 IN UINT8 Data
576 )
577 {
578 IoWrite8 ((UINTN)Address, Data);
579 }
580
581 /**
582 16-bit I/O write operations.
583
584 @param[in] PeiServices An indirect pointer to the PEI Services Table published
585 by the PEI Foundation.
586 @param[in] This Pointer to local data for the interface.
587 @param[in] Address The physical address of the access.
588 @param[in] Data The data to write.
589
590 **/
591 VOID
592 EFIAPI
593 CpuIoWrite16 (
594 IN CONST EFI_PEI_SERVICES **PeiServices,
595 IN CONST EFI_PEI_CPU_IO_PPI *This,
596 IN UINT64 Address,
597 IN UINT16 Data
598 )
599 {
600 IoWrite16 ((UINTN)Address, Data);
601 }
602
603 /**
604 32-bit I/O write operations.
605
606 @param[in] PeiServices An indirect pointer to the PEI Services Table published
607 by the PEI Foundation.
608 @param[in] This Pointer to local data for the interface.
609 @param[in] Address The physical address of the access.
610 @param[in] Data The data to write.
611
612 **/
613 VOID
614 EFIAPI
615 CpuIoWrite32 (
616 IN CONST EFI_PEI_SERVICES **PeiServices,
617 IN CONST EFI_PEI_CPU_IO_PPI *This,
618 IN UINT64 Address,
619 IN UINT32 Data
620 )
621 {
622 IoWrite32 ((UINTN)Address, Data);
623 }
624
625 /**
626 64-bit I/O write operations.
627
628 @param[in] PeiServices An indirect pointer to the PEI Services Table published
629 by the PEI Foundation.
630 @param[in] This Pointer to local data for the interface.
631 @param[in] Address The physical address of the access.
632 @param[in] Data The data to write.
633
634 **/
635 VOID
636 EFIAPI
637 CpuIoWrite64 (
638 IN CONST EFI_PEI_SERVICES **PeiServices,
639 IN CONST EFI_PEI_CPU_IO_PPI *This,
640 IN UINT64 Address,
641 IN UINT64 Data
642 )
643 {
644 IoWrite64 ((UINTN)Address, Data);
645 }
646
647 /**
648 8-bit memory read operations.
649
650 @param[in] PeiServices An indirect pointer to the PEI Services Table published
651 by the PEI Foundation.
652 @param[in] This Pointer to local data for the interface.
653 @param[in] Address The physical address of the access.
654
655 @return An 8-bit value returned from the memory space.
656
657 **/
658 UINT8
659 EFIAPI
660 CpuMemRead8 (
661 IN CONST EFI_PEI_SERVICES **PeiServices,
662 IN CONST EFI_PEI_CPU_IO_PPI *This,
663 IN UINT64 Address
664 )
665 {
666 return MmioRead8 ((UINTN)Address);
667 }
668
669 /**
670 16-bit memory read operations.
671
672 @param[in] PeiServices An indirect pointer to the PEI Services Table published
673 by the PEI Foundation.
674 @param[in] This Pointer to local data for the interface.
675 @param[in] Address The physical address of the access.
676
677 @return A 16-bit value returned from the memory space.
678
679 **/
680 UINT16
681 EFIAPI
682 CpuMemRead16 (
683 IN CONST EFI_PEI_SERVICES **PeiServices,
684 IN CONST EFI_PEI_CPU_IO_PPI *This,
685 IN UINT64 Address
686 )
687 {
688 return MmioRead16 ((UINTN)Address);
689 }
690
691 /**
692 32-bit memory read operations.
693
694 @param[in] PeiServices An indirect pointer to the PEI Services Table published
695 by the PEI Foundation.
696 @param[in] This Pointer to local data for the interface.
697 @param[in] Address The physical address of the access.
698
699 @return A 32-bit value returned from the memory space.
700
701 **/
702 UINT32
703 EFIAPI
704 CpuMemRead32 (
705 IN CONST EFI_PEI_SERVICES **PeiServices,
706 IN CONST EFI_PEI_CPU_IO_PPI *This,
707 IN UINT64 Address
708 )
709 {
710 return MmioRead32 ((UINTN)Address);
711 }
712
713 /**
714 64-bit memory read operations.
715
716 @param[in] PeiServices An indirect pointer to the PEI Services Table published
717 by the PEI Foundation.
718 @param[in] This Pointer to local data for the interface.
719 @param[in] Address The physical address of the access.
720
721 @return A 64-bit value returned from the memory space.
722
723 **/
724 UINT64
725 EFIAPI
726 CpuMemRead64 (
727 IN CONST EFI_PEI_SERVICES **PeiServices,
728 IN CONST EFI_PEI_CPU_IO_PPI *This,
729 IN UINT64 Address
730 )
731 {
732 return MmioRead64 ((UINTN)Address);
733 }
734
735 /**
736 8-bit memory write operations.
737
738 @param[in] PeiServices An indirect pointer to the PEI Services Table published
739 by the PEI Foundation.
740 @param[in] This Pointer to local data for the interface.
741 @param[in] Address The physical address of the access.
742 @param[in] Data The data to write.
743
744 **/
745 VOID
746 EFIAPI
747 CpuMemWrite8 (
748 IN CONST EFI_PEI_SERVICES **PeiServices,
749 IN CONST EFI_PEI_CPU_IO_PPI *This,
750 IN UINT64 Address,
751 IN UINT8 Data
752 )
753 {
754 MmioWrite8 ((UINTN)Address, Data);
755 }
756
757 /**
758 16-bit memory write operations.
759
760 @param[in] PeiServices An indirect pointer to the PEI Services Table published
761 by the PEI Foundation.
762 @param[in] This Pointer to local data for the interface.
763 @param[in] Address The physical address of the access.
764 @param[in] Data The data to write.
765
766 **/
767 VOID
768 EFIAPI
769 CpuMemWrite16 (
770 IN CONST EFI_PEI_SERVICES **PeiServices,
771 IN CONST EFI_PEI_CPU_IO_PPI *This,
772 IN UINT64 Address,
773 IN UINT16 Data
774 )
775 {
776 MmioWrite16 ((UINTN)Address, Data);
777 }
778
779 /**
780 32-bit memory write operations.
781
782 @param[in] PeiServices An indirect pointer to the PEI Services Table published
783 by the PEI Foundation.
784 @param[in] This Pointer to local data for the interface.
785 @param[in] Address The physical address of the access.
786 @param[in] Data The data to write.
787
788 **/
789 VOID
790 EFIAPI
791 CpuMemWrite32 (
792 IN CONST EFI_PEI_SERVICES **PeiServices,
793 IN CONST EFI_PEI_CPU_IO_PPI *This,
794 IN UINT64 Address,
795 IN UINT32 Data
796 )
797 {
798 MmioWrite32 ((UINTN)Address, Data);
799 }
800
801 /**
802 64-bit memory write operations.
803
804 @param[in] PeiServices An indirect pointer to the PEI Services Table published
805 by the PEI Foundation.
806 @param[in] This Pointer to local data for the interface.
807 @param[in] Address The physical address of the access.
808 @param[in] Data The data to write.
809
810 **/
811 VOID
812 EFIAPI
813 CpuMemWrite64 (
814 IN CONST EFI_PEI_SERVICES **PeiServices,
815 IN CONST EFI_PEI_CPU_IO_PPI *This,
816 IN UINT64 Address,
817 IN UINT64 Data
818 )
819 {
820 MmioWrite64 ((UINTN)Address, Data);
821 }
822
823 /**
824 The Entry point of the CPU I/O PEIM
825
826 This function is the Entry point of the CPU I/O PEIM which installs CpuIoPpi.
827
828 @param[in] FileHandle Pointer to image file handle.
829 @param[in] PeiServices Pointer to PEI Services Table
830
831 @retval EFI_SUCCESS CPU I/O PPI successfully installed
832
833 **/
834 EFI_STATUS
835 EFIAPI
836 CpuIoInitialize (
837 IN EFI_PEI_FILE_HANDLE FileHandle,
838 IN CONST EFI_PEI_SERVICES **PeiServices
839 )
840 {
841 EFI_STATUS Status;
842
843 //
844 // Register so it will be automatically shadowed to memory
845 //
846 Status = PeiServicesRegisterForShadow (FileHandle);
847
848 //
849 // Make CpuIo pointer in PeiService table point to gCpuIoPpi
850 //
851 (*((EFI_PEI_SERVICES **)PeiServices))->CpuIo = &gCpuIoPpi;
852
853 if (Status == EFI_ALREADY_STARTED) {
854 //
855 // Shadow completed and running from memory
856 //
857 DEBUG ((EFI_D_INFO, "CpuIO PPI has been loaded into memory. Reinstalled PPI=0x%x\n", &gCpuIoPpi));
858 } else {
859 Status = PeiServicesInstallPpi (&gPpiList);
860 ASSERT_EFI_ERROR (Status);
861 }
862
863 return EFI_SUCCESS;
864 }