From nobody Fri Apr 26 12:58:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+105142+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+105142+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1684808441; cv=none; d=zohomail.com; s=zohoarc; b=kgdW5xsV42qEVlbbQgO20/0baOg3N9S31M30Tfe4p+VYJz3kE812lw1RFM1vtXalShwkGhO3SFpwgLJlEjDtSMO1LxXcu3OMDipswwxwa2Qb/5wLWAO75CNbIZt18UVaDPHpF36lCnr9BsUYra1amtQnzzCurkSlsetya0YZTfo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1684808441; h=Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Sender:Subject:To; bh=qJ7vV5feutk0FCHbgzJ33t92/WAq85FUa5M6yQS8LIY=; b=nlvovzyQ3LgE4+Xon9oXCXoqePI565WxJtWki1VnAPXzpLKwp86MggEWH8p/i2A6p1Mf21nKGnJe+QaVEycIeex/N1QeN0QVnFbkA6/C4xX7xCWu7kw0HDavqywucpmV4fzqTkRF7GJWXw/3Y/81OuYa0+5+KsibvslzhkKNTBI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+105142+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1684808441445371.96979281729955; Mon, 22 May 2023 19:20:41 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id nAWVYY1788612xInuwfAXgPn; Mon, 22 May 2023 19:20:41 -0700 X-Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web10.15514.1684732884492738241 for ; Sun, 21 May 2023 22:21:24 -0700 X-IronPort-AV: E=McAfee;i="6600,9927,10717"; a="337418278" X-IronPort-AV: E=Sophos;i="6.00,183,1681196400"; d="scan'208";a="337418278" X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 May 2023 22:21:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10717"; a="706390243" X-IronPort-AV: E=Sophos;i="6.00,183,1681196400"; d="scan'208";a="706390243" X-Received: from hongbin1-mobl1.ccr.corp.intel.com ([10.254.210.93]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 May 2023 22:21:20 -0700 From: "Zhang, Hongbin1" To: devel@edk2.groups.io Cc: "Zhang, Hongbin1" , Jiewen Yao , Ray Ni , Star Zeng , Jiaxin Wu , Sami Mujawar , Ard Biesheuvel , Supreeth Venkatesh Subject: [edk2-devel] [PATCH v1] StandaloneMmPkg: Add StandaloneMmIplPei driver. Date: Mon, 22 May 2023 13:21:05 +0800 Message-Id: <20230522052105.1135-1-hongbin1.zhang@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: 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,hongbin1.zhang@intel.com X-Gm-Message-State: UNZuaAK5x6J86xHotuGJgH6Tx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1684808441; bh=GrDAjjnVkp/niAkPRfzHrhgr+8pzdGYz3DzMVUQiKx8=; h=Cc:Date:From:Reply-To:Subject:To; b=qYjq78swVF/syRZMTnooQYVnkkYKPMJmYWnxvVyYzmVmvVZfij/mpA4vruCe9R7xunu ZFJpBN2cOvyDJrMcXdkY8XaV+Yb1Rlg/jn7obNhg5x11mF/zWUgACZDLfDpfZy/3InGU5 b3oZM2yiAiaSdzry2/n3ioVSILAnoshWi70= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1684808442653100001 Content-Type: text/plain; charset="utf-8" Add StandaloneMmIplPei IA32/X64 driver at PEI stage. FSP will use this driver to load Standalone MM code to dispatch other Standalone MM drivers. Signed-off-by: Hongbin1 Zhang Cc: Jiewen Yao Cc: Ray Ni Cc: Star Zeng Cc: Jiaxin Wu Cc: Sami Mujawar Cc: Ard Biesheuvel Cc: Supreeth Venkatesh --- StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c | 456 ++= ++++++++++ StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c | 787 ++= ++++++++++++++++++ StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c | 32 + StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm | 148 ++= ++ StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h | 66 ++ StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf | 75 ++ StandaloneMmPkg/StandaloneMmPkg.ci.yaml | 4 +- StandaloneMmPkg/StandaloneMmPkg.dsc | 15 +- UefiPayloadPkg/UniversalPayloadBuild.sh | 34 +- edksetup.sh | 294 ++= ++---- 10 files changed, 1744 insertions(+), 167 deletions(-) diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c = b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c new file mode 100644 index 0000000000..d6174d73a3 --- /dev/null +++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c @@ -0,0 +1,456 @@ +/** @file + SMM IPL that load the SMM Core into SMRAM + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma pack(1) + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present : 1; // 0 =3D Not present in memory, = 1 =3D Present in memory + UINT64 ReadWrite : 1; // 0 =3D Read-Only, 1=3D Read/Wr= ite + UINT64 UserSupervisor : 1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough : 1; // 0 =3D Write-Back caching, 1= =3DWrite-Through caching + UINT64 CacheDisabled : 1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed : 1; // 0 =3D Not accessed, 1 =3D Acc= essed (set by CPU) + UINT64 Reserved : 1; // Reserved + UINT64 MustBeZero : 2; // Must Be Zero + UINT64 Available : 3; // Available for use by system s= oftware + UINT64 PageTableBaseAddress : 40; // Page Table Base Address + UINT64 AvailableHigh : 11; // Available for use by system s= oftware + UINT64 Nx : 1; // No Execute bit + } Bits; + UINT64 Uint64; +} PAGE_MAP_AND_DIRECTORY_POINTER; + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present : 1; // 0 =3D Not present in memory, = 1 =3D Present in memory + UINT64 ReadWrite : 1; // 0 =3D Read-Only, 1=3D Read/Wr= ite + UINT64 UserSupervisor : 1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough : 1; // 0 =3D Write-Back caching, 1= =3DWrite-Through caching + UINT64 CacheDisabled : 1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed : 1; // 0 =3D Not accessed, 1 =3D Acc= essed (set by CPU) + UINT64 Dirty : 1; // 0 =3D Not Dirty, 1 =3D writte= n by processor on access to page + UINT64 MustBe1 : 1; // Must be 1 + UINT64 Global : 1; // 0 =3D Not global page, 1 =3D = global page TLB not cleared on CR3 write + UINT64 Available : 3; // Available for use by system s= oftware + UINT64 Pat : 1; // + UINT64 MustBeZero : 8; // Must be zero + UINT64 PageTableBaseAddress : 31; // Page Table Base Address + UINT64 AvailableHigh : 11; // Available for use by system s= oftware + UINT64 Nx : 1; // 0 =3D Execute Code, 1 =3D No = Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_ENTRY; + +// +// Page Table Entry 1GB +// +typedef union { + struct { + UINT64 Present : 1; // 0 =3D Not present in memory, = 1 =3D Present in memory + UINT64 ReadWrite : 1; // 0 =3D Read-Only, 1=3D Read/Wr= ite + UINT64 UserSupervisor : 1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough : 1; // 0 =3D Write-Back caching, 1= =3DWrite-Through caching + UINT64 CacheDisabled : 1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed : 1; // 0 =3D Not accessed, 1 =3D Acc= essed (set by CPU) + UINT64 Dirty : 1; // 0 =3D Not Dirty, 1 =3D writte= n by processor on access to page + UINT64 MustBe1 : 1; // Must be 1 + UINT64 Global : 1; // 0 =3D Not global page, 1 =3D = global page TLB not cleared on CR3 write + UINT64 Available : 3; // Available for use by system s= oftware + UINT64 Pat : 1; // + UINT64 MustBeZero : 17; // Must be zero; + UINT64 PageTableBaseAddress : 22; // Page Table Base Address + UINT64 AvailableHigh : 11; // Available for use by system s= oftware + UINT64 Nx : 1; // 0 =3D Execute Code, 1 =3D No = Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_1G_ENTRY; + +#pragma pack() + +// +// Global Descriptor Table (GDT) +// +GLOBAL_REMOVE_IF_UNREFERENCED IA32_SEGMENT_DESCRIPTOR mGdtEntries[] =3D { + /* selector { Global Segment Descriptor } */ + /* 0x00 */ { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }, = // null descriptor + /* 0x08 */ { + { 0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 } + }, = // linear data segment descriptor + /* 0x10 */ { + { 0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 } + }, = // linear code segment descriptor + /* 0x18 */ { + { 0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 } + }, = // system data segment descriptor + /* 0x20 */ { + { 0xffff, 0, 0, 0xb, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 } + }, = // system code segment descriptor + /* 0x28 */ { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }, = // spare segment descriptor + /* 0x30 */ { + { 0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 } + }, = // system data segment descriptor + /* 0x38 */ { + { 0xffff, 0, 0, 0xb, 1, 0, 1, 0xf, 0, 1, 0, 1, 0 } + }, = // system code segment descriptor + /* 0x40 */ { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }, = // spare segment descriptor +}; + +// +// IA32 Gdt register +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt =3D { + sizeof (mGdtEntries) - 1, + (UINTN)mGdtEntries +}; + +/** + Calculate the total size of page table. + + @return The size of page table. + +**/ +UINTN +CalculatePageTableSize ( + VOID + ) +{ + UINT32 RegEax; + UINT32 RegEdx; + UINTN TotalPagesNum; + UINT8 PhysicalAddressBits; + VOID *Hob; + UINT32 NumberOfPml4EntriesNeeded; + UINT32 NumberOfPdpEntriesNeeded; + BOOLEAN Page1GSupport; + + Page1GSupport =3D FALSE; + if (PcdGetBool (PcdUse1GPageTable)) { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >=3D 0x80000001) { + AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); + if ((RegEdx & BIT26) !=3D 0) { + Page1GSupport =3D TRUE; + } + } + } + + // + // Get physical address bits supported. + // + Hob =3D GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob !=3D NULL) { + PhysicalAddressBits =3D ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace; + } else { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >=3D 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + PhysicalAddressBits =3D (UINT8)RegEax; + } else { + PhysicalAddressBits =3D 36; + } + } + + // + // IA-32e paging translates 48-bit linear addresses to 52-bit physical a= ddresses. + // + ASSERT (PhysicalAddressBits <=3D 52); + if (PhysicalAddressBits > 48) { + PhysicalAddressBits =3D 48; + } + + // + // Calculate the table entries needed. + // + if (PhysicalAddressBits <=3D 39 ) { + NumberOfPml4EntriesNeeded =3D 1; + NumberOfPdpEntriesNeeded =3D (UINT32)LShiftU64 (1, (PhysicalAddressBi= ts - 30)); + } else { + NumberOfPml4EntriesNeeded =3D (UINT32)LShiftU64 (1, (PhysicalAddressBi= ts - 39)); + NumberOfPdpEntriesNeeded =3D 512; + } + + if (!Page1GSupport) { + TotalPagesNum =3D (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4Entries= Needed + 1; + } else { + TotalPagesNum =3D NumberOfPml4EntriesNeeded + 1; + } + + return EFI_PAGES_TO_SIZE (TotalPagesNum); +} + +/** + Allocates and fills in the Page Directory and Page Table Entries to + establish a 1:1 Virtual to Physical mapping. + + @param[in] PageTablesAddress The base address of page table. + +**/ +VOID +CreateIdentityMappingPageTables ( + IN EFI_PHYSICAL_ADDRESS PageTablesAddress + ) +{ + UINT32 RegEax; + UINT32 RegEdx; + UINT8 PhysicalAddressBits; + EFI_PHYSICAL_ADDRESS PageAddress; + UINTN IndexOfPml4Entries; + UINTN IndexOfPdpEntries; + UINTN IndexOfPageDirectoryEntries; + UINT32 NumberOfPml4EntriesNeeded; + UINT32 NumberOfPdpEntriesNeeded; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMap; + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + UINTN BigPageAddress; + VOID *Hob; + BOOLEAN Page1GSupport; + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; + + Page1GSupport =3D FALSE; + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >=3D 0x80000001) { + AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); + if ((RegEdx & BIT26) !=3D 0) { + Page1GSupport =3D TRUE; + } + } + + // + // Get physical address bits supported. + // + Hob =3D GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob !=3D NULL) { + PhysicalAddressBits =3D ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace; + } else { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >=3D 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + PhysicalAddressBits =3D (UINT8)RegEax; + } else { + PhysicalAddressBits =3D 36; + } + } + + // + // IA-32e paging translates 48-bit linear addresses to 52-bit physical a= ddresses. + // + ASSERT (PhysicalAddressBits <=3D 52); + if (PhysicalAddressBits > 48) { + PhysicalAddressBits =3D 48; + } + + // + // Calculate the table entries needed. + // + if (PhysicalAddressBits <=3D 39 ) { + NumberOfPml4EntriesNeeded =3D 1; + NumberOfPdpEntriesNeeded =3D (UINT32)LShiftU64 (1, (PhysicalAddressBi= ts - 30)); + } else { + NumberOfPml4EntriesNeeded =3D (UINT32)LShiftU64 (1, (PhysicalAddressBi= ts - 39)); + NumberOfPdpEntriesNeeded =3D 512; + } + + // + // Pre-allocate big pages to avoid later allocations. + // + BigPageAddress =3D (UINTN)PageTablesAddress; + + // + // By architecture only one PageMapLevel4 exists - so lets allocate stor= age for it. + // + PageMap =3D (VOID *)BigPageAddress; + BigPageAddress +=3D SIZE_4KB; + + PageMapLevel4Entry =3D PageMap; + PageAddress =3D 0; + for (IndexOfPml4Entries =3D 0; IndexOfPml4Entries < NumberOfPml4EntriesN= eeded; IndexOfPml4Entries++, PageMapLevel4Entry++) { + // + // Each PML4 entry points to a page of Page Directory Pointer entires. + // So lets allocate space for them and fill them in in the IndexOfPdpE= ntries loop. + // + PageDirectoryPointerEntry =3D (VOID *)BigPageAddress; + BigPageAddress +=3D SIZE_4KB; + + // + // Make a PML4 Entry + // + PageMapLevel4Entry->Uint64 =3D (UINT64)(UINTN)PageDirectoryPoi= nterEntry; + PageMapLevel4Entry->Bits.ReadWrite =3D 1; + PageMapLevel4Entry->Bits.Present =3D 1; + + if (Page1GSupport) { + PageDirectory1GEntry =3D (VOID *)PageDirectoryPointerEntry; + + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntries = < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += =3D SIZE_1GB) { + // + // Fill in the Page Directory entries + // + PageDirectory1GEntry->Uint64 =3D (UINT64)PageAddress; + PageDirectory1GEntry->Bits.ReadWrite =3D 1; + PageDirectory1GEntry->Bits.Present =3D 1; + PageDirectory1GEntry->Bits.MustBe1 =3D 1; + } + } else { + for (IndexOfPdpEntries =3D 0; IndexOfPdpEntries < NumberOfPdpEntries= Needed; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { + // + // Each Directory Pointer entries points to a page of Page Directo= ry entires. + // So allocate space for them and fill them in in the IndexOfPageD= irectoryEntries loop. + // + PageDirectoryEntry =3D (VOID *)BigPageAddress; + BigPageAddress +=3D SIZE_4KB; + + // + // Fill in a Page Directory Pointer Entries + // + PageDirectoryPointerEntry->Uint64 =3D (UINT64)(UINTN)PageD= irectoryEntry; + PageDirectoryPointerEntry->Bits.ReadWrite =3D 1; + PageDirectoryPointerEntry->Bits.Present =3D 1; + + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntrie= s < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += =3D SIZE_2MB) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 =3D (UINT64)PageAddress; + PageDirectoryEntry->Bits.ReadWrite =3D 1; + PageDirectoryEntry->Bits.Present =3D 1; + PageDirectoryEntry->Bits.MustBe1 =3D 1; + } + } + + for ( ; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryP= ointerEntry++) { + ZeroMem ( + PageDirectoryPointerEntry, + sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) + ); + } + } + } + + // + // For the PML4 entries we are not using fill in a null entry. + // + for ( ; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Ent= ry++) { + ZeroMem ( + PageMapLevel4Entry, + sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) + ); + } +} + +/** + If in 32 bit protection mode, and coalesce image is of X64, switch to lo= ng mode. + + @param Entry Entry of Standalone MM Foundation. + @param Context1 A pointer to the context to pass into = the EntryPoint + function. + @param Context2 A pointer to the context to pass into = the EntryPoint + function. + @retval EFI_SUCCESS Successfully switched to long mode and= execute coalesce. + @retval Others Failed to execute coalesce in long mod= e. + +**/ +EFI_STATUS +ModeSwitch ( + IN EFI_PHYSICAL_ADDRESS Entry, + IN VOID *Context1, + IN VOID *Context2 + ) +{ + UINTN PageTableAddress; + UINTN PageTableSize; + EFI_STATUS Status; + IA32_DESCRIPTOR Gdtr; + + DEBUG ((DEBUG_INFO, "ModeSwitch\n")); + + // + // Save IA32 GDTR + // + AsmReadGdtr (&Gdtr); + + // + // Set X64 GDTR + // + AsmWriteGdtr (&mGdt); + + PageTableAddress =3D AsmReadCr3 () & 0xFFFFF000; + + // + // If page table was created, no need to create + // + if (PageTableAddress =3D=3D 0) { + PageTableSize =3D CalculatePageTableSize (); + + PageTableAddress =3D (UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PageTabl= eSize)); + ASSERT (PageTableAddress !=3D 0); + + CreateIdentityMappingPageTables (PageTableAddress); + + AsmWriteCr3 ((UINTN)PageTableAddress); + } + + DEBUG ((DEBUG_INFO, "AsmExecute64BitCode ...\n")); + + Status =3D AsmExecute64BitCode (Entry, (UINT64)(UINTN)Context1, (UINT64)= (UINTN)Context2, NULL); + if (Status !=3D 0) { + Status =3D Status | MAX_BIT; + } + + DEBUG ((DEBUG_INFO, "AsmExecute64BitCode - %r\n", Status)); + + // + // Restore IA32 GDTR + // + AsmWriteGdtr (&Gdtr); + + return Status; +} + +/** + Load SMM core to dispatch other Standalone MM drivers. + + @param Entry Entry of Standalone MM Foundation. + @param Context1 A pointer to the context to pass into = the EntryPoint + function. + @retval EFI_SUCCESS Successfully loaded SMM core. + @retval Others Failed to load SMM core. +**/ +EFI_STATUS +LoadSmmCore ( + IN EFI_PHYSICAL_ADDRESS Entry, + IN VOID *Context1 + ) +{ + return ModeSwitch (Entry, Context1, NULL); +} diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.= c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c new file mode 100644 index 0000000000..7fa42c32fb --- /dev/null +++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c @@ -0,0 +1,787 @@ +/** @file + SMM IPL that load the SMM Core into SMRAM at PEI stage + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// MM Core Private Data structure that contains the data shared between +// the SMM IPL and the Standalone MM Core. +// +MM_CORE_PRIVATE_DATA mMmCorePrivateData =3D { + MM_CORE_PRIVATE_DATA_SIGNATURE, // Signature + 0, // MmramRangeCount + 0, // MmramRanges + 0, // MmEntryPoint + FALSE, // MmEntryPointRegistered + FALSE, // InMm + 0, // Mmst + 0, // CommunicationBuffer + 0, // BufferSize + EFI_SUCCESS, // ReturnStatus + 0, // MmCoreImageBase + 0, // MmCoreImageSize + 0, // MmCoreEntryPoint + 0, // StandaloneBfvAddress +}; + +// +// Global pointer used to access mMmCorePrivateData from outside and insid= e SMM +// +MM_CORE_PRIVATE_DATA *gMmCorePrivate; + +// +// SMM IPL global variables +// +PEI_SMM_ACCESS_PPI *mSmmAccess; +EFI_SMRAM_DESCRIPTOR *mCurrentSmramRange; +BOOLEAN mSmmLocked =3D FALSE; +EFI_PHYSICAL_ADDRESS mSmramCacheBase; +UINT64 mSmramCacheSize; + +EFI_PEI_NOTIFY_DESCRIPTOR mReadyToBootNotifyList =3D { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINA= TE_LIST), + &gEfiEventReadyToBootGuid, + ReadyToBootEvent +}; + +/** + This is the callback function on ready to boot. + + Close and Lock smram range on ready to boot stage. + + @param PeiServices General purpose services available to ever= y PEIM. + @param NotifyDescriptor The notification structure this PEIM regis= tered on install. + @param Ppi Pointer to the PPI data associated with th= is function. + @retval EFI_SUCCESS Close and lock smram ranges successfully. + @retval Other Close and lock smram ranges failed. +**/ +EFI_STATUS +EFIAPI +ReadyToBootEvent ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + + // + // Close all SMRAM ranges + // + Status =3D mSmmAccess->Close ((EFI_PEI_SERVICES **)PeiServices, mSmmAcce= ss, 0); + ASSERT_EFI_ERROR (Status); + + // + // Lock all SMRAM ranges + // + Status =3D mSmmAccess->Lock ((EFI_PEI_SERVICES **)PeiServices, mSmmAcces= s, 0); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Find the maximum SMRAM cache range that covers the range specified by Sm= ramRange. + + This function searches and joins all adjacent ranges of SmramRange into = a range to be cached. + + @param SmramRange The SMRAM range to search from. + @param SmramCacheBase The returned cache range base. + @param SmramCacheSize The returned cache range size. +**/ +VOID +GetSmramCacheRange ( + IN EFI_SMRAM_DESCRIPTOR *SmramRange, + OUT EFI_PHYSICAL_ADDRESS *SmramCacheBase, + OUT UINT64 *SmramCacheSize + ) +{ + UINTN Index; + EFI_PHYSICAL_ADDRESS RangeCpuStart; + UINT64 RangePhysicalSize; + BOOLEAN FoundAdjacentRange; + EFI_SMRAM_DESCRIPTOR *SmramRanges; + + *SmramCacheBase =3D SmramRange->CpuStart; + *SmramCacheSize =3D SmramRange->PhysicalSize; + + SmramRanges =3D (EFI_SMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->MmramRang= es; + do { + FoundAdjacentRange =3D FALSE; + for (Index =3D 0; Index < gMmCorePrivate->MmramRangeCount; Index++) { + RangeCpuStart =3D SmramRanges[Index].CpuStart; + RangePhysicalSize =3D SmramRanges[Index].PhysicalSize; + if ((RangeCpuStart < *SmramCacheBase) && (*SmramCacheBase =3D=3D (Ra= ngeCpuStart + RangePhysicalSize))) { + *SmramCacheBase =3D RangeCpuStart; + *SmramCacheSize +=3D RangePhysicalSize; + FoundAdjacentRange =3D TRUE; + } else if (((*SmramCacheBase + *SmramCacheSize) =3D=3D RangeCpuStart= ) && (RangePhysicalSize > 0)) { + *SmramCacheSize +=3D RangePhysicalSize; + FoundAdjacentRange =3D TRUE; + } + } + } while (FoundAdjacentRange); +} + +/** + 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 thi= s function. + @retval EFI_SUCCESS An fixed loading address is assigned t= o this image by build tools . + @retval EFI_NOT_FOUND The image has no assigned fixed loadin= g address. +**/ +EFI_STATUS +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 FixLoadingAddress; + UINT16 Index; + UINTN Size; + UINT16 NumberOfSections; + EFI_PHYSICAL_ADDRESS SmramBase; + UINT64 SmmCodeSize; + UINT64 ValueInSectionHeader; + + // + // Build tool will calculate the smm code size and then patch the PcdLoa= dFixAddressSmmCodePageNumber + // + SmmCodeSize =3D EFI_PAGES_TO_SIZE (PcdGet32 (PcdLoadFixAddressSmmC= odePageNumber)); + FixLoadingAddress =3D 0; + Status =3D EFI_NOT_FOUND; + SmramBase =3D mCurrentSmramRange->CpuStart; + // + // Get PeHeader pointer + // + ImgHdr =3D (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8 *)Ima= geContext->Handle + ImageContext->PeCoffHeaderOffset); + SectionHeaderOffset =3D (UINTN)( + ImageContext->PeCoffHeaderOffset + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHead= er + ); + NumberOfSections =3D ImgHdr->Pe32.FileHeader.NumberOfSections; + + // + // Get base address from the first section header that doesn't point to = code section. + // + for (Index =3D 0; Index < NumberOfSections; Index++) { + // + // Read section header from file + // + Size =3D sizeof (EFI_IMAGE_SECTION_HEADER); + Status =3D ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D EFI_NOT_FOUND; + + if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) =3D=3D 0)= { + // + // Build tool saves the offset to SMRAM base as image base in Pointe= rToRelocations & PointerToLineNumbers fields in the + // first section header that doesn't point to code section in image = header. And there is an assumption that when the + // feature is enabled, if a module is assigned a loading address by = tools, PointerToRelocations & PointerToLineNumbers + // fields should NOT be Zero, or else, these 2 fields should be set = to Zero + // + ValueInSectionHeader =3D ReadUnaligned64 ((UINT64 *)&SectionHeader.P= ointerToRelocations); + if (ValueInSectionHeader !=3D 0) { + // + // Found first section header that doesn't point to code section i= n which build tool saves the + // offset to SMRAM base as image base in PointerToRelocations & Po= interToLineNumbers fields + // + FixLoadingAddress =3D (EFI_PHYSICAL_ADDRESS)(SmramBase + (INT64)Va= lueInSectionHeader); + + if ((SmramBase + SmmCodeSize > FixLoadingAddress) && (SmramBase <= =3D FixLoadingAddress)) { + // + // The assigned address is valid. Return the specified loading a= ddress + // + ImageContext->ImageAddress =3D FixLoadingAddress; + Status =3D EFI_SUCCESS; + } + } + + break; + } + + SectionHeaderOffset +=3D sizeof (EFI_IMAGE_SECTION_HEADER); + } + + DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading modul= e at fixed address %x, Status =3D %r \n", FixLoadingAddress, Status)); + return Status; +} + +/** + Searches all the available firmware volumes and returns the first matchi= ng FFS section. + + This function searches all the firmware volumes for FFS files with FV fi= le type specified by FileType + The order that the firmware volumes is searched is not deterministic. Fo= r each available FV a search + is made for FFS file of type FileType. If the FV contains more than one = FFS file with the same FileType, + the FileInstance instance will be the matched FFS file. For each FFS fil= e found a search + is made for FFS sections of type SectionType. If the FFS file contains a= t least SectionInstance instances + of the FFS section specified by SectionType, then the SectionInstance in= stance is returned in Buffer. + Buffer is allocated using AllocatePool(), and the size of the allocated = buffer is returned in Size. + It is the caller's responsibility to use FreePool() to free the allocate= d buffer. + + If Buffer is NULL, then ASSERT(). + If Size is NULL, then ASSERT(). + + @param FileType Indicates the FV file type to search for wi= thin all available FVs. + @param FileInstance Indicates which file instance within all av= ailable FVs specified by FileType. + FileInstance starts from zero. + @param SectionType Indicates the FFS section type to search fo= r within the FFS file + specified by FileType with FileInstance. + @param SectionInstance Indicates which section instance within the= FFS file + specified by FileType with FileInstance to = retrieve. SectionInstance starts from zero. + @param Buffer On output, a pointer to a callee allocated = buffer containing the FFS file section that was found. + Is it the caller's responsibility to free t= his buffer using FreePool(). + @param Size On output, a pointer to the size, in bytes,= of Buffer. + + @retval EFI_SUCCESS The specified FFS section was returned. + @retval EFI_NOT_FOUND The specified FFS section could not be fou= nd. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available t= o retrieve the matching FFS section. + +**/ +EFI_STATUS +EFIAPI +GetSectionFromAnyFvByFileType ( + IN EFI_FV_FILETYPE FileType, + IN UINTN FileInstance, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + UINTN FvIndex; + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_PEI_FILE_HANDLE FileHandle; + EFI_PE32_SECTION *SectionData; + UINT32 SectionSize; + + // + // Search all FV + // + VolumeHandle =3D NULL; + for (FvIndex =3D 0; ; FvIndex++) { + Status =3D PeiServicesFfsFindNextVolume (FvIndex, &VolumeHandle); + if (EFI_ERROR (Status)) { + break; + } + + // + // Search PEIM FFS + // + FileHandle =3D NULL; + Status =3D PeiServicesFfsFindNextFile (FileType, VolumeHandle, &Fi= leHandle); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Search Section + // + SectionData =3D NULL; + Status =3D PeiServicesFfsFindSectionData (SectionType, FileHandle= , Buffer); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Great! + // + SectionData =3D (EFI_PE32_SECTION *)((UINT8 *)*Buffer - sizeof (EFI_PE= 32_SECTION)); + ASSERT (SectionData->Type =3D=3D SectionType); + SectionSize =3D *(UINT32 *)SectionData->Size; + SectionSize &=3D 0xFFFFFF; + *Size =3D SectionSize - sizeof (EFI_PE32_SECTION); + + if (FileType =3D=3D EFI_FV_FILETYPE_MM_CORE_STANDALONE) { + EFI_FV_INFO VolumeInfo; + // + // This is SMM BFV + // + Status =3D PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo); + if (!EFI_ERROR (Status)) { + gMmCorePrivate->StandaloneBfvAddress =3D (EFI_PHYSICAL_ADDRESS)(UI= NTN)VolumeInfo.FvStart; + } + } + + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +/** + Load the SMM Core image into SMRAM and executes the SMM Core from SMRAM. + + @param[in, out] SmramRange Descriptor for the range of SMRAM = to reload the + currently executing image, the ran= g of SMRAM to + hold SMM Core will be excluded. + @param[in, out] SmramRangeSmmCore Descriptor for the range of SMRAM = to hold SMM Core. + + @param[in] Context Context to pass into SMM Core + + @return EFI_STATUS + +**/ +EFI_STATUS +ExecuteSmmCoreFromSmram ( + IN OUT EFI_SMRAM_DESCRIPTOR *SmramRange, + IN OUT EFI_SMRAM_DESCRIPTOR *SmramRangeSmmCore, + IN VOID *Context + ) +{ + EFI_STATUS Status; + VOID *SourceBuffer; + UINTN SourceSize; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + UINTN PageCount; + VOID *HobList; + + Status =3D PeiServicesGetHobList (&HobList); + ASSERT_EFI_ERROR (Status); + + // + // Search all Firmware Volumes for a PE/COFF image in a file of type SMM= _CORE + // + Status =3D GetSectionFromAnyFvByFileType ( + EFI_FV_FILETYPE_MM_CORE_STANDALONE, + 0, + EFI_SECTION_PE32, + 0, + &SourceBuffer, + &SourceSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Initialize ImageContext + // + ImageContext.Handle =3D SourceBuffer; + ImageContext.ImageRead =3D PeCoffLoaderImageReadFromMemory; + + // + // Get information about the image being loaded + // + Status =3D PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // if Loading module at Fixed Address feature is enabled, the SMM core d= river will be loaded to + // the address assigned by build tool. + // + if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) !=3D 0) { + // + // Get the fixed loading address assigned by Build tool + // + Status =3D GetPeCoffImageFixLoadingAssignedAddress (&ImageContext); + if (!EFI_ERROR (Status)) { + // + // Since the memory range to load SMM CORE will be cut out in SMM co= re, so no need to allocate and free this range + // + PageCount =3D 0; + // + // Reserved Smram Region for SmmCore is not used, and remove it from= SmramRangeCount. + // + gMmCorePrivate->MmramRangeCount--; + } else { + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR: Loading module at f= ixed address at address failed\n")); + // + // Allocate memory for the image being loaded from the EFI_SRAM_DESC= RIPTOR + // specified by SmramRange + // + PageCount =3D (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSiz= e + ImageContext.SectionAlignment); + + ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) =3D=3D 0); + ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount)); + + SmramRange->PhysicalSize -=3D EFI_PAGES_TO_SIZE (PageCount); + SmramRangeSmmCore->CpuStart =3D SmramRange->CpuStart + SmramRan= ge->PhysicalSize; + SmramRangeSmmCore->PhysicalStart =3D SmramRange->PhysicalStart + Smr= amRange->PhysicalSize; + SmramRangeSmmCore->RegionState =3D SmramRange->RegionState | EFI_A= LLOCATED; + SmramRangeSmmCore->PhysicalSize =3D EFI_PAGES_TO_SIZE (PageCount); + + // + // Align buffer on section boundary + // + ImageContext.ImageAddress =3D SmramRangeSmmCore->CpuStart; + } + } else { + // + // Allocate memory for the image being loaded from the EFI_SRAM_DESCRI= PTOR + // specified by SmramRange + // + PageCount =3D (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize = + ImageContext.SectionAlignment); + + ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) =3D=3D 0); + ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount)); + + SmramRange->PhysicalSize -=3D EFI_PAGES_TO_SIZE (PageCount); + SmramRangeSmmCore->CpuStart =3D SmramRange->CpuStart + SmramRange= ->PhysicalSize; + SmramRangeSmmCore->PhysicalStart =3D SmramRange->PhysicalStart + Smram= Range->PhysicalSize; + SmramRangeSmmCore->RegionState =3D SmramRange->RegionState | EFI_ALL= OCATED; + SmramRangeSmmCore->PhysicalSize =3D EFI_PAGES_TO_SIZE (PageCount); + + // + // Align buffer on section boundary + // + ImageContext.ImageAddress =3D SmramRangeSmmCore->CpuStart; + } + + ImageContext.ImageAddress +=3D ImageContext.SectionAlignment - 1; + ImageContext.ImageAddress &=3D ~((EFI_PHYSICAL_ADDRESS)ImageContext.Sect= ionAlignment - 1); + + // + // Print debug message showing SMM Core load address. + // + DEBUG ((DEBUG_INFO, "SMM IPL loading SMM Core at SMRAM address %p\n", (V= OID *)(UINTN)ImageContext.ImageAddress)); + + // + // Load the image to our new buffer + // + Status =3D PeCoffLoaderLoadImage (&ImageContext); + if (!EFI_ERROR (Status)) { + // + // Relocate the image in our new buffer + // + Status =3D PeCoffLoaderRelocateImage (&ImageContext); + if (!EFI_ERROR (Status)) { + // + // Flush the instruction cache so the image data are written before = we execute it + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAd= dress, (UINTN)ImageContext.ImageSize); + + // + // Print debug message showing SMM Core entry point address. + // + DEBUG ((DEBUG_INFO, "SMM IPL calling SMM Core at SMRAM address %p\n"= , (VOID *)(UINTN)ImageContext.EntryPoint)); + + gMmCorePrivate->MmCoreImageBase =3D ImageContext.ImageAddress; + gMmCorePrivate->MmCoreImageSize =3D ImageContext.ImageSize; + DEBUG ((DEBUG_INFO, "SmmCoreImageBase - 0x%016lx\n", gMmCorePrivate-= >MmCoreImageBase)); + DEBUG ((DEBUG_INFO, "SmmCoreImageSize - 0x%016lx\n", gMmCorePrivate-= >MmCoreImageSize)); + + gMmCorePrivate->MmCoreEntryPoint =3D ImageContext.EntryPoint; + + // + // Print debug message showing Standalone MM Core entry point addres= s. + // + DEBUG ((DEBUG_INFO, "SMM IPL calling Standalone MM Core at SMRAM add= ress - 0x%016lx\n", gMmCorePrivate->MmCoreEntryPoint)); + + // + // Execute image + // + LoadSmmCore (ImageContext.EntryPoint, HobList); + } + } + + // + // If the load operation, relocate operation, or the image execution ret= urn an + // error, then free memory allocated from the EFI_SRAM_DESCRIPTOR specif= ied by + // SmramRange + // + if (EFI_ERROR (Status)) { + SmramRange->PhysicalSize +=3D EFI_PAGES_TO_SIZE (PageCount); + } + + // + // Always free memory allocated by GetFileBufferByFilePath () + // + FreePool (SourceBuffer); + + return Status; +} + +/** + Get full SMRAM ranges. + + It will get SMRAM ranges from SmmAccess protocol and SMRAM reserved rang= es from + SmmConfiguration protocol, split the entries if there is overlap between= them. + It will also reserve one entry for SMM core. + + @param[in] PeiServices Describes the list of possible PEI Ser= vices. + @param[out] FullSmramRangeCount Output pointer to full SMRAM range cou= nt. + + @return Pointer to full SMRAM ranges. + +**/ +EFI_SMRAM_DESCRIPTOR * +GetFullSmramRanges ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINTN *FullSmramRangeCount + ) +{ + EFI_STATUS Status; + UINTN Size; + EFI_SMRAM_DESCRIPTOR *FullSmramRanges; + UINTN AdditionSmramRangeCount; + UINTN SmramRangeCount; + + // + // Get SMRAM information. + // + Size =3D 0; + Status =3D mSmmAccess->GetCapabilities ((EFI_PEI_SERVICES **)PeiServices= , mSmmAccess, &Size, NULL); + ASSERT (Status =3D=3D EFI_BUFFER_TOO_SMALL); + + SmramRangeCount =3D Size / sizeof (EFI_SMRAM_DESCRIPTOR); + + // + // Reserve one entry SMM Core in the full SMRAM ranges. + // + AdditionSmramRangeCount =3D 1; + if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) !=3D 0) { + // + // Reserve two entries for all SMM drivers & SMM Core in the full SMRA= M ranges. + // + AdditionSmramRangeCount =3D 2; + } + + *FullSmramRangeCount =3D SmramRangeCount + AdditionSmramRangeCount; + Size =3D (*FullSmramRangeCount) * sizeof (EFI_SMRAM_DESC= RIPTOR); + FullSmramRanges =3D (EFI_SMRAM_DESCRIPTOR *)AllocateZeroPool (Size); + ASSERT (FullSmramRanges !=3D NULL); + if (FullSmramRanges =3D=3D NULL) { + return NULL; + } + + Status =3D mSmmAccess->GetCapabilities ((EFI_PEI_SERVICES **)PeiServices= , mSmmAccess, &Size, FullSmramRanges); + + ASSERT_EFI_ERROR (Status); + + return FullSmramRanges; +} + +/** + The Entry Point for SMM IPL + + Load SMM Core into SMRAM. + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval Other Some error occurred when executing this entry poi= nt. + +**/ +EFI_STATUS +EFIAPI +SmmIplEntry ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + UINTN Index; + UINT64 MaxSize; + UINT64 SmmCodeSize; + MM_CORE_DATA_HOB_DATA SmmCoreDataHobData; + EFI_SMRAM_DESCRIPTOR *MmramRanges; + EFI_SMRAM_DESCRIPTOR *SmramRangeSmmDriver; + + // + // Build Hob for SMM and DXE phase + // + SmmCoreDataHobData.Address =3D (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateRunt= imePages (EFI_SIZE_TO_PAGES (sizeof (mMmCorePrivateData))); + ASSERT (SmmCoreDataHobData.Address !=3D 0); + gMmCorePrivate =3D (VOID *)(UINTN)SmmCoreDataHobData.Address; + CopyMem ((VOID *)(UINTN)SmmCoreDataHobData.Address, &mMmCorePrivateData,= sizeof (mMmCorePrivateData)); + DEBUG ((DEBUG_INFO, "gMmCorePrivate - 0x%x\n", gMmCorePrivate)); + + BuildGuidDataHob ( + &gMmCoreDataHobGuid, + (VOID *)&SmmCoreDataHobData, + sizeof (SmmCoreDataHobData) + ); + + // + // Get SMM Access Protocol + // + Status =3D PeiServicesLocatePpi (&gPeiSmmAccessPpiGuid, 0, NULL, (VOID *= *)&mSmmAccess); + ASSERT_EFI_ERROR (Status); + + // + // Get SMRAM information + // + gMmCorePrivate->MmramRanges =3D (EFI_PHYSICAL_ADDRESS)(UINTN)GetFullSmra= mRanges (PeiServices, (UINTN *)&gMmCorePrivate->MmramRangeCount); + ASSERT (gMmCorePrivate->MmramRanges !=3D 0); + if (gMmCorePrivate->MmramRanges =3D=3D 0) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Open all SMRAM ranges + // + Status =3D mSmmAccess->Open ((EFI_PEI_SERVICES **)PeiServices, mSmmAcces= s, 0); + ASSERT_EFI_ERROR (Status); + + // + // Print debug message that the SMRAM window is now open. + // + DEBUG ((DEBUG_INFO, "SMM IPL opened SMRAM window\n")); + + // + // Find the largest SMRAM range between 1MB and 4GB that is at least 256= KB - 4K in size + // + mCurrentSmramRange =3D NULL; + MmramRanges =3D (EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->Mm= ramRanges; + if (MmramRanges =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "Fail to retrieve MmramRanges\n")); + return EFI_UNSUPPORTED; + } + + for (Index =3D 0, MaxSize =3D SIZE_256KB - EFI_PAGE_SIZE; Index < gMmCor= ePrivate->MmramRangeCount; Index++) { + // + // Skip any SMRAM region that is already allocated, needs testing, or = needs ECC initialization + // + if ((MmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTI= NG | EFI_NEEDS_ECC_INITIALIZATION)) !=3D 0) { + continue; + } + + if (MmramRanges[Index].CpuStart >=3D BASE_1MB) { + if ((MmramRanges[Index].CpuStart + MmramRanges[Index].PhysicalSize) = <=3D BASE_4GB) { + if (MmramRanges[Index].PhysicalSize >=3D MaxSize) { + MaxSize =3D MmramRanges[Index].PhysicalSize; + mCurrentSmramRange =3D &MmramRanges[Index]; + } + } + } + } + + if (mCurrentSmramRange !=3D NULL) { + // + // Print debug message showing SMRAM window that will be used by SMM I= PL and SMM Core + // + DEBUG (( + DEBUG_INFO, + "SMM IPL found SMRAM window %p - %p\n", + (VOID *)(UINTN)mCurrentSmramRange->CpuStart, + (VOID *)(UINTN)(mCurrentSmramRange->CpuStart + mCurrentSmramRange->P= hysicalSize - 1) + )); + + GetSmramCacheRange (mCurrentSmramRange, &mSmramCacheBase, &mSmramCache= Size); + + // + // if Loading module at Fixed Address feature is enabled, save the SMR= AM base to Load + // Modules At Fixed Address Configuration Table. + // + if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) !=3D 0) { + // + // Build tool will calculate the smm code size and then patch the Pc= dLoadFixAddressSmmCodePageNumber + // + SmmCodeSize =3D LShiftU64 (PcdGet32 (PcdLoadFixAddressSmmCodePageNum= ber), EFI_PAGE_SHIFT); + // + // The SMRAM available memory is assumed to be larger than SmmCodeSi= ze + // + ASSERT (mCurrentSmramRange->PhysicalSize > SmmCodeSize); + // + // Fill the Smram range for all SMM code + // + MmramRanges =3D (EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->Mmram= Ranges; + // + // Note: SmramRanges specific for all SMM code will put in the gMmCo= rePrivate->MmramRangeCount - 2. + // + SmramRangeSmmDriver =3D &MmramRanges[gMmCorePrivate->= MmramRangeCount - 2]; + SmramRangeSmmDriver->CpuStart =3D mCurrentSmramRange->CpuStart; + SmramRangeSmmDriver->PhysicalStart =3D mCurrentSmramRange->PhysicalS= tart; + SmramRangeSmmDriver->RegionState =3D mCurrentSmramRange->RegionSta= te | EFI_ALLOCATED; + SmramRangeSmmDriver->PhysicalSize =3D SmmCodeSize; + + mCurrentSmramRange->PhysicalSize -=3D SmmCodeSize; + mCurrentSmramRange->CpuStart =3D mCurrentSmramRange->CpuStart += SmmCodeSize; + mCurrentSmramRange->PhysicalStart =3D mCurrentSmramRange->PhysicalSt= art + SmmCodeSize; + } + + // + // Load SMM Core into SMRAM and execute it from SMRAM + // Note: SmramRanges specific for SMM Core will put in the gMmCorePriv= ate->MmramRangeCount - 1. + // + Status =3D ExecuteSmmCoreFromSmram ( + mCurrentSmramRange, + &(((EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->MmramRang= es)[gMmCorePrivate->MmramRangeCount - 1]), + gMmCorePrivate + ); + if (EFI_ERROR (Status)) { + // + // Print error message that the SMM Core failed to be loaded and exe= cuted. + // + DEBUG ((DEBUG_ERROR, "SMM IPL could not load and execute SMM Core fr= om SMRAM\n")); + } + } else { + // + // Print error message that there are not enough SMRAM resources to lo= ad the SMM Core. + // + DEBUG ((DEBUG_ERROR, "SMM IPL could not find a large enough SMRAM regi= on to load SMM Core\n")); + } + + // + // If the SMM Core could not be loaded then close SMRAM window, free all= ocated + // resources, and return an error so SMM IPL will be unloaded. + // + if ((mCurrentSmramRange =3D=3D NULL) || EFI_ERROR (Status)) { + // + // Close all SMRAM ranges + // + Status =3D mSmmAccess->Close ((EFI_PEI_SERVICES **)PeiServices, mSmmAc= cess, 0); + ASSERT_EFI_ERROR (Status); + + // + // Print debug message that the SMRAM window is now closed. + // + DEBUG ((DEBUG_INFO, "SMM IPL closed SMRAM window\n")); + + // + // Free all allocated resources + // + FreePool ((VOID *)(UINTN)gMmCorePrivate->MmramRanges); + + return EFI_UNSUPPORTED; + } + + // + // Create ready to boot for close and lock smram ranges + // + Status =3D PeiServicesNotifyPpi (&mReadyToBootNotifyList); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c b= /StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c new file mode 100644 index 0000000000..6d3497f2ea --- /dev/null +++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c @@ -0,0 +1,32 @@ +/** @file + SMM IPL that load the SMM Core into SMRAM + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Load SMM core to dispatch other Standalone MM drivers. + + @param Entry Entry of Standalone MM Foundation. + @param Context1 A pointer to the context to pass into = the EntryPoint + function. + @retval EFI_SUCCESS Successfully loaded SMM core. + @retval Others Failed to load SMM core. +**/ +EFI_STATUS +LoadSmmCore ( + IN EFI_PHYSICAL_ADDRESS Entry, + IN VOID *Context1 + ) +{ + STANDALONE_MM_FOUNDATION_ENTRY_POINT EntryPoint; + + EntryPoint =3D (STANDALONE_MM_FOUNDATION_ENTRY_POINT)(UINTN)Entry; + return EntryPoint (Context1); +} diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.na= sm b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm new file mode 100644 index 0000000000..7f887eb77d --- /dev/null +++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm @@ -0,0 +1,148 @@ +;-------------------------------------------------------------------------= ----- +; +; Copyright (c) 2023, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; Thunk32To64.nasm +; +; Abstract: +; +; This is the assembly code to transition from long mode to compatibility +; mode to execute 32-bit code and then transit back to long mode. +; +;-------------------------------------------------------------------------= ----- + + SECTION .text + +;-------------------------------------------------------------------------= ----- +; Procedure: AsmExecute64BitCode +; +; Input: None +; +; Output: None +; +; Prototype: UINT32 +; AsmExecute64BitCode ( +; IN UINT64 Function, +; IN UINT64 Param1, +; IN UINT64 Param2, +; IN IA32_DESCRIPTOR *InternalGdtr +; ); +; +; +; Description: A thunk function to execute 32-bit code in long mode. +; +;-------------------------------------------------------------------------= ----- +global ASM_PFX(AsmExecute64BitCode) +ASM_PFX(AsmExecute64BitCode): +; +; +---------+ +; | EIP(64) | +; +---------+ +; | CS (64) | +; +---------+ +; | EIP(32) | +; +---------+ +; | CS (32) |<-ESP (16 bytes aligned) +; +---------+ +; | ... | +; +---------+ +; | ebx |<-EBP +; +---------+ +; | ebp |<-EBP + 4 +; +---------+ +; | esi |<-EBP + 8 +; +---------+ +; | edi |<-EBP + 12 +; +---------+ +; | RFlags |<-EBP + 16 +; +---------+ +; | RetAddr |<-EBP (org) +; +---------+ +; | Func |<-EBP + 24 +; | Func | +; +---------+ +; | Param1 |<-EBP + 32 +; | Param1 | +; +---------+ +; | Param2 |<-EBP + 40 +; | Param2 | +; +---------+ +; | Gdtr | +; +---------+ +; + ; + ; Save general purpose register and RFlags register + ; + pushfd + push edi + push esi + push ebp + push ebx + mov ebp, esp + + and esp, 0FFFFFFF0h + + push 010h ; protected mode selector on stack + mov eax, Compatible ; offset for LongMode + push eax ; offset on stack + + push 038h ; long mode selector on stack + mov eax, LongMode ; offset for LongMode + push eax ; offset on stack + + mov eax, cr4 + or al, 020h + mov cr4, eax ; enable PAE + mov ecx, 0c0000080h + rdmsr + or ah, 1 ; set LME + wrmsr + mov eax, cr0 + bts eax, 31 ; set PG + mov cr0, eax ; enable paging + retf ; topmost 2 dwords hold the address +LongMode: ; long mode starts here + + ; Call long mode function + DB 67h, 48h ; 32-bit address size, 64-bit oper= and size + mov eax, [ebp + 24] ; mov rbx, [ebp + 24] + DB 67h, 48h + mov ecx, [ebp + 24 + 8] ; mov rcx, [ebp + 24 + 8] + DB 67h, 48h + mov edx, [ebp + 24 + 16] ; mov rdx, [ebp + 24 + 16] + + DB 48h + add esp, -20h ; add rsp, -20h + call eax ; call rax + DB 48h + add esp, 20h ; add rsp, 20h + + ; after long mode function call + mov ebx, eax + + retf +Compatible: + mov ecx, cr0 + btc ecx, 31 ; clear PG + mov cr0, ecx ; disable paging + mov ecx, 0C0000080h + rdmsr + btc eax, 8 ; clear LME + wrmsr + + ; + ; Restore C register and eax hold the return status from 32-bit functi= on. + ; Note: Do not touch rax from now which hold the return value from IA3= 2 function + ; + mov eax, ebx ; put return status to EAX + mov esp, ebp ; restore stack pointer + pop ebx + pop ebp + pop esi + pop edi + popfd + + ret diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.= h b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h new file mode 100644 index 0000000000..be0aae70f0 --- /dev/null +++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h @@ -0,0 +1,66 @@ +/** @file + Private header with declarations and definitions specific to the Standal= one + MM IPL PEI driver + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef STANDALONE_MM_IPL_PEI_H_ +#define STANDALONE_MM_IPL_PEI_H_ + +/** + Load SMM core to dispatch other Standalone MM drivers. + + @param Entry Entry of Standalone MM Foundation. + @param Context1 A pointer to the context to pass into = the EntryPoint + function. + @retval EFI_SUCCESS Successfully loaded SMM core. + @retval Others Failed to load SMM core. +**/ +EFI_STATUS +LoadSmmCore ( + IN EFI_PHYSICAL_ADDRESS Entry, + IN VOID *Context1 + ); + +/** + Assembly function to transition from long mode to compatibility mode to + execute 32-bit code and then transit back to long mode. + + @param[in] Function The 32bit code entry to be executed. + @param[in] Param1 The first parameter to pass to 32bit code + @param[in] Param2 The second parameter to pass to 32bit code + @param[in] InternalGdtr The GDT and GDT descriptor used by this library + + @retval status. +**/ +UINT32 +AsmExecute64BitCode ( + IN UINT64 Function, + IN UINT64 Param1, + IN UINT64 Param2, + IN IA32_DESCRIPTOR *InternalGdtr + ); + +/** + This is the callback function on ready to boot. + + Close and lock smram ranges on ready to boot stage. + + @param PeiServices General purpose services available to every P= EIM. + @param NotifyDescriptor The notification structure this PEIM register= ed on install. + @param Ppi Pointer to the PPI data associated with this = function. + @retval EFI_SUCCESS Close and lock smram ranges successfully. + @retval Other Close and lock smram ranges failed. +**/ +EFI_STATUS +EFIAPI +ReadyToBootEvent ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +#endif diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.= inf b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf new file mode 100644 index 0000000000..ff4c67a92c --- /dev/null +++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf @@ -0,0 +1,75 @@ +## @file +# This module provide a Standalone SMM compliant implementation of SMM IP= L PEIM. +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D StandaloneMmIplPei + FILE_GUID =3D 578A0D17-2DC0-4C7D-A121-D8D771923BB0 + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + PI_SPECIFICATION_VERSION =3D 0x0001000A + ENTRY_POINT =3D SmmIplEntry + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Sources] + StandaloneMmIplPei.h + StandaloneMmIplPei.c + +[Sources.Ia32] + Ia32/LoadSmmCore.c + Ia32/Thunk32To64.nasm + +[Sources.X64] + X64/LoadSmmCore.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + StandaloneMmPkg/StandaloneMmPkg.dec + +[LibraryClasses] + PeimEntryPoint + PeiServicesTablePointerLib + PeiServicesLib + BaseLib + BaseMemoryLib + PeCoffLib + CacheMaintenanceLib + MemoryAllocationLib + DebugLib + HobLib + IntrinsicLib + +[Guids] + gMmCoreDataHobGuid + gEfiEventReadyToBootGuid + +[Ppis] + gPeiSmmAccessPpiGuid ## CONSUMES + gPeiSmmControlPpiGuid ## CONSUMES + +[FeaturePcd.IA32] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES + +[Pcd.IA32] + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIM= ES_CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber ##= SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable ##= CONSUMES + +[Depex] + gPeiSmmAccessPpiGuid AND + gPeiSmmControlPpiGuid + diff --git a/StandaloneMmPkg/StandaloneMmPkg.ci.yaml b/StandaloneMmPkg/Stan= daloneMmPkg.ci.yaml index 4777532a7e..872f7958be 100644 --- a/StandaloneMmPkg/StandaloneMmPkg.ci.yaml +++ b/StandaloneMmPkg/StandaloneMmPkg.ci.yaml @@ -78,7 +78,9 @@ ## options defined .pytool/Plugin/SpellCheck "SpellCheck": { "AuditOnly": False, - "IgnoreFiles": [], # use gitignore syntax to ignore erro= rs + "IgnoreFiles": [ + "Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm" + ], # use gitignore syntax to ignore errors # in matching files "ExtendWords": [ "Bsymbolic", diff --git a/StandaloneMmPkg/StandaloneMmPkg.dsc b/StandaloneMmPkg/Standalo= neMmPkg.dsc index 8012f93b7d..d88471fe82 100644 --- a/StandaloneMmPkg/StandaloneMmPkg.dsc +++ b/StandaloneMmPkg/StandaloneMmPkg.dsc @@ -20,7 +20,7 @@ PLATFORM_VERSION =3D 1.0 DSC_SPECIFICATION =3D 0x00010011 OUTPUT_DIRECTORY =3D Build/StandaloneMm - SUPPORTED_ARCHITECTURES =3D AARCH64|X64|ARM + SUPPORTED_ARCHITECTURES =3D AARCH64|X64|ARM|IA32 BUILD_TARGETS =3D DEBUG|RELEASE SKUID_IDENTIFIER =3D DEFAULT =20 @@ -60,6 +60,14 @@ StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint= /StandaloneMmDriverEntryPoint.inf VariableMmDependency|StandaloneMmPkg/Library/VariableMmDependency/Variab= leMmDependency.inf =20 +[LibraryClasses.common.PEIM] + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAlloc= ationLib.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/Pei= ServicesTablePointerLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + [LibraryClasses.AARCH64, LibraryClasses.ARM] ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf StandaloneMmMmuLib|ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmL= ib.inf @@ -104,7 +112,7 @@ # generated for it, but the binary will not be put into any firmware= volume. # ##########################################################################= ######################### -[Components.common] +[Components.AARCH64, Components.ARM, Components.X64] # # MM Core # @@ -122,6 +130,9 @@ StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/StandaloneMmPeC= offExtraActionLib.inf =20 +[Components.X64, Components.IA32] + StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf + ##########################################################################= ######################### # # BuildOptions Section - Define the module specific tool chain flags that = should be used as diff --git a/UefiPayloadPkg/UniversalPayloadBuild.sh b/UefiPayloadPkg/Unive= rsalPayloadBuild.sh index 9a72eedd35..bacf5233a8 100644 --- a/UefiPayloadPkg/UniversalPayloadBuild.sh +++ b/UefiPayloadPkg/UniversalPayloadBuild.sh @@ -1,17 +1,17 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2022, Intel Corporation. All rights reserved.
-# -# SPDX-License-Identifier: BSD-2-Clause-Patent -# - -if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then - echo python_exe=3D${PYTHON_COMMAND} -fi - -# Get file path of UniversalPayloadBuild.sh -uplbld_filepath=3D${BASH_SOURCE:-$0} -# Remove ".sh" extension -uplbld_filepath_noext=3D${uplbld_filepath%.*} -# execute UniversalPayloadBuild.py to build UefiPayloadPkg -exec "${python_exe:-python}" "$uplbld_filepath_noext.py" "$@" +#!/usr/bin/env bash +# +# Copyright (c) 2022, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then + echo python_exe=3D${PYTHON_COMMAND} +fi + +# Get file path of UniversalPayloadBuild.sh +uplbld_filepath=3D${BASH_SOURCE:-$0} +# Remove ".sh" extension +uplbld_filepath_noext=3D${uplbld_filepath%.*} +# execute UniversalPayloadBuild.py to build UefiPayloadPkg +exec "${python_exe:-python}" "$uplbld_filepath_noext.py" "$@" diff --git a/edksetup.sh b/edksetup.sh index cab3a8c113..553e1676d0 100755 --- a/edksetup.sh +++ b/edksetup.sh @@ -1,147 +1,147 @@ -# -# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
-# Copyright (c) 2016, Linaro Ltd. All rights reserved.
-# SPDX-License-Identifier: BSD-2-Clause-Patent -# -# In *inux environment, the build tools's source is required and need to b= e compiled -# firstly, please reference https://github.com/tianocore/tianocore.github.= io/wiki/SourceForge-to-Github-Quick-Start -# to get how to setup build tool. -# -# Setup the environment for unix-like systems running a bash-like shell. -# This file must be "sourced" not merely executed. For example: ". edksetu= p.sh" -# -# CYGWIN users: Your path and filename related environment variables shoul= d be -# set up in the unix style. This script will make the necessary conversio= ns to -# windows style. -# -# Please reference edk2 user manual for more detail descriptions at https:= //github.com/tianocore-docs/Docs/raw/master/User_Docs/EDK_II_UserManual_0_7= .pdf -# - -SCRIPTNAME=3D"edksetup.sh" -RECONFIG=3DFALSE - -HelpMsg() -{ - echo "Usage: $SCRIPTNAME [Options]" - echo - echo "The system environment variable, WORKSPACE, is always set to the c= urrent" - echo "working directory." - echo - echo "Options: " - echo " --help, -h, -? Print this help screen and exit." - echo - echo " --reconfig Overwrite the WORKSPACE/Conf/*.txt files w= ith the" - echo " template files from the BaseTools/Conf dir= ectory." - echo - echo Please note: This script must be \'sourced\' so the environment can= be changed. - echo ". $SCRIPTNAME" - echo "source $SCRIPTNAME" -} - -SetWorkspace() -{ - # - # If WORKSPACE is already set, then we can return right now - # - export PYTHONHASHSEED=3D1 - if [ -n "$WORKSPACE" ] - then - return 0 - fi - - if [ ! -f ${SCRIPTNAME} ] && [ -z "$PACKAGES_PATH" ] - then - echo Source this script from the base of your tree. For example: - echo " cd /Path/To/Edk2/Clone" - echo " . $SCRIPTNAME" - return 1 - fi - - # - # Check for BaseTools/BuildEnv before dirtying the user's environment. - # - if [ ! -f BaseTools/BuildEnv ] && [ -z "$EDK_TOOLS_PATH" ] - then - echo BaseTools not found in your tree, and EDK_TOOLS_PATH is not set. - echo Please point EDK_TOOLS_PATH at the directory that contains - echo the EDK2 BuildEnv script. - return 1 - fi - - # - # Set $WORKSPACE - # - export WORKSPACE=3D$PWD - return 0 -} - -SetupEnv() -{ - if [ -n "$EDK_TOOLS_PATH" ] - then - . $EDK_TOOLS_PATH/BuildEnv - elif [ -f "$WORKSPACE/BaseTools/BuildEnv" ] - then - . $WORKSPACE/BaseTools/BuildEnv - elif [ -n "$PACKAGES_PATH" ] - then - for DIR in $(echo $PACKAGES_PATH | tr ':' ' ') - do - if [ -f "$DIR/BaseTools/BuildEnv" ] - then - export EDK_TOOLS_PATH=3D$DIR/BaseTools - . $DIR/BaseTools/BuildEnv - break - fi - done - else - echo BaseTools not found in your tree, and EDK_TOOLS_PATH is not set. - echo Please check that WORKSPACE or PACKAGES_PATH is not set incorrect= ly - echo in your shell, or point EDK_TOOLS_PATH at the directory that cont= ains - echo the EDK2 BuildEnv script. - return 1 - fi -} - -SetupPython3() -{ - export PYTHON_COMMAND=3Dpython3 -} - -SourceEnv() -{ - SetupPython3 - SetWorkspace - SetupEnv -} - -I=3D$# -while [ $I -gt 0 ] -do - case "$1" in - BaseTools) - # Ignore argument for backwards compatibility - shift - ;; - --reconfig) - RECONFIG=3DTRUE - shift - ;; - *) - HelpMsg - break - ;; - esac - I=3D$((I - 1)) -done - -if [ $I -gt 0 ] -then - return 1 -fi - -SourceEnv - -unset SCRIPTNAME RECONFIG - -return $? +# +# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+# Copyright (c) 2016, Linaro Ltd. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# In *inux environment, the build tools's source is required and need to b= e compiled +# firstly, please reference https://github.com/tianocore/tianocore.github.= io/wiki/SourceForge-to-Github-Quick-Start +# to get how to setup build tool. +# +# Setup the environment for unix-like systems running a bash-like shell. +# This file must be "sourced" not merely executed. For example: ". edksetu= p.sh" +# +# CYGWIN users: Your path and filename related environment variables shoul= d be +# set up in the unix style. This script will make the necessary conversio= ns to +# windows style. +# +# Please reference edk2 user manual for more detail descriptions at https:= //github.com/tianocore-docs/Docs/raw/master/User_Docs/EDK_II_UserManual_0_7= .pdf +# + +SCRIPTNAME=3D"edksetup.sh" +RECONFIG=3DFALSE + +HelpMsg() +{ + echo "Usage: $SCRIPTNAME [Options]" + echo + echo "The system environment variable, WORKSPACE, is always set to the c= urrent" + echo "working directory." + echo + echo "Options: " + echo " --help, -h, -? Print this help screen and exit." + echo + echo " --reconfig Overwrite the WORKSPACE/Conf/*.txt files w= ith the" + echo " template files from the BaseTools/Conf dir= ectory." + echo + echo Please note: This script must be \'sourced\' so the environment can= be changed. + echo ". $SCRIPTNAME" + echo "source $SCRIPTNAME" +} + +SetWorkspace() +{ + # + # If WORKSPACE is already set, then we can return right now + # + export PYTHONHASHSEED=3D1 + if [ -n "$WORKSPACE" ] + then + return 0 + fi + + if [ ! -f ${SCRIPTNAME} ] && [ -z "$PACKAGES_PATH" ] + then + echo Source this script from the base of your tree. For example: + echo " cd /Path/To/Edk2/Clone" + echo " . $SCRIPTNAME" + return 1 + fi + + # + # Check for BaseTools/BuildEnv before dirtying the user's environment. + # + if [ ! -f BaseTools/BuildEnv ] && [ -z "$EDK_TOOLS_PATH" ] + then + echo BaseTools not found in your tree, and EDK_TOOLS_PATH is not set. + echo Please point EDK_TOOLS_PATH at the directory that contains + echo the EDK2 BuildEnv script. + return 1 + fi + + # + # Set $WORKSPACE + # + export WORKSPACE=3D$PWD + return 0 +} + +SetupEnv() +{ + if [ -n "$EDK_TOOLS_PATH" ] + then + . $EDK_TOOLS_PATH/BuildEnv + elif [ -f "$WORKSPACE/BaseTools/BuildEnv" ] + then + . $WORKSPACE/BaseTools/BuildEnv + elif [ -n "$PACKAGES_PATH" ] + then + for DIR in $(echo $PACKAGES_PATH | tr ':' ' ') + do + if [ -f "$DIR/BaseTools/BuildEnv" ] + then + export EDK_TOOLS_PATH=3D$DIR/BaseTools + . $DIR/BaseTools/BuildEnv + break + fi + done + else + echo BaseTools not found in your tree, and EDK_TOOLS_PATH is not set. + echo Please check that WORKSPACE or PACKAGES_PATH is not set incorrect= ly + echo in your shell, or point EDK_TOOLS_PATH at the directory that cont= ains + echo the EDK2 BuildEnv script. + return 1 + fi +} + +SetupPython3() +{ + export PYTHON_COMMAND=3Dpython3 +} + +SourceEnv() +{ + SetupPython3 + SetWorkspace + SetupEnv +} + +I=3D$# +while [ $I -gt 0 ] +do + case "$1" in + BaseTools) + # Ignore argument for backwards compatibility + shift + ;; + --reconfig) + RECONFIG=3DTRUE + shift + ;; + *) + HelpMsg + break + ;; + esac + I=3D$((I - 1)) +done + +if [ $I -gt 0 ] +then + return 1 +fi + +SourceEnv + +unset SCRIPTNAME RECONFIG + +return $? --=20 2.37.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#105142): https://edk2.groups.io/g/devel/message/105142 Mute This Topic: https://groups.io/mt/99079640/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-