Example #1
0
/**
  Worker function to setup IDT table and initialize the IDT entries.

  @param[in] Mailbox        Pointer to Mailbox.

**/
VOID
SetupDebugAgentEnviroment (
  IN DEBUG_AGENT_MAILBOX       *Mailbox
  )
{
  IA32_DESCRIPTOR              Idtr;
  UINT16                       IdtEntryCount;
  UINT64                       DebugPortHandle;

  if (mMultiProcessorDebugSupport) {
    InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);
    InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);
    InitializeSpinLock (&mDebugMpContext.MailboxSpinLock);
    //
    // Clear Break CPU index value
    //
    mDebugMpContext.BreakAtCpuIndex = (UINT32) -1;
  }

  //
  // Get original IDT address and size.
  //
  AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);
  IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));
  if (IdtEntryCount < 33) {
    ZeroMem (&mIdtEntryTable, sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33);
    //
    // Copy original IDT table into new one
    //
    CopyMem (&mIdtEntryTable, (VOID *) Idtr.Base, Idtr.Limit + 1);
    //
    // Load new IDT table
    //
    Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);
    Idtr.Base  = (UINTN) &mIdtEntryTable;
    AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);
  }

  //
  // Initialize the IDT table entries to support source level debug.
  //
  InitializeDebugIdt ();

  //
  // If mMailboxPointer is not set before, set it
  //
  if (mMailboxPointer == NULL) {
    if (Mailbox != NULL) {
      //
      // If Mailbox exists, copy it into one global variable
      //
      CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
    } else {
      ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));
    }
    mMailboxPointer = &mMailbox;
  }

  //
  // Initialize debug communication port
  //
  DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((VOID *)(UINTN)mMailboxPointer->DebugPortHandle, NULL);
  UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);

  if (Mailbox == NULL) {
    //
    // Trigger one software interrupt to inform HOST
    //
    TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);
    SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);
    //
    // Memory has been ready
    //
    if (IsHostAttached ()) {
      //
      // Trigger one software interrupt to inform HOST
      //
      TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
    }
  }
}
/**
  Perform SMM initialization for all processors in the S3 boot path.

  For a native platform, MP initialization in the S3 boot path is also performed in this function.
**/
VOID
EFIAPI
SmmRestoreCpu (
  VOID
  )
{
  SMM_S3_RESUME_STATE           *SmmS3ResumeState;
  IA32_DESCRIPTOR               Ia32Idtr;
  IA32_DESCRIPTOR               X64Idtr;
  IA32_IDT_GATE_DESCRIPTOR      IdtEntryTable[EXCEPTION_VECTOR_NUMBER];
  EFI_STATUS                    Status;

  DEBUG ((EFI_D_INFO, "SmmRestoreCpu()\n"));

  mSmmS3Flag = TRUE;

  InitializeSpinLock (mMemoryMappedLock);

  //
  // See if there is enough context to resume PEI Phase
  //
  if (mSmmS3ResumeState == NULL) {
    DEBUG ((EFI_D_ERROR, "No context to return to PEI Phase\n"));
    CpuDeadLoop ();
  }

  SmmS3ResumeState = mSmmS3ResumeState;
  ASSERT (SmmS3ResumeState != NULL);

  if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) {
    //
    // Save the IA32 IDT Descriptor
    //
    AsmReadIdtr ((IA32_DESCRIPTOR *) &Ia32Idtr);

    //
    // Setup X64 IDT table
    //
    ZeroMem (IdtEntryTable, sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32);
    X64Idtr.Base = (UINTN) IdtEntryTable;
    X64Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32 - 1);
    AsmWriteIdtr ((IA32_DESCRIPTOR *) &X64Idtr);

    //
    // Setup the default exception handler
    //
    Status = InitializeCpuExceptionHandlers (NULL);
    ASSERT_EFI_ERROR (Status);

    //
    // Initialize Debug Agent to support source level debug
    //
    InitializeDebugAgent (DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64, (VOID *)&Ia32Idtr, NULL);
  }

  //
  // Skip initialization if mAcpiCpuData is not valid
  //
  if (mAcpiCpuData.NumberOfCpus > 0) {
    //
    // First time microcode load and restore MTRRs
    //
    InitializeCpuBeforeRebase ();
  }

  //
  // Restore SMBASE for BSP and all APs
  //
  SmmRelocateBases ();

  //
  // Skip initialization if mAcpiCpuData is not valid
  //
  if (mAcpiCpuData.NumberOfCpus > 0) {
    //
    // Restore MSRs for BSP and all APs
    //
    InitializeCpuAfterRebase ();
  }

  //
  // Set a flag to restore SMM configuration in S3 path.
  //
  mRestoreSmmConfigurationInS3 = TRUE;

  DEBUG (( EFI_D_INFO, "SMM S3 Return CS                = %x\n", SmmS3ResumeState->ReturnCs));
  DEBUG (( EFI_D_INFO, "SMM S3 Return Entry Point       = %x\n", SmmS3ResumeState->ReturnEntryPoint));
  DEBUG (( EFI_D_INFO, "SMM S3 Return Context1          = %x\n", SmmS3ResumeState->ReturnContext1));
  DEBUG (( EFI_D_INFO, "SMM S3 Return Context2          = %x\n", SmmS3ResumeState->ReturnContext2));
  DEBUG (( EFI_D_INFO, "SMM S3 Return Stack Pointer     = %x\n", SmmS3ResumeState->ReturnStackPointer));

  //
  // If SMM is in 32-bit mode, then use SwitchStack() to resume PEI Phase
  //
  if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) {
    DEBUG ((EFI_D_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));

    SwitchStack (
      (SWITCH_STACK_ENTRY_POINT)(UINTN)SmmS3ResumeState->ReturnEntryPoint,
      (VOID *)(UINTN)SmmS3ResumeState->ReturnContext1,
      (VOID *)(UINTN)SmmS3ResumeState->ReturnContext2,
      (VOID *)(UINTN)SmmS3ResumeState->ReturnStackPointer
      );
  }

  //
  // If SMM is in 64-bit mode, then use AsmDisablePaging64() to resume PEI Phase
  //
  if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) {
    DEBUG ((EFI_D_INFO, "Call AsmDisablePaging64() to return to S3 Resume in PEI Phase\n"));
    //
    // Disable interrupt of Debug timer, since new IDT table is for IA32 and will not work in long mode.
    //
    SaveAndSetDebugTimerInterrupt (FALSE);
    //
    // Restore IA32 IDT table
    //
    AsmWriteIdtr ((IA32_DESCRIPTOR *) &Ia32Idtr);
    AsmDisablePaging64 (
      SmmS3ResumeState->ReturnCs,
      (UINT32)SmmS3ResumeState->ReturnEntryPoint,
      (UINT32)SmmS3ResumeState->ReturnContext1,
      (UINT32)SmmS3ResumeState->ReturnContext2,
      (UINT32)SmmS3ResumeState->ReturnStackPointer
      );
  }

  //
  // Can not resume PEI Phase
  //
  DEBUG ((EFI_D_ERROR, "No context to return to PEI Phase\n"));
  CpuDeadLoop ();
}
Example #3
0
mempool mempool_create(const char *name,
						uint64 elem_size,
						uint64 initial_count,
						uint64 realloc_count,
						memPoolOnNodeAllocationProc onNodeAlloc,
						memPoolOnNodeDeallocationProc onNodeDealloc){
	//..
	uint64 realloc_thresh;
	mempool pool;
	pool = (mempool)aCalloc( 1,  sizeof(struct mempool) );
	
	if(pool == NULL){
		ShowFatalError("mempool_create: Failed to allocate %u bytes memory.\n", sizeof(struct mempool) );
		exit(EXIT_FAILURE);		
	}
	
	// Check minimum initial count / realloc count requirements.
	if(initial_count < 50)
		initial_count = 50;
	if(realloc_count < 50)
		realloc_count = 50;
	
	// Set Reallocation threshold to 5% of realloc_count, at least 10.
	realloc_thresh = (realloc_count/100)*5; // 
	if(realloc_thresh < 10)
		realloc_thresh = 10;

	// Initialize members..
	pool->name = aStrdup(name);
	pool->elem_size	= ALIGN_TO_16(elem_size);
	pool->elem_realloc_step = realloc_count;
	pool->elem_realloc_thresh = realloc_thresh;
	pool->onalloc = onNodeAlloc;
	pool->ondealloc = onNodeDealloc;
	
	InitializeSpinLock(&pool->segmentLock);
	InitializeSpinLock(&pool->nodeLock);

	// Initial Statistic values:
	pool->num_nodes_total = 0;
	pool->num_nodes_free = 0;
	pool->num_segments = 0;
	pool->num_bytes_total = 0;
	pool->peak_nodes_used = 0;
	pool->num_realloc_events = 0;
		
	//
#ifdef MEMPOOL_DEBUG
	ShowDebug("Mempool [%s] Init (ElemSize: %u,  Initial Count: %u,  Realloc Count: %u)\n", pool->name,  pool->elem_size,  initial_count,  pool->elem_realloc_step);
#endif

	// Allocate first segment directly :) 	
	segment_allocate_add(pool, initial_count);
	

	// Add Pool to the global pool list
	EnterSpinLock(&l_mempoolListLock);
		pool->next = l_mempoolList;
		l_mempoolList = pool;
	LeaveSpinLock(&l_mempoolListLock);

	
	return pool;	
}//end: mempool_create()
Example #4
0
/**
  Create PageTable for SMM use.

  @return The address of PML4 (to set CR3).

**/
UINT32
SmmInitPageTable (
  VOID
  )
{
  EFI_PHYSICAL_ADDRESS              Pages;
  UINT64                            *PTEntry;
  LIST_ENTRY                        *FreePage;
  UINTN                             Index;
  UINTN                             PageFaultHandlerHookAddress;
  IA32_IDT_GATE_DESCRIPTOR          *IdtEntry;

  //
  // Initialize spin lock
  //
  InitializeSpinLock (&mPFLock);

  m1GPageTableSupport = Is1GPageSupport ();
  //
  // Generate PAE page table for the first 4GB memory space
  //
  Pages = Gen4GPageTable (PAGE_TABLE_PAGES + 1);

  //
  // Set IA32_PG_PMNT bit to mask this entry
  //
  PTEntry = (UINT64*)(UINTN)Pages;
  for (Index = 0; Index < 4; Index++) {
    PTEntry[Index] |= IA32_PG_PMNT;
  }

  //
  // Fill Page-Table-Level4 (PML4) entry
  //
  PTEntry = (UINT64*)(UINTN)(Pages - EFI_PAGES_TO_SIZE (PAGE_TABLE_PAGES + 1));
  *PTEntry = Pages + PAGE_ATTRIBUTE_BITS;
  ZeroMem (PTEntry + 1, EFI_PAGE_SIZE - sizeof (*PTEntry));
  //
  // Set sub-entries number
  //
  SetSubEntriesNum (PTEntry, 3);

  //
  // Add remaining pages to page pool
  //
  FreePage = (LIST_ENTRY*)(PTEntry + EFI_PAGE_SIZE / sizeof (*PTEntry));
  while ((UINTN)FreePage < Pages) {
    InsertTailList (&mPagePool, FreePage);
    FreePage += EFI_PAGE_SIZE / sizeof (*FreePage);
  }

  if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
    //
    // Set own Page Fault entry instead of the default one, because SMM Profile
    // feature depends on IRET instruction to do Single Step
    //
    PageFaultHandlerHookAddress = (UINTN)PageFaultIdtHandlerSmmProfile;
    IdtEntry  = (IA32_IDT_GATE_DESCRIPTOR *) gcSmiIdtr.Base;
    IdtEntry += EXCEPT_IA32_PAGE_FAULT;
    IdtEntry->Bits.OffsetLow      = (UINT16)PageFaultHandlerHookAddress;
    IdtEntry->Bits.Reserved_0     = 0;
    IdtEntry->Bits.GateType       = IA32_IDT_GATE_TYPE_INTERRUPT_32;
    IdtEntry->Bits.OffsetHigh     = (UINT16)(PageFaultHandlerHookAddress >> 16);
    IdtEntry->Bits.OffsetUpper    = (UINT32)(PageFaultHandlerHookAddress >> 32);
    IdtEntry->Bits.Reserved_1     = 0;
  } else {
Example #5
0
/**
  Internal worker function to update IDT entries accordling to vector attributes.

  @param[in] IdtTable       Pointer to IDT table.
  @param[in] TemplateMap    Pointer to a buffer where the address map is returned.
  @param[in] IdtEntryCount  IDT entries number to be updated.

**/
VOID
UpdateIdtTable (
  IN IA32_IDT_GATE_DESCRIPTOR        *IdtTable,
  IN EXCEPTION_HANDLER_TEMPLATE_MAP  *TemplateMap,
  IN UINTN                           IdtEntryCount
  )
{
  UINT16                             CodeSegment;
  UINTN                              Index;
  UINTN                              InterruptHandler;

  //
  // Use current CS as the segment selector of interrupt gate in IDT
  //
  CodeSegment = AsmReadCs ();

  for (Index = 0; Index < IdtEntryCount; Index ++) {
    IdtTable[Index].Bits.Selector = CodeSegment;
    //
    // Check reserved vectors attributes
    //
    switch (mReservedVectors[Index].Attribute) {
    case EFI_VECTOR_HANDOFF_DO_NOT_HOOK:
      //
      // Keep original IDT entry
      //
      continue;
    case EFI_VECTOR_HANDOFF_HOOK_AFTER:
      InitializeSpinLock (&mReservedVectors[Index].SpinLock);
      CopyMem (
        (VOID *) mReservedVectors[Index].HookAfterStubHeaderCode,
        (VOID *) TemplateMap->HookAfterStubHeaderStart,
        TemplateMap->ExceptionStubHeaderSize
        );
      AsmVectorNumFixup (
        (VOID *) mReservedVectors[Index].HookAfterStubHeaderCode,
        (UINT8) Index,
        (VOID *) TemplateMap->HookAfterStubHeaderStart
        );
      //
      // Go on the following code
      //
    case EFI_VECTOR_HANDOFF_HOOK_BEFORE:
      //
      // Save original IDT handler address
      //
      mReservedVectors[Index].ExceptonHandler = ArchGetIdtHandler (&IdtTable[Index]);
      //
      // Go on the following code
      //
    default:
      //
      // Update new IDT entry
      //
      InterruptHandler = TemplateMap->ExceptionStart + Index * TemplateMap->ExceptionStubHeaderSize;
      ArchUpdateIdtEntry (&IdtTable[Index], InterruptHandler);
      break;
    }
  }

  //
  // Save Interrupt number to global variable used for RegisterCpuInterruptHandler ()
  //
  mEnabledInterruptNum = IdtEntryCount;
}
Example #6
0
/**
  Initialize debug agent.

  This function is used to set up debug enviroment for DXE phase.

  If this function is called by DXE Core, Context must be the pointer
  to HOB list which will be used to get GUIDed HOB. It will enable
  interrupt to support break-in feature.
  If this function is called by DXE module, Context must be NULL. It
  will enable interrupt to support break-in feature.

  @param[in] InitFlag     Init flag is used to decide initialize process.
  @param[in] Context      Context needed according to InitFlag.
  @param[in] Function     Continue function called by debug agent library; it was
                          optional.

**/
VOID
EFIAPI
InitializeDebugAgent (
  IN UINT32                InitFlag,
  IN VOID                  *Context, OPTIONAL
  IN DEBUG_AGENT_CONTINUE  Function  OPTIONAL
  )
{
  DEBUG_AGENT_MAILBOX          *Mailbox;
  IA32_DESCRIPTOR              Idtr;
  UINT16                       IdtEntryCount;
  BOOLEAN                      InterruptStatus;

  if (InitFlag != DEBUG_AGENT_INIT_DXE_CORE &&
      InitFlag != DEBUG_AGENT_INIT_S3 &&
      InitFlag != DEBUG_AGENT_INIT_DXE_AP) {
    return;
  }

  //
  // Save and disable original interrupt status
  //
  InterruptStatus = SaveAndDisableInterrupts ();

  if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {
    //
    // Try to get Mailbox from GUIDed HOB.
    //
    mDxeCoreFlag = TRUE;
    Mailbox = GetMailboxFromHob (Context);
    
    //
    // Clear Break CPU index value
    //
    mDebugMpContext.BreakAtCpuIndex = (UINT32) -1;

  } else if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {

    EnableInterrupts ();

    return;

  } else {
    //
    // If it is in S3 path, needn't to install configuration table.
    //
    Mailbox = NULL;
  }

  if (Mailbox != NULL) {
    //
    // If Mailbox exists, copy it into one global variable.
    //
    CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
  } else {
    //
    // If Mailbox not exists, used the local Mailbox.
    //
    ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));
  }

  mMailboxPointer = &mMailbox;

  //
  // Get original IDT address and size.
  //
  AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);
  IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));
  if (IdtEntryCount < 33) {
    Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);
    Idtr.Base  = (UINTN) &mIdtEntryTable;
    ZeroMem (&mIdtEntryTable, Idtr.Limit + 1);
    AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);
  }

  //
  // Initialize the IDT table entries to support source level debug.
  //
  InitializeDebugIdt ();

  //
  // Initialize debug communication port
  //
  mMailboxPointer->DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((VOID *)(UINTN)mMailbox.DebugPortHandle, NULL);

  InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);
  InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);
 
  if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {
    //
    // Initialize Debug Timer hardware and enable interrupt.
    //
    InitializeDebugTimer ();
    EnableInterrupts ();

    return;
  } else {
    //
    // Disable Debug Timer interrupt in S3 path.
    //
    SaveAndSetDebugTimerInterrupt (FALSE);

    //
    // Restore interrupt state.
    //
    SetInterruptState (InterruptStatus);
  }

}
Example #7
0
/**
  Create PageTable for SMM use.

  @return The address of PML4 (to set CR3).

**/
UINT32
SmmInitPageTable (
  VOID
  )
{
  EFI_PHYSICAL_ADDRESS              Pages;
  UINT64                            *PTEntry;
  LIST_ENTRY                        *FreePage;
  UINTN                             Index;
  UINTN                             PageFaultHandlerHookAddress;
  IA32_IDT_GATE_DESCRIPTOR          *IdtEntry;
  EFI_STATUS                        Status;

  //
  // Initialize spin lock
  //
  InitializeSpinLock (mPFLock);

  mCpuSmmStaticPageTable = PcdGetBool (PcdCpuSmmStaticPageTable);
  m1GPageTableSupport = Is1GPageSupport ();
  DEBUG ((DEBUG_INFO, "1GPageTableSupport - 0x%x\n", m1GPageTableSupport));
  DEBUG ((DEBUG_INFO, "PcdCpuSmmStaticPageTable - 0x%x\n", mCpuSmmStaticPageTable));

  mPhysicalAddressBits = CalculateMaximumSupportAddress ();
  DEBUG ((DEBUG_INFO, "PhysicalAddressBits - 0x%x\n", mPhysicalAddressBits));
  //
  // Generate PAE page table for the first 4GB memory space
  //
  Pages = Gen4GPageTable (FALSE);

  //
  // Set IA32_PG_PMNT bit to mask this entry
  //
  PTEntry = (UINT64*)(UINTN)Pages;
  for (Index = 0; Index < 4; Index++) {
    PTEntry[Index] |= IA32_PG_PMNT;
  }

  //
  // Fill Page-Table-Level4 (PML4) entry
  //
  PTEntry = (UINT64*)AllocatePageTableMemory (1);
  ASSERT (PTEntry != NULL);
  *PTEntry = Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS;
  ZeroMem (PTEntry + 1, EFI_PAGE_SIZE - sizeof (*PTEntry));

  //
  // Set sub-entries number
  //
  SetSubEntriesNum (PTEntry, 3);

  if (mCpuSmmStaticPageTable) {
    SetStaticPageTable ((UINTN)PTEntry);
  } else {
    //
    // Add pages to page pool
    //
    FreePage = (LIST_ENTRY*)AllocatePageTableMemory (PAGE_TABLE_PAGES);
    ASSERT (FreePage != NULL);
    for (Index = 0; Index < PAGE_TABLE_PAGES; Index++) {
      InsertTailList (&mPagePool, FreePage);
      FreePage += EFI_PAGE_SIZE / sizeof (*FreePage);
    }
  }

  if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
    //
    // Set own Page Fault entry instead of the default one, because SMM Profile
    // feature depends on IRET instruction to do Single Step
    //
    PageFaultHandlerHookAddress = (UINTN)PageFaultIdtHandlerSmmProfile;
    IdtEntry  = (IA32_IDT_GATE_DESCRIPTOR *) gcSmiIdtr.Base;
    IdtEntry += EXCEPT_IA32_PAGE_FAULT;
    IdtEntry->Bits.OffsetLow      = (UINT16)PageFaultHandlerHookAddress;
    IdtEntry->Bits.Reserved_0     = 0;
    IdtEntry->Bits.GateType       = IA32_IDT_GATE_TYPE_INTERRUPT_32;
    IdtEntry->Bits.OffsetHigh     = (UINT16)(PageFaultHandlerHookAddress >> 16);
    IdtEntry->Bits.OffsetUpper    = (UINT32)(PageFaultHandlerHookAddress >> 32);
    IdtEntry->Bits.Reserved_1     = 0;
  } else {
Example #8
0
/*---------------------------------------------------------------------------------------*/
EFI_STATUS
EFIAPI
PrepareSmmStartupVector (
  IN       EFI_PHYSICAL_ADDRESS     Smm16Entry,
  IN       EFI_PHYSICAL_ADDRESS     PageTableBase,
  IN       SMM_FOUNDATION_TABLE     *SmmEntryInfo
  )
{
  SMM_ADDRESS_PATCH_MAP       AddressMap;
  EFI_STATUS                  Status = EFI_SUCCESS;
  SMM_FOUNDATION_TABLE        *Info;
  STATIC SPIN_LOCK            *SmmSpinLock = NULL;

  AsmGetSmmPatchAddressMap  (&AddressMap);

  //
  // Copy AP startup code to startup vector, and then redirect the long jump
  // instructions for mode switching.
  //
  CopyMem ((VOID *) (UINTN) Smm16Entry, AddressMap.SmmEntryOffset, AddressMap.Size);

  // Some patchup is requred in SmmEntry code to adjust for this relocation operation (i.e. copy from DXE
  // driver to SMM space). Look for SMM_ADDRESS_PATCH_MAP for those patch offsets

  // Perform patchup on SmmEntry based on the relocation
  *(UINT32 *) (UINTN) (Smm16Entry + 2) = (UINT32) (Smm16Entry);

  *(UINT32 *) (UINTN) (Smm16Entry + AddressMap.FlatJumpOffset + 3) = (UINT32) (Smm16Entry + AddressMap.PModeEntryOffset);
  //
  // For IA32 mode, LongJumpOffset is filled with zero. If non-zero, then we are in
  // X64 mode, so further redirect for long mode switch.
  //
  if (AddressMap.LongJumpOffset != 0) {
    *(UINT32 *) (UINTN) (Smm16Entry + AddressMap.LongJumpOffset + 2) = (UINT32) (Smm16Entry + AddressMap.LModeEntryOffset);
  }

  // Fix the GDT base
  *(UINT32 *) (UINTN) (Smm16Entry + AddressMap.GdtOffset + 2)  = (UINT32) (Smm16Entry + AddressMap.GdtBaseOffset);

  *(UINT32 *) (UINTN) (Smm16Entry + AddressMap.IdtOffset + 2)  = (UINT32) (Smm16Entry + AddressMap.IdtBaseOffset);
  *(UINT32 *) (UINTN) (Smm16Entry + AddressMap.Cr3 + 1)  = (UINT32)PageTableBase;


  if (!SmmSpinLock) {
    SmmSpinLock =  (SPIN_LOCK *) (UINTN) (Smm16Entry + AddressMap.SmmSpinLock);
    InitializeSpinLock (SmmSpinLock);
  }
  SmmEntryInfo->SmmSpinLock = SmmSpinLock;

  //
  // Update the SmmInfo structure of each core
  //
  Info = (SMM_FOUNDATION_TABLE *) (UINTN) (Smm16Entry + AddressMap.Size);
  CopyMem (Info, SmmEntryInfo, sizeof (SMM_FOUNDATION_TABLE));

  Info->CoreSmmBase = (UINT32) Smm16Entry;

  //Add this to link list

  if (mSmmInfoListHead == NULL) {
    mSmmInfoListHead = &Info->Link;
    InitializeListHead (mSmmInfoListHead);
  } else {
    // Create a link list so that each core can parse to other cores Smm info
    InsertTailList (mSmmInfoListHead, &Info->Link);
  }

  return (Status);
}