CpuIo2Dxe.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. /** @file
  2. Produces the CPU I/O 2 Protocol.
  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 "CpuIo2Dxe.h"
  8. //
  9. // Handle for the CPU I/O 2 Protocol
  10. //
  11. EFI_HANDLE mHandle = NULL;
  12. //
  13. // CPU I/O 2 Protocol instance
  14. //
  15. EFI_CPU_IO2_PROTOCOL mCpuIo2 = {
  16. {
  17. CpuMemoryServiceRead,
  18. CpuMemoryServiceWrite
  19. },
  20. {
  21. CpuIoServiceRead,
  22. CpuIoServiceWrite
  23. }
  24. };
  25. //
  26. // Lookup table for increment values based on transfer widths
  27. //
  28. UINT8 mInStride[] = {
  29. 1, // EfiCpuIoWidthUint8
  30. 2, // EfiCpuIoWidthUint16
  31. 4, // EfiCpuIoWidthUint32
  32. 8, // EfiCpuIoWidthUint64
  33. 0, // EfiCpuIoWidthFifoUint8
  34. 0, // EfiCpuIoWidthFifoUint16
  35. 0, // EfiCpuIoWidthFifoUint32
  36. 0, // EfiCpuIoWidthFifoUint64
  37. 1, // EfiCpuIoWidthFillUint8
  38. 2, // EfiCpuIoWidthFillUint16
  39. 4, // EfiCpuIoWidthFillUint32
  40. 8 // EfiCpuIoWidthFillUint64
  41. };
  42. //
  43. // Lookup table for increment values based on transfer widths
  44. //
  45. UINT8 mOutStride[] = {
  46. 1, // EfiCpuIoWidthUint8
  47. 2, // EfiCpuIoWidthUint16
  48. 4, // EfiCpuIoWidthUint32
  49. 8, // EfiCpuIoWidthUint64
  50. 1, // EfiCpuIoWidthFifoUint8
  51. 2, // EfiCpuIoWidthFifoUint16
  52. 4, // EfiCpuIoWidthFifoUint32
  53. 8, // EfiCpuIoWidthFifoUint64
  54. 0, // EfiCpuIoWidthFillUint8
  55. 0, // EfiCpuIoWidthFillUint16
  56. 0, // EfiCpuIoWidthFillUint32
  57. 0 // EfiCpuIoWidthFillUint64
  58. };
  59. /**
  60. Check parameters to a CPU I/O 2 Protocol service request.
  61. The I/O operations are carried out exactly as requested. The caller is responsible
  62. for satisfying any alignment and I/O width restrictions that a PI System on a
  63. platform might require. For example on some platforms, width requests of
  64. EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
  65. be handled by the driver.
  66. @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.
  67. @param[in] Width Signifies the width of the I/O or Memory operation.
  68. @param[in] Address The base address of the I/O operation.
  69. @param[in] Count The number of I/O operations to perform. The number of
  70. bytes moved is Width size * Count, starting at Address.
  71. @param[in] Buffer For read operations, the destination buffer to store the results.
  72. For write operations, the source buffer from which to write data.
  73. @retval EFI_SUCCESS The parameters for this request pass the checks.
  74. @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
  75. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  76. @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
  77. @retval EFI_UNSUPPORTED The address range specified by Address, Width,
  78. and Count is not valid for this PI system.
  79. **/
  80. EFI_STATUS
  81. CpuIoCheckParameter (
  82. IN BOOLEAN MmioOperation,
  83. IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
  84. IN UINT64 Address,
  85. IN UINTN Count,
  86. IN VOID *Buffer
  87. )
  88. {
  89. UINT64 MaxCount;
  90. UINT64 Limit;
  91. //
  92. // Check to see if Buffer is NULL
  93. //
  94. if (Buffer == NULL) {
  95. return EFI_INVALID_PARAMETER;
  96. }
  97. //
  98. // Check to see if Width is in the valid range
  99. //
  100. if ((UINT32)Width >= EfiCpuIoWidthMaximum) {
  101. return EFI_INVALID_PARAMETER;
  102. }
  103. //
  104. // For FIFO type, the target address won't increase during the access,
  105. // so treat Count as 1
  106. //
  107. if ((Width >= EfiCpuIoWidthFifoUint8) && (Width <= EfiCpuIoWidthFifoUint64)) {
  108. Count = 1;
  109. }
  110. //
  111. // Check to see if Width is in the valid range for I/O Port operations
  112. //
  113. Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
  114. if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {
  115. return EFI_INVALID_PARAMETER;
  116. }
  117. //
  118. // Check to see if Address is aligned
  119. //
  120. if ((Address & ((UINT64)mInStride[Width] - 1)) != 0) {
  121. return EFI_UNSUPPORTED;
  122. }
  123. //
  124. // Check to see if any address associated with this transfer exceeds the maximum
  125. // allowed address. The maximum address implied by the parameters passed in is
  126. // Address + Size * Count. If the following condition is met, then the transfer
  127. // is not supported.
  128. //
  129. // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
  130. //
  131. // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
  132. // can also be the maximum integer value supported by the CPU, this range
  133. // check must be adjusted to avoid all oveflow conditions.
  134. //
  135. // The following form of the range check is equivalent but assumes that
  136. // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
  137. //
  138. Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
  139. if (Count == 0) {
  140. if (Address > Limit) {
  141. return EFI_UNSUPPORTED;
  142. }
  143. } else {
  144. MaxCount = RShiftU64 (Limit, Width);
  145. if (MaxCount < (Count - 1)) {
  146. return EFI_UNSUPPORTED;
  147. }
  148. if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
  149. return EFI_UNSUPPORTED;
  150. }
  151. }
  152. //
  153. // Check to see if Buffer is aligned
  154. // (IA-32 allows UINT64 and INT64 data types to be 32-bit aligned.)
  155. //
  156. if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) {
  157. return EFI_UNSUPPORTED;
  158. }
  159. return EFI_SUCCESS;
  160. }
  161. /**
  162. Reads memory-mapped registers.
  163. The I/O operations are carried out exactly as requested. The caller is responsible
  164. for satisfying any alignment and I/O width restrictions that a PI System on a
  165. platform might require. For example on some platforms, width requests of
  166. EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
  167. be handled by the driver.
  168. If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
  169. or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
  170. each of the Count operations that is performed.
  171. If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
  172. EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
  173. incremented for each of the Count operations that is performed. The read or
  174. write operation is performed Count times on the same Address.
  175. If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
  176. EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
  177. incremented for each of the Count operations that is performed. The read or
  178. write operation is performed Count times from the first element of Buffer.
  179. @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
  180. @param[in] Width Signifies the width of the I/O or Memory operation.
  181. @param[in] Address The base address of the I/O operation.
  182. @param[in] Count The number of I/O operations to perform. The number of
  183. bytes moved is Width size * Count, starting at Address.
  184. @param[out] Buffer For read operations, the destination buffer to store the results.
  185. For write operations, the source buffer from which to write data.
  186. @retval EFI_SUCCESS The data was read from or written to the PI system.
  187. @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
  188. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  189. @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
  190. @retval EFI_UNSUPPORTED The address range specified by Address, Width,
  191. and Count is not valid for this PI system.
  192. **/
  193. EFI_STATUS
  194. EFIAPI
  195. CpuMemoryServiceRead (
  196. IN EFI_CPU_IO2_PROTOCOL *This,
  197. IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
  198. IN UINT64 Address,
  199. IN UINTN Count,
  200. OUT VOID *Buffer
  201. )
  202. {
  203. EFI_STATUS Status;
  204. UINT8 InStride;
  205. UINT8 OutStride;
  206. EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
  207. UINT8 *Uint8Buffer;
  208. Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
  209. if (EFI_ERROR (Status)) {
  210. return Status;
  211. }
  212. //
  213. // Select loop based on the width of the transfer
  214. //
  215. InStride = mInStride[Width];
  216. OutStride = mOutStride[Width];
  217. OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
  218. for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
  219. if (OperationWidth == EfiCpuIoWidthUint8) {
  220. *Uint8Buffer = MmioRead8 ((UINTN)Address);
  221. } else if (OperationWidth == EfiCpuIoWidthUint16) {
  222. *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
  223. } else if (OperationWidth == EfiCpuIoWidthUint32) {
  224. *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
  225. } else if (OperationWidth == EfiCpuIoWidthUint64) {
  226. *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
  227. }
  228. }
  229. return EFI_SUCCESS;
  230. }
  231. /**
  232. Writes memory-mapped registers.
  233. The I/O operations are carried out exactly as requested. The caller is responsible
  234. for satisfying any alignment and I/O width restrictions that a PI System on a
  235. platform might require. For example on some platforms, width requests of
  236. EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
  237. be handled by the driver.
  238. If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
  239. or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
  240. each of the Count operations that is performed.
  241. If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
  242. EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
  243. incremented for each of the Count operations that is performed. The read or
  244. write operation is performed Count times on the same Address.
  245. If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
  246. EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
  247. incremented for each of the Count operations that is performed. The read or
  248. write operation is performed Count times from the first element of Buffer.
  249. @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
  250. @param[in] Width Signifies the width of the I/O or Memory operation.
  251. @param[in] Address The base address of the I/O operation.
  252. @param[in] Count The number of I/O operations to perform. The number of
  253. bytes moved is Width size * Count, starting at Address.
  254. @param[in] Buffer For read operations, the destination buffer to store the results.
  255. For write operations, the source buffer from which to write data.
  256. @retval EFI_SUCCESS The data was read from or written to the PI system.
  257. @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
  258. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  259. @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
  260. @retval EFI_UNSUPPORTED The address range specified by Address, Width,
  261. and Count is not valid for this PI system.
  262. **/
  263. EFI_STATUS
  264. EFIAPI
  265. CpuMemoryServiceWrite (
  266. IN EFI_CPU_IO2_PROTOCOL *This,
  267. IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
  268. IN UINT64 Address,
  269. IN UINTN Count,
  270. IN VOID *Buffer
  271. )
  272. {
  273. EFI_STATUS Status;
  274. UINT8 InStride;
  275. UINT8 OutStride;
  276. EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
  277. UINT8 *Uint8Buffer;
  278. Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
  279. if (EFI_ERROR (Status)) {
  280. return Status;
  281. }
  282. //
  283. // Select loop based on the width of the transfer
  284. //
  285. InStride = mInStride[Width];
  286. OutStride = mOutStride[Width];
  287. OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
  288. for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
  289. if (OperationWidth == EfiCpuIoWidthUint8) {
  290. MmioWrite8 ((UINTN)Address, *Uint8Buffer);
  291. } else if (OperationWidth == EfiCpuIoWidthUint16) {
  292. MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
  293. } else if (OperationWidth == EfiCpuIoWidthUint32) {
  294. MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
  295. } else if (OperationWidth == EfiCpuIoWidthUint64) {
  296. MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
  297. }
  298. }
  299. return EFI_SUCCESS;
  300. }
  301. /**
  302. Reads I/O registers.
  303. The I/O operations are carried out exactly as requested. The caller is responsible
  304. for satisfying any alignment and I/O width restrictions that a PI System on a
  305. platform might require. For example on some platforms, width requests of
  306. EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
  307. be handled by the driver.
  308. If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
  309. or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
  310. each of the Count operations that is performed.
  311. If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
  312. EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
  313. incremented for each of the Count operations that is performed. The read or
  314. write operation is performed Count times on the same Address.
  315. If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
  316. EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
  317. incremented for each of the Count operations that is performed. The read or
  318. write operation is performed Count times from the first element of Buffer.
  319. @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
  320. @param[in] Width Signifies the width of the I/O or Memory operation.
  321. @param[in] Address The base address of the I/O operation.
  322. @param[in] Count The number of I/O operations to perform. The number of
  323. bytes moved is Width size * Count, starting at Address.
  324. @param[out] Buffer For read operations, the destination buffer to store the results.
  325. For write operations, the source buffer from which to write data.
  326. @retval EFI_SUCCESS The data was read from or written to the PI system.
  327. @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
  328. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  329. @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
  330. @retval EFI_UNSUPPORTED The address range specified by Address, Width,
  331. and Count is not valid for this PI system.
  332. **/
  333. EFI_STATUS
  334. EFIAPI
  335. CpuIoServiceRead (
  336. IN EFI_CPU_IO2_PROTOCOL *This,
  337. IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
  338. IN UINT64 Address,
  339. IN UINTN Count,
  340. OUT VOID *Buffer
  341. )
  342. {
  343. EFI_STATUS Status;
  344. UINT8 InStride;
  345. UINT8 OutStride;
  346. EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
  347. UINT8 *Uint8Buffer;
  348. Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
  349. if (EFI_ERROR (Status)) {
  350. return Status;
  351. }
  352. //
  353. // Select loop based on the width of the transfer
  354. //
  355. InStride = mInStride[Width];
  356. OutStride = mOutStride[Width];
  357. OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
  358. //
  359. // Fifo operations supported for (mInStride[Width] == 0)
  360. //
  361. if (InStride == 0) {
  362. switch (OperationWidth) {
  363. case EfiCpuIoWidthUint8:
  364. IoReadFifo8 ((UINTN)Address, Count, Buffer);
  365. return EFI_SUCCESS;
  366. case EfiCpuIoWidthUint16:
  367. IoReadFifo16 ((UINTN)Address, Count, Buffer);
  368. return EFI_SUCCESS;
  369. case EfiCpuIoWidthUint32:
  370. IoReadFifo32 ((UINTN)Address, Count, Buffer);
  371. return EFI_SUCCESS;
  372. default:
  373. //
  374. // The CpuIoCheckParameter call above will ensure that this
  375. // path is not taken.
  376. //
  377. ASSERT (FALSE);
  378. break;
  379. }
  380. }
  381. for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
  382. if (OperationWidth == EfiCpuIoWidthUint8) {
  383. *Uint8Buffer = IoRead8 ((UINTN)Address);
  384. } else if (OperationWidth == EfiCpuIoWidthUint16) {
  385. *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
  386. } else if (OperationWidth == EfiCpuIoWidthUint32) {
  387. *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
  388. }
  389. }
  390. return EFI_SUCCESS;
  391. }
  392. /**
  393. Write I/O registers.
  394. The I/O operations are carried out exactly as requested. The caller is responsible
  395. for satisfying any alignment and I/O width restrictions that a PI System on a
  396. platform might require. For example on some platforms, width requests of
  397. EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
  398. be handled by the driver.
  399. If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
  400. or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
  401. each of the Count operations that is performed.
  402. If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
  403. EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
  404. incremented for each of the Count operations that is performed. The read or
  405. write operation is performed Count times on the same Address.
  406. If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
  407. EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
  408. incremented for each of the Count operations that is performed. The read or
  409. write operation is performed Count times from the first element of Buffer.
  410. @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.
  411. @param[in] Width Signifies the width of the I/O or Memory operation.
  412. @param[in] Address The base address of the I/O operation.
  413. @param[in] Count The number of I/O operations to perform. The number of
  414. bytes moved is Width size * Count, starting at Address.
  415. @param[in] Buffer For read operations, the destination buffer to store the results.
  416. For write operations, the source buffer from which to write data.
  417. @retval EFI_SUCCESS The data was read from or written to the PI system.
  418. @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
  419. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  420. @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
  421. @retval EFI_UNSUPPORTED The address range specified by Address, Width,
  422. and Count is not valid for this PI system.
  423. **/
  424. EFI_STATUS
  425. EFIAPI
  426. CpuIoServiceWrite (
  427. IN EFI_CPU_IO2_PROTOCOL *This,
  428. IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
  429. IN UINT64 Address,
  430. IN UINTN Count,
  431. IN VOID *Buffer
  432. )
  433. {
  434. EFI_STATUS Status;
  435. UINT8 InStride;
  436. UINT8 OutStride;
  437. EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
  438. UINT8 *Uint8Buffer;
  439. //
  440. // Make sure the parameters are valid
  441. //
  442. Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
  443. if (EFI_ERROR (Status)) {
  444. return Status;
  445. }
  446. //
  447. // Select loop based on the width of the transfer
  448. //
  449. InStride = mInStride[Width];
  450. OutStride = mOutStride[Width];
  451. OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
  452. //
  453. // Fifo operations supported for (mInStride[Width] == 0)
  454. //
  455. if (InStride == 0) {
  456. switch (OperationWidth) {
  457. case EfiCpuIoWidthUint8:
  458. IoWriteFifo8 ((UINTN)Address, Count, Buffer);
  459. return EFI_SUCCESS;
  460. case EfiCpuIoWidthUint16:
  461. IoWriteFifo16 ((UINTN)Address, Count, Buffer);
  462. return EFI_SUCCESS;
  463. case EfiCpuIoWidthUint32:
  464. IoWriteFifo32 ((UINTN)Address, Count, Buffer);
  465. return EFI_SUCCESS;
  466. default:
  467. //
  468. // The CpuIoCheckParameter call above will ensure that this
  469. // path is not taken.
  470. //
  471. ASSERT (FALSE);
  472. break;
  473. }
  474. }
  475. for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
  476. if (OperationWidth == EfiCpuIoWidthUint8) {
  477. IoWrite8 ((UINTN)Address, *Uint8Buffer);
  478. } else if (OperationWidth == EfiCpuIoWidthUint16) {
  479. IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
  480. } else if (OperationWidth == EfiCpuIoWidthUint32) {
  481. IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
  482. }
  483. }
  484. return EFI_SUCCESS;
  485. }
  486. /**
  487. The user Entry Point for module CpuIo2Dxe. The user code starts with this function.
  488. @param[in] ImageHandle The firmware allocated handle for the EFI image.
  489. @param[in] SystemTable A pointer to the EFI System Table.
  490. @retval EFI_SUCCESS The entry point is executed successfully.
  491. @retval other Some error occurs when executing this entry point.
  492. **/
  493. EFI_STATUS
  494. EFIAPI
  495. CpuIo2Initialize (
  496. IN EFI_HANDLE ImageHandle,
  497. IN EFI_SYSTEM_TABLE *SystemTable
  498. )
  499. {
  500. EFI_STATUS Status;
  501. ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);
  502. Status = gBS->InstallMultipleProtocolInterfaces (
  503. &mHandle,
  504. &gEfiCpuIo2ProtocolGuid,
  505. &mCpuIo2,
  506. NULL
  507. );
  508. ASSERT_EFI_ERROR (Status);
  509. return Status;
  510. }