Пример #1
0
/**
   Transfers control to DxeCore.

   This function performs a CPU architecture specific operations to execute
   the entry point of DxeCore with the parameters of HobList.
   It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase.

   @param DxeCoreEntryPoint         The entry point of DxeCore.
   @param HobList                   The start of HobList passed to DxeCore.

**/
VOID
HandOffToDxeCore (
  IN EFI_PHYSICAL_ADDRESS   DxeCoreEntryPoint,
  IN EFI_PEI_HOB_POINTERS   HobList
  )
{
  VOID                *BaseOfStack;
  VOID                *TopOfStack;
  EFI_STATUS          Status;
  UINTN               PageTables;

  //
  // Allocate 128KB for the Stack
  //
  BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE));
  ASSERT (BaseOfStack != NULL);

  //
  // Compute the top of the stack we were allocated. Pre-allocate a UINTN
  // for safety.
  //
  TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
  TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);

  PageTables = 0;
  if (FeaturePcdGet (PcdDxeIplBuildPageTables)) {
    //
    // Create page table and save PageMapLevel4 to CR3
    //
    PageTables = CreateIdentityMappingPageTables ();
  }
  
  //
  // End of PEI phase signal
  //
  Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
  ASSERT_EFI_ERROR (Status);

  if (FeaturePcdGet (PcdDxeIplBuildPageTables)) {
    AsmWriteCr3 (PageTables);
  }

  //
  // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
  //    
  UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, STACK_SIZE);

  //
  // Transfer the control to the entry point of DxeCore.
  //
  SwitchStack (
    (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
    HobList.Raw,
    NULL,
    TopOfStack
    );
}
Пример #2
0
int
main (
  int argc,
  char **argv
  )
{
  VOID        *BaseMemory;
  INTN        result;
  CHAR8       *OutputFile = NULL;
  CHAR8       *InputFile = NULL;
  EFI_STATUS  Status;
  UINT64      TempValue;

  SetUtilityName("GenPage");

  if (argc == 1) {
    Usage();
    return STATUS_ERROR;
  }
  
  argc --;
  argv ++;

  if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
    Usage();
    return 0;    
  }

  if (stricmp (argv[0], "--version") == 0) {
    Version();
    return 0;    
  }
  
  while (argc > 0) {
    if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {
      if (argv[1] == NULL || argv[1][0] == '-') {
        Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option");
        return STATUS_ERROR;
      }
      OutputFile = argv[1];
      argc -= 2;
      argv += 2;
      continue; 
    }
    
    if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--baseaddr") == 0)) {
      if (argv[1] == NULL || argv[1][0] == '-') {
        Error (NULL, 0, 1003, "Invalid option value", "Base address is missing for -b option");
        return STATUS_ERROR;
      }
      Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue);
      if (EFI_ERROR (Status)) {
        Error (NULL, 0, 1003, "Invalid option value", "Base address is not valid intergrator");
        return STATUS_ERROR;
      }
      gPageTableBaseAddress = (UINT32) TempValue;
      argc -= 2;
      argv += 2;
      continue; 
    }
    
    if ((stricmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--offset") == 0)) {
      if (argv[1] == NULL || argv[1][0] == '-') {
        Error (NULL, 0, 1003, "Invalid option value", "Offset is missing for -f option");
        return STATUS_ERROR;
      }
      Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue);
      if (EFI_ERROR (Status)) {
        Error (NULL, 0, 1003, "Invalid option value", "Offset is not valid intergrator");
        return STATUS_ERROR;
      }
      gPageTableOffsetInFile = (UINT32) TempValue;
      argc -= 2;
      argv += 2;
      continue; 
    }

    if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
      argc --;
      argv ++;
      continue; 
    }
    
    if ((stricmp (argv[0], "-v") ==0) || (stricmp (argv[0], "--verbose") == 0)) {
      argc --;
      argv ++;
      continue; 
    }
    
    if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
      if (argv[1] == NULL || argv[1][0] == '-') {
        Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not specified.");
        return STATUS_ERROR;
      }
      Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue);
      if (EFI_ERROR (Status)) {
        Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not valid intergrator.");
        return STATUS_ERROR;
      }
      if (TempValue > 9) {
        Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) TempValue);
        return STATUS_ERROR;
      }
      argc -= 2;
      argv += 2;
      continue; 
    }

    if (argv[0][0] == '-') {
      Error (NULL, 0, 1000, "Unknown option", argv[0]);
      return STATUS_ERROR;
    }
    
    //
    // Don't recognize the parameter.
    //
    InputFile = argv[0];
    argc--;
    argv++;
  }
  
  if (InputFile == NULL) {
    Error (NULL, 0, 1003, "Invalid option value", "Input file is not specified");
    return STATUS_ERROR;
  }
  
  //
  // Create X64 page table
  //
  BaseMemory = CreateIdentityMappingPageTables ();

  //
  // Add page table to binary file
  //
  result = GenBinPage (BaseMemory, InputFile, OutputFile);
  if (result < 0) {
    return STATUS_ERROR;
  }

  return 0;
}
Пример #3
0
/*---------------------------------------------------------------------------------------*/
EFI_STATUS InitSmmFoundationCode (
  IN       EFI_SMM_ACCESS2_PROTOCOL   *SmmAccess,
  IN       UINTN                      TsegBase,
  IN       UINTN                      TsegSize,
  IN       UINTN                      SmmFoundationBase
  )
{

  EFI_STATUS                    Status;
  UINTN                         ImageSize;
  EFI_IMAGE_ENTRY_POINT         Smm64Entry;
  UINTN                         i;
  EFI_PHYSICAL_ADDRESS          Smm16Entry;
  EFI_PHYSICAL_ADDRESS          Smm16Size;
  EFI_PHYSICAL_ADDRESS          Smm16Start;
  UINT8                         CoreCount;
  SMM_FOUNDATION_TABLE          SmmInfo;
  EFI_PHYSICAL_ADDRESS          PageTableEnd;
  UINTN                         SmmStackSize;

  //PageTable+Smm64Entry+Smm16Entry are placed towards the end of Tseg. Carve the reserve space at the end

  // find the total no. of AP's in the system
  CoreCount = (UINT8)GetTotalCpuCores ();
  if (!CoreCount) {
    return (EFI_NOT_FOUND);
  }

  DEBUG ((DEBUG_INFO, "InitSmmFoundationCode:: TsegBase %08x TsegSize %08x SmmFoundationBase %08x\n", TsegBase, TsegSize, SmmFoundationBase));


  // First create PageTable at SmmFoundationBase. Needed for 16->64 bit CPU mode
  PageTableEnd = CreateIdentityMappingPageTables (SmmFoundationBase);
  DEBUG ((DEBUG_INFO, "Loaded PageTable at %016x\n", SmmFoundationBase));
  DEBUG ((DEBUG_INFO, "PageTable ends at %016x\n", PageTableEnd));
  // Make sure Page Table doesn't overrun size allotted for it.  Leave 1MB for
  // rest of SmmFoundation code.
  if (PageTableEnd > (EFI_PHYSICAL_ADDRESS) (TsegBase + TsegSize - 0x100000)) {
    DEBUG ((DEBUG_ERROR, "Page Table overflowed allotted space\n"));
    ASSERT (FALSE);
  }
  // Next load Smm64 entry point after PageTable ends
  Status = LoadExeFileInMemory (&SMM64EntryFileGuid ,
                  EFI_SECTION_PE32,
                  (EFI_PHYSICAL_ADDRESS)PageTableEnd,
                  &ImageSize,
                 &Smm64Entry);

  if (EFI_ERROR (Status)) {
    return Status;
  }

  DEBUG ((DEBUG_INFO, "Loaded Smm64Foundation at %08x\n", Smm64Entry));

  // PageTable and Smm64 foundation code is in Tseg. This is shared by all core. Next build Smm16Entry
  // for each core
  Smm16Size = AsmGetSmm16CodeSize ();
  SmmStackSize = GetSmmStackSize ();

  // Smm16Start after PageTable, Smm64 code. Align to 0x200
  Smm16Start = ((PageTableEnd + ImageSize + 0x1ff) / 0x200) * 0x200,

  ZeroMem (&SmmInfo, sizeof (SmmInfo));

  // Indicate no SMM Entry has been identified yet, and need to initialize everything.
  Smm16Entry = NULL;

  // Relocate all the CPU cores
  for (i = 0; i < CoreCount; i++) {

    // Open the SMM area to build SMM PageTable and copy Smm Foundation code
    // After CPU rsm the SMM area may be closed so make sure to enable again
    Status = SmmAccess->Open (mSmmAccess);

    // Find the next available SMM base for Smm16Entry code for each core and update Smm16Entry variable
    // Smm16 code for each core is after Smm64 foundation code
    Status = FindNextAvailableSmm16EntryBase (
                    Smm16Start,
                    (EFI_PHYSICAL_ADDRESS) TsegBase + TsegSize,
                    Smm16Size,
                    &Smm16Entry
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }


    // Update SmmInfo foundation table
    SmmInfo.StackBase             = TsegBase + TsegSize - (i * SmmStackSize);
    SmmInfo.StackSize             = SmmStackSize;
    SmmInfo.UefiSmmCoreBase       = 0;
    SmmInfo.TotalCores            = CoreCount;
    SmmInfo.CoreSmmBase           = Smm16Entry;
    SmmInfo.Smm64Entry            = Smm64Entry;
    SmmInfo.CpuNumber             = (UINT8) i;
    SmmInfo.ApicId                = GetCoreApicId (SmmInfo.CpuNumber);


    // Check Smm code and Stack are not overlapping
    if (SmmInfo.CoreSmmBase + Smm16Size > SmmInfo.StackBase - SmmStackSize) {
      return EFI_OUT_OF_RESOURCES;
    }

    DEBUG ((DEBUG_INFO, "Core %x Smm16Foundation at %08x Stack at %08x \n", i, SmmInfo.CoreSmmBase, SmmInfo.StackBase));
    // Prepare Smm16 Startup code at Tseg ie. update the SmmInfo structure in Smm16Entry location of each core
    Status = PrepareSmmStartupVector (
                Smm16Entry,
                SmmFoundationBase,
                &SmmInfo
                );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    // Send SIPI to each core to set new SmmBase at Tseg (default 0x38000)
    Status = RelocateSmmBase (
                i,
                Smm16Entry - 0x8000,              // newSmmBase
                TsegBase,                         // TsegBase
                (UINT32)TsegSize                  // TsegSize
                );

    if (EFI_ERROR (Status)) {
      return Status;
    }

    SmmAccess->Close (mSmmAccess);
  }


  // Finally send Sipi to all core to test if responding. Add correction if necessary - FMO
  SendSmiIpl (0xff);

  DEBUG ((DEBUG_INFO, "Unused SmmFoundation space %08x \n", (SmmInfo.StackBase - SmmStackSize) - (SmmInfo.CoreSmmBase + Smm16Size)));

  return EFI_SUCCESS;
}
Пример #4
0
/**
   Transfers control to DxeCore.

   This function performs a CPU architecture specific operations to execute
   the entry point of DxeCore with the parameters of HobList.
   It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase.

   @param DxeCoreEntryPoint         The entry point of DxeCore.
   @param HobList                   The start of HobList passed to DxeCore.

**/
VOID
HandOffToDxeCore (
  IN EFI_PHYSICAL_ADDRESS   DxeCoreEntryPoint,
  IN EFI_PEI_HOB_POINTERS   HobList
  )
{
  EFI_STATUS                Status;
  EFI_PHYSICAL_ADDRESS      BaseOfStack;
  EFI_PHYSICAL_ADDRESS      TopOfStack;
  UINTN                     PageTables;
  X64_IDT_GATE_DESCRIPTOR   *IdtTable;
  UINTN                     SizeOfTemplate;
  VOID                      *TemplateBase;
  EFI_PHYSICAL_ADDRESS      VectorAddress;
  UINT32                    Index;
  X64_IDT_TABLE             *IdtTableForX64;
  EFI_VECTOR_HANDOFF_INFO   *VectorInfo;
  EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
  BOOLEAN                   BuildPageTablesIa32Pae;

  if (IsNullDetectionEnabled ()) {
    ClearFirst4KPage (HobList.Raw);
  }

  Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);
  ASSERT_EFI_ERROR (Status);

  if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) {
    //
    // Compute the top of the stack we were allocated, which is used to load X64 dxe core.
    // Pre-allocate a 32 bytes which confroms to x64 calling convention.
    //
    // The first four parameters to a function are passed in rcx, rdx, r8 and r9.
    // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the
    // register parameters is reserved on the stack, in case the called function
    // wants to spill them; this is important if the function is variadic.
    //
    TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;

    //
    //  x64 Calling Conventions requires that the stack must be aligned to 16 bytes
    //
    TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16);

    //
    // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA
    // memory, it may be corrupted when copying FV to high-end memory
    //
    AsmWriteGdtr (&gGdt);
    //
    // Create page table and save PageMapLevel4 to CR3
    //
    PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE);

    //
    // End of PEI phase signal
    //
    PERF_EVENT_SIGNAL_BEGIN (gEndOfPeiSignalPpi.Guid);
    Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
    PERF_EVENT_SIGNAL_END (gEndOfPeiSignalPpi.Guid);
    ASSERT_EFI_ERROR (Status);

    //
    // Paging might be already enabled. To avoid conflict configuration,
    // disable paging first anyway.
    //
    AsmWriteCr0 (AsmReadCr0 () & (~BIT31));
    AsmWriteCr3 (PageTables);

    //
    // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
    //
    UpdateStackHob (BaseOfStack, STACK_SIZE);

    SizeOfTemplate = AsmGetVectorTemplatInfo (&TemplateBase);

    Status = PeiServicesAllocatePages (
               EfiBootServicesData,
               EFI_SIZE_TO_PAGES(sizeof (X64_IDT_TABLE) + SizeOfTemplate * IDT_ENTRY_COUNT),
               &VectorAddress
               );
    ASSERT_EFI_ERROR (Status);

    //
    // Store EFI_PEI_SERVICES** in the 4 bytes immediately preceding IDT to avoid that
    // it may not be gotten correctly after IDT register is re-written.
    //
    IdtTableForX64 = (X64_IDT_TABLE *) (UINTN) VectorAddress;
    IdtTableForX64->PeiService = GetPeiServicesTablePointer ();

    VectorAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (IdtTableForX64 + 1);
    IdtTable      = IdtTableForX64->IdtTable;
    for (Index = 0; Index < IDT_ENTRY_COUNT; Index++) {
      IdtTable[Index].Ia32IdtEntry.Bits.GateType    =  0x8e;
      IdtTable[Index].Ia32IdtEntry.Bits.Reserved_0  =  0;
      IdtTable[Index].Ia32IdtEntry.Bits.Selector    =  SYS_CODE64_SEL;

      IdtTable[Index].Ia32IdtEntry.Bits.OffsetLow   = (UINT16) VectorAddress;
      IdtTable[Index].Ia32IdtEntry.Bits.OffsetHigh  = (UINT16) (RShiftU64 (VectorAddress, 16));
      IdtTable[Index].Offset32To63                  = (UINT32) (RShiftU64 (VectorAddress, 32));
      IdtTable[Index].Reserved                      = 0;

      CopyMem ((VOID *) (UINTN) VectorAddress, TemplateBase, SizeOfTemplate);
      AsmVectorFixup ((VOID *) (UINTN) VectorAddress, (UINT8) Index);

      VectorAddress += SizeOfTemplate;
    }

    gLidtDescriptor.Base = (UINTN) IdtTable;

    //
    // Disable interrupt of Debug timer, since new IDT table cannot handle it.
    //
    SaveAndSetDebugTimerInterrupt (FALSE);

    AsmWriteIdtr (&gLidtDescriptor);

    DEBUG ((
      DEBUG_INFO,
      "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n",
      __FUNCTION__,
      BaseOfStack,
      STACK_SIZE
      ));

    //
    // Go to Long Mode and transfer control to DxeCore.
    // Interrupts will not get turned on until the CPU AP is loaded.
    // Call x64 drivers passing in single argument, a pointer to the HOBs.
    //
    AsmEnablePaging64 (
      SYS_CODE64_SEL,
      DxeCoreEntryPoint,
      (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw),
      0,
      TopOfStack
      );
  } else {
    //
    // Get Vector Hand-off Info PPI and build Guided HOB
    //
    Status = PeiServicesLocatePpi (
               &gEfiVectorHandoffInfoPpiGuid,
               0,
               NULL,
               (VOID **)&VectorHandoffInfoPpi
               );
    if (Status == EFI_SUCCESS) {
      DEBUG ((EFI_D_INFO, "Vector Hand-off Info PPI is gotten, GUIDed HOB is created!\n"));
      VectorInfo = VectorHandoffInfoPpi->Info;
      Index = 1;
      while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) {
        VectorInfo ++;
        Index ++;
      }
      BuildGuidDataHob (
        &gEfiVectorHandoffInfoPpiGuid,
        VectorHandoffInfoPpi->Info,
        sizeof (EFI_VECTOR_HANDOFF_INFO) * Index
        );
    }

    //
    // Compute the top of the stack we were allocated. Pre-allocate a UINTN
    // for safety.
    //
    TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT;
    TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);

    PageTables = 0;
    BuildPageTablesIa32Pae = ToBuildPageTable ();
    if (BuildPageTablesIa32Pae) {
      PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE);
      if (IsEnableNonExecNeeded ()) {
        EnableExecuteDisableBit();
      }
    }

    //
    // End of PEI phase signal
    //
    PERF_EVENT_SIGNAL_BEGIN (gEndOfPeiSignalPpi.Guid);
    Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
    PERF_EVENT_SIGNAL_END (gEndOfPeiSignalPpi.Guid);
    ASSERT_EFI_ERROR (Status);

    if (BuildPageTablesIa32Pae) {
      //
      // Paging might be already enabled. To avoid conflict configuration,
      // disable paging first anyway.
      //
      AsmWriteCr0 (AsmReadCr0 () & (~BIT31));
      AsmWriteCr3 (PageTables);
      //
      // Set Physical Address Extension (bit 5 of CR4).
      //
      AsmWriteCr4 (AsmReadCr4 () | BIT5);
    }

    //
    // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
    //
    UpdateStackHob (BaseOfStack, STACK_SIZE);

    DEBUG ((
      DEBUG_INFO,
      "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n",
      __FUNCTION__,
      BaseOfStack,
      STACK_SIZE
      ));

    //
    // Transfer the control to the entry point of DxeCore.
    //
    if (BuildPageTablesIa32Pae) {
      AsmEnablePaging32 (
        (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
        HobList.Raw,
        NULL,
        (VOID *) (UINTN) TopOfStack
        );
    } else {
      SwitchStack (
        (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
        HobList.Raw,
        NULL,
        (VOID *) (UINTN) TopOfStack
        );
    }
  }
}