/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
- /*
- * COPYRIGHT: See COPYING.ARM in the top level directory
- * PROJECT: ReactOS UEFI Boot Library
- * FILE: boot/environ/lib/arch/i386/arch.c
- * PURPOSE: Boot Library Architectural Initialization for i386
- * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
- */
- /* INCLUDES ******************************************************************/
- #include "bl.h"
- /* DATA VARIABLES ************************************************************/
- BL_ARCH_CONTEXT FirmwareExecutionContext;
- BL_ARCH_CONTEXT ApplicationExecutionContext;
- PBL_ARCH_CONTEXT CurrentExecutionContext;
- /* FUNCTIONS *****************************************************************/
- VOID
- DECLSPEC_NORETURN
- ArchTrapNoProcess (
- VOID
- )
- {
- /* Do nothing, this is an unsupported debugging interrupt */
- #if defined(__GNUC__)
- __asm__ __volatile__ ("iret");
- #elif defined (_MSC_VER)
- _asm { iret };
- #else
- #error wtf are you using
- #endif
- __assume(0);
- }
- VOID
- ArchSwitchContext (
- _In_ PBL_ARCH_CONTEXT NewContext,
- _In_ PBL_ARCH_CONTEXT OldContext
- )
- {
- /* Are we switching to real mode? */
- if (NewContext->Mode == BlRealMode)
- {
- /* Disable paging */
- __writecr0(__readcr0() & ~CR0_PG);
- /* Are we coming from PAE mode? */
- if ((OldContext != NULL) && (OldContext->TranslationType == BlPae))
- {
- /* Turn off PAE */
- __writecr4(__readcr4() & ~CR4_PAE);
- }
- /* Enable interrupts */
- _enable();
- }
- else
- {
- /* Switching to protected mode -- disable interrupts if needed */
- if (!(NewContext->ContextFlags & BL_CONTEXT_INTERRUPTS_ON))
- {
- _disable();
- }
- /* Are we enabling paging for the first time? */
- if (NewContext->ContextFlags & BL_CONTEXT_PAGING_ON)
- {
- /* In PAE mode? */
- if (NewContext->TranslationType == BlPae)
- {
- /* Turn on PAE */
- __writecr4(__readcr4() | CR4_PAE);
- }
- /* Turn on paging */
- __writecr0(__readcr0() | CR0_PG);
- }
- }
- }
- NTSTATUS
- ArchInitializeContext (
- _In_ PBL_ARCH_CONTEXT Context
- )
- {
- NTSTATUS Status = STATUS_SUCCESS;
- /* Are we initializing real mode? */
- if (Context->Mode == BlRealMode)
- {
- /* Disable paging, enable interrupts */
- Context->ContextFlags &= ~BL_CONTEXT_PAGING_ON;
- Context->ContextFlags |= BL_CONTEXT_INTERRUPTS_ON;
- }
- else if (!(BlpApplicationFlags & BL_APPLICATION_FLAG_CONVERTED_FROM_EFI) ||
- (BlpLibraryParameters.TranslationType != BlNone))
- {
- /* Read the current translation type */
- Context->TranslationType = BlpLibraryParameters.TranslationType;
- /* Disable paging (it's already on), enable interrupts */
- Context->ContextFlags &= ~BL_CONTEXT_PAGING_ON;
- Context->ContextFlags |= BL_CONTEXT_INTERRUPTS_ON;
- /* Enable FXSR support in the FPU */
- __writecr4(__readcr4() | CR4_FXSR);
- }
- else
- {
- /* Invalid context */
- Status = STATUS_NOT_SUPPORTED;
- }
- /* Return context status */
- return Status;
- }
- NTSTATUS
- ArchInitializeContexts (
- VOID
- )
- {
- PBL_ARCH_CONTEXT Context = NULL;
- NTSTATUS EfiStatus, AppStatus;
- /* No current context */
- CurrentExecutionContext = NULL;
- /* Setup the EFI and Application modes respectively */
- FirmwareExecutionContext.Mode = BlRealMode;
- ApplicationExecutionContext.Mode = BlProtectedMode;
- /* Initialize application mode */
- AppStatus = ArchInitializeContext(&ApplicationExecutionContext);
- if (NT_SUCCESS(AppStatus))
- {
- /* Set it as current if it worked */
- Context = &ApplicationExecutionContext;
- CurrentExecutionContext = &ApplicationExecutionContext;
- }
- /* Initialize EFI mode */
- EfiStatus = ArchInitializeContext(&FirmwareExecutionContext);
- if (NT_SUCCESS(EfiStatus))
- {
- /* Set it as current if application context failed */
- if (!NT_SUCCESS(AppStatus))
- {
- Context = &FirmwareExecutionContext;
- CurrentExecutionContext = &FirmwareExecutionContext;
- }
- /* Switch to application mode, or EFI if that one failed */
- ArchSwitchContext(Context, NULL);
- EfiStatus = STATUS_SUCCESS;
- }
- /* Return initialization state */
- return EfiStatus;
- }
- VOID
- BlpArchSwitchContext (
- _In_ BL_ARCH_MODE NewMode
- )
- {
- PBL_ARCH_CONTEXT Context;
- /* In real mode, use EFI, otherwise, use the application mode */
- Context = &FirmwareExecutionContext;
- if (NewMode != BlProtectedMode) Context = &ApplicationExecutionContext;
- /* Are we in a different mode? */
- if (CurrentExecutionContext->Mode != NewMode)
- {
- /* Switch to the new one */
- ArchSwitchContext(Context, CurrentExecutionContext);
- CurrentExecutionContext = Context;
- }
- }
- /*++
- * @name BlpArchInitialize
- *
- * The BlpArchInitialize function initializes the Boot Library.
- *
- * @param Phase
- * Pointer to the Boot Application Parameter Block.
- *
- * @return NT_SUCCESS if the boot library was loaded correctly, relevant error
- * otherwise.
- *
- *--*/
- NTSTATUS
- BlpArchInitialize (
- _In_ ULONG Phase
- )
- {
- KDESCRIPTOR Idtr;
- USHORT CodeSegment;
- NTSTATUS Status;
- PKIDTENTRY IdtBase;
- /* Assume success */
- Status = STATUS_SUCCESS;
- /* Is this phase 1? */
- if (Phase != 0)
- {
- /* Get the IDT */
- __sidt(&Idtr);
- IdtBase = (PKIDTENTRY)Idtr.Base;
- /* Get the Code Segment */
- #if defined(__GNUC__)
- __asm__ __volatile__ ("mov %%cs,%0\n\t" :"=r" (CodeSegment));
- #elif defined (_MSC_VER)
- _asm { mov CodeSegment, cs };
- #else
- #error wtf are you using
- #endif
- /* Set up INT 3, ASSERT, and SECURITY_ASSERT to be no-op (for Rtl) */
- IdtBase[3].Offset = (USHORT)(ULONG_PTR)ArchTrapNoProcess;
- IdtBase[3].Selector = CodeSegment;
- IdtBase[3].Access = 0x8E00u;
- IdtBase[3].ExtendedOffset = (ULONG_PTR)ArchTrapNoProcess >> 16;
- IdtBase[0x2C].Offset = (USHORT)(ULONG_PTR)ArchTrapNoProcess;
- IdtBase[0x2C].Selector = CodeSegment;
- IdtBase[0x2C].Access = 0x8E00u;
- IdtBase[0x2C].ExtendedOffset = (ULONG_PTR)ArchTrapNoProcess >> 16;
- IdtBase[0x2D].Offset = (USHORT)(ULONG_PTR)ArchTrapNoProcess;
- IdtBase[0x2D].Selector = CodeSegment;
- IdtBase[0x2D].Access = 0x8E00u;
- IdtBase[0x2D].ExtendedOffset = (ULONG_PTR)ArchTrapNoProcess >> 16;
- /* Write the IDT back */
- Idtr.Base = (ULONG)IdtBase;
- __lidt(&Idtr);
- /* Reset FPU state */
- #if defined(__GNUC__)
- __asm__ __volatile__ ("fninit");
- #elif defined (_MSC_VER)
- _asm { fninit };
- #else
- #error wtf are you using
- #endif
- }
- else
- {
- /* Reset TSC if needed */
- if ((__readmsr(0x10) >> 32) & 0xFFC00000)
- {
- __writemsr(0x10, 0);
- }
- /* Initialize all the contexts */
- Status = ArchInitializeContexts();
- }
- /* Return initialization state */
- return Status;
- }