/** This notification function is invoked when an instance of the EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle. This is the function where the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done. @param Event The event that occured @param Context For EFI compatiblity. Not used. **/ VOID EFIAPI NotifyFwVolBlock ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_HANDLE Handle; EFI_STATUS Status; UINTN BufferSize; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; FV_DEVICE *FvDevice; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; // // Examine all new handles // for (;;) { // // Get the next handle // BufferSize = sizeof (Handle); Status = CoreLocateHandle ( ByRegisterNotify, NULL, gEfiFwVolBlockNotifyReg, &BufferSize, &Handle ); // // If not found, we're done // if (EFI_NOT_FOUND == Status) { break; } if (EFI_ERROR (Status)) { continue; } // // Get the FirmwareVolumeBlock protocol on that handle // Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb); ASSERT_EFI_ERROR (Status); ASSERT (Fvb != NULL); // // Make sure the Fv Header is O.K. // Status = GetFwVolHeader (Fvb, &FwVolHeader); if (EFI_ERROR (Status)) { return; } ASSERT (FwVolHeader != NULL); if (!VerifyFvHeaderChecksum (FwVolHeader)) { CoreFreePool (FwVolHeader); continue; } // // Check to see that the file system is indeed formatted in a way we can // understand it... // if ((!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) && (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) { continue; } // // Check if there is an FV protocol already installed in that handle // Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv); if (!EFI_ERROR (Status)) { // // Update Fv to use a new Fvb // FvDevice = BASE_CR (Fv, FV_DEVICE, Fv); if (FvDevice->Signature == FV2_DEVICE_SIGNATURE) { // // Only write into our device structure if it's our device structure // FvDevice->Fvb = Fvb; } } else { // // No FwVol protocol on the handle so create a new one // FvDevice = AllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice); if (FvDevice == NULL) { return; } FvDevice->Fvb = Fvb; FvDevice->Handle = Handle; FvDevice->FwVolHeader = FwVolHeader; FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid); FvDevice->Fv.ParentHandle = Fvb->ParentHandle; if (Fvb->ParentHandle != NULL) { // // Inherit the authentication status from FVB. // FvDevice->AuthenticationStatus = GetFvbAuthenticationStatus (Fvb); } if (!EFI_ERROR (FvCheck (FvDevice))) { // // Install an New FV protocol on the existing handle // Status = CoreInstallProtocolInterface ( &Handle, &gEfiFirmwareVolume2ProtocolGuid, EFI_NATIVE_INTERFACE, &FvDevice->Fv ); ASSERT_EFI_ERROR (Status); } else { // // Free FvDevice Buffer for the corrupt FV image. // CoreFreePool (FvDevice); } } } return; }
/** Entry point function does install/reinstall FV2 protocol with full functionality. @param ImageHandle A handle for the image that is initializing this driver @param SystemTable A pointer to the EFI system table @retval EFI_SUCCESS At least one Fv protocol install/reinstall successfully. @retval EFI_NOT_FOUND No FV protocol install/reinstall successfully. **/ EFI_STATUS EFIAPI FwVolDriverInit ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_HANDLE *HandleBuffer; UINTN HandleCount; UINTN Index; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; FV_DEVICE *FvDevice; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; BOOLEAN Reinstall; BOOLEAN InstallFlag; DEBUG ((EFI_D_INFO, "=========FwVol writable driver installed\n")); InstallFlag = FALSE; // // Locate all handles of Fvb protocol // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiFirmwareVolumeBlockProtocolGuid, NULL, &HandleCount, &HandleBuffer ); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } for (Index = 0; Index < HandleCount; Index += 1) { Status = gBS->HandleProtocol ( HandleBuffer[Index], &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **) &Fvb ); if (EFI_ERROR (Status)) { continue; } FwVolHeader = NULL; Status = GetFwVolHeader (Fvb, &FwVolHeader); if (EFI_ERROR (Status)) { continue; } ASSERT (FwVolHeader != NULL); FreePool (FwVolHeader); Reinstall = FALSE; // // Check if there is an FV protocol already installed in that handle // Status = gBS->HandleProtocol ( HandleBuffer[Index], &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &Fv ); if (!EFI_ERROR (Status)) { Reinstall = TRUE; } // // FwVol protocol on the handle so create a new one // FvDevice = AllocateZeroPool (sizeof (FV_DEVICE)); if (FvDevice == NULL) { goto Done; } FvDevice->Signature = FV_DEVICE_SIGNATURE; FvDevice->Fvb = Fvb; // // Firmware Volume Protocol interface // FvDevice->Fv.GetVolumeAttributes = FvGetVolumeAttributes; FvDevice->Fv.SetVolumeAttributes = FvSetVolumeAttributes; FvDevice->Fv.ReadFile = FvReadFile; FvDevice->Fv.ReadSection = FvReadFileSection; FvDevice->Fv.WriteFile = FvWriteFile; FvDevice->Fv.GetNextFile = FvGetNextFile; FvDevice->Fv.KeySize = KEYSIZE; FvDevice->Fv.GetInfo = FvGetVolumeInfo; FvDevice->Fv.SetInfo = FvSetVolumeInfo; FvDevice->Fv.ParentHandle = Fvb->ParentHandle; Status = FvCheck (FvDevice); if (EFI_ERROR (Status)) { // // The file system is not consistence // FreePool (FvDevice); continue; } FwVolInheritAuthenticationStatus (FvDevice); if (Reinstall) { // // Reinstall an New FV protocol // // FvDevice = FV_DEVICE_FROM_THIS (Fv); // FvDevice->Fvb = Fvb; // FreeFvDeviceResource (FvDevice); // Status = gBS->ReinstallProtocolInterface ( HandleBuffer[Index], &gEfiFirmwareVolume2ProtocolGuid, Fv, &FvDevice->Fv ); if (!EFI_ERROR (Status)) { InstallFlag = TRUE; } else { FreePool (FvDevice); } DEBUG ((EFI_D_INFO, "Reinstall FV protocol as writable - %r\n", Status)); ASSERT_EFI_ERROR (Status); } else { // // Install an New FV protocol // Status = gBS->InstallProtocolInterface ( &FvDevice->Handle, &gEfiFirmwareVolume2ProtocolGuid, EFI_NATIVE_INTERFACE, &FvDevice->Fv ); if (!EFI_ERROR (Status)) { InstallFlag = TRUE; } else { FreePool (FvDevice); } DEBUG ((EFI_D_INFO, "Install FV protocol as writable - %r\n", Status)); ASSERT_EFI_ERROR (Status); } } Done: // // As long as one Fv protocol install/reinstall successfully, // success should return to ensure this image will be not unloaded. // Otherwise, new Fv protocols are corrupted by other loaded driver. // if (InstallFlag) { return EFI_SUCCESS; } // // No FV protocol install/reinstall successfully. // EFI_NOT_FOUND should return to ensure this image will be unloaded. // return EFI_NOT_FOUND; }