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

📄 load.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 2 页
字号:
    //

    CloseSimpleReadFile (FHand);
    
    //
    // There was an error.  If there's an Image structure, free it
    //

    if (EFI_ERROR(Status)) {
        if (Image) {
            UnloadImage (Image);
            *ImageHandle = NULL;
        }
    }

    return Status;
}
    
EFI_STATUS
BOOTSERVICE
StartImage (
    IN EFI_HANDLE           ImageHandle,
    OUT UINTN               *ExitDataSize,
    OUT CHAR16              **ExitData  OPTIONAL
    )
{
    START_IMAGE             Si;
    START_IMAGE             *LastSi;
    BOOLEAN                 Flag;
    UINT64                  HandleDatabaseKey;

    ZeroMem (&Si, sizeof(Si));
    Si.Image = LoadedImageInfo(ImageHandle);
    if (!Si.Image  ||  Si.Image->Started) {
        return EFI_INVALID_PARAMETER;
    }

    //
    // Save some information about the handle database
    //
    HandleDatabaseKey = CoreGetHandleDatabaseKey();

    //
    // Push the current start image context, and 
    // link the current image to the head.   This is the
    // only image that can call Exit()
    // 

    LastSi = CurrentStartImage;
    CurrentStartImage = &Si;
    Si.Image->StartImageContext = &Si;
    Si.Tpl = CurrentTPL();

    //
    // Set long jump for Exit() support
    //

    Flag = SetJump (&Si.Exit);
    if (!Flag) {

        //
        // Call platform code to set handoff state
        //
        
        if (PL->SI_HandoffState) {
            PL->SI_HandoffState();
        }
        
        //
        // Call the image's entry point
        //

        Si.Image->Started = TRUE;
        DEBUG ((D_LOAD, "StartImage: Calling %hs entry point\n", Si.Image->Name));
        Si.Status = Si.Image->EntryPoint (ImageHandle, Si.Image->Info.SystemTable);

        //
        // If the image returns, exit it through Exit()
        //

        BS->Exit(ImageHandle, Si.Status, 0, NULL);

        //
        // Call platform code to verify state on exit
        //
        
        if (PL->EI_ReturnState) {
            PL->EI_ReturnState();
        }
    }

    //
    // Image has completed.  Verify the tpl is the same
    //

    ASSERT (Si.Tpl == CurrentTPL());
    RestoreTPL (Si.Tpl);
    
    //
    // Pop the current start image context
    //
    
    Si.Image->StartImageContext = NULL;
    CurrentStartImage = LastSi;
    DEBUG ((D_LOAD, "StartImage: Image %hs returned %x\n", Si.Image->Name, Si.Status));

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

    //
    // Handle the image's returned ExitData
    //

    if (ExitData != NULL) {

        DEBUG ((D_LOAD, "StartImage: ExitDataSize %d, ExitData %x (%hs)\n", 
                            Si.ExitDataSize,
                            Si.ExitData,
                            Si.ExitData
                            ));

        //
        // Return the exit data to the caller
        //

        if (ExitDataSize != NULL) {

            *ExitDataSize = Si.ExitDataSize;
            *ExitData = Si.ExitData;

        } else {

            //
            // Caller doesn't want the exit data, free it
            //
            
            FreePool (ExitData);
        }
    }

    //
    // If the image returned an error, of if the image is an application
    // unload it
    //

    if (EFI_ERROR(Si.Status) || Si.Image->Type == IMAGE_SUBSYSTEM_EFI_APPLICATION) {
        UnloadImage (Si.Image);
    }

    //
    // Done
    //

    return Si.Status;
}


VOID
UnloadImage (
    IN LOADED_IMAGE     *Image
    )
{
    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;

    DEBUG((D_LOAD, "UnloadImage: unloading %s\n", Image->Name));

    //
    // If this image is on the runtime list, free it
    //

    if (Image->ImageLink.Flink) {
        AcquireLock (&ImageListLock);
        RemoveEntryList (&Image->ImageLink);
        ReleaseLock (&ImageListLock);
    }

    //
    // Free our references to the image handle
    //

    if (Image->Handle) {

        Status = LibLocateHandle (
                        AllHandles,   
                        NULL,
                        NULL,
                        &HandleCount, 
                        &HandleBuffer
                        );
        if (!EFI_ERROR (Status)) {
          for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
    			  Status = EFI_UNSUPPORTED;
            ArrayCount = 0;
            ProtocolGuidArray = NULL;
            Status = BS->ProtocolsPerHandle (
                           HandleBuffer[HandleIndex], 
                            &ProtocolGuidArray, 
                            &ArrayCount
                            );
            if (!EFI_ERROR (Status)) {
              for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
                Status = BS->OpenProtocolInformation (
                                HandleBuffer[HandleIndex], 
                                ProtocolGuidArray[ProtocolIndex],
                                &OpenInfo,
                                &OpenInfoCount
                                );
                if (!EFI_ERROR (Status)) {
                  for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
                    if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
                      Status = BS->CloseProtocol (
                                      HandleBuffer[HandleIndex],
                                      ProtocolGuidArray[ProtocolIndex],
                                      OpenInfo[OpenInfoIndex].AgentHandle,
                                      OpenInfo[OpenInfoIndex].ControllerHandle
                                      );
                    }
                  }
                  if (OpenInfo != NULL) {
                    BS->FreePool(OpenInfo);
                  }
                }
              }
              if (ProtocolGuidArray != NULL) {
                BS->FreePool(ProtocolGuidArray);
              }
            }
          }
          if (HandleBuffer != NULL) {
            BS->FreePool (HandleBuffer);
          }
        }

        //
        // Remove image handle from debug image info table
        // This step is optional and not required by architecture.  It is
        // used by debuggers to determine image information
        //
    
        DeleteDebugImageInfoEntry (Image->Handle);
        
        LibUninstallProtocolInterfaces (
            Image->Handle, 
            &LoadedImageProtocol,       &Image->Info,    
            &InternalImageStructure,    Image,
            NULL
            );
    }

    //
    // Free the Image from memory
    //

    if (Image->ImageBasePage) {
        FreePages (Image->ImageBasePage, Image->NumberOfPages);
    }

    //
    // Done with the Image structure
    //

    if (Image->Info.FilePath) {
        FreePool (Image->Info.FilePath);
    }

    if (Image->Name) {
        FreePool (Image->Name);
    }

    if (Image->FixupData) {
        FreePool (Image->FixupData);
    }

    FreePool (Image);
}


EFI_STATUS
BOOTSERVICE
Exit (
    IN EFI_HANDLE       ImageHandle,
    IN EFI_STATUS       Status,
    IN UINTN            ExitDataSize,
    IN CHAR16           *ExitData  OPTIONAL
    )
{
    LOADED_IMAGE        *Image;
    START_IMAGE         *Si;
    
    Image = LoadedImageInfo(ImageHandle);
    if (!Image) {
        return EFI_INVALID_PARAMETER;
    }

    //
    // If this Image has been started, then unload it
    //
    
    if (!Image->Started) {
        UnloadImage (Image);
        return EFI_SUCCESS;
    }

    //
    // Image has been started, verify this image can exit
    //

    if (!Image->StartImageContext || 
        Image->StartImageContext != CurrentStartImage) {

        DEBUG ((D_LOAD|D_ERROR, "Exit: Image is not exitable image\n"));
        return EFI_INVALID_PARAMETER;
    }

    //
    //  Set status
    //

    Si = (START_IMAGE *) Image->StartImageContext;
    Si->Status = Status;

    //
    // If there's ExitData info, move it
    //

    if (ExitData) {
        Si->ExitData = ReallocatePool (ExitData, ExitDataSize, ExitDataSize);
        Si->ExitDataSize = ExitDataSize;
    }

    //
    // return to StartImage
    //

    LongJump (&Si->Exit);
    ASSERT (FALSE);
    return EFI_ACCESS_DENIED;
}

#pragma RUNTIME_CODE(RtLoaderExitBootServices)
VOID
RUNTIMEFUNCTION
RtLoaderExitBootServices (
    VOID
    )
{
    LIST_ENTRY          *Link;
    LOADED_IMAGE        *Image;

    //
    // Walk all the boot service driver images
    //

    Link = BootImageList.Flink;
    while (Link != &BootImageList) {
        Image = CR(Link, LOADED_IMAGE, ImageLink, LOADED_IMAGE_SIGNATURE);
        Link = Link->Flink;

        //
        // Clear memory of old components
        //

        ZeroMem (Image->ImageBase, Image->NumberOfPages << EFI_PAGE_SHIFT);
        ZeroMem (Image, sizeof(LOADED_IMAGE));
    }

    //
    // Walk all the runtime images
    //

    for(Link=RuntimeImageList.Flink; Link != &RuntimeImageList; Link=Link->Flink) {
        Image = CR(Link, LOADED_IMAGE, ImageLink, LOADED_IMAGE_SIGNATURE);

        // 
        // Clear non-runtime pointers
        //

        Image->Handle = NULL;
        Image->Name = NULL;
        Image->Info.ParentHandle = NULL;
        Image->Info.SystemTable = NULL;
        Image->Info.DeviceHandle = NULL;
        Image->Info.FilePath = NULL;
        Image->Info.LoadOptions = NULL;
    }
}

#pragma RUNTIME_CODE(RtLoaderVirtualAddressFixup)    
VOID
RUNTIMEFUNCTION
RtLoaderVirtualAddressFixup (
    VOID
    )
// Switching into virtual mode. reapply fix ups to all runtime images
{
    LIST_ENTRY              *Link;
    LOADED_IMAGE            *Image;

    for(Link=RuntimeImageList.Flink; Link != &RuntimeImageList; Link=Link->Flink) {
        Image = CR(Link, LOADED_IMAGE, ImageLink, LOADED_IMAGE_SIGNATURE);
        ConvertPeImage (Image);
        RT->ConvertPointer (0, &Image->ImageBase);
        RT->ConvertPointer (0, &Image->ImageEof);
        RT->ConvertPointer (0, &Image->Info.ImageBase);
    }

    RtConvertList(EFI_INTERNAL_PTR, &RuntimeImageList);
}



EFI_STATUS
BSUnloadImage (
    IN EFI_HANDLE                   ImageHandle
    )
// Unload a driver
{
  EFI_STATUS              Status;
  LOADED_IMAGE            *Image;
  EFI_EBC_PROTOCOL        *EbcProtocol;

  //
  // Make sure ImageHandle is a valid handle
  //
  if (ImageHandle == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Get the Loaded Image Protocol that is installed on ImageHandle
  //
  Image = LoadedImageInfo (ImageHandle);

  //
  // If ImageHandle does not support a Loaded Image Protocol, then return an error
  //
  if (Image == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // If this Image hasn't been started, then it can be unloaded immediately
  //
  if (!Image->Started) {
    UnloadImage (Image);
    return EFI_SUCCESS;
  }

  //
  // The image has been started, request it to unload.
  // If the Loaded Image Protocol does not have an Unload() function, then the 
  // image can not be unloaded, so return an error.
  //
  if (Image->Info.Unload == NULL) {
    return EFI_UNSUPPORTED;
  }

  //
  // Call the image specific Unload() function.  If it fails, then return an error
  //
  Status = Image->Info.Unload (ImageHandle);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Determine if this is an EBC image. If so, then make a call into the
  // EBC protocol to perform any cleanup for this image.
  //
  if (Image->Machine == EFI_IMAGE_MACHINE_EBC) {
    //
    // Try to get the EBC protocol
    //
    Status = BS->LocateProtocol (&gEfiEbcProtocolGuid, NULL, &EbcProtocol);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    //
    // Free the thunks that were created when the EBC image was loaded and initialized
    //
    Status = EbcProtocol->UnloadImage (EbcProtocol, ImageHandle);
    if (EFI_ERROR(Status)) {
      return Status;
    }
  }

  //
  // Unload the image from system memory
  //
  UnloadImage (Image);

  return EFI_SUCCESS;
}

⌨️ 快捷键说明

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