From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id AFDB5AC06F5 for ; Tue, 25 Jul 2023 01:35:34 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=3obgLafqa5RqMkmIazSHnnhYVfsWrgGY3sd2sTmBnmc=; c=relaxed/simple; d=groups.io; h=X-Received:X-Received:X-Received:X-Gm-Message-State:X-Google-Smtp-Source:X-Received:X-Received:From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20140610; t=1690248933; v=1; b=f6p0tpOOH68sTtiNDVWxaODxKZt2hQl/pBVNb6l2AH4gfNzU4e6EF4ds56bYeIdnOT3nF2ji ETpgEc1vX6gpAxemPg0BT8ZS7gdkl48uHdvy3p50jbntcp/GUoD4SdxB+IlKYxhW7oxQdtinZXR 4fyZqz7KO61KzjVK6Qm37kco= X-Received: by 127.0.0.2 with SMTP id G8HBYY7687511xDSBGeMsmj8; Mon, 24 Jul 2023 18:35:33 -0700 X-Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) by mx.groups.io with SMTP id smtpd.web10.11288.1690248930591987479 for ; Mon, 24 Jul 2023 18:35:30 -0700 X-Received: by mail-pl1-f178.google.com with SMTP id d9443c01a7336-1bb81809ca8so22229545ad.3 for ; Mon, 24 Jul 2023 18:35:30 -0700 (PDT) X-Gm-Message-State: 5zYloPL16G36SR8p9vux3mtIx7686176AA= X-Google-Smtp-Source: APBJJlGCod26pgalK2HKrJ17g+OedZxbizaGYCyHF8+oBelJQUxGro53l5tpvhOap6a5mMWZVTHTwQ== X-Received: by 2002:a17:902:988b:b0:1b2:fa8:d9c9 with SMTP id s11-20020a170902988b00b001b20fa8d9c9mr10942223plp.49.1690248929729; Mon, 24 Jul 2023 18:35:29 -0700 (PDT) X-Received: from localhost.localdomain ([50.46.230.135]) by smtp.gmail.com with ESMTPSA id f8-20020a170902ce8800b001b893b689a0sm9630868plg.84.2023.07.24.18.35.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jul 2023 18:35:29 -0700 (PDT) From: "Taylor Beebe" To: devel@edk2.groups.io Cc: Jian J Wang , Liming Gao , Dandan Bi Subject: [edk2-devel] [PATCH v3 07/14] MdeModulePkg: Move Some DXE MAT Logic to ImagePropertiesRecordLib Date: Mon, 24 Jul 2023 18:35:06 -0700 Message-ID: <20230725013513.1403-8-t@taylorbeebe.com> In-Reply-To: <20230725013513.1403-1-t@taylorbeebe.com> References: <20230725013513.1403-1-t@taylorbeebe.com> MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,t@taylorbeebe.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: Content-Transfer-Encoding: 8bit X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=f6p0tpOO; dmarc=none; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io Move some DXE MAT logic to ImagePropertiesRecordLib to consolidate code and enable unit testability. Signed-off-by: Taylor Beebe Cc: Jian J Wang Cc: Liming Gao Cc: Dandan Bi --- MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c | 774 +------------------- MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c | 24 +- MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c | 770 +++++++++++++++++++ MdeModulePkg/Core/Dxe/DxeMain.h | 20 - MdeModulePkg/Core/Dxe/DxeMain.inf | 1 + MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h | 133 ++++ MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf | 4 + 7 files changed, 921 insertions(+), 805 deletions(-) diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c index 64b0aa1ff5e5..51630f504ea1 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c @@ -14,6 +14,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include @@ -333,45 +334,6 @@ CoreInitializeMemoryAttributesTable ( // Below functions are for MemoryMap // -/** - Converts a number of EFI_PAGEs to a size in bytes. - - NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only. - - @param Pages The number of EFI_PAGES. - - @return The number of bytes associated with the number of EFI_PAGEs specified - by Pages. -**/ -STATIC -UINT64 -EfiPagesToSize ( - IN UINT64 Pages - ) -{ - return LShiftU64 (Pages, EFI_PAGE_SHIFT); -} - -/** - Converts a size, in bytes, to a number of EFI_PAGESs. - - NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only. - - @param Size A size in bytes. - - @return The number of EFI_PAGESs associated with the number of bytes specified - by Size. - -**/ -STATIC -UINT64 -EfiSizeToPages ( - IN UINT64 Size - ) -{ - return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0); -} - /** Acquire memory lock on mMemoryAttributesTableLock. **/ @@ -396,48 +358,6 @@ CoreReleasemMemoryAttributesTableLock ( CoreReleaseLock (&mMemoryAttributesTableLock); } -/** - Sort memory map entries based upon PhysicalStart, from low to high. - - @param MemoryMap A pointer to the buffer in which firmware places - the current memory map. - @param MemoryMapSize Size, in bytes, of the MemoryMap buffer. - @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. -**/ -STATIC -VOID -SortMemoryMap ( - IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, - IN UINTN MemoryMapSize, - IN UINTN DescriptorSize - ) -{ - EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; - EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry; - EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; - EFI_MEMORY_DESCRIPTOR TempMemoryMap; - - MemoryMapEntry = MemoryMap; - NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); - MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize); - while (MemoryMapEntry < MemoryMapEnd) { - while (NextMemoryMapEntry < MemoryMapEnd) { - if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) { - CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); - CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); - CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof (EFI_MEMORY_DESCRIPTOR)); - } - - NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize); - } - - MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); - NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); - } - - return; -} - /** Merge continous memory map entries whose have same attributes. @@ -471,7 +391,7 @@ MergeMemoryMap ( do { MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart); - MemoryBlockLength = (UINT64)(EfiPagesToSize (NewMemoryMapEntry->NumberOfPages)); + MemoryBlockLength = LShiftU64 (NewMemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT); if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) && (NewMemoryMapEntry->Type == NextMemoryMapEntry->Type) && (NewMemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) && @@ -538,434 +458,6 @@ EnforceMemoryMapAttribute ( return; } -/** - Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length]. - - @param Buffer Start Address - @param Length Address length - @param ImageRecordList Image record list - - @return first image record covered by [buffer, length] -**/ -STATIC -IMAGE_PROPERTIES_RECORD * -GetImageRecordByAddress ( - IN EFI_PHYSICAL_ADDRESS Buffer, - IN UINT64 Length, - IN LIST_ENTRY *ImageRecordList - ) -{ - IMAGE_PROPERTIES_RECORD *ImageRecord; - LIST_ENTRY *ImageRecordLink; - - for (ImageRecordLink = ImageRecordList->ForwardLink; - ImageRecordLink != ImageRecordList; - ImageRecordLink = ImageRecordLink->ForwardLink) - { - ImageRecord = CR ( - ImageRecordLink, - IMAGE_PROPERTIES_RECORD, - Link, - IMAGE_PROPERTIES_RECORD_SIGNATURE - ); - - if ((Buffer <= ImageRecord->ImageBase) && - (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize)) - { - return ImageRecord; - } - } - - return NULL; -} - -/** - Set the memory map to new entries, according to one old entry, - based upon PE code section and data section in image record - - @param ImageRecord An image record whose [ImageBase, ImageSize] covered - by old memory map entry. - @param NewRecord A pointer to several new memory map entries. - The caller gurantee the buffer size be 1 + - (SplitRecordCount * DescriptorSize) calculated - below. - @param OldRecord A pointer to one old memory map entry. - @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. -**/ -STATIC -UINTN -SetNewRecord ( - IN IMAGE_PROPERTIES_RECORD *ImageRecord, - IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord, - IN EFI_MEMORY_DESCRIPTOR *OldRecord, - IN UINTN DescriptorSize - ) -{ - EFI_MEMORY_DESCRIPTOR TempRecord; - IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; - LIST_ENTRY *ImageRecordCodeSectionLink; - LIST_ENTRY *ImageRecordCodeSectionEndLink; - LIST_ENTRY *ImageRecordCodeSectionList; - UINTN NewRecordCount; - UINT64 PhysicalEnd; - UINT64 ImageEnd; - - CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR)); - PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages); - NewRecordCount = 0; - - ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; - - ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; - ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; - while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { - ImageRecordCodeSection = CR ( - ImageRecordCodeSectionLink, - IMAGE_PROPERTIES_RECORD_CODE_SECTION, - Link, - IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE - ); - ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; - - if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) { - // - // DATA - // - NewRecord->Type = TempRecord.Type; - NewRecord->PhysicalStart = TempRecord.PhysicalStart; - NewRecord->VirtualStart = 0; - NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart); - NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; - if (NewRecord->NumberOfPages != 0) { - NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); - NewRecordCount++; - } - - // - // CODE - // - NewRecord->Type = TempRecord.Type; - NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase; - NewRecord->VirtualStart = 0; - NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize); - NewRecord->Attribute = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO; - if (NewRecord->NumberOfPages != 0) { - NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); - NewRecordCount++; - } - - TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize)); - TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - TempRecord.PhysicalStart); - if (TempRecord.NumberOfPages == 0) { - break; - } - } - } - - ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize; - - // - // Final DATA - // - if (TempRecord.PhysicalStart < ImageEnd) { - NewRecord->Type = TempRecord.Type; - NewRecord->PhysicalStart = TempRecord.PhysicalStart; - NewRecord->VirtualStart = 0; - NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart); - NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; - NewRecordCount++; - } - - return NewRecordCount; -} - -/** - Return the max number of new splitted entries, according to one old entry, - based upon PE code section and data section. - - @param OldRecord A pointer to one old memory map entry. - - @retval 0 no entry need to be splitted. - @return the max number of new splitted entries -**/ -STATIC -UINTN -GetMaxSplitRecordCount ( - IN EFI_MEMORY_DESCRIPTOR *OldRecord, - IN LIST_ENTRY *ImageRecordList - ) -{ - IMAGE_PROPERTIES_RECORD *ImageRecord; - UINTN SplitRecordCount; - UINT64 PhysicalStart; - UINT64 PhysicalEnd; - - SplitRecordCount = 0; - PhysicalStart = OldRecord->PhysicalStart; - PhysicalEnd = OldRecord->PhysicalStart + EfiPagesToSize (OldRecord->NumberOfPages); - - do { - ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList); - if (ImageRecord == NULL) { - break; - } - - SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1); - PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize; - } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd)); - - if (SplitRecordCount != 0) { - SplitRecordCount--; - } - - return SplitRecordCount; -} - -/** - Split the memory map to new entries, according to one old entry, - based upon PE code section and data section. - - @param OldRecord A pointer to one old memory map entry. - @param NewRecord A pointer to several new memory map entries. - The caller gurantee the buffer size be 1 + - (SplitRecordCount * DescriptorSize) calculated - below. - @param MaxSplitRecordCount The max number of splitted entries - @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. - @param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching - for an image record contained by the memory range described in - the existing EFI memory map descriptor OldRecord - - @retval 0 no entry is splitted. - @return the real number of splitted record. -**/ -STATIC -UINTN -SplitRecord ( - IN EFI_MEMORY_DESCRIPTOR *OldRecord, - IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord, - IN UINTN MaxSplitRecordCount, - IN UINTN DescriptorSize, - IN LIST_ENTRY *ImageRecordList - ) -{ - EFI_MEMORY_DESCRIPTOR TempRecord; - IMAGE_PROPERTIES_RECORD *ImageRecord; - IMAGE_PROPERTIES_RECORD *NewImageRecord; - UINT64 PhysicalStart; - UINT64 PhysicalEnd; - UINTN NewRecordCount; - UINTN TotalNewRecordCount; - BOOLEAN IsLastRecordData; - - if (MaxSplitRecordCount == 0) { - CopyMem (NewRecord, OldRecord, DescriptorSize); - return 0; - } - - TotalNewRecordCount = 0; - - // - // Override previous record - // - CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR)); - PhysicalStart = TempRecord.PhysicalStart; - PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages); - - ImageRecord = NULL; - do { - NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList); - if (NewImageRecord == NULL) { - // - // No more image covered by this range, stop - // - if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) { - // - // If this is still address in this record, need record. - // - NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); - IsLastRecordData = FALSE; - if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) { - IsLastRecordData = TRUE; - } - - if (IsLastRecordData) { - // - // Last record is DATA, just merge it. - // - NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - NewRecord->PhysicalStart); - } else { - // - // Last record is CODE, create a new DATA entry. - // - NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); - NewRecord->Type = TempRecord.Type; - NewRecord->PhysicalStart = TempRecord.PhysicalStart; - NewRecord->VirtualStart = 0; - NewRecord->NumberOfPages = TempRecord.NumberOfPages; - NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; - TotalNewRecordCount++; - } - } - - break; - } - - ImageRecord = NewImageRecord; - - // - // Set new record - // - NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize); - TotalNewRecordCount += NewRecordCount; - NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize); - - // - // Update PhysicalStart, in order to exclude the image buffer already splitted. - // - PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize; - TempRecord.PhysicalStart = PhysicalStart; - TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart); - } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd)); - - // - // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the - // code reaches here. - // - ASSERT (TotalNewRecordCount != 0); - return TotalNewRecordCount - 1; -} - -/** - Split the original memory map, and add more entries to describe PE code section and data section. - This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP. - This function will merge entries with same attributes finally. - - NOTE: It assumes PE code/data section are page aligned. - NOTE: It assumes enough entry is prepared for new memory map. - - Split table: - +---------------+ - | Record X | - +---------------+ - | Record RtCode | - +---------------+ - | Record Y | - +---------------+ - ==> - +---------------+ - | Record X | - +---------------+ ---- - | Record RtData | | - +---------------+ | - | Record RtCode | |-> PE/COFF1 - +---------------+ | - | Record RtData | | - +---------------+ ---- - | Record RtData | | - +---------------+ | - | Record RtCode | |-> PE/COFF2 - +---------------+ | - | Record RtData | | - +---------------+ ---- - | Record Y | - +---------------+ - - @param MemoryMapSize A pointer to the size, in bytes, of the - MemoryMap buffer. On input, this is the size of - old MemoryMap before split. The actual buffer - size of MemoryMap is MemoryMapSize + - (AdditionalRecordCount * DescriptorSize) calculated - below. On output, it is the size of new MemoryMap - after split. - @param MemoryMap A pointer to the buffer in which firmware places - the current memory map. - @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. - @param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching - for an image record contained by the memory range described in - EFI memory map descriptors. - @param NumberOfAdditionalDescriptors The number of unused descriptors at the end of the input MemoryMap. -**/ -STATIC -VOID -SplitTable ( - IN OUT UINTN *MemoryMapSize, - IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, - IN UINTN DescriptorSize, - IN LIST_ENTRY *ImageRecordList, - IN UINTN NumberOfAdditionalDescriptors - ) -{ - INTN IndexOld; - INTN IndexNew; - UINTN MaxSplitRecordCount; - UINTN RealSplitRecordCount; - UINTN TotalSplitRecordCount; - - TotalSplitRecordCount = 0; - // - // Let old record point to end of valid MemoryMap buffer. - // - IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1; - // - // Let new record point to end of full MemoryMap buffer. - // - IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + NumberOfAdditionalDescriptors; - for ( ; IndexOld >= 0; IndexOld--) { - MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), ImageRecordList); - // - // Split this MemoryMap record - // - IndexNew -= MaxSplitRecordCount; - RealSplitRecordCount = SplitRecord ( - (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), - (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize), - MaxSplitRecordCount, - DescriptorSize, - ImageRecordList - ); - // - // Adjust IndexNew according to real split. - // - CopyMem ( - ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize), - ((UINT8 *)MemoryMap + IndexNew * DescriptorSize), - RealSplitRecordCount * DescriptorSize - ); - IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount; - TotalSplitRecordCount += RealSplitRecordCount; - IndexNew--; - } - - // - // Move all records to the beginning. - // - CopyMem ( - MemoryMap, - (UINT8 *)MemoryMap + (NumberOfAdditionalDescriptors - TotalSplitRecordCount) * DescriptorSize, - (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize - ); - - *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount; - - // - // Sort from low to high (Just in case) - // - SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize); - - // - // Set RuntimeData to XP - // - EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, DescriptorSize); - - // - // Merge same type to save entry size - // - MergeMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize); - - return; -} - /** This function for GetMemoryMap() with properties table capability. @@ -1044,6 +536,16 @@ CoreGetMemoryMapWithSeparatedImageSection ( // Split PE code/data // SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize, &mImagePropertiesPrivateData.ImageRecordList, AdditionalRecordCount); + + // + // Set RuntimeData to XP + // + EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, *DescriptorSize); + + // + // Merge same type to save entry size + // + MergeMemoryMap (MemoryMap, MemoryMapSize, *DescriptorSize); } } @@ -1074,217 +576,6 @@ SetMemoryAttributesTableSectionAlignment ( } } -/** - Swap two code sections in image record. - - @param FirstImageRecordCodeSection first code section in image record - @param SecondImageRecordCodeSection second code section in image record -**/ -STATIC -VOID -SwapImageRecordCodeSection ( - IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection, - IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection - ) -{ - IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection; - - TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase; - TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize; - - FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase; - FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize; - - SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase; - SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize; -} - -/** - Sort code section in image record, based upon CodeSegmentBase from low to high. - - @param ImageRecord image record to be sorted -**/ -VOID -SortImageRecordCodeSection ( - IN IMAGE_PROPERTIES_RECORD *ImageRecord - ) -{ - IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; - IMAGE_PROPERTIES_RECORD_CODE_SECTION *NextImageRecordCodeSection; - LIST_ENTRY *ImageRecordCodeSectionLink; - LIST_ENTRY *NextImageRecordCodeSectionLink; - LIST_ENTRY *ImageRecordCodeSectionEndLink; - LIST_ENTRY *ImageRecordCodeSectionList; - - ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; - - ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; - NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; - ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; - while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { - ImageRecordCodeSection = CR ( - ImageRecordCodeSectionLink, - IMAGE_PROPERTIES_RECORD_CODE_SECTION, - Link, - IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE - ); - while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { - NextImageRecordCodeSection = CR ( - NextImageRecordCodeSectionLink, - IMAGE_PROPERTIES_RECORD_CODE_SECTION, - Link, - IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE - ); - if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) { - SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection); - } - - NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink; - } - - ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; - NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; - } -} - -/** - Check if code section in image record is valid. - - @param ImageRecord image record to be checked - - @retval TRUE image record is valid - @retval FALSE image record is invalid -**/ -BOOLEAN -IsImageRecordCodeSectionValid ( - IN IMAGE_PROPERTIES_RECORD *ImageRecord - ) -{ - IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; - IMAGE_PROPERTIES_RECORD_CODE_SECTION *LastImageRecordCodeSection; - LIST_ENTRY *ImageRecordCodeSectionLink; - LIST_ENTRY *ImageRecordCodeSectionEndLink; - LIST_ENTRY *ImageRecordCodeSectionList; - - DEBUG ((DEBUG_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount)); - - ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; - - ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; - ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; - LastImageRecordCodeSection = NULL; - while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { - ImageRecordCodeSection = CR ( - ImageRecordCodeSectionLink, - IMAGE_PROPERTIES_RECORD_CODE_SECTION, - Link, - IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE - ); - if (ImageRecordCodeSection->CodeSegmentSize == 0) { - return FALSE; - } - - if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) { - return FALSE; - } - - if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) { - return FALSE; - } - - if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) { - return FALSE; - } - - if (LastImageRecordCodeSection != NULL) { - if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) { - return FALSE; - } - } - - LastImageRecordCodeSection = ImageRecordCodeSection; - ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; - } - - return TRUE; -} - -/** - Swap two image records. - - @param FirstImageRecord first image record. - @param SecondImageRecord second image record. -**/ -STATIC -VOID -SwapImageRecord ( - IN IMAGE_PROPERTIES_RECORD *FirstImageRecord, - IN IMAGE_PROPERTIES_RECORD *SecondImageRecord - ) -{ - IMAGE_PROPERTIES_RECORD TempImageRecord; - - TempImageRecord.ImageBase = FirstImageRecord->ImageBase; - TempImageRecord.ImageSize = FirstImageRecord->ImageSize; - TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount; - - FirstImageRecord->ImageBase = SecondImageRecord->ImageBase; - FirstImageRecord->ImageSize = SecondImageRecord->ImageSize; - FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount; - - SecondImageRecord->ImageBase = TempImageRecord.ImageBase; - SecondImageRecord->ImageSize = TempImageRecord.ImageSize; - SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount; - - SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList); -} - -/** - Sort image record based upon the ImageBase from low to high. - - @param ImageRecordList Image record list to be sorted -**/ -STATIC -VOID -SortImageRecord ( - IN LIST_ENTRY *ImageRecordList - ) -{ - IMAGE_PROPERTIES_RECORD *ImageRecord; - IMAGE_PROPERTIES_RECORD *NextImageRecord; - LIST_ENTRY *ImageRecordLink; - LIST_ENTRY *NextImageRecordLink; - LIST_ENTRY *ImageRecordEndLink; - - ImageRecordLink = ImageRecordList->ForwardLink; - NextImageRecordLink = ImageRecordLink->ForwardLink; - ImageRecordEndLink = ImageRecordList; - while (ImageRecordLink != ImageRecordEndLink) { - ImageRecord = CR ( - ImageRecordLink, - IMAGE_PROPERTIES_RECORD, - Link, - IMAGE_PROPERTIES_RECORD_SIGNATURE - ); - while (NextImageRecordLink != ImageRecordEndLink) { - NextImageRecord = CR ( - NextImageRecordLink, - IMAGE_PROPERTIES_RECORD, - Link, - IMAGE_PROPERTIES_RECORD_SIGNATURE - ); - if (ImageRecord->ImageBase > NextImageRecord->ImageBase) { - SwapImageRecord (ImageRecord, NextImageRecord); - } - - NextImageRecordLink = NextImageRecordLink->ForwardLink; - } - - ImageRecordLink = ImageRecordLink->ForwardLink; - NextImageRecordLink = ImageRecordLink->ForwardLink; - } -} - /** Insert image record. @@ -1469,47 +760,6 @@ Finish: return; } -/** - Find image record according to image base and size. - - @param ImageBase Base of PE image - @param ImageSize Size of PE image - @param ImageRecordList Image record list to be searched - - @return image record -**/ -STATIC -IMAGE_PROPERTIES_RECORD * -FindImageRecord ( - IN EFI_PHYSICAL_ADDRESS ImageBase, - IN UINT64 ImageSize, - IN LIST_ENTRY *ImageRecordList - ) -{ - IMAGE_PROPERTIES_RECORD *ImageRecord; - LIST_ENTRY *ImageRecordLink; - - for (ImageRecordLink = ImageRecordList->ForwardLink; - ImageRecordLink != ImageRecordList; - ImageRecordLink = ImageRecordLink->ForwardLink) - { - ImageRecord = CR ( - ImageRecordLink, - IMAGE_PROPERTIES_RECORD, - Link, - IMAGE_PROPERTIES_RECORD_SIGNATURE - ); - - if ((ImageBase == ImageRecord->ImageBase) && - (ImageSize == ImageRecord->ImageSize)) - { - return ImageRecord; - } - } - - return NULL; -} - /** Remove Image record. diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c index 7cc829b17402..977239d08afc 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c @@ -32,6 +32,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include @@ -66,29 +67,6 @@ extern LIST_ENTRY mGcdMemorySpaceMap; STATIC LIST_ENTRY mProtectedImageRecordList; -/** - Sort code section in image record, based upon CodeSegmentBase from low to high. - - @param ImageRecord image record to be sorted -**/ -VOID -SortImageRecordCodeSection ( - IN IMAGE_PROPERTIES_RECORD *ImageRecord - ); - -/** - Check if code section in image record is valid. - - @param ImageRecord image record to be checked - - @retval TRUE image record is valid - @retval FALSE image record is invalid -**/ -BOOLEAN -IsImageRecordCodeSectionValid ( - IN IMAGE_PROPERTIES_RECORD *ImageRecord - ); - /** Get the image type. diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c index df7c54ebb793..d942c7fef19a 100644 --- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c +++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c @@ -7,3 +7,773 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ + +#include + +#include +#include +#include +#include + +#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \ + ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size))) + +#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \ + ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size))) + +/** + Converts a number of EFI_PAGEs to a size in bytes. + + NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only. + + @param Pages The number of EFI_PAGES. + + @return The number of bytes associated with the number of EFI_PAGEs specified + by Pages. +**/ +STATIC +UINT64 +EfiPagesToSize ( + IN UINT64 Pages + ) +{ + return LShiftU64 (Pages, EFI_PAGE_SHIFT); +} + +/** + Converts a size, in bytes, to a number of EFI_PAGESs. + + NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only. + + @param Size A size in bytes. + + @return The number of EFI_PAGESs associated with the number of bytes specified + by Size. + +**/ +STATIC +UINT64 +EfiSizeToPages ( + IN UINT64 Size + ) +{ + return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0); +} + +/** + Sort memory map entries based upon PhysicalStart, from low to high. + + @param MemoryMap A pointer to the buffer in which firmware places + the current memory map. + @param MemoryMapSize Size, in bytes, of the MemoryMap buffer. + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. +**/ +STATIC +VOID +SortMemoryMap ( + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize + ) +{ + EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; + EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry; + EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; + EFI_MEMORY_DESCRIPTOR TempMemoryMap; + + MemoryMapEntry = MemoryMap; + NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); + MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize); + while (MemoryMapEntry < MemoryMapEnd) { + while (NextMemoryMapEntry < MemoryMapEnd) { + if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) { + CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); + CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); + CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof (EFI_MEMORY_DESCRIPTOR)); + } + + NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize); + } + + MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); + NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); + } + + return; +} + +/** + Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length]. + + @param Buffer Start Address + @param Length Address length + @param ImageRecordList Image record list + + @return first image record covered by [buffer, length] +**/ +STATIC +IMAGE_PROPERTIES_RECORD * +GetImageRecordByAddress ( + IN EFI_PHYSICAL_ADDRESS Buffer, + IN UINT64 Length, + IN LIST_ENTRY *ImageRecordList + ) +{ + IMAGE_PROPERTIES_RECORD *ImageRecord; + LIST_ENTRY *ImageRecordLink; + + for (ImageRecordLink = ImageRecordList->ForwardLink; + ImageRecordLink != ImageRecordList; + ImageRecordLink = ImageRecordLink->ForwardLink) + { + ImageRecord = CR ( + ImageRecordLink, + IMAGE_PROPERTIES_RECORD, + Link, + IMAGE_PROPERTIES_RECORD_SIGNATURE + ); + + if ((Buffer <= ImageRecord->ImageBase) && + (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize)) + { + return ImageRecord; + } + } + + return NULL; +} + +/** + Set the memory map to new entries, according to one old entry, + based upon PE code section and data section in image record + + @param ImageRecord An image record whose [ImageBase, ImageSize] covered + by old memory map entry. + @param NewRecord A pointer to several new memory map entries. + The caller gurantee the buffer size be 1 + + (SplitRecordCount * DescriptorSize) calculated + below. + @param OldRecord A pointer to one old memory map entry. + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. +**/ +STATIC +UINTN +SetNewRecord ( + IN IMAGE_PROPERTIES_RECORD *ImageRecord, + IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord, + IN EFI_MEMORY_DESCRIPTOR *OldRecord, + IN UINTN DescriptorSize + ) +{ + EFI_MEMORY_DESCRIPTOR TempRecord; + IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; + LIST_ENTRY *ImageRecordCodeSectionLink; + LIST_ENTRY *ImageRecordCodeSectionEndLink; + LIST_ENTRY *ImageRecordCodeSectionList; + UINTN NewRecordCount; + UINT64 PhysicalEnd; + UINT64 ImageEnd; + + CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR)); + PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages); + NewRecordCount = 0; + + ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; + + ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; + ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; + while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { + ImageRecordCodeSection = CR ( + ImageRecordCodeSectionLink, + IMAGE_PROPERTIES_RECORD_CODE_SECTION, + Link, + IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE + ); + ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; + + if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) { + // + // DATA + // + NewRecord->Type = TempRecord.Type; + NewRecord->PhysicalStart = TempRecord.PhysicalStart; + NewRecord->VirtualStart = 0; + NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart); + NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; + if (NewRecord->NumberOfPages != 0) { + NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); + NewRecordCount++; + } + + // + // CODE + // + NewRecord->Type = TempRecord.Type; + NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase; + NewRecord->VirtualStart = 0; + NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize); + NewRecord->Attribute = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO; + if (NewRecord->NumberOfPages != 0) { + NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); + NewRecordCount++; + } + + TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize)); + TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - TempRecord.PhysicalStart); + if (TempRecord.NumberOfPages == 0) { + break; + } + } + } + + ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize; + + // + // Final DATA + // + if (TempRecord.PhysicalStart < ImageEnd) { + NewRecord->Type = TempRecord.Type; + NewRecord->PhysicalStart = TempRecord.PhysicalStart; + NewRecord->VirtualStart = 0; + NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart); + NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; + NewRecordCount++; + } + + return NewRecordCount; +} + +/** + Return the max number of new splitted entries, according to one old entry, + based upon PE code section and data section. + + @param OldRecord A pointer to one old memory map entry. + @param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching + for an image record contained by the memory range described in + the existing EFI memory map descriptor OldRecord + + @retval 0 no entry need to be splitted. + @return the max number of new splitted entries +**/ +STATIC +UINTN +GetMaxSplitRecordCount ( + IN EFI_MEMORY_DESCRIPTOR *OldRecord, + IN LIST_ENTRY *ImageRecordList + ) +{ + IMAGE_PROPERTIES_RECORD *ImageRecord; + UINTN SplitRecordCount; + UINT64 PhysicalStart; + UINT64 PhysicalEnd; + + SplitRecordCount = 0; + PhysicalStart = OldRecord->PhysicalStart; + PhysicalEnd = OldRecord->PhysicalStart + EfiPagesToSize (OldRecord->NumberOfPages); + + do { + ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList); + if (ImageRecord == NULL) { + break; + } + + SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1); + PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize; + } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd)); + + if (SplitRecordCount != 0) { + SplitRecordCount--; + } + + return SplitRecordCount; +} + +/** + Split the memory map to new entries, according to one old entry, + based upon PE code section and data section. + + @param OldRecord A pointer to one old memory map entry. + @param NewRecord A pointer to several new memory map entries. + The caller gurantee the buffer size be 1 + + (SplitRecordCount * DescriptorSize) calculated + below. + @param MaxSplitRecordCount The max number of splitted entries + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. + @param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching + for an image record contained by the memory range described in + the existing EFI memory map descriptor OldRecord + + @retval 0 no entry is splitted. + @return the real number of splitted record. +**/ +STATIC +UINTN +SplitRecord ( + IN EFI_MEMORY_DESCRIPTOR *OldRecord, + IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord, + IN UINTN MaxSplitRecordCount, + IN UINTN DescriptorSize, + IN LIST_ENTRY *ImageRecordList + ) +{ + EFI_MEMORY_DESCRIPTOR TempRecord; + IMAGE_PROPERTIES_RECORD *ImageRecord; + IMAGE_PROPERTIES_RECORD *NewImageRecord; + UINT64 PhysicalStart; + UINT64 PhysicalEnd; + UINTN NewRecordCount; + UINTN TotalNewRecordCount; + BOOLEAN IsLastRecordData; + + if (MaxSplitRecordCount == 0) { + CopyMem (NewRecord, OldRecord, DescriptorSize); + return 0; + } + + TotalNewRecordCount = 0; + + // + // Override previous record + // + CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR)); + PhysicalStart = TempRecord.PhysicalStart; + PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages); + + ImageRecord = NULL; + do { + NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList); + if (NewImageRecord == NULL) { + // + // No more image covered by this range, stop + // + if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) { + // + // If this is still address in this record, need record. + // + NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); + IsLastRecordData = FALSE; + if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) { + IsLastRecordData = TRUE; + } + + if (IsLastRecordData) { + // + // Last record is DATA, just merge it. + // + NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - NewRecord->PhysicalStart); + } else { + // + // Last record is CODE, create a new DATA entry. + // + NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); + NewRecord->Type = TempRecord.Type; + NewRecord->PhysicalStart = TempRecord.PhysicalStart; + NewRecord->VirtualStart = 0; + NewRecord->NumberOfPages = TempRecord.NumberOfPages; + NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; + TotalNewRecordCount++; + } + } + + break; + } + + ImageRecord = NewImageRecord; + + // + // Set new record + // + NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize); + TotalNewRecordCount += NewRecordCount; + NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize); + + // + // Update PhysicalStart, in order to exclude the image buffer already splitted. + // + PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize; + TempRecord.PhysicalStart = PhysicalStart; + TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart); + } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd)); + + // + // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the + // code reaches here. + // + ASSERT (TotalNewRecordCount != 0); + return TotalNewRecordCount - 1; +} + +/** + Split the original memory map, and add more entries to describe PE code section and data section. + This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP. + This function will merge entries with same attributes finally. + + NOTE: It assumes PE code/data section are page aligned. + NOTE: It assumes enough entry is prepared for new memory map. + + Split table: + +---------------+ + | Record X | + +---------------+ + | Record RtCode | + +---------------+ + | Record Y | + +---------------+ + ==> + +---------------+ + | Record X | + +---------------+ ---- + | Record RtData | | + +---------------+ | + | Record RtCode | |-> PE/COFF1 + +---------------+ | + | Record RtData | | + +---------------+ ---- + | Record RtData | | + +---------------+ | + | Record RtCode | |-> PE/COFF2 + +---------------+ | + | Record RtData | | + +---------------+ ---- + | Record Y | + +---------------+ + + @param MemoryMapSize A pointer to the size, in bytes, of the + MemoryMap buffer. On input, this is the size of + old MemoryMap before split. The actual buffer + size of MemoryMap is MemoryMapSize + + (AdditionalRecordCount * DescriptorSize) calculated + below. On output, it is the size of new MemoryMap + after split. + @param MemoryMap A pointer to the buffer in which firmware places + the current memory map. + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. + @param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching + for an image record contained by the memory range described in + EFI memory map descriptors. + @param NumberOfAdditionalDescriptors The number of unused descriptors at the end of the input MemoryMap. +**/ +VOID +EFIAPI +SplitTable ( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + IN UINTN DescriptorSize, + IN LIST_ENTRY *ImageRecordList, + IN UINTN NumberOfAdditionalDescriptors + ) +{ + INTN IndexOld; + INTN IndexNew; + UINTN MaxSplitRecordCount; + UINTN RealSplitRecordCount; + UINTN TotalSplitRecordCount; + + TotalSplitRecordCount = 0; + // + // Let old record point to end of valid MemoryMap buffer. + // + IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1; + // + // Let new record point to end of full MemoryMap buffer. + // + IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + NumberOfAdditionalDescriptors; + for ( ; IndexOld >= 0; IndexOld--) { + MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), ImageRecordList); + // + // Split this MemoryMap record + // + IndexNew -= MaxSplitRecordCount; + RealSplitRecordCount = SplitRecord ( + (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), + (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize), + MaxSplitRecordCount, + DescriptorSize, + ImageRecordList + ); + // + // Adjust IndexNew according to real split. + // + CopyMem ( + ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize), + ((UINT8 *)MemoryMap + IndexNew * DescriptorSize), + RealSplitRecordCount * DescriptorSize + ); + IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount; + TotalSplitRecordCount += RealSplitRecordCount; + IndexNew--; + } + + // + // Move all records to the beginning. + // + CopyMem ( + MemoryMap, + (UINT8 *)MemoryMap + (NumberOfAdditionalDescriptors - TotalSplitRecordCount) * DescriptorSize, + (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize + ); + + *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount; + + // + // Sort from low to high (Just in case) + // + SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize); + + return; +} + +/** + Swap two code sections in image record. + + @param FirstImageRecordCodeSection first code section in image record + @param SecondImageRecordCodeSection second code section in image record +**/ +STATIC +VOID +SwapImageRecordCodeSection ( + IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection, + IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection + ) +{ + IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection; + + TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase; + TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize; + + FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase; + FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize; + + SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase; + SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize; +} + +/** + Sort code section in image record, based upon CodeSegmentBase from low to high. + + @param ImageRecord image record to be sorted +**/ +VOID +EFIAPI +SortImageRecordCodeSection ( + IN IMAGE_PROPERTIES_RECORD *ImageRecord + ) +{ + IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; + IMAGE_PROPERTIES_RECORD_CODE_SECTION *NextImageRecordCodeSection; + LIST_ENTRY *ImageRecordCodeSectionLink; + LIST_ENTRY *NextImageRecordCodeSectionLink; + LIST_ENTRY *ImageRecordCodeSectionEndLink; + LIST_ENTRY *ImageRecordCodeSectionList; + + ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; + + ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; + NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; + ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; + while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { + ImageRecordCodeSection = CR ( + ImageRecordCodeSectionLink, + IMAGE_PROPERTIES_RECORD_CODE_SECTION, + Link, + IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE + ); + while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { + NextImageRecordCodeSection = CR ( + NextImageRecordCodeSectionLink, + IMAGE_PROPERTIES_RECORD_CODE_SECTION, + Link, + IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE + ); + if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) { + SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection); + } + + NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink; + } + + ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; + NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; + } +} + +/** + Check if code section in image record is valid. + + @param ImageRecord image record to be checked + + @retval TRUE image record is valid + @retval FALSE image record is invalid +**/ +BOOLEAN +EFIAPI +IsImageRecordCodeSectionValid ( + IN IMAGE_PROPERTIES_RECORD *ImageRecord + ) +{ + IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; + IMAGE_PROPERTIES_RECORD_CODE_SECTION *LastImageRecordCodeSection; + LIST_ENTRY *ImageRecordCodeSectionLink; + LIST_ENTRY *ImageRecordCodeSectionEndLink; + LIST_ENTRY *ImageRecordCodeSectionList; + + DEBUG ((DEBUG_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount)); + + ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; + + ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; + ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; + LastImageRecordCodeSection = NULL; + while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { + ImageRecordCodeSection = CR ( + ImageRecordCodeSectionLink, + IMAGE_PROPERTIES_RECORD_CODE_SECTION, + Link, + IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE + ); + if (ImageRecordCodeSection->CodeSegmentSize == 0) { + return FALSE; + } + + if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) { + return FALSE; + } + + if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) { + return FALSE; + } + + if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) { + return FALSE; + } + + if (LastImageRecordCodeSection != NULL) { + if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) { + return FALSE; + } + } + + LastImageRecordCodeSection = ImageRecordCodeSection; + ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; + } + + return TRUE; +} + +/** + Swap two image records. + + @param FirstImageRecord first image record. + @param SecondImageRecord second image record. +**/ +STATIC +VOID +SwapImageRecord ( + IN IMAGE_PROPERTIES_RECORD *FirstImageRecord, + IN IMAGE_PROPERTIES_RECORD *SecondImageRecord + ) +{ + IMAGE_PROPERTIES_RECORD TempImageRecord; + + TempImageRecord.ImageBase = FirstImageRecord->ImageBase; + TempImageRecord.ImageSize = FirstImageRecord->ImageSize; + TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount; + + FirstImageRecord->ImageBase = SecondImageRecord->ImageBase; + FirstImageRecord->ImageSize = SecondImageRecord->ImageSize; + FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount; + + SecondImageRecord->ImageBase = TempImageRecord.ImageBase; + SecondImageRecord->ImageSize = TempImageRecord.ImageSize; + SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount; + + SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList); +} + +/** + Sort image record based upon the ImageBase from low to high. + + @param ImageRecordList Image record list to be sorted +**/ +VOID +EFIAPI +SortImageRecord ( + IN LIST_ENTRY *ImageRecordList + ) +{ + IMAGE_PROPERTIES_RECORD *ImageRecord; + IMAGE_PROPERTIES_RECORD *NextImageRecord; + LIST_ENTRY *ImageRecordLink; + LIST_ENTRY *NextImageRecordLink; + LIST_ENTRY *ImageRecordEndLink; + + ImageRecordLink = ImageRecordList->ForwardLink; + NextImageRecordLink = ImageRecordLink->ForwardLink; + ImageRecordEndLink = ImageRecordList; + while (ImageRecordLink != ImageRecordEndLink) { + ImageRecord = CR ( + ImageRecordLink, + IMAGE_PROPERTIES_RECORD, + Link, + IMAGE_PROPERTIES_RECORD_SIGNATURE + ); + while (NextImageRecordLink != ImageRecordEndLink) { + NextImageRecord = CR ( + NextImageRecordLink, + IMAGE_PROPERTIES_RECORD, + Link, + IMAGE_PROPERTIES_RECORD_SIGNATURE + + ); + if (ImageRecord->ImageBase > NextImageRecord->ImageBase) { + SwapImageRecord (ImageRecord, NextImageRecord); + } + + NextImageRecordLink = NextImageRecordLink->ForwardLink; + } + + ImageRecordLink = ImageRecordLink->ForwardLink; + NextImageRecordLink = ImageRecordLink->ForwardLink; + } +} + +/** + Find image record according to image base and size. + + @param ImageBase Base of PE image + @param ImageSize Size of PE image + @param ImageRecordList Image record list to be searched + + @return image record +**/ +IMAGE_PROPERTIES_RECORD * +EFIAPI +FindImageRecord ( + IN EFI_PHYSICAL_ADDRESS ImageBase, + IN UINT64 ImageSize, + IN LIST_ENTRY *ImageRecordList + ) +{ + IMAGE_PROPERTIES_RECORD *ImageRecord; + LIST_ENTRY *ImageRecordLink; + + for (ImageRecordLink = ImageRecordList->ForwardLink; + ImageRecordLink != ImageRecordList; + ImageRecordLink = ImageRecordLink->ForwardLink) + { + ImageRecord = CR ( + ImageRecordLink, + IMAGE_PROPERTIES_RECORD, + Link, + IMAGE_PROPERTIES_RECORD_SIGNATURE + ); + + if ((ImageBase == ImageRecord->ImageBase) && + (ImageSize == ImageRecord->ImageSize)) + { + return ImageRecord; + } + } + + return NULL; +} diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index 43daa037be44..86a7be2f5188 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -228,26 +228,6 @@ typedef struct { #define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \ CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE) -#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C') - -typedef struct { - UINT32 Signature; - LIST_ENTRY Link; - EFI_PHYSICAL_ADDRESS CodeSegmentBase; - UINT64 CodeSegmentSize; -} IMAGE_PROPERTIES_RECORD_CODE_SECTION; - -#define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D') - -typedef struct { - UINT32 Signature; - LIST_ENTRY Link; - EFI_PHYSICAL_ADDRESS ImageBase; - UINT64 ImageSize; - UINTN CodeSegmentCount; - LIST_ENTRY CodeSegmentList; -} IMAGE_PROPERTIES_RECORD; - // // DXE Core Global Variables // diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index 35d5bf0dee6f..c0aa37d118c5 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -94,6 +94,7 @@ [LibraryClasses] DebugAgentLib CpuExceptionHandlerLib PcdLib + ImagePropertiesRecordLib [Guids] gEfiEventMemoryMapChangeGuid ## PRODUCES ## Event diff --git a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h index 728008a2e5bb..7321d99ef51b 100644 --- a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h +++ b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h @@ -11,4 +11,137 @@ #ifndef IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_ #define IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_ +#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C') + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + EFI_PHYSICAL_ADDRESS CodeSegmentBase; + UINT64 CodeSegmentSize; +} IMAGE_PROPERTIES_RECORD_CODE_SECTION; + +#define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D') + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + EFI_PHYSICAL_ADDRESS ImageBase; + UINT64 ImageSize; + UINTN CodeSegmentCount; + LIST_ENTRY CodeSegmentList; +} IMAGE_PROPERTIES_RECORD; + +/** + Split the original memory map, and add more entries to describe PE code section and data section. + This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP. + This function will merge entries with same attributes finally. + + NOTE: It assumes PE code/data section are page aligned. + NOTE: It assumes enough entry is prepared for new memory map. + + Split table: + +---------------+ + | Record X | + +---------------+ + | Record RtCode | + +---------------+ + | Record Y | + +---------------+ + ==> + +---------------+ + | Record X | + +---------------+ ---- + | Record RtData | | + +---------------+ | + | Record RtCode | |-> PE/COFF1 + +---------------+ | + | Record RtData | | + +---------------+ ---- + | Record RtData | | + +---------------+ | + | Record RtCode | |-> PE/COFF2 + +---------------+ | + | Record RtData | | + +---------------+ ---- + | Record Y | + +---------------+ + + @param MemoryMapSize A pointer to the size, in bytes, of the + MemoryMap buffer. On input, this is the size of + old MemoryMap before split. The actual buffer + size of MemoryMap is MemoryMapSize + + (AdditionalRecordCount * DescriptorSize) calculated + below. On output, it is the size of new MemoryMap + after split. + @param MemoryMap A pointer to the buffer in which firmware places + the current memory map. + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. + @param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching + for an image record contained by the memory range described in + EFI memory map descriptors. + @param NumberOfAdditionalDescriptors The number of unused descriptors at the end of the input MemoryMap. +**/ +VOID +EFIAPI +SplitTable ( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + IN UINTN DescriptorSize, + IN LIST_ENTRY *ImageRecordList, + IN UINTN NumberOfAdditionalDescriptors + ); + +/** + Sort code section in image record, based upon CodeSegmentBase from low to high. + + @param ImageRecord image record to be sorted +**/ +VOID +EFIAPI +SortImageRecordCodeSection ( + IN IMAGE_PROPERTIES_RECORD *ImageRecord + ); + +/** + Check if code section in image record is valid. + + @param ImageRecord image record to be checked + + @retval TRUE image record is valid + @retval FALSE image record is invalid +**/ +BOOLEAN +EFIAPI +IsImageRecordCodeSectionValid ( + IN IMAGE_PROPERTIES_RECORD *ImageRecord + ); + +/** + Sort image record based upon the ImageBase from low to high. + + @param ImageRecordList Image record list to be sorted +**/ +VOID +EFIAPI +SortImageRecord ( + IN LIST_ENTRY *ImageRecordList + ); + +/** + Find image record according to image base and size. + + @param ImageBase Base of PE image + @param ImageSize Size of PE image + @param ImageRecordList Image record list to be searched + + @return image record +**/ +IMAGE_PROPERTIES_RECORD * +EFIAPI +FindImageRecord ( + IN EFI_PHYSICAL_ADDRESS ImageBase, + IN UINT64 ImageSize, + IN LIST_ENTRY *ImageRecordList + ); + #endif diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf index b7e493056889..4c1466fc3336 100644 --- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf +++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf @@ -19,6 +19,10 @@ [Defines] [Sources.common] ImagePropertiesRecordLib.c +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib [Packages] MdePkg/MdePkg.dec -- 2.41.0.windows.2 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#107204): https://edk2.groups.io/g/devel/message/107204 Mute This Topic: https://groups.io/mt/100342603/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-