/reactos/boot/environ/lib/arch/i386/arch.c

https://gitlab.com/dj-tech/reactos · C · 268 lines · 171 code · 36 blank · 61 comment · 25 complexity · 1bc83a3480da204dcb499c75089f0a78 MD5 · raw file

  1. /*
  2. * COPYRIGHT: See COPYING.ARM in the top level directory
  3. * PROJECT: ReactOS UEFI Boot Library
  4. * FILE: boot/environ/lib/arch/i386/arch.c
  5. * PURPOSE: Boot Library Architectural Initialization for i386
  6. * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
  7. */
  8. /* INCLUDES ******************************************************************/
  9. #include "bl.h"
  10. /* DATA VARIABLES ************************************************************/
  11. BL_ARCH_CONTEXT FirmwareExecutionContext;
  12. BL_ARCH_CONTEXT ApplicationExecutionContext;
  13. PBL_ARCH_CONTEXT CurrentExecutionContext;
  14. /* FUNCTIONS *****************************************************************/
  15. VOID
  16. DECLSPEC_NORETURN
  17. ArchTrapNoProcess (
  18. VOID
  19. )
  20. {
  21. /* Do nothing, this is an unsupported debugging interrupt */
  22. #if defined(__GNUC__)
  23. __asm__ __volatile__ ("iret");
  24. #elif defined (_MSC_VER)
  25. _asm { iret };
  26. #else
  27. #error wtf are you using
  28. #endif
  29. __assume(0);
  30. }
  31. VOID
  32. ArchSwitchContext (
  33. _In_ PBL_ARCH_CONTEXT NewContext,
  34. _In_ PBL_ARCH_CONTEXT OldContext
  35. )
  36. {
  37. /* Are we switching to real mode? */
  38. if (NewContext->Mode == BlRealMode)
  39. {
  40. /* Disable paging */
  41. __writecr0(__readcr0() & ~CR0_PG);
  42. /* Are we coming from PAE mode? */
  43. if ((OldContext != NULL) && (OldContext->TranslationType == BlPae))
  44. {
  45. /* Turn off PAE */
  46. __writecr4(__readcr4() & ~CR4_PAE);
  47. }
  48. /* Enable interrupts */
  49. _enable();
  50. }
  51. else
  52. {
  53. /* Switching to protected mode -- disable interrupts if needed */
  54. if (!(NewContext->ContextFlags & BL_CONTEXT_INTERRUPTS_ON))
  55. {
  56. _disable();
  57. }
  58. /* Are we enabling paging for the first time? */
  59. if (NewContext->ContextFlags & BL_CONTEXT_PAGING_ON)
  60. {
  61. /* In PAE mode? */
  62. if (NewContext->TranslationType == BlPae)
  63. {
  64. /* Turn on PAE */
  65. __writecr4(__readcr4() | CR4_PAE);
  66. }
  67. /* Turn on paging */
  68. __writecr0(__readcr0() | CR0_PG);
  69. }
  70. }
  71. }
  72. NTSTATUS
  73. ArchInitializeContext (
  74. _In_ PBL_ARCH_CONTEXT Context
  75. )
  76. {
  77. NTSTATUS Status = STATUS_SUCCESS;
  78. /* Are we initializing real mode? */
  79. if (Context->Mode == BlRealMode)
  80. {
  81. /* Disable paging, enable interrupts */
  82. Context->ContextFlags &= ~BL_CONTEXT_PAGING_ON;
  83. Context->ContextFlags |= BL_CONTEXT_INTERRUPTS_ON;
  84. }
  85. else if (!(BlpApplicationFlags & BL_APPLICATION_FLAG_CONVERTED_FROM_EFI) ||
  86. (BlpLibraryParameters.TranslationType != BlNone))
  87. {
  88. /* Read the current translation type */
  89. Context->TranslationType = BlpLibraryParameters.TranslationType;
  90. /* Disable paging (it's already on), enable interrupts */
  91. Context->ContextFlags &= ~BL_CONTEXT_PAGING_ON;
  92. Context->ContextFlags |= BL_CONTEXT_INTERRUPTS_ON;
  93. /* Enable FXSR support in the FPU */
  94. __writecr4(__readcr4() | CR4_FXSR);
  95. }
  96. else
  97. {
  98. /* Invalid context */
  99. Status = STATUS_NOT_SUPPORTED;
  100. }
  101. /* Return context status */
  102. return Status;
  103. }
  104. NTSTATUS
  105. ArchInitializeContexts (
  106. VOID
  107. )
  108. {
  109. PBL_ARCH_CONTEXT Context = NULL;
  110. NTSTATUS EfiStatus, AppStatus;
  111. /* No current context */
  112. CurrentExecutionContext = NULL;
  113. /* Setup the EFI and Application modes respectively */
  114. FirmwareExecutionContext.Mode = BlRealMode;
  115. ApplicationExecutionContext.Mode = BlProtectedMode;
  116. /* Initialize application mode */
  117. AppStatus = ArchInitializeContext(&ApplicationExecutionContext);
  118. if (NT_SUCCESS(AppStatus))
  119. {
  120. /* Set it as current if it worked */
  121. Context = &ApplicationExecutionContext;
  122. CurrentExecutionContext = &ApplicationExecutionContext;
  123. }
  124. /* Initialize EFI mode */
  125. EfiStatus = ArchInitializeContext(&FirmwareExecutionContext);
  126. if (NT_SUCCESS(EfiStatus))
  127. {
  128. /* Set it as current if application context failed */
  129. if (!NT_SUCCESS(AppStatus))
  130. {
  131. Context = &FirmwareExecutionContext;
  132. CurrentExecutionContext = &FirmwareExecutionContext;
  133. }
  134. /* Switch to application mode, or EFI if that one failed */
  135. ArchSwitchContext(Context, NULL);
  136. EfiStatus = STATUS_SUCCESS;
  137. }
  138. /* Return initialization state */
  139. return EfiStatus;
  140. }
  141. VOID
  142. BlpArchSwitchContext (
  143. _In_ BL_ARCH_MODE NewMode
  144. )
  145. {
  146. PBL_ARCH_CONTEXT Context;
  147. /* In real mode, use EFI, otherwise, use the application mode */
  148. Context = &FirmwareExecutionContext;
  149. if (NewMode != BlProtectedMode) Context = &ApplicationExecutionContext;
  150. /* Are we in a different mode? */
  151. if (CurrentExecutionContext->Mode != NewMode)
  152. {
  153. /* Switch to the new one */
  154. ArchSwitchContext(Context, CurrentExecutionContext);
  155. CurrentExecutionContext = Context;
  156. }
  157. }
  158. /*++
  159. * @name BlpArchInitialize
  160. *
  161. * The BlpArchInitialize function initializes the Boot Library.
  162. *
  163. * @param Phase
  164. * Pointer to the Boot Application Parameter Block.
  165. *
  166. * @return NT_SUCCESS if the boot library was loaded correctly, relevant error
  167. * otherwise.
  168. *
  169. *--*/
  170. NTSTATUS
  171. BlpArchInitialize (
  172. _In_ ULONG Phase
  173. )
  174. {
  175. KDESCRIPTOR Idtr;
  176. USHORT CodeSegment;
  177. NTSTATUS Status;
  178. PKIDTENTRY IdtBase;
  179. /* Assume success */
  180. Status = STATUS_SUCCESS;
  181. /* Is this phase 1? */
  182. if (Phase != 0)
  183. {
  184. /* Get the IDT */
  185. __sidt(&Idtr);
  186. IdtBase = (PKIDTENTRY)Idtr.Base;
  187. /* Get the Code Segment */
  188. #if defined(__GNUC__)
  189. __asm__ __volatile__ ("mov %%cs,%0\n\t" :"=r" (CodeSegment));
  190. #elif defined (_MSC_VER)
  191. _asm { mov CodeSegment, cs };
  192. #else
  193. #error wtf are you using
  194. #endif
  195. /* Set up INT 3, ASSERT, and SECURITY_ASSERT to be no-op (for Rtl) */
  196. IdtBase[3].Offset = (USHORT)(ULONG_PTR)ArchTrapNoProcess;
  197. IdtBase[3].Selector = CodeSegment;
  198. IdtBase[3].Access = 0x8E00u;
  199. IdtBase[3].ExtendedOffset = (ULONG_PTR)ArchTrapNoProcess >> 16;
  200. IdtBase[0x2C].Offset = (USHORT)(ULONG_PTR)ArchTrapNoProcess;
  201. IdtBase[0x2C].Selector = CodeSegment;
  202. IdtBase[0x2C].Access = 0x8E00u;
  203. IdtBase[0x2C].ExtendedOffset = (ULONG_PTR)ArchTrapNoProcess >> 16;
  204. IdtBase[0x2D].Offset = (USHORT)(ULONG_PTR)ArchTrapNoProcess;
  205. IdtBase[0x2D].Selector = CodeSegment;
  206. IdtBase[0x2D].Access = 0x8E00u;
  207. IdtBase[0x2D].ExtendedOffset = (ULONG_PTR)ArchTrapNoProcess >> 16;
  208. /* Write the IDT back */
  209. Idtr.Base = (ULONG)IdtBase;
  210. __lidt(&Idtr);
  211. /* Reset FPU state */
  212. #if defined(__GNUC__)
  213. __asm__ __volatile__ ("fninit");
  214. #elif defined (_MSC_VER)
  215. _asm { fninit };
  216. #else
  217. #error wtf are you using
  218. #endif
  219. }
  220. else
  221. {
  222. /* Reset TSC if needed */
  223. if ((__readmsr(0x10) >> 32) & 0xFFC00000)
  224. {
  225. __writemsr(0x10, 0);
  226. }
  227. /* Initialize all the contexts */
  228. Status = ArchInitializeContexts();
  229. }
  230. /* Return initialization state */
  231. return Status;
  232. }