⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image.c

📁 EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是EFI BIOS源代码中的与平台无关部分的代码
💻 C
📖 第 1 页 / 共 3 页
字号:

  //
  // Set long jump for Exit() support
  //
  Image->JumpContext = CoreAllocateBootServicesPool (gEfiPeiTransferControl->JumpContextSize);
  if (Image->JumpContext == NULL) {
    PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
    return EFI_OUT_OF_RESOURCES;
  }

  Status = gEfiPeiTransferControl->SetJump (gEfiPeiTransferControl, Image->JumpContext);
  //
  // The SetJump returns EFI_SUCCESS when LongJump Buffer has been armed
  // SetJump returns EFI_WARN_RETURN_FROM_LONG_JUMP as a result of the LongJump
  // All other return values for SetJump are undefined.
  //
  if (Status == EFI_SUCCESS) {

    //
    // Call the image's entry point
    //
    Image->Started = TRUE;
    Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);

    //
    // Add some debug information if the image returned with error. 
    // This make the user aware and check if the driver image have already released 
    // all the resource in this situation. 
    //
    DEBUG_CODE (
      if (EFI_ERROR (Image->Status)) {
        DEBUG ((EFI_D_ERROR, "Error: Image at %08X start failed: %x\n", Image->Info.ImageBase, Image->Status));
      }
    )
    
    //
    // If the image returns, exit it through Exit()
    //
    CoreExit (ImageHandle, Image->Status, 0, NULL);
  }

  //
  // Image has completed.  Verify the tpl is the same
  //
  ASSERT (Image->Tpl == gEfiCurrentTpl);
  CoreRestoreTpl (Image->Tpl);

  CoreFreePool (Image->JumpContext);

  //
  // Pop the current start image context
  //
  mCurrentImage = LastImage;

  //
  // Go connect any handles that were created or modified while the image executed.
  //
  CoreConnectHandlesByKey (HandleDatabaseKey);

  //
  // Handle the image's returned ExitData
  //
  DEBUG_CODE (
    if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {

      DEBUG (
        (EFI_D_LOAD,
        "StartImage: ExitDataSize %d, ExitData %x",
                            Image->ExitDataSize,
        Image->ExitData)
        );
      if (Image->ExitData != NULL) {
        DEBUG ((EFI_D_LOAD, " (%hs)", Image->ExitData));
      } 
      DEBUG ((EFI_D_LOAD, "\n"));
    }
  )

  //
  //  Return the exit data to the caller
  //
  if (ExitData != NULL && ExitDataSize != NULL) {
    *ExitDataSize = Image->ExitDataSize;
    *ExitData     = Image->ExitData;
  } else {
    //
    // Caller doesn't want the exit data, free it
    //
    CoreFreePool (Image->ExitData);
    Image->ExitData = NULL;
  }

  //
  // Save the Status because Image will get destroyed if it is unloaded.
  //
  Status = Image->Status;

  //
  // If the image returned an error, or if the image is an application
  // unload it
  //
  if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
    CoreUnloadAndCloseImage (Image, TRUE);
  }

  //
  // Done
  //
  PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
  return Status;
}


VOID
CoreUnloadAndCloseImage (
  IN LOADED_IMAGE_PRIVATE_DATA  *Image,
  IN BOOLEAN                    FreePage
  )
/*++

Routine Description:

  Unloads EFI image from memory.

Arguments:

  Image      - EFI image 
  FreePage   - Free allocated pages

Returns:

  None

--*/
{
  EFI_STATUS                          Status;
  UINTN                               HandleCount;
  EFI_HANDLE                          *HandleBuffer;
  UINTN                               HandleIndex;
  EFI_GUID                            **ProtocolGuidArray;
  UINTN                               ArrayCount;
  UINTN                               ProtocolIndex;
  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
  UINTN                               OpenInfoCount;
  UINTN                               OpenInfoIndex;
  
  if (Image->Ebc != NULL) {
    //
    // If EBC protocol exists we must perform cleanups for this image.
    //
    Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);
  }

  //
  // Unload image, free Image->ImageContext->ModHandle
  //
  gEfiPeiPeCoffLoader->UnloadImage (&Image->ImageContext);

  //
  // Free our references to the image handle
  //
  if (Image->Handle != NULL_HANDLE) {

    Status = CoreLocateHandleBuffer (
               AllHandles,   
               NULL,
               NULL,
               &HandleCount, 
               &HandleBuffer
               );
    if (!EFI_ERROR (Status)) {
      for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
        Status = CoreProtocolsPerHandle (
                   HandleBuffer[HandleIndex], 
                   &ProtocolGuidArray, 
                   &ArrayCount
                   );
        if (!EFI_ERROR (Status)) {
          for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
            Status = CoreOpenProtocolInformation (
                       HandleBuffer[HandleIndex], 
                       ProtocolGuidArray[ProtocolIndex],
                       &OpenInfo,
                       &OpenInfoCount
                       );
            if (!EFI_ERROR (Status)) {
              for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
                if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
                  Status = CoreCloseProtocol (
                             HandleBuffer[HandleIndex],
                             ProtocolGuidArray[ProtocolIndex],
                             Image->Handle,
                             OpenInfo[OpenInfoIndex].ControllerHandle
                             );
                }
              }
              if (OpenInfo != NULL) {
                CoreFreePool(OpenInfo);
              }
            }
          }
          if (ProtocolGuidArray != NULL) {
            CoreFreePool(ProtocolGuidArray);
          }
        }
      }
      if (HandleBuffer != NULL) {
        CoreFreePool (HandleBuffer);
      }
    }

    CoreRemoveDebugImageInfoEntry (Image->Handle);
    
    Status = CoreUninstallProtocolInterface (
               Image->Handle,
               &gEfiLoadedImageProtocolGuid,
               &Image->Info
               );

    //
    // Uninstall Debug Mask Protocol
    //
    DEBUG_CODE (
      Status = UninstallDebugMaskProtocol(Image->Handle);
      ASSERT_EFI_ERROR (Status);
    )

  }

  if (Image->RuntimeData != NULL) {
    if (Image->RuntimeData->Link.ForwardLink != NULL) {
      //
      // Remove the Image from the Runtime Image list as we are about to Free it!
      //
      RemoveEntryList (&Image->RuntimeData->Link);
    }
    CoreFreePool (Image->RuntimeData);
  }
  
  //
  // Free the Image from memory
  //
  if ((Image->ImageBasePage != 0) && FreePage) {
    CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
  }

  //
  // Done with the Image structure
  //
  if (Image->Info.FilePath != NULL) {
    CoreFreePool (Image->Info.FilePath);
  }

  if (Image->FixupData != NULL) {
    CoreFreePool (Image->FixupData);
  }

  CoreFreePool (Image);
}


EFI_BOOTSERVICE
EFI_STATUS
EFIAPI
CoreExit (
  IN EFI_HANDLE  ImageHandle,
  IN EFI_STATUS  Status,
  IN UINTN       ExitDataSize,
  IN CHAR16      *ExitData  OPTIONAL
  )
/*++

Routine Description:

  Terminates the currently loaded EFI image and returns control to boot services.

Arguments:

  ImageHandle       - Handle that identifies the image. This parameter is passed to the image 
                      on entry.
  Status            - The image’s exit code.
  ExitDataSize      - The size, in bytes, of ExitData. Ignored if ExitStatus is
                      EFI_SUCCESS.
  ExitData          - Pointer to a data buffer that includes a Null-terminated Unicode string,
                      optionally followed by additional binary data. The string is a 
                      description that the caller may use to further indicate the reason for
                      the image’s exit.

Returns:

  EFI_INVALID_PARAMETER     - Image handle is NULL or it is not current image.
  
  EFI_SUCCESS               - Successfully terminates the currently loaded EFI image.
  
  EFI_ACCESS_DENIED         - Should never reach there.

  EFI_OUT_OF_RESOURCES      - Could not allocate pool

--*/
{
  LOADED_IMAGE_PRIVATE_DATA  *Image;

  Image = CoreLoadedImageInfo (ImageHandle);
  if (Image == NULL_HANDLE) {
    return EFI_INVALID_PARAMETER;
  }

  if (!Image->Started) {
    //
    // The image has not been started so just free its resources
    //
    CoreUnloadAndCloseImage (Image, TRUE);
    return EFI_SUCCESS;
  }

  //
  // Image has been started, verify this image can exit
  //
  if (Image != mCurrentImage) {
    DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n"));
    return EFI_INVALID_PARAMETER;
  }

  //
  // Set status
  //
  Image->Status = Status;

  //
  // If there's ExitData info, move it
  //
  if (ExitData != NULL) {
    Image->ExitDataSize = ExitDataSize;
    Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize);
    if (Image->ExitData == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    EfiCommonLibCopyMem (Image->ExitData, ExitData, Image->ExitDataSize);
  }

  //
  // return to StartImage
  //
  Status = gEfiPeiTransferControl->LongJump (gEfiPeiTransferControl, Image->JumpContext);

  //
  // If we return from LongJump, then it is an error
  //
  ASSERT (FALSE);
  return EFI_ACCESS_DENIED;
}


EFI_BOOTSERVICE
EFI_STATUS
EFIAPI
CoreUnloadImage (
  IN EFI_HANDLE  ImageHandle
  )
/*++

Routine Description:

  Unloads an image.

Arguments:

  ImageHandle           - Handle that identifies the image to be unloaded.

Returns:

 EFI_SUCCESS            - The image has been unloaded.
 EFI_UNSUPPORTED        - The image has been sarted, and does not support unload.
 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.

--*/
{
  EFI_STATUS                 Status;
  LOADED_IMAGE_PRIVATE_DATA  *Image;

  Image = CoreLoadedImageInfo (ImageHandle);
  if (Image == NULL ) {
    //
    // The image handle is not valid
    //
    return EFI_INVALID_PARAMETER;
  }

  if (Image->Started) {
    //
    // The image has been started, request it to unload.
    //
    Status = EFI_UNSUPPORTED;
    if (Image->Info.Unload != NULL) {
      Status = Image->Info.Unload (ImageHandle);
    }

  } else {
    //
    // This Image hasn't been started, thus it can be unloaded
    //
    Status = EFI_SUCCESS;
  }
 

  if (!EFI_ERROR (Status)) {
    //
    // if the Image was not started or Unloaded O.K. then clean up
    //
    CoreUnloadAndCloseImage (Image, TRUE);
  }

  return Status;
}


EFI_STATUS
EFIAPI
CoreUnloadImageEx (
  IN EFI_PE32_IMAGE_PROTOCOL  *This,
  IN EFI_HANDLE                         ImageHandle
  )
/*++

Routine Description:

  Unload the specified image.

Arguments:

  This              - Indicates the calling context.

  ImageHandle       - The specified image handle.

Returns:

  EFI_INVALID_PARAMETER       - Image handle is NULL.
  
  EFI_UNSUPPORTED             - Attempt to unload an unsupported image.
  
  EFI_SUCCESS                 - Image successfully unloaded.

--*/
{
  return CoreUnloadImage (ImageHandle);
}



//
// This callback function is used by the EBC interpreter driver to flush the 
// processor instruction cache after creating thunks. We're simply hiding
// the "this" pointer that must be passed into the real flush function.
//
STATIC
EFI_STATUS
EFIAPI
CoreFlushICache (
  IN EFI_PHYSICAL_ADDRESS     Start,
  IN UINT64                   Length
  )
/*++

Routine Description:

  flush the processor instruction cache.

Arguments:

  Start             - Start adddress in memory to flush.

  Length            - Length of memory to flush.

Returns:

--*/
{
  return gEfiPeiFlushInstructionCache->Flush (
                                         gEfiPeiFlushInstructionCache,
                                         Start, 
                                         Length
                                         );
}

   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -