mirror of https://github.com/acidanthera/audk.git
MdeModulePkg: Add ImagePropertiesRecordLib Host-Based Unit Test
Create a host-based unit test for the ImagePropertiesRecordLib SplitTable() logic. This test has 4 cases which tests different potential image and memory map layouts. 3/4 of these tests fail with the logic in its current state to provide proof of the bugs in the current MAT logic. Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Dandan Bi <dandan.bi@intel.com> Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
This commit is contained in:
parent
7284c44951
commit
0a9e215312
|
@ -0,0 +1,938 @@
|
||||||
|
/** @file
|
||||||
|
Unit tests the SplitTable() ImagePropertiesRecordLib Logic
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation.
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <cmocka.h>
|
||||||
|
|
||||||
|
#include <Uefi.h>
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/UnitTestLib.h>
|
||||||
|
#include <Library/ImagePropertiesRecordLib.h>
|
||||||
|
|
||||||
|
#define UNIT_TEST_APP_NAME "Image Properties Record Lib Unit Test"
|
||||||
|
#define UNIT_TEST_APP_VERSION "1.0"
|
||||||
|
|
||||||
|
#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
|
||||||
|
((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))
|
||||||
|
|
||||||
|
// The starting memory map will contain 6 entries
|
||||||
|
#define NUMBER_OF_MEMORY_MAP_DESCRIPTORS 6
|
||||||
|
|
||||||
|
// Each memory map descriptor will be the sizeof(EFI_MEMORY_DESCRIPTOR) instead of a nonstandard size
|
||||||
|
// to catch pointer math issues
|
||||||
|
#define DESCRIPTOR_SIZE sizeof(EFI_MEMORY_DESCRIPTOR)
|
||||||
|
|
||||||
|
// Each memory map descriptor will describe 12 pages
|
||||||
|
#define BASE_DESCRIPTOR_NUMBER_OF_PAGES 0x0C
|
||||||
|
|
||||||
|
// The size, in bytes, of each memory map descriptor range
|
||||||
|
#define BASE_DESCRIPTOR_ENTRY_SIZE (EFI_PAGES_TO_SIZE(BASE_DESCRIPTOR_NUMBER_OF_PAGES))
|
||||||
|
|
||||||
|
// MACRO to get the starting address of a descriptor's described range based on the index of that descriptor
|
||||||
|
#define BASE_DESCRIPTOR_START_ADDRESS(DescriptorNumber) (DescriptorNumber * BASE_DESCRIPTOR_ENTRY_SIZE)
|
||||||
|
|
||||||
|
// Virtual start must be zero
|
||||||
|
#define BASE_DESCRIPTOR_VIRTUAL_START 0x0
|
||||||
|
|
||||||
|
// Size of the default memory map
|
||||||
|
#define BASE_MEMORY_MAP_SIZE (NUMBER_OF_MEMORY_MAP_DESCRIPTORS * DESCRIPTOR_SIZE)
|
||||||
|
|
||||||
|
// Number of images in each test case
|
||||||
|
#define NUMBER_OF_IMAGES_TO_SPLIT 3
|
||||||
|
|
||||||
|
// Maximum number of descriptors required for each image (None->Data->Code->Data->Code->Data->None)
|
||||||
|
#define MAX_DESCRIPTORS_PER_IMAGE 7
|
||||||
|
|
||||||
|
// Number of unused additional descriptors in the starting memory map buffer which is used by the
|
||||||
|
// SplitTable() logic
|
||||||
|
#define NUMBER_OF_ADDITIONAL_DESCRIPTORS (NUMBER_OF_IMAGES_TO_SPLIT * MAX_DESCRIPTORS_PER_IMAGE)
|
||||||
|
|
||||||
|
// Size of the memory map with enough space for the starting descriptors and the split descriptors
|
||||||
|
#define SPLIT_MEMORY_MAP_SIZE (BASE_MEMORY_MAP_SIZE + (NUMBER_OF_ADDITIONAL_DESCRIPTORS * DESCRIPTOR_SIZE))
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SectionTypeCode,
|
||||||
|
SectionTypeData,
|
||||||
|
SectionTypeNotFound
|
||||||
|
} SECTION_TYPE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EFI_MEMORY_DESCRIPTOR *MemoryMap;
|
||||||
|
LIST_ENTRY ImageList;
|
||||||
|
} IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT;
|
||||||
|
|
||||||
|
EFI_MEMORY_DESCRIPTOR BaseMemoryMap[] = {
|
||||||
|
{
|
||||||
|
EfiConventionalMemory, // Type
|
||||||
|
BASE_DESCRIPTOR_START_ADDRESS (0), // PhysicalStart
|
||||||
|
BASE_DESCRIPTOR_VIRTUAL_START, // VirtualStart
|
||||||
|
BASE_DESCRIPTOR_NUMBER_OF_PAGES, // Number of Pages
|
||||||
|
0 // Attribute
|
||||||
|
},
|
||||||
|
{
|
||||||
|
EfiConventionalMemory, // Type
|
||||||
|
BASE_DESCRIPTOR_START_ADDRESS (1), // PhysicalStart
|
||||||
|
BASE_DESCRIPTOR_VIRTUAL_START, // VirtualStart
|
||||||
|
BASE_DESCRIPTOR_NUMBER_OF_PAGES, // Number of Pages
|
||||||
|
0 // Attribute
|
||||||
|
},
|
||||||
|
{
|
||||||
|
EfiConventionalMemory, // Type
|
||||||
|
BASE_DESCRIPTOR_START_ADDRESS (2), // PhysicalStart
|
||||||
|
BASE_DESCRIPTOR_VIRTUAL_START, // VirtualStart
|
||||||
|
BASE_DESCRIPTOR_NUMBER_OF_PAGES, // Number of Pages
|
||||||
|
0 // Attribute
|
||||||
|
},
|
||||||
|
{
|
||||||
|
EfiConventionalMemory, // Type
|
||||||
|
BASE_DESCRIPTOR_START_ADDRESS (3), // PhysicalStart
|
||||||
|
BASE_DESCRIPTOR_VIRTUAL_START, // VirtualStart
|
||||||
|
BASE_DESCRIPTOR_NUMBER_OF_PAGES, // Number of Pages
|
||||||
|
0 // Attribute
|
||||||
|
},
|
||||||
|
{
|
||||||
|
EfiConventionalMemory, // Type
|
||||||
|
BASE_DESCRIPTOR_START_ADDRESS (4), // PhysicalStart
|
||||||
|
BASE_DESCRIPTOR_VIRTUAL_START, // VirtualStart
|
||||||
|
BASE_DESCRIPTOR_NUMBER_OF_PAGES, // Number of Pages
|
||||||
|
0 // Attribute
|
||||||
|
},
|
||||||
|
{
|
||||||
|
EfiConventionalMemory, // Type
|
||||||
|
BASE_DESCRIPTOR_START_ADDRESS (5), // PhysicalStart
|
||||||
|
BASE_DESCRIPTOR_VIRTUAL_START, // VirtualStart
|
||||||
|
BASE_DESCRIPTOR_NUMBER_OF_PAGES, // Number of Pages
|
||||||
|
0 // Attribute
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns a bitmap where one bit is set for each section in the image list. For example, if
|
||||||
|
there are 3 images and each image 3 sections the returned bitmap will be 111111111.
|
||||||
|
|
||||||
|
@param[in] ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries
|
||||||
|
|
||||||
|
@retval A bitmap such that the most significant bit is the number of sections
|
||||||
|
in all images and every bit between 0 -> MSB is set
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
UINT64
|
||||||
|
GetImageSectionBitmap (
|
||||||
|
IN LIST_ENTRY *ImageRecordList
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IMAGE_PROPERTIES_RECORD *ImageRecord;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
|
||||||
|
LIST_ENTRY *ImageRecordLink;
|
||||||
|
LIST_ENTRY *ImageRecordCodeSectionLink;
|
||||||
|
EFI_PHYSICAL_ADDRESS SectionBase;
|
||||||
|
UINT64 ReturnBitmap;
|
||||||
|
UINT64 Shift;
|
||||||
|
|
||||||
|
if (ImageRecordList == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnBitmap = 0;
|
||||||
|
Shift = 0;
|
||||||
|
|
||||||
|
// Walk through each image record
|
||||||
|
for (ImageRecordLink = ImageRecordList->ForwardLink;
|
||||||
|
ImageRecordLink != ImageRecordList;
|
||||||
|
ImageRecordLink = ImageRecordLink->ForwardLink)
|
||||||
|
{
|
||||||
|
ImageRecord = CR (
|
||||||
|
ImageRecordLink,
|
||||||
|
IMAGE_PROPERTIES_RECORD,
|
||||||
|
Link,
|
||||||
|
IMAGE_PROPERTIES_RECORD_SIGNATURE
|
||||||
|
);
|
||||||
|
|
||||||
|
SectionBase = ImageRecord->ImageBase;
|
||||||
|
|
||||||
|
// Walk through each code entry
|
||||||
|
for (ImageRecordCodeSectionLink = ImageRecord->CodeSegmentList.ForwardLink;
|
||||||
|
ImageRecordCodeSectionLink != &ImageRecord->CodeSegmentList;
|
||||||
|
ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink)
|
||||||
|
{
|
||||||
|
ImageRecordCodeSection = CR (
|
||||||
|
ImageRecordCodeSectionLink,
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION,
|
||||||
|
Link,
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check for data region before the code section base
|
||||||
|
if (SectionBase < ImageRecordCodeSection->CodeSegmentBase) {
|
||||||
|
ReturnBitmap |= LShiftU64 (1, Shift++);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code section
|
||||||
|
ReturnBitmap |= LShiftU64 (1, Shift++);
|
||||||
|
SectionBase = ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for data region after the previous code section
|
||||||
|
if (SectionBase < (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
|
||||||
|
ReturnBitmap |= LShiftU64 (1, Shift++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReturnBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Searches the input image list for a section which exactly matches the memory range Buffer -> Buffer + Length.
|
||||||
|
|
||||||
|
@param[in] Buffer Start Address to check
|
||||||
|
@param[in] Length Length to check
|
||||||
|
@param[out] Type The type of the section which corresponds with the memory
|
||||||
|
range Buffer -> Buffer + Length (Code or Data) or SectionTypeNotFound
|
||||||
|
if no image section matches the memory range
|
||||||
|
@param[in] ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries to check against
|
||||||
|
the memory range Buffer -> Buffer + Length
|
||||||
|
|
||||||
|
@retval A bitmap with a single bit set (1 << Shift) where Shift corresponds with the number of sections inspected
|
||||||
|
in the image list before arriving at the section matching the memory range Buffer -> Buffer + Length
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
UINT64
|
||||||
|
MatchDescriptorToImageSection (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS Buffer,
|
||||||
|
IN UINT64 Length,
|
||||||
|
OUT SECTION_TYPE *Type,
|
||||||
|
IN LIST_ENTRY *ImageRecordList
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IMAGE_PROPERTIES_RECORD *ImageRecord;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
|
||||||
|
LIST_ENTRY *ImageRecordLink;
|
||||||
|
LIST_ENTRY *ImageRecordCodeSectionLink;
|
||||||
|
EFI_PHYSICAL_ADDRESS SectionBase;
|
||||||
|
UINT8 Shift;
|
||||||
|
|
||||||
|
Shift = 0;
|
||||||
|
|
||||||
|
if (ImageRecordList == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk through each image record
|
||||||
|
for (ImageRecordLink = ImageRecordList->ForwardLink;
|
||||||
|
ImageRecordLink != ImageRecordList;
|
||||||
|
ImageRecordLink = ImageRecordLink->ForwardLink)
|
||||||
|
{
|
||||||
|
ImageRecord = CR (
|
||||||
|
ImageRecordLink,
|
||||||
|
IMAGE_PROPERTIES_RECORD,
|
||||||
|
Link,
|
||||||
|
IMAGE_PROPERTIES_RECORD_SIGNATURE
|
||||||
|
);
|
||||||
|
|
||||||
|
SectionBase = ImageRecord->ImageBase;
|
||||||
|
|
||||||
|
// Walk through each code entry
|
||||||
|
for (ImageRecordCodeSectionLink = ImageRecord->CodeSegmentList.ForwardLink;
|
||||||
|
ImageRecordCodeSectionLink != &ImageRecord->CodeSegmentList;
|
||||||
|
ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink)
|
||||||
|
{
|
||||||
|
ImageRecordCodeSection = CR (
|
||||||
|
ImageRecordCodeSectionLink,
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION,
|
||||||
|
Link,
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (SectionBase < ImageRecordCodeSection->CodeSegmentBase) {
|
||||||
|
// Check the data region before the code section base
|
||||||
|
if ((Buffer == SectionBase) &&
|
||||||
|
(Length == ImageRecordCodeSection->CodeSegmentBase - SectionBase))
|
||||||
|
{
|
||||||
|
*Type = SectionTypeData;
|
||||||
|
return LShiftU64 (1, Shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shift++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the code region
|
||||||
|
if ((Buffer == ImageRecordCodeSection->CodeSegmentBase) &&
|
||||||
|
(Length == ImageRecordCodeSection->CodeSegmentSize))
|
||||||
|
{
|
||||||
|
*Type = SectionTypeCode;
|
||||||
|
return LShiftU64 (1, Shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shift++;
|
||||||
|
SectionBase = ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the data region after the code section
|
||||||
|
if (SectionBase < (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
|
||||||
|
if ((Buffer == SectionBase) &&
|
||||||
|
(Length == (ImageRecord->ImageBase + ImageRecord->ImageSize) - SectionBase))
|
||||||
|
{
|
||||||
|
*Type = SectionTypeData;
|
||||||
|
return LShiftU64 (1, Shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shift++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No image sections match
|
||||||
|
*Type = SectionTypeNotFound;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Walks through the input memory map and checks that every memory descriptor with an attribute matches
|
||||||
|
an image in ImageRecordList.
|
||||||
|
|
||||||
|
@param[in] MemoryMapSize The size, in bytes, of the memory map
|
||||||
|
@param[in] MemoryMap A pointer to the buffer containing the memory map
|
||||||
|
@param[in] ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries
|
||||||
|
|
||||||
|
@retval TRUE if all memory descriptors with attributes match an image section and have the correct attributes
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
BOOLEAN
|
||||||
|
IsMemoryMapValid (
|
||||||
|
IN UINTN MemoryMapSize,
|
||||||
|
IN EFI_MEMORY_DESCRIPTOR *MemoryMap,
|
||||||
|
IN LIST_ENTRY *ImageRecordList
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT64 ImageSectionsBitmap;
|
||||||
|
UINT64 ReturnSectionBitmask;
|
||||||
|
UINT64 NumberOfDescriptors;
|
||||||
|
UINT8 Index;
|
||||||
|
SECTION_TYPE Type;
|
||||||
|
|
||||||
|
Index = 0;
|
||||||
|
NumberOfDescriptors = MemoryMapSize / DESCRIPTOR_SIZE;
|
||||||
|
|
||||||
|
UT_ASSERT_EQUAL (MemoryMapSize % DESCRIPTOR_SIZE, 0);
|
||||||
|
UT_ASSERT_NOT_NULL (MemoryMap);
|
||||||
|
UT_ASSERT_NOT_NULL (ImageRecordList);
|
||||||
|
|
||||||
|
// The returned bitmap will have one bit is set for each section in the image list.
|
||||||
|
// If there are 3 images and 3 sections each image, the resulting bitmap will
|
||||||
|
// be 0000000000000000000000000000000000000000000000000000000111111111. Flipping that bitmap
|
||||||
|
// results in 1111111111111111111111111111111111111111111111111111111000000000. The return value
|
||||||
|
// of each iteration through MatchDescriptorToImageSection() is one set bit corrosponding to the number
|
||||||
|
// of sections before finding the section which matched the descriptor memory range which we
|
||||||
|
// OR with ImageSectionsBitmap. If, at the end of the loop, every bit in ImageSectionsBitmap is set,
|
||||||
|
// we must have matched every image in ImageRecordList with a descriptor in the memory map which has
|
||||||
|
// nonzero attributes.
|
||||||
|
ImageSectionsBitmap = ~GetImageSectionBitmap (ImageRecordList);
|
||||||
|
|
||||||
|
// For each descriptor in the memory map
|
||||||
|
for ( ; Index < NumberOfDescriptors; Index++) {
|
||||||
|
if (MemoryMap[Index].Attribute != 0) {
|
||||||
|
ReturnSectionBitmask = MatchDescriptorToImageSection (
|
||||||
|
MemoryMap[Index].PhysicalStart,
|
||||||
|
EFI_PAGES_TO_SIZE (MemoryMap[Index].NumberOfPages),
|
||||||
|
&Type,
|
||||||
|
ImageRecordList
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make sure the attributes of the descriptor match the returned section type.
|
||||||
|
// DATA sections should have execution protection and CODE sections should have
|
||||||
|
// write protection.
|
||||||
|
if ((Type == SectionTypeNotFound) ||
|
||||||
|
((Type == SectionTypeData) && (MemoryMap[Index].Attribute == EFI_MEMORY_RP)) ||
|
||||||
|
((Type == SectionTypeCode) && (MemoryMap[Index].Attribute == EFI_MEMORY_XP)))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the bit associated with image found has already been set, then there must be a duplicate
|
||||||
|
// in the memory map meaning it is invalid.
|
||||||
|
UT_ASSERT_EQUAL (ImageSectionsBitmap & ReturnSectionBitmask, 0);
|
||||||
|
|
||||||
|
ImageSectionsBitmap |= ReturnSectionBitmask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If every bit in ImageSectionsBitmap is set, the return value will be TRUE
|
||||||
|
return !(~ImageSectionsBitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Separate the image sections in the memory map and run a check to ensure the output is valid.
|
||||||
|
|
||||||
|
@param[in] Context Context containing the memory map and image record pointers
|
||||||
|
|
||||||
|
@retval TRUE if the memory map is split correctly
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
BOOLEAN
|
||||||
|
SeparateAndCheck (
|
||||||
|
IN IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN MemoryMapSize;
|
||||||
|
|
||||||
|
MemoryMapSize = BASE_MEMORY_MAP_SIZE;
|
||||||
|
|
||||||
|
// Separate the memory map so each image section has its own descriptor
|
||||||
|
SplitTable (
|
||||||
|
&MemoryMapSize,
|
||||||
|
Context->MemoryMap,
|
||||||
|
DESCRIPTOR_SIZE,
|
||||||
|
&Context->ImageList,
|
||||||
|
NUMBER_OF_ADDITIONAL_DESCRIPTORS
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ensure the updated memory map is valid
|
||||||
|
return IsMemoryMapValid (MemoryMapSize, Context->MemoryMap, &Context->ImageList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Test the case where the image range contains multiple code sections and does not perfectly align with
|
||||||
|
the existing memory descriptor.
|
||||||
|
|
||||||
|
@param[in] Context Context containing the memory map and image record pointers
|
||||||
|
|
||||||
|
@retval UNIT_TEST_PASSED The Unit test has completed and the test
|
||||||
|
case was successful.
|
||||||
|
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
|
||||||
|
**/
|
||||||
|
UNIT_TEST_STATUS
|
||||||
|
EFIAPI
|
||||||
|
MaxOutAdditionalDescriptors (
|
||||||
|
IN UNIT_TEST_CONTEXT Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image1;
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image2;
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image3;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage1;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage2;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage3;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *AddCodeSectionInImage1;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *AddCodeSectionInImage2;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *AddCodeSectionInImage3;
|
||||||
|
IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *TestContext;
|
||||||
|
|
||||||
|
TestContext = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)Context;
|
||||||
|
|
||||||
|
Image1 = CR (TestContext->ImageList.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
Image2 = CR (Image1->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
Image3 = CR (Image2->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
|
||||||
|
CodeSectionInImage1 = CR (Image1->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
CodeSectionInImage2 = CR (Image2->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
CodeSectionInImage3 = CR (Image3->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Descriptor 1
|
||||||
|
///////////////
|
||||||
|
// | | | | | | | |
|
||||||
|
// | 4K PAGE | DATA | CODE | DATA | CODE | DATA | 4K PAGE * 5 |
|
||||||
|
// | | | | | | | |
|
||||||
|
|
||||||
|
Image1->ImageBase = BASE_DESCRIPTOR_START_ADDRESS (1) + EFI_PAGE_SIZE;
|
||||||
|
Image1->ImageSize = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE - EFI_PAGE_SIZE;
|
||||||
|
Image1->CodeSegmentCount = 2;
|
||||||
|
CodeSectionInImage1->CodeSegmentBase = Image1->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage1->CodeSegmentSize = EFI_PAGE_SIZE;
|
||||||
|
TestContext->MemoryMap[1].Type = EfiBootServicesCode;
|
||||||
|
|
||||||
|
AddCodeSectionInImage1 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
|
||||||
|
AddCodeSectionInImage1->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
|
||||||
|
AddCodeSectionInImage1->CodeSegmentBase = CodeSectionInImage1->CodeSegmentBase + CodeSectionInImage1->CodeSegmentSize + EFI_PAGE_SIZE;
|
||||||
|
AddCodeSectionInImage1->CodeSegmentSize = EFI_PAGE_SIZE;
|
||||||
|
|
||||||
|
InsertTailList (&Image1->CodeSegmentList, &AddCodeSectionInImage1->Link);
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Descriptor 2
|
||||||
|
///////////////
|
||||||
|
// | | | | | | | |
|
||||||
|
// | 4K PAGE | DATA | CODE | DATA | CODE | DATA | 4K PAGE * 5 |
|
||||||
|
// | | | | | | | |
|
||||||
|
|
||||||
|
Image2->ImageBase = BASE_DESCRIPTOR_START_ADDRESS (2) + EFI_PAGE_SIZE;
|
||||||
|
Image2->ImageSize = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE - EFI_PAGE_SIZE;
|
||||||
|
Image2->CodeSegmentCount = 2;
|
||||||
|
CodeSectionInImage2->CodeSegmentBase = Image2->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage2->CodeSegmentSize = EFI_PAGE_SIZE;
|
||||||
|
TestContext->MemoryMap[2].Type = EfiLoaderCode;
|
||||||
|
|
||||||
|
AddCodeSectionInImage2 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
|
||||||
|
AddCodeSectionInImage2->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
|
||||||
|
AddCodeSectionInImage2->CodeSegmentBase = CodeSectionInImage2->CodeSegmentBase + CodeSectionInImage2->CodeSegmentSize + EFI_PAGE_SIZE;
|
||||||
|
AddCodeSectionInImage2->CodeSegmentSize = EFI_PAGE_SIZE;
|
||||||
|
|
||||||
|
InsertTailList (&Image2->CodeSegmentList, &AddCodeSectionInImage2->Link);
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Descriptor 3
|
||||||
|
///////////////
|
||||||
|
// | | | | | | | |
|
||||||
|
// | 4K PAGE | DATA | CODE | DATA | CODE | DATA | 4K PAGE * 5 |
|
||||||
|
// | | | | | | | |
|
||||||
|
|
||||||
|
Image3->ImageBase = BASE_DESCRIPTOR_START_ADDRESS (3) + EFI_PAGE_SIZE;
|
||||||
|
Image3->ImageSize = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE - EFI_PAGE_SIZE;
|
||||||
|
Image3->CodeSegmentCount = 2;
|
||||||
|
CodeSectionInImage3->CodeSegmentBase = Image3->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage3->CodeSegmentSize = EFI_PAGE_SIZE;
|
||||||
|
TestContext->MemoryMap[3].Type = EfiRuntimeServicesCode;
|
||||||
|
|
||||||
|
AddCodeSectionInImage3 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
|
||||||
|
AddCodeSectionInImage3->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
|
||||||
|
AddCodeSectionInImage3->CodeSegmentBase = CodeSectionInImage3->CodeSegmentBase + CodeSectionInImage3->CodeSegmentSize + EFI_PAGE_SIZE;
|
||||||
|
AddCodeSectionInImage3->CodeSegmentSize = EFI_PAGE_SIZE;
|
||||||
|
|
||||||
|
InsertTailList (&Image3->CodeSegmentList, &AddCodeSectionInImage3->Link);
|
||||||
|
|
||||||
|
UT_ASSERT_TRUE (SeparateAndCheck (TestContext));
|
||||||
|
|
||||||
|
return UNIT_TEST_PASSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Test the case where multiple image ranges lie within an existing memory descriptor.
|
||||||
|
|
||||||
|
@param[in] Context Context containing the memory map and image record pointers
|
||||||
|
|
||||||
|
@retval UNIT_TEST_PASSED The Unit test has completed and the test
|
||||||
|
case was successful.
|
||||||
|
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
|
||||||
|
**/
|
||||||
|
UNIT_TEST_STATUS
|
||||||
|
EFIAPI
|
||||||
|
MultipleImagesInOneDescriptor (
|
||||||
|
IN UNIT_TEST_CONTEXT Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image1;
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image2;
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image3;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage1;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage2;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage3;
|
||||||
|
IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *TestContext;
|
||||||
|
|
||||||
|
TestContext = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)Context;
|
||||||
|
|
||||||
|
Image1 = CR (TestContext->ImageList.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
Image2 = CR (Image1->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
Image3 = CR (Image2->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
|
||||||
|
CodeSectionInImage1 = CR (Image1->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
CodeSectionInImage2 = CR (Image2->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
CodeSectionInImage3 = CR (Image3->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Descriptor 1
|
||||||
|
///////////////
|
||||||
|
// | | | | | | | | | | | | |
|
||||||
|
// | 4K PAGE | DATA | CODE | DATA | 4K PAGE | DATA | CODE | DATA | DATA | CODE | DATA | 4K PAGE |
|
||||||
|
// | | | | | | | | | | | | |
|
||||||
|
|
||||||
|
Image1->ImageBase = BASE_DESCRIPTOR_START_ADDRESS (1) + EFI_PAGE_SIZE;
|
||||||
|
Image1->ImageSize = EFI_PAGES_TO_SIZE (3);
|
||||||
|
Image1->CodeSegmentCount = 1;
|
||||||
|
CodeSectionInImage1->CodeSegmentBase = Image1->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage1->CodeSegmentSize = EFI_PAGE_SIZE;
|
||||||
|
TestContext->MemoryMap[1].Type = EfiBootServicesCode;
|
||||||
|
|
||||||
|
Image2->ImageBase = Image1->ImageBase + Image1->ImageSize + EFI_PAGE_SIZE;
|
||||||
|
Image2->ImageSize = EFI_PAGES_TO_SIZE (3);
|
||||||
|
Image2->CodeSegmentCount = 1;
|
||||||
|
CodeSectionInImage2->CodeSegmentBase = Image2->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage2->CodeSegmentSize = EFI_PAGE_SIZE;
|
||||||
|
|
||||||
|
Image3->ImageBase = Image2->ImageBase + Image2->ImageSize;
|
||||||
|
Image3->ImageSize = EFI_PAGES_TO_SIZE (3);
|
||||||
|
Image3->CodeSegmentCount = 1;
|
||||||
|
CodeSectionInImage3->CodeSegmentBase = Image3->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage3->CodeSegmentSize = EFI_PAGE_SIZE;
|
||||||
|
|
||||||
|
UT_ASSERT_TRUE (SeparateAndCheck (TestContext));
|
||||||
|
|
||||||
|
return UNIT_TEST_PASSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Test the case where all image ranges do not fit perfectly within an existing memory descriptor.
|
||||||
|
|
||||||
|
@param[in] Context Context containing the memory map and image record pointers
|
||||||
|
|
||||||
|
@retval UNIT_TEST_PASSED The Unit test has completed and the test
|
||||||
|
case was successful.
|
||||||
|
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
|
||||||
|
**/
|
||||||
|
UNIT_TEST_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ImagesDontFitDescriptors (
|
||||||
|
IN UNIT_TEST_CONTEXT Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image1;
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image2;
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image3;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage1;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage2;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage3;
|
||||||
|
IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *TestContext;
|
||||||
|
|
||||||
|
TestContext = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)Context;
|
||||||
|
|
||||||
|
Image1 = CR (TestContext->ImageList.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
Image2 = CR (Image1->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
Image3 = CR (Image2->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
|
||||||
|
CodeSectionInImage1 = CR (Image1->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
CodeSectionInImage2 = CR (Image2->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
CodeSectionInImage3 = CR (Image3->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Descriptor 1
|
||||||
|
///////////////
|
||||||
|
// | | | | |
|
||||||
|
// | 4K PAGE | DATA | CODE * 2 | DATA * 8 |
|
||||||
|
// | | | | |
|
||||||
|
|
||||||
|
Image1->ImageBase = BASE_DESCRIPTOR_START_ADDRESS (1) + EFI_PAGE_SIZE;
|
||||||
|
Image1->ImageSize = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE;
|
||||||
|
Image1->CodeSegmentCount = 1;
|
||||||
|
CodeSectionInImage1->CodeSegmentBase = Image1->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage1->CodeSegmentSize = EFI_PAGES_TO_SIZE (2);
|
||||||
|
TestContext->MemoryMap[1].Type = EfiBootServicesCode;
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Descriptor 3
|
||||||
|
///////////////
|
||||||
|
// | | | | |
|
||||||
|
// | DATA | CODE * 3 | DATA * 7 | 4K PAGE |
|
||||||
|
// | | | | |
|
||||||
|
|
||||||
|
Image2->ImageBase = BASE_DESCRIPTOR_START_ADDRESS (3);
|
||||||
|
Image2->ImageSize = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE;
|
||||||
|
Image2->CodeSegmentCount = 1;
|
||||||
|
CodeSectionInImage2->CodeSegmentBase = Image2->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage2->CodeSegmentSize = EFI_PAGES_TO_SIZE (3);
|
||||||
|
TestContext->MemoryMap[3].Type = EfiLoaderCode;
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Descriptor 4
|
||||||
|
///////////////
|
||||||
|
// | | | | | |
|
||||||
|
// | 4K PAGE | DATA | CODE * 2 | DATA * 7 | 4K PAGE |
|
||||||
|
// | | | | | |
|
||||||
|
|
||||||
|
Image3->ImageBase = BASE_DESCRIPTOR_START_ADDRESS (4) + EFI_PAGE_SIZE;
|
||||||
|
Image3->ImageSize = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE - EFI_PAGE_SIZE;
|
||||||
|
Image3->CodeSegmentCount = 1;
|
||||||
|
CodeSectionInImage3->CodeSegmentBase = Image3->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage3->CodeSegmentSize = EFI_PAGES_TO_SIZE (2);
|
||||||
|
TestContext->MemoryMap[4].Type = EfiRuntimeServicesCode;
|
||||||
|
|
||||||
|
UT_ASSERT_TRUE (SeparateAndCheck (TestContext));
|
||||||
|
|
||||||
|
return UNIT_TEST_PASSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Test the case where all image ranges fit perfectly within an existing memory descriptor.
|
||||||
|
|
||||||
|
@param[in] Context Context containing the memory map and image record pointers
|
||||||
|
|
||||||
|
@retval UNIT_TEST_PASSED The Unit test has completed and the test
|
||||||
|
case was successful.
|
||||||
|
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
|
||||||
|
**/
|
||||||
|
UNIT_TEST_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ImagesFitDescriptors (
|
||||||
|
IN UNIT_TEST_CONTEXT Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image1;
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image2;
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image3;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage1;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage2;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage3;
|
||||||
|
IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *TestContext;
|
||||||
|
|
||||||
|
TestContext = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)Context;
|
||||||
|
|
||||||
|
Image1 = CR (TestContext->ImageList.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
Image2 = CR (Image1->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
Image3 = CR (Image2->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
|
||||||
|
|
||||||
|
CodeSectionInImage1 = CR (Image1->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
CodeSectionInImage2 = CR (Image2->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
CodeSectionInImage3 = CR (Image3->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Descriptor 1
|
||||||
|
///////////////
|
||||||
|
// | | | |
|
||||||
|
// | DATA | CODE * 3 | DATA * 8 |
|
||||||
|
// | | | |
|
||||||
|
|
||||||
|
Image1->ImageBase = BASE_DESCRIPTOR_START_ADDRESS (1);
|
||||||
|
Image1->ImageSize = BASE_DESCRIPTOR_ENTRY_SIZE;
|
||||||
|
Image1->CodeSegmentCount = 1;
|
||||||
|
CodeSectionInImage1->CodeSegmentBase = Image1->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage1->CodeSegmentSize = EFI_PAGES_TO_SIZE (3);
|
||||||
|
TestContext->MemoryMap[1].Type = EfiBootServicesCode;
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Descriptor 2
|
||||||
|
///////////////
|
||||||
|
// | | | |
|
||||||
|
// | DATA | CODE * 4 | DATA * 7 |
|
||||||
|
// | | | |
|
||||||
|
|
||||||
|
Image2->ImageBase = BASE_DESCRIPTOR_START_ADDRESS (2);
|
||||||
|
Image2->ImageSize = BASE_DESCRIPTOR_ENTRY_SIZE;
|
||||||
|
Image2->CodeSegmentCount = 1;
|
||||||
|
CodeSectionInImage2->CodeSegmentBase = Image2->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage2->CodeSegmentSize = EFI_PAGES_TO_SIZE (4);
|
||||||
|
TestContext->MemoryMap[2].Type = EfiLoaderCode;
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Descriptor 3
|
||||||
|
///////////////
|
||||||
|
// | | | |
|
||||||
|
// | DATA | CODE * 3 | DATA * 8 |
|
||||||
|
// | | | |
|
||||||
|
|
||||||
|
Image3->ImageBase = BASE_DESCRIPTOR_START_ADDRESS (3);
|
||||||
|
Image3->ImageSize = BASE_DESCRIPTOR_ENTRY_SIZE;
|
||||||
|
Image3->CodeSegmentCount = 1;
|
||||||
|
CodeSectionInImage3->CodeSegmentBase = Image3->ImageBase + EFI_PAGE_SIZE;
|
||||||
|
CodeSectionInImage3->CodeSegmentSize = EFI_PAGES_TO_SIZE (3);
|
||||||
|
TestContext->MemoryMap[3].Type = EfiRuntimeServicesCode;
|
||||||
|
|
||||||
|
UT_ASSERT_TRUE (SeparateAndCheck (TestContext));
|
||||||
|
|
||||||
|
return UNIT_TEST_PASSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Free all allocated memory.
|
||||||
|
|
||||||
|
@param[in] Context Context containing the memory map and image record pointers
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
TestCleanup (
|
||||||
|
IN UNIT_TEST_CONTEXT Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IMAGE_PROPERTIES_RECORD *ImageRecord;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
|
||||||
|
LIST_ENTRY *ImageRecordLink;
|
||||||
|
LIST_ENTRY *CodeSegmentListHead;
|
||||||
|
IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *TestContext;
|
||||||
|
|
||||||
|
TestContext = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)Context;
|
||||||
|
ImageRecordLink = &TestContext->ImageList;
|
||||||
|
|
||||||
|
while (!IsListEmpty (ImageRecordLink)) {
|
||||||
|
ImageRecord = CR (
|
||||||
|
ImageRecordLink->ForwardLink,
|
||||||
|
IMAGE_PROPERTIES_RECORD,
|
||||||
|
Link,
|
||||||
|
IMAGE_PROPERTIES_RECORD_SIGNATURE
|
||||||
|
);
|
||||||
|
|
||||||
|
CodeSegmentListHead = &ImageRecord->CodeSegmentList;
|
||||||
|
while (!IsListEmpty (CodeSegmentListHead)) {
|
||||||
|
ImageRecordCodeSection = CR (
|
||||||
|
CodeSegmentListHead->ForwardLink,
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION,
|
||||||
|
Link,
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
|
||||||
|
);
|
||||||
|
RemoveEntryList (&ImageRecordCodeSection->Link);
|
||||||
|
FreePool (ImageRecordCodeSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveEntryList (&ImageRecord->Link);
|
||||||
|
FreePool (ImageRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TestContext->MemoryMap != NULL) {
|
||||||
|
FreePool (TestContext->MemoryMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a generic image list with the proper signatures which will be customized for each test
|
||||||
|
and allocate the default memory map.
|
||||||
|
|
||||||
|
@param[out] TestContext Context which will be passed to the test cases
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
CreateBaseContextEntry (
|
||||||
|
OUT IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *TestContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image1;
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image2;
|
||||||
|
IMAGE_PROPERTIES_RECORD *Image3;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage1;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage2;
|
||||||
|
IMAGE_PROPERTIES_RECORD_CODE_SECTION *CodeSectionInImage3;
|
||||||
|
|
||||||
|
InitializeListHead (&TestContext->ImageList);
|
||||||
|
|
||||||
|
Image1 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD));
|
||||||
|
CodeSectionInImage1 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
|
||||||
|
|
||||||
|
Image1->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;
|
||||||
|
CodeSectionInImage1->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
|
||||||
|
InitializeListHead (&Image1->CodeSegmentList);
|
||||||
|
|
||||||
|
InsertTailList (&TestContext->ImageList, &Image1->Link);
|
||||||
|
InsertTailList (&Image1->CodeSegmentList, &CodeSectionInImage1->Link);
|
||||||
|
|
||||||
|
Image2 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD));
|
||||||
|
CodeSectionInImage2 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
|
||||||
|
|
||||||
|
Image2->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;
|
||||||
|
CodeSectionInImage2->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
|
||||||
|
InitializeListHead (&Image2->CodeSegmentList);
|
||||||
|
|
||||||
|
InsertTailList (&TestContext->ImageList, &Image2->Link);
|
||||||
|
InsertTailList (&Image2->CodeSegmentList, &CodeSectionInImage2->Link);
|
||||||
|
|
||||||
|
Image3 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD));
|
||||||
|
CodeSectionInImage3 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
|
||||||
|
|
||||||
|
Image3->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;
|
||||||
|
CodeSectionInImage3->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
|
||||||
|
InitializeListHead (&Image3->CodeSegmentList);
|
||||||
|
|
||||||
|
InsertTailList (&TestContext->ImageList, &Image3->Link);
|
||||||
|
InsertTailList (&Image3->CodeSegmentList, &CodeSectionInImage3->Link);
|
||||||
|
|
||||||
|
TestContext->MemoryMap = AllocateZeroPool (SPLIT_MEMORY_MAP_SIZE);
|
||||||
|
CopyMem (TestContext->MemoryMap, &BaseMemoryMap, BASE_MEMORY_MAP_SIZE);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialze the unit test framework, suite, and unit tests.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS All test cases were dispatched.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to
|
||||||
|
initialize the unit tests.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
UnitTestingEntry (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UNIT_TEST_FRAMEWORK_HANDLE Framework;
|
||||||
|
UNIT_TEST_SUITE_HANDLE ImagePropertiesRecordTests;
|
||||||
|
IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *Context1;
|
||||||
|
IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *Context2;
|
||||||
|
IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *Context3;
|
||||||
|
IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *Context4;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION));
|
||||||
|
|
||||||
|
Framework = NULL;
|
||||||
|
|
||||||
|
Context1 = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT));
|
||||||
|
Context2 = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT));
|
||||||
|
Context3 = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT));
|
||||||
|
Context4 = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT));
|
||||||
|
|
||||||
|
CreateBaseContextEntry (Context1);
|
||||||
|
CreateBaseContextEntry (Context2);
|
||||||
|
CreateBaseContextEntry (Context3);
|
||||||
|
CreateBaseContextEntry (Context4);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Start setting up the test framework for running the tests.
|
||||||
|
//
|
||||||
|
Status = InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
|
||||||
|
goto EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Populate the Unit Test Suite.
|
||||||
|
//
|
||||||
|
Status = CreateUnitTestSuite (&ImagePropertiesRecordTests, Framework, "Image Properties Record Tests", "ImagePropertiesRecordLib.SplitTable", NULL, NULL);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Image Properties Record Tests\n"));
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// --------------Suite-----------Description--------------Name----------Function--------Pre---Post-------------------Context-----------
|
||||||
|
//
|
||||||
|
AddTestCase (ImagePropertiesRecordTests, "All images fit perfectly into existing descriptors", "ImagesFitDescriptors", ImagesFitDescriptors, NULL, TestCleanup, Context1);
|
||||||
|
AddTestCase (ImagePropertiesRecordTests, "All images don't fit perfectly into existing descriptors", "ImagesDontFitDescriptors", ImagesDontFitDescriptors, NULL, TestCleanup, Context2);
|
||||||
|
AddTestCase (ImagePropertiesRecordTests, "All Images are contined In single descriptor", "MultipleImagesInOneDescriptor", MultipleImagesInOneDescriptor, NULL, TestCleanup, Context3);
|
||||||
|
AddTestCase (ImagePropertiesRecordTests, "Multiple code sections each image", "MaxOutAdditionalDescriptors", MaxOutAdditionalDescriptors, NULL, TestCleanup, Context4);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Execute the tests.
|
||||||
|
//
|
||||||
|
Status = RunAllTestSuites (Framework);
|
||||||
|
|
||||||
|
EXIT:
|
||||||
|
if (Framework) {
|
||||||
|
FreeUnitTestFramework (Framework);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Avoid ECC error for function name that starts with lower case letter
|
||||||
|
///
|
||||||
|
#define ImagePropertiesRecordLibUnitTestMain main
|
||||||
|
|
||||||
|
/**
|
||||||
|
Standard POSIX C entry point for host based unit test execution.
|
||||||
|
|
||||||
|
@param[in] Argc Number of arguments
|
||||||
|
@param[in] Argv Array of pointers to arguments
|
||||||
|
|
||||||
|
@retval 0 Success
|
||||||
|
@retval other Error
|
||||||
|
**/
|
||||||
|
INT32
|
||||||
|
ImagePropertiesRecordLibUnitTestMain (
|
||||||
|
IN INT32 Argc,
|
||||||
|
IN CHAR8 *Argv[]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return UnitTestingEntry ();
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
## @file
|
||||||
|
# Unit tests the SplitTable() ImagePropertiesRecordLib Logic
|
||||||
|
#
|
||||||
|
# Copyright (C) Microsoft Corporation.
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010006
|
||||||
|
BASE_NAME = ImagePropertiesRecordLibUnitTestHost
|
||||||
|
FILE_GUID = 45B39FAA-E25D-4724-A6F4-93C0C8588A80
|
||||||
|
MODULE_TYPE = HOST_APPLICATION
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64 AARCH64
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
ImagePropertiesRecordLibUnitTestHost.c
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
BaseLib
|
||||||
|
BaseMemoryLib
|
||||||
|
DebugLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
UnitTestLib
|
||||||
|
ImagePropertiesRecordLib
|
|
@ -54,6 +54,11 @@
|
||||||
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
|
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.inf {
|
||||||
|
<LibraryClasses>
|
||||||
|
ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Build HOST_APPLICATION Libraries
|
# Build HOST_APPLICATION Libraries
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in New Issue