/** SMM Fault Tolerant Write protocol notification event handler. Non-Volatile variable write may needs FTW protocol to reclaim when writting variable. @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 SmmEventCallback runs successfully @retval EFI_NOT_FOUND The Fvb protocol for variable is not found. **/ EFI_STATUS EFIAPI SmmFtwNotificationEvent ( IN CONST EFI_GUID *Protocol, IN VOID *Interface, IN EFI_HANDLE Handle ) { EFI_STATUS Status; EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol; EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol; EFI_PHYSICAL_ADDRESS NvStorageVariableBase; if (mVariableModuleGlobal->FvbInstance != NULL) { return EFI_SUCCESS; } // // Ensure SMM FTW protocol is installed. // Status = GetFtwProtocol ((VOID **)&FtwProtocol); if (EFI_ERROR (Status)) { return Status; } // // Find the proper FVB protocol for variable. // NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64); if (NvStorageVariableBase == 0) { NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase); } Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } mVariableModuleGlobal->FvbInstance = FvbProtocol; Status = VariableWriteServiceInitialize (); ASSERT_EFI_ERROR (Status); // // Notify the variable wrapper driver the variable write service is ready // Status = gBS->InstallProtocolInterface ( &mSmmVariableHandle, &gSmmVariableWriteGuid, EFI_NATIVE_INTERFACE, NULL ); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }
/** Fault Tolerant Write protocol notification event handler. Non-Volatile variable write may needs FTW protocol to reclaim when writting variable. @param[in] Event Event whose notification function is being invoked. @param[in] Context Pointer to the notification function's context. **/ VOID EFIAPI FtwNotificationEvent ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol; EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol; EFI_PHYSICAL_ADDRESS NvStorageVariableBase; EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; EFI_PHYSICAL_ADDRESS BaseAddress; UINT64 Length; EFI_PHYSICAL_ADDRESS VariableStoreBase; UINT64 VariableStoreLength; UINTN FtwMaxBlockSize; // // Ensure FTW protocol is installed. // Status = GetFtwProtocol ((VOID**) &FtwProtocol); if (EFI_ERROR (Status)) { return ; } Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize); if (!EFI_ERROR (Status)) { ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize); } // // Find the proper FVB protocol for variable. // NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64); if (NvStorageVariableBase == 0) { NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase); } Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol); if (EFI_ERROR (Status)) { return ; } mVariableModuleGlobal->FvbInstance = FvbProtocol; // // Mark the variable storage region of the FLASH as RUNTIME. // VariableStoreBase = NvStorageVariableBase + (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NvStorageVariableBase))->HeaderLength); VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size; BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK); Length = VariableStoreLength + (VariableStoreBase - BaseAddress); Length = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK); Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "Variable driver failed to get flash memory attribute.\n")); } else { Status = gDS->SetMemorySpaceAttributes ( BaseAddress, Length, GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n")); } } Status = VariableWriteServiceInitialize (); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status)); } // // Some Secure Boot Policy Var (SecureBoot, etc) updates following other // Secure Boot Policy Variable change. Record their initial value. // RecordSecureBootPolicyVarData(); // // Install the Variable Write Architectural protocol. // Status = gBS->InstallProtocolInterface ( &mHandle, &gEfiVariableWriteArchProtocolGuid, EFI_NATIVE_INTERFACE, NULL ); ASSERT_EFI_ERROR (Status); // // Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again. // gBS->CloseEvent (Event); }