PciCpuIo2Dxe.c 20 KB

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