From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by mx.groups.io with SMTP id smtpd.web10.46512.1685355461422191016 for ; Mon, 29 May 2023 03:17:41 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=nlqbahdA; spf=pass (domain: kernel.org, ip: 139.178.84.217, mailfrom: ardb@kernel.org) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id EA72561362; Mon, 29 May 2023 10:17:40 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id F1FE6C433D2; Mon, 29 May 2023 10:17:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685355460; bh=jOBN3s1PRuyTVMyf5XaKX7FVJXPANezV5v2N5lwkRl0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nlqbahdABWRRcPmjiWNpM03aIvHlvAk97RTZ4UAfxN4sExHnlwnR/JYWRU/dISu8l 4DqLxmBeWlix7LMtAViS6aiHxaZrL8u4gt4GZ/gG84aCgof8zYHLxY1ZcSQqLGUx1V PXEzAYI/hfo9ovK0KH+OFmzl+8+D9MvpJ8LkytYsui26SDRQsJedZhXmqMzVTVLkt7 HybxNpoRICbTjKJ2jpxylGLw7DJA7cCVF7yvLzOdI2tBNbO/CZI3Xz50Dz4I02yJLZ oSmnITFSmmEYNxxBDChOLWwPZtvTglKjMz0opg+8B34rCskpO1GKWUUzy9BDxBkx6n V4rVm/9sH1IMA== From: "Ard Biesheuvel" To: devel@edk2.groups.io Cc: Ard Biesheuvel , Ray Ni , Jiewen Yao , Gerd Hoffmann , Taylor Beebe , Oliver Smith-Denny , Dandan Bi , Liming Gao , "Kinney, Michael D" , Leif Lindholm , Michael Kubacki Subject: [RFC PATCH 08/11] MdeModulePkg/DxeIpl: Relocate and remap XIP capable DXE drivers Date: Mon, 29 May 2023 12:17:02 +0200 Message-Id: <20230529101705.2476949-9-ardb@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230529101705.2476949-1-ardb@kernel.org> References: <20230529101705.2476949-1-ardb@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Before handing over to the DXE core, iterate over all known FFS files and find the ones that can execute in place. These files are then relocated in place and mapped with restricted permissions, allowing the DXE core to dispatch them without the need to perform any manipulation of the file contents or the page table permissions. Signed-off-by: Ard Biesheuvel --- MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 1 + MdeModulePkg/Core/DxeIplPeim/DxeLoad.c | 196 ++++++++++++++++++++ 2 files changed, 197 insertions(+) diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/Dx= eIplPeim/DxeIpl.inf index f1990eac77607854..60112100df78b396 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -65,6 +65,7 @@ [LibraryClasses] PeimEntryPoint=0D DebugLib=0D DebugAgentLib=0D + PeCoffLib=0D PeiServicesTablePointerLib=0D PerformanceLib=0D =0D diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/Dxe= IplPeim/DxeLoad.c index 2c19f1a507baf34a..1f20db1faffbd1d2 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c @@ -10,6 +10,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent =0D #include "DxeIpl.h"=0D =0D +#include =0D +#include =0D +=0D //=0D // Module Globals used in the DXE to PEI hand off=0D // These must be module globals, so the stack can be switched=0D @@ -228,6 +231,197 @@ ValidateMemoryTypeInfoVariable ( return TRUE;=0D }=0D =0D +/**=0D + Support routine for the PE/COFF Loader that reads a buffer from a PE/COF= F file.=0D + The function is used for XIP code to have optimized memory copy.=0D +=0D + @param FileHandle The handle to the PE/COFF file=0D + @param FileOffset The offset, in bytes, into the file to read=0D + @param ReadSize The number of bytes to read from the file startin= g at FileOffset=0D + @param Buffer A pointer to the buffer to read the data into.=0D +=0D + @return EFI_SUCCESS ReadSize bytes of data were read into Buffer from= the=0D + PE/COFF file starting at FileOffset=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +EFIAPI=0D +PeiImageRead (=0D + IN VOID *FileHandle,=0D + IN UINTN FileOffset,=0D + IN UINTN *ReadSize,=0D + OUT VOID *Buffer=0D + )=0D +{=0D + CHAR8 *Destination8;=0D + CHAR8 *Source8;=0D +=0D + Destination8 =3D Buffer;=0D + Source8 =3D (CHAR8 *)((UINTN)FileHandle + FileOffset);=0D + if (Destination8 !=3D Source8) {=0D + CopyMem (Destination8, Source8, *ReadSize);=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +STATIC=0D +VOID=0D +RemapImage (=0D + IN EDKII_MEMORY_ATTRIBUTE_PPI *MemoryPpi,=0D + IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext=0D + )=0D +{=0D + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;=0D + EFI_IMAGE_SECTION_HEADER *Section;=0D + PHYSICAL_ADDRESS SectionAddress;=0D + EFI_STATUS Status;=0D + UINT64 Permissions;=0D + UINTN Index;=0D +=0D + if (MemoryPpi =3D=3D NULL) {=0D + return;=0D + }=0D +=0D + Hdr.Union =3D (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINT8 *)ImageContext-= >Handle +=0D + ImageContext->PeCoffHead= erOffset);=0D + ASSERT (Hdr.Pe32->Signature =3D=3D EFI_IMAGE_NT_SIGNATURE);=0D +=0D + Section =3D (EFI_IMAGE_SECTION_HEADER *)((UINT8 *)Hdr.Union + sizeof (UI= NT32) +=0D + sizeof (EFI_IMAGE_FILE_HEADER) += =0D + Hdr.Pe32->FileHeader.SizeOfOption= alHeader=0D + );=0D +=0D + for (Index =3D 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++= ) {=0D + SectionAddress =3D ImageContext->ImageAddress + Section[Index].Virtual= Address;=0D + Permissions =3D 0;=0D +=0D + if ((Section[Index].Characteristics & EFI_IMAGE_SCN_MEM_WRITE) =3D=3D = 0) {=0D + Permissions |=3D EFI_MEMORY_RO;=0D + }=0D +=0D + if ((Section[Index].Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) =3D= =3D 0) {=0D + Permissions |=3D EFI_MEMORY_XP;=0D + }=0D +=0D + Status =3D MemoryPpi->SetPermissions (=0D + MemoryPpi,=0D + SectionAddress,=0D + Section[Index].Misc.VirtualSize,=0D + Permissions,=0D + Permissions ^ EFI_MEMORY_RO ^ EFI_MEMORY_XP=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D + }=0D +}=0D +=0D +STATIC=0D +VOID=0D +RelocateAndRemapDriversInPlace (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINTN Instance;=0D + EFI_PEI_FV_HANDLE VolumeHandle;=0D + EFI_PEI_FILE_HANDLE FileHandle;=0D + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;=0D + UINT32 AuthenticationState;=0D + EDKII_MEMORY_ATTRIBUTE_PPI *MemoryPpi;=0D +=0D + MemoryPpi =3D NULL;=0D + PeiServicesLocatePpi (&gEdkiiMemoryAttributePpiGuid, 0, NULL, (VOID **)&= MemoryPpi);=0D +=0D + Instance =3D 0;=0D + do {=0D + //=0D + // Traverse all firmware volume instances=0D + //=0D + Status =3D PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);=0D + if (Status =3D=3D EFI_NOT_FOUND) {=0D + return;=0D + }=0D +=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + FileHandle =3D NULL;=0D + do {=0D + Status =3D PeiServicesFfsFindNextFile (=0D + EFI_FV_FILETYPE_DRIVER,=0D + VolumeHandle,=0D + &FileHandle);=0D + if (Status =3D=3D EFI_NOT_FOUND) {=0D + break;=0D + }=0D +=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + ZeroMem (&ImageContext, sizeof (ImageContext));=0D +=0D + Status =3D PeiServicesFfsFindSectionData3 (=0D + EFI_SECTION_PE32,=0D + 0,=0D + FileHandle,=0D + &ImageContext.Handle,=0D + &AuthenticationState=0D + );=0D + if (Status =3D=3D EFI_NOT_FOUND) {=0D + continue;=0D + }=0D +=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + ImageContext.ImageRead =3D PeiImageRead;=0D + Status =3D PeCoffLoaderGetImageInfo (&ImageContext);= =0D + if (EFI_ERROR (Status)) {=0D + ASSERT_EFI_ERROR (Status);=0D + continue;=0D + }=0D +=0D + ImageContext.ImageAddress =3D (PHYSICAL_ADDRESS)(UINTN)ImageContext.= Handle;=0D + if ((ImageContext.ImageAddress & (ImageContext.SectionAlignment - 1)= ) !=3D 0) {=0D + DEBUG ((DEBUG_VERBOSE, "%a: skip PE image at %p\n", __func__, Imag= eContext.Handle));=0D + continue;=0D + }=0D +=0D + DEBUG ((=0D + DEBUG_INFO,=0D + "%a: relocate PE image at %p for execution in place\n",=0D + __func__,=0D + ImageContext.Handle=0D + ));=0D +=0D + //=0D + // 'Load' the image in-place - this just performs a sanity check on= =0D + // the PE metadata but does not actually move any data=0D + //=0D + Status =3D PeCoffLoaderLoadImage (&ImageContext);=0D + if (EFI_ERROR (Status)) {=0D + ASSERT_EFI_ERROR (Status);=0D + continue;=0D + }=0D +=0D + //=0D + // Relocate this driver in place=0D + //=0D + Status =3D PeCoffLoaderRelocateImage (&ImageContext);=0D + if (EFI_ERROR (Status)) {=0D + ASSERT_EFI_ERROR (Status);=0D + continue;=0D + }=0D +=0D + //=0D + // Apply section permissions to the page tables=0D + //=0D + RemapImage (MemoryPpi, &ImageContext);=0D +=0D + } while (TRUE);=0D +=0D + Instance++;=0D + } while (TRUE);=0D +}=0D +=0D /**=0D Main entry point to last PEIM.=0D =0D @@ -436,6 +630,8 @@ DxeLoadCore ( DxeCoreEntryPoint=0D );=0D =0D + RelocateAndRemapDriversInPlace ();=0D +=0D //=0D // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT=0D //=0D --=20 2.39.2