Example #1
0
/**
  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;
}
Example #2
0
/**
  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;
}