/** Uninstalls a list of protocol interface in the boot services environment. This function calls UnisatllProtocolInterface() in a loop. This is basically a lib function to save space. @param Handle The handle to uninstall the protocol @param ... EFI_GUID followed by protocol instance. A NULL terminates the list. The pairs are the arguments to UninstallProtocolInterface(). All the protocols are added to Handle. @return Status code **/ EFI_STATUS EFIAPI CoreUninstallMultipleProtocolInterfaces ( IN EFI_HANDLE Handle, ... ) { EFI_STATUS Status; VA_LIST Args; EFI_GUID *Protocol; VOID *Interface; UINTN Index; VA_START (Args, Handle); for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) { // // If protocol is NULL, then it's the end of the list // Protocol = VA_ARG (Args, EFI_GUID *); if (Protocol == NULL) { break; } Interface = VA_ARG (Args, VOID *); // // Uninstall it // Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface); } VA_END (Args); // // If there was an error, add all the interfaces that were // uninstalled without any errors // if (EFI_ERROR (Status)) { // // Reset the va_arg back to the first argument. // VA_START (Args, Handle); for (; Index > 1; Index--) { Protocol = VA_ARG(Args, EFI_GUID *); Interface = VA_ARG(Args, VOID *); CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); } VA_END (Args); } return Status; }
/** 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; }
/** Installs a list of protocol interface into the boot services environment. This function calls InstallProtocolInterface() in a loop. If any error occures all the protocols added by this function are removed. This is basically a lib function to save space. @param Handle The pointer to a handle to install the new protocol interfaces on, or a pointer to NULL if a new handle is to be allocated. @param ... EFI_GUID followed by protocol instance. A NULL terminates the list. The pairs are the arguments to InstallProtocolInterface(). All the protocols are added to Handle. @retval EFI_SUCCESS All the protocol interface was installed. @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in the handle database. @retval EFI_INVALID_PARAMETER Handle is NULL. @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle. **/ EFI_STATUS EFIAPI CoreInstallMultipleProtocolInterfaces ( IN OUT EFI_HANDLE *Handle, ... ) { VA_LIST Args; EFI_STATUS Status; EFI_GUID *Protocol; VOID *Interface; EFI_TPL OldTpl; UINTN Index; EFI_HANDLE OldHandle; EFI_HANDLE DeviceHandle; EFI_DEVICE_PATH_PROTOCOL *DevicePath; if (Handle == NULL) { return EFI_INVALID_PARAMETER; } // // Syncronize with notifcations. // OldTpl = CoreRaiseTpl (TPL_NOTIFY); OldHandle = *Handle; // // Check for duplicate device path and install the protocol interfaces // VA_START (Args, Handle); for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) { // // If protocol is NULL, then it's the end of the list // Protocol = VA_ARG (Args, EFI_GUID *); if (Protocol == NULL) { break; } Interface = VA_ARG (Args, VOID *); // // Make sure you are installing on top a device path that has already been added. // if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) { DeviceHandle = NULL; DevicePath = Interface; Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle); if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(DevicePath)) { Status = EFI_ALREADY_STARTED; continue; } } // // Install it // Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); } VA_END (Args); // // If there was an error, remove all the interfaces that were installed without any errors // if (EFI_ERROR (Status)) { // // Reset the va_arg back to the first argument. // VA_START (Args, Handle); for (; Index > 1; Index--) { Protocol = VA_ARG (Args, EFI_GUID *); Interface = VA_ARG (Args, VOID *); CoreUninstallProtocolInterface (*Handle, Protocol, Interface); } VA_END (Args); *Handle = OldHandle; } // // Done // CoreRestoreTpl (OldTpl); return Status; }