PageRenderTime 21ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/UnixPkg/CpuRuntimeDxe/Cpu.c

https://bitbucket.org/incubaid/edk2
C | 556 lines | 235 code | 41 blank | 280 comment | 12 complexity | e09f9246c368d487de0d97551e96f8c9 MD5 | raw file
  1. /*++
  2. Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
  3. This program and the accompanying materials
  4. are licensed and made available under the terms and conditions of the BSD License
  5. which accompanies this distribution. The full text of the license may be found at
  6. http://opensource.org/licenses/bsd-license.php
  7. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  9. Module Name:
  10. Cpu.c
  11. Abstract:
  12. Unix Emulation Architectural Protocol Driver as defined in Tiano.
  13. This CPU module abstracts the interrupt subsystem of a platform and
  14. the CPU-specific setjump/long pair. Other services are not implemented
  15. in this driver.
  16. --*/
  17. #include <FrameworkDxe.h>
  18. #include <IndustryStandard/SmBios.h>
  19. #include <Protocol/Cpu.h>
  20. #include <Protocol/Smbios.h>
  21. #include <Guid/DataHubRecords.h>
  22. #include <Protocol/CpuIo2.h>
  23. #include <Protocol/FrameworkHii.h>
  24. #include <Protocol/UnixThunk.h>
  25. #include <Library/BaseLib.h>
  26. #include <Library/DebugLib.h>
  27. #include <Library/HiiLib.h>
  28. #include <Library/UefiLib.h>
  29. #include <Library/UefiDriverEntryPoint.h>
  30. #include <Library/BaseMemoryLib.h>
  31. #include <Library/MemoryAllocationLib.h>
  32. #include <Library/UefiBootServicesTableLib.h>
  33. #include <Library/UnixLib.h>
  34. #include "CpuDriver.h"
  35. #include "UnixDxe.h"
  36. #include <Protocol/UnixIo.h>
  37. #define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100
  38. CPU_ARCH_PROTOCOL_PRIVATE mCpuTemplate = {
  39. CPU_ARCH_PROT_PRIVATE_SIGNATURE,
  40. NULL,
  41. {
  42. UnixFlushCpuDataCache,
  43. UnixEnableInterrupt,
  44. UnixDisableInterrupt,
  45. UnixGetInterruptState,
  46. UnixInit,
  47. UnixRegisterInterruptHandler,
  48. UnixGetTimerValue,
  49. UnixSetMemoryAttributes,
  50. 0,
  51. 4
  52. },
  53. {
  54. {
  55. CpuMemoryServiceRead,
  56. CpuMemoryServiceWrite
  57. },
  58. {
  59. CpuIoServiceRead,
  60. CpuIoServiceWrite
  61. }
  62. },
  63. TRUE
  64. };
  65. //
  66. // Service routines for the driver
  67. //
  68. EFI_STATUS
  69. EFIAPI
  70. UnixFlushCpuDataCache (
  71. IN EFI_CPU_ARCH_PROTOCOL *This,
  72. IN EFI_PHYSICAL_ADDRESS Start,
  73. IN UINT64 Length,
  74. IN EFI_CPU_FLUSH_TYPE FlushType
  75. )
  76. /*++
  77. Routine Description:
  78. This routine would provide support for flushing the CPU data cache.
  79. In the case of UNIX emulation environment, this flushing is not necessary and
  80. is thus not implemented.
  81. Arguments:
  82. Pointer to CPU Architectural Protocol interface
  83. Start adddress in memory to flush
  84. Length of memory to flush
  85. Flush type
  86. Returns:
  87. Status
  88. EFI_SUCCESS
  89. --*/
  90. // TODO: This - add argument and description to function comment
  91. // TODO: FlushType - add argument and description to function comment
  92. // TODO: EFI_UNSUPPORTED - add return value to function comment
  93. {
  94. if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
  95. //
  96. // Only WB flush is supported. We actually need do nothing on UNIX emulator
  97. // environment. Classify this to follow EFI spec
  98. //
  99. return EFI_SUCCESS;
  100. }
  101. //
  102. // Other flush types are not supported by UNIX emulator
  103. //
  104. return EFI_UNSUPPORTED;
  105. }
  106. EFI_STATUS
  107. EFIAPI
  108. UnixEnableInterrupt (
  109. IN EFI_CPU_ARCH_PROTOCOL *This
  110. )
  111. /*++
  112. Routine Description:
  113. This routine provides support for emulation of the interrupt enable of the
  114. the system. For our purposes, CPU enable is just a BOOLEAN that the Timer
  115. Architectural Protocol observes in order to defer behaviour while in its
  116. emulated interrupt, or timer tick.
  117. Arguments:
  118. Pointer to CPU Architectural Protocol interface
  119. Returns:
  120. Status
  121. EFI_SUCCESS
  122. --*/
  123. // TODO: This - add argument and description to function comment
  124. {
  125. CPU_ARCH_PROTOCOL_PRIVATE *Private;
  126. Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
  127. Private->InterruptState = TRUE;
  128. gUnix->EnableInterrupt ();
  129. return EFI_SUCCESS;
  130. }
  131. EFI_STATUS
  132. EFIAPI
  133. UnixDisableInterrupt (
  134. IN EFI_CPU_ARCH_PROTOCOL *This
  135. )
  136. /*++
  137. Routine Description:
  138. This routine provides support for emulation of the interrupt disable of the
  139. the system. For our purposes, CPU enable is just a BOOLEAN that the Timer
  140. Architectural Protocol observes in order to defer behaviour while in its
  141. emulated interrupt, or timer tick.
  142. Arguments:
  143. Pointer to CPU Architectural Protocol interface
  144. Returns:
  145. Status
  146. EFI_SUCCESS
  147. --*/
  148. // TODO: This - add argument and description to function comment
  149. {
  150. CPU_ARCH_PROTOCOL_PRIVATE *Private;
  151. Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
  152. Private->InterruptState = FALSE;
  153. gUnix->DisableInterrupt ();
  154. return EFI_SUCCESS;
  155. }
  156. EFI_STATUS
  157. EFIAPI
  158. UnixGetInterruptState (
  159. IN EFI_CPU_ARCH_PROTOCOL *This,
  160. OUT BOOLEAN *State
  161. )
  162. /*++
  163. Routine Description:
  164. This routine provides support for emulation of the interrupt disable of the
  165. the system. For our purposes, CPU enable is just a BOOLEAN that the Timer
  166. Architectural Protocol observes in order to defer behaviour while in its
  167. emulated interrupt, or timer tick.
  168. Arguments:
  169. Pointer to CPU Architectural Protocol interface
  170. Returns:
  171. Status
  172. EFI_SUCCESS
  173. --*/
  174. // TODO: This - add argument and description to function comment
  175. // TODO: State - add argument and description to function comment
  176. // TODO: EFI_INVALID_PARAMETER - add return value to function comment
  177. {
  178. CPU_ARCH_PROTOCOL_PRIVATE *Private;
  179. if (State == NULL) {
  180. return EFI_INVALID_PARAMETER;
  181. }
  182. Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
  183. *State = Private->InterruptState;
  184. return EFI_SUCCESS;
  185. }
  186. EFI_STATUS
  187. EFIAPI
  188. UnixInit (
  189. IN EFI_CPU_ARCH_PROTOCOL *This,
  190. IN EFI_CPU_INIT_TYPE InitType
  191. )
  192. /*++
  193. Routine Description:
  194. This routine would support generation of a CPU INIT. At
  195. present, this code does not provide emulation.
  196. Arguments:
  197. Pointer to CPU Architectural Protocol interface
  198. INIT Type
  199. Returns:
  200. Status
  201. EFI_UNSUPPORTED - not yet implemented
  202. --*/
  203. // TODO: This - add argument and description to function comment
  204. // TODO: InitType - add argument and description to function comment
  205. {
  206. CPU_ARCH_PROTOCOL_PRIVATE *Private;
  207. Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
  208. return EFI_UNSUPPORTED;
  209. }
  210. EFI_STATUS
  211. EFIAPI
  212. UnixRegisterInterruptHandler (
  213. IN EFI_CPU_ARCH_PROTOCOL *This,
  214. IN EFI_EXCEPTION_TYPE InterruptType,
  215. IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
  216. )
  217. /*++
  218. Routine Description:
  219. This routine would support registration of an interrupt handler. At
  220. present, this code does not provide emulation.
  221. Arguments:
  222. Pointer to CPU Architectural Protocol interface
  223. Pointer to interrupt handlers
  224. Interrupt type
  225. Returns:
  226. Status
  227. EFI_UNSUPPORTED - not yet implemented
  228. --*/
  229. // TODO: This - add argument and description to function comment
  230. // TODO: InterruptType - add argument and description to function comment
  231. // TODO: InterruptHandler - add argument and description to function comment
  232. {
  233. CPU_ARCH_PROTOCOL_PRIVATE *Private;
  234. //
  235. // Do parameter checking for EFI spec conformance
  236. //
  237. if (InterruptType < 0 || InterruptType > 0xff) {
  238. return EFI_UNSUPPORTED;
  239. }
  240. //
  241. // Do nothing for Nt32 emulation
  242. //
  243. Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
  244. return EFI_UNSUPPORTED;
  245. }
  246. EFI_STATUS
  247. EFIAPI
  248. UnixGetTimerValue (
  249. IN EFI_CPU_ARCH_PROTOCOL *This,
  250. IN UINT32 TimerIndex,
  251. OUT UINT64 *TimerValue,
  252. OUT UINT64 *TimerPeriod OPTIONAL
  253. )
  254. /*++
  255. Routine Description:
  256. This routine would support querying of an on-CPU timer. At present,
  257. this code does not provide timer emulation.
  258. Arguments:
  259. This - Pointer to CPU Architectural Protocol interface
  260. TimerIndex - Index of given CPU timer
  261. TimerValue - Output of the timer
  262. TimerPeriod - Output of the timer period
  263. Returns:
  264. EFI_UNSUPPORTED - not yet implemented
  265. EFI_INVALID_PARAMETER - TimeValue is NULL
  266. --*/
  267. {
  268. if (TimerValue == NULL) {
  269. return EFI_INVALID_PARAMETER;
  270. }
  271. //
  272. // No timer supported
  273. //
  274. return EFI_UNSUPPORTED;
  275. }
  276. EFI_STATUS
  277. EFIAPI
  278. UnixSetMemoryAttributes (
  279. IN EFI_CPU_ARCH_PROTOCOL *This,
  280. IN EFI_PHYSICAL_ADDRESS BaseAddress,
  281. IN UINT64 Length,
  282. IN UINT64 Attributes
  283. )
  284. /*++
  285. Routine Description:
  286. This routine would support querying of an on-CPU timer. At present,
  287. this code does not provide timer emulation.
  288. Arguments:
  289. Pointer to CPU Architectural Protocol interface
  290. Start address of memory region
  291. The size in bytes of the memory region
  292. The bit mask of attributes to set for the memory region
  293. Returns:
  294. Status
  295. EFI_UNSUPPORTED - not yet implemented
  296. --*/
  297. // TODO: This - add argument and description to function comment
  298. // TODO: BaseAddress - add argument and description to function comment
  299. // TODO: Length - add argument and description to function comment
  300. // TODO: Attributes - add argument and description to function comment
  301. // TODO: EFI_INVALID_PARAMETER - add return value to function comment
  302. {
  303. CPU_ARCH_PROTOCOL_PRIVATE *Private;
  304. //
  305. // Check for invalid parameter for Spec conformance
  306. //
  307. if (Length == 0) {
  308. return EFI_INVALID_PARAMETER;
  309. }
  310. //
  311. // Do nothing for Nt32 emulation
  312. //
  313. Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
  314. return EFI_UNSUPPORTED;
  315. }
  316. /**
  317. Logs SMBIOS record.
  318. @param Smbios Pointer to SMBIOS protocol instance.
  319. @param Buffer Pointer to the data buffer.
  320. **/
  321. VOID
  322. LogSmbiosData (
  323. IN EFI_SMBIOS_PROTOCOL *Smbios,
  324. IN UINT8 *Buffer
  325. )
  326. {
  327. EFI_STATUS Status;
  328. EFI_SMBIOS_HANDLE SmbiosHandle;
  329. SmbiosHandle = 0;
  330. Status = Smbios->Add (
  331. Smbios,
  332. NULL,
  333. &SmbiosHandle,
  334. (EFI_SMBIOS_TABLE_HEADER*)Buffer
  335. );
  336. ASSERT_EFI_ERROR (Status);
  337. }
  338. VOID
  339. CpuUpdateSmbios (
  340. VOID
  341. )
  342. /*++
  343. Routine Description:
  344. This function will log processor version and frequency data to data hub.
  345. Arguments:
  346. Event - Event whose notification function is being invoked.
  347. Context - Pointer to the notification function's context.
  348. Returns:
  349. None.
  350. --*/
  351. {
  352. EFI_STATUS Status;
  353. EFI_SMBIOS_PROTOCOL *Smbios;
  354. UINT32 TotalSize;
  355. EFI_HII_HANDLE HiiHandle;
  356. STRING_REF Token;
  357. UINTN CpuVerStrLen;
  358. EFI_STRING CpuVerStr;
  359. SMBIOS_TABLE_TYPE4 *SmbiosRecord;
  360. CHAR8 *OptionalStrStart;
  361. //
  362. // Locate Smbios protocol.
  363. //
  364. Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);
  365. if (EFI_ERROR (Status)) {
  366. return;
  367. }
  368. //
  369. // Initialize strings to HII database
  370. //
  371. HiiHandle = HiiAddPackages (
  372. &gEfiCallerIdGuid,
  373. NULL,
  374. CpuStrings,
  375. NULL
  376. );
  377. ASSERT (HiiHandle != NULL);
  378. Token = STRING_TOKEN (STR_INTEL_GENUINE_PROCESSOR);
  379. CpuVerStr = HiiGetPackageString(&gEfiCallerIdGuid, Token, NULL);
  380. CpuVerStrLen = StrLen(CpuVerStr);
  381. ASSERT (CpuVerStrLen <= SMBIOS_STRING_MAX_LENGTH);
  382. TotalSize = sizeof(SMBIOS_TABLE_TYPE4) + CpuVerStrLen + 1 + 1;
  383. SmbiosRecord = AllocatePool(TotalSize);
  384. ZeroMem(SmbiosRecord, TotalSize);
  385. SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;
  386. SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE4);
  387. //
  388. // Make handle chosen by smbios protocol.add automatically.
  389. //
  390. SmbiosRecord->Hdr.Handle = 0;
  391. //
  392. // Processor version is the 1st string.
  393. //
  394. SmbiosRecord->ProcessorVersion = 1;
  395. //
  396. // Store CPU frequency data record to data hub - It's an emulator so make up a value
  397. //
  398. SmbiosRecord->CurrentSpeed = 1234;
  399. OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
  400. UnicodeStrToAsciiStr(CpuVerStr, OptionalStrStart);
  401. //
  402. // Now we have got the full smbios record, call smbios protocol to add this record.
  403. //
  404. LogSmbiosData(Smbios, (UINT8 *) SmbiosRecord);
  405. FreePool (SmbiosRecord);
  406. }
  407. EFI_STATUS
  408. EFIAPI
  409. InitializeCpu (
  410. IN EFI_HANDLE ImageHandle,
  411. IN EFI_SYSTEM_TABLE *SystemTable
  412. )
  413. /*++
  414. Routine Description:
  415. Initialize the state information for the CPU Architectural Protocol
  416. Arguments:
  417. ImageHandle of the loaded driver
  418. Pointer to the System Table
  419. Returns:
  420. Status
  421. EFI_SUCCESS - protocol instance can be published
  422. EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
  423. EFI_DEVICE_ERROR - cannot create the thread
  424. --*/
  425. // TODO: SystemTable - add argument and description to function comment
  426. {
  427. EFI_STATUS Status;
  428. CpuUpdateSmbios ();
  429. Status = gBS->InstallMultipleProtocolInterfaces (
  430. &mCpuTemplate.Handle,
  431. &gEfiCpuArchProtocolGuid, &mCpuTemplate.Cpu,
  432. &gEfiCpuIo2ProtocolGuid, &mCpuTemplate.CpuIo,
  433. NULL
  434. );
  435. ASSERT_EFI_ERROR (Status);
  436. DEBUG ((EFI_D_ERROR, "CPU Architectural Protocol Loaded\n"));
  437. return Status;
  438. }