/** Call the browser and display the front page @return Status code that will be returned by EFI_FORM_BROWSER2_PROTOCOL.SendForm (). **/ EFI_STATUS CallFrontPage ( VOID ) { EFI_STATUS Status; EFI_BROWSER_ACTION_REQUEST ActionRequest; // // Begin waiting for USER INPUT // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT) ); ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; Status = gFormBrowser2->SendForm ( gFormBrowser2, &gFrontPagePrivate.HiiHandle, 1, &mFrontPageGuid, 0, NULL, &ActionRequest ); // // Check whether user change any option setting which needs a reset to be effective // if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { EnableResetRequired (); } return Status; }
/** Core version of the Reset System @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. @retval EFI_NOT_AVAILABLE_YET PPI not available yet. @retval EFI_DEVICE_ERROR Did not reset system. Otherwise, resets the system. **/ EFI_STATUS EFIAPI PeiResetSystem ( IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; EFI_PEI_RESET_PPI *ResetPpi; Status = PeiServicesLocatePpi ( &gEfiPeiResetPpiGuid, 0, NULL, (VOID **)&ResetPpi ); // // LocatePpi returns EFI_NOT_FOUND on error // if (!EFI_ERROR (Status)) { return ResetPpi->ResetSystem (PeiServices); } // // Report Status Code that Reset PPI is not available // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_SOFTWARE_PEI_CORE | EFI_SW_PS_EC_RESET_NOT_AVAILABLE) ); return EFI_NOT_AVAILABLE_YET; }
/** Entry point to the C language phase of SEC. After the SEC assembly code has initialized some temporary memory and set up the stack, the control is transferred to this function. @param SizeOfRam Size of the temporary memory available for use. @param TempRamBase Base address of tempory ram @param BootFirmwareVolume Base address of the Boot Firmware Volume. **/ VOID EFIAPI SecStartup ( IN UINT32 SizeOfRam, IN UINT32 TempRamBase, IN VOID *BootFirmwareVolume ) { EFI_SEC_PEI_HAND_OFF SecCoreData; IA32_DESCRIPTOR IdtDescriptor; SEC_IDT_TABLE IdtTableInStack; UINT32 Index; UINT32 PeiStackSize; // // Report Status Code to indicate entering SEC core // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_ENTRY_POINT ); PeiStackSize = PcdGet32 (PcdPeiTemporaryRamStackSize); if (PeiStackSize == 0) { PeiStackSize = (SizeOfRam >> 1); }
/** Sends an 32-bit value to a POST card. Sends the 32-bit value specified by Value to a POST card, and returns Value. Some implementations of this library function may perform I/O operations directly to a POST card device. Other implementations may send Value to ReportStatusCode(), and the status code reporting mechanism will eventually display the 32-bit value on the status reporting device. PostCode() must actively prevent recursion. If PostCode() is called while processing another any other Report Status Code Library function, then PostCode() must return Value immediately. @param Value The 32-bit value to write to the POST card. @return Value **/ UINT32 EFIAPI GluePostCode ( IN UINT32 Value ) { REPORT_STATUS_CODE (EFI_PROGRESS_CODE, POST_CODE_TO_STATUS_CODE_VALUE (Value)); return Value; }
/** This function is the main entry of the UI entry. The function will present the main menu of the system UI. @param ConnectAllHappened Caller passes the value to UI to avoid unnecessary connect-all. **/ VOID EFIAPI UiEntry ( IN BOOLEAN ConnectAllHappened ) { EFI_STATUS Status; EFI_BOOT_LOGO_PROTOCOL *BootLogo; // // Enter Setup page. // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP) ); // // Indicate if the connect all has been performed before. // If has not been performed before, do here. // if (!ConnectAllHappened) { EfiBootManagerConnectAll (); } // // The boot option enumeration time is acceptable in Ui driver // EfiBootManagerRefreshAllBootOption (); // // Boot Logo is corrupted, report it using Boot Logo protocol. // Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo); if (!EFI_ERROR (Status) && (BootLogo != NULL)) { BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0); } InitializeFrontPage (); CallFrontPage (); FreeFrontPage (); if (mLanguageString != NULL) { FreePool (mLanguageString); mLanguageString = NULL; } // //Will leave browser, check any reset required change is applied? if yes, reset system // SetupResetReminder (); }
/** This function returns control to BootLoader after TempRamExitApi. @param[in] Status return status for the TempRamExitApi. **/ VOID EFIAPI FspTempRamExitDone2 ( IN EFI_STATUS Status ) { // // Convert to FSP EAS defined API return codes // switch (Status) { case EFI_SUCCESS: case EFI_INVALID_PARAMETER: case EFI_UNSUPPORTED: case EFI_DEVICE_ERROR: break; default: DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() Invalid Error - [Status: 0x%08X]\n", Status)); Status = EFI_DEVICE_ERROR; // Force to known error. break; } // // This is the end of the TempRamExit API // Give control back to the boot loader // DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - [Status: 0x%08X] - End\n", Status)); SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT); PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); do { SetFspApiReturnStatus (Status); Pei2LoaderSwitchStack (); if (Status != EFI_SUCCESS) { DEBUG ((DEBUG_ERROR, "!!!ERROR: TempRamExitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status)); } } while (Status != EFI_SUCCESS); SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT); SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY); PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); DEBUG ((DEBUG_INFO | DEBUG_INIT, "SiliconInitApi() - Begin\n")); }
/** The Entry point of the CPU PEIM This function is the Entry point of the CPU PEIM which will install the CachePpi and BuildBISTHob notifier. And also the function will deal with the relocation to memory when permanent memory is ready @param FileHandle Handle of the file being invoked. @param PeiServices Describes the list of possible PEI Services. @retval EFI_SUCCESS CachePpi and BIST hob build notification is installed successfully. **/ EFI_STATUS EFIAPI CpuPeimInit ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; // // Report Status Code to indicate the start of CPU PEIM // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, EFI_COMPUTING_UNIT_HOST_PROCESSOR + EFI_CU_HP_PC_POWER_ON_INIT ); // // Install PPIs // Status = PeiServicesInstallPpi(&mPpiList[0]); ASSERT_EFI_ERROR (Status); // // Register for PPI Notifications // Status = PeiServicesNotifyPpi (&mNotifyList[0]); ASSERT_EFI_ERROR (Status); // // Report Status Code to indicate the start of CPU PEI initialization // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, EFI_COMPUTING_UNIT_HOST_PROCESSOR + EFI_CU_PC_INIT_BEGIN ); InitXMM (); return Status; }
/** This function returns control to BootLoader after MemoryInitApi. @param[in,out] HobListPtr The address of HobList pointer. **/ VOID EFIAPI FspMemoryInitDone ( IN OUT VOID **HobListPtr ) { // // Calling use FspMemoryInit API // Update HOB and return the control directly // if (HobListPtr != NULL) { *HobListPtr = (VOID *) GetHobList (); } // // This is the end of the FspMemoryInit API // Give control back to the boot loader // SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT); DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() - End\n")); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); SetFspApiReturnStatus (EFI_SUCCESS); Pei2LoaderSwitchStack (); // // The TempRamExitApi is called // if (GetFspApiCallingIndex () == TempRamExitApiIndex) { SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY); DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - Begin\n")); } else { SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY); DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - Begin\n")); SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); } }
/** Do reset system. **/ VOID DoResetSystem ( VOID ) { DEBUG((DEBUG_INFO, "Capsule Request Cold Reboot.")); REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeResettingSystem))); gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); CpuDeadLoop(); }
/** This function returns control to BootLoader after TempRamExitApi. **/ VOID EFIAPI FspTempRamExitDone ( VOID ) { // // This is the end of the TempRamExit API // Give control back to the boot loader // SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT); DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - End\n")); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); SetFspApiReturnStatus (EFI_SUCCESS); Pei2LoaderSwitchStack (); SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT); SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY); DEBUG ((DEBUG_INFO | DEBUG_INIT, "SiliconInitApi() - Begin\n")); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); }
/** Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result, and add an entry to the Event Log. @param[in] TcgData TCG_DXE_DATA structure. @param[in] HashData Physical address of the start of the data buffer to be hashed, extended, and logged. @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. @param[in] NewEventData Pointer to the new event data. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI TcgDxeHashLogExtendEventI ( IN TCG_DXE_DATA *TcgData, IN UINT8 *HashData, IN UINT64 HashDataLen, IN OUT TCG_PCR_EVENT_HDR *NewEventHdr, IN UINT8 *NewEventData ) { EFI_STATUS Status; if (!TcgData->BsCap.TPMPresentFlag) { return EFI_DEVICE_ERROR; } if (HashDataLen > 0 || HashData != NULL) { Status = TpmCommHashAll ( HashData, (UINTN) HashDataLen, &NewEventHdr->Digest ); if (EFI_ERROR(Status)) { DEBUG ((DEBUG_ERROR, "TpmCommHashAll Failed. %x\n", Status)); goto Done; } } Status = TpmCommExtend ( TcgData->TpmHandle, &NewEventHdr->Digest, NewEventHdr->PCRIndex, NULL ); if (!EFI_ERROR (Status)) { Status = TcgDxeLogEventI (TcgData, NewEventHdr, NewEventData); } Done: if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) { DEBUG ((EFI_D_ERROR, "TcgDxeHashLogExtendEventI - %r. Disable TPM.\n", Status)); TcgData->BsCap.TPMPresentFlag = FALSE; REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) ); Status = EFI_DEVICE_ERROR; } return Status; }
/** Jump to OS waking vector. The function will install boot script done PPI, report S3 resume status code, and then jump to OS waking vector. @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT @param PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE **/ VOID EFIAPI S3ResumeBootOs ( IN ACPI_S3_CONTEXT *AcpiS3Context, IN PEI_S3_RESUME_STATE *PeiS3ResumeState ) { EFI_STATUS Status; EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; ASM_TRANSFER_CONTROL AsmTransferControl; UINTN TempStackTop; UINTN TempStack[0x10]; // // Restore IDT // AsmWriteIdtr (&PeiS3ResumeState->Idtr); // // Install BootScriptDonePpi // Status = PeiServicesInstallPpi (&mPpiListPostScriptTable); ASSERT_EFI_ERROR (Status); // // Get ACPI Table Address // Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable)); if ((Facs == NULL) || (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) || ((Facs->FirmwareWakingVector == 0) && (Facs->XFirmwareWakingVector == 0)) ) { CpuDeadLoop (); return ; } // // report status code on S3 resume // REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE); // // Install EndOfPeiPpi // Status = PeiServicesInstallPpi (&mPpiListEndOfPeiTable); ASSERT_EFI_ERROR (Status); PERF_CODE ( WriteToOsS3PerformanceData (); );
/** Searches DxeCore in all firmware Volumes and loads the first instance that contains DxeCore. @return FileHandle of DxeCore to load DxeCore. **/ EFI_PEI_FILE_HANDLE DxeIplFindDxeCore ( VOID ) { EFI_STATUS Status; UINTN Instance; EFI_PEI_FV_HANDLE VolumeHandle; EFI_PEI_FILE_HANDLE FileHandle; Instance = 0; while (TRUE) { // // Traverse all firmware volume instances // Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle); // // If some error occurs here, then we cannot find any firmware // volume that may contain DxeCore. // if (EFI_ERROR (Status)) { REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_EC_DXE_CORRUPT)); } ASSERT_EFI_ERROR (Status); // // Find the DxeCore file type from the beginning in this firmware volume. // FileHandle = NULL; Status = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle); if (!EFI_ERROR (Status)) { // // Find DxeCore FileHandle in this volume, then we skip other firmware volume and // return the FileHandle. // return FileHandle; } // // We cannot find DxeCore in this firmware volume, then search the next volume. // Instance++; } }
/** This function transfer control back to BootLoader after FspSiliconInit. **/ VOID EFIAPI FspSiliconInitDone ( VOID ) { // // This is the end of the FspSiliconInit API // Give control back to the boot loader // SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT); DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - End\n")); PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, 0x907F); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); SetFspApiReturnStatus (EFI_SUCCESS); Pei2LoaderSwitchStack(); PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, 0x6000); }
/** Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result, and build a GUIDed HOB recording the event which will be passed to the DXE phase and added into the Event Log. @param[in] Flags Bitmap providing additional information. @param[in] HashData Physical address of the start of the data buffer to be hashed, extended, and logged. @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData. @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. @param[in] NewEventData Pointer to the new event data. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS HashLogExtendEvent ( IN UINT64 Flags, IN UINT8 *HashData, IN UINTN HashDataLen, IN TCG_PCR_EVENT_HDR *NewEventHdr, IN UINT8 *NewEventData ) { EFI_STATUS Status; TPML_DIGEST_VALUES DigestList; if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { return EFI_DEVICE_ERROR; } Status = HashAndExtend ( NewEventHdr->PCRIndex, HashData, HashDataLen, &DigestList ); if (!EFI_ERROR (Status)) { if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) { Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData); } } if (Status == EFI_DEVICE_ERROR) { DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status)); BuildGuidHob (&gTpmErrorHobGuid,0); REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) ); } return Status; }
/** Notification function that is called if the watchdog timer is fired. Notification function for the one-shot timer event that was signaled when the watchdog timer expired. If a handler has been registered with the Watchdog Timer Architectural Protocol, then that handler is called passing in the time period that has passed that cause the watchdog timer to fire. Then, a call to the Runtime Service ResetSystem() is made to reset the platform. @param Timer The one-shot timer event that was signaled when the watchdog timer expired. @param Context The context that was registered when the event Timer was created. **/ VOID EFIAPI WatchdogTimerDriverExpires ( IN EFI_EVENT Timer, IN VOID *Context ) { REPORT_STATUS_CODE (EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_TIMER_EXPIRED)); // // If a notification function has been registered, then call it // if (mWatchdogTimerNotifyFunction != NULL) { mWatchdogTimerNotifyFunction (mWatchdogTimerPeriod); } DEBUG ((EFI_D_ERROR, "Watchdog Timer resetting system\n")); // // Reset the platform // gRT->ResetSystem (EfiResetCold, EFI_TIMEOUT, 0, NULL); }
/** Main entry point to DXE Core. @param HobStart Pointer to the beginning of the HOB List from PEI. @return This function should never return. **/ VOID EFIAPI DxeMain ( IN VOID *HobStart ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS MemoryBaseAddress; UINT64 MemoryLength; PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; UINTN Index; EFI_HOB_GUID_TYPE *GuidHob; EFI_VECTOR_HANDOFF_INFO *VectorInfoList; EFI_VECTOR_HANDOFF_INFO *VectorInfo; VOID *EntryPoint; // // Setup the default exception handlers // VectorInfoList = NULL; GuidHob = GetNextGuidHob (&gEfiVectorHandoffInfoPpiGuid, HobStart); if (GuidHob != NULL) { VectorInfoList = (EFI_VECTOR_HANDOFF_INFO *) (GET_GUID_HOB_DATA(GuidHob)); } Status = InitializeCpuExceptionHandlers (VectorInfoList); ASSERT_EFI_ERROR (Status); // // Initialize Debug Agent to support source level debug in DXE phase // InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_CORE, HobStart, NULL); // // Initialize Memory Services // CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength); MemoryProfileInit (HobStart); // // Allocate the EFI System Table and EFI Runtime Service Table from EfiRuntimeServicesData // Use the templates to initialize the contents of the EFI System Table and EFI Runtime Services Table // gDxeCoreST = AllocateRuntimeCopyPool (sizeof (EFI_SYSTEM_TABLE), &mEfiSystemTableTemplate); ASSERT (gDxeCoreST != NULL); gDxeCoreRT = AllocateRuntimeCopyPool (sizeof (EFI_RUNTIME_SERVICES), &mEfiRuntimeServicesTableTemplate); ASSERT (gDxeCoreRT != NULL); gDxeCoreST->RuntimeServices = gDxeCoreRT; // // Start the Image Services. // Status = CoreInitializeImageServices (HobStart); ASSERT_EFI_ERROR (Status); // // Initialize the Global Coherency Domain Services // Status = CoreInitializeGcdServices (&HobStart, MemoryBaseAddress, MemoryLength); ASSERT_EFI_ERROR (Status); // // Call constructor for all libraries // ProcessLibraryConstructorList (gDxeCoreImageHandle, gDxeCoreST); PERF_END (NULL,"PEI", NULL, 0) ; PERF_START (NULL,"DXE", NULL, 0) ; // // Report DXE Core image information to the PE/COFF Extra Action Library // ZeroMem (&ImageContext, sizeof (ImageContext)); ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)gDxeCoreLoadedImage->ImageBase; ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*)(UINTN)ImageContext.ImageAddress); ImageContext.SizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID*)(UINTN)ImageContext.ImageAddress); Status = PeCoffLoaderGetEntryPoint ((VOID*)(UINTN)ImageContext.ImageAddress, &EntryPoint); if (Status == EFI_SUCCESS) { ImageContext.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint; } ImageContext.Handle = (VOID *)(UINTN)gDxeCoreLoadedImage->ImageBase; ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; PeCoffLoaderRelocateImageExtraAction (&ImageContext); // // Install the DXE Services Table into the EFI System Tables's Configuration Table // Status = CoreInstallConfigurationTable (&gEfiDxeServicesTableGuid, gDxeCoreDS); ASSERT_EFI_ERROR (Status); // // Install the HOB List into the EFI System Tables's Configuration Table // Status = CoreInstallConfigurationTable (&gEfiHobListGuid, HobStart); ASSERT_EFI_ERROR (Status); // // Install Memory Type Information Table into the EFI System Tables's Configuration Table // Status = CoreInstallConfigurationTable (&gEfiMemoryTypeInformationGuid, &gMemoryTypeInformation); ASSERT_EFI_ERROR (Status); // // If Loading modules At fixed address feature is enabled, install Load moduels at fixed address // Configuration Table so that user could easily to retrieve the top address to load Dxe and PEI // Code and Tseg base to load SMM driver. // if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) { Status = CoreInstallConfigurationTable (&gLoadFixedAddressConfigurationTableGuid, &gLoadModuleAtFixAddressConfigurationTable); ASSERT_EFI_ERROR (Status); } // // Report Status Code here for DXE_ENTRY_POINT once it is available // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_ENTRY_POINT) ); // // Create the aligned system table pointer structure that is used by external // debuggers to locate the system table... Also, install debug image info // configuration table. // CoreInitializeDebugImageInfoTable (); CoreNewDebugImageInfoEntry ( EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, gDxeCoreLoadedImage, gDxeCoreImageHandle ); DEBUG ((DEBUG_INFO | DEBUG_LOAD, "HOBLIST address in DXE = 0x%p\n", HobStart)); DEBUG_CODE_BEGIN (); EFI_PEI_HOB_POINTERS Hob; for (Hob.Raw = HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) { if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) { DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Memory Allocation 0x%08x 0x%0lx - 0x%0lx\n", \ Hob.MemoryAllocation->AllocDescriptor.MemoryType, \ Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, \ Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength - 1)); } } for (Hob.Raw = HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) { if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2) { DEBUG ((DEBUG_INFO | DEBUG_LOAD, "FV2 Hob 0x%0lx - 0x%0lx\n", Hob.FirmwareVolume2->BaseAddress, Hob.FirmwareVolume2->BaseAddress + Hob.FirmwareVolume2->Length - 1)); } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) { DEBUG ((DEBUG_INFO | DEBUG_LOAD, "FV Hob 0x%0lx - 0x%0lx\n", Hob.FirmwareVolume->BaseAddress, Hob.FirmwareVolume->BaseAddress + Hob.FirmwareVolume->Length - 1)); } } DEBUG_CODE_END (); // // Initialize the Event Services // Status = CoreInitializeEventServices (); ASSERT_EFI_ERROR (Status); MemoryProfileInstallProtocol (); CoreInitializePropertiesTable (); CoreInitializeMemoryAttributesTable (); // // Get persisted vector hand-off info from GUIDeed HOB again due to HobStart may be updated, // and install configuration table // GuidHob = GetNextGuidHob (&gEfiVectorHandoffInfoPpiGuid, HobStart); if (GuidHob != NULL) { VectorInfoList = (EFI_VECTOR_HANDOFF_INFO *) (GET_GUID_HOB_DATA(GuidHob)); VectorInfo = VectorInfoList; Index = 1; while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) { VectorInfo ++; Index ++; } VectorInfo = AllocateCopyPool (sizeof (EFI_VECTOR_HANDOFF_INFO) * Index, (VOID *) VectorInfoList); ASSERT (VectorInfo != NULL); Status = CoreInstallConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID *) VectorInfo); ASSERT_EFI_ERROR (Status); } // // Get the Protocols that were passed in from PEI to DXE through GUIDed HOBs // // These Protocols are not architectural. This implementation is sharing code between // PEI and DXE in order to save FLASH space. These Protocols could also be implemented // as part of the DXE Core. However, that would also require the DXE Core to be ported // each time a different CPU is used, a different Decompression algorithm is used, or a // different Image type is used. By placing these Protocols in PEI, the DXE Core remains // generic, and only PEI and the Arch Protocols need to be ported from Platform to Platform, // and from CPU to CPU. // // // Publish the EFI, Tiano, and Custom Decompress protocols for use by other DXE components // Status = CoreInstallMultipleProtocolInterfaces ( &mDecompressHandle, &gEfiDecompressProtocolGuid, &gEfiDecompress, NULL ); ASSERT_EFI_ERROR (Status); // // Register for the GUIDs of the Architectural Protocols, so the rest of the // EFI Boot Services and EFI Runtime Services tables can be filled in. // Also register for the GUIDs of optional protocols. // CoreNotifyOnProtocolInstallation (); // // Produce Firmware Volume Protocols, one for each FV in the HOB list. // Status = FwVolBlockDriverInit (gDxeCoreImageHandle, gDxeCoreST); ASSERT_EFI_ERROR (Status); Status = FwVolDriverInit (gDxeCoreImageHandle, gDxeCoreST); ASSERT_EFI_ERROR (Status); // // Produce the Section Extraction Protocol // Status = InitializeSectionExtraction (gDxeCoreImageHandle, gDxeCoreST); ASSERT_EFI_ERROR (Status); // // Initialize the DXE Dispatcher // PERF_START (NULL,"CoreInitializeDispatcher", "DxeMain", 0) ; CoreInitializeDispatcher (); PERF_END (NULL,"CoreInitializeDispatcher", "DxeMain", 0) ; // // Invoke the DXE Dispatcher // PERF_START (NULL, "CoreDispatcher", "DxeMain", 0); CoreDispatcher (); PERF_END (NULL, "CoreDispatcher", "DxeMain", 0); // // Display Architectural protocols that were not loaded if this is DEBUG build // DEBUG_CODE_BEGIN (); CoreDisplayMissingArchProtocols (); DEBUG_CODE_END (); // // Display any drivers that were not dispatched because dependency expression // evaluated to false if this is a debug build // DEBUG_CODE_BEGIN (); CoreDisplayDiscoveredNotDispatched (); DEBUG_CODE_END (); // // Assert if the Architectural Protocols are not present. // Status = CoreAllEfiServicesAvailable (); if (EFI_ERROR(Status)) { // // Report Status code that some Architectural Protocols are not present. // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MAJOR, (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_EC_NO_ARCH) ); } ASSERT_EFI_ERROR (Status); // // Report Status code before transfer control to BDS // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT) ); // // Transfer control to the BDS Architectural Protocol // gBds->Entry (gBds); // // BDS should never return // ASSERT (FALSE); CpuDeadLoop (); UNREACHABLE (); }
/** Main entry point to last PEIM. This function finds DXE Core in the firmware volume and transfer the control to DXE core. @param This Entry point for DXE IPL PPI. @param PeiServices General purpose services available to every PEIM. @param HobList Address to the Pei HOB list. @return EFI_SUCCESS DXE core was successfully loaded. @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core. **/ EFI_STATUS EFIAPI DxeLoadCore ( IN CONST EFI_DXE_IPL_PPI *This, IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_HOB_POINTERS HobList ) { EFI_STATUS Status; EFI_FV_FILE_INFO DxeCoreFileInfo; EFI_PHYSICAL_ADDRESS DxeCoreAddress; UINT64 DxeCoreSize; EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint; EFI_BOOT_MODE BootMode; EFI_PEI_FILE_HANDLE FileHandle; EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; EFI_PEI_LOAD_FILE_PPI *LoadFile; UINTN Instance; UINT32 AuthenticationState; UINTN DataSize; EFI_PEI_S3_RESUME2_PPI *S3Resume; EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1]; // // if in S3 Resume, restore configure // BootMode = GetBootModeHob (); if (BootMode == BOOT_ON_S3_RESUME) { Status = PeiServicesLocatePpi ( &gEfiPeiS3Resume2PpiGuid, 0, NULL, (VOID **) &S3Resume ); if (EFI_ERROR (Status)) { // // Report Status code that S3Resume PPI can not be found // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MAJOR, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_RESUME_PPI_NOT_FOUND) ); } ASSERT_EFI_ERROR (Status); Status = S3Resume->S3RestoreConfig2 (S3Resume); ASSERT_EFI_ERROR (Status); } else if (BootMode == BOOT_IN_RECOVERY_MODE) { REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_RECOVERY_BEGIN)); Status = PeiServicesLocatePpi ( &gEfiPeiRecoveryModulePpiGuid, 0, NULL, (VOID **) &PeiRecovery ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Locate Recovery PPI Failed.(Status = %r)\n", Status)); // // Report Status code the failure of locating Recovery PPI // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MAJOR, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND) ); CpuDeadLoop (); } REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_LOAD)); Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status)); // // Report Status code that recovery image can not be found // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MAJOR, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE) ); CpuDeadLoop (); } REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_START)); // // Now should have a HOB with the DXE core // } if (GetFirstGuidHob ((CONST EFI_GUID *)&gEfiMemoryTypeInformationGuid) == NULL) { // // Don't build GuidHob if GuidHob has been installed. // Status = PeiServicesLocatePpi ( &gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **)&Variable ); if (!EFI_ERROR (Status)) { DataSize = sizeof (MemoryData); Status = Variable->GetVariable ( Variable, EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, &gEfiMemoryTypeInformationGuid, NULL, &DataSize, &MemoryData ); if (!EFI_ERROR (Status) && ValidateMemoryTypeInfoVariable(MemoryData, DataSize)) { // // Build the GUID'd HOB for DXE // BuildGuidDataHob ( &gEfiMemoryTypeInformationGuid, MemoryData, DataSize ); } } } // // Look in all the FVs present in PEI and find the DXE Core FileHandle // FileHandle = DxeIplFindDxeCore (); // // Load the DXE Core from a Firmware Volume. // Instance = 0; do { Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **) &LoadFile); // // These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully. // ASSERT_EFI_ERROR (Status); Status = LoadFile->LoadFile ( LoadFile, FileHandle, &DxeCoreAddress, &DxeCoreSize, &DxeCoreEntryPoint, &AuthenticationState ); } while (EFI_ERROR (Status)); // // Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name. // Status = PeiServicesFfsGetFileInfo (FileHandle, &DxeCoreFileInfo); ASSERT_EFI_ERROR (Status); // // Add HOB for the DXE Core // BuildModuleHob ( &DxeCoreFileInfo.FileName, DxeCoreAddress, ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE), DxeCoreEntryPoint ); // // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT // REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT)); DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint))); // // Transfer control to the DXE Core // The hand off state is simply a pointer to the HOB list // HandOffToDxeCore (DxeCoreEntryPoint, HobList); // // If we get here, then the DXE Core returned. This is an error // DxeCore should not return. // ASSERT (FALSE); CpuDeadLoop (); return EFI_OUT_OF_RESOURCES; }
/** Changes the runtime addressing mode of EFI firmware from physical to virtual. @param MemoryMapSize The size in bytes of VirtualMap. @param DescriptorSize The size in bytes of an entry in the VirtualMap. @param DescriptorVersion The version of the structure entries in VirtualMap. @param VirtualMap An array of memory descriptors which contain new virtual address mapping information for all runtime ranges. @retval EFI_SUCCESS The virtual address map has been applied. @retval EFI_UNSUPPORTED EFI firmware is not at runtime, or the EFI firmware is already in virtual address mapped mode. @retval EFI_INVALID_PARAMETER DescriptorSize or DescriptorVersion is invalid. @retval EFI_NO_MAPPING A virtual address was not supplied for a range in the memory map that requires a mapping. @retval EFI_NOT_FOUND A virtual address was supplied for an address that is not found in the memory map. **/ EFI_STATUS EFIAPI RuntimeDriverSetVirtualAddressMap ( IN UINTN MemoryMapSize, IN UINTN DescriptorSize, IN UINT32 DescriptorVersion, IN EFI_MEMORY_DESCRIPTOR *VirtualMap ) { EFI_STATUS Status; EFI_RUNTIME_EVENT_ENTRY *RuntimeEvent; EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage; LIST_ENTRY *Link; EFI_PHYSICAL_ADDRESS VirtImageBase; // // Can only switch to virtual addresses once the memory map is locked down, // and can only set it once // if (!mRuntime.AtRuntime || mRuntime.VirtualMode) { return EFI_UNSUPPORTED; } // // Only understand the original descriptor format // if (DescriptorVersion != EFI_MEMORY_DESCRIPTOR_VERSION || DescriptorSize < sizeof (EFI_MEMORY_DESCRIPTOR)) { return EFI_INVALID_PARAMETER; } // // We are now committed to go to virtual mode, so lets get to it! // mRuntime.VirtualMode = TRUE; // // ConvertPointer() needs this mVirtualMap to do the conversion. So set up // globals we need to parse the virtual address map. // mVirtualMapDescriptorSize = DescriptorSize; mVirtualMapMaxIndex = MemoryMapSize / DescriptorSize; mVirtualMap = VirtualMap; // // ReporstStatusCodeLib will check and make sure this service can be called in runtime mode. // REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_EFI_RUNTIME_SERVICE | EFI_SW_RS_PC_SET_VIRTUAL_ADDRESS_MAP)); // // Signal all the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE events. // All runtime events are stored in a list in Runtime AP. // for (Link = mRuntime.EventHead.ForwardLink; Link != &mRuntime.EventHead; Link = Link->ForwardLink) { RuntimeEvent = BASE_CR (Link, EFI_RUNTIME_EVENT_ENTRY, Link); if ((RuntimeEvent->Type & EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) { RuntimeEvent->NotifyFunction ( RuntimeEvent->Event, RuntimeEvent->NotifyContext ); } } // // Relocate runtime images. All runtime images are stored in a list in Runtime AP. // for (Link = mRuntime.ImageHead.ForwardLink; Link != &mRuntime.ImageHead; Link = Link->ForwardLink) { RuntimeImage = BASE_CR (Link, EFI_RUNTIME_IMAGE_ENTRY, Link); // // We don't want to relocate our selves, as we only run in physical mode. // if (mMyImageBase != RuntimeImage->ImageBase) { VirtImageBase = (EFI_PHYSICAL_ADDRESS) (UINTN) RuntimeImage->ImageBase; Status = RuntimeDriverConvertPointer (0, (VOID **) &VirtImageBase); ASSERT_EFI_ERROR (Status); PeCoffLoaderRelocateImageForRuntime ( (EFI_PHYSICAL_ADDRESS) (UINTN) RuntimeImage->ImageBase, VirtImageBase, (UINTN) RuntimeImage->ImageSize, RuntimeImage->RelocationData ); InvalidateInstructionCacheRange (RuntimeImage->ImageBase, (UINTN) RuntimeImage->ImageSize); } } // // Convert all the Runtime Services except ConvertPointer() and SetVirtualAddressMap() // and recompute the CRC-32 // RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetTime); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetTime); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetWakeupTime); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetWakeupTime); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->ResetSystem); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetNextHighMonotonicCount); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetVariable); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetVariable); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetNextVariableName); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->QueryVariableInfo); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->UpdateCapsule); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->QueryCapsuleCapabilities); RuntimeDriverCalculateEfiHdrCrc (&gRT->Hdr); // // UEFI don't require System Configuration Tables Conversion. // // // Convert the runtime fields of the EFI System Table and recompute the CRC-32 // RuntimeDriverConvertInternalPointer ((VOID **) &gST->FirmwareVendor); RuntimeDriverConvertInternalPointer ((VOID **) &gST->ConfigurationTable); RuntimeDriverConvertInternalPointer ((VOID **) &gST->RuntimeServices); RuntimeDriverCalculateEfiHdrCrc (&gST->Hdr); // // At this point, gRT and gST are physical pointers, but the contents of these tables // have been converted to runtime. // // // mVirtualMap is only valid during SetVirtualAddressMap() call // mVirtualMap = NULL; return EFI_SUCCESS; }
/** 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_STATUS Status2; EFI_BOOT_MODE BootMode; if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){ DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n")); return EFI_UNSUPPORTED; } if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { DEBUG ((EFI_D_ERROR, "TPM error!\n")); return EFI_DEVICE_ERROR; } // // Initialize TPM device // Status = PeiServicesGetBootMode (&BootMode); ASSERT_EFI_ERROR (Status); // // In S3 path, skip shadow logic. no measurement is required // if (BootMode != BOOT_ON_S3_RESUME) { Status = (**PeiServices).RegisterForShadow(FileHandle); if (Status == EFI_ALREADY_STARTED) { mImageInMemory = TRUE; } else if (Status == EFI_NOT_FOUND) { ASSERT_EFI_ERROR (Status); } } if (!mImageInMemory) { Status = Tpm12RequestUseTpm (); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "TPM not detected!\n")); goto Done; } if (PcdGet8 (PcdTpmInitializationPolicy) == 1) { if (BootMode == BOOT_ON_S3_RESUME) { Status = Tpm12Startup (TPM_ST_STATE); } else { Status = Tpm12Startup (TPM_ST_CLEAR); } if (EFI_ERROR (Status) ) { goto Done; } } // // TpmSelfTest is optional on S3 path, skip it to save S3 time // if (BootMode != BOOT_ON_S3_RESUME) { Status = Tpm12ContinueSelfTest (); if (EFI_ERROR (Status)) { goto Done; } } // // Only intall TpmInitializedPpi on success // Status = PeiServicesInstallPpi (&mTpmInitializedPpiList); ASSERT_EFI_ERROR (Status); } if (mImageInMemory) { Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices); return Status; } Done: if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "TPM error! Build Hob\n")); BuildGuidHob (&gTpmErrorHobGuid,0); REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) ); } // // Always intall TpmInitializationDonePpi no matter success or fail. // Other driver can know TPM initialization state by TpmInitializedPpi. // Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList); ASSERT_EFI_ERROR (Status2); return Status; }
/** Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result, and build a GUIDed HOB recording the event which will be passed to the DXE phase and added into the Event Log. @param[in] PeiServices Describes the list of possible PEI Services. @param[in] HashData Physical address of the start of the data buffer to be hashed, extended, and logged. @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData. @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. @param[in] NewEventData Pointer to the new event data. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS HashLogExtendEvent ( IN EFI_PEI_SERVICES **PeiServices, IN UINT8 *HashData, IN UINTN HashDataLen, IN TCG_PCR_EVENT_HDR *NewEventHdr, IN UINT8 *NewEventData ) { EFI_STATUS Status; VOID *HobData; if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { return EFI_DEVICE_ERROR; } HobData = NULL; if (HashDataLen != 0) { Status = TpmCommHashAll ( HashData, HashDataLen, &NewEventHdr->Digest ); if (EFI_ERROR (Status)) { goto Done; } } Status = Tpm12Extend ( &NewEventHdr->Digest, NewEventHdr->PCRIndex, NULL ); if (EFI_ERROR (Status)) { goto Done; } HobData = BuildGuidHob ( &gTcgEventEntryHobGuid, sizeof (*NewEventHdr) + NewEventHdr->EventSize ); if (HobData == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr)); HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr)); CopyMem (HobData, NewEventData, NewEventHdr->EventSize); Done: if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) { DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status)); BuildGuidHob (&gTpmErrorHobGuid,0); REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) ); Status = EFI_DEVICE_ERROR; } return Status; }
/** This function handle NotifyPhase API call from the BootLoader. It gives control back to the BootLoader after it is handled. If the Notification code is a ReadyToBoot event, this function will return and FSP continues the remaining execution until it reaches the DxeIpl. **/ VOID FspWaitForNotify ( VOID ) { EFI_STATUS Status; UINT32 NotificationValue; UINT32 NotificationCount; UINT8 Count; NotificationCount = 0; while (NotificationCount < sizeof(mFspNotifySequence) / sizeof(UINT32)) { Count = (UINT8)((NotificationCount << 1) & 0x07); SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY + Count); if (NotificationCount == 0) { SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION); PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); } else if (NotificationCount == 1) { SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION); PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); } else if (NotificationCount == 2) { SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION); PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); } NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase; DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - Begin [Phase: %08X]\n", NotificationValue)); if (mFspNotifySequence[NotificationCount] != NotificationValue) { // // Notify code does not follow the predefined order // DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n")); Status = EFI_UNSUPPORTED; } else { // // Process Notification and Give control back to the boot loader framework caller // Status = FspNotificationHandler (NotificationValue); if (!EFI_ERROR(Status)) { NotificationCount++; } } DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - End [Status: 0x%08X]\n", Status)); SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT + Count); if ((NotificationCount - 1) == 0) { PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); } else if ((NotificationCount - 1) == 1) { PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); } else if ((NotificationCount - 1) == 2) { PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); } do { SetFspApiReturnStatus(Status); Pei2LoaderSwitchStack(); if (Status != EFI_SUCCESS) { DEBUG ((DEBUG_ERROR, "!!!ERROR: NotifyPhaseApi() [Phase: %08X] - Failed - [Status: 0x%08X]\n", NotificationValue, Status)); } } while (Status != EFI_SUCCESS); } // // Control goes back to the PEI Core and it dispatches further PEIMs. // DXEIPL is the final one to transfer control back to the boot loader. // }
/** Collects BIST data from PPI. This function collects BIST data from Sec Platform Information2 PPI or SEC Platform Information PPI. @param PeiServices Pointer to PEI Services Table @param PeiCpuMpData Pointer to PEI CPU MP Data **/ VOID CollectBistDataFromPpi ( IN CONST EFI_PEI_SERVICES **PeiServices, IN PEI_CPU_MP_DATA *PeiCpuMpData ) { EFI_STATUS Status; EFI_PEI_PPI_DESCRIPTOR *SecInformationDescriptor; EFI_SEC_PLATFORM_INFORMATION_RECORD2 *SecPlatformInformation2; EFI_SEC_PLATFORM_INFORMATION_RECORD *SecPlatformInformation; UINTN NumberOfData; EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstance; EFI_SEC_PLATFORM_INFORMATION_CPU BspCpuInstance; UINTN ProcessorNumber; UINTN CpuIndex; PEI_CPU_DATA *CpuData; SecPlatformInformation2 = NULL; SecPlatformInformation = NULL; NumberOfData = 0; CpuInstance = NULL; // // Get BIST information from Sec Platform Information2 Ppi firstly // Status = GetBistInfoFromPpi ( PeiServices, &gEfiSecPlatformInformation2PpiGuid, &SecInformationDescriptor, (VOID *) &SecPlatformInformation2 ); if (Status == EFI_SUCCESS) { // // Sec Platform Information2 PPI includes BSP/APs' BIST information // NumberOfData = SecPlatformInformation2->NumberOfCpus; CpuInstance = SecPlatformInformation2->CpuInstance; } else { // // Otherwise, get BIST information from Sec Platform Information Ppi // Status = GetBistInfoFromPpi ( PeiServices, &gEfiSecPlatformInformationPpiGuid, &SecInformationDescriptor, (VOID *) &SecPlatformInformation ); if (Status == EFI_SUCCESS) { NumberOfData = 1; // // SEC Platform Information only includes BSP's BIST information // and does not have BSP's APIC ID // BspCpuInstance.CpuLocation = GetInitialApicId (); BspCpuInstance.InfoRecord.IA32HealthFlags.Uint32 = SecPlatformInformation->IA32HealthFlags.Uint32; CpuInstance = &BspCpuInstance; } else { DEBUG ((EFI_D_INFO, "Does not find any stored CPU BIST information from PPI!\n")); } } for (ProcessorNumber = 0; ProcessorNumber < PeiCpuMpData->CpuCount; ProcessorNumber ++) { CpuData = &PeiCpuMpData->CpuData[ProcessorNumber]; for (CpuIndex = 0; CpuIndex < NumberOfData; CpuIndex ++) { ASSERT (CpuInstance != NULL); if (CpuData->ApicId == CpuInstance[CpuIndex].CpuLocation) { // // Update processor's BIST data if it is already stored before // CpuData->Health = CpuInstance[CpuIndex].InfoRecord.IA32HealthFlags; } } if (CpuData->Health.Uint32 == 0) { CpuData->CpuHealthy = TRUE; } else { CpuData->CpuHealthy = FALSE; // // Report Status Code that self test is failed // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MAJOR, (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST) ); } DEBUG ((EFI_D_INFO, " APICID - 0x%08x, BIST - 0x%08x\n", PeiCpuMpData->CpuData[ProcessorNumber].ApicId, PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32 )); } if (SecPlatformInformation2 != NULL && NumberOfData < PeiCpuMpData->CpuCount) { // // Reinstall SecPlatformInformation2 PPI to include new BIST inforamtion // Status = PeiServicesReInstallPpi ( SecInformationDescriptor, &mPeiSecPlatformInformation2Ppi ); ASSERT_EFI_ERROR (Status); } else { // // Install SecPlatformInformation2 PPI to include new BIST inforamtion // Status = PeiServicesInstallPpi (&mPeiSecPlatformInformation2Ppi); ASSERT_EFI_ERROR(Status); } }
/** 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_STATUS Status2; EFI_BOOT_MODE BootMode; TPM_PCRINDEX PcrIndex; BOOLEAN S3ErrorReport; if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) || CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)) { DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n")); return EFI_UNSUPPORTED; } if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { DEBUG ((EFI_D_ERROR, "TPM2 error!\n")); return EFI_DEVICE_ERROR; } Status = PeiServicesGetBootMode (&BootMode); ASSERT_EFI_ERROR (Status); // // In S3 path, skip shadow logic. no measurement is required // if (BootMode != BOOT_ON_S3_RESUME) { Status = (**PeiServices).RegisterForShadow(FileHandle); if (Status == EFI_ALREADY_STARTED) { mImageInMemory = TRUE; mFileHandle = FileHandle; } else if (Status == EFI_NOT_FOUND) { ASSERT_EFI_ERROR (Status); } } if (!mImageInMemory) { // // Initialize TPM device // Status = Tpm2RequestUseTpm (); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "TPM2 not detected!\n")); goto Done; } S3ErrorReport = FALSE; if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) { if (BootMode == BOOT_ON_S3_RESUME) { Status = Tpm2Startup (TPM_SU_STATE); if (EFI_ERROR (Status) ) { Status = Tpm2Startup (TPM_SU_CLEAR); if (!EFI_ERROR(Status)) { S3ErrorReport = TRUE; } } } else { Status = Tpm2Startup (TPM_SU_CLEAR); } if (EFI_ERROR (Status) ) { goto Done; } } // // Update Tpm2HashMask according to PCR bank. // SyncPcrAllocationsAndPcrMask (); if (S3ErrorReport) { // // The system firmware that resumes from S3 MUST deal with a // TPM2_Startup error appropriately. // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and // configuring the device securely by taking actions like extending a // separator with an error digest (0x01) into PCRs 0 through 7. // for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) { Status = MeasureSeparatorEventWithError (PcrIndex); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Separator Event with Error not Measured. Error!\n")); } } } // // TpmSelfTest is optional on S3 path, skip it to save S3 time // if (BootMode != BOOT_ON_S3_RESUME) { if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) { Status = Tpm2SelfTest (NO); if (EFI_ERROR (Status)) { goto Done; } } } // // Only intall TpmInitializedPpi on success // Status = PeiServicesInstallPpi (&mTpmInitializedPpiList); ASSERT_EFI_ERROR (Status); } if (mImageInMemory) { Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices); return Status; } Done: if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "TPM2 error! Build Hob\n")); BuildGuidHob (&gTpmErrorHobGuid,0); REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) ); } // // Always intall TpmInitializationDonePpi no matter success or fail. // Other driver can know TPM initialization state by TpmInitializedPpi. // Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList); ASSERT_EFI_ERROR (Status2); return Status; }
/** Starts the mouse device with this driver. This function consumes USB I/O Portocol, intializes USB mouse device, installs Simple Pointer Protocol, and submits Asynchronous Interrupt Transfer to manage the USB mouse device. @param This The USB mouse driver binding instance. @param Controller Handle of device to bind driver to. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver supports this device. @retval EFI_UNSUPPORTED This driver does not support this device. @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error. @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources. @retval EFI_ALREADY_STARTED This driver has been started. **/ EFI_STATUS EFIAPI USBMouseDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_USB_IO_PROTOCOL *UsbIo; USB_MOUSE_DEV *UsbMouseDevice; UINT8 EndpointNumber; EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; UINT8 Index; UINT8 EndpointAddr; UINT8 PollingInterval; UINT8 PacketSize; BOOLEAN Found; EFI_TPL OldTpl; OldTpl = gBS->RaiseTPL (TPL_CALLBACK); // // Open USB I/O Protocol // Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid, (VOID **) &UsbIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ErrorExit1; } UsbMouseDevice = AllocateZeroPool (sizeof (USB_MOUSE_DEV)); ASSERT (UsbMouseDevice != NULL); UsbMouseDevice->UsbIo = UsbIo; UsbMouseDevice->Signature = USB_MOUSE_DEV_SIGNATURE; // // Get the Device Path Protocol on Controller's handle // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &UsbMouseDevice->DevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { goto ErrorExit; } // // Report Status Code here since USB mouse will be detected next. // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT), UsbMouseDevice->DevicePath ); // // Get interface & endpoint descriptor // UsbIo->UsbGetInterfaceDescriptor ( UsbIo, &UsbMouseDevice->InterfaceDescriptor ); EndpointNumber = UsbMouseDevice->InterfaceDescriptor.NumEndpoints; // // Traverse endpoints to find interrupt endpoint // Found = FALSE; for (Index = 0; Index < EndpointNumber; Index++) { UsbIo->UsbGetEndpointDescriptor ( UsbIo, Index, &EndpointDescriptor ); if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) { // // We only care interrupt endpoint here // CopyMem(&UsbMouseDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); Found = TRUE; break; } } if (!Found) { // // Report Status Code to indicate that there is no USB mouse // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED) ); // // No interrupt endpoint found, then return unsupported. // Status = EFI_UNSUPPORTED; goto ErrorExit; } // // Report Status Code here since USB mouse has be detected. // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED), UsbMouseDevice->DevicePath ); Status = InitializeUsbMouseDevice (UsbMouseDevice); if (EFI_ERROR (Status)) { // // Fail to initialize USB mouse device. // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INTERFACE_ERROR), UsbMouseDevice->DevicePath ); goto ErrorExit; } // // Initialize and install EFI Simple Pointer Protocol. // UsbMouseDevice->SimplePointerProtocol.GetState = GetMouseState; UsbMouseDevice->SimplePointerProtocol.Reset = UsbMouseReset; UsbMouseDevice->SimplePointerProtocol.Mode = &UsbMouseDevice->Mode; Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, UsbMouseWaitForInput, UsbMouseDevice, &((UsbMouseDevice->SimplePointerProtocol).WaitForInput) ); if (EFI_ERROR (Status)) { goto ErrorExit; } Status = gBS->InstallProtocolInterface ( &Controller, &gEfiSimplePointerProtocolGuid, EFI_NATIVE_INTERFACE, &UsbMouseDevice->SimplePointerProtocol ); if (EFI_ERROR (Status)) { goto ErrorExit; } // // The next step would be submitting Asynchronous Interrupt Transfer on this mouse device. // After that we will be able to get key data from it. Thus this is deemed as // the enable action of the mouse, so report status code accordingly. // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE), UsbMouseDevice->DevicePath ); // // Submit Asynchronous Interrupt Transfer to manage this device. // EndpointAddr = UsbMouseDevice->IntEndpointDescriptor.EndpointAddress; PollingInterval = UsbMouseDevice->IntEndpointDescriptor.Interval; PacketSize = (UINT8) (UsbMouseDevice->IntEndpointDescriptor.MaxPacketSize); Status = UsbIo->UsbAsyncInterruptTransfer ( UsbIo, EndpointAddr, TRUE, PollingInterval, PacketSize, OnMouseInterruptComplete, UsbMouseDevice ); if (EFI_ERROR (Status)) { // // If submit error, uninstall that interface // gBS->UninstallProtocolInterface ( Controller, &gEfiSimplePointerProtocolGuid, &UsbMouseDevice->SimplePointerProtocol ); goto ErrorExit; } UsbMouseDevice->ControllerNameTable = NULL; AddUnicodeString2 ( "eng", gUsbMouseComponentName.SupportedLanguages, &UsbMouseDevice->ControllerNameTable, L"Generic Usb Mouse", TRUE ); AddUnicodeString2 ( "en", gUsbMouseComponentName2.SupportedLanguages, &UsbMouseDevice->ControllerNameTable, L"Generic Usb Mouse", FALSE ); gBS->RestoreTPL (OldTpl); return EFI_SUCCESS; // // Error handler // ErrorExit: if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiUsbIoProtocolGuid, This->DriverBindingHandle, Controller ); if (UsbMouseDevice != NULL) { if ((UsbMouseDevice->SimplePointerProtocol).WaitForInput != NULL) { gBS->CloseEvent ((UsbMouseDevice->SimplePointerProtocol).WaitForInput); } FreePool (UsbMouseDevice); UsbMouseDevice = NULL; } } ErrorExit1: gBS->RestoreTPL (OldTpl); return Status; }
/** This function is the main entry of the platform setup entry. The function will present the main menu of the system setup, this is the platform reference part and can be customize. @param TimeoutDefault The fault time out value before the system continue to boot. @param ConnectAllHappened The indicater to check if the connect all have already happened. **/ VOID PlatformBdsEnterFrontPage ( IN UINT16 TimeoutDefault, IN BOOLEAN ConnectAllHappened ) { EFI_STATUS Status; EFI_STATUS StatusHotkey; EFI_BOOT_LOGO_PROTOCOL *BootLogo; EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; UINTN BootTextColumn; UINTN BootTextRow; UINT64 OsIndication; UINTN DataSize; EFI_INPUT_KEY Key; GraphicsOutput = NULL; SimpleTextOut = NULL; PERF_START (NULL, "BdsTimeOut", "BDS", 0); // // Indicate if we need connect all in the platform setup // if (ConnectAllHappened) { gConnectAllHappened = TRUE; } if (!mModeInitialized) { // // After the console is ready, get current video resolution // and text mode before launching setup at first time. // Status = gBS->HandleProtocol ( gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID**)&GraphicsOutput ); if (EFI_ERROR (Status)) { GraphicsOutput = NULL; } Status = gBS->HandleProtocol ( gST->ConsoleOutHandle, &gEfiSimpleTextOutProtocolGuid, (VOID**)&SimpleTextOut ); if (EFI_ERROR (Status)) { SimpleTextOut = NULL; } if (GraphicsOutput != NULL) { // // Get current video resolution and text mode. // mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution; mBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution; } if (SimpleTextOut != NULL) { Status = SimpleTextOut->QueryMode ( SimpleTextOut, SimpleTextOut->Mode->Mode, &BootTextColumn, &BootTextRow ); mBootTextModeColumn = (UINT32)BootTextColumn; mBootTextModeRow = (UINT32)BootTextRow; } // // Get user defined text mode for setup. // mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution); mSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution); mSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn); mSetupTextModeRow = PcdGet32 (PcdSetupConOutRow); mModeInitialized = TRUE; } // // goto FrontPage directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set // OsIndication = 0; DataSize = sizeof(UINT64); Status = gRT->GetVariable ( L"OsIndications", &gEfiGlobalVariableGuid, NULL, &DataSize, &OsIndication ); // // goto FrontPage directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot // if (!EFI_ERROR(Status) && ((OsIndication & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0)) { // // Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS // OsIndication &= ~((UINT64)EFI_OS_INDICATIONS_BOOT_TO_FW_UI); Status = gRT->SetVariable ( L"OsIndications", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, sizeof(UINT64), &OsIndication ); // // Changing the content without increasing its size with current variable implementation shouldn't fail. // ASSERT_EFI_ERROR (Status); // // Follow generic rule, Call ReadKeyStroke to connect ConIn before enter UI // if (PcdGetBool (PcdConInConnectOnDemand)) { gST->ConIn->ReadKeyStroke(gST->ConIn, &Key); } // // Ensure screen is clear when switch Console from Graphics mode to Text mode // gST->ConOut->EnableCursor (gST->ConOut, TRUE); gST->ConOut->ClearScreen (gST->ConOut); } else { HotkeyBoot (); if (TimeoutDefault != 0xffff) { Status = ShowProgress (TimeoutDefault); StatusHotkey = HotkeyBoot (); if (!FeaturePcdGet(PcdBootlogoOnlyEnable) || !EFI_ERROR(Status) || !EFI_ERROR(StatusHotkey)){ // // Ensure screen is clear when switch Console from Graphics mode to Text mode // Skip it in normal boot // gST->ConOut->EnableCursor (gST->ConOut, TRUE); gST->ConOut->ClearScreen (gST->ConOut); } if (EFI_ERROR (Status)) { // // Timeout or user press enter to continue // goto Exit; } } } // // Boot Logo is corrupted, report it using Boot Logo protocol. // Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo); if (!EFI_ERROR (Status) && (BootLogo != NULL)) { BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0); } // // Install BM HiiPackages. // Keep BootMaint HiiPackage, so that it can be covered by global setting. // InitBMPackage (); Status = EFI_SUCCESS; do { // // Set proper video resolution and text mode for setup // BdsSetConsoleMode (TRUE); InitializeFrontPage (FALSE); // // Update Front Page strings // UpdateFrontPageStrings (); gCallbackKey = 0; CallFrontPage (); // // If gCallbackKey is greater than 1 and less or equal to 5, // it will launch configuration utilities. // 2 = set language // 3 = boot manager // 4 = device manager // 5 = boot maintenance manager // if (gCallbackKey != 0) { REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP) ); } // // Based on the key that was set, we can determine what to do // switch (gCallbackKey) { // // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can // describe to their customers in documentation how to find their setup information (namely // under the device manager and specific buckets) // // These entries consist of the Continue, Select language, Boot Manager, and Device Manager // case FRONT_PAGE_KEY_CONTINUE: // // User hit continue // break; case FRONT_PAGE_KEY_LANGUAGE: // // User made a language setting change - display front page again // break; case FRONT_PAGE_KEY_BOOT_MANAGER: // // Remove the installed BootMaint HiiPackages when exit. // FreeBMPackage (); // // User chose to run the Boot Manager // CallBootManager (); // // Reinstall BootMaint HiiPackages after exiting from Boot Manager. // InitBMPackage (); break; case FRONT_PAGE_KEY_DEVICE_MANAGER: // // Display the Device Manager // do { CallDeviceManager (); } while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER); break; case FRONT_PAGE_KEY_BOOT_MAINTAIN: // // Display the Boot Maintenance Manager // BdsStartBootMaint (); break; } } while ((Status == EFI_SUCCESS) && (gCallbackKey != FRONT_PAGE_KEY_CONTINUE)); if (mLanguageString != NULL) { FreePool (mLanguageString); mLanguageString = NULL; } // //Will leave browser, check any reset required change is applied? if yes, reset system // SetupResetReminder (); // // Remove the installed BootMaint HiiPackages when exit. // FreeBMPackage (); Exit: // // Automatically load current entry // Note: The following lines of code only execute when Auto boot // takes affect // PERF_END (NULL, "BdsTimeOut", "BDS", 0); }
/** Starts the device with this driver. @param This The driver binding instance. @param Controller Handle of device to bind driver to. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS The controller is controlled by the driver. @retval Other This controller cannot be started. **/ EFI_STATUS EFIAPI VirtualKeyboardDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate; PLATFORM_VIRTUAL_KBD_PROTOCOL *PlatformVirtual; Status = gBS->OpenProtocol ( Controller, &gPlatformVirtualKeyboardProtocolGuid, (VOID **) &PlatformVirtual, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Allocate the private device structure // VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_DEV)); if (VirtualKeyboardPrivate == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } // // Initialize the private device structure // VirtualKeyboardPrivate->Signature = VIRTUAL_KEYBOARD_DEV_SIGNATURE; VirtualKeyboardPrivate->Handle = Controller; VirtualKeyboardPrivate->PlatformVirtual = PlatformVirtual; VirtualKeyboardPrivate->Queue.Front = 0; VirtualKeyboardPrivate->Queue.Rear = 0; VirtualKeyboardPrivate->QueueForNotify.Front = 0; VirtualKeyboardPrivate->QueueForNotify.Rear = 0; VirtualKeyboardPrivate->SimpleTextIn.Reset = VirtualKeyboardReset; VirtualKeyboardPrivate->SimpleTextIn.ReadKeyStroke = VirtualKeyboardReadKeyStroke; VirtualKeyboardPrivate->SimpleTextInputEx.Reset = VirtualKeyboardResetEx; VirtualKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx = VirtualKeyboardReadKeyStrokeEx; VirtualKeyboardPrivate->SimpleTextInputEx.SetState = VirtualKeyboardSetState; VirtualKeyboardPrivate->SimpleTextInputEx.RegisterKeyNotify = VirtualKeyboardRegisterKeyNotify; VirtualKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = VirtualKeyboardUnregisterKeyNotify; InitializeListHead (&VirtualKeyboardPrivate->NotifyList); Status = PlatformVirtual->Register (); if (EFI_ERROR (Status)) { goto Done; } // // Report that the keyboard is being enabled // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE ); // // Setup the WaitForKey event // Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, VirtualKeyboardWaitForKey, &(VirtualKeyboardPrivate->SimpleTextIn), &((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey) ); if (EFI_ERROR (Status)) { (VirtualKeyboardPrivate->SimpleTextIn).WaitForKey = NULL; goto Done; } Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, VirtualKeyboardWaitForKeyEx, &(VirtualKeyboardPrivate->SimpleTextInputEx), &(VirtualKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx) ); if (EFI_ERROR (Status)) { VirtualKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx = NULL; goto Done; } // // Setup a periodic timer, used for reading keystrokes at a fixed interval // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, VirtualKeyboardTimerHandler, VirtualKeyboardPrivate, &VirtualKeyboardPrivate->TimerEvent ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; goto Done; } Status = gBS->SetTimer ( VirtualKeyboardPrivate->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; goto Done; } Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, KeyNotifyProcessHandler, VirtualKeyboardPrivate, &VirtualKeyboardPrivate->KeyNotifyProcessEvent ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; goto Done; } // // Reset the keyboard device // Status = VirtualKeyboardPrivate->SimpleTextInputEx.Reset ( &VirtualKeyboardPrivate->SimpleTextInputEx, FALSE ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "[KBD]Reset Failed. Status - %r\n", Status)); goto Done; } // // Install protocol interfaces for the keyboard device. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiSimpleTextInProtocolGuid, &VirtualKeyboardPrivate->SimpleTextIn, &gEfiSimpleTextInputExProtocolGuid, &VirtualKeyboardPrivate->SimpleTextInputEx, NULL ); Done: if (EFI_ERROR (Status)) { if (VirtualKeyboardPrivate != NULL) { if ((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey != NULL) { gBS->CloseEvent ((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey); } if ((VirtualKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) { gBS->CloseEvent ( (VirtualKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx ); } if (VirtualKeyboardPrivate->KeyNotifyProcessEvent != NULL) { gBS->CloseEvent (VirtualKeyboardPrivate->KeyNotifyProcessEvent); } VirtualKeyboardFreeNotifyList (&VirtualKeyboardPrivate->NotifyList); if (VirtualKeyboardPrivate->TimerEvent != NULL) { gBS->CloseEvent (VirtualKeyboardPrivate->TimerEvent); } FreePool (VirtualKeyboardPrivate); } } gBS->CloseProtocol ( Controller, &gPlatformVirtualKeyboardProtocolGuid, This->DriverBindingHandle, Controller ); return Status; }
/** Starts the keyboard device with this driver. This function produces Simple Text Input Protocol and Simple Text Input Ex Protocol, initializes the keyboard device, and submit Asynchronous Interrupt Transfer to manage this keyboard device. @param This The USB keyboard driver binding instance. @param Controller Handle of device to bind driver to. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver. @retval EFI_UNSUPPORTED No interrupt endpoint can be found. @retval Other This controller cannot be started. **/ EFI_STATUS EFIAPI USBKeyboardDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_USB_IO_PROTOCOL *UsbIo; USB_KB_DEV *UsbKeyboardDevice; UINT8 EndpointNumber; EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; UINT8 Index; UINT8 EndpointAddr; UINT8 PollingInterval; UINT8 PacketSize; BOOLEAN Found; EFI_TPL OldTpl; OldTpl = gBS->RaiseTPL (TPL_CALLBACK); // // Open USB I/O Protocol // Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid, (VOID **) &UsbIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ErrorExit1; } UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV)); ASSERT (UsbKeyboardDevice != NULL); // // Get the Device Path Protocol on Controller's handle // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &UsbKeyboardDevice->DevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { goto ErrorExit; } // // Report that the USB keyboard is being enabled // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE), UsbKeyboardDevice->DevicePath ); // // This is pretty close to keyboard detection, so log progress // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT), UsbKeyboardDevice->DevicePath ); UsbKeyboardDevice->UsbIo = UsbIo; // // Get interface & endpoint descriptor // UsbIo->UsbGetInterfaceDescriptor ( UsbIo, &UsbKeyboardDevice->InterfaceDescriptor ); EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints; // // Traverse endpoints to find interrupt endpoint // Found = FALSE; for (Index = 0; Index < EndpointNumber; Index++) { UsbIo->UsbGetEndpointDescriptor ( UsbIo, Index, &EndpointDescriptor ); if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) { // // We only care interrupt endpoint here // CopyMem(&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); Found = TRUE; break; } } if (!Found) { // // Report Status Code to indicate that there is no USB keyboard // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED) ); // // No interrupt endpoint found, then return unsupported. // Status = EFI_UNSUPPORTED; goto ErrorExit; } REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED), UsbKeyboardDevice->DevicePath ); UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE; UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset; UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke; UsbKeyboardDevice->SimpleInputEx.Reset = USBKeyboardResetEx; UsbKeyboardDevice->SimpleInputEx.ReadKeyStrokeEx = USBKeyboardReadKeyStrokeEx; UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState; UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify; UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify; InitializeListHead (&UsbKeyboardDevice->NotifyList); Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, USBKeyboardTimerHandler, UsbKeyboardDevice, &UsbKeyboardDevice->TimerEvent ); if (!EFI_ERROR (Status)) { Status = gBS->SetTimer (UsbKeyboardDevice->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL); } if (EFI_ERROR (Status)) { goto ErrorExit; } Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, USBKeyboardWaitForKey, UsbKeyboardDevice, &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx) ); if (EFI_ERROR (Status)) { goto ErrorExit; } Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, USBKeyboardWaitForKey, UsbKeyboardDevice, &(UsbKeyboardDevice->SimpleInput.WaitForKey) ); if (EFI_ERROR (Status)) { goto ErrorExit; } // // Install Simple Text Input Protocol and Simple Text Input Ex Protocol // for the USB keyboard device. // USB keyboard is a hot plug device, and expected to work immediately // when plugging into system, other conventional console devices could // distinguish it by its device path. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiSimpleTextInProtocolGuid, &UsbKeyboardDevice->SimpleInput, &gEfiSimpleTextInputExProtocolGuid, &UsbKeyboardDevice->SimpleInputEx, NULL ); if (EFI_ERROR (Status)) { goto ErrorExit; } UsbKeyboardDevice->ControllerHandle = Controller; Status = InitKeyboardLayout (UsbKeyboardDevice); if (EFI_ERROR (Status)) { gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiSimpleTextInProtocolGuid, &UsbKeyboardDevice->SimpleInput, &gEfiSimpleTextInputExProtocolGuid, &UsbKeyboardDevice->SimpleInputEx, NULL ); goto ErrorExit; } // // Reset USB Keyboard Device exhaustively. // Status = UsbKeyboardDevice->SimpleInputEx.Reset ( &UsbKeyboardDevice->SimpleInputEx, TRUE ); if (EFI_ERROR (Status)) { gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiSimpleTextInProtocolGuid, &UsbKeyboardDevice->SimpleInput, &gEfiSimpleTextInputExProtocolGuid, &UsbKeyboardDevice->SimpleInputEx, NULL ); goto ErrorExit; } // // Submit Asynchronous Interrupt Transfer to manage this device. // EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress; PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval; PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize); Status = UsbIo->UsbAsyncInterruptTransfer ( UsbIo, EndpointAddr, TRUE, PollingInterval, PacketSize, KeyboardHandler, UsbKeyboardDevice ); if (EFI_ERROR (Status)) { gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiSimpleTextInProtocolGuid, &UsbKeyboardDevice->SimpleInput, &gEfiSimpleTextInputExProtocolGuid, &UsbKeyboardDevice->SimpleInputEx, NULL ); goto ErrorExit; } UsbKeyboardDevice->ControllerNameTable = NULL; AddUnicodeString2 ( "eng", gUsbKeyboardComponentName.SupportedLanguages, &UsbKeyboardDevice->ControllerNameTable, L"Generic Usb Keyboard", TRUE ); AddUnicodeString2 ( "en", gUsbKeyboardComponentName2.SupportedLanguages, &UsbKeyboardDevice->ControllerNameTable, L"Generic Usb Keyboard", FALSE ); gBS->RestoreTPL (OldTpl); return EFI_SUCCESS; // // Error handler // ErrorExit: if (UsbKeyboardDevice != NULL) { if (UsbKeyboardDevice->TimerEvent != NULL) { gBS->CloseEvent (UsbKeyboardDevice->TimerEvent); } if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) { gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey); } if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) { gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx); } if (UsbKeyboardDevice->KeyboardLayoutEvent != NULL) { ReleaseKeyboardLayoutResources (UsbKeyboardDevice); gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent); } FreePool (UsbKeyboardDevice); UsbKeyboardDevice = NULL; } gBS->CloseProtocol ( Controller, &gEfiUsbIoProtocolGuid, This->DriverBindingHandle, Controller ); ErrorExit1: gBS->RestoreTPL (OldTpl); return Status; }
/** The module Entry Point of the CPU SMM driver. @param ImageHandle The firmware allocated handle for the EFI image. @param 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 PiCpuSmmEntry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MpServices; UINTN NumberOfEnabledProcessors; UINTN Index; VOID *Buffer; UINTN BufferPages; UINTN TileCodeSize; UINTN TileDataSize; UINTN TileSize; UINT8 *Stacks; VOID *Registration; UINT32 RegEax; UINT32 RegEdx; UINTN FamilyId; UINTN ModelId; UINT32 Cr3; // // Initialize Debug Agent to support source level debug in SMM code // InitializeDebugAgent (DEBUG_AGENT_INIT_SMM, NULL, NULL); // // Report the start of CPU SMM initialization. // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_SMM_INIT ); // // Fix segment address of the long-mode-switch jump // if (sizeof (UINTN) == sizeof (UINT64)) { gSmmJmpAddr.Segment = LONG_MODE_CODE_SEGMENT; } // // Find out SMRR Base and SMRR Size // FindSmramInfo (&mCpuHotPlugData.SmrrBase, &mCpuHotPlugData.SmrrSize); // // Get MP Services Protocol // Status = SystemTable->BootServices->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices); ASSERT_EFI_ERROR (Status); // // Use MP Services Protocol to retrieve the number of processors and number of enabled processors // Status = MpServices->GetNumberOfProcessors (MpServices, &mNumberOfCpus, &NumberOfEnabledProcessors); ASSERT_EFI_ERROR (Status); ASSERT (mNumberOfCpus <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber)); // // 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)); } );
/** Terminates all boot services. @param ImageHandle Handle that identifies the exiting image. @param MapKey Key to the latest memory map. @retval EFI_SUCCESS Boot Services terminated @retval EFI_INVALID_PARAMETER MapKey is incorrect. **/ EFI_STATUS EFIAPI CoreExitBootServices ( IN EFI_HANDLE ImageHandle, IN UINTN MapKey ) { EFI_STATUS Status; // // Disable Timer // gTimer->SetTimerPeriod (gTimer, 0); // // Terminate memory services if the MapKey matches // Status = CoreTerminateMemoryMap (MapKey); if (EFI_ERROR (Status)) { // // Notify other drivers that ExitBootServices fail // CoreNotifySignalList (&gEventExitBootServicesFailedGuid); return Status; } gMemoryMapTerminated = TRUE; // // Notify other drivers that we are exiting boot services. // CoreNotifySignalList (&gEfiEventExitBootServicesGuid); // // Report that ExitBootServices() has been called // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES) ); // // Disable interrupt of Debug timer. // SaveAndSetDebugTimerInterrupt (FALSE); // // Disable CPU Interrupts // gCpu->DisableInterrupt (gCpu); // // Clear the non-runtime values of the EFI System Table // gDxeCoreST->BootServices = NULL; gDxeCoreST->ConIn = NULL; gDxeCoreST->ConsoleInHandle = NULL; gDxeCoreST->ConOut = NULL; gDxeCoreST->ConsoleOutHandle = NULL; gDxeCoreST->StdErr = NULL; gDxeCoreST->StandardErrorHandle = NULL; // // Recompute the 32-bit CRC of the EFI System Table // CalculateEfiHdrCrc (&gDxeCoreST->Hdr); // // Zero out the Boot Service Table // ZeroMem (gBS, sizeof (EFI_BOOT_SERVICES)); gBS = NULL; // // Update the AtRuntime field in Runtiem AP. // gRuntime->AtRuntime = TRUE; return Status; }