CpuIoPei.c 27 KB

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