/** Entry point of this module. @param[in] FileHandle Handle of the file being invoked. @param[in] PeiServices Describes the list of possible PEI Services. @return Status. **/ EFI_STATUS EFIAPI PeimEntryMA ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; EFI_BOOT_MODE BootMode; TIS_TPM_HANDLE TpmHandle; if (PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm)) { return EFI_UNSUPPORTED; } Status = (**PeiServices).RegisterForShadow(FileHandle); if (Status == EFI_ALREADY_STARTED) { mImageInMemory = TRUE; } else if (Status == EFI_NOT_FOUND) { ASSERT_EFI_ERROR (Status); } if (!mImageInMemory) { // // Initialize TPM device // Status = PeiServicesGetBootMode (&BootMode); ASSERT_EFI_ERROR (Status); TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS; Status = TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)TpmHandle); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "TPM not detected!\n")); return Status; } Status = TpmCommStartup ((EFI_PEI_SERVICES**)PeiServices, TpmHandle, BootMode); if (EFI_ERROR (Status) ) { return Status; } Status = TpmCommContinueSelfTest ((EFI_PEI_SERVICES**)PeiServices, TpmHandle); if (EFI_ERROR (Status)) { return Status; } Status = PeiServicesInstallPpi (&mTpmInitializedPpiList); ASSERT_EFI_ERROR (Status); } if (mImageInMemory) { Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices); if (EFI_ERROR (Status)) { return Status; } } return Status; }
/** Locates and extracts the QEMU SMBIOS data if present in fw_cfg @return Address of extracted QEMU SMBIOS data **/ UINT8 * GetQemuSmbiosTables ( VOID ) { EFI_STATUS Status; FIRMWARE_CONFIG_ITEM Tables; UINTN TablesSize; UINT8 *QemuTables; if (!PcdGetBool (PcdQemuSmbiosValidated)) { return NULL; } Status = QemuFwCfgFindFile ("etc/smbios/smbios-tables", &Tables, &TablesSize); ASSERT_EFI_ERROR (Status); ASSERT (TablesSize > 0); QemuTables = AllocatePool (TablesSize); if (QemuTables == NULL) { return NULL; } QemuFwCfgSelectItem (Tables); QemuFwCfgReadBytes (TablesSize, QemuTables); return QemuTables; }
/** Get ACPI S3 enable flag. **/ VOID GetAcpiS3EnableFlag ( VOID ) { mAcpiS3Enable = PcdGetBool (PcdAcpiS3Enable); }
/** The function will check if page table should be setup or not. @retval TRUE Page table should be created. @retval FALSE Page table should not be created. **/ BOOLEAN ToBuildPageTable ( VOID ) { if (!IsIa32PaeSupport ()) { return FALSE; } if (IsNullDetectionEnabled ()) { return TRUE; } if (PcdGet8 (PcdHeapGuardPropertyMask) != 0) { return TRUE; } if (PcdGetBool (PcdCpuStackGuard)) { return TRUE; } if (IsEnableNonExecNeeded ()) { return TRUE; } return FALSE; }
/** Support routine to get the Image read file function. @param ImageContext - The context of the image being loaded @retval EFI_SUCCESS - If Image function location is found **/ EFI_STATUS GetImageReadFunction ( IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext ) { PEI_CORE_INSTANCE *Private; VOID* MemoryBuffer; Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); if (Private->PeiMemoryInstalled && (((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnBoot)) || ((Private->HobList.HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnS3Boot))) && (EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64) || EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_IA32))) { // // Shadow algorithm makes lots of non ANSI C assumptions and only works for IA32 and X64 // compilers that have been tested // if (Private->ShadowedImageRead == NULL) { MemoryBuffer = AllocatePages (0x400 / EFI_PAGE_SIZE + 1); ASSERT (MemoryBuffer != NULL); CopyMem (MemoryBuffer, (CONST VOID *) (UINTN) PeiImageReadForShadow, 0x400); Private->ShadowedImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer; } ImageContext->ImageRead = Private->ShadowedImageRead; } else { ImageContext->ImageRead = PeiImageRead; } return EFI_SUCCESS; }
STATIC VOID SetSocIdStatus ( IN VOID *Fdt ) { UINT32 SocId; BOOLEAN IsRevB1; BOOLEAN DisableXgbeSmmus; SocId = PcdGet32 (PcdSocCpuId); IsRevB1 = (SocId & STYX_SOC_VERSION_MASK) >= STYX_SOC_VERSION_B1; SetDeviceStatus (Fdt, "sata@e0d00000", IsRevB1 && FixedPcdGet8 (PcdSata1PortCount) > 0); SetDeviceStatus (Fdt, "gpio@e0020000", IsRevB1); SetDeviceStatus (Fdt, "gpio@e0030000", IsRevB1); SetDeviceStatus (Fdt, "gwdt@e0bb0000", IsRevB1); #if DO_KCS SetDeviceStatus (Fdt, "kcs@e0010000", IsRevB1); #else SetDeviceStatus (Fdt, "kcs@e0010000", FALSE); #endif if (!PcdGetBool (PcdEnableSmmus)) { DisableSmmu (Fdt, "iommu-map", "/smb/smmu@e0a00000", "/smb/pcie@f0000000"); DisableSmmu (Fdt, "iommus", "/smb/smmu@e0200000", "/smb/sata@e0300000"); } if (!PcdGetBool (PcdEnableSmmus) || !IsRevB1 || FixedPcdGet8 (PcdSata1PortCount) == 0) { DisableSmmu (Fdt, "iommus", "/smb/smmu@e0c00000", "/smb/sata@e0d00000"); } #if DO_XGBE DisableXgbeSmmus = !PcdGetBool (PcdEnableSmmus); #else DisableXgbeSmmus = TRUE; #endif if (DisableXgbeSmmus) { DisableSmmu (Fdt, "iommus", "/smb/smmu@e0600000", "/smb/xgmac@e0700000"); DisableSmmu (Fdt, "iommus", "/smb/smmu@e0800000", "/smb/xgmac@e0900000"); } }
/** This interface returns whether TPM physical presence needs be locked or not. @param[in] PeiServices The pointer to the PEI Services Table. @retval TRUE The TPM physical presence should be locked. @retval FALSE The TPM physical presence cannot be locked. **/ BOOLEAN EFIAPI LockTpmPhysicalPresence ( IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; UINTN DataSize; EFI_PHYSICAL_PRESENCE TcgPpData; // // The CRTM has sensed the physical presence assertion of the user. For example, // the user has pressed the startup button or inserted a USB dongle. The details // of the implementation are vendor-specific. Here we read a PCD value to indicate // whether operator physical presence. // if (!PcdGetBool (PcdTpmPhysicalPresence)) { return TRUE; } // // Check the pending TPM requests. Lock TPM physical presence if there is no TPM // request. // Status = PeiServicesLocatePpi ( &gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **)&Variable ); if (!EFI_ERROR (Status)) { DataSize = sizeof (EFI_PHYSICAL_PRESENCE); Status = Variable->GetVariable ( Variable, PHYSICAL_PRESENCE_VARIABLE, &gEfiPhysicalPresenceGuid, NULL, &DataSize, &TcgPpData ); if (!EFI_ERROR (Status)) { if (TcgPpData.PPRequest != 0) { return FALSE; } } } // // Lock TPM physical presence by default. // return TRUE; }
/** Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group. This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group. @param Event Event whose notification function is being invoked. @param Context Pointer to the notification function's context. **/ VOID EFIAPI OnEndOfDxe ( EFI_EVENT Event, VOID *Context ) { mEndOfDxe = TRUE; if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) { ReclaimForOS (); } }
/** This function attempts to boot per the boot order specified by platform policy. If the boot via Boot#### returns with a status of EFI_SUCCESS the boot manager will stop processing the BootOrder variable and present a boot manager menu to the user. If a boot via Boot#### returns a status other than EFI_SUCCESS, the boot has failed and the next Boot#### in the BootOrder variable will be tried until all possibilities are exhausted. -- Chapter 3.1.1 Boot Manager Programming, the 4th paragraph **/ VOID DefaultBootBehavior ( VOID ) { UINTN BootOptionCount; EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu; EfiBootManagerGetBootManagerMenu (&BootManagerMenu); // // BootManagerMenu always contains the correct information even the above function returns failure. // BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); if (BootAllBootOptions (BootOptions, BootOptionCount)) { // // Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI // if (PcdGetBool (PcdConInConnectOnDemand)) { BdsDxeOnConnectConInCallBack (NULL, NULL); } // // Show the Boot Manager Menu after successful boot // EfiBootManagerBoot (&BootManagerMenu); } else { EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); // // Re-scan all EFI boot options in case all the boot#### are deleted or failed to boot // // If no valid boot options exist, the boot manager will enumerate all removable media // devices followed by all fixed media devices. The order within each group is undefined. // These new default boot options are not saved to non volatile storage.The boot manger // will then attempt toboot from each boot option. // -- Chapter 3.3 Boot Manager Programming, the 2nd paragraph // EfiBootManagerConnectAll (); BootOptions = BdsEnumerateBootOptions (&BootOptionCount); if (!BootAllBootOptions (BootOptions, BootOptionCount)) { DEBUG ((EFI_D_ERROR, "[Bds]No bootable device!\n")); EfiBootManagerBoot (&BootManagerMenu); } } EfiBootManagerFreeLoadOption (&BootManagerMenu); EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); }
/** SMM END_OF_DXE protocol notification event handler. @param Protocol Points to the protocol's unique identifier @param Interface Points to the interface instance @param Handle The handle on which the interface was installed @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully **/ EFI_STATUS EFIAPI SmmEndOfDxeCallback ( IN CONST EFI_GUID *Protocol, IN VOID *Interface, IN EFI_HANDLE Handle ) { DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n")); mEndOfDxe = TRUE; if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) { ReclaimForOS (); } return EFI_SUCCESS; }
/** Determines if a user is physically present by reading the reset button state. @param ImageHandle The image handle of this driver. @param SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS Install the Secure Boot Helper Protocol successfully. **/ EFI_STATUS EFIAPI PlatformSecureLibInitialize ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { // // Read the state of the reset button when the library is initialized // mUserIsPhysicallyPresent = PcdGetBool (PcdUserIsPhysicallyPresent); DEBUG((EFI_D_INFO, "UserIsPhysicallyPresent - 0x%x\n", mUserIsPhysicallyPresent)); return EFI_SUCCESS; }
/** 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; // // Allocate 128KB for the Stack // BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE)); ASSERT (BaseOfStack != NULL); if (PcdGetBool (PcdSetNxForStack)) { Status = ArmSetMemoryRegionNoExec ((UINTN)BaseOfStack, STACK_SIZE); ASSERT_EFI_ERROR (Status); } // // 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); // // End of PEI phase singal // Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi); ASSERT_EFI_ERROR (Status); // // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. // UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, STACK_SIZE); SwitchStack ( (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, HobList.Raw, NULL, TopOfStack ); }
/** CPU Features driver entry point function. If PcdCpuFeaturesInitAfterSmmRelocation is TRUE, it will register one SMM Configuration Protocol notify function to perform CPU features initialization. Otherwise, it will perform CPU features initialization directly. @param ImageHandle Image handle this driver. @param SystemTable Pointer to the System Table. @retval EFI_SUCCESS CPU Features is initialized successfully. **/ EFI_STATUS EFIAPI CpuFeaturesDxeInitialize ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { VOID *Registration; EFI_STATUS Status; EFI_HANDLE Handle; if (GetFirstGuidHob (&gEdkiiCpuFeaturesInitDoneGuid) != NULL) { // // Try to find HOB first. This HOB exist means CPU features have // been initialized by CpuFeaturesPei driver, just install // gEdkiiCpuFeaturesInitDoneGuid. // Handle = NULL; Status = gBS->InstallProtocolInterface ( &Handle, &gEdkiiCpuFeaturesInitDoneGuid, EFI_NATIVE_INTERFACE, NULL ); ASSERT_EFI_ERROR (Status); return Status; } if (PcdGetBool (PcdCpuFeaturesInitAfterSmmRelocation)) { // // Install notification callback on SMM Configuration Protocol // EfiCreateProtocolNotifyEvent ( &gEfiSmmConfigurationProtocolGuid, TPL_CALLBACK, SmmConfigurationEventNotify, NULL, &Registration ); } else { CpuFeaturesInitializeWorker (); } return EFI_SUCCESS; }
/** Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group. This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group. @param Event Event whose notification function is being invoked. @param Context Pointer to the notification function's context. **/ VOID EFIAPI OnEndOfDxe ( EFI_EVENT Event, VOID *Context ) { mEndOfDxe = TRUE; // // The initialization for variable quota. // InitializeVariableQuota (); if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) { ReclaimForOS (); } gBS->CloseEvent (Event); }
/** Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group. This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group. @param Event Event whose notification function is being invoked. @param Context Pointer to the notification function's context. **/ VOID EFIAPI OnEndOfDxe ( EFI_EVENT Event, VOID *Context ) { DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n")); mEndOfDxe = TRUE; mVarCheckAddressPointer = VarCheckLibInitializeAtEndOfDxe (&mVarCheckAddressPointerCount); // // The initialization for variable quota. // InitializeVariableQuota (); if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) { ReclaimForOS (); } gBS->CloseEvent (Event); }
/** SMM END_OF_DXE protocol notification event handler. @param Protocol Points to the protocol's unique identifier @param Interface Points to the interface instance @param Handle The handle on which the interface was installed @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully **/ EFI_STATUS EFIAPI SmmEndOfDxeCallback ( IN CONST EFI_GUID *Protocol, IN VOID *Interface, IN EFI_HANDLE Handle ) { DEBUG ((EFI_D_INFO, "[Variable]SMM_END_OF_DXE is signaled\n")); mEndOfDxe = TRUE; VarCheckLibInitializeAtEndOfDxe (NULL); // // The initialization for variable quota. // InitializeVariableQuota (); if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) { ReclaimForOS (); } return EFI_SUCCESS; }
/** This function checks the HTTP(S) URI scheme. @param[in] Uri The pointer to the URI string. @retval EFI_SUCCESS The URI scheme is valid. @retval EFI_INVALID_PARAMETER The URI scheme is not HTTP or HTTPS. @retval EFI_ACCESS_DENIED HTTP is disabled and the URI is HTTP. **/ EFI_STATUS HttpBootCheckUriScheme ( IN CHAR8 *Uri ) { UINTN Index; EFI_STATUS Status; Status = EFI_SUCCESS; // // Convert the scheme to all lower case. // for (Index = 0; Index < AsciiStrLen (Uri); Index++) { if (Uri[Index] == ':') { break; } if (Uri[Index] >= 'A' && Uri[Index] <= 'Z') { Uri[Index] -= (CHAR8)('A' - 'a'); } } // // Return EFI_INVALID_PARAMETER if the URI is not HTTP or HTTPS. // if ((AsciiStrnCmp (Uri, "http://", 7) != 0) && (AsciiStrnCmp (Uri, "https://", 8) != 0)) { DEBUG ((EFI_D_ERROR, "HttpBootCheckUriScheme: Invalid Uri.\n")); return EFI_INVALID_PARAMETER; } // // HTTP is disabled, return EFI_ACCESS_DENIED if the URI is HTTP. // if (!PcdGetBool (PcdAllowHttpConnections) && (AsciiStrnCmp (Uri, "http://", 7) == 0)) { DEBUG ((EFI_D_ERROR, "HttpBootCheckUriScheme: HTTP is disabled.\n")); return EFI_ACCESS_DENIED; } return Status; }
EFI_STATUS EFIAPI AcpiPlatformEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_EVENT RootBridgesConnected; // // If the platform doesn't support PCI, or PCI enumeration has been disabled, // install the tables at once, and let the entry point's return code reflect // the full functionality. // if (PcdGetBool (PcdPciDisableBusEnumeration)) { DEBUG ((EFI_D_INFO, "%a: PCI or its enumeration disabled, installing " "ACPI tables\n", __FUNCTION__)); return InstallAcpiTables (FindAcpiTableProtocol ()); } // // Otherwise, delay installing the ACPI tables until root bridges are // connected. The entry point's return status will only reflect the callback // setup. (Note that we're a DXE_DRIVER; our entry point function is invoked // strictly before BDS is entered and can connect the root bridges.) // Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, OnRootBridgesConnected, NULL /* Context */, &gRootBridgesConnectedEventGroupGuid, &RootBridgesConnected); if (!EFI_ERROR (Status)) { DEBUG ((EFI_D_INFO, "%a: waiting for root bridges to be connected, registered callback\n", __FUNCTION__)); } return Status; }
/** The function reads user inputs. **/ VOID BdsReadKeys ( VOID ) { EFI_STATUS Status; EFI_INPUT_KEY Key; if (PcdGetBool (PcdConInConnectOnDemand)) { return; } while (gST->ConIn != NULL) { Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); if (EFI_ERROR (Status)) { // // No more keys. // break; } } }
// // If support CPU hot plug, PcdCpuSmmEnableBspElection should be set to TRUE. // A constant BSP index makes no sense because it may be hot removed. // DEBUG_CODE ( if (FeaturePcdGet (PcdCpuHotPlugSupport)) { ASSERT (FeaturePcdGet (PcdCpuSmmEnableBspElection)); } ); // // Save the PcdCpuSmmCodeAccessCheckEnable value into a global variable. // mSmmCodeAccessCheckEnable = PcdGetBool (PcdCpuSmmCodeAccessCheckEnable); DEBUG ((EFI_D_INFO, "PcdCpuSmmCodeAccessCheckEnable = %d\n", mSmmCodeAccessCheckEnable)); // // If support CPU hot plug, we need to allocate resources for possibly hot-added processors // if (FeaturePcdGet (PcdCpuHotPlugSupport)) { mMaxNumberOfCpus = PcdGet32 (PcdCpuMaxLogicalProcessorNumber); } else { mMaxNumberOfCpus = mNumberOfCpus; } gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus = mMaxNumberOfCpus; // // The CPU save state and code for the SMI entry point are tiled within an SMRAM // allocated buffer. The minimum size of this buffer for a uniprocessor system
/** Perform the memory test base on the memory test intensive level, and update the memory resource. @param Level The memory test intensive level. @retval EFI_STATUS Success test all the system memory and update the memory resource **/ EFI_STATUS EFIAPI BdsMemoryTest ( IN EXTENDMEM_COVERAGE_LEVEL Level ) { EFI_STATUS Status; EFI_STATUS KeyStatus; EFI_STATUS InitStatus; EFI_STATUS ReturnStatus; BOOLEAN RequireSoftECCInit; EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; UINT64 TestedMemorySize; UINT64 TotalMemorySize; UINTN TestPercent; UINT64 PreviousValue; BOOLEAN ErrorOut; BOOLEAN TestAbort; EFI_INPUT_KEY Key; CHAR16 StrPercent[80]; CHAR16 *StrTotalMemory; CHAR16 *Pos; CHAR16 *TmpStr; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; BOOLEAN IsFirstBoot; UINT32 TempData; UINTN StrTotalMemorySize; ReturnStatus = EFI_SUCCESS; ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); StrTotalMemorySize = 128; Pos = AllocateZeroPool (StrTotalMemorySize); if (Pos == NULL) { return ReturnStatus; } StrTotalMemory = Pos; TestedMemorySize = 0; TotalMemorySize = 0; PreviousValue = 0; ErrorOut = FALSE; TestAbort = FALSE; SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff); RequireSoftECCInit = FALSE; Status = gBS->LocateProtocol ( &gEfiGenericMemTestProtocolGuid, NULL, (VOID **) &GenMemoryTest ); if (EFI_ERROR (Status)) { FreePool (Pos); return EFI_SUCCESS; } InitStatus = GenMemoryTest->MemoryTestInit ( GenMemoryTest, Level, &RequireSoftECCInit ); if (InitStatus == EFI_NO_MEDIA) { // // The PEI codes also have the relevant memory test code to check the memory, // it can select to test some range of the memory or all of them. If PEI code // checks all the memory, this BDS memory test will has no not-test memory to // do the test, and then the status of EFI_NO_MEDIA will be returned by // "MemoryTestInit". So it does not need to test memory again, just return. // FreePool (Pos); return EFI_SUCCESS; } if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST)); if (TmpStr != NULL) { PrintXY (10, 10, NULL, NULL, TmpStr); FreePool (TmpStr); } } else { DEBUG ((EFI_D_INFO, "Enter memory test.\n")); } do { Status = GenMemoryTest->PerformMemoryTest ( GenMemoryTest, &TestedMemorySize, &TotalMemorySize, &ErrorOut, TestAbort ); if (ErrorOut && (Status == EFI_DEVICE_ERROR)) { TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR)); if (TmpStr != NULL) { PrintXY (10, 10, NULL, NULL, TmpStr); FreePool (TmpStr); } ASSERT (0); } if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TempData = (UINT32) DivU64x32 (TotalMemorySize, 16); TestPercent = (UINTN) DivU64x32 ( DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16), TempData ); if (TestPercent != PreviousValue) { UnicodeValueToString (StrPercent, 0, TestPercent, 0); TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT)); if (TmpStr != NULL) { // // TmpStr size is 64, StrPercent is reserved to 16. // StrCatS (StrPercent, sizeof (StrPercent) / sizeof (CHAR16), TmpStr); PrintXY (10, 10, NULL, NULL, StrPercent); FreePool (TmpStr); } TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); if (TmpStr != NULL) { PlatformBdsShowProgress ( Foreground, Background, TmpStr, Color, TestPercent, (UINTN) PreviousValue ); FreePool (TmpStr); } } PreviousValue = TestPercent; } else { DEBUG ((EFI_D_INFO, "Perform memory test (ESC to skip).\n")); } if (!PcdGetBool (PcdConInConnectOnDemand)) { KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) { if (!RequireSoftECCInit) { if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); if (TmpStr != NULL) { PlatformBdsShowProgress ( Foreground, Background, TmpStr, Color, 100, (UINTN) PreviousValue ); FreePool (TmpStr); } PrintXY (10, 10, NULL, NULL, L"100"); } Status = GenMemoryTest->Finished (GenMemoryTest); goto Done; } TestAbort = TRUE; } } } while (Status != EFI_NOT_FOUND); Status = GenMemoryTest->Finished (GenMemoryTest); Done: if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0); if (StrTotalMemory[0] == L',') { StrTotalMemory++; StrTotalMemorySize -= sizeof (CHAR16); } TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED)); if (TmpStr != NULL) { StrCatS (StrTotalMemory, StrTotalMemorySize / sizeof (CHAR16), TmpStr); FreePool (TmpStr); } PrintXY (10, 10, NULL, NULL, StrTotalMemory); PlatformBdsShowProgress ( Foreground, Background, StrTotalMemory, Color, 100, (UINTN) PreviousValue ); } else { DEBUG ((EFI_D_INFO, "%d bytes of system memory tested OK\r\n", TotalMemorySize)); } FreePool (Pos); // // Use a DynamicHii type pcd to save the boot status, which is used to // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration. // IsFirstBoot = PcdGetBool(PcdBootState); if (IsFirstBoot) { PcdSetBool(PcdBootState, FALSE); } return ReturnStatus; }
/** Create KEYBOARD_CONSOLE_IN_DEV instance on controller. @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL @param Controller driver controller handle @param RemainingDevicePath Children's device path @retval whether success to create floppy control instance. **/ EFI_STATUS EFIAPI KbdControllerDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_STATUS Status1; EFI_ISA_IO_PROTOCOL *IsaIo; KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; UINT8 Data; EFI_STATUS_CODE_VALUE StatusCode; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; StatusCode = 0; Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Report that the keyboard is being enabled // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE, ParentDevicePath ); // // Get the ISA I/O Protocol on Controller's handle // Status = gBS->OpenProtocol ( Controller, &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); return EFI_INVALID_PARAMETER; } // // Allocate private data // ConsoleIn = AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV)); if (ConsoleIn == NULL) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } // // Setup the device instance // ConsoleIn->Signature = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE; ConsoleIn->Handle = Controller; (ConsoleIn->ConIn).Reset = KeyboardEfiReset; (ConsoleIn->ConIn).ReadKeyStroke = KeyboardReadKeyStroke; ConsoleIn->DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER; ConsoleIn->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER; ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER; ConsoleIn->IsaIo = IsaIo; ConsoleIn->DevicePath = ParentDevicePath; ConsoleIn->ConInEx.Reset = KeyboardEfiResetEx; ConsoleIn->ConInEx.ReadKeyStrokeEx = KeyboardReadKeyStrokeEx; ConsoleIn->ConInEx.SetState = KeyboardSetState; ConsoleIn->ConInEx.RegisterKeyNotify = KeyboardRegisterKeyNotify; ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify; InitializeListHead (&ConsoleIn->NotifyList); // // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS. // When KBC decode (IO port 0x60/0x64 decode) is not enabled, // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS. // So instead we read status register to detect after read if KBC decode is enabled. // // // Return code is ignored on purpose. // if (!PcdGetBool (PcdFastPS2Detection)) { KeyboardRead (ConsoleIn, &Data); if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) { // // If nobody decodes KBC I/O port, it will read back as 0xFF. // Check the Time-Out and Parity bit to see if it has an active KBC in system // Status = EFI_DEVICE_ERROR; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; goto ErrorExit; } } // // Setup the WaitForKey event // Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, KeyboardWaitForKey, ConsoleIn, &((ConsoleIn->ConIn).WaitForKey) ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } // // Setup the WaitForKeyEx event // Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, KeyboardWaitForKeyEx, ConsoleIn, &(ConsoleIn->ConInEx.WaitForKeyEx) ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } // Setup a periodic timer, used for reading keystrokes at a fixed interval // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, KeyboardTimerHandler, ConsoleIn, &ConsoleIn->TimerEvent ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } Status = gBS->SetTimer ( ConsoleIn->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT, ParentDevicePath ); // // Reset the keyboard device // Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FeaturePcdGet (PcdPs2KbdExtendedVerification)); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; goto ErrorExit; } REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED, ParentDevicePath ); ConsoleIn->ControllerNameTable = NULL; AddUnicodeString2 ( "eng", gPs2KeyboardComponentName.SupportedLanguages, &ConsoleIn->ControllerNameTable, L"PS/2 Keyboard Device", TRUE ); AddUnicodeString2 ( "en", gPs2KeyboardComponentName2.SupportedLanguages, &ConsoleIn->ControllerNameTable, L"PS/2 Keyboard Device", FALSE ); // // Install protocol interfaces for the keyboard device. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiSimpleTextInProtocolGuid, &ConsoleIn->ConIn, &gEfiSimpleTextInputExProtocolGuid, &ConsoleIn->ConInEx, NULL ); if (EFI_ERROR (Status)) { StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } return Status; ErrorExit: // // Report error code // if (StatusCode != 0) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, StatusCode, ParentDevicePath ); } if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) { gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey); } if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) { gBS->CloseEvent (ConsoleIn->TimerEvent); } if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) { gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); } KbdFreeNotifyList (&ConsoleIn->NotifyList); if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) { FreeUnicodeStringTable (ConsoleIn->ControllerNameTable); } // // Since there will be no timer handler for keyboard input any more, // exhaust input data just in case there is still keyboard data left // if (ConsoleIn != NULL) { Status1 = EFI_SUCCESS; while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) { Status1 = KeyboardRead (ConsoleIn, &Data);; } } if (ConsoleIn != NULL) { gBS->FreePool (ConsoleIn); } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiIsaIoProtocolGuid, This->DriverBindingHandle, Controller ); return Status; }
/** Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs. And lock physical presence if needed. @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation @param[in] NotifyDescriptor Address of the notification descriptor data structure. @param[in] Ppi Address of the PPI that was installed. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_ABORTED physicalPresenceCMDEnable is locked. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI PhysicalPresencePpiNotifyCallback ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ) { EFI_STATUS Status; TPM_PERMANENT_FLAGS TpmPermanentFlags; PEI_LOCK_PHYSICAL_PRESENCE_PPI *LockPhysicalPresencePpi; TPM_PHYSICAL_PRESENCE PhysicalPresenceValue; Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags); if (EFI_ERROR (Status)) { return Status; } // // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs. // if (PcdGetBool (PcdPhysicalPresenceLifetimeLock) && !TpmPermanentFlags.physicalPresenceLifetimeLock) { // // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet. // PhysicalPresenceValue = TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK; TpmPermanentFlags.physicalPresenceLifetimeLock = TRUE; if (PcdGetBool (PcdPhysicalPresenceCmdEnable)) { PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_ENABLE; TpmPermanentFlags.physicalPresenceCMDEnable = TRUE; } else { PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_DISABLE; TpmPermanentFlags.physicalPresenceCMDEnable = FALSE; } if (PcdGetBool (PcdPhysicalPresenceHwEnable)) { PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_ENABLE; } else { PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_DISABLE; } Status = Tpm12PhysicalPresence ( PhysicalPresenceValue ); if (EFI_ERROR (Status)) { return Status; } } // // 2. Lock physical presence if it is required. // LockPhysicalPresencePpi = (PEI_LOCK_PHYSICAL_PRESENCE_PPI *) Ppi; if (!LockPhysicalPresencePpi->LockPhysicalPresence ((CONST EFI_PEI_SERVICES**) PeiServices)) { return EFI_SUCCESS; } if (!TpmPermanentFlags.physicalPresenceCMDEnable) { if (TpmPermanentFlags.physicalPresenceLifetimeLock) { // // physicalPresenceCMDEnable is locked, can't change. // return EFI_ABORTED; } // // Enable physical presence command // It is necessary in order to lock physical presence // Status = Tpm12PhysicalPresence ( TPM_PHYSICAL_PRESENCE_CMD_ENABLE ); if (EFI_ERROR (Status)) { return Status; } } // // Lock physical presence // Status = Tpm12PhysicalPresence ( TPM_PHYSICAL_PRESENCE_LOCK ); return Status; }
/** Remove exec permissions from all regions whose type is identified by PcdDxeNxMemoryProtectionPolicy. **/ STATIC VOID InitializeDxeNxMemoryProtectionPolicy ( VOID ) { UINTN MemoryMapSize; UINTN MapKey; UINTN DescriptorSize; UINT32 DescriptorVersion; EFI_MEMORY_DESCRIPTOR *MemoryMap; EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; EFI_STATUS Status; UINT64 Attributes; LIST_ENTRY *Link; EFI_GCD_MAP_ENTRY *Entry; EFI_PEI_HOB_POINTERS Hob; EFI_HOB_MEMORY_ALLOCATION *MemoryHob; EFI_PHYSICAL_ADDRESS StackBase; // // Get the EFI memory map. // MemoryMapSize = 0; MemoryMap = NULL; Status = gBS->GetMemoryMap ( &MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion ); ASSERT (Status == EFI_BUFFER_TOO_SMALL); do { MemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (MemoryMapSize); ASSERT (MemoryMap != NULL); Status = gBS->GetMemoryMap ( &MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion ); if (EFI_ERROR (Status)) { FreePool (MemoryMap); } } while (Status == EFI_BUFFER_TOO_SMALL); ASSERT_EFI_ERROR (Status); StackBase = 0; if (PcdGetBool (PcdCpuStackGuard)) { // // Get the base of stack from Hob. // Hob.Raw = GetHobList (); while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) { MemoryHob = Hob.MemoryAllocation; if (CompareGuid(&gEfiHobMemoryAllocStackGuid, &MemoryHob->AllocDescriptor.Name)) { DEBUG (( DEBUG_INFO, "%a: StackBase = 0x%016lx StackSize = 0x%016lx\n", __FUNCTION__, MemoryHob->AllocDescriptor.MemoryBaseAddress, MemoryHob->AllocDescriptor.MemoryLength )); StackBase = MemoryHob->AllocDescriptor.MemoryBaseAddress; // // Ensure the base of the stack is page-size aligned. // ASSERT ((StackBase & EFI_PAGE_MASK) == 0); break; } Hob.Raw = GET_NEXT_HOB (Hob); } // // Ensure the base of stack can be found from Hob when stack guard is // enabled. // ASSERT (StackBase != 0); } DEBUG (( DEBUG_INFO, "%a: applying strict permissions to active memory regions\n", __FUNCTION__ )); MergeMemoryMapForProtectionPolicy (MemoryMap, &MemoryMapSize, DescriptorSize); MemoryMapEntry = MemoryMap; MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize); while ((UINTN) MemoryMapEntry < (UINTN) MemoryMapEnd) { Attributes = GetPermissionAttributeForMemoryType (MemoryMapEntry->Type); if (Attributes != 0) { SetUefiImageMemoryAttributes ( MemoryMapEntry->PhysicalStart, LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT), Attributes); // // Add EFI_MEMORY_RP attribute for page 0 if NULL pointer detection is // enabled. // if (MemoryMapEntry->PhysicalStart == 0 && PcdGet8 (PcdNullPointerDetectionPropertyMask) != 0) { ASSERT (MemoryMapEntry->NumberOfPages > 0); SetUefiImageMemoryAttributes ( 0, EFI_PAGES_TO_SIZE (1), EFI_MEMORY_RP | Attributes); } // // Add EFI_MEMORY_RP attribute for the first page of the stack if stack // guard is enabled. // if (StackBase != 0 && (StackBase >= MemoryMapEntry->PhysicalStart && StackBase < MemoryMapEntry->PhysicalStart + LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT)) && PcdGetBool (PcdCpuStackGuard)) { SetUefiImageMemoryAttributes ( StackBase, EFI_PAGES_TO_SIZE (1), EFI_MEMORY_RP | Attributes); } } MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); } FreePool (MemoryMap); // // Apply the policy for RAM regions that we know are present and // accessible, but have not been added to the UEFI memory map (yet). // if (GetPermissionAttributeForMemoryType (EfiConventionalMemory) != 0) { DEBUG (( DEBUG_INFO, "%a: applying strict permissions to inactive memory regions\n", __FUNCTION__ )); CoreAcquireGcdMemoryLock (); Link = mGcdMemorySpaceMap.ForwardLink; while (Link != &mGcdMemorySpaceMap) { Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); if (Entry->GcdMemoryType == EfiGcdMemoryTypeReserved && Entry->EndAddress < MAX_ADDRESS && (Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) == (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)) { Attributes = GetPermissionAttributeForMemoryType (EfiConventionalMemory) | (Entry->Attributes & CACHE_ATTRIBUTE_MASK); DEBUG ((DEBUG_INFO, "Untested GCD memory space region: - 0x%016lx - 0x%016lx (0x%016lx)\n", Entry->BaseAddress, Entry->EndAddress - Entry->BaseAddress + 1, Attributes)); ASSERT(gCpu != NULL); gCpu->SetMemoryAttributes (gCpu, Entry->BaseAddress, Entry->EndAddress - Entry->BaseAddress + 1, Attributes); } Link = Link->ForwardLink; } CoreReleaseGcdMemoryLock (); } }
/** Entry point for this driver. @param[in] ImageHandle Image handle of this driver. @param[in] SystemTable Pointer to SystemTable. @retval EFI_SUCESS Driver has loaded successfully. @retval EFI_UNSUPPORTED PCI resource allocation has been disabled. @retval EFI_UNSUPPORTED There is no 64-bit PCI MMIO aperture. @return Error codes from lower level functions. **/ EFI_STATUS EFIAPI DriverInitialize ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_EVENT Event; VOID *Registration; // // If the PCI Bus driver is not supposed to allocate resources, then it makes // no sense to install a protocol that influences the resource allocation. // // Similarly, if there is no 64-bit PCI MMIO aperture, then 64-bit MMIO BARs // have to be allocated under 4 GB unconditionally. // if (PcdGetBool (PcdPciDisableBusEnumeration) || PcdGet64 (PcdPciMmio64Size) == 0) { return EFI_UNSUPPORTED; } // // Otherwise, create a protocol notify to see if a CSM is present. (With the // CSM absent, the PCI Bus driver won't have to worry about allocating 64-bit // MMIO BARs in the 32-bit MMIO aperture, for the sake of a legacy BIOS.) // // If the Legacy BIOS Protocol is present at the time of this driver starting // up, we can mark immediately that the PCI Bus driver should perform the // usual 64-bit MMIO BAR degradation. // // Otherwise, if the Legacy BIOS Protocol is absent at startup, it may be // installed later. However, if it doesn't show up until the first // EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL.CheckDevice() call from the // PCI Bus driver, then it never will: // // 1. The following drivers are dispatched in some unspecified order: // - PCI Host Bridge DXE_DRIVER, // - PCI Bus UEFI_DRIVER, // - this DXE_DRIVER, // - Legacy BIOS DXE_DRIVER. // // 2. The DXE_CORE enters BDS. // // 3. The platform BDS connects the PCI Root Bridge IO instances (produced by // the PCI Host Bridge DXE_DRIVER). // // 4. The PCI Bus UEFI_DRIVER enumerates resources and calls into this // DXE_DRIVER (CheckDevice()). // // 5. This driver remembers if EFI_LEGACY_BIOS_PROTOCOL has been installed // sometime during step 1 (produced by the Legacy BIOS DXE_DRIVER). // // For breaking this order, the Legacy BIOS DXE_DRIVER would have to install // its protocol after the firmware enters BDS, which cannot happen. // Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, LegacyBiosInstalled, NULL /* Context */, &Event); if (EFI_ERROR (Status)) { return Status; } Status = gBS->RegisterProtocolNotify (&gEfiLegacyBiosProtocolGuid, Event, &Registration); if (EFI_ERROR (Status)) { goto CloseEvent; } Status = gBS->SignalEvent (Event); ASSERT_EFI_ERROR (Status); mIncompatiblePciDeviceSupport.CheckDevice = CheckDevice; Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle, &gEfiIncompatiblePciDeviceSupportProtocolGuid, &mIncompatiblePciDeviceSupport, NULL); if (EFI_ERROR (Status)) { goto CloseEvent; } return EFI_SUCCESS; CloseEvent: if (!mLegacyBiosInstalled) { EFI_STATUS CloseStatus; CloseStatus = gBS->CloseEvent (Event); ASSERT_EFI_ERROR (CloseStatus); } return Status; }
/** Allocates and fills in the Page Directory and Page Table Entries to establish a 1:1 Virtual to Physical mapping. @param[in] StackBase Stack base address. @param[in] StackSize Stack size. @return The address of 4 level page map. **/ UINTN CreateIdentityMappingPageTables ( IN EFI_PHYSICAL_ADDRESS StackBase, IN UINTN StackSize ) { UINT32 RegEax; UINT32 RegEdx; UINT8 PhysicalAddressBits; EFI_PHYSICAL_ADDRESS PageAddress; UINTN IndexOfPml4Entries; UINTN IndexOfPdpEntries; UINTN IndexOfPageDirectoryEntries; UINT32 NumberOfPml4EntriesNeeded; UINT32 NumberOfPdpEntriesNeeded; PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; PAGE_MAP_AND_DIRECTORY_POINTER *PageMap; PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; PAGE_TABLE_ENTRY *PageDirectoryEntry; UINTN TotalPagesNum; UINTN BigPageAddress; VOID *Hob; BOOLEAN Page1GSupport; PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; Page1GSupport = FALSE; if (PcdGetBool(PcdUse1GPageTable)) { AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000001) { AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); if ((RegEdx & BIT26) != 0) { Page1GSupport = TRUE; } } } // // Get physical address bits supported. // Hob = GetFirstHob (EFI_HOB_TYPE_CPU); if (Hob != NULL) { PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; } else { AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000008) { AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); PhysicalAddressBits = (UINT8) RegEax; } else { PhysicalAddressBits = 36; } } // // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. // ASSERT (PhysicalAddressBits <= 52); if (PhysicalAddressBits > 48) { PhysicalAddressBits = 48; } // // Calculate the table entries needed. // if (PhysicalAddressBits <= 39 ) { NumberOfPml4EntriesNeeded = 1; NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); } else { NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39)); NumberOfPdpEntriesNeeded = 512; } // // Pre-allocate big pages to avoid later allocations. // if (!Page1GSupport) { TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1; } else { TotalPagesNum = NumberOfPml4EntriesNeeded + 1; } BigPageAddress = (UINTN) AllocatePages (TotalPagesNum); ASSERT (BigPageAddress != 0); // // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. // PageMap = (VOID *) BigPageAddress; BigPageAddress += SIZE_4KB; PageMapLevel4Entry = PageMap; PageAddress = 0; for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) { // // Each PML4 entry points to a page of Page Directory Pointer entires. // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop. // PageDirectoryPointerEntry = (VOID *) BigPageAddress; BigPageAddress += SIZE_4KB; // // Make a PML4 Entry // PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry; PageMapLevel4Entry->Bits.ReadWrite = 1; PageMapLevel4Entry->Bits.Present = 1; if (Page1GSupport) { PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry; for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) { if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_1GB) > StackBase)) { Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize); } else { // // Fill in the Page Directory entries // PageDirectory1GEntry->Uint64 = (UINT64)PageAddress; PageDirectory1GEntry->Bits.ReadWrite = 1; PageDirectory1GEntry->Bits.Present = 1; PageDirectory1GEntry->Bits.MustBe1 = 1; } } } else { for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { // // Each Directory Pointer entries points to a page of Page Directory entires. // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop. // PageDirectoryEntry = (VOID *) BigPageAddress; BigPageAddress += SIZE_4KB; // // Fill in a Page Directory Pointer Entries // PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry; PageDirectoryPointerEntry->Bits.ReadWrite = 1; PageDirectoryPointerEntry->Bits.Present = 1; for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) { if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_2MB) > StackBase)) { // // Need to split this 2M page that covers stack range. // Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize); } else { // // Fill in the Page Directory entries // PageDirectoryEntry->Uint64 = (UINT64)PageAddress; PageDirectoryEntry->Bits.ReadWrite = 1; PageDirectoryEntry->Bits.Present = 1; PageDirectoryEntry->Bits.MustBe1 = 1; } } } for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { ZeroMem ( PageDirectoryPointerEntry, sizeof(PAGE_MAP_AND_DIRECTORY_POINTER) ); } } } // // For the PML4 entries we are not using fill in a null entry. // for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) { ZeroMem ( PageMapLevel4Entry, sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) ); } if (PcdGetBool (PcdSetNxForStack)) { EnableExecuteDisableBit (); } return (UINTN)PageMap; }
EFI_STATUS AcpiPlatformEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTable; EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; INTN Instance; EFI_ACPI_COMMON_HEADER *CurrentTable; UINTN TableHandle; UINT32 FvStatus; UINTN Size; EFI_ACPI_TABLE_VERSION Version; QNC_DEVICE_ENABLES QNCDeviceEnables; EFI_HANDLE Handle; UINTN Index; PCI_DEVICE_INFO *PciDeviceInfo; EFI_ACPI_HANDLE PciRootHandle; BOOLEAN UpdatePRT; BOOLEAN UpdatePRW; PCI_DEVICE_SETTING *mConfigData; Instance = 0; TableHandle = 0; CurrentTable = NULL; mConfigData = NULL; QNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables); // // Initialize the EFI Driver Library // ASSERT (sizeof (EFI_GLOBAL_NVS_AREA) == 512); Status = gBS->AllocatePool ( EfiACPIMemoryNVS, sizeof (EFI_GLOBAL_NVS_AREA), (VOID**)&mGlobalNvsArea.Area ); Handle = NULL; Status = gBS->InstallProtocolInterface ( &Handle, &gEfiGlobalNvsAreaProtocolGuid, EFI_NATIVE_INTERFACE, &mGlobalNvsArea ); ASSERT_EFI_ERROR (Status); if (!EFI_ERROR (Status)) { SetMem ( mGlobalNvsArea.Area, sizeof (EFI_GLOBAL_NVS_AREA), 0 ); } // // Initialize the data. Eventually, this will be controlled by setup options. // mGlobalNvsArea.Area->HpetEnable = PcdGetBool (PcdHpetEnable); mGlobalNvsArea.Area->Pm1blkIoBaseAddress = PcdGet16(PcdPm1blkIoBaseAddress); mGlobalNvsArea.Area->PmbaIoBaseAddress = PcdGet16(PcdPmbaIoBaseAddress); mGlobalNvsArea.Area->Gpe0blkIoBaseAddress = PcdGet16(PcdGpe0blkIoBaseAddress); mGlobalNvsArea.Area->GbaIoBaseAddress = PcdGet16(PcdGbaIoBaseAddress); mGlobalNvsArea.Area->SmbaIoBaseAddress = PcdGet16(PcdSmbaIoBaseAddress); mGlobalNvsArea.Area->SpiDmaIoBaseAddress = PcdGet16(PcdSpiDmaIoBaseAddress); mGlobalNvsArea.Area->WdtbaIoBaseAddress = PcdGet16(PcdWdtbaIoBaseAddress); mGlobalNvsArea.Area->HpetBaseAddress = (UINT32)PcdGet64(PcdHpetBaseAddress); mGlobalNvsArea.Area->HpetSize = (UINT32)PcdGet64(PcdHpetSize); mGlobalNvsArea.Area->PciExpressBaseAddress= (UINT32)PcdGet64(PcdPciExpressBaseAddress); mGlobalNvsArea.Area->PciExpressSize = (UINT32)PcdGet64(PcdPciExpressSize); mGlobalNvsArea.Area->RcbaMmioBaseAddress = (UINT32)PcdGet64(PcdRcbaMmioBaseAddress); mGlobalNvsArea.Area->RcbaMmioSize = (UINT32)PcdGet64(PcdRcbaMmioSize); mGlobalNvsArea.Area->IoApicBaseAddress = (UINT32)PcdGet64(PcdIoApicBaseAddress); mGlobalNvsArea.Area->IoApicSize = (UINT32)PcdGet64(PcdIoApicSize); mGlobalNvsArea.Area->TpmPresent = (UINT32)(FALSE); // // Find the AcpiTable protocol // Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable); if (EFI_ERROR (Status)) { return EFI_ABORTED; } // // Initialize MADT table // Status = MadtTableInitialize (&CurrentTable, &Size); ASSERT_EFI_ERROR (Status); // // Perform any table specific updates. // AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version); // // Update the check sum // It needs to be zeroed before the checksum calculation // ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0; ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length); // // Add the table // TableHandle = 0; Status = AcpiTable->InstallAcpiTable ( AcpiTable, CurrentTable, CurrentTable->Length, &TableHandle ); ASSERT_EFI_ERROR (Status); CurrentTable = NULL; // // Init Pci Device PRT PRW information structure from PCD // mConfigData = (PCI_DEVICE_SETTING *)AllocateZeroPool (sizeof (PCI_DEVICE_SETTING)); ASSERT_EFI_ERROR (mConfigData); InitPciDeviceInfoStructure (mConfigData); // // Get the Acpi SDT protocol for manipulation on acpi table // Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&mAcpiSdt); ASSERT_EFI_ERROR (Status); // // Locate the firmware volume protocol // Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1); if (EFI_ERROR (Status)) { return EFI_ABORTED; } // // Read tables from the storage file. // while (Status == EFI_SUCCESS) { Status = FwVol->ReadSection ( FwVol, (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile), EFI_SECTION_RAW, Instance, (VOID**)&CurrentTable, &Size, &FvStatus ); if (!EFI_ERROR(Status)) { // // Perform any table specific updates. // AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version); // // Update the check sum // It needs to be zeroed before the checksum calculation // ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0; ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length); // // Add the table // TableHandle = 0; Status = AcpiTable->InstallAcpiTable ( AcpiTable, CurrentTable, ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length, &TableHandle ); if (EFI_ERROR(Status)) { return EFI_ABORTED; } // // If this table is the DSDT table, then update the _PRT and _PRW based on // the settings from pcds // if (CurrentTable->Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) { // // Create the root handle for DSDT table // Status = mAcpiSdt->OpenSdt (TableHandle, &mDsdtHandle); ASSERT_EFI_ERROR (Status); PciRootHandle = NULL; PciRootHandle = SdtGetRootBridgeHandle (mAcpiSdt, mDsdtHandle); ASSERT (PciRootHandle != NULL); PciDeviceInfo = NULL; for (Index = 0; Index < mConfigData->PciDeviceInfoNumber; Index++) { PciDeviceInfo = &(mConfigData->PciDeviceInfo[Index]); // // Check whether this is a valid item // if ((PciDeviceInfo->BridgeAddress != 0xFFFFFFFF) && (PciDeviceInfo->DeviceAddress != 0xFFFFFFFF)) { //DEBUG ((EFI_D_ERROR, "Valid pci info structure: bridge address:0x%x, device address:0x%x\n", PciDeviceInfo->BridgeAddress, PciDeviceInfo->DeviceAddress)); UpdatePRT = FALSE; UpdatePRW = FALSE; SdtCheckPciDeviceInfoChanged (PciDeviceInfo, &UpdatePRT, &UpdatePRW); // // Check whether there is any valid pci routing item // if (UpdatePRT) { // // Update the pci routing information // //DEBUG ((EFI_D_ERROR, "Update _PRT\n")); SdtUpdatePciRouting (mAcpiSdt, PciRootHandle, PciDeviceInfo); } // // Check whether there is any valid pci routing item // if (UpdatePRW) { // // Update the pci wakeup information // //DEBUG ((EFI_D_ERROR, "Update _PRW\n")); SdtUpdatePowerWake (mAcpiSdt, PciRootHandle, PciDeviceInfo); } } } Status = mAcpiSdt->Close (PciRootHandle); ASSERT_EFI_ERROR (Status); // // Mark the root handle as modified , let SDT protocol recaculate the checksum // ((EFI_AML_HANDLE *)mDsdtHandle)->Modified = TRUE; Status = mAcpiSdt->Close (mDsdtHandle); ASSERT_EFI_ERROR (Status); } // // Increment the instance // Instance++; CurrentTable = NULL; } } gBS->FreePool (mConfigData); return EFI_SUCCESS; }
/** Entrypoint of Boot script exector driver, this function will be executed in normal boot phase and invoked by DXE dispatch. @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI BootScriptExecutorEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { UINTN BufferSize; UINTN Pages; BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable; EFI_PHYSICAL_ADDRESS BootScriptExecutorBuffer; EFI_STATUS Status; VOID *DevicePath; EFI_EVENT ReadyToLockEvent; VOID *Registration; UINT32 RegEax; UINT32 RegEdx; if (!PcdGetBool (PcdAcpiS3Enable)) { return EFI_UNSUPPORTED; } // // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry // point is loaded by DXE code which is the first time loaded. or else, it is already // be reloaded be itself.This is a work-around // Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath); if (EFI_ERROR (Status)) { // // Create ReadyToLock event to reload BootScriptExecutor image // to RESERVED mem and save it to LockBox. // ReadyToLockEvent = EfiCreateProtocolNotifyEvent ( &gEfiDxeSmmReadyToLockProtocolGuid, TPL_NOTIFY, ReadyToLockEventNotify, NULL, &Registration ); ASSERT (ReadyToLockEvent != NULL); } else { // // the entry point is invoked after reloading. following code only run in RESERVED mem // if (PcdGetBool(PcdUse1GPageTable)) { AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000001) { AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); if ((RegEdx & BIT26) != 0) { mPage1GSupport = TRUE; } } } BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE); BootScriptExecutorBuffer = 0xFFFFFFFF; Pages = EFI_SIZE_TO_PAGES(BufferSize); Status = gBS->AllocatePages ( AllocateMaxAddress, EfiReservedMemoryType, Pages, &BootScriptExecutorBuffer ); ASSERT_EFI_ERROR (Status); EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *)(UINTN)BootScriptExecutorBuffer; EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = (UINTN) S3BootScriptExecutorEntryFunction ; Status = SaveLockBox ( &gEfiBootScriptExecutorVariableGuid, &BootScriptExecutorBuffer, sizeof(BootScriptExecutorBuffer) ); ASSERT_EFI_ERROR (Status); // // Additional step for BootScript integrity // Save BootScriptExecutor context // Status = SaveLockBox ( &gEfiBootScriptExecutorContextGuid, EfiBootScriptExecutorVariable, sizeof(*EfiBootScriptExecutorVariable) ); ASSERT_EFI_ERROR (Status); Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE); ASSERT_EFI_ERROR (Status); } return EFI_SUCCESS; }
VOID EFIAPI PlatformBdsPolicyBehavior ( IN OUT LIST_ENTRY *DriverOptionList, IN OUT LIST_ENTRY *BootOptionList, IN PROCESS_CAPSULES ProcessCapsules, IN BASEM_MEMORY_TEST BaseMemoryTest ) /*++ Routine Description: The function will excute with as the platform policy, current policy is driven by boot mode. IBV/OEM can customize this code for their specific policy action. Arguments: DriverOptionList - The header of the driver option link list BootOptionList - The header of the boot option link list ProcessCapsules - A pointer to ProcessCapsules() BaseMemoryTest - A pointer to BaseMemoryTest() Returns: None. --*/ { EFI_STATUS Status; UINT16 Timeout; EFI_EVENT UserInputDurationTime; LIST_ENTRY *Link; BDS_COMMON_OPTION *BootOption; UINTN Index; EFI_INPUT_KEY Key; EFI_TPL OldTpl; EFI_BOOT_MODE BootMode; VBoxLogFlowFuncEnter(); ConnectRootBridge (); if (PcdGetBool (PcdOvmfFlashVariablesEnable)) { DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars " "from disk since flash variables appear to be supported.\n")); } else { // // Try to restore variables from the hard disk early so // they can be used for the other BDS connect operations. // PlatformBdsRestoreNvVarsFromHardDisk (); } // // Init the time out value // Timeout = PcdGet16 (PcdPlatformBootTimeOut); // // Load the driver option as the driver option list // PlatformBdsGetDriverOption (DriverOptionList); // // Get current Boot Mode // Status = BdsLibGetBootMode (&BootMode); DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode)); // // Go the different platform policy with different boot mode // Notes: this part code can be change with the table policy // ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION); // // Connect platform console // Status = PlatformBdsConnectConsole (gPlatformConsole); if (EFI_ERROR (Status)) { // // Here OEM/IBV can customize with defined action // PlatformBdsNoConsoleAction (); } // // Create a 300ms duration event to ensure user has enough input time to enter Setup // Status = gBS->CreateEvent ( EVT_TIMER, 0, NULL, NULL, &UserInputDurationTime ); ASSERT (Status == EFI_SUCCESS); Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000); ASSERT (Status == EFI_SUCCESS); // // Memory test and Logo show // PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); // // Perform some platform specific connect sequence // PlatformBdsConnectSequence (); // // Process QEMU's -kernel command line option // TryRunningQemuKernel (); // // Give one chance to enter the setup if we // have the time out // if (Timeout != 0) { //PlatformBdsEnterFrontPage (Timeout, FALSE); } DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n")); BdsLibConnectAll (); #ifdef VBOX { UINTN cFileSystem = 0; EFI_HANDLE *phFileSystem = NULL; BDS_COMMON_OPTION *BootOption0080 = NULL; EFI_STATUS rc = EFI_SUCCESS; DEBUG ((EFI_D_INFO, "------------------ VBox Platform Specific Initialization Start -----------------------\n")); BootOption0080 = BdsLibVariableToOption(BootOptionList, L"Boot0080"); if (!BootOption0080) { rc = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &cFileSystem, &phFileSystem); VBoxLogFlowFuncMarkRC(rc); VBoxLogFlowFuncMarkVar(cFileSystem, "%d"); if ( rc == EFI_SUCCESS && cFileSystem > 0) { EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFSVolume; EFI_FILE_HANDLE hFSRoot; EFI_FILE_HANDLE hBootEfiFile; UINTN iFileSystem = 0; /* Ok, we've found several simple file system handles * 1. we should find if '\\System\\Library\\CoreServices\\boot.efi' present * 2. Alter 'BootOrder' to include this file in boot sequence. */ for (iFileSystem = 0; iFileSystem < cFileSystem; ++iFileSystem) { EFI_DEVICE_PATH_PROTOCOL *pDevicePath = NULL; /* mount and look up the boot.efi */ rc = gBS->HandleProtocol (phFileSystem[iFileSystem], &gEfiSimpleFileSystemProtocolGuid, (VOID *) &pFSVolume); VBoxLogFlowFuncMarkVar(iFileSystem, "%d"); VBoxLogFlowFuncMarkRC(rc); if (EFI_ERROR(rc)) continue; rc = pFSVolume->OpenVolume(pFSVolume, &hFSRoot); VBoxLogFlowFuncMarkRC(rc); if (EFI_ERROR(rc)) continue; rc = hFSRoot->Open(hFSRoot, &hBootEfiFile, L"\\System\\Library\\CoreServices\\boot.efi", EFI_FILE_MODE_READ, 0); VBoxLogFlowFuncMarkRC(rc); if (EFI_ERROR(rc)) continue; /* nice file is found and we have to register it */ pDevicePath = FileDevicePath(phFileSystem[iFileSystem], L"\\System\\Library\\CoreServices\\boot.efi"); VBoxLogFlowFuncMarkVar(pDevicePath,"%p"); if (!pDevicePath) continue; rc = BdsLibRegisterNewOption (BootOptionList, pDevicePath, L"Mac Boot", L"BootOrder"); VBoxLogFlowFuncMarkRC(rc); } } } else { VBoxLogFlowFuncMarkVar(BootOption0080->LoadOptionsSize, "%d"); if (BootOption0080->LoadOptionsSize) VBoxLogFlowFuncMarkVar(BootOption0080->LoadOptions, "%s"); #if 0 /* Boot0080 option is found */ UINT16 *BootOrder; UINTN BootOrderSize; UINTN Index = 0; CHAR16 *BootOptionName; ASSERT(BootOption0080->Signature == BDS_LOAD_OPTION_SIGNATURE); BootOrder = BdsLibGetVariableAndSize ( L"BootOrder", &gEfiGlobalVariableGuid, &BootOrderSize); ASSERT(BootOrder); BootOptionName = AllocateRuntimePool(256 * sizeof(UINT16)); UnicodeSPrint(BootOptionName, 256 * sizeof(UINT16), L"Boot%04x", BootOrder[Index]); BootOption0080->OptionName = BootOptionName; rc = gRT->SetVariable(BootOptionName, &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(BDS_COMMON_OPTION), BootOption0080); LogFlowFuncMarkRC(rc); #if 0 rc = BdsLibRegisterNewOption (BootOptionList, BootOption0080->DevicePath, L"Mac Boot Temp", L"BootOrder"); #endif LogFlowFuncMarkRC(rc); #endif } DEBUG ((EFI_D_INFO, "------------------ VBox Platform Specific Initialization End -----------------------\n")); } #endif BdsLibEnumerateAllBootOption (BootOptionList); SetBootOrderFromQemu (BootOptionList); // // The BootOrder variable may have changed, reload the in-memory list with // it. // BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); // // To give the User a chance to enter Setup here, if user set TimeOut is 0. // BDS should still give user a chance to enter Setup // // Connect first boot option, and then check user input before exit // for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) { BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) { // // skip the header of the link list, becuase it has no boot option // continue; } else { // // Make sure the boot option device path connected, but ignore the BBS device path // if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) { BdsLibConnectDevicePath (BootOption->DevicePath); } break; } } // // Check whether the user input after the duration time has expired // OldTpl = EfiGetCurrentTpl(); gBS->RestoreTPL (TPL_APPLICATION); gBS->WaitForEvent (1, &UserInputDurationTime, &Index); gBS->CloseEvent (UserInputDurationTime); Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); gBS->RaiseTPL (OldTpl); if (!EFI_ERROR (Status)) { // // Enter Setup if user input // Timeout = 0xffff; PlatformBdsEnterFrontPage (Timeout, FALSE); } VBoxLogFlowFuncLeave(); return ; }
/** Allocates and fills in the Page Directory and Page Table Entries to establish a 1:1 Virtual to Physical mapping. If BootScriptExector driver will run in 64-bit mode, this function will establish the 1:1 virtual to physical mapping page table. If BootScriptExector driver will not run in 64-bit mode, this function will do nothing. @return the 1:1 Virtual to Physical identity mapping page table base address. **/ EFI_PHYSICAL_ADDRESS S3CreateIdentityMappingPageTables ( VOID ) { if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { UINT32 RegEax; UINT32 RegEdx; UINT8 PhysicalAddressBits; UINT32 NumberOfPml4EntriesNeeded; UINT32 NumberOfPdpEntriesNeeded; EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress; UINTN TotalPageTableSize; VOID *Hob; BOOLEAN Page1GSupport; Page1GSupport = FALSE; if (PcdGetBool(PcdUse1GPageTable)) { AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000001) { AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); if ((RegEdx & BIT26) != 0) { Page1GSupport = TRUE; } } } // // Get physical address bits supported. // Hob = GetFirstHob (EFI_HOB_TYPE_CPU); if (Hob != NULL) { PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; } else { AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000008) { AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); PhysicalAddressBits = (UINT8) RegEax; } else { PhysicalAddressBits = 36; } } // // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. // ASSERT (PhysicalAddressBits <= 52); if (PhysicalAddressBits > 48) { PhysicalAddressBits = 48; } // // Calculate the table entries needed. // if (PhysicalAddressBits <= 39 ) { NumberOfPml4EntriesNeeded = 1; NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); } else { NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39)); NumberOfPdpEntriesNeeded = 512; } // // We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs. // if (!Page1GSupport) { TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded); } else { TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded); } DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %x pages\n", TotalPageTableSize)); // // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. // S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGES_TO_SIZE(TotalPageTableSize)); ASSERT (S3NvsPageTableAddress != 0); return S3NvsPageTableAddress; } else { // // If DXE is running 32-bit mode, no need to establish page table. // return (EFI_PHYSICAL_ADDRESS) 0; } }