/** @file Copyright (c) 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #include #include CHAR8 * ShortNameOfMemoryType( IN UINT32 Type ); VOID TestPointDumpMemoryAttributesTable ( IN EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable ) { UINTN Index; EFI_MEMORY_DESCRIPTOR *Entry; UINT64 Pages[EfiMaxMemoryType]; ZeroMem (Pages, sizeof(Pages)); DEBUG ((DEBUG_INFO, "MemoryAttributesTable:")); DEBUG ((DEBUG_INFO, " Version=0x%x", MemoryAttributesTable->Version)); DEBUG ((DEBUG_INFO, " Count=0x%x", MemoryAttributesTable->NumberOfEntries)); DEBUG ((DEBUG_INFO, " DescriptorSize=0x%x\n", MemoryAttributesTable->DescriptorSize)); Entry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1); DEBUG ((DEBUG_INFO, "Type Start End # Pages Attributes\n")); for (Index = 0; Index < MemoryAttributesTable->NumberOfEntries; Index++) { DEBUG ((DEBUG_INFO, ShortNameOfMemoryType(Entry->Type))); DEBUG ((DEBUG_INFO, " %016LX-%016LX %016LX %016LX\n", Entry->PhysicalStart, Entry->PhysicalStart+MultU64x64 (SIZE_4KB,Entry->NumberOfPages) - 1, Entry->NumberOfPages, Entry->Attribute )); if (Entry->Type < EfiMaxMemoryType) { Pages[Entry->Type] += Entry->NumberOfPages; } Entry = NEXT_MEMORY_DESCRIPTOR (Entry, MemoryAttributesTable->DescriptorSize); } DEBUG ((DEBUG_INFO, "\n")); DEBUG ((DEBUG_INFO, " RT_Code : %14ld Pages (%ld Bytes)\n", Pages[EfiRuntimeServicesCode], MultU64x64(SIZE_4KB, Pages[EfiRuntimeServicesCode]))); DEBUG ((DEBUG_INFO, " RT_Data : %14ld Pages (%ld Bytes)\n", Pages[EfiRuntimeServicesData], MultU64x64(SIZE_4KB, Pages[EfiRuntimeServicesData]))); DEBUG ((DEBUG_INFO, " -------------- \n")); } EFI_STATUS TestPointCheckMemoryAttribute ( IN EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable, IN EFI_PHYSICAL_ADDRESS Base, IN UINT64 Size, IN BOOLEAN IsCode, IN BOOLEAN IsFromSmm ) { UINTN Index; EFI_MEMORY_DESCRIPTOR *Entry; DEBUG ((DEBUG_ERROR, "Attribute Checking 0x%lx - 0x%lx\n", Base, Size)); Entry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1); for (Index = 0; Index < MemoryAttributesTable->NumberOfEntries; Index++) { if (Base >= Entry->PhysicalStart && Base+Size <= Entry->PhysicalStart+MultU64x64 (SIZE_4KB,Entry->NumberOfPages)) { if (IsFromSmm) { if (IsCode) { if (Entry->Type != EfiRuntimeServicesCode) { DEBUG ((DEBUG_ERROR, "Invalid Entry->Type %d\n", Entry->Type)); return EFI_INVALID_PARAMETER; } if ((Entry->Attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP)) != EFI_MEMORY_RO) { DEBUG ((DEBUG_ERROR, "Invalid Code Entry->Attribute 0x%lx\n", Entry->Attribute)); return EFI_INVALID_PARAMETER; } } else { if (Entry->Type != EfiRuntimeServicesData) { DEBUG ((DEBUG_ERROR, "Invalid Entry->Type %d\n", Entry->Type)); return EFI_INVALID_PARAMETER; } if ((Entry->Attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP)) != EFI_MEMORY_XP) { DEBUG ((DEBUG_ERROR, "Invalid Data Entry->Attribute 0x%lx\n", Entry->Attribute)); return EFI_INVALID_PARAMETER; } } } else { if (Entry->Type != EfiRuntimeServicesCode) { DEBUG ((DEBUG_ERROR, "Invalid Entry->Type %d\n", Entry->Type)); return EFI_INVALID_PARAMETER; } if (IsCode) { if ((Entry->Attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP)) != EFI_MEMORY_RO) { DEBUG ((DEBUG_ERROR, "Invalid Code Entry->Attribute 0x%lx\n", Entry->Attribute)); return EFI_INVALID_PARAMETER; } } else { if ((Entry->Attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP)) != EFI_MEMORY_XP) { DEBUG ((DEBUG_ERROR, "Invalid Data Entry->Attribute 0x%lx\n", Entry->Attribute)); return EFI_INVALID_PARAMETER; } } } } } return EFI_SUCCESS; } EFI_STATUS TestPointCheckImageMemoryAttribute ( IN EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable, IN EFI_PHYSICAL_ADDRESS ImageBase, IN UINT64 ImageSize, IN BOOLEAN IsFromSmm ) { EFI_STATUS Status; EFI_STATUS ReturnStatus; VOID *ImageAddress; EFI_IMAGE_DOS_HEADER *DosHdr; UINT32 PeCoffHeaderOffset; UINT32 SectionAlignment; EFI_IMAGE_SECTION_HEADER *Section; EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; UINT8 *Name; UINTN Index; CHAR8 *PdbPointer; ReturnStatus = EFI_SUCCESS; // // Check whole region // ImageAddress = (VOID *)(UINTN)ImageBase; PdbPointer = PeCoffLoaderGetPdbPointer (ImageAddress); if (PdbPointer != NULL) { DEBUG ((EFI_D_INFO, " Image - %a\n", PdbPointer)); } // // Check PE/COFF image // DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress; PeCoffHeaderOffset = 0; if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { PeCoffHeaderOffset = DosHdr->e_lfanew; } Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset); if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) { DEBUG ((EFI_D_INFO, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature)); return EFI_INVALID_PARAMETER; } // // Measuring PE/COFF Image Header; // But CheckSum field and SECURITY data directory (certificate) are excluded // if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value // in the PE/COFF Header. // SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment; } else { // // Get the section alignment value from the PE/COFF Optional Header // SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment; } if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) { DEBUG ((EFI_D_INFO, "!!!!!!!! RecordImageMemoryMap - Section Alignment(0x%x) is not %dK !!!!!!!!\n", SectionAlignment, RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10)); PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress); if (PdbPointer != NULL) { DEBUG ((EFI_D_INFO, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer)); } return EFI_INVALID_PARAMETER; } Section = (EFI_IMAGE_SECTION_HEADER *) ( (UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER) + Hdr.Pe32->FileHeader.SizeOfOptionalHeader ); Status = TestPointCheckMemoryAttribute ( MemoryAttributesTable, (UINTN)ImageAddress, (UINTN)&Section[Hdr.Pe32->FileHeader.NumberOfSections] - (UINTN)ImageAddress, FALSE, IsFromSmm ); if (EFI_ERROR(Status)) { ReturnStatus = Status; } for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) { Name = Section[Index].Name; DEBUG (( EFI_D_INFO, " Section - '%c%c%c%c%c%c%c%c'\n", Name[0], Name[1], Name[2], Name[3], Name[4], Name[5], Name[6], Name[7] )); DEBUG ((EFI_D_INFO, " VirtualSize - 0x%08x\n", Section[Index].Misc.VirtualSize)); DEBUG ((EFI_D_INFO, " VirtualAddress - 0x%08x\n", Section[Index].VirtualAddress)); DEBUG ((EFI_D_INFO, " SizeOfRawData - 0x%08x\n", Section[Index].SizeOfRawData)); DEBUG ((EFI_D_INFO, " PointerToRawData - 0x%08x\n", Section[Index].PointerToRawData)); DEBUG ((EFI_D_INFO, " PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations)); DEBUG ((EFI_D_INFO, " PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers)); DEBUG ((EFI_D_INFO, " NumberOfRelocations - 0x%08x\n", Section[Index].NumberOfRelocations)); DEBUG ((EFI_D_INFO, " NumberOfLinenumbers - 0x%08x\n", Section[Index].NumberOfLinenumbers)); DEBUG ((EFI_D_INFO, " Characteristics - 0x%08x\n", Section[Index].Characteristics)); if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) { // // Check code section // Status = TestPointCheckMemoryAttribute ( MemoryAttributesTable, (UINTN)ImageAddress + Section[Index].VirtualAddress, Section[Index].SizeOfRawData, TRUE, IsFromSmm ); } else { // // Check data section // Status = TestPointCheckMemoryAttribute ( MemoryAttributesTable, (UINTN)ImageAddress + Section[Index].VirtualAddress, Section[Index].SizeOfRawData, FALSE, IsFromSmm ); } if (EFI_ERROR(Status)) { ReturnStatus = Status; } } return ReturnStatus; } EFI_STATUS TestPointCheckUefiMemoryAttributesTable ( IN EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable ) { EFI_STATUS Status; EFI_STATUS ReturnStatus; EFI_RUNTIME_ARCH_PROTOCOL *RuntimeArch; LIST_ENTRY *Link; EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage; Status = gBS->LocateProtocol ( &gEfiRuntimeArchProtocolGuid, NULL, (VOID **)&RuntimeArch ); if (EFI_ERROR (Status)) { return EFI_SUCCESS; } ReturnStatus = EFI_SUCCESS; for (Link = RuntimeArch->ImageHead.ForwardLink; Link != &(RuntimeArch->ImageHead); Link = Link->ForwardLink) { RuntimeImage = BASE_CR (Link, EFI_RUNTIME_IMAGE_ENTRY, Link); Status = TestPointCheckImageMemoryAttribute ( MemoryAttributesTable, (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize, FALSE ); if (EFI_ERROR(Status)) { ReturnStatus = Status; } } return ReturnStatus; } EFI_STATUS TestPointCheckUefiMemAttribute ( VOID ) { EFI_STATUS Status; VOID *MemoryAttributesTable; DEBUG ((DEBUG_INFO, "==== TestPointCheckUefiMemAttribute - Enter\n")); Status = EfiGetSystemConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable); if (!EFI_ERROR (Status)) { TestPointDumpMemoryAttributesTable(MemoryAttributesTable); Status = TestPointCheckUefiMemoryAttributesTable(MemoryAttributesTable); } if (EFI_ERROR (Status)) { TestPointLibAppendErrorString ( PLATFORM_TEST_POINT_ROLE_PLATFORM_IBV, NULL, TEST_POINT_BYTE4_READY_TO_BOOT_UEFI_MEMORY_ATTRIBUTE_TABLE_FUNCTIONAL_ERROR_CODE \ TEST_POINT_READY_TO_BOOT \ TEST_POINT_BYTE4_READY_TO_BOOT_UEFI_MEMORY_ATTRIBUTE_TABLE_FUNCTIONAL_ERROR_STRING ); } DEBUG ((DEBUG_INFO, "==== TestPointCheckUefiMemAttribute - Exit\n")); return Status; }