CpuIo.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*++ @file
  2. This is the code that publishes the CPU I/O Protocol.
  3. The intent herein is to have a single I/O service that can load
  4. as early as possible, extend into runtime, and be layered upon by
  5. the implementations of architectural protocols and the PCI Root
  6. Bridge I/O Protocol.
  7. Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
  8. Portions copyright (c) 2011, Apple Inc. All rights reserved.
  9. SPDX-License-Identifier: BSD-2-Clause-Patent
  10. **/
  11. #include <PiDxe.h>
  12. #include <Protocol/Cpu.h>
  13. #include <Protocol/CpuIo2.h>
  14. #include <Library/BaseLib.h>
  15. #include <Library/DebugLib.h>
  16. #include <Library/HiiLib.h>
  17. #include <Library/UefiLib.h>
  18. #include <Library/UefiDriverEntryPoint.h>
  19. #include <Library/BaseMemoryLib.h>
  20. #include <Library/MemoryAllocationLib.h>
  21. #include <Library/UefiBootServicesTableLib.h>
  22. #include <CpuDriver.h>
  23. #define IA32_MAX_IO_ADDRESS 0xFFFF
  24. #define IA32_MAX_MEM_ADDRESS 0xFFFFFFFF
  25. EFI_STATUS
  26. CpuIoCheckAddressRange (
  27. IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
  28. IN UINT64 Address,
  29. IN UINTN Count,
  30. IN VOID *Buffer,
  31. IN UINT64 Limit
  32. );
  33. EFI_STATUS
  34. EFIAPI
  35. CpuMemoryServiceRead (
  36. IN EFI_CPU_IO2_PROTOCOL *This,
  37. IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
  38. IN UINT64 Address,
  39. IN UINTN Count,
  40. IN OUT VOID *Buffer
  41. )
  42. /*++
  43. Routine Description:
  44. Perform the Memory Access Read service for the CPU I/O Protocol
  45. Arguments:
  46. Pointer to an instance of the CPU I/O Protocol
  47. Width of the Memory Access
  48. Address of the Memory access
  49. Count of the number of accesses to perform
  50. Pointer to the buffer to read or write from memory
  51. Returns:
  52. Status
  53. EFI_SUCCESS - The data was read from or written to the EFI
  54. System.
  55. EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
  56. EFI_INVALID_PARAMETER - Buffer is NULL.
  57. EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
  58. EFI_UNSUPPORTED - The address range specified by Address, Width,
  59. and Count is not valid for this EFI System.
  60. **/
  61. {
  62. EFI_STATUS Status;
  63. if (!Buffer) {
  64. return EFI_INVALID_PARAMETER;
  65. }
  66. Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
  67. if (EFI_ERROR (Status)) {
  68. return Status;
  69. }
  70. //
  71. // Do nothing for Nt32 version
  72. //
  73. return EFI_SUCCESS;
  74. }
  75. EFI_STATUS
  76. EFIAPI
  77. CpuMemoryServiceWrite (
  78. IN EFI_CPU_IO2_PROTOCOL *This,
  79. IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
  80. IN UINT64 Address,
  81. IN UINTN Count,
  82. IN OUT VOID *Buffer
  83. )
  84. /*++
  85. Routine Description:
  86. Perform the Memory Access Read service for the CPU I/O Protocol
  87. Arguments:
  88. Pointer to an instance of the CPU I/O Protocol
  89. Width of the Memory Access
  90. Address of the Memory access
  91. Count of the number of accesses to perform
  92. Pointer to the buffer to read or write from memory
  93. Returns:
  94. Status
  95. EFI_SUCCESS - The data was read from or written to the EFI System.
  96. EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
  97. EFI_INVALID_PARAMETER - Buffer is NULL.
  98. EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
  99. EFI_UNSUPPORTED - The address range specified by Address, Width, and
  100. Count is not valid for this EFI System.
  101. **/
  102. {
  103. EFI_STATUS Status;
  104. if (!Buffer) {
  105. return EFI_INVALID_PARAMETER;
  106. }
  107. Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
  108. if (EFI_ERROR (Status)) {
  109. return Status;
  110. }
  111. //
  112. // Do nothing for Nt32 version
  113. //
  114. return EFI_SUCCESS;
  115. }
  116. EFI_STATUS
  117. EFIAPI
  118. CpuIoServiceRead (
  119. IN EFI_CPU_IO2_PROTOCOL *This,
  120. IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
  121. IN UINT64 UserAddress,
  122. IN UINTN Count,
  123. IN OUT VOID *UserBuffer
  124. )
  125. /*++
  126. Routine Description:
  127. This is the service that implements the I/O read
  128. Arguments:
  129. Pointer to an instance of the CPU I/O Protocol
  130. Width of the Memory Access
  131. Address of the I/O access
  132. Count of the number of accesses to perform
  133. Pointer to the buffer to read or write from I/O space
  134. Returns:
  135. Status
  136. EFI_SUCCESS - The data was read from or written to the EFI System.
  137. EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
  138. EFI_INVALID_PARAMETER - Buffer is NULL.
  139. EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
  140. EFI_UNSUPPORTED - The address range specified by Address, Width, and
  141. Count is not valid for this EFI System.
  142. **/
  143. {
  144. UINTN Address;
  145. EFI_STATUS Status;
  146. if (!UserBuffer) {
  147. return EFI_INVALID_PARAMETER;
  148. }
  149. Address = (UINTN)UserAddress;
  150. if (Width >= EfiCpuIoWidthMaximum) {
  151. return EFI_INVALID_PARAMETER;
  152. }
  153. Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
  154. if (EFI_ERROR (Status)) {
  155. return Status;
  156. }
  157. //
  158. // Do nothing for Nt32 version
  159. //
  160. return EFI_SUCCESS;
  161. }
  162. EFI_STATUS
  163. EFIAPI
  164. CpuIoServiceWrite (
  165. IN EFI_CPU_IO2_PROTOCOL *This,
  166. IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
  167. IN UINT64 UserAddress,
  168. IN UINTN Count,
  169. IN OUT VOID *UserBuffer
  170. )
  171. /*++
  172. Routine Description:
  173. This is the service that implements the I/O Write
  174. Arguments:
  175. Pointer to an instance of the CPU I/O Protocol
  176. Width of the Memory Access
  177. Address of the I/O access
  178. Count of the number of accesses to perform
  179. Pointer to the buffer to read or write from I/O space
  180. Returns:
  181. Status
  182. Status
  183. EFI_SUCCESS - The data was read from or written to the EFI System.
  184. EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
  185. EFI_INVALID_PARAMETER - Buffer is NULL.
  186. EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
  187. EFI_UNSUPPORTED - The address range specified by Address, Width, and
  188. Count is not valid for this EFI System.
  189. **/
  190. {
  191. UINTN Address;
  192. EFI_STATUS Status;
  193. if (!UserBuffer) {
  194. return EFI_INVALID_PARAMETER;
  195. }
  196. Address = (UINTN)UserAddress;
  197. if (Width >= EfiCpuIoWidthMaximum) {
  198. return EFI_INVALID_PARAMETER;
  199. }
  200. Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
  201. if (EFI_ERROR (Status)) {
  202. return Status;
  203. }
  204. //
  205. // Do nothing for Nt32 version
  206. //
  207. return EFI_SUCCESS;
  208. }
  209. /*++
  210. Routine Description:
  211. Arguments:
  212. Width - TODO: add argument description
  213. Address - TODO: add argument description
  214. Count - TODO: add argument description
  215. Buffer - TODO: add argument description
  216. Limit - TODO: add argument description
  217. Returns:
  218. EFI_UNSUPPORTED - TODO: Add description for return value
  219. EFI_UNSUPPORTED - TODO: Add description for return value
  220. EFI_UNSUPPORTED - TODO: Add description for return value
  221. EFI_SUCCESS - TODO: Add description for return value
  222. **/
  223. EFI_STATUS
  224. CpuIoCheckAddressRange (
  225. IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
  226. IN UINT64 Address,
  227. IN UINTN Count,
  228. IN VOID *Buffer,
  229. IN UINT64 Limit
  230. )
  231. {
  232. UINTN AlignMask;
  233. if (Address > Limit) {
  234. return EFI_UNSUPPORTED;
  235. }
  236. //
  237. // For FiFo type, the target address won't increase during the access, so treat count as 1
  238. //
  239. if ((Width >= EfiCpuIoWidthFifoUint8) && (Width <= EfiCpuIoWidthFifoUint64)) {
  240. Count = 1;
  241. }
  242. Width = Width & 0x03;
  243. if ((Address - 1 + LShiftU64 (Count, Width)) > Limit) {
  244. return EFI_UNSUPPORTED;
  245. }
  246. AlignMask = (1 << Width) - 1;
  247. if ((UINTN)Buffer & AlignMask) {
  248. return EFI_UNSUPPORTED;
  249. }
  250. return EFI_SUCCESS;
  251. }