ImageTool: Utilize UefiImageLib

This commit is contained in:
Marvin Häuser 2023-04-23 23:45:16 +02:00 committed by Mikhail Krichanov
parent dcdb8d3425
commit 5ed47e7c71
8 changed files with 306 additions and 137 deletions

View File

@ -7,9 +7,10 @@
PROJECT = ImageTool PROJECT = ImageTool
PRODUCT = $(PROJECT)$(INFIX)$(SUFFIX) PRODUCT = $(PROJECT)$(INFIX)$(SUFFIX)
OBJS = $(PROJECT).o OBJS = $(PROJECT).o
OBJS += Image.o PeEmit32.o PeEmit64.o PeEmitCommon.o PeScan.o ElfScan32.o ElfScan64.o ElfScanCommon.o BinEmit.o ImageToolEmit.o OBJS += Image.o UefiImageScan.o PeEmit32.o PeEmit64.o PeEmitCommon.o PeScan.o ElfScan32.o ElfScan64.o ElfScanCommon.o BinEmit.o ImageToolEmit.o
OBJS += UefiImageExtraActionLib.o OBJS += UefiImageExtraActionLib.o
OBJS += PeCoffInit.o PeCoffInfo.o PeCoffLoad.o PeCoffRelocate.o PeCoffHii.o PeCoffDebug.o OBJS += PeCoffInit.o PeCoffInfo.o PeCoffLoad.o PeCoffRelocate.o PeCoffHii.o PeCoffDebug.o PeCoffHash.o
OBJS += UefiImageLibPeCoff.o PeCoffSupport.o CommonSupport.o
WERROR = 1 WERROR = 1
DEBUG = 1 DEBUG = 1
@ -18,6 +19,7 @@ OC_USER = ../../OpenCorePkg
UDK_PATH = ../.. UDK_PATH = ../..
VPATH += ../../MdePkg/Library/BasePeCoffLib2:$\ VPATH += ../../MdePkg/Library/BasePeCoffLib2:$\
../../MdePkg/Library/BaseUefiImageExtraActionLibNull ../../MdePkg/Library/BaseUefiImageExtraActionLibNull:$\
../../MdePkg/Library/BaseUefiImageLib
include $(OC_USER)/User/Makefile include $(OC_USER)/User/Makefile

View File

@ -136,8 +136,9 @@ ToolImageStripRelocs (
); );
RETURN_STATUS RETURN_STATUS
ToolContextConstructPe ( ToolContextConstructUefiImage (
OUT image_tool_image_info_t *Image, OUT image_tool_image_info_t *Image,
OUT INT8 *Format,
IN const void *File, IN const void *File,
IN size_t FileSize IN size_t FileSize
); );

View File

@ -19,7 +19,7 @@ ToolContextConstruct (
OUT image_tool_image_info_t *ImageInfo, OUT image_tool_image_info_t *ImageInfo,
OUT int8_t *Format, OUT int8_t *Format,
IN const void *File, IN const void *File,
IN size_t FileSize, IN uint32_t FileSize,
IN const char *SymbolsPath OPTIONAL IN const char *SymbolsPath OPTIONAL
) )
{ {
@ -27,14 +27,13 @@ ToolContextConstruct (
*Format = -1; *Format = -1;
Status = ToolContextConstructPe ( Status = ToolContextConstructUefiImage (
ImageInfo, ImageInfo,
Format,
File, File,
FileSize FileSize
); );
if (!RETURN_ERROR (Status)) { if (Status == RETURN_UNSUPPORTED) {
*Format = UefiImageFormatPe;
} else if (Status == RETURN_UNSUPPORTED) {
Status = ScanElf (ImageInfo, File, FileSize, SymbolsPath); Status = ScanElf (ImageInfo, File, FileSize, SymbolsPath);
} }
@ -89,7 +88,7 @@ void *
ToolImageEmit ( ToolImageEmit (
OUT uint32_t *OutputFileSize, OUT uint32_t *OutputFileSize,
IN const void *Buffer, IN const void *Buffer,
IN uint64_t BufferSize, IN uint32_t BufferSize,
IN int8_t Format, IN int8_t Format,
IN int32_t Type, IN int32_t Type,
IN void *HiiFile, IN void *HiiFile,

View File

@ -14,7 +14,7 @@ void *
ToolImageEmit ( ToolImageEmit (
OUT uint32_t *OutputFileSize, OUT uint32_t *OutputFileSize,
IN const void *Buffer, IN const void *Buffer,
IN uint64_t BufferSize, IN uint32_t BufferSize,
IN int8_t Format, IN int8_t Format,
IN int32_t Type, IN int32_t Type,
IN void *HiiFile, IN void *HiiFile,

View File

@ -19,19 +19,21 @@ OV = $(UDK_PATH)\MdePkg\Library\BaseOverflowLib
PE = $(UDK_PATH)\MdePkg\Library\BasePeCoffLib2 PE = $(UDK_PATH)\MdePkg\Library\BasePeCoffLib2
UA = $(UDK_PATH)\MdePkg\Library\BaseUefiImageExtraActionLibNull UA = $(UDK_PATH)\MdePkg\Library\BaseUefiImageExtraActionLibNull
OBJECTS = ImageTool.obj Image.obj PeEmit32.obj PeEmit64.obj PeEmitCommon.obj PeScan.obj ElfScan32.obj ElfScan64.obj ElfScanCommon.obj BinEmit.obj ImageToolEmit.obj OBJECTS = ImageTool.obj Image.obj PeEmit32.obj PeEmit64.obj PeEmitCommon.obj UefiImageScan.obj PeScan.obj ElfScan32.obj ElfScan64.obj ElfScanCommon.obj BinEmit.obj ImageToolEmit.obj
OBJECTS = $(OBJECTS) {$(OV)}BaseAlignment.obj BaseBitOverflow.obj {$(UA)}UefiImageExtraActionLib.obj OBJECTS = $(OBJECTS) {$(OV)}BaseAlignment.obj BaseBitOverflow.obj {$(UA)}UefiImageExtraActionLib.obj
OBJECTS = $(OBJECTS) {$(PE)}PeCoffInit.obj PeCoffInfo.obj PeCoffRelocate.obj PeCoffLoad.obj PeCoffHii.obj PeCoffDebug.obj OBJECTS = $(OBJECTS) {$(PE)}PeCoffInit.obj PeCoffInfo.obj PeCoffRelocate.obj PeCoffLoad.obj PeCoffHii.obj PeCoffDebug.obj PeCoffHash.obj
BASE = $(UDK_PATH)\MdePkg\Library\BaseLib BASE = $(UDK_PATH)\MdePkg\Library\BaseLib
OUT = $(UDK_PATH)\MdePkg\Library\UefiDebugLibConOut OUT = $(UDK_PATH)\MdePkg\Library\UefiDebugLibConOut
PRIN = $(UDK_PATH)\MdePkg\Library\BasePrintLib PRIN = $(UDK_PATH)\MdePkg\Library\BasePrintLib
ERRO = $(UDK_PATH)\MdePkg\Library\BaseDebugPrintErrorLevelLib ERRO = $(UDK_PATH)\MdePkg\Library\BaseDebugPrintErrorLevelLib
UIMG = $(UDK_PATH)\MdePkg\Library\BaseUefiImageLib
BMPN = $(UDK_PATH)\MdeModulePkg\Library\BaseMemoryProfileLibNull BMPN = $(UDK_PATH)\MdeModulePkg\Library\BaseMemoryProfileLibNull
CMEM = $(UDK_PATH)\MdeModulePkg\Library\CommonMemoryAllocationLib CMEM = $(UDK_PATH)\MdeModulePkg\Library\CommonMemoryAllocationLib
USER = $(OC_USER)\User\Library USER = $(OC_USER)\User\Library
OBJECTS = $(OBJECTS) {$(BASE)}SafeString.obj String.obj SwapBytes16.obj SwapBytes32.obj CpuDeadLoop.obj CheckSum.obj QuickSort.obj OBJECTS = $(OBJECTS) {$(BASE)}SafeString.obj String.obj SwapBytes16.obj SwapBytes32.obj CpuDeadLoop.obj CheckSum.obj QuickSort.obj LinkedList.obj
OBJECTS = $(OBJECTS) {$(OUT)}DebugLib.obj {$(PRIN)}PrintLib.obj PrintLibInternal.obj {$(ERRO)}BaseDebugPrintErrorLevelLib.obj OBJECTS = $(OBJECTS) {$(OUT)}DebugLib.obj {$(PRIN)}PrintLib.obj PrintLibInternal.obj {$(ERRO)}BaseDebugPrintErrorLevelLib.obj
OBJECTS = $(OBJECTS) {$(UIMG)}UefiImageLibPeCoff.obj PeCoffSupport.obj CommonSupport.obj
OBJECTS = $(OBJECTS) {$(USER)}UserFile.obj UserBaseMemoryLib.obj UserMath.obj UserPcd.obj UserMisc.obj UserGlobalVar.obj UserBootServices.obj OBJECTS = $(OBJECTS) {$(USER)}UserFile.obj UserBaseMemoryLib.obj UserMath.obj UserPcd.obj UserMisc.obj UserGlobalVar.obj UserBootServices.obj
OBJECTS = $(OBJECTS) {$(BMPN)}BaseMemoryProfileLibNull.obj {$(CMEM)}CommonMemoryAllocationLib.obj {$(CMEM)}CommonMemoryAllocationLibEx.obj OBJECTS = $(OBJECTS) {$(BMPN)}BaseMemoryProfileLibNull.obj {$(CMEM)}CommonMemoryAllocationLib.obj {$(CMEM)}CommonMemoryAllocationLibEx.obj
@ -99,6 +101,10 @@ cleanall:
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@ $(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\ @move $@ $(OUT_DIR)\
{$(UIMG)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) $< -Fo$@
@move $@ $(OUT_DIR)\
{$(USER)}.c.obj : {$(USER)}.c.obj :
$(CC) -c $(CFLAGS) $(INC) /D WIN32 /wd 4754 $< -Fo$@ $(CC) -c $(CFLAGS) $(INC) /D WIN32 /wd 4754 $< -Fo$@
@move $@ $(OUT_DIR)\ @move $@ $(OUT_DIR)\

View File

@ -10,27 +10,6 @@
#define PE_COFF_SECT_NAME_RESRC ".rsrc\0\0" #define PE_COFF_SECT_NAME_RESRC ".rsrc\0\0"
#define PE_COFF_SECT_NAME_DEBUG ".debug\0" #define PE_COFF_SECT_NAME_DEBUG ".debug\0"
static
bool
ScanPeGetHeaderInfo (
OUT image_tool_header_info_t *HeaderInfo,
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
)
{
assert (HeaderInfo != NULL);
assert (Context != NULL);
HeaderInfo->BaseAddress = (uint64_t)PeCoffGetImageBase (Context);
HeaderInfo->EntryPointAddress = PeCoffGetAddressOfEntryPoint (Context);
// FIXME:
HeaderInfo->Machine = PeCoffGetMachine (Context);
HeaderInfo->IsXip = true;
HeaderInfo->Subsystem = PeCoffGetSubsystem (Context);
return true;
}
static
bool bool
ScanPeGetRelocInfo ( ScanPeGetRelocInfo (
OUT image_tool_reloc_info_t *RelocInfo, OUT image_tool_reloc_info_t *RelocInfo,
@ -54,8 +33,6 @@ ScanPeGetRelocInfo (
assert (RelocInfo != NULL); assert (RelocInfo != NULL);
assert (Context != NULL); assert (Context != NULL);
RelocInfo->RelocsStripped = false;
// FIXME: PE/COFF context access // FIXME: PE/COFF context access
RelocBlockRva = Context->RelocDirRva; RelocBlockRva = Context->RelocDirRva;
RelocDirSize = Context->RelocDirSize; RelocDirSize = Context->RelocDirSize;
@ -169,7 +146,6 @@ ScanPeGetRelocInfo (
return true; return true;
} }
static
bool bool
ScanPeGetSegmentInfo ( ScanPeGetSegmentInfo (
OUT image_tool_segment_info_t *SegmentInfo, OUT image_tool_segment_info_t *SegmentInfo,
@ -185,8 +161,6 @@ ScanPeGetSegmentInfo (
assert (SegmentInfo != NULL); assert (SegmentInfo != NULL);
assert (Context != NULL); assert (Context != NULL);
SegmentInfo->SegmentAlignment = PeCoffGetSectionAlignment (Context);
NumSections = PeCoffGetSectionTable (Context, &Section); NumSections = PeCoffGetSectionTable (Context, &Section);
SegmentInfo->Segments = calloc (NumSections, sizeof (*SegmentInfo->Segments)); SegmentInfo->Segments = calloc (NumSections, sizeof (*SegmentInfo->Segments));
@ -319,100 +293,3 @@ ScanPeGetHiiInfo (
return true; return true;
} }
RETURN_STATUS
ToolContextConstructPe (
OUT image_tool_image_info_t *Image,
IN const void *File,
IN size_t FileSize
)
{
PE_COFF_LOADER_IMAGE_CONTEXT Context;
RETURN_STATUS Status;
UINT32 ImageSize;
UINT32 ImageAlignment;
UINT32 DestinationSize;
UINT32 DestinationPages;
void *Destination;
bool Result;
assert (Image != NULL);
assert (File != NULL || FileSize == 0);
if (FileSize > MAX_UINT32) {
fprintf (stderr, "ImageTool: FileSize is too huge\n");
return RETURN_UNSUPPORTED;
}
Status = PeCoffInitializeContext (&Context, File, (UINT32)FileSize);
if (RETURN_ERROR (Status)) {
return Status;
}
ImageSize = PeCoffGetSizeOfImage (&Context);
DestinationPages = EFI_SIZE_TO_PAGES (ImageSize);
DestinationSize = EFI_PAGES_TO_SIZE (DestinationPages);
ImageAlignment = PeCoffGetSectionAlignment (&Context);
Destination = AllocateAlignedCodePages (
DestinationPages,
ImageAlignment
);
if (Destination == NULL) {
fprintf (stderr, "ImageTool: Could not allocate Destination buffer\n");
return RETURN_OUT_OF_RESOURCES;
}
Status = PeCoffLoadImage (&Context, Destination, DestinationSize);
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not Load Image\n");
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
memset (Image, 0, sizeof (*Image));
Result = ScanPeGetHeaderInfo (&Image->HeaderInfo, &Context);
if (!Result) {
fprintf (stderr, "ImageTool: Could not retrieve header info\n");
ToolImageDestruct (Image);
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
Result = ScanPeGetDebugInfo (&Image->DebugInfo, &Context);
if (!Result) {
fprintf (stderr, "ImageTool: Could not retrieve debug info\n");
ToolImageDestruct (Image);
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
Result = ScanPeGetSegmentInfo (&Image->SegmentInfo, &Context);
if (!Result) {
fprintf (stderr, "ImageTool: Could not retrieve segment info\n");
ToolImageDestruct (Image);
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
Result = ScanPeGetRelocInfo (&Image->RelocInfo, &Context);
if (!Result) {
fprintf (stderr, "ImageTool: Could not retrieve reloc info\n");
ToolImageDestruct (Image);
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
Result = ScanPeGetHiiInfo (&Image->HiiInfo, &Context);
if (!Result) {
fprintf (stderr, "ImageTool: Could not retrieve HII info\n");
ToolImageDestruct (Image);
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
FreeAlignedPages (Destination, DestinationPages);
return RETURN_SUCCESS;
}

View File

@ -0,0 +1,23 @@
/** @file
Copyright (c) 2023, Marvin Häuser. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#ifndef PE_SCAN_H
#define PE_SCAN_H
#include "ImageTool.h"
bool
ScanPeGetRelocInfo (
OUT image_tool_reloc_info_t *RelocInfo,
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
);
bool
ScanPeGetSegmentInfo (
OUT image_tool_segment_info_t *SegmentInfo,
IN PE_COFF_LOADER_IMAGE_CONTEXT *Context
);
#endif // PE_SCAN_H

View File

@ -0,0 +1,261 @@
/** @file
Copyright (c) 2023, Marvin Häuser. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include "ImageTool.h"
#include <Uefi/UefiBaseType.h>
#include <Library/UefiImageLib.h>
#include "PeScan.h"
static
bool
ScanUefiImageGetHeaderInfo (
OUT image_tool_header_info_t *HeaderInfo,
IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
)
{
assert (HeaderInfo != NULL);
assert (Context != NULL);
HeaderInfo->BaseAddress = (uint64_t)UefiImageGetPreferredAddress (Context);
HeaderInfo->EntryPointAddress = UefiImageGetEntryPointAddress (Context);
HeaderInfo->Machine = UefiImageGetMachine (Context);
HeaderInfo->Subsystem = UefiImageGetSubsystem (Context);
// FIXME:
HeaderInfo->IsXip = true;
return true;
}
static
bool
ScanUefiImageGetRelocInfo (
OUT image_tool_reloc_info_t *RelocInfo,
IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
)
{
UINT8 FormatIndex;
assert (RelocInfo != NULL);
assert (Context != NULL);
FormatIndex = UefiImageGetFormat (Context);
RelocInfo->RelocsStripped = UefiImageGetRelocsStripped (Context);
if (FormatIndex == UefiImageFormatPe) {
return ScanPeGetRelocInfo (
RelocInfo,
(PE_COFF_LOADER_IMAGE_CONTEXT *)Context
);
}
fprintf (
stderr,
"ImageTool: Unsupported UefiImage format %u\n",
FormatIndex
);
return false;
}
static
bool
ScanUefiImageGetSegmentInfo (
OUT image_tool_segment_info_t *SegmentInfo,
IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
)
{
UINT8 FormatIndex;
assert (SegmentInfo != NULL);
assert (Context != NULL);
FormatIndex = UefiImageGetFormat (Context);
SegmentInfo->SegmentAlignment = UefiImageGetSegmentAlignment (Context);
if (FormatIndex == UefiImageFormatPe) {
return ScanPeGetSegmentInfo (
SegmentInfo,
(PE_COFF_LOADER_IMAGE_CONTEXT *)Context
);
}
fprintf (
stderr,
"ImageTool: Unsupported UefiImage format %u\n",
FormatIndex
);
return false;
}
bool
ScanUefiImageGetDebugInfo (
OUT image_tool_debug_info_t *DebugInfo,
IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
)
{
RETURN_STATUS Status;
const CHAR8 *SymbolsPath;
UINT32 SymbolsPathSize;
assert (DebugInfo != NULL);
assert (Context != NULL);
Status = UefiImageGetSymbolsPath (Context, &SymbolsPath, &SymbolsPathSize);
if (Status == RETURN_NOT_FOUND) {
return true;
}
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not get SymbolsPath\n");
return false;
}
assert (SymbolsPathSize >= 1);
DebugInfo->SymbolsPath = malloc (SymbolsPathSize + 1);
if (DebugInfo->SymbolsPath == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for SymbolsPath\n");
return false;
}
memmove (DebugInfo->SymbolsPath, SymbolsPath, SymbolsPathSize);
assert (DebugInfo->SymbolsPath[SymbolsPathSize - 1] == '\0');
DebugInfo->SymbolsPathLen = SymbolsPathSize - 1;
return true;
}
bool
ScanUefiImageGetHiiInfo (
OUT image_tool_hii_info_t *HiiInfo,
IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *Context
)
{
RETURN_STATUS Status;
UINT32 HiiRva;
UINT32 HiiSize;
const char *ImageBuffer;
assert (HiiInfo != NULL);
assert (Context != NULL);
Status = UefiImageGetHiiDataRva (Context, &HiiRva, &HiiSize);
if (Status == RETURN_NOT_FOUND) {
return true;
}
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Malformed HII data\n");
return false;
}
HiiInfo->Data = malloc (HiiSize);
if (HiiInfo->Data == NULL) {
fprintf (stderr, "ImageTool: Could not allocate memory for HiiInfo Data\n");
return false;
}
ImageBuffer = (char *)UefiImageLoaderGetImageAddress (Context);
memmove (HiiInfo->Data, ImageBuffer + HiiRva, HiiSize);
HiiInfo->DataSize = HiiSize;
return true;
}
RETURN_STATUS
ToolContextConstructUefiImage (
OUT image_tool_image_info_t *Image,
OUT int8_t *Format,
IN const void *File,
IN size_t FileSize
)
{
RETURN_STATUS Status;
UEFI_IMAGE_LOADER_IMAGE_CONTEXT Context;
UINT32 ImageSize;
UINT32 ImageAlignment;
UINT32 DestinationPages;
UINT32 DestinationSize;
void *Destination;
bool Success;
assert (Image != NULL);
assert (File != NULL || FileSize == 0);
if (FileSize > MAX_UINT32) {
fprintf (stderr, "ImageTool: FileSize is too huge\n");
return RETURN_UNSUPPORTED;
}
Status = UefiImageInitializeContext (&Context, File, (UINT32)FileSize);
if (RETURN_ERROR (Status)) {
return Status;
}
*Format = (int8_t)UefiImageGetFormat (&Context);
ImageSize = UefiImageGetImageSize (&Context);
DestinationPages = EFI_SIZE_TO_PAGES (ImageSize);
DestinationSize = EFI_PAGES_TO_SIZE (DestinationPages);
ImageAlignment = UefiImageGetSegmentAlignment (&Context);
Destination = AllocateAlignedCodePages (DestinationPages, ImageAlignment);
if (Destination == NULL) {
fprintf (stderr, "ImageTool: Could not allocate Destination buffer\n");
return RETURN_OUT_OF_RESOURCES;
}
Status = UefiImageLoadImage (&Context, Destination, DestinationSize);
if (RETURN_ERROR (Status)) {
fprintf (stderr, "ImageTool: Could not Load Image\n");
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
memset (Image, 0, sizeof (*Image));
Success = ScanUefiImageGetHeaderInfo (&Image->HeaderInfo, &Context);
if (!Success) {
fprintf (stderr, "ImageTool: Could not retrieve header info\n");
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
Success = ScanUefiImageGetSegmentInfo (&Image->SegmentInfo, &Context);
if (!Success) {
fprintf (stderr, "ImageTool: Could not retrieve segment info\n");
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
Success = ScanUefiImageGetRelocInfo (&Image->RelocInfo, &Context);
if (!Success) {
fprintf (stderr, "ImageTool: Could not retrieve reloc info\n");
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
Success = ScanUefiImageGetHiiInfo (&Image->HiiInfo, &Context);
if (!Success) {
fprintf (stderr, "ImageTool: Could not retrieve HII info\n");
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
Success = ScanUefiImageGetDebugInfo (&Image->DebugInfo, &Context);
if (!Success) {
fprintf (stderr, "ImageTool: Could not retrieve debug info\n");
FreeAlignedPages (Destination, DestinationPages);
return RETURN_VOLUME_CORRUPTED;
}
FreeAlignedPages (Destination, DestinationPages);
return RETURN_SUCCESS;
}