in lsvmutils/peimage.c [152:318]
int ParseImage(
Image* image,
IN const void* imageData,
IN UINTN imageSize)
{
int status = 0;
unsigned int i;
EFI_IMAGE_SECTION_HEADER *sections = NULL;
EFI_IMAGE_DOS_HEADER *dos_hdr = (void *)imageData;
unsigned int pe_hdr_offset;
EFI_IMAGE_NT_HEADERS64* pe_hdr;
EFI_IMAGE_DATA_DIRECTORY* sec_dir;
/* Check parameters */
if (!imageData || imageSize < sizeof(EFI_IMAGE_DOS_HEADER) || !image)
{
status = -1;
goto done;
}
/* Initialize the image */
Memset(image, 0, sizeof(Image));
image->imageData = imageData;
image->imageSize = imageSize;
/* Check header magic number */
if (dos_hdr->e_magic != EFI_IMAGE_DOS_SIGNATURE)
{
status = -1;
goto done;
}
/* Set a pointer to the PE header */
pe_hdr_offset = dos_hdr->e_lfanew;
pe_hdr = (EFI_IMAGE_NT_HEADERS64*)((UINT8*)imageData + pe_hdr_offset);
/* Region 1: up to (but not including) the checksum */
{
const void* p = imageData;
UINTN n = (char*)&pe_hdr->OptionalHeader.CheckSum - (char*)imageData;
if (_AppendRegion(image, p, n) != 0)
{
status = -1;
goto done;
}
}
/* Set a pointer to the security directory entry (holds signature) */
sec_dir = &pe_hdr->OptionalHeader.DataDirectory[
EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
/* Save the digital signature data (do not add to regions list) */
if (_ParseSignature(image, sec_dir->VirtualAddress, sec_dir->Size) != 0)
{
status = -1;
goto done;
}
/* Region 2: from after checksum up to security directory entry */
{
const void* p = (char*)&pe_hdr->OptionalHeader.CheckSum + sizeof(int);
UINTN n = (char*)sec_dir - (char*)p;
if (_AppendRegion(image, p, n) != 0)
{
status = -1;
goto done;
}
}
/* Region 3: end of certificate table to end of imageData header */
{
const void* p = sec_dir + 1;
UINTN n = pe_hdr->OptionalHeader.SizeOfHeaders -
((char*)p - (char*)imageData);
if (_AppendRegion(image, p, n) != 0)
{
status = -1;
goto done;
}
}
/* Sort the section headers (in auxilliary storage) */
{
int i;
int j;
if (!(sections = (EFI_IMAGE_SECTION_HEADER *)Calloc(
pe_hdr->FileHeader.NumberOfSections,
sizeof(EFI_IMAGE_SECTION_HEADER))))
{
status = -1;
goto done;
}
Memcpy(sections,
(char*)imageData +
pe_hdr_offset +
sizeof(UINT32) +
sizeof(EFI_IMAGE_FILE_HEADER) +
pe_hdr->FileHeader.SizeOfOptionalHeader,
pe_hdr->FileHeader.NumberOfSections *
sizeof(EFI_IMAGE_SECTION_HEADER));
for (i = 0; i < pe_hdr->FileHeader.NumberOfSections - 1; i++)
{
for (j = 0; j < pe_hdr->FileHeader.NumberOfSections - 1; j++)
{
if (_compare(§ions[j], §ions[j+1]) > 0)
{
EFI_IMAGE_SECTION_HEADER tmp = sections[j];
sections[j] = sections[j+1];
sections[j+1] = tmp;
}
}
}
}
/* Add a region for each section */
for (i = 0; i < pe_hdr->FileHeader.NumberOfSections; i++)
{
EFI_IMAGE_SECTION_HEADER *section = §ions[i];
if (section->SizeOfRawData)
{
const void* p = (char*)imageData + section->PointerToRawData;
UINTN n = section->SizeOfRawData;
if (_AppendRegion(image, p, n) != 0)
{
status = -1;
goto done;
}
}
}
/* Add a region for whatever follows the final section */
{
EFI_IMAGE_SECTION_HEADER *section =
§ions[pe_hdr->FileHeader.NumberOfSections-1];
unsigned int offset =
section->PointerToRawData + section->SizeOfRawData;
/* Hash data following the sections */
if (offset < imageSize)
{
const void* p = (char*)imageData + offset;
UINTN n = imageSize - sec_dir->Size - offset;
if (_AppendRegion(image, p, n) != 0)
{
status = -1;
goto done;
}
}
}
done:
if (sections)
Free(sections);
return status;
}