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