X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FCore%2FPiSmmCore%2FDispatcher.c;h=f32bbbd1b4b3da6abaadb2c504ef963039ce330e;hp=1f85ae8def6165ccbf9c88d89c06c7c2ea40b49e;hb=322d827c0f41efe14387ee67834ddced09f95c9c;hpb=0b256fb1dd7ca267d6e448768e519f54f97f347a diff --git a/MdeModulePkg/Core/PiSmmCore/Dispatcher.c b/MdeModulePkg/Core/PiSmmCore/Dispatcher.c index 1f85ae8def..f32bbbd1b4 100644 --- a/MdeModulePkg/Core/PiSmmCore/Dispatcher.c +++ b/MdeModulePkg/Core/PiSmmCore/Dispatcher.c @@ -28,7 +28,7 @@ Depex - Dependency Expresion. Copyright (c) 2014, Hewlett-Packard Development Company, L.P. - Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -126,17 +126,17 @@ EFI_SECURITY2_ARCH_PROTOCOL *mSecurity2 = NULL; // // The global variable is defined for Loading modules at fixed address feature to track the SMM code -// memory range usage. It is a bit mapped array in which every bit indicates the correspoding +// memory range usage. It is a bit mapped array in which every bit indicates the corresponding // memory page available or not. // GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mSmmCodeMemoryRangeUsageBitMap=NULL; /** - To check memory usage bit map array to figure out if the memory range in which the image will be loaded is available or not. If - memory range is avaliable, the function will mark the correponding bits to 1 which indicates the memory range is used. + To check memory usage bit map array to figure out if the memory range in which the image will be loaded is available or not. If + memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used. The function is only invoked when load modules at fixed address feature is enabled. - @param ImageBase The base addres the image will be loaded at. + @param ImageBase The base address the image will be loaded at. @param ImageSize The size of the image @retval EFI_SUCCESS The memory range the image will be loaded in is available @@ -183,8 +183,8 @@ CheckAndMarkFixLoadingMemoryUsageBitMap ( // // Test if the memory is avalaible or not. // - BaseOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase - SmmCodeBase)); - TopOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - SmmCodeBase)); + BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - SmmCodeBase)); + TopOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - SmmCodeBase)); for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) { if ((mSmmCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) { // @@ -203,13 +203,13 @@ CheckAndMarkFixLoadingMemoryUsageBitMap ( return EFI_SUCCESS; } /** - Get the fixed loadding address from image header assigned by build tool. This function only be called + Get the fixed loading address from image header assigned by build tool. This function only be called when Loading module at Fixed address feature enabled. @param ImageContext Pointer to the image context structure that describes the PE/COFF image that needs to be examined by this function. @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools . - @retval EFI_NOT_FOUND The image has no assigned fixed loadding address. + @retval EFI_NOT_FOUND The image has no assigned fixed loading address. **/ EFI_STATUS @@ -217,82 +217,80 @@ GetPeCoffImageFixLoadingAssignedAddress( IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext ) { - UINTN SectionHeaderOffset; - EFI_STATUS Status; - EFI_IMAGE_SECTION_HEADER SectionHeader; - EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; - EFI_PHYSICAL_ADDRESS FixLoaddingAddress; - UINT16 Index; - UINTN Size; - UINT16 NumberOfSections; - UINT64 ValueInSectionHeader; - - FixLoaddingAddress = 0; - Status = EFI_NOT_FOUND; - - // - // Get PeHeader pointer - // - ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset); - SectionHeaderOffset = (UINTN)( - ImageContext->PeCoffHeaderOffset + - sizeof (UINT32) + - sizeof (EFI_IMAGE_FILE_HEADER) + - ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader - ); - NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections; - - // - // Get base address from the first section header that doesn't point to code section. - // - for (Index = 0; Index < NumberOfSections; Index++) { - // - // Read section header from file - // - Size = sizeof (EFI_IMAGE_SECTION_HEADER); - Status = ImageContext->ImageRead ( + UINTN SectionHeaderOffset; + EFI_STATUS Status; + EFI_IMAGE_SECTION_HEADER SectionHeader; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + EFI_PHYSICAL_ADDRESS FixLoadingAddress; + UINT16 Index; + UINTN Size; + UINT16 NumberOfSections; + UINT64 ValueInSectionHeader; + + FixLoadingAddress = 0; + Status = EFI_NOT_FOUND; + + // + // Get PeHeader pointer + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset); + SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader; + NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections; + + // + // Get base address from the first section header that doesn't point to code section. + // + for (Index = 0; Index < NumberOfSections; Index++) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( ImageContext->Handle, SectionHeaderOffset, &Size, &SectionHeader ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = EFI_NOT_FOUND; - - if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { - // - // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header - // that doesn't point to code section in image header.So there is an assumption that when the feature is enabled, - // if a module with a loading address assigned by tools, the PointerToRelocations & PointerToLineNumbers fields - // should not be Zero, or else, these 2 fileds should be set to Zero - // - ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations); - if (ValueInSectionHeader != 0) { - // - // Found first section header that doesn't point to code section in which uild tool saves the - // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields - // - FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + (INT64)ValueInSectionHeader); - // - // Check if the memory range is avaliable. - // - Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoaddingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment)); - if (!EFI_ERROR(Status)) { - // - // The assigned address is valid. Return the specified loadding address - // - ImageContext->ImageAddress = FixLoaddingAddress; - } - } - break; - } - SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); - } - DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r\n", FixLoaddingAddress, Status)); - return Status; + if (EFI_ERROR (Status)) { + return Status; + } + + Status = EFI_NOT_FOUND; + + if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { + // + // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header + // that doesn't point to code section in image header.So there is an assumption that when the feature is enabled, + // if a module with a loading address assigned by tools, the PointerToRelocations & PointerToLineNumbers fields + // should not be Zero, or else, these 2 fields should be set to Zero + // + ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations); + if (ValueInSectionHeader != 0) { + // + // Found first section header that doesn't point to code section in which build tool saves the + // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields + // + FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + (INT64)ValueInSectionHeader); + // + // Check if the memory range is available. + // + Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoadingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment)); + if (!EFI_ERROR(Status)) { + // + // The assigned address is valid. Return the specified loading address + // + ImageContext->ImageAddress = FixLoadingAddress; + } + } + break; + } + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r\n", FixLoadingAddress, Status)); + return Status; } /** Loads an EFI image into SMRAM. @@ -517,10 +515,10 @@ SmmLoadImage ( ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer; } // - // Align buffer on section boundry + // Align buffer on section boundary // ImageContext.ImageAddress += ImageContext.SectionAlignment - 1; - ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)(ImageContext.SectionAlignment - 1)); + ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1); // // Load the image to our new buffer @@ -580,6 +578,11 @@ SmmLoadImage ( DriverEntry->LoadedImage->SystemTable = gST; DriverEntry->LoadedImage->DeviceHandle = DeviceHandle; + DriverEntry->SmmLoadedImage.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION; + DriverEntry->SmmLoadedImage.ParentHandle = gSmmCorePrivate->SmmIplImageHandle; + DriverEntry->SmmLoadedImage.SystemTable = gST; + DriverEntry->SmmLoadedImage.DeviceHandle = DeviceHandle; + // // Make an EfiBootServicesData buffer copy of FilePath // @@ -593,11 +596,30 @@ SmmLoadImage ( } CopyMem (DriverEntry->LoadedImage->FilePath, FilePath, GetDevicePathSize (FilePath)); - DriverEntry->LoadedImage->ImageBase = (VOID *)(UINTN)DriverEntry->ImageBuffer; + DriverEntry->LoadedImage->ImageBase = (VOID *)(UINTN) ImageContext.ImageAddress; DriverEntry->LoadedImage->ImageSize = ImageContext.ImageSize; DriverEntry->LoadedImage->ImageCodeType = EfiRuntimeServicesCode; DriverEntry->LoadedImage->ImageDataType = EfiRuntimeServicesData; + // + // Make a buffer copy of FilePath + // + Status = SmmAllocatePool (EfiRuntimeServicesData, GetDevicePathSize(FilePath), (VOID **)&DriverEntry->SmmLoadedImage.FilePath); + if (EFI_ERROR (Status)) { + if (Buffer != NULL) { + gBS->FreePool (Buffer); + } + gBS->FreePool (DriverEntry->LoadedImage->FilePath); + SmmFreePages (DstBuffer, PageCount); + return Status; + } + CopyMem (DriverEntry->SmmLoadedImage.FilePath, FilePath, GetDevicePathSize(FilePath)); + + DriverEntry->SmmLoadedImage.ImageBase = (VOID *)(UINTN) ImageContext.ImageAddress; + DriverEntry->SmmLoadedImage.ImageSize = ImageContext.ImageSize; + DriverEntry->SmmLoadedImage.ImageCodeType = EfiRuntimeServicesCode; + DriverEntry->SmmLoadedImage.ImageDataType = EfiRuntimeServicesData; + // // Create a new image handle in the UEFI handle database for the SMM Driver // @@ -608,6 +630,17 @@ SmmLoadImage ( NULL ); + // + // Create a new image handle in the SMM handle database for the SMM Driver + // + DriverEntry->SmmImageHandle = NULL; + Status = SmmInstallProtocolInterface ( + &DriverEntry->SmmImageHandle, + &gEfiLoadedImageProtocolGuid, + EFI_NATIVE_INTERFACE, + &DriverEntry->SmmLoadedImage + ); + PERF_START (DriverEntry->ImageHandle, "LoadImage:", NULL, Tick); PERF_END (DriverEntry->ImageHandle, "LoadImage:", NULL, 0); @@ -896,6 +929,16 @@ SmmDispatcher ( } gBS->FreePool (DriverEntry->LoadedImage); } + Status = SmmUninstallProtocolInterface ( + DriverEntry->SmmImageHandle, + &gEfiLoadedImageProtocolGuid, + &DriverEntry->SmmLoadedImage + ); + if (!EFI_ERROR(Status)) { + if (DriverEntry->SmmLoadedImage.FilePath != NULL) { + SmmFreePool (DriverEntry->SmmLoadedImage.FilePath); + } + } } REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( @@ -1327,6 +1370,27 @@ SmmDriverDispatchHandler ( mSmmCoreLoadedImage->DeviceHandle = FvHandle; } + if (mSmmCoreDriverEntry->SmmLoadedImage.FilePath == NULL) { + // + // Maybe one special FV contains only one SMM_CORE module, so its device path must + // be initialized completely. + // + EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid); + SetDevicePathEndNode (&mFvDevicePath.End); + + // + // Make a buffer copy FilePath + // + Status = SmmAllocatePool ( + EfiRuntimeServicesData, + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath), + (VOID **)&mSmmCoreDriverEntry->SmmLoadedImage.FilePath + ); + ASSERT_EFI_ERROR (Status); + CopyMem (mSmmCoreDriverEntry->SmmLoadedImage.FilePath, &mFvDevicePath, GetDevicePathSize((EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath)); + + mSmmCoreDriverEntry->SmmLoadedImage.DeviceHandle = FvHandle; + } } else { SmmAddToDriverList (Fv, FvHandle, &NameGuid); }