mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
250 lines
5.7 KiB
C
250 lines
5.7 KiB
C
/** @file
|
|
Copyright (C) 2019, vit9696. All rights reserved.
|
|
|
|
All rights reserved.
|
|
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
**/
|
|
|
|
#include "BootManagementInternal.h"
|
|
|
|
#include <Protocol/DevicePath.h>
|
|
#include <Protocol/SimpleFileSystem.h>
|
|
|
|
#include <Guid/AppleVariable.h>
|
|
#include <Guid/FileInfo.h>
|
|
#include <Guid/GlobalVariable.h>
|
|
#include <Guid/OcVariable.h>
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/OcDebugLogLib.h>
|
|
#include <Library/DevicePathLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/OcBootManagementLib.h>
|
|
#include <Library/OcDevicePathLib.h>
|
|
#include <Library/OcFileLib.h>
|
|
#include <Library/OcMachoLib.h>
|
|
#include <Library/OcStringLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Library/PrintLib.h>
|
|
|
|
STATIC EFI_IMAGE_LOAD mOriginalEfiLoadImage;
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
InternalEfiLoadImageFile (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
|
OUT UINTN *FileSize,
|
|
OUT VOID **FileBuffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_FILE_PROTOCOL *File;
|
|
VOID *Buffer;
|
|
UINT32 Size;
|
|
|
|
Status = OcOpenFileByDevicePath (
|
|
&DevicePath,
|
|
&File,
|
|
EFI_FILE_MODE_READ,
|
|
0
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Status = GetFileSize (
|
|
File,
|
|
&Size
|
|
);
|
|
if (EFI_ERROR (Status) || Size == 0) {
|
|
File->Close (File);
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Buffer = AllocatePool (Size);
|
|
if (Buffer == NULL) {
|
|
File->Close (File);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Status = GetFileData (
|
|
File,
|
|
0,
|
|
Size,
|
|
Buffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool (Buffer);
|
|
File->Close (File);
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
*FileBuffer = Buffer;
|
|
*FileSize = Size;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
InternalEfiLoadImageProtocol (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
|
IN BOOLEAN UseLoadImage2,
|
|
OUT UINTN *FileSize,
|
|
OUT VOID **FileBuffer
|
|
)
|
|
{
|
|
//
|
|
// TODO: Implement image load protocol if necessary.
|
|
//
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
InternalUpdateLoadedImage (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE DeviceHandle;
|
|
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
|
|
EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
|
|
|
|
Status = gBS->HandleProtocol (
|
|
ImageHandle,
|
|
&gEfiLoadedImageProtocolGuid,
|
|
(VOID **) &LoadedImage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
RemainingDevicePath = DevicePath;
|
|
Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &RemainingDevicePath, &DeviceHandle);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// TODO: Handle load protocol if necessary.
|
|
//
|
|
return Status;
|
|
}
|
|
|
|
if (LoadedImage->DeviceHandle != DeviceHandle) {
|
|
LoadedImage->DeviceHandle = DeviceHandle;
|
|
LoadedImage->FilePath = DuplicateDevicePath (RemainingDevicePath);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InternalEfiLoadImage (
|
|
IN BOOLEAN BootPolicy,
|
|
IN EFI_HANDLE ParentImageHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
|
IN VOID *SourceBuffer OPTIONAL,
|
|
IN UINTN SourceSize,
|
|
OUT EFI_HANDLE *ImageHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VOID *AllocatedBuffer;
|
|
UINT32 RealSize;
|
|
|
|
if (ParentImageHandle == NULL || ImageHandle == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (SourceBuffer == NULL && DevicePath == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
if (SourceBuffer != NULL && SourceSize == 0) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
AllocatedBuffer = NULL;
|
|
if (SourceBuffer == NULL) {
|
|
Status = InternalEfiLoadImageFile (
|
|
DevicePath,
|
|
&SourceSize,
|
|
&SourceBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
Status = InternalEfiLoadImageProtocol (
|
|
DevicePath,
|
|
BootPolicy == FALSE,
|
|
&SourceSize,
|
|
&SourceBuffer
|
|
);
|
|
}
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
AllocatedBuffer = SourceBuffer;
|
|
}
|
|
}
|
|
|
|
if (SourceBuffer != NULL) {
|
|
RealSize = (UINT32) SourceSize;
|
|
#ifdef MDE_CPU_IA32
|
|
Status = FatFilterArchitecture32 ((UINT8 **) &SourceBuffer, &RealSize);
|
|
#else
|
|
Status = FatFilterArchitecture64 ((UINT8 **) &SourceBuffer, &RealSize);
|
|
#endif
|
|
if (!EFI_ERROR (Status)) {
|
|
SourceSize = RealSize;
|
|
} else if (AllocatedBuffer != NULL) {
|
|
SourceBuffer = NULL;
|
|
SourceSize = 0;
|
|
}
|
|
}
|
|
|
|
Status = mOriginalEfiLoadImage (
|
|
BootPolicy,
|
|
ParentImageHandle,
|
|
DevicePath,
|
|
SourceBuffer,
|
|
SourceSize,
|
|
ImageHandle
|
|
);
|
|
|
|
if (AllocatedBuffer != NULL) {
|
|
FreePool (AllocatedBuffer);
|
|
}
|
|
|
|
//
|
|
// Some firmwares may not update loaded image protocol fields correctly
|
|
// when loading via source buffer. Do it here.
|
|
//
|
|
if (!EFI_ERROR (Status) && SourceBuffer != NULL && DevicePath != NULL) {
|
|
InternalUpdateLoadedImage (*ImageHandle, DevicePath);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
InternalInitImageLoader (
|
|
VOID
|
|
)
|
|
{
|
|
mOriginalEfiLoadImage = gBS->LoadImage;
|
|
gBS->LoadImage = InternalEfiLoadImage;
|
|
|
|
gBS->Hdr.CRC32 = 0;
|
|
gBS->CalculateCrc32 (gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
|
|
return EFI_SUCCESS;
|
|
}
|