From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=104.47.1.41; helo=eur01-ve1-obe.outbound.protection.outlook.com; envelope-from=supreeth.venkatesh@arm.com; receiver=edk2-devel@lists.01.org Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-ve1eur01on0041.outbound.protection.outlook.com [104.47.1.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 9D50D20946062 for ; Fri, 4 May 2018 16:28:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector1-arm-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=PFYLpiO8dwF6IftLYakflLkpO3jYlgf4UBndMnlFtaw=; b=mqR16CxWOCjxIJq+C1wDpqAEQ7H9Hw7gzd7jvgc4A06roVLva/+wa+UrPqD7ObMqz0waspZ5M2UBBZCQFDvR7HULFNqK7LQhzoGvtu2vEdygXJJ5oP0uB3Rx8oY0d7sVT8htErMd39O109qmWiF0xxABNMkZjMq/BlNt78q6q5o= Received: from AM4PR0802MB2306.eurprd08.prod.outlook.com (10.172.218.15) by AM4PR0802MB2276.eurprd08.prod.outlook.com (10.172.218.9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.735.16; Fri, 4 May 2018 23:28:02 +0000 Received: from AM4PR0802MB2306.eurprd08.prod.outlook.com ([fe80::e117:6f62:6a9b:6be4]) by AM4PR0802MB2306.eurprd08.prod.outlook.com ([fe80::e117:6f62:6a9b:6be4%8]) with mapi id 15.20.0735.016; Fri, 4 May 2018 23:28:01 +0000 From: Supreeth Venkatesh To: Achin Gupta CC: "edk2-devel@lists.01.org" , "michael.d.kinney@intel.com" , "liming.gao@intel.com" , "jiewen.yao@intel.com" , "leif.lindholm@linaro.org" , "ard.biesheuvel@linaro.org" , nd Thread-Topic: [PATCH v1 13/18] StandaloneMmPkg/Core: Implementation of Standalone MM Core Module. Thread-Index: AQHTzbWoRXOlD8g79kKvcYCVA98huqQZ1PeAgASESOA= Date: Fri, 4 May 2018 23:28:01 +0000 Message-ID: References: <20180406144223.10931-1-supreeth.venkatesh@arm.com> <20180406144223.10931-14-supreeth.venkatesh@arm.com> <20180430191942.GX663@e104320-lin> In-Reply-To: <20180430191942.GX663@e104320-lin> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=none (sender IP is ) smtp.mailfrom=Supreeth.Venkatesh@arm.com; x-originating-ip: [217.140.111.135] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; AM4PR0802MB2276; 7:eQ+wzEJggcchsOZE4DxNg2uKRQCzllFIh/BLjt2JS59zYZfPoqsdQkHp7aWUCrOPLGj2EZr40bZISvA2jIYkAnM529SXppp0OpmK9MSOyZYDwJGpp1tjuSPq5DPblfFm2Ud2LMZa6FcBmfgH84gKWu9MC/R6JF/5F5CKZJQOMhuA3OpwDgWMBrBqUNVFK+WxZ9iujBC0LXThWQyNwkNqvunsF74zIhTS5fYgA0g0zk+5EuU3MoqBixedawG99Vbw x-ms-exchange-antispam-srfa-diagnostics: SOS;SOR; x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(48565401081)(5600026)(2017052603328)(7153060)(7193020); SRVR:AM4PR0802MB2276; x-ms-traffictypediagnostic: AM4PR0802MB2276: x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(180628864354917)(788757137089)(162533806227266)(228905959029699); x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(10201501046)(93006095)(93001095)(3231254)(944501410)(52105095)(3002001)(6055026)(6041310)(20161123564045)(20161123562045)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123558120)(6072148)(201708071742011); SRVR:AM4PR0802MB2276; BCL:0; PCL:0; RULEID:; SRVR:AM4PR0802MB2276; x-forefront-prvs: 06628F7CA4 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(979002)(6029001)(39860400002)(396003)(366004)(346002)(376002)(39380400002)(199004)(189003)(50944005)(13464003)(40434004)(53936002)(81166006)(6636002)(4326008)(53376002)(7736002)(55016002)(6862004)(6306002)(9686003)(8936002)(6116002)(2900100001)(3846002)(5250100002)(97736004)(6246003)(68736007)(5890100001)(8676002)(25786009)(229853002)(72206003)(86362001)(966005)(3660700001)(478600001)(59450400001)(7696005)(6436002)(3280700002)(106356001)(15188155005)(102836004)(26005)(105586002)(11346002)(6506007)(305945005)(33656002)(76176011)(66066001)(5660300001)(14454004)(81156014)(316002)(99286004)(74316002)(53546011)(16200700003)(476003)(16799955002)(446003)(2906002)(54906003)(486006)(53946003)(959014)(559001)(569006); DIR:OUT; SFP:1101; SCL:1; SRVR:AM4PR0802MB2276; H:AM4PR0802MB2306.eurprd08.prod.outlook.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:; received-spf: None (protection.outlook.com: arm.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: wAF2HzO3IW++/h3D2/vmqLV0xNp70YtvmiVimF+6wc/4s9HLDR9ySsH6wcj3V1SCNYGhzgEkYkFAP6hcRfRrR8tEjPquhEamJmjkit25Qwywk1xzHqpynOsL//Mxq4Iw/LNeQolmfhcKpDl4HhfYFIV2XWlxHH+82VRbgnNKlqAtfYb1fvFpUiCkHvxyXnJ6 spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: f5b243b4-383c-4ce9-3490-08d5b216ade1 X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-Network-Message-Id: f5b243b4-383c-4ce9-3490-08d5b216ade1 X-MS-Exchange-CrossTenant-originalarrivaltime: 04 May 2018 23:28:01.6535 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM4PR0802MB2276 Subject: Re: [PATCH v1 13/18] StandaloneMmPkg/Core: Implementation of Standalone MM Core Module. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 04 May 2018 23:28:23 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable My response inline. -----Original Message----- From: Achin Gupta Sent: Monday, April 30, 2018 2:20 PM To: Supreeth Venkatesh Cc: edk2-devel@lists.01.org; michael.d.kinney@intel.com; liming.gao@intel.c= om; jiewen.yao@intel.com; leif.lindholm@linaro.org; ard.biesheuvel@linaro.o= rg; nd Subject: Re: [PATCH v1 13/18] StandaloneMmPkg/Core: Implementation of Stand= alone MM Core Module. Hi Supreeth, I think it is worth adding a signed off by Jiewen since he originally contributed the code and it has not changed much since. Please update the correct year in the copyright headers too. [Supreeth] Indeed. Cover letter includes contribution. Since, he is reviewi= ng it, added Reviewed-by. Acked-by: Achin Gupta cheers, Achin On Fri, Apr 06, 2018 at 03:42:18PM +0100, Supreeth Venkatesh wrote: > Management Mode (MM) is a generic term used to describe a secure > execution environment provided by the CPU and related silicon that is > entered when the CPU detects a MMI. For x86 systems, this can be > implemented with System Management Mode (SMM). For ARM systems, this can > be implemented with TrustZone (TZ). > A MMI can be a CPU instruction or interrupt. Upon detection of a MMI, a > CPU will jump to the MM Entry Point and save some portion of its state > (the "save state") such that execution can be resumed. > The MMI can be generated synchronously by software or asynchronously by > a hardware event. Each MMI source can be detected, cleared and disabled. > Some systems provide for special memory (Management Mode RAM or MMRAM) > which is set aside for software running in MM. Usually the MMRAM is > hidden during normal CPU execution, but this is not required. Usually, > after MMRAM is hidden it cannot be exposed until the next system reset. > > The MM Core Interface Specification describes three pieces of the PI > Management Mode architecture: > 1. MM Dispatch > During DXE, the DXE Foundation works with the MM Foundation to > schedule MM drivers for execution in the discovered firmware volumes. > 2. MM Initialization > MM related code opens MMRAM, creates the MMRAM memory map, and > launches the MM Foundation, which provides the necessary services to > launch MM-related drivers. Then, sometime before boot, MMRAM is > closed and locked. This piece may be completed during the > SEC, PEI or DXE phases. > 3. MMI Management > When an MMI generated, the MM environment is created and then the MMI > > sources are detected and MMI handlers called. > > This patch implements the MM Core. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Achin Gupta > Signed-off-by: Supreeth Venkatesh > --- > StandaloneMmPkg/Core/Dependency.c | 389 +++++++ > StandaloneMmPkg/Core/Dispatcher.c | 1071 ++++++++++++++= ++++++ > StandaloneMmPkg/Core/FwVol.c | 104 ++ > StandaloneMmPkg/Core/Handle.c | 533 ++++++++++ > StandaloneMmPkg/Core/InstallConfigurationTable.c | 178 ++++ > StandaloneMmPkg/Core/Locate.c | 496 +++++++++ > StandaloneMmPkg/Core/Mmi.c | 337 ++++++ > StandaloneMmPkg/Core/Notify.c | 203 ++++ > StandaloneMmPkg/Core/Page.c | 384 +++++++ > StandaloneMmPkg/Core/Pool.c | 287 ++++++ > StandaloneMmPkg/Core/StandaloneMmCore.c | 708 +++++++++++++ > StandaloneMmPkg/Core/StandaloneMmCore.h | 903 ++++++++++++++= +++ > StandaloneMmPkg/Core/StandaloneMmCore.inf | 80 ++ > StandaloneMmPkg/Core/StandaloneMmCorePrivateData.h | 66 ++ > StandaloneMmPkg/Include/Guid/MmFvDispatch.h | 38 + > StandaloneMmPkg/Include/StandaloneMm.h | 36 + > 16 files changed, 5813 insertions(+) > create mode 100644 StandaloneMmPkg/Core/Dependency.c > create mode 100644 StandaloneMmPkg/Core/Dispatcher.c > create mode 100644 StandaloneMmPkg/Core/FwVol.c > create mode 100644 StandaloneMmPkg/Core/Handle.c > create mode 100644 StandaloneMmPkg/Core/InstallConfigurationTable.c > create mode 100644 StandaloneMmPkg/Core/Locate.c > create mode 100644 StandaloneMmPkg/Core/Mmi.c > create mode 100644 StandaloneMmPkg/Core/Notify.c > create mode 100644 StandaloneMmPkg/Core/Page.c > create mode 100644 StandaloneMmPkg/Core/Pool.c > create mode 100644 StandaloneMmPkg/Core/StandaloneMmCore.c > create mode 100644 StandaloneMmPkg/Core/StandaloneMmCore.h > create mode 100644 StandaloneMmPkg/Core/StandaloneMmCore.inf > create mode 100644 StandaloneMmPkg/Core/StandaloneMmCorePrivateData.h > create mode 100644 StandaloneMmPkg/Include/Guid/MmFvDispatch.h > create mode 100644 StandaloneMmPkg/Include/StandaloneMm.h > > diff --git a/StandaloneMmPkg/Core/Dependency.c b/StandaloneMmPkg/Core/Dep= endency.c > new file mode 100644 > index 0000000000..e501369130 > --- /dev/null > +++ b/StandaloneMmPkg/Core/Dependency.c > @@ -0,0 +1,389 @@ > +/** @file > + MM Driver Dispatcher Dependency Evaluator > + > + This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION)= to determine > + if a driver can be scheduled for execution. The criteria for > + schedulability is that the dependency expression is satisfied. > + > + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#include "StandaloneMmCore.h" > + > +/// > +/// EFI_DEP_REPLACE_TRUE - Used to dynamically patch the dependency expr= ession > +/// to save time. A EFI_DEP_PUSH is evaluated on= e an > +/// replaced with EFI_DEP_REPLACE_TRUE. If PI spe= c's Vol 2 > +/// Driver Execution Environment Core Interface u= se 0xff > +/// as new DEPEX opcode. EFI_DEP_REPLACE_TRUE sho= uld be > +/// defined to a new value that is not conflictin= g with PI spec. > +/// > +#define EFI_DEP_REPLACE_TRUE 0xff > + > +/// > +/// Define the initial size of the dependency expression evaluation stac= k > +/// > +#define DEPEX_STACK_SIZE_INCREMENT 0x1000 > + > +// > +// Global stack used to evaluate dependency expressions > +// > +BOOLEAN *mDepexEvaluationStack =3D NULL; > +BOOLEAN *mDepexEvaluationStackEnd =3D NULL; > +BOOLEAN *mDepexEvaluationStackPointer =3D NULL; > + > +/** > + Grow size of the Depex stack > + > + @retval EFI_SUCCESS Stack successfully growed. > + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to gro= w the stack. > + > +**/ > +EFI_STATUS > +GrowDepexStack ( > + VOID > + ) > +{ > + BOOLEAN *NewStack; > + UINTN Size; > + > + Size =3D DEPEX_STACK_SIZE_INCREMENT; > + if (mDepexEvaluationStack !=3D NULL) { > + Size =3D Size + (mDepexEvaluationStackEnd - mDepexEvaluationStack); > + } > + > + NewStack =3D AllocatePool (Size * sizeof (BOOLEAN)); > + if (NewStack =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + if (mDepexEvaluationStack !=3D NULL) { > + // > + // Copy to Old Stack to the New Stack > + // > + CopyMem ( > + NewStack, > + mDepexEvaluationStack, > + (mDepexEvaluationStackEnd - mDepexEvaluationStack) * sizeof (BOOLE= AN) > + ); > + > + // > + // Free The Old Stack > + // > + FreePool (mDepexEvaluationStack); > + } > + > + // > + // Make the Stack pointer point to the old data in the new stack > + // > + mDepexEvaluationStackPointer =3D NewStack + (mDepexEvaluationStackPoin= ter - mDepexEvaluationStack); > + mDepexEvaluationStack =3D NewStack; > + mDepexEvaluationStackEnd =3D NewStack + Size; > + > + return EFI_SUCCESS; > +} > + > +/** > + Push an element onto the Boolean Stack. > + > + @param Value BOOLEAN to push. > + > + @retval EFI_SUCCESS The value was pushed onto the stack. > + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to gro= w the stack. > + > +**/ > +EFI_STATUS > +PushBool ( > + IN BOOLEAN Value > + ) > +{ > + EFI_STATUS Status; > + > + // > + // Check for a stack overflow condition > + // > + if (mDepexEvaluationStackPointer =3D=3D mDepexEvaluationStackEnd) { > + // > + // Grow the stack > + // > + Status =3D GrowDepexStack (); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + > + // > + // Push the item onto the stack > + // > + *mDepexEvaluationStackPointer =3D Value; > + mDepexEvaluationStackPointer++; > + > + return EFI_SUCCESS; > +} > + > +/** > + Pop an element from the Boolean stack. > + > + @param Value BOOLEAN to pop. > + > + @retval EFI_SUCCESS The value was popped onto the stack. > + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack. > + > +**/ > +EFI_STATUS > +PopBool ( > + OUT BOOLEAN *Value > + ) > +{ > + // > + // Check for a stack underflow condition > + // > + if (mDepexEvaluationStackPointer =3D=3D mDepexEvaluationStack) { > + return EFI_ACCESS_DENIED; > + } > + > + // > + // Pop the item off the stack > + // > + mDepexEvaluationStackPointer--; > + *Value =3D *mDepexEvaluationStackPointer; > + return EFI_SUCCESS; > +} > + > +/** > + This is the POSTFIX version of the dependency evaluator. This code do= es > + not need to handle Before or After, as it is not valid to call this > + routine in this case. POSTFIX means all the math is done on top of the= stack. > + > + @param DriverEntry DriverEntry element to update. > + > + @retval TRUE If driver is ready to run. > + @retval FALSE If driver is not ready to run or some fa= tal error > + was found. > + > +**/ > +BOOLEAN > +MmIsSchedulable ( > + IN EFI_MM_DRIVER_ENTRY *DriverEntry > + ) > +{ > + EFI_STATUS Status; > + UINT8 *Iterator; > + BOOLEAN Operator; > + BOOLEAN Operator2; > + EFI_GUID DriverGuid; > + VOID *Interface; > + > + Operator =3D FALSE; > + Operator2 =3D FALSE; > + > + if (DriverEntry->After || DriverEntry->Before) { > + // > + // If Before or After Depex skip as MmInsertOnScheduledQueueWhilePro= cessingBeforeAndAfter () > + // processes them. > + // > + return FALSE; > + } > + > + DEBUG ((DEBUG_DISPATCH, "Evaluate MM DEPEX for FFS(%g)\n", &DriverEntr= y->FileName)); > + > + if (DriverEntry->Depex =3D=3D NULL) { > + // > + // A NULL Depex means that the MM driver is not built correctly. > + // All MM drivers must have a valid depex expressiion. > + // > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Depex is empty)\n")); > + ASSERT (FALSE); > + return FALSE; > + } > + > + // > + // Clean out memory leaks in Depex Boolean stack. Leaks are only cause= d by > + // incorrectly formed DEPEX expressions > + // > + mDepexEvaluationStackPointer =3D mDepexEvaluationStack; > + > + > + Iterator =3D DriverEntry->Depex; > + > + while (TRUE) { > + // > + // Check to see if we are attempting to fetch dependency expression = instructions > + // past the end of the dependency expression. > + // > + if (((UINTN)Iterator - (UINTN)DriverEntry->Depex) >=3D DriverEntry->= DepexSize) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Attempt to fetch past= end of depex)\n")); > + return FALSE; > + } > + > + // > + // Look at the opcode of the dependency expression instruction. > + // > + switch (*Iterator) { > + case EFI_DEP_BEFORE: > + case EFI_DEP_AFTER: > + // > + // For a well-formed Dependency Expression, the code should never = get here. > + // The BEFORE and AFTER are processed prior to this routine's invo= cation. > + // If the code flow arrives at this point, there was a BEFORE or A= FTER > + // that were not the first opcodes. > + // > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected BEFORE or = AFTER opcode)\n")); > + ASSERT (FALSE); > + > + case EFI_DEP_PUSH: > + // > + // Push operator is followed by a GUID. Test to see if the GUID pr= otocol > + // is installed and push the boolean result on the stack. > + // > + CopyMem (&DriverGuid, Iterator + 1, sizeof (EFI_GUID)); > + > + Status =3D MmLocateProtocol (&DriverGuid, NULL, &Interface); > + if (EFI_ERROR (Status) && (mEfiSystemTable !=3D NULL)) { > + // > + // For MM Driver, it may depend on uefi protocols > + // > + Status =3D mEfiSystemTable->BootServices->LocateProtocol (&Drive= rGuid, NULL, &Interface); > + } > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " PUSH GUID(%g) =3D FALSE\n", &DriverGu= id)); > + Status =3D PushBool (FALSE); > + } else { > + DEBUG ((DEBUG_DISPATCH, " PUSH GUID(%g) =3D TRUE\n", &DriverGui= d)); > + *Iterator =3D EFI_DEP_REPLACE_TRUE; > + Status =3D PushBool (TRUE); > + } > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + > + Iterator +=3D sizeof (EFI_GUID); > + break; > + > + case EFI_DEP_AND: > + DEBUG ((DEBUG_DISPATCH, " AND\n")); > + Status =3D PopBool (&Operator); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + > + Status =3D PopBool (&Operator2); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + > + Status =3D PushBool ((BOOLEAN)(Operator && Operator2)); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + break; > + > + case EFI_DEP_OR: > + DEBUG ((DEBUG_DISPATCH, " OR\n")); > + Status =3D PopBool (&Operator); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + > + Status =3D PopBool (&Operator2); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + > + Status =3D PushBool ((BOOLEAN)(Operator || Operator2)); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + break; > + > + case EFI_DEP_NOT: > + DEBUG ((DEBUG_DISPATCH, " NOT\n")); > + Status =3D PopBool (&Operator); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + > + Status =3D PushBool ((BOOLEAN)(!Operator)); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + break; > + > + case EFI_DEP_TRUE: > + DEBUG ((DEBUG_DISPATCH, " TRUE\n")); > + Status =3D PushBool (TRUE); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + break; > + > + case EFI_DEP_FALSE: > + DEBUG ((DEBUG_DISPATCH, " FALSE\n")); > + Status =3D PushBool (FALSE); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + break; > + > + case EFI_DEP_END: > + DEBUG ((DEBUG_DISPATCH, " END\n")); > + Status =3D PopBool (&Operator); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D %a\n", Operator ? "TRUE" : "= FALSE")); > + return Operator; > + > + case EFI_DEP_REPLACE_TRUE: > + CopyMem (&DriverGuid, Iterator + 1, sizeof (EFI_GUID)); > + DEBUG ((DEBUG_DISPATCH, " PUSH GUID(%g) =3D TRUE\n", &DriverGuid)= ); > + Status =3D PushBool (TRUE); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unexpected error)\n= ")); > + return FALSE; > + } > + > + Iterator +=3D sizeof (EFI_GUID); > + break; > + > + default: > + DEBUG ((DEBUG_DISPATCH, " RESULT =3D FALSE (Unknown opcode)\n")); > + goto Done; > + } > + > + // > + // Skip over the Dependency Op Code we just processed in the switch. > + // The math is done out of order, but it should not matter. That is > + // we may add in the sizeof (EFI_GUID) before we account for the OP = Code. > + // This is not an issue, since we just need the correct end result. = You > + // need to be careful using Iterator in the loop as it's intermediat= e value > + // may be strange. > + // > + Iterator++; > + } > + > +Done: > + return FALSE; > +} > diff --git a/StandaloneMmPkg/Core/Dispatcher.c b/StandaloneMmPkg/Core/Dis= patcher.c > new file mode 100644 > index 0000000000..af18fa7eaa > --- /dev/null > +++ b/StandaloneMmPkg/Core/Dispatcher.c > @@ -0,0 +1,1071 @@ > +/** @file > + MM Driver Dispatcher. > + > + Step #1 - When a FV protocol is added to the system every driver in th= e FV > + is added to the mDiscoveredList. The Before, and After Depex= are > + pre-processed as drivers are added to the mDiscoveredList. I= f an Apriori > + file exists in the FV those drivers are addeded to the > + mScheduledQueue. The mFvHandleList is used to make sure a > + FV is only processed once. > + > + Step #2 - Dispatch. Remove driver from the mScheduledQueue and load an= d > + start it. After mScheduledQueue is drained check the > + mDiscoveredList to see if any item has a Depex that is ready= to > + be placed on the mScheduledQueue. > + > + Step #3 - Adding to the mScheduledQueue requires that you process Befo= re > + and After dependencies. This is done recursively as the call= to add > + to the mScheduledQueue checks for Before and recursively add= s > + all Befores. It then addes the item that was passed in and t= hen > + processess the After dependecies by recursively calling the = routine. > + > + Dispatcher Rules: > + The rules for the dispatcher are similar to the DXE dispatcher. > + > + The rules for DXE dispatcher are in chapter 10 of the DXE CIS. Figure = 10-3 > + is the state diagram for the DXE dispatcher > + > + Depex - Dependency Expresion. > + > + Copyright (c) 2014, Hewlett-Packard Development Company, L.P. > + Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + > + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#include "StandaloneMmCore.h" > + > +// > +// MM Dispatcher Data structures > +// > +#define KNOWN_HANDLE_SIGNATURE SIGNATURE_32('k','n','o','w') > +typedef struct { > + UINTN Signature; > + LIST_ENTRY Link; // mFvHandleList > + EFI_HANDLE Handle; > +} KNOWN_HANDLE; > + > +// > +// Function Prototypes > +// > + > +EFI_STATUS > +MmCoreFfsFindMmDriver ( > + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader > + ); > + > +/** > + Insert InsertedDriverEntry onto the mScheduledQueue. To do this you > + must add any driver with a before dependency on InsertedDriverEntry fi= rst. > + You do this by recursively calling this routine. After all the Befores= are > + processed you can add InsertedDriverEntry to the mScheduledQueue. > + Then you can add any driver with an After dependency on InsertedDriver= Entry > + by recursively calling this routine. > + > + @param InsertedDriverEntry The driver to insert on the ScheduledLin= k Queue > + > +**/ > +VOID > +MmInsertOnScheduledQueueWhileProcessingBeforeAndAfter ( > + IN EFI_MM_DRIVER_ENTRY *InsertedDriverEntry > + ); > + > +// > +// The Driver List contains one copy of every driver that has been disco= vered. > +// Items are never removed from the driver list. List of EFI_MM_DRIVER_E= NTRY > +// > +LIST_ENTRY mDiscoveredList =3D INITIALIZE_LIST_HEAD_VARIABLE (mDiscover= edList); > + > +// > +// Queue of drivers that are ready to dispatch. This queue is a subset o= f the > +// mDiscoveredList.list of EFI_MM_DRIVER_ENTRY. > +// > +LIST_ENTRY mScheduledQueue =3D INITIALIZE_LIST_HEAD_VARIABLE (mSchedule= dQueue); > + > +// > +// List of handles who's Fv's have been parsed and added to the mFwDrive= rList. > +// > +LIST_ENTRY mFvHandleList =3D INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleLi= st); > + > +// > +// Flag for the MM Dispacher. TRUE if dispatcher is execuing. > +// > +BOOLEAN gDispatcherRunning =3D FALSE; > + > +// > +// Flag for the MM Dispacher. TRUE if there is one or more MM drivers r= eady to be dispatched > +// > +BOOLEAN gRequestDispatch =3D FALSE; > + > +// > +// The global variable is defined for Loading modules at fixed address f= eature to track the MM code > +// memory range usage. It is a bit mapped array in which every bit indic= ates the correspoding > +// memory page available or not. > +// > +GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mMmCodeMemoryRan= geUsageBitMap=3DNULL; > + > +/** > + 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 bit= s to 1 which indicates the memory range is used. > + The function is only invoked when load modules at fixed address featur= e is enabled. > + > + @param ImageBase The base addres the image will be loa= ded at. > + @param ImageSize The size of the image > + > + @retval EFI_SUCCESS The memory range the image will be lo= aded in is available > + @retval EFI_NOT_FOUND The memory range the image will be lo= aded in is not available > +**/ > +EFI_STATUS > +CheckAndMarkFixLoadingMemoryUsageBitMap ( > + IN EFI_PHYSICAL_ADDRESS ImageBase, > + IN UINTN ImageSize > + ) > +{ > + UINT32 MmCodePageNumber; > + UINT64 MmCodeSize; > + EFI_PHYSICAL_ADDRESS MmCodeBase; > + UINTN BaseOffsetPageNumber; > + UINTN TopOffsetPageNumber; > + UINTN Index; > + // > + // Build tool will calculate the smm code size and then patch the Pcd= LoadFixAddressMmCodePageNumber > + // > + MmCodePageNumber =3D 0; > + MmCodeSize =3D EFI_PAGES_TO_SIZE (MmCodePageNumber); > + MmCodeBase =3D gLoadModuleAtFixAddressMmramBase; > + > + // > + // If the memory usage bit map is not initialized, do it. Every bit = in the array > + // indicate the status of the corresponding memory page, available or= not > + // > + if (mMmCodeMemoryRangeUsageBitMap =3D=3D NULL) { > + mMmCodeMemoryRangeUsageBitMap =3D AllocateZeroPool(((MmCodePageNumb= er / 64) + 1)*sizeof(UINT64)); > + } > + // > + // If the Dxe code memory range is not allocated or the bit map array= allocation failed, return EFI_NOT_FOUND > + // > + if (mMmCodeMemoryRangeUsageBitMap =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + // > + // see if the memory range for loading the image is in the MM code ra= nge. > + // > + if (MmCodeBase + MmCodeSize < ImageBase + ImageSize || MmCodeBase > = ImageBase) { > + return EFI_NOT_FOUND; > + } > + // > + // Test if the memory is avalaible or not. > + // > + BaseOffsetPageNumber =3D (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase = - MmCodeBase)); > + TopOffsetPageNumber =3D (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase = + ImageSize - MmCodeBase)); > + for (Index =3D BaseOffsetPageNumber; Index < TopOffsetPageNumber; Ind= ex ++) { > + if ((mMmCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Inde= x % 64))) !=3D 0) { > + // > + // This page is already used. > + // > + return EFI_NOT_FOUND; > + } > + } > + > + // > + // Being here means the memory range is available. So mark the bits = for the memory range > + // > + for (Index =3D BaseOffsetPageNumber; Index < TopOffsetPageNumber; Ind= ex ++) { > + mMmCodeMemoryRangeUsageBitMap[Index / 64] |=3D LShiftU64(1, (Index = % 64)); > + } > + return EFI_SUCCESS; > +} > +/** > + 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 structu= re that describes the PE/COFF > + image that needs to be examined by t= his 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 load= ding 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; > + UINT64 ValueInSectionHeader; > + > + FixLoadingAddress =3D 0; > + Status =3D EFI_NOT_FOUND; > + > + // > + // Get PeHeader pointer > + // > + ImgHdr =3D (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->= Handle + ImageContext->PeCoffHeaderOffset); > + SectionHeaderOffset =3D ImageContext->PeCoffHeaderOffset + > + sizeof (UINT32) + > + sizeof (EFI_IMAGE_FILE_HEADER) + > + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader; > + NumberOfSections =3D ImgHdr->Pe32.FileHeader.NumberOfSections; > + > + // > + // Get base address from the first section header that doesn't point t= o 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 will save the address in PointerToRelocations & Poin= terToLineNumbers 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 Point= erToRelocations & PointerToLineNumbers fields > + // should not be Zero, or else, these 2 fields should be set to Ze= ro > + // > + ValueInSectionHeader =3D ReadUnaligned64((UINT64*)&SectionHeader.P= ointerToRelocations); > + if (ValueInSectionHeader !=3D 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 =3D (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAdd= ressMmramBase + (INT64)ValueInSectionHeader); > + // > + // Check if the memory range is available. > + // > + Status =3D CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoadingAd= dress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment)); > + if (!EFI_ERROR(Status)) { > + // > + // The assigned address is valid. Return the specified loading= address > + // > + ImageContext->ImageAddress =3D FixLoadingAddress; > + } > + } > + break; > + } > + SectionHeaderOffset +=3D sizeof (EFI_IMAGE_SECTION_HEADER); > + } > + DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading mod= ule at fixed address %x, Status =3D %r\n", FixLoadingAddress, Status)); > + return Status; > +} > +/** > + Loads an EFI image into SMRAM. > + > + @param DriverEntry EFI_MM_DRIVER_ENTRY instance > + > + @return EFI_STATUS > + > +**/ > +EFI_STATUS > +EFIAPI > +MmLoadImage ( > + IN OUT EFI_MM_DRIVER_ENTRY *DriverEntry > + ) > +{ > + VOID *Buffer; > + UINTN PageCount; > + EFI_STATUS Status; > + EFI_PHYSICAL_ADDRESS DstBuffer; > + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; > + > + DEBUG ((DEBUG_INFO, "MmLoadImage - %g\n", &DriverEntry->FileName)); > + > + Buffer =3D AllocateCopyPool (DriverEntry->Pe32DataSize, DriverEntry->P= e32Data); > + if (Buffer =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status =3D EFI_SUCCESS; > + > + // > + // Initialize ImageContext > + // > + ImageContext.Handle =3D Buffer; > + ImageContext.ImageRead =3D PeCoffLoaderImageReadFromMemory; > + > + // > + // Get information about the image being loaded > + // > + Status =3D PeCoffLoaderGetImageInfo (&ImageContext); > + if (EFI_ERROR (Status)) { > + if (Buffer !=3D NULL) { > + MmFreePool (Buffer); > + } > + return Status; > + } > + > + PageCount =3D (UINTN)EFI_SIZE_TO_PAGES((UINTN)ImageContext.ImageSize += ImageContext.SectionAlignment); > + DstBuffer =3D (UINTN)(-1); > + > + Status =3D MmAllocatePages ( > + AllocateMaxAddress, > + EfiRuntimeServicesCode, > + PageCount, > + &DstBuffer > + ); > + if (EFI_ERROR (Status)) { > + if (Buffer !=3D NULL) { > + MmFreePool (Buffer); > + } > + return Status; > + } > + > + ImageContext.ImageAddress =3D (EFI_PHYSICAL_ADDRESS)DstBuffer; > + > + // > + // Align buffer on section boundry > + // > + ImageContext.ImageAddress +=3D ImageContext.SectionAlignment - 1; > + ImageContext.ImageAddress &=3D ~((EFI_PHYSICAL_ADDRESS)(ImageContext.S= ectionAlignment - 1)); > + > + // > + // Load the image to our new buffer > + // > + Status =3D PeCoffLoaderLoadImage (&ImageContext); > + if (EFI_ERROR (Status)) { > + if (Buffer !=3D NULL) { > + MmFreePool (Buffer); > + } > + MmFreePages (DstBuffer, PageCount); > + return Status; > + } > + > + // > + // Relocate the image in our new buffer > + // > + Status =3D PeCoffLoaderRelocateImage (&ImageContext); > + if (EFI_ERROR (Status)) { > + if (Buffer !=3D NULL) { > + MmFreePool (Buffer); > + } > + MmFreePages (DstBuffer, PageCount); > + return Status; > + } > + > + // > + // Flush the instruction cache so the image data are written before we= execute it > + // > + InvalidateInstructionCacheRange ((VOID *)(UINTN) ImageContext.ImageAdd= ress, (UINTN) ImageContext.ImageSize); > + > + // > + // Save Image EntryPoint in DriverEntry > + // > + DriverEntry->ImageEntryPoint =3D ImageContext.EntryPoint; > + DriverEntry->ImageBuffer =3D DstBuffer; > + DriverEntry->NumberOfPage =3D PageCount; > + > + if (mEfiSystemTable !=3D NULL) { > + Status =3D mEfiSystemTable->BootServices->AllocatePool (EfiBootServi= cesData, sizeof (EFI_LOADED_IMAGE_PROTOCOL), (VOID **)&DriverEntry->LoadedI= mage); > + if (EFI_ERROR (Status)) { > + if (Buffer !=3D NULL) { > + MmFreePool (Buffer); > + } > + MmFreePages (DstBuffer, PageCount); > + return Status; > + } > + > + ZeroMem (DriverEntry->LoadedImage, sizeof (EFI_LOADED_IMAGE_PROTOCOL= )); > + // > + // Fill in the remaining fields of the Loaded Image Protocol instanc= e. > + // Note: ImageBase is an SMRAM address that can not be accessed outs= ide of SMRAM if SMRAM window is closed. > + // > + DriverEntry->LoadedImage->Revision =3D EFI_LOADED_IMAGE_PROTOCO= L_REVISION; > + DriverEntry->LoadedImage->ParentHandle =3D NULL; > + DriverEntry->LoadedImage->SystemTable =3D mEfiSystemTable; > + DriverEntry->LoadedImage->DeviceHandle =3D NULL; > + DriverEntry->LoadedImage->FilePath =3D NULL; > + > + DriverEntry->LoadedImage->ImageBase =3D (VOID *)(UINTN)DriverEnt= ry->ImageBuffer; > + DriverEntry->LoadedImage->ImageSize =3D ImageContext.ImageSize; > + DriverEntry->LoadedImage->ImageCodeType =3D EfiRuntimeServicesCode; > + DriverEntry->LoadedImage->ImageDataType =3D EfiRuntimeServicesData; > + > + // > + // Create a new image handle in the UEFI handle database for the MM = Driver > + // > + DriverEntry->ImageHandle =3D NULL; > + Status =3D mEfiSystemTable->BootServices->InstallMultipleProtocolInt= erfaces ( > + &DriverEntry->ImageHandle, > + &gEfiLoadedImageProtocolGuid, DriverEntry->LoadedIma= ge, > + NULL > + ); > + } > + > + // > + // Print the load address and the PDB file name if it is available > + // > + > + DEBUG_CODE_BEGIN (); > + > + UINTN Index; > + UINTN StartIndex; > + CHAR8 EfiFileName[256]; > + > + > + DEBUG ((DEBUG_INFO | DEBUG_LOAD, > + "Loading MM driver at 0x%11p EntryPoint=3D0x%11p ", > + (VOID *)(UINTN) ImageContext.ImageAddress, > + FUNCTION_ENTRY_POINT (ImageContext.EntryPoint))); > + > + > + // > + // Print Module Name by Pdb file path. > + // Windows and Unix style file path are all trimmed correctly. > + // > + if (ImageContext.PdbPointer !=3D NULL) { > + StartIndex =3D 0; > + for (Index =3D 0; ImageContext.PdbPointer[Index] !=3D 0; Index++) = { > + if ((ImageContext.PdbPointer[Index] =3D=3D '\\') || (ImageContex= t.PdbPointer[Index] =3D=3D '/')) { > + StartIndex =3D Index + 1; > + } > + } > + // > + // Copy the PDB file name to our temporary string, and replace .pd= b with .efi > + // The PDB file name is limited in the range of 0~255. > + // If the length is bigger than 255, trim the redudant characters = to avoid overflow in array boundary. > + // > + for (Index =3D 0; Index < sizeof (EfiFileName) - 4; Index++) { > + EfiFileName[Index] =3D ImageContext.PdbPointer[Index + StartInde= x]; > + if (EfiFileName[Index] =3D=3D 0) { > + EfiFileName[Index] =3D '.'; > + } > + if (EfiFileName[Index] =3D=3D '.') { > + EfiFileName[Index + 1] =3D 'e'; > + EfiFileName[Index + 2] =3D 'f'; > + EfiFileName[Index + 3] =3D 'i'; > + EfiFileName[Index + 4] =3D 0; > + break; > + } > + } > + > + if (Index =3D=3D sizeof (EfiFileName) - 4) { > + EfiFileName[Index] =3D 0; > + } > + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->I= mageContext.PdbPointer[StartIndex])); > + } > + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n")); > + > + DEBUG_CODE_END (); > + > + // > + // Free buffer allocated by Fv->ReadSection. > + // > + // The UEFI Boot Services FreePool() function must be used because Fv-= >ReadSection > + // used the UEFI Boot Services AllocatePool() function > + // > + MmFreePool(Buffer); > + return Status; > +} > + > +/** > + Preprocess dependency expression and update DriverEntry to reflect the > + state of Before and After dependencies. If DriverEntry->Before > + or DriverEntry->After is set it will never be cleared. > + > + @param DriverEntry DriverEntry element to update . > + > + @retval EFI_SUCCESS It always works. > + > +**/ > +EFI_STATUS > +MmPreProcessDepex ( > + IN EFI_MM_DRIVER_ENTRY *DriverEntry > + ) > +{ > + UINT8 *Iterator; > + > + Iterator =3D DriverEntry->Depex; > + DriverEntry->Dependent =3D TRUE; > + > + if (*Iterator =3D=3D EFI_DEP_BEFORE) { > + DriverEntry->Before =3D TRUE; > + } else if (*Iterator =3D=3D EFI_DEP_AFTER) { > + DriverEntry->After =3D TRUE; > + } > + > + if (DriverEntry->Before || DriverEntry->After) { > + CopyMem (&DriverEntry->BeforeAfterGuid, Iterator + 1, sizeof (EFI_GU= ID)); > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Read Depex and pre-process the Depex for Before and After. If Section = Extraction > + protocol returns an error via ReadSection defer the reading of the Dep= ex. > + > + @param DriverEntry Driver to work on. > + > + @retval EFI_SUCCESS Depex read and preprossesed > + @retval EFI_PROTOCOL_ERROR The section extraction protocol returned= an error > + and Depex reading needs to be retried. > + @retval Error DEPEX not found. > + > +**/ > +EFI_STATUS > +MmGetDepexSectionAndPreProccess ( > + IN EFI_MM_DRIVER_ENTRY *DriverEntry > + ) > +{ > + EFI_STATUS Status; > + > + // > + // Data already read > + // > + if (DriverEntry->Depex =3D=3D NULL) { > + Status =3D EFI_NOT_FOUND; > + } else { > + Status =3D EFI_SUCCESS; > + } > + if (EFI_ERROR (Status)) { > + if (Status =3D=3D EFI_PROTOCOL_ERROR) { > + // > + // The section extraction protocol failed so set protocol error fl= ag > + // > + DriverEntry->DepexProtocolError =3D TRUE; > + } else { > + // > + // If no Depex assume depend on all architectural protocols > + // > + DriverEntry->Depex =3D NULL; > + DriverEntry->Dependent =3D TRUE; > + DriverEntry->DepexProtocolError =3D FALSE; > + } > + } else { > + // > + // Set Before and After state information based on Depex > + // Driver will be put in Dependent state > + // > + MmPreProcessDepex (DriverEntry); > + DriverEntry->DepexProtocolError =3D FALSE; > + } > + > + return Status; > +} > + > +/** > + This is the main Dispatcher for MM and it exits when there are no more > + drivers to run. Drain the mScheduledQueue and load and start a PE > + image for each driver. Search the mDiscoveredList to see if any driver= can > + be placed on the mScheduledQueue. If no drivers are placed on the > + mScheduledQueue exit the function. > + > + @retval EFI_SUCCESS All of the MM Drivers that could be disp= atched > + have been run and the MM Entry Point has= been > + registered. > + @retval EFI_NOT_READY The MM Driver that registered the MM Ent= ry Point > + was just dispatched. > + @retval EFI_NOT_FOUND There are no MM Drivers available to be = dispatched. > + @retval EFI_ALREADY_STARTED The MM Dispatcher is already running > + > +**/ > +EFI_STATUS > +MmDispatcher ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + LIST_ENTRY *Link; > + EFI_MM_DRIVER_ENTRY *DriverEntry; > + BOOLEAN ReadyToRun; > + BOOLEAN PreviousMmEntryPointRegistered; > + > + DEBUG ((DEBUG_INFO, "MmDispatcher\n")); > + > + if (!gRequestDispatch) { > + DEBUG ((DEBUG_INFO, " !gRequestDispatch\n")); > + return EFI_NOT_FOUND; > + } > + > + if (gDispatcherRunning) { > + DEBUG ((DEBUG_INFO, " gDispatcherRunning\n")); > + // > + // If the dispatcher is running don't let it be restarted. > + // > + return EFI_ALREADY_STARTED; > + } > + > + gDispatcherRunning =3D TRUE; > + > + do { > + // > + // Drain the Scheduled Queue > + // > + DEBUG ((DEBUG_INFO, " Drain the Scheduled Queue\n")); > + while (!IsListEmpty (&mScheduledQueue)) { > + DriverEntry =3D CR ( > + mScheduledQueue.ForwardLink, > + EFI_MM_DRIVER_ENTRY, > + ScheduledLink, > + EFI_MM_DRIVER_ENTRY_SIGNATURE > + ); > + DEBUG ((DEBUG_INFO, " DriverEntry (Scheduled) - %g\n", &DriverEnt= ry->FileName)); > + > + // > + // Load the MM Driver image into memory. If the Driver was transit= ioned from > + // Untrused to Scheduled it would have already been loaded so we m= ay need to > + // skip the LoadImage > + // > + if (DriverEntry->ImageHandle =3D=3D NULL) { > + Status =3D MmLoadImage (DriverEntry); > + > + // > + // Update the driver state to reflect that it's been loaded > + // > + if (EFI_ERROR (Status)) { > + // > + // The MM Driver could not be loaded, and do not attempt to lo= ad or start it again. > + // Take driver from Scheduled to Initialized. > + // > + DriverEntry->Initialized =3D TRUE; > + DriverEntry->Scheduled =3D FALSE; > + RemoveEntryList (&DriverEntry->ScheduledLink); > + > + // > + // If it's an error don't try the StartImage > + // > + continue; > + } > + } > + > + DriverEntry->Scheduled =3D FALSE; > + DriverEntry->Initialized =3D TRUE; > + RemoveEntryList (&DriverEntry->ScheduledLink); > + > + /*REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( > + EFI_PROGRESS_CODE, > + EFI_SOFTWARE_MM_DRIVER | EFI_SW_PC_INIT_BEGIN, > + &DriverEntry->ImageHandle, > + sizeof (DriverEntry->ImageHandle) > + );*/ > + > + // > + // Cache state of MmEntryPointRegistered before calling entry poin= t > + // > + PreviousMmEntryPointRegistered =3D gMmCorePrivate->MmEntryPointReg= istered; > + > + // > + // For each MM driver, pass NULL as ImageHandle > + // > + if (mEfiSystemTable =3D=3D NULL) { > + DEBUG ((DEBUG_INFO, "StartImage - 0x%x (Standalone Mode)\n", Dri= verEntry->ImageEntryPoint)); > + Status =3D ((MM_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntry= Point)(DriverEntry->ImageHandle, &gMmCoreMmst); > + } else { > + DEBUG ((DEBUG_INFO, "StartImage - 0x%x (Tradition Mode)\n", Driv= erEntry->ImageEntryPoint)); > + Status =3D ((EFI_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntr= yPoint)(DriverEntry->ImageHandle, mEfiSystemTable); > + } > + if (EFI_ERROR(Status)){ > + DEBUG ((DEBUG_INFO, "StartImage Status - %r\n", Status)); > + MmFreePages(DriverEntry->ImageBuffer, DriverEntry->NumberOfPage)= ; > + } > + > + /*REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( > + EFI_PROGRESS_CODE, > + EFI_SOFTWARE_MM_DRIVER | EFI_SW_PC_INIT_END, > + &DriverEntry->ImageHandle, > + sizeof (DriverEntry->ImageHandle) > + );*/ > + > + if (!PreviousMmEntryPointRegistered && gMmCorePrivate->MmEntryPoin= tRegistered) { > + // > + // Return immediately if the MM Entry Point was registered by th= e MM > + // Driver that was just dispatched. The MM IPL will reinvoke th= e MM > + // Core Dispatcher. This is required so MM Mode may be enabled = as soon > + // as all the dependent MM Drivers for MM Mode have been dispatc= hed. > + // Once the MM Entry Point has been registered, then MM Mode wil= l be > + // used. > + // > + gRequestDispatch =3D TRUE; > + gDispatcherRunning =3D FALSE; > + return EFI_NOT_READY; > + } > + } > + > + // > + // Search DriverList for items to place on Scheduled Queue > + // > + DEBUG ((DEBUG_INFO, " Search DriverList for items to place on Sched= uled Queue\n")); > + ReadyToRun =3D FALSE; > + for (Link =3D mDiscoveredList.ForwardLink; Link !=3D &mDiscoveredLis= t; Link =3D Link->ForwardLink) { > + DriverEntry =3D CR (Link, EFI_MM_DRIVER_ENTRY, Link, EFI_MM_DRIVER= _ENTRY_SIGNATURE); > + DEBUG ((DEBUG_INFO, " DriverEntry (Discovered) - %g\n", &DriverEn= try->FileName)); > + > + if (DriverEntry->DepexProtocolError){ > + // > + // If Section Extraction Protocol did not let the Depex be read = before retry the read > + // > + Status =3D MmGetDepexSectionAndPreProccess (DriverEntry); > + } > + > + if (DriverEntry->Dependent) { > + if (MmIsSchedulable (DriverEntry)) { > + MmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverE= ntry); > + ReadyToRun =3D TRUE; > + } > + } > + } > + } while (ReadyToRun); > + > + // > + // If there is no more MM driver to dispatch, stop the dispatch reques= t > + // > + DEBUG ((DEBUG_INFO, " no more MM driver to dispatch, stop the dispatc= h request\n")); > + gRequestDispatch =3D FALSE; > + for (Link =3D mDiscoveredList.ForwardLink; Link !=3D &mDiscoveredList;= Link =3D Link->ForwardLink) { > + DriverEntry =3D CR (Link, EFI_MM_DRIVER_ENTRY, Link, EFI_MM_DRIVER_E= NTRY_SIGNATURE); > + DEBUG ((DEBUG_INFO, " DriverEntry (Discovered) - %g\n", &DriverEntr= y->FileName)); > + > + if (!DriverEntry->Initialized){ > + // > + // We have MM driver pending to dispatch > + // > + gRequestDispatch =3D TRUE; > + break; > + } > + } > + > + gDispatcherRunning =3D FALSE; > + > + return EFI_SUCCESS; > +} > + > +/** > + Insert InsertedDriverEntry onto the mScheduledQueue. To do this you > + must add any driver with a before dependency on InsertedDriverEntry fi= rst. > + You do this by recursively calling this routine. After all the Befores= are > + processed you can add InsertedDriverEntry to the mScheduledQueue. > + Then you can add any driver with an After dependency on InsertedDriver= Entry > + by recursively calling this routine. > + > + @param InsertedDriverEntry The driver to insert on the ScheduledLin= k Queue > + > +**/ > +VOID > +MmInsertOnScheduledQueueWhileProcessingBeforeAndAfter ( > + IN EFI_MM_DRIVER_ENTRY *InsertedDriverEntry > + ) > +{ > + LIST_ENTRY *Link; > + EFI_MM_DRIVER_ENTRY *DriverEntry; > + > + // > + // Process Before Dependency > + // > + for (Link =3D mDiscoveredList.ForwardLink; Link !=3D &mDiscoveredList;= Link =3D Link->ForwardLink) { > + DriverEntry =3D CR(Link, EFI_MM_DRIVER_ENTRY, Link, EFI_MM_DRIVER_EN= TRY_SIGNATURE); > + if (DriverEntry->Before && DriverEntry->Dependent && DriverEntry != =3D InsertedDriverEntry) { > + DEBUG ((DEBUG_DISPATCH, "Evaluate MM DEPEX for FFS(%g)\n", &Driver= Entry->FileName)); > + DEBUG ((DEBUG_DISPATCH, " BEFORE FFS(%g) =3D ", &DriverEntry->Bef= oreAfterGuid)); > + if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->Bef= oreAfterGuid)) { > + // > + // Recursively process BEFORE > + // > + DEBUG ((DEBUG_DISPATCH, "TRUE\n END\n RESULT =3D TRUE\n")); > + MmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEnt= ry); > + } else { > + DEBUG ((DEBUG_DISPATCH, "FALSE\n END\n RESULT =3D FALSE\n")); > + } > + } > + } > + > + // > + // Convert driver from Dependent to Scheduled state > + // > + > + InsertedDriverEntry->Dependent =3D FALSE; > + InsertedDriverEntry->Scheduled =3D TRUE; > + InsertTailList (&mScheduledQueue, &InsertedDriverEntry->ScheduledLink)= ; > + > + > + // > + // Process After Dependency > + // > + for (Link =3D mDiscoveredList.ForwardLink; Link !=3D &mDiscoveredList;= Link =3D Link->ForwardLink) { > + DriverEntry =3D CR(Link, EFI_MM_DRIVER_ENTRY, Link, EFI_MM_DRIVER_EN= TRY_SIGNATURE); > + if (DriverEntry->After && DriverEntry->Dependent && DriverEntry !=3D= InsertedDriverEntry) { > + DEBUG ((DEBUG_DISPATCH, "Evaluate MM DEPEX for FFS(%g)\n", &Driver= Entry->FileName)); > + DEBUG ((DEBUG_DISPATCH, " AFTER FFS(%g) =3D ", &DriverEntry->Befo= reAfterGuid)); > + if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->Bef= oreAfterGuid)) { > + // > + // Recursively process AFTER > + // > + DEBUG ((DEBUG_DISPATCH, "TRUE\n END\n RESULT =3D TRUE\n")); > + MmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEnt= ry); > + } else { > + DEBUG ((DEBUG_DISPATCH, "FALSE\n END\n RESULT =3D FALSE\n")); > + } > + } > + } > +} > + > +/** > + Return TRUE if the Fv has been processed, FALSE if not. > + > + @param FvHandle The handle of a FV that's being tested > + > + @retval TRUE Fv protocol on FvHandle has been process= ed > + @retval FALSE Fv protocol on FvHandle has not yet been > + processed > + > +**/ > +BOOLEAN > +FvHasBeenProcessed ( > + IN EFI_HANDLE FvHandle > + ) > +{ > + LIST_ENTRY *Link; > + KNOWN_HANDLE *KnownHandle; > + > + for (Link =3D mFvHandleList.ForwardLink; Link !=3D &mFvHandleList; Lin= k =3D Link->ForwardLink) { > + KnownHandle =3D CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE)= ; > + if (KnownHandle->Handle =3D=3D FvHandle) { > + return TRUE; > + } > + } > + return FALSE; > +} > + > +/** > + Remember that Fv protocol on FvHandle has had it's drivers placed on t= he > + mDiscoveredList. This fucntion adds entries on the mFvHandleList. Item= s are > + never removed/freed from the mFvHandleList. > + > + @param FvHandle The handle of a FV that has been process= ed > + > +**/ > +VOID > +FvIsBeingProcesssed ( > + IN EFI_HANDLE FvHandle > + ) > +{ > + KNOWN_HANDLE *KnownHandle; > + > + DEBUG ((DEBUG_INFO, "FvIsBeingProcesssed - 0x%08x\n", FvHandle)); > + > + KnownHandle =3D AllocatePool (sizeof (KNOWN_HANDLE)); > + ASSERT (KnownHandle !=3D NULL); > + > + KnownHandle->Signature =3D KNOWN_HANDLE_SIGNATURE; > + KnownHandle->Handle =3D FvHandle; > + InsertTailList (&mFvHandleList, &KnownHandle->Link); > +} > + > +/** > + Add an entry to the mDiscoveredList. Allocate memory to store the Driv= erEntry, > + and initilize any state variables. Read the Depex from the FV and stor= e it > + in DriverEntry. Pre-process the Depex to set the Before and After stat= e. > + The Discovered list is never free'ed and contains booleans that repres= ent the > + other possible MM driver states. > + > + @param Fv Fv protocol, needed to read Depex info o= ut of > + FLASH. > + @param FvHandle Handle for Fv, needed in the > + EFI_MM_DRIVER_ENTRY so that the PE image= can be > + read out of the FV at a later time. > + @param DriverName Name of driver to add to mDiscoveredList= . > + > + @retval EFI_SUCCESS If driver was added to the mDiscoveredLi= st. > + @retval EFI_ALREADY_STARTED The driver has already been started. Onl= y one > + DriverName may be active in the system a= t any one > + time. > + > +**/ > +EFI_STATUS > +MmAddToDriverList ( > + IN EFI_HANDLE FvHandle, > + IN VOID *Pe32Data, > + IN UINTN Pe32DataSize, > + IN VOID *Depex, > + IN UINTN DepexSize, > + IN EFI_GUID *DriverName > + ) > +{ > + EFI_MM_DRIVER_ENTRY *DriverEntry; > + > + DEBUG ((DEBUG_INFO, "MmAddToDriverList - %g (0x%08x)\n", DriverName, P= e32Data)); > + > + // > + // Create the Driver Entry for the list. ZeroPool initializes lots of = variables to > + // NULL or FALSE. > + // > + DriverEntry =3D AllocateZeroPool (sizeof (EFI_MM_DRIVER_ENTRY)); > + ASSERT (DriverEntry !=3D NULL); > + > + DriverEntry->Signature =3D EFI_MM_DRIVER_ENTRY_SIGNATURE; > + CopyGuid (&DriverEntry->FileName, DriverName); > + DriverEntry->FvHandle =3D FvHandle; > + DriverEntry->Pe32Data =3D Pe32Data; > + DriverEntry->Pe32DataSize =3D Pe32DataSize; > + DriverEntry->Depex =3D Depex; > + DriverEntry->DepexSize =3D DepexSize; > + > + MmGetDepexSectionAndPreProccess (DriverEntry); > + > + InsertTailList (&mDiscoveredList, &DriverEntry->Link); > + gRequestDispatch =3D TRUE; > + > + return EFI_SUCCESS; > +} > + > +/** > + This function is the main entry point for an MM handler dispatch > + or communicate-based callback. > + > + Event notification that is fired every time a FV dispatch protocol is = added. > + More than one protocol may have been added when this event is fired, s= o you > + must loop on MmLocateHandle () to see how many protocols were added an= d > + do the following to each FV: > + If the Fv has already been processed, skip it. If the Fv has not been > + processed then mark it as being processed, as we are about to process = it. > + Read the Fv and add any driver in the Fv to the mDiscoveredList.The > + mDiscoveredList is never free'ed and contains variables that define > + the other states the MM driver transitions to.. > + While you are at it read the A Priori file into memory. > + Place drivers in the A Priori list onto the mScheduledQueue. > + > + @param DispatchHandle The unique handle assigned to this handler by = SmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmDriverDispatchHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + > + DEBUG ((DEBUG_INFO, "MmDriverDispatchHandler\n")); > + > + // > + // Execute the MM Dispatcher on any newly discovered FVs and previousl= y > + // discovered MM drivers that have been discovered but not dispatched. > + // > + Status =3D MmDispatcher (); > + > + // > + // Check to see if CommBuffer and CommBufferSize are valid > + // > + if (CommBuffer !=3D NULL && CommBufferSize !=3D NULL) { > + if (*CommBufferSize > 0) { > + if (Status =3D=3D EFI_NOT_READY) { > + // > + // If a the MM Core Entry Point was just registered, then set fl= ag to > + // request the MM Dispatcher to be restarted. > + // > + *(UINT8 *)CommBuffer =3D COMM_BUFFER_MM_DISPATCH_RESTART; > + } else if (!EFI_ERROR (Status)) { > + // > + // Set the flag to show that the MM Dispatcher executed without = errors > + // > + *(UINT8 *)CommBuffer =3D COMM_BUFFER_MM_DISPATCH_SUCCESS; > + } else { > + // > + // Set the flag to show that the MM Dispatcher encountered an er= ror > + // > + *(UINT8 *)CommBuffer =3D COMM_BUFFER_MM_DISPATCH_ERROR; > + } > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + This function is the main entry point for an MM handler dispatch > + or communicate-based callback. > + > + @param DispatchHandle The unique handle assigned to this handler by = SmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmFvDispatchHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + EFI_MM_COMMUNICATE_FV_DISPATCH_DATA *CommunicationFvDispatchData; > + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; > + > + DEBUG ((DEBUG_INFO, "MmFvDispatchHandler\n")); > + > + CommunicationFvDispatchData =3D CommBuffer; > + > + DEBUG ((DEBUG_INFO, " Dispatch - 0x%016lx - 0x%016lx\n", Communicatio= nFvDispatchData->Address, CommunicationFvDispatchData->Size)); > + > + FwVolHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)CommunicationFvDi= spatchData->Address; > + > + MmCoreFfsFindMmDriver (FwVolHeader); > + > + // > + // Execute the MM Dispatcher on any newly discovered FVs and previousl= y > + // discovered MM drivers that have been discovered but not dispatched. > + // > + Status =3D MmDispatcher (); > + > + return Status; > +} > + > +/** > + Traverse the discovered list for any drivers that were discovered but = not loaded > + because the dependency experessions evaluated to false. > + > +**/ > +VOID > +MmDisplayDiscoveredNotDispatched ( > + VOID > + ) > +{ > + LIST_ENTRY *Link; > + EFI_MM_DRIVER_ENTRY *DriverEntry; > + > + for (Link =3D mDiscoveredList.ForwardLink;Link !=3D&mDiscoveredList; L= ink =3D Link->ForwardLink) { > + DriverEntry =3D CR(Link, EFI_MM_DRIVER_ENTRY, Link, EFI_MM_DRIVER_EN= TRY_SIGNATURE); > + if (DriverEntry->Dependent) { > + DEBUG ((DEBUG_LOAD, "MM Driver %g was discovered but not loaded!!\= n", &DriverEntry->FileName)); > + } > + } > +} > diff --git a/StandaloneMmPkg/Core/FwVol.c b/StandaloneMmPkg/Core/FwVol.c > new file mode 100644 > index 0000000000..901c58bc53 > --- /dev/null > +++ b/StandaloneMmPkg/Core/FwVol.c > @@ -0,0 +1,104 @@ > +/**@file > + > +Copyright (c) 2015, Intel Corporation. All rights reserved.
> +Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> +This program and the accompanying materials > +are licensed and made available under the terms and conditions of the BS= D License > +which accompanies this distribution. The full text of the license may b= e found at > +http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. > + > +**/ > + > +#include "StandaloneMmCore.h" > +#include > + > +// > +// List of file types supported by dispatcher > +// > +EFI_FV_FILETYPE mMmFileTypes[] =3D { > + EFI_FV_FILETYPE_MM, > + 0xE, //EFI_FV_FILETYPE_MM_STANDALONE, > + // > + // Note: DXE core will process the FV image file, so skip it in M= M core > + // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE > + // > +}; > + > +EFI_STATUS > +MmAddToDriverList ( > + IN EFI_HANDLE FvHandle, > + IN VOID *Pe32Data, > + IN UINTN Pe32DataSize, > + IN VOID *Depex, > + IN UINTN DepexSize, > + IN EFI_GUID *DriverName > + ); > + > +BOOLEAN > +FvHasBeenProcessed ( > + IN EFI_HANDLE FvHandle > + ); > + > +VOID > +FvIsBeingProcesssed ( > + IN EFI_HANDLE FvHandle > + ); > + > +EFI_STATUS > +MmCoreFfsFindMmDriver ( > + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader > + ) > +/*++ > + > +Routine Description: > + Given the pointer to the Firmware Volume Header find the > + MM driver and return it's PE32 image. > + > +Arguments: > + FwVolHeader - Pointer to memory mapped FV > + > +Returns: > + other - Failure > + > +--*/ > +{ > + EFI_STATUS Status; > + EFI_STATUS DepexStatus; > + EFI_FFS_FILE_HEADER *FileHeader; > + EFI_FV_FILETYPE FileType; > + VOID *Pe32Data; > + UINTN Pe32DataSize; > + VOID *Depex; > + UINTN DepexSize; > + UINTN Index; > + > + DEBUG((DEBUG_INFO, "MmCoreFfsFindMmDriver - 0x%x\n", FwVolHeader)); > + > + if (FvHasBeenProcessed (FwVolHeader)) { > + return EFI_SUCCESS; > + } > + > + FvIsBeingProcesssed (FwVolHeader); > + > + for (Index =3D 0; Index < sizeof(mMmFileTypes) / sizeof(mMmFileTypes[0= ]); Index++) { > + DEBUG((DEBUG_INFO, "Check MmFileTypes - 0x%x\n", mMmFileTypes[Index]= )); > + FileType =3D mMmFileTypes[Index]; > + FileHeader =3D NULL; > + do { > + Status =3D FfsFindNextFile(FileType, FwVolHeader, &FileHeader); > + if (!EFI_ERROR(Status)) { > + Status =3D FfsFindSectionData(EFI_SECTION_PE32, FileHeader, &Pe3= 2Data, &Pe32DataSize); > + DEBUG((DEBUG_INFO, "Find PE data - 0x%x\n", Pe32Data)); > + DepexStatus =3D FfsFindSectionData(EFI_SECTION_MM_DEPEX, FileHea= der, &Depex, &DepexSize); > + if (!EFI_ERROR(DepexStatus)) { > + MmAddToDriverList(FwVolHeader, Pe32Data, Pe32DataSize, Depex, = DepexSize, &FileHeader->Name); > + } > + } > + } while (!EFI_ERROR(Status)); > + } > + > + return Status; > +} > diff --git a/StandaloneMmPkg/Core/Handle.c b/StandaloneMmPkg/Core/Handle.= c > new file mode 100644 > index 0000000000..01832f4bbe > --- /dev/null > +++ b/StandaloneMmPkg/Core/Handle.c > @@ -0,0 +1,533 @@ > +/** @file > + SMM handle & protocol handling. > + > + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#include "StandaloneMmCore.h" > + > +// > +// mProtocolDatabase - A list of all protocols in the system. (simp= le list for now) > +// gHandleList - A list of all the handles in the system > +// > +LIST_ENTRY mProtocolDatabase =3D INITIALIZE_LIST_HEAD_VARIABLE (mProto= colDatabase); > +LIST_ENTRY gHandleList =3D INITIALIZE_LIST_HEAD_VARIABLE (gHandl= eList); > + > +/** > + Check whether a handle is a valid EFI_HANDLE > + > + @param UserHandle The handle to check > + > + @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_H= ANDLE. > + @retval EFI_SUCCESS The handle is valid EFI_HANDLE. > + > +**/ > +EFI_STATUS > +MmValidateHandle ( > + IN EFI_HANDLE UserHandle > + ) > +{ > + IHANDLE *Handle; > + > + Handle =3D (IHANDLE *)UserHandle; > + if (Handle =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + if (Handle->Signature !=3D EFI_HANDLE_SIGNATURE) { > + return EFI_INVALID_PARAMETER; > + } > + return EFI_SUCCESS; > +} > + > +/** > + Finds the protocol entry for the requested protocol. > + > + @param Protocol The ID of the protocol > + @param Create Create a new entry if not found > + > + @return Protocol entry > + > +**/ > +PROTOCOL_ENTRY * > +MmFindProtocolEntry ( > + IN EFI_GUID *Protocol, > + IN BOOLEAN Create > + ) > +{ > + LIST_ENTRY *Link; > + PROTOCOL_ENTRY *Item; > + PROTOCOL_ENTRY *ProtEntry; > + > + // > + // Search the database for the matching GUID > + // > + > + ProtEntry =3D NULL; > + for (Link =3D mProtocolDatabase.ForwardLink; > + Link !=3D &mProtocolDatabase; > + Link =3D Link->ForwardLink) { > + > + Item =3D CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATU= RE); > + if (CompareGuid (&Item->ProtocolID, Protocol)) { > + // > + // This is the protocol entry > + // > + ProtEntry =3D Item; > + break; > + } > + } > + > + // > + // If the protocol entry was not found and Create is TRUE, then > + // allocate a new entry > + // > + if ((ProtEntry =3D=3D NULL) && Create) { > + ProtEntry =3D AllocatePool (sizeof(PROTOCOL_ENTRY)); > + if (ProtEntry !=3D NULL) { > + // > + // Initialize new protocol entry structure > + // > + ProtEntry->Signature =3D PROTOCOL_ENTRY_SIGNATURE; > + CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol); > + InitializeListHead (&ProtEntry->Protocols); > + InitializeListHead (&ProtEntry->Notify); > + > + // > + // Add it to protocol database > + // > + InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries); > + } > + } > + return ProtEntry; > +} > + > +/** > + Finds the protocol instance for the requested handle and protocol. > + Note: This function doesn't do parameters checking, it's caller's resp= onsibility > + to pass in valid parameters. > + > + @param Handle The handle to search the protocol on > + @param Protocol GUID of the protocol > + @param Interface The interface for the protocol being se= arched > + > + @return Protocol instance (NULL: Not found) > + > +**/ > +PROTOCOL_INTERFACE * > +MmFindProtocolInterface ( > + IN IHANDLE *Handle, > + IN EFI_GUID *Protocol, > + IN VOID *Interface > + ) > +{ > + PROTOCOL_INTERFACE *Prot; > + PROTOCOL_ENTRY *ProtEntry; > + LIST_ENTRY *Link; > + > + Prot =3D NULL; > + > + // > + // Lookup the protocol entry for this protocol ID > + // > + ProtEntry =3D MmFindProtocolEntry (Protocol, FALSE); > + if (ProtEntry !=3D NULL) { > + // > + // Look at each protocol interface for any matches > + // > + for (Link =3D Handle->Protocols.ForwardLink; Link !=3D &Handle->Prot= ocols; Link=3DLink->ForwardLink) { > + // > + // If this protocol interface matches, remove it > + // > + Prot =3D CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIG= NATURE); > + if (Prot->Interface =3D=3D Interface && Prot->Protocol =3D=3D Prot= Entry) { > + break; > + } > + Prot =3D NULL; > + } > + } > + return Prot; > +} > + > +/** > + Wrapper function to MmInstallProtocolInterfaceNotify. This is the pub= lic API which > + Calls the private one which contains a BOOLEAN parameter for notificat= ions > + > + @param UserHandle The handle to install the protocol hand= ler on, > + or NULL if a new handle is to be alloca= ted > + @param Protocol The protocol to add to the handle > + @param InterfaceType Indicates whether Interface is supplied= in > + native form. > + @param Interface The interface for the protocol being ad= ded > + > + @return Status code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInstallProtocolInterface ( > + IN OUT EFI_HANDLE *UserHandle, > + IN EFI_GUID *Protocol, > + IN EFI_INTERFACE_TYPE InterfaceType, > + IN VOID *Interface > + ) > +{ > + return MmInstallProtocolInterfaceNotify ( > + UserHandle, > + Protocol, > + InterfaceType, > + Interface, > + TRUE > + ); > +} > + > +/** > + Installs a protocol interface into the boot services environment. > + > + @param UserHandle The handle to install the protocol hand= ler on, > + or NULL if a new handle is to be alloca= ted > + @param Protocol The protocol to add to the handle > + @param InterfaceType Indicates whether Interface is supplied= in > + native form. > + @param Interface The interface for the protocol being ad= ded > + @param Notify indicates whether notify the notificati= on list > + for this protocol > + > + @retval EFI_INVALID_PARAMETER Invalid parameter > + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate > + @retval EFI_SUCCESS Protocol interface successfully install= ed > + > +**/ > +EFI_STATUS > +MmInstallProtocolInterfaceNotify ( > + IN OUT EFI_HANDLE *UserHandle, > + IN EFI_GUID *Protocol, > + IN EFI_INTERFACE_TYPE InterfaceType, > + IN VOID *Interface, > + IN BOOLEAN Notify > + ) > +{ > + PROTOCOL_INTERFACE *Prot; > + PROTOCOL_ENTRY *ProtEntry; > + IHANDLE *Handle; > + EFI_STATUS Status; > + VOID *ExistingInterface; > + > + // > + // returns EFI_INVALID_PARAMETER if InterfaceType is invalid. > + // Also added check for invalid UserHandle and Protocol pointers. > + // > + if (UserHandle =3D=3D NULL || Protocol =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (InterfaceType !=3D EFI_NATIVE_INTERFACE) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Print debug message > + // > + DEBUG((DEBUG_LOAD | DEBUG_INFO, "MmInstallProtocolInterface: %g %p\n",= Protocol, Interface)); > + > + Status =3D EFI_OUT_OF_RESOURCES; > + Prot =3D NULL; > + Handle =3D NULL; > + > + if (*UserHandle !=3D NULL) { > + Status =3D MmHandleProtocol (*UserHandle, Protocol, (VOID **)&Existi= ngInterface); > + if (!EFI_ERROR (Status)) { > + return EFI_INVALID_PARAMETER; > + } > + } > + > + // > + // Lookup the Protocol Entry for the requested protocol > + // > + ProtEntry =3D MmFindProtocolEntry (Protocol, TRUE); > + if (ProtEntry =3D=3D NULL) { > + goto Done; > + } > + > + // > + // Allocate a new protocol interface structure > + // > + Prot =3D AllocateZeroPool (sizeof(PROTOCOL_INTERFACE)); > + if (Prot =3D=3D NULL) { > + Status =3D EFI_OUT_OF_RESOURCES; > + goto Done; > + } > + > + // > + // If caller didn't supply a handle, allocate a new one > + // > + Handle =3D (IHANDLE *)*UserHandle; > + if (Handle =3D=3D NULL) { > + Handle =3D AllocateZeroPool (sizeof(IHANDLE)); > + if (Handle =3D=3D NULL) { > + Status =3D EFI_OUT_OF_RESOURCES; > + goto Done; > + } > + > + // > + // Initialize new handler structure > + // > + Handle->Signature =3D EFI_HANDLE_SIGNATURE; > + InitializeListHead (&Handle->Protocols); > + > + // > + // Add this handle to the list global list of all handles > + // in the system > + // > + InsertTailList (&gHandleList, &Handle->AllHandles); > + } > + > + Status =3D MmValidateHandle (Handle); > + if (EFI_ERROR (Status)) { > + goto Done; > + } > + > + // > + // Each interface that is added must be unique > + // > + ASSERT (MmFindProtocolInterface (Handle, Protocol, Interface) =3D=3D N= ULL); > + > + // > + // Initialize the protocol interface structure > + // > + Prot->Signature =3D PROTOCOL_INTERFACE_SIGNATURE; > + Prot->Handle =3D Handle; > + Prot->Protocol =3D ProtEntry; > + Prot->Interface =3D Interface; > + > + // > + // Add this protocol interface to the head of the supported > + // protocol list for this handle > + // > + InsertHeadList (&Handle->Protocols, &Prot->Link); > + > + // > + // Add this protocol interface to the tail of the > + // protocol entry > + // > + InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); > + > + // > + // Notify the notification list for this protocol > + // > + if (Notify) { > + MmNotifyProtocol (Prot); > + } > + Status =3D EFI_SUCCESS; > + > +Done: > + if (!EFI_ERROR (Status)) { > + // > + // Return the new handle back to the caller > + // > + *UserHandle =3D Handle; > + } else { > + // > + // There was an error, clean up > + // > + if (Prot !=3D NULL) { > + FreePool (Prot); > + } > + } > + return Status; > +} > + > +/** > + Uninstalls all instances of a protocol:interfacer from a handle. > + If the last protocol interface is remove from the handle, the > + handle is freed. > + > + @param UserHandle The handle to remove the protocol handl= er from > + @param Protocol The protocol, of protocol:interface, to= remove > + @param Interface The interface, of protocol:interface, t= o remove > + > + @retval EFI_INVALID_PARAMETER Protocol is NULL. > + @retval EFI_SUCCESS Protocol interface successfully uninsta= lled. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmUninstallProtocolInterface ( > + IN EFI_HANDLE UserHandle, > + IN EFI_GUID *Protocol, > + IN VOID *Interface > + ) > +{ > + EFI_STATUS Status; > + IHANDLE *Handle; > + PROTOCOL_INTERFACE *Prot; > + > + // > + // Check that Protocol is valid > + // > + if (Protocol =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Check that UserHandle is a valid handle > + // > + Status =3D MmValidateHandle (UserHandle); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Check that Protocol exists on UserHandle, and Interface matches the= interface in the database > + // > + Prot =3D MmFindProtocolInterface (UserHandle, Protocol, Interface); > + if (Prot =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Remove the protocol interface from the protocol > + // > + Status =3D EFI_NOT_FOUND; > + Handle =3D (IHANDLE *)UserHandle; > + Prot =3D MmRemoveInterfaceFromProtocol (Handle, Protocol, Interface)= ; > + > + if (Prot !=3D NULL) { > + // > + // Remove the protocol interface from the handle > + // > + RemoveEntryList (&Prot->Link); > + > + // > + // Free the memory > + // > + Prot->Signature =3D 0; > + FreePool (Prot); > + Status =3D EFI_SUCCESS; > + } > + > + // > + // If there are no more handlers for the handle, free the handle > + // > + if (IsListEmpty (&Handle->Protocols)) { > + Handle->Signature =3D 0; > + RemoveEntryList (&Handle->AllHandles); > + FreePool (Handle); > + } > + return Status; > +} > + > +/** > + Locate a certain GUID protocol interface in a Handle's protocols. > + > + @param UserHandle The handle to obtain the protocol inter= face on > + @param Protocol The GUID of the protocol > + > + @return The requested protocol interface for the handle > + > +**/ > +PROTOCOL_INTERFACE * > +MmGetProtocolInterface ( > + IN EFI_HANDLE UserHandle, > + IN EFI_GUID *Protocol > + ) > +{ > + EFI_STATUS Status; > + PROTOCOL_ENTRY *ProtEntry; > + PROTOCOL_INTERFACE *Prot; > + IHANDLE *Handle; > + LIST_ENTRY *Link; > + > + Status =3D MmValidateHandle (UserHandle); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + > + Handle =3D (IHANDLE *)UserHandle; > + > + // > + // Look at each protocol interface for a match > + // > + for (Link =3D Handle->Protocols.ForwardLink; Link !=3D &Handle->Protoc= ols; Link =3D Link->ForwardLink) { > + Prot =3D CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNA= TURE); > + ProtEntry =3D Prot->Protocol; > + if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) { > + return Prot; > + } > + } > + return NULL; > +} > + > +/** > + Queries a handle to determine if it supports a specified protocol. > + > + @param UserHandle The handle being queried. > + @param Protocol The published unique identifier of the = protocol. > + @param Interface Supplies the address where a pointer to= the > + corresponding Protocol Interface is ret= urned. > + > + @retval EFI_SUCCESS The interface information for the speci= fied protocol was returned. > + @retval EFI_UNSUPPORTED The device does not support the specifi= ed protocol. > + @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.. > + @retval EFI_INVALID_PARAMETER Protocol is NULL. > + @retval EFI_INVALID_PARAMETER Interface is NULL. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmHandleProtocol ( > + IN EFI_HANDLE UserHandle, > + IN EFI_GUID *Protocol, > + OUT VOID **Interface > + ) > +{ > + EFI_STATUS Status; > + PROTOCOL_INTERFACE *Prot; > + > + // > + // Check for invalid Protocol > + // > + if (Protocol =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Check for invalid Interface > + // > + if (Interface =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } else { > + *Interface =3D NULL; > + } > + > + // > + // Check for invalid UserHandle > + // > + Status =3D MmValidateHandle (UserHandle); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Look at each protocol interface for a match > + // > + Prot =3D MmGetProtocolInterface (UserHandle, Protocol); > + if (Prot =3D=3D NULL) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // This is the protocol interface entry for this protocol > + // > + *Interface =3D Prot->Interface; > + > + return EFI_SUCCESS; > +} > diff --git a/StandaloneMmPkg/Core/InstallConfigurationTable.c b/Standalon= eMmPkg/Core/InstallConfigurationTable.c > new file mode 100644 > index 0000000000..3a31c63f94 > --- /dev/null > +++ b/StandaloneMmPkg/Core/InstallConfigurationTable.c > @@ -0,0 +1,178 @@ > +/** @file > + System Management System Table Services MmInstallConfigurationTable se= rvice > + > + Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#include "StandaloneMmCore.h" > + > +#define CONFIG_TABLE_SIZE_INCREASED 0x10 > + > +UINTN mMmSystemTableAllocateSize =3D 0; > + > +/** > + The MmInstallConfigurationTable() function is used to maintain the lis= t > + of configuration tables that are stored in the System Management Syste= m > + Table. The list is stored as an array of (GUID, Pointer) pairs. The = list > + must be allocated from pool memory with PoolType set to EfiRuntimeServ= icesData. > + > + @param SystemTable A pointer to the SMM System Table (SMST). > + @param Guid A pointer to the GUID for the entry to add, u= pdate, or remove. > + @param Table A pointer to the buffer of the table to add. > + @param TableSize The size of the table to install. > + > + @retval EFI_SUCCESS The (Guid, Table) pair was added, update= d, or removed. > + @retval EFI_INVALID_PARAMETER Guid is not valid. > + @retval EFI_NOT_FOUND An attempt was made to delete a non-exis= tent entry. > + @retval EFI_OUT_OF_RESOURCES There is not enough memory available to = complete the operation. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInstallConfigurationTable ( > + IN CONST EFI_MM_SYSTEM_TABLE *SystemTable, > + IN CONST EFI_GUID *Guid, > + IN VOID *Table, > + IN UINTN TableSize > + ) > +{ > + UINTN Index; > + EFI_CONFIGURATION_TABLE *ConfigurationTable; > + EFI_CONFIGURATION_TABLE *OldTable; > + > + // > + // If Guid is NULL, then this operation cannot be performed > + // > + if (Guid =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + ConfigurationTable =3D gMmCoreMmst.MmConfigurationTable; > + > + // > + // Search all the table for an entry that matches Guid > + // > + for (Index =3D 0; Index < gMmCoreMmst.NumberOfTableEntries; Index++) { > + if (CompareGuid (Guid, &(ConfigurationTable[Index].VendorGuid))) { > + break; > + } > + } > + > + if (Index < gMmCoreMmst.NumberOfTableEntries) { > + // > + // A match was found, so this is either a modify or a delete operati= on > + // > + if (Table !=3D NULL) { > + // > + // If Table is not NULL, then this is a modify operation. > + // Modify the table entry and return. > + // > + ConfigurationTable[Index].VendorTable =3D Table; > + return EFI_SUCCESS; > + } > + > + // > + // A match was found and Table is NULL, so this is a delete operatio= n. > + // > + gMmCoreMmst.NumberOfTableEntries--; > + > + // > + // Copy over deleted entry > + // > + CopyMem ( > + &(ConfigurationTable[Index]), > + &(ConfigurationTable[Index + 1]), > + (gMmCoreMmst.NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURA= TION_TABLE) > + ); > + > + } else { > + // > + // No matching GUIDs were found, so this is an add operation. > + // > + if (Table =3D=3D NULL) { > + // > + // If Table is NULL on an add operation, then return an error. > + // > + return EFI_NOT_FOUND; > + } > + > + // > + // Assume that Index =3D=3D gMmCoreMmst.NumberOfTableEntries > + // > + if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >=3D mMmSystemTableAl= locateSize) { > + // > + // Allocate a table with one additional entry. > + // > + mMmSystemTableAllocateSize +=3D (CONFIG_TABLE_SIZE_INCREASED * siz= eof (EFI_CONFIGURATION_TABLE)); > + ConfigurationTable =3D AllocatePool (mMmSystemTableAllocateSize); > + if (ConfigurationTable =3D=3D NULL) { > + // > + // If a new table could not be allocated, then return an error. > + // > + return EFI_OUT_OF_RESOURCES; > + } > + > + if (gMmCoreMmst.MmConfigurationTable !=3D NULL) { > + // > + // Copy the old table to the new table. > + // > + CopyMem ( > + ConfigurationTable, > + gMmCoreMmst.MmConfigurationTable, > + Index * sizeof (EFI_CONFIGURATION_TABLE) > + ); > + > + // > + // Record the old table pointer. > + // > + OldTable =3D gMmCoreMmst.MmConfigurationTable; > + > + // > + // As the MmInstallConfigurationTable() may be re-entered by Fre= ePool() in > + // its calling stack, updating System table to the new table poi= nter must > + // be done before calling FreePool() to free the old table. > + // It can make sure the gMmCoreMmst.MmConfigurationTable point t= o the new > + // table and avoid the errors of use-after-free to the old table= by the > + // reenter of MmInstallConfigurationTable() in FreePool()'s call= ing stack. > + // > + gMmCoreMmst.MmConfigurationTable =3D ConfigurationTable; > + > + // > + // Free the old table after updating System Table to the new tab= le pointer. > + // > + FreePool (OldTable); > + } else { > + // > + // Update System Table > + // > + gMmCoreMmst.MmConfigurationTable =3D ConfigurationTable; > + } > + } > + > + // > + // Fill in the new entry > + // > + CopyGuid ((VOID *)&ConfigurationTable[Index].VendorGuid, Guid); > + ConfigurationTable[Index].VendorTable =3D Table; > + > + // > + // This is an add operation, so increment the number of table entrie= s > + // > + gMmCoreMmst.NumberOfTableEntries++; > + } > + > + // > + // CRC-32 field is ignorable for SMM System Table and should be set to= zero > + // > + > + return EFI_SUCCESS; > +} > diff --git a/StandaloneMmPkg/Core/Locate.c b/StandaloneMmPkg/Core/Locate.= c > new file mode 100644 > index 0000000000..6a90575f99 > --- /dev/null > +++ b/StandaloneMmPkg/Core/Locate.c > @@ -0,0 +1,496 @@ > +/** @file > + Locate handle functions > + > + Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#include "StandaloneMmCore.h" > + > +// > +// ProtocolRequest - Last LocateHandle request ID > +// > +UINTN mEfiLocateHandleRequest =3D 0; > + > +// > +// Internal prototypes > +// > + > +typedef struct { > + EFI_GUID *Protocol; > + VOID *SearchKey; > + LIST_ENTRY *Position; > + PROTOCOL_ENTRY *ProtEntry; > +} LOCATE_POSITION; > + > +typedef > +IHANDLE * > +(* CORE_GET_NEXT) ( > + IN OUT LOCATE_POSITION *Position, > + OUT VOID **Interface > + ); > + > +/** > + Routine to get the next Handle, when you are searching for all handles= . > + > + @param Position Information about which Handle to seach= for. > + @param Interface Return the interface structure for the = matching > + protocol. > + > + @return An pointer to IHANDLE if the next Position is not the end of t= he list. > + Otherwise,NULL is returned. > + > +**/ > +IHANDLE * > +MmGetNextLocateAllHandles ( > + IN OUT LOCATE_POSITION *Position, > + OUT VOID **Interface > + ) > +{ > + IHANDLE *Handle; > + > + // > + // Next handle > + // > + Position->Position =3D Position->Position->ForwardLink; > + > + // > + // If not at the end of the list, get the handle > + // > + Handle =3D NULL; > + *Interface =3D NULL; > + if (Position->Position !=3D &gHandleList) { > + Handle =3D CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_S= IGNATURE); > + } > + return Handle; > +} > + > +/** > + Routine to get the next Handle, when you are searching for register pr= otocol > + notifies. > + > + @param Position Information about which Handle to seach= for. > + @param Interface Return the interface structure for the = matching > + protocol. > + > + @return An pointer to IHANDLE if the next Position is not the end of t= he list. > + Otherwise,NULL is returned. > + > +**/ > +IHANDLE * > +MmGetNextLocateByRegisterNotify ( > + IN OUT LOCATE_POSITION *Position, > + OUT VOID **Interface > + ) > +{ > + IHANDLE *Handle; > + PROTOCOL_NOTIFY *ProtNotify; > + PROTOCOL_INTERFACE *Prot; > + LIST_ENTRY *Link; > + > + Handle =3D NULL; > + *Interface =3D NULL; > + ProtNotify =3D Position->SearchKey; > + > + // > + // If this is the first request, get the next handle > + // > + if (ProtNotify !=3D NULL) { > + ASSERT(ProtNotify->Signature =3D=3D PROTOCOL_NOTIFY_SIGNATURE); > + Position->SearchKey =3D NULL; > + > + // > + // If not at the end of the list, get the next handle > + // > + Link =3D ProtNotify->Position->ForwardLink; > + if (Link !=3D &ProtNotify->Protocol->Protocols) { > + Prot =3D CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERF= ACE_SIGNATURE); > + Handle =3D Prot->Handle; > + *Interface =3D Prot->Interface; > + } > + } > + return Handle; > +} > + > +/** > + Routine to get the next Handle, when you are searching for a given pro= tocol. > + > + @param Position Information about which Handle to seach= for. > + @param Interface Return the interface structure for the = matching > + protocol. > + > + @return An pointer to IHANDLE if the next Position is not the end of t= he list. > + Otherwise,NULL is returned. > + > +**/ > +IHANDLE * > +MmGetNextLocateByProtocol ( > + IN OUT LOCATE_POSITION *Position, > + OUT VOID **Interface > + ) > +{ > + IHANDLE *Handle; > + LIST_ENTRY *Link; > + PROTOCOL_INTERFACE *Prot; > + > + Handle =3D NULL; > + *Interface =3D NULL; > + for (; ;) { > + // > + // Next entry > + // > + Link =3D Position->Position->ForwardLink; > + Position->Position =3D Link; > + > + // > + // If not at the end, return the handle > + // > + if (Link =3D=3D &Position->ProtEntry->Protocols) { > + Handle =3D NULL; > + break; > + } > + > + // > + // Get the handle > + // > + Prot =3D CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE= _SIGNATURE); > + Handle =3D Prot->Handle; > + *Interface =3D Prot->Interface; > + > + // > + // If this handle has not been returned this request, then > + // return it now > + // > + if (Handle->LocateRequest !=3D mEfiLocateHandleRequest) { > + Handle->LocateRequest =3D mEfiLocateHandleRequest; > + break; > + } > + } > + return Handle; > +} > + > +/** > + Return the first Protocol Interface that matches the Protocol GUID. If > + Registration is pasased in return a Protocol Instance that was just ad= d > + to the system. If Retistration is NULL return the first Protocol Inter= face > + you find. > + > + @param Protocol The protocol to search for > + @param Registration Optional Registration Key returned from > + RegisterProtocolNotify() > + @param Interface Return the Protocol interface (instance= ). > + > + @retval EFI_SUCCESS If a valid Interface is returned > + @retval EFI_INVALID_PARAMETER Invalid parameter > + @retval EFI_NOT_FOUND Protocol interface not found > + > +**/ > +EFI_STATUS > +EFIAPI > +MmLocateProtocol ( > + IN EFI_GUID *Protocol, > + IN VOID *Registration OPTIONAL, > + OUT VOID **Interface > + ) > +{ > + EFI_STATUS Status; > + LOCATE_POSITION Position; > + PROTOCOL_NOTIFY *ProtNotify; > + IHANDLE *Handle; > + > + if ((Interface =3D=3D NULL) || (Protocol =3D=3D NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + *Interface =3D NULL; > + Status =3D EFI_SUCCESS; > + > + // > + // Set initial position > + // > + Position.Protocol =3D Protocol; > + Position.SearchKey =3D Registration; > + Position.Position =3D &gHandleList; > + > + mEfiLocateHandleRequest +=3D 1; > + > + if (Registration =3D=3D NULL) { > + // > + // Look up the protocol entry and set the head pointer > + // > + Position.ProtEntry =3D MmFindProtocolEntry (Protocol, FALSE); > + if (Position.ProtEntry =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + Position.Position =3D &Position.ProtEntry->Protocols; > + > + Handle =3D MmGetNextLocateByProtocol (&Position, Interface); > + } else { > + Handle =3D MmGetNextLocateByRegisterNotify (&Position, Interface); > + } > + > + if (Handle =3D=3D NULL) { > + Status =3D EFI_NOT_FOUND; > + } else if (Registration !=3D NULL) { > + // > + // If this is a search by register notify and a handle was > + // returned, update the register notification position > + // > + ProtNotify =3D Registration; > + ProtNotify->Position =3D ProtNotify->Position->ForwardLink; > + } > + > + return Status; > +} > + > +/** > + Locates the requested handle(s) and returns them in Buffer. > + > + @param SearchType The type of search to perform to locate= the > + handles > + @param Protocol The protocol to search for > + @param SearchKey Dependant on SearchType > + @param BufferSize On input the size of Buffer. On output= the > + size of data returned. > + @param Buffer The buffer to return the results in > + > + @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size = is > + returned in BufferSize. > + @retval EFI_INVALID_PARAMETER Invalid parameter > + @retval EFI_SUCCESS Successfully found the requested handle= (s) and > + returns them in Buffer. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmLocateHandle ( > + IN EFI_LOCATE_SEARCH_TYPE SearchType, > + IN EFI_GUID *Protocol OPTIONAL, > + IN VOID *SearchKey OPTIONAL, > + IN OUT UINTN *BufferSize, > + OUT EFI_HANDLE *Buffer > + ) > +{ > + EFI_STATUS Status; > + LOCATE_POSITION Position; > + PROTOCOL_NOTIFY *ProtNotify; > + CORE_GET_NEXT GetNext; > + UINTN ResultSize; > + IHANDLE *Handle; > + IHANDLE **ResultBuffer; > + VOID *Interface; > + > + if (BufferSize =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + if ((*BufferSize > 0) && (Buffer =3D=3D NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + GetNext =3D NULL; > + > + // > + // Set initial position > + // > + Position.Protocol =3D Protocol; > + Position.SearchKey =3D SearchKey; > + Position.Position =3D &gHandleList; > + > + ResultSize =3D 0; > + ResultBuffer =3D (IHANDLE **) Buffer; > + Status =3D EFI_SUCCESS; > + > + // > + // Get the search function based on type > + // > + switch (SearchType) { > + case AllHandles: > + GetNext =3D MmGetNextLocateAllHandles; > + break; > + > + case ByRegisterNotify: > + GetNext =3D MmGetNextLocateByRegisterNotify; > + // > + // Must have SearchKey for locate ByRegisterNotify > + // > + if (SearchKey =3D=3D NULL) { > + Status =3D EFI_INVALID_PARAMETER; > + } > + break; > + > + case ByProtocol: > + GetNext =3D MmGetNextLocateByProtocol; > + if (Protocol =3D=3D NULL) { > + Status =3D EFI_INVALID_PARAMETER; > + break; > + } > + // > + // Look up the protocol entry and set the head pointer > + // > + Position.ProtEntry =3D MmFindProtocolEntry (Protocol, FALSE); > + if (Position.ProtEntry =3D=3D NULL) { > + Status =3D EFI_NOT_FOUND; > + break; > + } > + Position.Position =3D &Position.ProtEntry->Protocols; > + break; > + > + default: > + Status =3D EFI_INVALID_PARAMETER; > + break; > + } > + > + if (EFI_ERROR(Status)) { > + return Status; > + } > + > + // > + // Enumerate out the matching handles > + // > + mEfiLocateHandleRequest +=3D 1; > + for (; ;) { > + // > + // Get the next handle. If no more handles, stop > + // > + Handle =3D GetNext (&Position, &Interface); > + if (NULL =3D=3D Handle) { > + break; > + } > + > + // > + // Increase the resulting buffer size, and if this handle > + // fits return it > + // > + ResultSize +=3D sizeof(Handle); > + if (ResultSize <=3D *BufferSize) { > + *ResultBuffer =3D Handle; > + ResultBuffer +=3D 1; > + } > + } > + > + // > + // If the result is a zero length buffer, then there were no > + // matching handles > + // > + if (ResultSize =3D=3D 0) { > + Status =3D EFI_NOT_FOUND; > + } else { > + // > + // Return the resulting buffer size. If it's larger than what > + // was passed, then set the error code > + // > + if (ResultSize > *BufferSize) { > + Status =3D EFI_BUFFER_TOO_SMALL; > + } > + > + *BufferSize =3D ResultSize; > + > + if (SearchType =3D=3D ByRegisterNotify && !EFI_ERROR(Status)) { > + ASSERT (SearchKey !=3D NULL); > + // > + // If this is a search by register notify and a handle was > + // returned, update the register notification position > + // > + ProtNotify =3D SearchKey; > + ProtNotify->Position =3D ProtNotify->Position->ForwardLink; > + } > + } > + > + return Status; > +} > + > +/** > + Function returns an array of handles that support the requested protoc= ol > + in a buffer allocated from pool. This is a version of MmLocateHandle() > + that allocates a buffer for the caller. > + > + @param SearchType Specifies which handle(s) are to be ret= urned. > + @param Protocol Provides the protocol to search by. = This > + parameter is only valid for SearchType > + ByProtocol. > + @param SearchKey Supplies the search key depending on th= e > + SearchType. > + @param NumberHandles The number of handles returned in Buffe= r. > + @param Buffer A pointer to the buffer to return the r= equested > + array of handles that support Protocol= . > + > + @retval EFI_SUCCESS The result array of handles was returne= d. > + @retval EFI_NOT_FOUND No handles match the search. > + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to stor= e the > + matching results. > + @retval EFI_INVALID_PARAMETER One or more parameters are not valid. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmLocateHandleBuffer ( > + IN EFI_LOCATE_SEARCH_TYPE SearchType, > + IN EFI_GUID *Protocol OPTIONAL, > + IN VOID *SearchKey OPTIONAL, > + IN OUT UINTN *NumberHandles, > + OUT EFI_HANDLE **Buffer > + ) > +{ > + EFI_STATUS Status; > + UINTN BufferSize; > + > + if (NumberHandles =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Buffer =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + BufferSize =3D 0; > + *NumberHandles =3D 0; > + *Buffer =3D NULL; > + Status =3D MmLocateHandle ( > + SearchType, > + Protocol, > + SearchKey, > + &BufferSize, > + *Buffer > + ); > + // > + // LocateHandleBuffer() returns incorrect status code if SearchType is > + // invalid. > + // > + // Add code to correctly handle expected errors from MmLocateHandle(). > + // > + if (EFI_ERROR(Status) && Status !=3D EFI_BUFFER_TOO_SMALL) { > + if (Status !=3D EFI_INVALID_PARAMETER) { > + Status =3D EFI_NOT_FOUND; > + } > + return Status; > + } > + > + *Buffer =3D AllocatePool (BufferSize); > + if (*Buffer =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status =3D MmLocateHandle ( > + SearchType, > + Protocol, > + SearchKey, > + &BufferSize, > + *Buffer > + ); > + > + *NumberHandles =3D BufferSize / sizeof(EFI_HANDLE); > + if (EFI_ERROR(Status)) { > + *NumberHandles =3D 0; > + } > + > + return Status; > +} > diff --git a/StandaloneMmPkg/Core/Mmi.c b/StandaloneMmPkg/Core/Mmi.c > new file mode 100644 > index 0000000000..29aba7b53d > --- /dev/null > +++ b/StandaloneMmPkg/Core/Mmi.c > @@ -0,0 +1,337 @@ > +/** @file > + MMI management. > + > + Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#include "StandaloneMmCore.h" > + > +// > +// MM_HANDLER_STATE_NOTIFIER > +// > + > +// > +// MM_HANDLER - used for each MM handler > +// > + > +#define MMI_ENTRY_SIGNATURE SIGNATURE_32('m','m','i','e') > + > + typedef struct { > + UINTN Signature; > + LIST_ENTRY AllEntries; // All entries > + > + EFI_GUID HandlerType; // Type of interrupt > + LIST_ENTRY MmiHandlers; // All handlers > +} MMI_ENTRY; > + > +#define MMI_HANDLER_SIGNATURE SIGNATURE_32('m','m','i','h') > + > + typedef struct { > + UINTN Signature; > + LIST_ENTRY Link; // Link on MMI_ENTRY.MmiHan= dlers > + EFI_MM_HANDLER_ENTRY_POINT Handler; // The mm handler's entry p= oint > + MMI_ENTRY *MmiEntry; > +} MMI_HANDLER; > + > +LIST_ENTRY mRootMmiHandlerList =3D INITIALIZE_LIST_HEAD_VARIABLE (mRoot= MmiHandlerList); > +LIST_ENTRY mMmiEntryList =3D INITIALIZE_LIST_HEAD_VARIABLE (mMmiE= ntryList); > + > +/** > + Finds the MMI entry for the requested handler type. > + > + @param HandlerType The type of the interrupt > + @param Create Create a new entry if not found > + > + @return MMI entry > + > +**/ > +MMI_ENTRY * > +EFIAPI > +MmCoreFindMmiEntry ( > + IN EFI_GUID *HandlerType, > + IN BOOLEAN Create > + ) > +{ > + LIST_ENTRY *Link; > + MMI_ENTRY *Item; > + MMI_ENTRY *MmiEntry; > + > + // > + // Search the MMI entry list for the matching GUID > + // > + MmiEntry =3D NULL; > + for (Link =3D mMmiEntryList.ForwardLink; > + Link !=3D &mMmiEntryList; > + Link =3D Link->ForwardLink) { > + > + Item =3D CR (Link, MMI_ENTRY, AllEntries, MMI_ENTRY_SIGNATURE); > + if (CompareGuid (&Item->HandlerType, HandlerType)) { > + // > + // This is the MMI entry > + // > + MmiEntry =3D Item; > + break; > + } > + } > + > + // > + // If the protocol entry was not found and Create is TRUE, then > + // allocate a new entry > + // > + if ((MmiEntry =3D=3D NULL) && Create) { > + MmiEntry =3D AllocatePool (sizeof(MMI_ENTRY)); > + if (MmiEntry !=3D NULL) { > + // > + // Initialize new MMI entry structure > + // > + MmiEntry->Signature =3D MMI_ENTRY_SIGNATURE; > + CopyGuid ((VOID *)&MmiEntry->HandlerType, HandlerType); > + InitializeListHead (&MmiEntry->MmiHandlers); > + > + // > + // Add it to MMI entry list > + // > + InsertTailList (&mMmiEntryList, &MmiEntry->AllEntries); > + } > + } > + return MmiEntry; > +} > + > +/** > + Manage MMI of a particular type. > + > + @param HandlerType Points to the handler type or NULL for root MMI= handlers. > + @param Context Points to an optional context buffer. > + @param CommBuffer Points to the optional communication buffer. > + @param CommBufferSize Points to the size of the optional communicatio= n buffer. > + > + @retval EFI_WARN_INTERRUPT_SOURCE_PENDING Interrupt source was proces= sed successfully but not quiesced. > + @retval EFI_INTERRUPT_PENDING One or more MMI sources cou= ld not be quiesced. > + @retval EFI_NOT_FOUND Interrupt source was not ha= ndled or quiesced. > + @retval EFI_SUCCESS Interrupt source was handle= d and quiesced. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmiManage ( > + IN CONST EFI_GUID *HandlerType, > + IN CONST VOID *Context OPTIONAL, > + IN OUT VOID *CommBuffer OPTIONAL, > + IN OUT UINTN *CommBufferSize OPTIONAL > + ) > +{ > + LIST_ENTRY *Link; > + LIST_ENTRY *Head; > + MMI_ENTRY *MmiEntry; > + MMI_HANDLER *MmiHandler; > + BOOLEAN SuccessReturn; > + EFI_STATUS Status; > + > + Status =3D EFI_NOT_FOUND; > + SuccessReturn =3D FALSE; > + if (HandlerType =3D=3D NULL) { > + // > + // Root MMI handler > + // > + > + Head =3D &mRootMmiHandlerList; > + } else { > + // > + // Non-root MMI handler > + // > + MmiEntry =3D MmCoreFindMmiEntry ((EFI_GUID *) HandlerType, FALSE); > + if (MmiEntry =3D=3D NULL) { > + // > + // There is no handler registered for this interrupt source > + // > + return Status; > + } > + > + Head =3D &MmiEntry->MmiHandlers; > + } > + > + for (Link =3D Head->ForwardLink; Link !=3D Head; Link =3D Link->Forwar= dLink) { > + MmiHandler =3D CR (Link, MMI_HANDLER, Link, MMI_HANDLER_SIGNATURE); > + > + Status =3D MmiHandler->Handler ( > + (EFI_HANDLE) MmiHandler, > + Context, > + CommBuffer, > + CommBufferSize > + ); > + > + switch (Status) { > + case EFI_INTERRUPT_PENDING: > + // > + // If a handler returns EFI_INTERRUPT_PENDING and HandlerType is n= ot NULL then > + // no additional handlers will be processed and EFI_INTERRUPT_PEND= ING will be returned. > + // > + if (HandlerType !=3D NULL) { > + return EFI_INTERRUPT_PENDING; > + } > + break; > + > + case EFI_SUCCESS: > + // > + // If at least one of the handlers returns EFI_SUCCESS then the fu= nction will return > + // EFI_SUCCESS. If a handler returns EFI_SUCCESS and HandlerType i= s not NULL then no > + // additional handlers will be processed. > + // > + if (HandlerType !=3D NULL) { > + return EFI_SUCCESS; > + } > + SuccessReturn =3D TRUE; > + break; > + > + case EFI_WARN_INTERRUPT_SOURCE_QUIESCED: > + // > + // If at least one of the handlers returns EFI_WARN_INTERRUPT_SOUR= CE_QUIESCED > + // then the function will return EFI_SUCCESS. > + // > + SuccessReturn =3D TRUE; > + break; > + > + case EFI_WARN_INTERRUPT_SOURCE_PENDING: > + // > + // If all the handlers returned EFI_WARN_INTERRUPT_SOURCE_PENDING > + // then EFI_WARN_INTERRUPT_SOURCE_PENDING will be returned. > + // > + break; > + > + default: > + // > + // Unexpected status code returned. > + // > + ASSERT (FALSE); > + break; > + } > + } > + > + if (SuccessReturn) { > + Status =3D EFI_SUCCESS; > + } > + > + return Status; > +} > + > +/** > + Registers a handler to execute within MM. > + > + @param Handler Handler service funtion pointer. > + @param HandlerType Points to the handler type or NULL for root MMI= handlers. > + @param DispatchHandle On return, contains a unique handle which can b= e used to later unregister the handler function. > + > + @retval EFI_SUCCESS Handler register success. > + @retval EFI_INVALID_PARAMETER Handler or DispatchHandle is NULL. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmiHandlerRegister ( > + IN EFI_MM_HANDLER_ENTRY_POINT Handler, > + IN CONST EFI_GUID *HandlerType OPTIONAL, > + OUT EFI_HANDLE *DispatchHandle > + ) > +{ > + MMI_HANDLER *MmiHandler; > + MMI_ENTRY *MmiEntry; > + LIST_ENTRY *List; > + > + if (Handler =3D=3D NULL || DispatchHandle =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + MmiHandler =3D AllocateZeroPool (sizeof (MMI_HANDLER)); > + if (MmiHandler =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + MmiHandler->Signature =3D MMI_HANDLER_SIGNATURE; > + MmiHandler->Handler =3D Handler; > + > + if (HandlerType =3D=3D NULL) { > + // > + // This is root MMI handler > + // > + MmiEntry =3D NULL; > + List =3D &mRootMmiHandlerList; > + } else { > + // > + // None root MMI handler > + // > + MmiEntry =3D MmCoreFindMmiEntry ((EFI_GUID *) HandlerType, TRUE); > + if (MmiEntry =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + List =3D &MmiEntry->MmiHandlers; > + } > + > + MmiHandler->MmiEntry =3D MmiEntry; > + InsertTailList (List, &MmiHandler->Link); > + > + *DispatchHandle =3D (EFI_HANDLE) MmiHandler; > + > + return EFI_SUCCESS; > +} > + > +/** > + Unregister a handler in MM. > + > + @param DispatchHandle The handle that was specified when the handler= was registered. > + > + @retval EFI_SUCCESS Handler function was successfully unregi= stered. > + @retval EFI_INVALID_PARAMETER DispatchHandle does not refer to a valid= handle. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmiHandlerUnRegister ( > + IN EFI_HANDLE DispatchHandle > + ) > +{ > + MMI_HANDLER *MmiHandler; > + MMI_ENTRY *MmiEntry; > + > + MmiHandler =3D (MMI_HANDLER *) DispatchHandle; > + > + if (MmiHandler =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (MmiHandler->Signature !=3D MMI_HANDLER_SIGNATURE) { > + return EFI_INVALID_PARAMETER; > + } > + > + MmiEntry =3D MmiHandler->MmiEntry; > + > + RemoveEntryList (&MmiHandler->Link); > + FreePool (MmiHandler); > + > + if (MmiEntry =3D=3D NULL) { > + // > + // This is root MMI handler > + // > + return EFI_SUCCESS; > + } > + > + if (IsListEmpty (&MmiEntry->MmiHandlers)) { > + // > + // No handler registered for this interrupt now, remove the MMI_ENTR= Y > + // > + RemoveEntryList (&MmiEntry->AllEntries); > + > + FreePool (MmiEntry); > + } > + > + return EFI_SUCCESS; > +} > diff --git a/StandaloneMmPkg/Core/Notify.c b/StandaloneMmPkg/Core/Notify.= c > new file mode 100644 > index 0000000000..d5fc8f50d1 > --- /dev/null > +++ b/StandaloneMmPkg/Core/Notify.c > @@ -0,0 +1,203 @@ > +/** @file > + Support functions for UEFI protocol notification infrastructure. > + > + Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#include "StandaloneMmCore.h" > + > +/** > + Signal event for every protocol in protocol entry. > + > + @param Prot Protocol interface > + > +**/ > +VOID > +MmNotifyProtocol ( > + IN PROTOCOL_INTERFACE *Prot > + ) > +{ > + PROTOCOL_ENTRY *ProtEntry; > + PROTOCOL_NOTIFY *ProtNotify; > + LIST_ENTRY *Link; > + > + ProtEntry =3D Prot->Protocol; > + for (Link=3DProtEntry->Notify.ForwardLink; Link !=3D &ProtEntry->Notif= y; Link=3DLink->ForwardLink) { > + ProtNotify =3D CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNA= TURE); > + ProtNotify->Function (&ProtEntry->ProtocolID, Prot->Interface, Prot-= >Handle); > + } > +} > + > +/** > + Removes Protocol from the protocol list (but not the handle list). > + > + @param Handle The handle to remove protocol on. > + @param Protocol GUID of the protocol to be moved > + @param Interface The interface of the protocol > + > + @return Protocol Entry > + > +**/ > +PROTOCOL_INTERFACE * > +MmRemoveInterfaceFromProtocol ( > + IN IHANDLE *Handle, > + IN EFI_GUID *Protocol, > + IN VOID *Interface > + ) > +{ > + PROTOCOL_INTERFACE *Prot; > + PROTOCOL_NOTIFY *ProtNotify; > + PROTOCOL_ENTRY *ProtEntry; > + LIST_ENTRY *Link; > + > + Prot =3D MmFindProtocolInterface (Handle, Protocol, Interface); > + if (Prot !=3D NULL) { > + > + ProtEntry =3D Prot->Protocol; > + > + // > + // If there's a protocol notify location pointing to this entry, bac= k it up one > + // > + for(Link =3D ProtEntry->Notify.ForwardLink; Link !=3D &ProtEntry->No= tify; Link=3DLink->ForwardLink) { > + ProtNotify =3D CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIG= NATURE); > + > + if (ProtNotify->Position =3D=3D &Prot->ByProtocol) { > + ProtNotify->Position =3D Prot->ByProtocol.BackLink; > + } > + } > + > + // > + // Remove the protocol interface entry > + // > + RemoveEntryList (&Prot->ByProtocol); > + } > + > + return Prot; > +} > + > +/** > + Add a new protocol notification record for the request protocol. > + > + @param Protocol The requested protocol to add the notif= y > + registration > + @param Function Points to the notification function > + @param Registration Returns the registration record > + > + @retval EFI_SUCCESS Successfully returned the registration = record > + that has been added or unhooked > + @retval EFI_INVALID_PARAMETER Protocol is NULL or Registration is NUL= L > + @retval EFI_OUT_OF_RESOURCES Not enough memory resource to finish th= e request > + @retval EFI_NOT_FOUND If the registration is not found when F= unction =3D=3D NULL > + > +**/ > +EFI_STATUS > +EFIAPI > +MmRegisterProtocolNotify ( > + IN CONST EFI_GUID *Protocol, > + IN EFI_MM_NOTIFY_FN Function, > + OUT VOID **Registration > + ) > +{ > + PROTOCOL_ENTRY *ProtEntry; > + PROTOCOL_NOTIFY *ProtNotify; > + LIST_ENTRY *Link; > + EFI_STATUS Status; > + > + if (Protocol =3D=3D NULL || Registration =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Function =3D=3D NULL) { > + // > + // Get the protocol entry per Protocol > + // > + ProtEntry =3D MmFindProtocolEntry ((EFI_GUID *) Protocol, FALSE); > + if (ProtEntry !=3D NULL) { > + ProtNotify =3D (PROTOCOL_NOTIFY * )*Registration; > + for (Link =3D ProtEntry->Notify.ForwardLink; > + Link !=3D &ProtEntry->Notify; > + Link =3D Link->ForwardLink) { > + // > + // Compare the notification record > + // > + if (ProtNotify =3D=3D (CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_= NOTIFY_SIGNATURE))){ > + // > + // If Registration is an existing registration, then unhook it > + // > + ProtNotify->Signature =3D 0; > + RemoveEntryList (&ProtNotify->Link); > + FreePool (ProtNotify); > + return EFI_SUCCESS; > + } > + } > + } > + // > + // If the registration is not found > + // > + return EFI_NOT_FOUND; > + } > + > + ProtNotify =3D NULL; > + > + // > + // Get the protocol entry to add the notification too > + // > + ProtEntry =3D MmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE); > + if (ProtEntry !=3D NULL) { > + // > + // Find whether notification already exist > + // > + for (Link =3D ProtEntry->Notify.ForwardLink; > + Link !=3D &ProtEntry->Notify; > + Link =3D Link->ForwardLink) { > + > + ProtNotify =3D CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIG= NATURE); > + if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) && > + (ProtNotify->Function =3D=3D Function)) { > + > + // > + // Notification already exist > + // > + *Registration =3D ProtNotify; > + > + return EFI_SUCCESS; > + } > + } > + > + // > + // Allocate a new notification record > + // > + ProtNotify =3D AllocatePool (sizeof(PROTOCOL_NOTIFY)); > + if (ProtNotify !=3D NULL) { > + ProtNotify->Signature =3D PROTOCOL_NOTIFY_SIGNATURE; > + ProtNotify->Protocol =3D ProtEntry; > + ProtNotify->Function =3D Function; > + // > + // Start at the ending > + // > + ProtNotify->Position =3D ProtEntry->Protocols.BackLink; > + > + InsertTailList (&ProtEntry->Notify, &ProtNotify->Link); > + } > + } > + > + // > + // Done. If we have a protocol notify entry, then return it. > + // Otherwise, we must have run out of resources trying to add one > + // > + Status =3D EFI_OUT_OF_RESOURCES; > + if (ProtNotify !=3D NULL) { > + *Registration =3D ProtNotify; > + Status =3D EFI_SUCCESS; > + } > + return Status; > +} > diff --git a/StandaloneMmPkg/Core/Page.c b/StandaloneMmPkg/Core/Page.c > new file mode 100644 > index 0000000000..ba3e7cea74 > --- /dev/null > +++ b/StandaloneMmPkg/Core/Page.c > @@ -0,0 +1,384 @@ > +/** @file > + MM Memory page management functions. > + > + Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#include "StandaloneMmCore.h" > + > +#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \ > + ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size))) > + > +#define TRUNCATE_TO_PAGES(a) ((a) >> EFI_PAGE_SHIFT) > + > +LIST_ENTRY mMmMemoryMap =3D INITIALIZE_LIST_HEAD_VARIABLE (mMmMemoryMap= ); > + > +UINTN mMapKey; > + > +/** > + Internal Function. Allocate n pages from given free page node. > + > + @param Pages The free page node. > + @param NumberOfPages Number of pages to be allocated. > + @param MaxAddress Request to allocate memory below this a= ddress. > + > + @return Memory address of allocated pages. > + > +**/ > +UINTN > +InternalAllocPagesOnOneNode ( > + IN OUT FREE_PAGE_LIST *Pages, > + IN UINTN NumberOfPages, > + IN UINTN MaxAddress > + ) > +{ > + UINTN Top; > + UINTN Bottom; > + FREE_PAGE_LIST *Node; > + > + Top =3D TRUNCATE_TO_PAGES (MaxAddress + 1 - (UINTN)Pages); > + if (Top > Pages->NumberOfPages) { > + Top =3D Pages->NumberOfPages; > + } > + Bottom =3D Top - NumberOfPages; > + > + if (Top < Pages->NumberOfPages) { > + Node =3D (FREE_PAGE_LIST*)((UINTN)Pages + EFI_PAGES_TO_SIZE (Top)); > + Node->NumberOfPages =3D Pages->NumberOfPages - Top; > + InsertHeadList (&Pages->Link, &Node->Link); > + } > + > + if (Bottom > 0) { > + Pages->NumberOfPages =3D Bottom; > + } else { > + RemoveEntryList (&Pages->Link); > + } > + > + return (UINTN)Pages + EFI_PAGES_TO_SIZE (Bottom); > +} > + > +/** > + Internal Function. Allocate n pages from free page list below MaxAddre= ss. > + > + @param FreePageList The free page node. > + @param NumberOfPages Number of pages to be allocated. > + @param MaxAddress Request to allocate memory below this a= ddress. > + > + @return Memory address of allocated pages. > + > +**/ > +UINTN > +InternalAllocMaxAddress ( > + IN OUT LIST_ENTRY *FreePageList, > + IN UINTN NumberOfPages, > + IN UINTN MaxAddress > + ) > +{ > + LIST_ENTRY *Node; > + FREE_PAGE_LIST *Pages; > + > + for (Node =3D FreePageList->BackLink; Node !=3D FreePageList; Node =3D= Node->BackLink) { > + Pages =3D BASE_CR (Node, FREE_PAGE_LIST, Link); > + if (Pages->NumberOfPages >=3D NumberOfPages && > + (UINTN)Pages + EFI_PAGES_TO_SIZE (NumberOfPages) - 1 <=3D MaxAdd= ress) { > + return InternalAllocPagesOnOneNode (Pages, NumberOfPages, MaxAddre= ss); > + } > + } > + return (UINTN)(-1); > +} > + > +/** > + Internal Function. Allocate n pages from free page list at given addre= ss. > + > + @param FreePageList The free page node. > + @param NumberOfPages Number of pages to be allocated. > + @param MaxAddress Request to allocate memory below this a= ddress. > + > + @return Memory address of allocated pages. > + > +**/ > +UINTN > +InternalAllocAddress ( > + IN OUT LIST_ENTRY *FreePageList, > + IN UINTN NumberOfPages, > + IN UINTN Address > + ) > +{ > + UINTN EndAddress; > + LIST_ENTRY *Node; > + FREE_PAGE_LIST *Pages; > + > + if ((Address & EFI_PAGE_MASK) !=3D 0) { > + return ~Address; > + } > + > + EndAddress =3D Address + EFI_PAGES_TO_SIZE (NumberOfPages); > + for (Node =3D FreePageList->BackLink; Node!=3D FreePageList; Node =3D = Node->BackLink) { > + Pages =3D BASE_CR (Node, FREE_PAGE_LIST, Link); > + if ((UINTN)Pages <=3D Address) { > + if ((UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages) < EndA= ddress) { > + break; > + } > + return InternalAllocPagesOnOneNode (Pages, NumberOfPages, EndAddre= ss); > + } > + } > + return ~Address; > +} > + > +/** > + Allocates pages from the memory map. > + > + @param Type The type of allocation to perform. > + @param MemoryType The type of memory to turn the allocate= d pages > + into. > + @param NumberOfPages The number of pages to allocate. > + @param Memory A pointer to receive the base allocated= memory > + address. > + > + @retval EFI_INVALID_PARAMETER Parameters violate checking rules defin= ed in spec. > + @retval EFI_NOT_FOUND Could not allocate pages match the requ= irement. > + @retval EFI_OUT_OF_RESOURCES No enough pages to allocate. > + @retval EFI_SUCCESS Pages successfully allocated. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInternalAllocatePages ( > + IN EFI_ALLOCATE_TYPE Type, > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN NumberOfPages, > + OUT EFI_PHYSICAL_ADDRESS *Memory > + ) > +{ > + UINTN RequestedAddress; > + > + if (MemoryType !=3D EfiRuntimeServicesCode && > + MemoryType !=3D EfiRuntimeServicesData) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (NumberOfPages > TRUNCATE_TO_PAGES ((UINTN)-1) + 1) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // We don't track memory type in MM > + // > + RequestedAddress =3D (UINTN)*Memory; > + switch (Type) { > + case AllocateAnyPages: > + RequestedAddress =3D (UINTN)(-1); > + case AllocateMaxAddress: > + *Memory =3D InternalAllocMaxAddress ( > + &mMmMemoryMap, > + NumberOfPages, > + RequestedAddress > + ); > + if (*Memory =3D=3D (UINTN)-1) { > + return EFI_OUT_OF_RESOURCES; > + } > + break; > + case AllocateAddress: > + *Memory =3D InternalAllocAddress ( > + &mMmMemoryMap, > + NumberOfPages, > + RequestedAddress > + ); > + if (*Memory !=3D RequestedAddress) { > + return EFI_NOT_FOUND; > + } > + break; > + default: > + return EFI_INVALID_PARAMETER; > + } > + return EFI_SUCCESS; > +} > + > +/** > + Allocates pages from the memory map. > + > + @param Type The type of allocation to perform. > + @param MemoryType The type of memory to turn the allocate= d pages > + into. > + @param NumberOfPages The number of pages to allocate. > + @param Memory A pointer to receive the base allocated= memory > + address. > + > + @retval EFI_INVALID_PARAMETER Parameters violate checking rules defin= ed in spec. > + @retval EFI_NOT_FOUND Could not allocate pages match the requ= irement. > + @retval EFI_OUT_OF_RESOURCES No enough pages to allocate. > + @retval EFI_SUCCESS Pages successfully allocated. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmAllocatePages ( > + IN EFI_ALLOCATE_TYPE Type, > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN NumberOfPages, > + OUT EFI_PHYSICAL_ADDRESS *Memory > + ) > +{ > + EFI_STATUS Status; > + > + Status =3D MmInternalAllocatePages (Type, MemoryType, NumberOfPages, M= emory); > + return Status; > +} > + > +/** > + Internal Function. Merge two adjacent nodes. > + > + @param First The first of two nodes to merge. > + > + @return Pointer to node after merge (if success) or pointer to next no= de (if fail). > + > +**/ > +FREE_PAGE_LIST * > +InternalMergeNodes ( > + IN FREE_PAGE_LIST *First > + ) > +{ > + FREE_PAGE_LIST *Next; > + > + Next =3D BASE_CR (First->Link.ForwardLink, FREE_PAGE_LIST, Link); > + ASSERT ( > + TRUNCATE_TO_PAGES ((UINTN)Next - (UINTN)First) >=3D First->NumberOfP= ages); > + > + if (TRUNCATE_TO_PAGES ((UINTN)Next - (UINTN)First) =3D=3D First->Numbe= rOfPages) { > + First->NumberOfPages +=3D Next->NumberOfPages; > + RemoveEntryList (&Next->Link); > + Next =3D First; > + } > + return Next; > +} > + > +/** > + Frees previous allocated pages. > + > + @param Memory Base address of memory being freed. > + @param NumberOfPages The number of pages to free. > + > + @retval EFI_NOT_FOUND Could not find the entry that covers th= e range. > + @retval EFI_INVALID_PARAMETER Address not aligned. > + @return EFI_SUCCESS Pages successfully freed. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInternalFreePages ( > + IN EFI_PHYSICAL_ADDRESS Memory, > + IN UINTN NumberOfPages > + ) > +{ > + LIST_ENTRY *Node; > + FREE_PAGE_LIST *Pages; > + > + if ((Memory & EFI_PAGE_MASK) !=3D 0) { > + return EFI_INVALID_PARAMETER; > + } > + > + Pages =3D NULL; > + Node =3D mMmMemoryMap.ForwardLink; > + while (Node !=3D &mMmMemoryMap) { > + Pages =3D BASE_CR (Node, FREE_PAGE_LIST, Link); > + if (Memory < (UINTN)Pages) { > + break; > + } > + Node =3D Node->ForwardLink; > + } > + > + if (Node !=3D &mMmMemoryMap && > + Memory + EFI_PAGES_TO_SIZE (NumberOfPages) > (UINTN)Pages) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Node->BackLink !=3D &mMmMemoryMap) { > + Pages =3D BASE_CR (Node->BackLink, FREE_PAGE_LIST, Link); > + if ((UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages) > Memory= ) { > + return EFI_INVALID_PARAMETER; > + } > + } > + > + Pages =3D (FREE_PAGE_LIST*)(UINTN)Memory; > + Pages->NumberOfPages =3D NumberOfPages; > + InsertTailList (Node, &Pages->Link); > + > + if (Pages->Link.BackLink !=3D &mMmMemoryMap) { > + Pages =3D InternalMergeNodes ( > + BASE_CR (Pages->Link.BackLink, FREE_PAGE_LIST, Link) > + ); > + } > + > + if (Node !=3D &mMmMemoryMap) { > + InternalMergeNodes (Pages); > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Frees previous allocated pages. > + > + @param Memory Base address of memory being freed. > + @param NumberOfPages The number of pages to free. > + > + @retval EFI_NOT_FOUND Could not find the entry that covers th= e range. > + @retval EFI_INVALID_PARAMETER Address not aligned. > + @return EFI_SUCCESS Pages successfully freed. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmFreePages ( > + IN EFI_PHYSICAL_ADDRESS Memory, > + IN UINTN NumberOfPages > + ) > +{ > + EFI_STATUS Status; > + > + Status =3D MmInternalFreePages (Memory, NumberOfPages); > + return Status; > +} > + > +/** > + Add free MMRAM region for use by memory service. > + > + @param MemBase Base address of memory region. > + @param MemLength Length of the memory region. > + @param Type Memory type. > + @param Attributes Memory region state. > + > +**/ > +VOID > +MmAddMemoryRegion ( > + IN EFI_PHYSICAL_ADDRESS MemBase, > + IN UINT64 MemLength, > + IN EFI_MEMORY_TYPE Type, > + IN UINT64 Attributes > + ) > +{ > + UINTN AlignedMemBase; > + > + // > + // Do not add memory regions that is already allocated, needs testing,= or needs ECC initialization > + // > + if ((Attributes & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_I= NITIALIZATION)) !=3D 0) { > + return; > + } > + > + // > + // Align range on an EFI_PAGE_SIZE boundary > + // > + AlignedMemBase =3D (UINTN)(MemBase + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; > + MemLength -=3D AlignedMemBase - MemBase; > + MmFreePages (AlignedMemBase, TRUNCATE_TO_PAGES ((UINTN)MemLength)); > +} > diff --git a/StandaloneMmPkg/Core/Pool.c b/StandaloneMmPkg/Core/Pool.c > new file mode 100644 > index 0000000000..bdf1258381 > --- /dev/null > +++ b/StandaloneMmPkg/Core/Pool.c > @@ -0,0 +1,287 @@ > +/** @file > + SMM Memory pool management functions. > + > + Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#include "StandaloneMmCore.h" > + > +LIST_ENTRY mMmPoolLists[MAX_POOL_INDEX]; > +// > +// To cache the MMRAM base since when Loading modules At fixed address f= eature is enabled, > +// all module is assigned an offset relative the MMRAM base in build tim= e. > +// > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtF= ixAddressMmramBase =3D 0; > + > +/** > + Called to initialize the memory service. > + > + @param MmramRangeCount Number of MMRAM Regions > + @param MmramRanges Pointer to MMRAM Descriptors > + > +**/ > +VOID > +MmInitializeMemoryServices ( > + IN UINTN MmramRangeCount, > + IN EFI_MMRAM_DESCRIPTOR *MmramRanges > + ) > +{ > + UINTN Index; > + > + // > + // Initialize Pool list > + // > + for (Index =3D sizeof (mMmPoolLists) / sizeof (*mMmPoolLists); Index >= 0;) { > + InitializeListHead (&mMmPoolLists[--Index]); > + } > + > + > + // > + // Initialize free MMRAM regions > + // > + for (Index =3D 0; Index < MmramRangeCount; Index++) { > + // > + // BUGBUG: Add legacy MMRAM region is buggy. > + // > + if (MmramRanges[Index].CpuStart < BASE_1MB) { > + continue; > + } > + DEBUG ((DEBUG_INFO, "MmAddMemoryRegion %d : 0x%016lx - 0x%016lx\n", = Index, MmramRanges[Index].CpuStart, MmramRanges[Index].PhysicalSize)); > + MmAddMemoryRegion ( > + MmramRanges[Index].CpuStart, > + MmramRanges[Index].PhysicalSize, > + EfiConventionalMemory, > + MmramRanges[Index].RegionState > + ); > + } > + > +} > + > +/** > + Internal Function. Allocate a pool by specified PoolIndex. > + > + @param PoolIndex Index which indicate the Pool size. > + @param FreePoolHdr The returned Free pool. > + > + @retval EFI_OUT_OF_RESOURCES Allocation failed. > + @retval EFI_SUCCESS Pool successfully allocated. > + > +**/ > +EFI_STATUS > +InternalAllocPoolByIndex ( > + IN UINTN PoolIndex, > + OUT FREE_POOL_HEADER **FreePoolHdr > + ) > +{ > + EFI_STATUS Status; > + FREE_POOL_HEADER *Hdr; > + EFI_PHYSICAL_ADDRESS Address; > + > + ASSERT (PoolIndex <=3D MAX_POOL_INDEX); > + Status =3D EFI_SUCCESS; > + Hdr =3D NULL; > + if (PoolIndex =3D=3D MAX_POOL_INDEX) { > + Status =3D MmInternalAllocatePages (AllocateAnyPages, EfiRuntimeServ= icesData, EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1), &Address); > + if (EFI_ERROR (Status)) { > + return EFI_OUT_OF_RESOURCES; > + } > + Hdr =3D (FREE_POOL_HEADER *) (UINTN) Address; > + } else if (!IsListEmpty (&mMmPoolLists[PoolIndex])) { > + Hdr =3D BASE_CR (GetFirstNode (&mMmPoolLists[PoolIndex]), FREE_POOL_= HEADER, Link); > + RemoveEntryList (&Hdr->Link); > + } else { > + Status =3D InternalAllocPoolByIndex (PoolIndex + 1, &Hdr); > + if (!EFI_ERROR (Status)) { > + Hdr->Header.Size >>=3D 1; > + Hdr->Header.Available =3D TRUE; > + InsertHeadList (&mMmPoolLists[PoolIndex], &Hdr->Link); > + Hdr =3D (FREE_POOL_HEADER*)((UINT8*)Hdr + Hdr->Header.Size); > + } > + } > + > + if (!EFI_ERROR (Status)) { > + Hdr->Header.Size =3D MIN_POOL_SIZE << PoolIndex; > + Hdr->Header.Available =3D FALSE; > + } > + > + *FreePoolHdr =3D Hdr; > + return Status; > +} > + > +/** > + Internal Function. Free a pool by specified PoolIndex. > + > + @param FreePoolHdr The pool to free. > + > + @retval EFI_SUCCESS Pool successfully freed. > + > +**/ > +EFI_STATUS > +InternalFreePoolByIndex ( > + IN FREE_POOL_HEADER *FreePoolHdr > + ) > +{ > + UINTN PoolIndex; > + > + ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) = =3D=3D 0); > + ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) =3D=3D 0= ); > + ASSERT (FreePoolHdr->Header.Size >=3D MIN_POOL_SIZE); > + > + PoolIndex =3D (UINTN) (HighBitSet32 ((UINT32)FreePoolHdr->Header.Size)= - MIN_POOL_SHIFT); > + FreePoolHdr->Header.Available =3D TRUE; > + ASSERT (PoolIndex < MAX_POOL_INDEX); > + InsertHeadList (&mMmPoolLists[PoolIndex], &FreePoolHdr->Link); > + return EFI_SUCCESS; > +} > + > +/** > + Allocate pool of a particular type. > + > + @param PoolType Type of pool to allocate. > + @param Size The amount of pool to allocate. > + @param Buffer The address to return a pointer to the = allocated > + pool. > + > + @retval EFI_INVALID_PARAMETER PoolType not valid. > + @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocatio= n failed. > + @retval EFI_SUCCESS Pool successfully allocated. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInternalAllocatePool ( > + IN EFI_MEMORY_TYPE PoolType, > + IN UINTN Size, > + OUT VOID **Buffer > + ) > +{ > + POOL_HEADER *PoolHdr; > + FREE_POOL_HEADER *FreePoolHdr; > + EFI_STATUS Status; > + EFI_PHYSICAL_ADDRESS Address; > + UINTN PoolIndex; > + > + if (PoolType !=3D EfiRuntimeServicesCode && > + PoolType !=3D EfiRuntimeServicesData) { > + return EFI_INVALID_PARAMETER; > + } > + > + Size +=3D sizeof (*PoolHdr); > + if (Size > MAX_POOL_SIZE) { > + Size =3D EFI_SIZE_TO_PAGES (Size); > + Status =3D MmInternalAllocatePages (AllocateAnyPages, PoolType, Size= , &Address); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + PoolHdr =3D (POOL_HEADER*)(UINTN)Address; > + PoolHdr->Size =3D EFI_PAGES_TO_SIZE (Size); > + PoolHdr->Available =3D FALSE; > + *Buffer =3D PoolHdr + 1; > + return Status; > + } > + > + Size =3D (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT; > + PoolIndex =3D (UINTN) HighBitSet32 ((UINT32)Size); > + if ((Size & (Size - 1)) !=3D 0) { > + PoolIndex++; > + } > + > + Status =3D InternalAllocPoolByIndex (PoolIndex, &FreePoolHdr); > + if (!EFI_ERROR(Status)) { > + *Buffer =3D &FreePoolHdr->Header + 1; > + } > + return Status; > +} > + > +/** > + Allocate pool of a particular type. > + > + @param PoolType Type of pool to allocate. > + @param Size The amount of pool to allocate. > + @param Buffer The address to return a pointer to the = allocated > + pool. > + > + @retval EFI_INVALID_PARAMETER PoolType not valid. > + @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocatio= n failed. > + @retval EFI_SUCCESS Pool successfully allocated. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmAllocatePool ( > + IN EFI_MEMORY_TYPE PoolType, > + IN UINTN Size, > + OUT VOID **Buffer > + ) > +{ > + EFI_STATUS Status; > + > + Status =3D MmInternalAllocatePool (PoolType, Size, Buffer); > + return Status; > +} > + > +/** > + Frees pool. > + > + @param Buffer The allocated pool entry to free. > + > + @retval EFI_INVALID_PARAMETER Buffer is not a valid value. > + @retval EFI_SUCCESS Pool successfully freed. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInternalFreePool ( > + IN VOID *Buffer > + ) > +{ > + FREE_POOL_HEADER *FreePoolHdr; > + > + if (Buffer =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + FreePoolHdr =3D (FREE_POOL_HEADER*)((POOL_HEADER*)Buffer - 1); > + ASSERT (!FreePoolHdr->Header.Available); > + > + if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) { > + ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) =3D=3D 0); > + ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) =3D=3D 0); > + return MmInternalFreePages ( > + (EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr, > + EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size) > + ); > + } > + return InternalFreePoolByIndex (FreePoolHdr); > +} > + > +/** > + Frees pool. > + > + @param Buffer The allocated pool entry to free. > + > + @retval EFI_INVALID_PARAMETER Buffer is not a valid value. > + @retval EFI_SUCCESS Pool successfully freed. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmFreePool ( > + IN VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + > + Status =3D MmInternalFreePool (Buffer); > + return Status; > +} > diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.c b/StandaloneMmPkg/Co= re/StandaloneMmCore.c > new file mode 100644 > index 0000000000..0bb99b9710 > --- /dev/null > +++ b/StandaloneMmPkg/Core/StandaloneMmCore.c > @@ -0,0 +1,708 @@ > +/** @file > + MM Core Main Entry Point > + > + Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#include "StandaloneMmCore.h" > + > +EFI_STATUS > +MmCoreFfsFindMmDriver ( > + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader > + ); > + > +EFI_STATUS > +MmDispatcher ( > + VOID > + ); > + > +// > +// Globals used to initialize the protocol > +// > +EFI_HANDLE mMmCpuHandle =3D NULL; > + > +// > +// Physical pointer to private structure shared between MM IPL and the M= M Core > +// > +MM_CORE_PRIVATE_DATA *gMmCorePrivate; > + > +// > +// MM Core global variable for MM System Table. Only accessed as a phys= ical structure in MMRAM. > +// > +EFI_MM_SYSTEM_TABLE gMmCoreMmst =3D { > + > + // The table header for the MMST. > + { > + MM_MMST_SIGNATURE, > + EFI_MM_SYSTEM_TABLE_REVISION, > + sizeof (gMmCoreMmst.Hdr) > + }, > + // MmFirmwareVendor > + NULL, > + // MmFirmwareRevision > + 0, > + // MmInstallConfigurationTable > + MmInstallConfigurationTable, > + // I/O Service > + { > + { > + (EFI_MM_CPU_IO) MmEfiNotAvailableYetArg5, // MmMemRead > + (EFI_MM_CPU_IO) MmEfiNotAvailableYetArg5 // MmMemWrite > + }, > + { > + (EFI_MM_CPU_IO) MmEfiNotAvailableYetArg5, // MmIoRead > + (EFI_MM_CPU_IO) MmEfiNotAvailableYetArg5 // MmIoWrite > + } > + }, > + // Runtime memory services > + MmAllocatePool, > + MmFreePool, > + MmAllocatePages, > + MmFreePages, > + // MP service > + NULL, // MmStartupThisAp > + 0, // CurrentlyExecutingCpu > + 0, // NumberOfCpus > + NULL, // CpuSaveStateSize > + NULL, // CpuSaveState > + 0, // NumberOfTableEntries > + NULL, // MmConfigurationTable > + MmInstallProtocolInterface, > + MmUninstallProtocolInterface, > + MmHandleProtocol, > + MmRegisterProtocolNotify, > + MmLocateHandle, > + MmLocateProtocol, > + MmiManage, > + MmiHandlerRegister, > + MmiHandlerUnRegister > +}; > + > +// > +// Flag to determine if the platform has performed a legacy boot. > +// If this flag is TRUE, then the runtime code and runtime data associat= ed with the > +// MM IPL are converted to free memory, so the MM Core must guarantee th= at is > +// does not touch of the code/data associated with the MM IPL if this fl= ag is TRUE. > +// > +BOOLEAN mInLegacyBoot =3D FALSE; > + > +// > +// Table of MMI Handlers that are registered by the MM Core when it is i= nitialized > +// > +MM_CORE_MMI_HANDLERS mMmCoreMmiHandlers[] =3D { > + { MmFvDispatchHandler, &gMmFvDispatchGuid, NULL, T= RUE }, > + { MmDriverDispatchHandler, &gEfiEventDxeDispatchGuid, NULL, T= RUE }, > + { MmReadyToLockHandler, &gEfiDxeMmReadyToLockProtocolGuid, NULL, T= RUE }, > + { MmEndOfDxeHandler, &gEfiEndOfDxeEventGroupGuid, NULL, F= ALSE }, > + { MmLegacyBootHandler, &gEfiEventLegacyBootGuid, NULL, F= ALSE }, > + { MmExitBootServiceHandler,&gEfiEventExitBootServicesGuid, NULL, F= ALSE }, > + { MmReadyToBootHandler, &gEfiEventReadyToBootGuid, NULL, F= ALSE }, > + { NULL, NULL, NULL, F= ALSE }, > +}; > + > +EFI_SYSTEM_TABLE *mEfiSystemTable; > +UINTN mMmramRangeCount; > +EFI_MMRAM_DESCRIPTOR *mMmramRanges; > + > +/** > + Place holder function until all the MM System Table Service are availa= ble. > + > + Note: This function is only used by MMRAM invocation. It is never use= d by DXE invocation. > + > + @param Arg1 Undefined > + @param Arg2 Undefined > + @param Arg3 Undefined > + @param Arg4 Undefined > + @param Arg5 Undefined > + > + @return EFI_NOT_AVAILABLE_YET > + > +**/ > +EFI_STATUS > +EFIAPI > +MmEfiNotAvailableYetArg5 ( > + UINTN Arg1, > + UINTN Arg2, > + UINTN Arg3, > + UINTN Arg4, > + UINTN Arg5 > + ) > +{ > + // > + // This function should never be executed. If it does, then the archi= tectural protocols > + // have not been designed correctly. > + // > + return EFI_NOT_AVAILABLE_YET; > +} > + > +/** > + Software MMI handler that is called when a Legacy Boot event is signal= ed. The MM > + Core uses this signal to know that a Legacy Boot has been performed an= d that > + gMmCorePrivate that is shared between the UEFI and MM execution enviro= nments can > + not be accessed from MM anymore since that structure is considered fre= e memory by > + a legacy OS. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmLegacyBootHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ) > +{ > + EFI_HANDLE MmHandle; > + EFI_STATUS Status =3D EFI_SUCCESS; > + > + if (!mInLegacyBoot) { > + MmHandle =3D NULL; > + Status =3D MmInstallProtocolInterface ( > + &MmHandle, > + &gEfiEventLegacyBootGuid, > + EFI_NATIVE_INTERFACE, > + NULL > + ); > + } > + mInLegacyBoot =3D TRUE; > + return Status; > +} > + > +/** > + Software MMI handler that is called when a ExitBoot Service event is s= ignaled. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmExitBootServiceHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ) > +{ > + EFI_HANDLE MmHandle; > + EFI_STATUS Status =3D EFI_SUCCESS; > + STATIC BOOLEAN mInExitBootServices =3D FALSE; > + > + if (!mInExitBootServices) { > + MmHandle =3D NULL; > + Status =3D MmInstallProtocolInterface ( > + &MmHandle, > + &gEfiEventExitBootServicesGuid, > + EFI_NATIVE_INTERFACE, > + NULL > + ); > + } > + mInExitBootServices =3D TRUE; > + return Status; > +} > + > +/** > + Software MMI handler that is called when a ExitBoot Service event is s= ignaled. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmReadyToBootHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ) > +{ > + EFI_HANDLE MmHandle; > + EFI_STATUS Status =3D EFI_SUCCESS; > + STATIC BOOLEAN mInReadyToBoot =3D FALSE; > + > + if (!mInReadyToBoot) { > + MmHandle =3D NULL; > + Status =3D MmInstallProtocolInterface ( > + &MmHandle, > + &gEfiEventReadyToBootGuid, > + EFI_NATIVE_INTERFACE, > + NULL > + ); > + } > + mInReadyToBoot =3D TRUE; > + return Status; > +} > + > +/** > + Software MMI handler that is called when the DxeMmReadyToLock protocol= is added > + or if gEfiEventReadyToBootGuid is signaled. This function unregisters= the > + Software SMIs that are nor required after MMRAM is locked and installs= the > + MM Ready To Lock Protocol so MM Drivers are informed that MMRAM is abo= ut > + to be locked. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmReadyToLockHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + EFI_HANDLE MmHandle; > + > + DEBUG ((DEBUG_INFO, "MmReadyToLockHandler\n")); > + > + // > + // Unregister MMI Handlers that are no longer required after the MM dr= iver dispatch is stopped > + // > + for (Index =3D 0; mMmCoreMmiHandlers[Index].HandlerType !=3D NULL; Ind= ex++) { > + if (mMmCoreMmiHandlers[Index].UnRegister) { > + MmiHandlerUnRegister (mMmCoreMmiHandlers[Index].DispatchHandle); > + } > + } > + > + // > + // Install MM Ready to lock protocol > + // > + MmHandle =3D NULL; > + Status =3D MmInstallProtocolInterface ( > + &MmHandle, > + &gEfiMmReadyToLockProtocolGuid, > + EFI_NATIVE_INTERFACE, > + NULL > + ); > + > + // > + // Make sure MM CPU I/O 2 Protocol has been installed into the handle = database > + // > + //Status =3D MmLocateProtocol (&EFI_MM_CPU_IO_PROTOCOL_GUID, NULL, &In= terface); > + > + // > + // Print a message on a debug build if the MM CPU I/O 2 Protocol is no= t installed > + // > + //if (EFI_ERROR (Status)) { > + //DEBUG ((DEBUG_ERROR, "\nSMM: SmmCpuIo Arch Protocol not present!= !\n")); > + //} > + > + > + // > + // Assert if the CPU I/O 2 Protocol is not installed > + // > + //ASSERT_EFI_ERROR (Status); > + > + // > + // Display any drivers that were not dispatched because dependency exp= ression > + // evaluated to false if this is a debug build > + // > + //MmDisplayDiscoveredNotDispatched (); > + > + return Status; > +} > + > +/** > + Software MMI handler that is called when the EndOfDxe event is signale= d. > + This function installs the MM EndOfDxe Protocol so MM Drivers are info= rmed that > + platform code will invoke 3rd part code. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmEndOfDxeHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE MmHandle; > + > + DEBUG ((DEBUG_INFO, "MmEndOfDxeHandler\n")); > + // > + // Install MM EndOfDxe protocol > + // > + MmHandle =3D NULL; > + Status =3D MmInstallProtocolInterface ( > + &MmHandle, > + &gEfiMmEndOfDxeProtocolGuid, > + EFI_NATIVE_INTERFACE, > + NULL > + ); > + return Status; > +} > + > + > + > +/** > + The main entry point to MM Foundation. > + > + Note: This function is only used by MMRAM invocation. It is never use= d by DXE invocation. > + > + @param MmEntryContext Processor information and functionali= ty > + needed by MM Foundation. > + > +**/ > +VOID > +EFIAPI > +MmEntryPoint ( > + IN CONST EFI_MM_ENTRY_CONTEXT *MmEntryContext > +) > +{ > + EFI_STATUS Status; > + EFI_MM_COMMUNICATE_HEADER *CommunicateHeader; > + BOOLEAN InLegacyBoot; > + > + DEBUG ((DEBUG_INFO, "MmEntryPoint ...\n")); > + > + // > + // Update MMST using the context > + // > + CopyMem (&gMmCoreMmst.MmStartupThisAp, MmEntryContext, sizeof (EFI_MM_= ENTRY_CONTEXT)); > + > + // > + // Call platform hook before Mm Dispatch > + // > + //PlatformHookBeforeMmDispatch (); > + > + // > + // If a legacy boot has occured, then make sure gMmCorePrivate is not = accessed > + // > + InLegacyBoot =3D mInLegacyBoot; > + if (!InLegacyBoot) { > + // > + // TBD: Mark the InMm flag as TRUE > + // > + gMmCorePrivate->InMm =3D TRUE; > + > + // > + // Check to see if this is a Synchronous MMI sent through the MM Com= munication > + // Protocol or an Asynchronous MMI > + // > + if (gMmCorePrivate->CommunicationBuffer !=3D 0) { > + // > + // Synchronous MMI for MM Core or request from Communicate protoco= l > + // > + if (!MmIsBufferOutsideMmValid ((UINTN)gMmCorePrivate->Communicatio= nBuffer, gMmCorePrivate->BufferSize)) { > + // > + // If CommunicationBuffer is not in valid address scope, return = EFI_INVALID_PARAMETER > + // > + gMmCorePrivate->CommunicationBuffer =3D 0; > + gMmCorePrivate->ReturnStatus =3D EFI_INVALID_PARAMETER; > + } else { > + CommunicateHeader =3D (EFI_MM_COMMUNICATE_HEADER *)(UINTN)gMmCor= ePrivate->CommunicationBuffer; > + gMmCorePrivate->BufferSize -=3D OFFSET_OF (EFI_MM_COMMUNICATE_HE= ADER, Data); > + //DEBUG ((DEBUG_INFO, "CommunicateHeader->HeaderGuid - %g\n", &C= ommunicateHeader->HeaderGuid)); > + Status =3D MmiManage ( > + &CommunicateHeader->HeaderGuid, > + NULL, > + CommunicateHeader->Data, > + (UINTN *)&gMmCorePrivate->BufferSize > + ); > + // > + // Update CommunicationBuffer, BufferSize and ReturnStatus > + // Communicate service finished, reset the pointer to CommBuffer= to NULL > + // > + gMmCorePrivate->BufferSize +=3D OFFSET_OF (EFI_MM_COMMUNICATE_HE= ADER, Data); > + gMmCorePrivate->CommunicationBuffer =3D 0; > + gMmCorePrivate->ReturnStatus =3D (Status =3D=3D EFI_SUCCESS) ? E= FI_SUCCESS : EFI_NOT_FOUND; > + } > + } > + } > + > + // > + // Process Asynchronous MMI sources > + // > + MmiManage (NULL, NULL, NULL, NULL); > + > + // > + // TBD: Do not use private data structure ? > + // > + > + // > + // If a legacy boot has occured, then make sure gMmCorePrivate is not = accessed > + // > + if (!InLegacyBoot) { > + // > + // Clear the InMm flag as we are going to leave MM > + // > + gMmCorePrivate->InMm =3D FALSE; > + } > + > + DEBUG ((DEBUG_INFO, "MmEntryPoint Done\n")); > +} > + > +EFI_STATUS > +EFIAPI > +MmConfigurationMmNotify ( > + IN CONST EFI_GUID *Protocol, > + IN VOID *Interface, > + IN EFI_HANDLE Handle > + ) > +{ > + EFI_STATUS Status; > + EFI_MM_CONFIGURATION_PROTOCOL *MmConfiguration; > + > + DEBUG ((DEBUG_INFO, "MmConfigurationMmNotify(%g) - %x\n", Protocol, In= terface)); > + > + MmConfiguration =3D Interface; > + > + // > + // Register the MM Entry Point provided by the MM Core with the MM COn= figuration protocol > + // > + Status =3D MmConfiguration->RegisterMmEntry (MmConfiguration, (EFI_MM_= ENTRY_POINT)(UINTN)gMmCorePrivate->MmEntryPoint); > + ASSERT_EFI_ERROR (Status); > + > + // > + // Set flag to indicate that the MM Entry Point has been registered wh= ich > + // means that MMIs are now fully operational. > + // > + gMmCorePrivate->MmEntryPointRegistered =3D TRUE; > + > + // > + // Print debug message showing MM Core entry point address. > + // > + DEBUG ((DEBUG_INFO, "MM Core registered MM Entry Point address %p\n", = (VOID *)(UINTN)gMmCorePrivate->MmEntryPoint)); > + return EFI_SUCCESS; > +} > + > +UINTN > +GetHobListSize ( > + IN VOID *HobStart > + ) > +{ > + EFI_PEI_HOB_POINTERS Hob; > + > + ASSERT (HobStart !=3D NULL); > + > + Hob.Raw =3D (UINT8 *) HobStart; > + while (!END_OF_HOB_LIST (Hob)) { > + Hob.Raw =3D GET_NEXT_HOB (Hob); > + } > + // > + // Need plus END_OF_HOB_LIST > + // > + return (UINTN)Hob.Raw - (UINTN)HobStart + sizeof(EFI_HOB_GENERIC_HEADE= R); > +} > + > +/** > + The Entry Point for MM Core > + > + Install DXE Protocols and reload MM Core into MMRAM and register MM Co= re > + EntryPoint on the MMI vector. > + > + Note: This function is called for both DXE invocation and MMRAM invoca= tion. > + > + @param ImageHandle The firmware allocated handle for the EFI image= . > + @param SystemTable A pointer to the EFI System Table. > + > + @retval EFI_SUCCESS The entry point is executed successfully. > + @retval Other Some error occurred when executing this entry p= oint. > + > +**/ > +EFI_STATUS > +EFIAPI > +StandaloneMmMain ( > + IN VOID *HobStart > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + VOID *MmHobStart; > + UINTN HobSize; > + VOID *Registration; > + EFI_HOB_GUID_TYPE *GuidHob; > + MM_CORE_DATA_HOB_DATA *DataInHob; > + EFI_HOB_GUID_TYPE *MmramRangesHob; > + EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHobData; > + EFI_MMRAM_DESCRIPTOR *MmramRanges; > + UINT32 MmramRangeCount; > + EFI_HOB_FIRMWARE_VOLUME *BfvHob; > + > + ProcessLibraryConstructorList (HobStart, &gMmCoreMmst); > + > + DEBUG ((DEBUG_INFO, "MmMain - 0x%x\n", HobStart)); > + > + // > + // Determine if the caller has passed a reference to a MM_CORE_PRIVATE= _DATA > + // structure in the Hoblist. This choice will govern how boot informat= ion is > + // extracted later. > + // > + GuidHob =3D GetNextGuidHob (&gMmCoreDataHobGuid, HobStart); > + if (GuidHob =3D=3D NULL) { > + // > + // Allocate and zero memory for a MM_CORE_PRIVATE_DATA table and the= n > + // initialise it > + // > + gMmCorePrivate =3D (MM_CORE_PRIVATE_DATA *) AllocateRuntimePages(EFI= _SIZE_TO_PAGES(sizeof(MM_CORE_PRIVATE_DATA))); > + SetMem ((VOID *)(UINTN)gMmCorePrivate, sizeof(MM_CORE_PRIVATE_DATA),= 0); > + gMmCorePrivate->Signature =3D MM_CORE_PRIVATE_DATA_SIGNATURE; > + gMmCorePrivate->MmEntryPointRegistered =3D FALSE; > + gMmCorePrivate->InMm =3D FALSE; > + gMmCorePrivate->ReturnStatus =3D EFI_SUCCESS; > + > + // > + // Extract the MMRAM ranges from the MMRAM descriptor HOB > + // > + MmramRangesHob =3D GetNextGuidHob (&gEfiMmPeiMmramMemoryReserveGuid,= HobStart); > + if (MmramRangesHob =3D=3D NULL) > + return EFI_UNSUPPORTED; > + > + MmramRangesHobData =3D GET_GUID_HOB_DATA (MmramRangesHob); > + ASSERT (MmramRangesHobData !=3D NULL); > + MmramRanges =3D MmramRangesHobData->Descriptor; > + MmramRangeCount =3D MmramRangesHobData->NumberOfMmReservedRegions; > + ASSERT (MmramRanges); > + ASSERT (MmramRangeCount); > + > + // > + // Copy the MMRAM ranges into MM_CORE_PRIVATE_DATA table just in cas= e any > + // code relies on them being present there > + // > + gMmCorePrivate->MmramRangeCount =3D MmramRangeCount; > + gMmCorePrivate->MmramRanges =3D (EFI_PHYSICAL_ADDRESS)(UINTN)Allocat= ePool (MmramRangeCount * sizeof(EFI_MMRAM_DESCRIPTOR)); > + ASSERT (gMmCorePrivate->MmramRanges !=3D 0); > + CopyMem ((VOID *)(UINTN)gMmCorePrivate->MmramRanges, > + MmramRanges, > + MmramRangeCount * sizeof(EFI_MMRAM_DESCRIPTOR)); > + } else { > + DataInHob =3D GET_GUID_HOB_DATA (GuidHob); > + gMmCorePrivate =3D (MM_CORE_PRIVATE_DATA *)(UINTN)DataInHob->Address= ; > + MmramRanges =3D (EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->M= mramRanges; > + MmramRangeCount =3D gMmCorePrivate->MmramRangeCount; > + } > + > + // > + // Print the MMRAM ranges passed by the caller > + // > + DEBUG ((DEBUG_INFO, "MmramRangeCount - 0x%x\n", MmramRangeCount)); > + for (Index =3D 0; Index < MmramRangeCount; Index++) { > + DEBUG ((DEBUG_INFO, "MmramRanges[%d]: 0x%016lx - 0x%lx\n", Ind= ex, > + MmramRanges[Index].CpuStart, > + MmramRanges[Index].PhysicalSize)); > + } > + > + // > + // Copy the MMRAM ranges into private MMRAM > + // > + mMmramRangeCount =3D MmramRangeCount; > + DEBUG ((DEBUG_INFO, "mMmramRangeCount - 0x%x\n", mMmramRangeCount)); > + mMmramRanges =3D AllocatePool (mMmramRangeCount * sizeof (EFI_MMRAM_DE= SCRIPTOR)); > + DEBUG ((DEBUG_INFO, "mMmramRanges - 0x%x\n", mMmramRanges)); > + ASSERT (mMmramRanges !=3D NULL); > + CopyMem (mMmramRanges, (VOID *)(UINTN)MmramRanges, mMmramRangeCount * = sizeof (EFI_MMRAM_DESCRIPTOR)); > + > + // > + // Get Boot Firmware Volume address from the BFV Hob > + // > + BfvHob =3D GetFirstHob (EFI_HOB_TYPE_FV); > + if (BfvHob !=3D NULL) { > + DEBUG ((DEBUG_INFO, "BFV address - 0x%x\n", BfvHob->BaseAddress)); > + DEBUG ((DEBUG_INFO, "BFV size - 0x%x\n", BfvHob->Length)); > + gMmCorePrivate->StandaloneBfvAddress =3D BfvHob->BaseAddress; > + } > + > + gMmCorePrivate->Mmst =3D (EFI_PHYSICAL_ADDRESS)(UINTN)&gMmCor= eMmst; > + gMmCorePrivate->MmEntryPoint =3D (EFI_PHYSICAL_ADDRESS)(UINTN)MmEntryP= oint; > + > + // > + // No need to initialize memory service. > + // It is done in constructor of StandaloneMmCoreMemoryAllocationLib(), > + // so that the library linked with StandaloneMmCore can use AllocatePo= ol() in constuctor. > + // > + > + DEBUG ((DEBUG_INFO, "MmInstallConfigurationTable For HobList\n")); > + // > + // Install HobList > + // > + HobSize =3D GetHobListSize (HobStart); > + DEBUG ((DEBUG_INFO, "HobSize - 0x%x\n", HobSize)); > + MmHobStart =3D AllocatePool (HobSize); > + DEBUG ((DEBUG_INFO, "MmHobStart - 0x%x\n", MmHobStart)); > + ASSERT (MmHobStart !=3D NULL); > + CopyMem (MmHobStart, HobStart, HobSize); > + Status =3D MmInstallConfigurationTable (&gMmCoreMmst, &gEfiHobListGuid= , MmHobStart, HobSize); > + ASSERT_EFI_ERROR (Status); > + > + // > + // Register notification for EFI_MM_CONFIGURATION_PROTOCOL registratio= n and > + // use it to register the MM Foundation entrypoint > + // > + DEBUG ((DEBUG_INFO, "MmRegisterProtocolNotify - MmConfigurationMmProto= col\n")); > + Status =3D MmRegisterProtocolNotify ( > + &gEfiMmConfigurationProtocolGuid, > + MmConfigurationMmNotify, > + &Registration > + ); > + ASSERT_EFI_ERROR (Status); > + > + // > + // Dispatch standalone BFV > + // > + DEBUG ((DEBUG_INFO, "Mm Dispatch StandaloneBfvAddress - 0x%08x\n", gMm= CorePrivate->StandaloneBfvAddress)); > + if (gMmCorePrivate->StandaloneBfvAddress !=3D 0) { > + MmCoreFfsFindMmDriver ((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)gMmCoreP= rivate->StandaloneBfvAddress); > + MmDispatcher (); > + } > + > + // > + // Register all handlers in the core table > + // > + for (Index =3D 0; mMmCoreMmiHandlers[Index].HandlerType !=3D NULL; Ind= ex++) { > + Status =3D MmiHandlerRegister(mMmCoreMmiHandlers[Index].Handler, > + mMmCoreMmiHandlers[Index].HandlerType, > + &mMmCoreMmiHandlers[Index].DispatchHandl= e); > + DEBUG ((DEBUG_INFO, "MmiHandlerRegister - GUID %g - Status %d\n", mM= mCoreMmiHandlers[Index].HandlerType, Status)); > + } > + > + DEBUG ((DEBUG_INFO, "MmMain Done!\n")); > + > + return EFI_SUCCESS; > +} > diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.h b/StandaloneMmPkg/Co= re/StandaloneMmCore.h > new file mode 100644 > index 0000000000..53921b7844 > --- /dev/null > +++ b/StandaloneMmPkg/Core/StandaloneMmCore.h > @@ -0,0 +1,903 @@ > +/** @file > + The internal header file includes the common header files, defines > + internal structure and functions used by MmCore module. > + > + Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + > + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#ifndef _MM_CORE_H_ > +#define _MM_CORE_H_ > + > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +//#include > +#include > +#include > + > +#include "StandaloneMmCorePrivateData.h" > + > +// > +// Used to build a table of MMI Handlers that the MM Core registers > +// > +typedef struct { > + EFI_MM_HANDLER_ENTRY_POINT Handler; > + EFI_GUID *HandlerType; > + EFI_HANDLE DispatchHandle; > + BOOLEAN UnRegister; > +} MM_CORE_MMI_HANDLERS; > + > +// > +// Structure for recording the state of an MM Driver > +// > +#define EFI_MM_DRIVER_ENTRY_SIGNATURE SIGNATURE_32('s', 'd','r','v') > + > +typedef struct { > + UINTN Signature; > + LIST_ENTRY Link; // mDriverList > + > + LIST_ENTRY ScheduledLink; // mScheduledQueue > + > + EFI_HANDLE FvHandle; > + EFI_GUID FileName; > + VOID *Pe32Data; > + UINTN Pe32DataSize; > + > + VOID *Depex; > + UINTN DepexSize; > + > + BOOLEAN Before; > + BOOLEAN After; > + EFI_GUID BeforeAfterGuid; > + > + BOOLEAN Dependent; > + BOOLEAN Scheduled; > + BOOLEAN Initialized; > + BOOLEAN DepexProtocolError; > + > + EFI_HANDLE ImageHandle; > + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; > + // > + // Image EntryPoint in MMRAM > + // > + PHYSICAL_ADDRESS ImageEntryPoint; > + // > + // Image Buffer in MMRAM > + // > + PHYSICAL_ADDRESS ImageBuffer; > + // > + // Image Page Number > + // > + UINTN NumberOfPage; > +} EFI_MM_DRIVER_ENTRY; > + > +#define EFI_HANDLE_SIGNATURE SIGNATURE_32('h','n','d','l') > + > +/// > +/// IHANDLE - contains a list of protocol handles > +/// > +typedef struct { > + UINTN Signature; > + /// All handles list of IHANDLE > + LIST_ENTRY AllHandles; > + /// List of PROTOCOL_INTERFACE's for this handle > + LIST_ENTRY Protocols; > + UINTN LocateRequest; > +} IHANDLE; > + > +#define ASSERT_IS_HANDLE(a) ASSERT((a)->Signature =3D=3D EFI_HANDLE_SIG= NATURE) > + > +#define PROTOCOL_ENTRY_SIGNATURE SIGNATURE_32('p','r','t','e') > + > +/// > +/// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol > +/// database. Each handler that supports this protocol is listed, along > +/// with a list of registered notifies. > +/// > +typedef struct { > + UINTN Signature; > + /// Link Entry inserted to mProtocolDatabase > + LIST_ENTRY AllEntries; > + /// ID of the protocol > + EFI_GUID ProtocolID; > + /// All protocol interfaces > + LIST_ENTRY Protocols; > + /// Registerd notification handlers > + LIST_ENTRY Notify; > +} PROTOCOL_ENTRY; > + > +#define PROTOCOL_INTERFACE_SIGNATURE SIGNATURE_32('p','i','f','c') > + > +/// > +/// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked > +/// with a protocol interface structure > +/// > +typedef struct { > + UINTN Signature; > + /// Link on IHANDLE.Protocols > + LIST_ENTRY Link; > + /// Back pointer > + IHANDLE *Handle; > + /// Link on PROTOCOL_ENTRY.Protocols > + LIST_ENTRY ByProtocol; > + /// The protocol ID > + PROTOCOL_ENTRY *Protocol; > + /// The interface value > + VOID *Interface; > +} PROTOCOL_INTERFACE; > + > +#define PROTOCOL_NOTIFY_SIGNATURE SIGNATURE_32('p','r','t','n') > + > +/// > +/// PROTOCOL_NOTIFY - used for each register notification for a protocol > +/// > +typedef struct { > + UINTN Signature; > + PROTOCOL_ENTRY *Protocol; > + /// All notifications for this protocol > + LIST_ENTRY Link; > + /// Notification function > + EFI_MM_NOTIFY_FN Function; > + /// Last position notified > + LIST_ENTRY *Position; > +} PROTOCOL_NOTIFY; > + > +// > +// MM Core Global Variables > +// > +extern MM_CORE_PRIVATE_DATA *gMmCorePrivate; > +extern EFI_MM_SYSTEM_TABLE gMmCoreMmst; > +extern LIST_ENTRY gHandleList; > +extern EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressMmramBase; > + > +/** > + Called to initialize the memory service. > + > + @param MmramRangeCount Number of MMRAM Regions > + @param MmramRanges Pointer to MMRAM Descriptors > + > +**/ > +VOID > +MmInitializeMemoryServices ( > + IN UINTN MmramRangeCount, > + IN EFI_MMRAM_DESCRIPTOR *MmramRanges > + ); > + > +/** > + The MmInstallConfigurationTable() function is used to maintain the lis= t > + of configuration tables that are stored in the System Management Syste= m > + Table. The list is stored as an array of (GUID, Pointer) pairs. The = list > + must be allocated from pool memory with PoolType set to EfiRuntimeServ= icesData. > + > + @param SystemTable A pointer to the MM System Table (SMST). > + @param Guid A pointer to the GUID for the entry to add, u= pdate, or remove. > + @param Table A pointer to the buffer of the table to add. > + @param TableSize The size of the table to install. > + > + @retval EFI_SUCCESS The (Guid, Table) pair was added, update= d, or removed. > + @retval EFI_INVALID_PARAMETER Guid is not valid. > + @retval EFI_NOT_FOUND An attempt was made to delete a non-exis= tent entry. > + @retval EFI_OUT_OF_RESOURCES There is not enough memory available to = complete the operation. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInstallConfigurationTable ( > + IN CONST EFI_MM_SYSTEM_TABLE *SystemTable, > + IN CONST EFI_GUID *Guid, > + IN VOID *Table, > + IN UINTN TableSize > + ); > + > +/** > + Wrapper function to MmInstallProtocolInterfaceNotify. This is the pub= lic API which > + Calls the private one which contains a BOOLEAN parameter for notificat= ions > + > + @param UserHandle The handle to install the protocol hand= ler on, > + or NULL if a new handle is to be alloca= ted > + @param Protocol The protocol to add to the handle > + @param InterfaceType Indicates whether Interface is supplied= in > + native form. > + @param Interface The interface for the protocol being ad= ded > + > + @return Status code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInstallProtocolInterface ( > + IN OUT EFI_HANDLE *UserHandle, > + IN EFI_GUID *Protocol, > + IN EFI_INTERFACE_TYPE InterfaceType, > + IN VOID *Interface > + ); > + > +/** > + Allocates pages from the memory map. > + > + @param Type The type of allocation to perform > + @param MemoryType The type of memory to turn the allocate= d pages > + into > + @param NumberOfPages The number of pages to allocate > + @param Memory A pointer to receive the base allocated= memory > + address > + > + @retval EFI_INVALID_PARAMETER Parameters violate checking rules defin= ed in spec. > + @retval EFI_NOT_FOUND Could not allocate pages match the requ= irement. > + @retval EFI_OUT_OF_RESOURCES No enough pages to allocate. > + @retval EFI_SUCCESS Pages successfully allocated. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmAllocatePages ( > + IN EFI_ALLOCATE_TYPE Type, > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN NumberOfPages, > + OUT EFI_PHYSICAL_ADDRESS *Memory > + ); > + > +/** > + Allocates pages from the memory map. > + > + @param Type The type of allocation to perform > + @param MemoryType The type of memory to turn the allocate= d pages > + into > + @param NumberOfPages The number of pages to allocate > + @param Memory A pointer to receive the base allocated= memory > + address > + > + @retval EFI_INVALID_PARAMETER Parameters violate checking rules defin= ed in spec. > + @retval EFI_NOT_FOUND Could not allocate pages match the requ= irement. > + @retval EFI_OUT_OF_RESOURCES No enough pages to allocate. > + @retval EFI_SUCCESS Pages successfully allocated. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInternalAllocatePages ( > + IN EFI_ALLOCATE_TYPE Type, > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN NumberOfPages, > + OUT EFI_PHYSICAL_ADDRESS *Memory > + ); > + > +/** > + Frees previous allocated pages. > + > + @param Memory Base address of memory being freed > + @param NumberOfPages The number of pages to free > + > + @retval EFI_NOT_FOUND Could not find the entry that covers th= e range > + @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or= NumberOfPages is zero. > + @return EFI_SUCCESS Pages successfully freed. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmFreePages ( > + IN EFI_PHYSICAL_ADDRESS Memory, > + IN UINTN NumberOfPages > + ); > + > +/** > + Frees previous allocated pages. > + > + @param Memory Base address of memory being freed > + @param NumberOfPages The number of pages to free > + > + @retval EFI_NOT_FOUND Could not find the entry that covers th= e range > + @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or= NumberOfPages is zero. > + @return EFI_SUCCESS Pages successfully freed. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInternalFreePages ( > + IN EFI_PHYSICAL_ADDRESS Memory, > + IN UINTN NumberOfPages > + ); > + > +/** > + Allocate pool of a particular type. > + > + @param PoolType Type of pool to allocate > + @param Size The amount of pool to allocate > + @param Buffer The address to return a pointer to the = allocated > + pool > + > + @retval EFI_INVALID_PARAMETER PoolType not valid > + @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocatio= n failed. > + @retval EFI_SUCCESS Pool successfully allocated. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmAllocatePool ( > + IN EFI_MEMORY_TYPE PoolType, > + IN UINTN Size, > + OUT VOID **Buffer > + ); > + > +/** > + Allocate pool of a particular type. > + > + @param PoolType Type of pool to allocate > + @param Size The amount of pool to allocate > + @param Buffer The address to return a pointer to the = allocated > + pool > + > + @retval EFI_INVALID_PARAMETER PoolType not valid > + @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocatio= n failed. > + @retval EFI_SUCCESS Pool successfully allocated. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInternalAllocatePool ( > + IN EFI_MEMORY_TYPE PoolType, > + IN UINTN Size, > + OUT VOID **Buffer > + ); > + > +/** > + Frees pool. > + > + @param Buffer The allocated pool entry to free > + > + @retval EFI_INVALID_PARAMETER Buffer is not a valid value. > + @retval EFI_SUCCESS Pool successfully freed. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmFreePool ( > + IN VOID *Buffer > + ); > + > +/** > + Frees pool. > + > + @param Buffer The allocated pool entry to free > + > + @retval EFI_INVALID_PARAMETER Buffer is not a valid value. > + @retval EFI_SUCCESS Pool successfully freed. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmInternalFreePool ( > + IN VOID *Buffer > + ); > + > +/** > + Installs a protocol interface into the boot services environment. > + > + @param UserHandle The handle to install the protocol hand= ler on, > + or NULL if a new handle is to be alloca= ted > + @param Protocol The protocol to add to the handle > + @param InterfaceType Indicates whether Interface is supplied= in > + native form. > + @param Interface The interface for the protocol being ad= ded > + @param Notify indicates whether notify the notificati= on list > + for this protocol > + > + @retval EFI_INVALID_PARAMETER Invalid parameter > + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate > + @retval EFI_SUCCESS Protocol interface successfully install= ed > + > +**/ > +EFI_STATUS > +MmInstallProtocolInterfaceNotify ( > + IN OUT EFI_HANDLE *UserHandle, > + IN EFI_GUID *Protocol, > + IN EFI_INTERFACE_TYPE InterfaceType, > + IN VOID *Interface, > + IN BOOLEAN Notify > + ); > + > +/** > + Uninstalls all instances of a protocol:interfacer from a handle. > + If the last protocol interface is remove from the handle, the > + handle is freed. > + > + @param UserHandle The handle to remove the protocol handl= er from > + @param Protocol The protocol, of protocol:interface, to= remove > + @param Interface The interface, of protocol:interface, t= o remove > + > + @retval EFI_INVALID_PARAMETER Protocol is NULL. > + @retval EFI_SUCCESS Protocol interface successfully uninsta= lled. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmUninstallProtocolInterface ( > + IN EFI_HANDLE UserHandle, > + IN EFI_GUID *Protocol, > + IN VOID *Interface > + ); > + > +/** > + Queries a handle to determine if it supports a specified protocol. > + > + @param UserHandle The handle being queried. > + @param Protocol The published unique identifier of the = protocol. > + @param Interface Supplies the address where a pointer to= the > + corresponding Protocol Interface is ret= urned. > + > + @return The requested protocol interface for the handle > + > +**/ > +EFI_STATUS > +EFIAPI > +MmHandleProtocol ( > + IN EFI_HANDLE UserHandle, > + IN EFI_GUID *Protocol, > + OUT VOID **Interface > + ); > + > +/** > + Add a new protocol notification record for the request protocol. > + > + @param Protocol The requested protocol to add the notif= y > + registration > + @param Function Points to the notification function > + @param Registration Returns the registration record > + > + @retval EFI_INVALID_PARAMETER Invalid parameter > + @retval EFI_SUCCESS Successfully returned the registration = record > + that has been added > + > +**/ > +EFI_STATUS > +EFIAPI > +MmRegisterProtocolNotify ( > + IN CONST EFI_GUID *Protocol, > + IN EFI_MM_NOTIFY_FN Function, > + OUT VOID **Registration > + ); > + > +/** > + Locates the requested handle(s) and returns them in Buffer. > + > + @param SearchType The type of search to perform to locate= the > + handles > + @param Protocol The protocol to search for > + @param SearchKey Dependant on SearchType > + @param BufferSize On input the size of Buffer. On output= the > + size of data returned. > + @param Buffer The buffer to return the results in > + > + @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size = is > + returned in BufferSize. > + @retval EFI_INVALID_PARAMETER Invalid parameter > + @retval EFI_SUCCESS Successfully found the requested handle= (s) and > + returns them in Buffer. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmLocateHandle ( > + IN EFI_LOCATE_SEARCH_TYPE SearchType, > + IN EFI_GUID *Protocol OPTIONAL, > + IN VOID *SearchKey OPTIONAL, > + IN OUT UINTN *BufferSize, > + OUT EFI_HANDLE *Buffer > + ); > + > +/** > + Return the first Protocol Interface that matches the Protocol GUID. If > + Registration is pasased in return a Protocol Instance that was just ad= d > + to the system. If Retistration is NULL return the first Protocol Inter= face > + you find. > + > + @param Protocol The protocol to search for > + @param Registration Optional Registration Key returned from > + RegisterProtocolNotify() > + @param Interface Return the Protocol interface (instance= ). > + > + @retval EFI_SUCCESS If a valid Interface is returned > + @retval EFI_INVALID_PARAMETER Invalid parameter > + @retval EFI_NOT_FOUND Protocol interface not found > + > +**/ > +EFI_STATUS > +EFIAPI > +MmLocateProtocol ( > + IN EFI_GUID *Protocol, > + IN VOID *Registration OPTIONAL, > + OUT VOID **Interface > + ); > + > +/** > + Manage MMI of a particular type. > + > + @param HandlerType Points to the handler type or NULL for root MMI= handlers. > + @param Context Points to an optional context buffer. > + @param CommBuffer Points to the optional communication buffer. > + @param CommBufferSize Points to the size of the optional communicatio= n buffer. > + > + @retval EFI_SUCCESS Interrupt source was proces= sed successfully but not quiesced. > + @retval EFI_INTERRUPT_PENDING One or more MMI sources cou= ld not be quiesced. > + @retval EFI_WARN_INTERRUPT_SOURCE_PENDING Interrupt source was not ha= ndled or quiesced. > + @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED Interrupt source was handle= d and quiesced. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmiManage ( > + IN CONST EFI_GUID *HandlerType, > + IN CONST VOID *Context OPTIONAL, > + IN OUT VOID *CommBuffer OPTIONAL, > + IN OUT UINTN *CommBufferSize OPTIONAL > + ); > + > +/** > + Registers a handler to execute within MM. > + > + @param Handler Handler service funtion pointer. > + @param HandlerType Points to the handler type or NULL for root MMI= handlers. > + @param DispatchHandle On return, contains a unique handle which can b= e used to later unregister the handler function. > + > + @retval EFI_SUCCESS Handler register success. > + @retval EFI_INVALID_PARAMETER Handler or DispatchHandle is NULL. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmiHandlerRegister ( > + IN EFI_MM_HANDLER_ENTRY_POINT Handler, > + IN CONST EFI_GUID *HandlerType OPTIONAL, > + OUT EFI_HANDLE *DispatchHandle > + ); > + > +/** > + Unregister a handler in MM. > + > + @param DispatchHandle The handle that was specified when the handler= was registered. > + > + @retval EFI_SUCCESS Handler function was successfully unregi= stered. > + @retval EFI_INVALID_PARAMETER DispatchHandle does not refer to a valid= handle. > + > +**/ > +EFI_STATUS > +EFIAPI > +MmiHandlerUnRegister ( > + IN EFI_HANDLE DispatchHandle > + ); > + > +/** > + This function is the main entry point for an MM handler dispatch > + or communicate-based callback. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmDriverDispatchHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ); > + > +/** > + This function is the main entry point for an MM handler dispatch > + or communicate-based callback. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmFvDispatchHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ); > + > +/** > + This function is the main entry point for an MM handler dispatch > + or communicate-based callback. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmLegacyBootHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ); > + > +/** > + This function is the main entry point for an MM handler dispatch > + or communicate-based callback. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmExitBootServiceHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ); > + > +/** > + This function is the main entry point for an MM handler dispatch > + or communicate-based callback. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmReadyToBootHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ); > + > +/** > + This function is the main entry point for an MM handler dispatch > + or communicate-based callback. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmReadyToLockHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ); > + > +/** > + This function is the main entry point for an MM handler dispatch > + or communicate-based callback. > + > + @param DispatchHandle The unique handle assigned to this handler by = MmiHandlerRegister(). > + @param Context Points to an optional handler context which wa= s specified when the handler was registered. > + @param CommBuffer A pointer to a collection of data in memory th= at will > + be conveyed from a non-MM environment into an = MM environment. > + @param CommBufferSize The size of the CommBuffer. > + > + @return Status Code > + > +**/ > +EFI_STATUS > +EFIAPI > +MmEndOfDxeHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *Context, OPTIONAL > + IN OUT VOID *CommBuffer, OPTIONAL > + IN OUT UINTN *CommBufferSize OPTIONAL > + ); > + > +/** > + Place holder function until all the MM System Table Service are availa= ble. > + > + @param Arg1 Undefined > + @param Arg2 Undefined > + @param Arg3 Undefined > + @param Arg4 Undefined > + @param Arg5 Undefined > + > + @return EFI_NOT_AVAILABLE_YET > + > +**/ > +EFI_STATUS > +EFIAPI > +MmEfiNotAvailableYetArg5 ( > + UINTN Arg1, > + UINTN Arg2, > + UINTN Arg3, > + UINTN Arg4, > + UINTN Arg5 > + ); > + > +// > +//Functions used during debug buils > +// > + > +/** > + Traverse the discovered list for any drivers that were discovered but = not loaded > + because the dependency expressions evaluated to false. > + > +**/ > +VOID > +MmDisplayDiscoveredNotDispatched ( > + VOID > + ); > + > +/** > + Add free MMRAM region for use by memory service. > + > + @param MemBase Base address of memory region. > + @param MemLength Length of the memory region. > + @param Type Memory type. > + @param Attributes Memory region state. > + > +**/ > +VOID > +MmAddMemoryRegion ( > + IN EFI_PHYSICAL_ADDRESS MemBase, > + IN UINT64 MemLength, > + IN EFI_MEMORY_TYPE Type, > + IN UINT64 Attributes > + ); > + > +/** > + Finds the protocol entry for the requested protocol. > + > + @param Protocol The ID of the protocol > + @param Create Create a new entry if not found > + > + @return Protocol entry > + > +**/ > +PROTOCOL_ENTRY * > +MmFindProtocolEntry ( > + IN EFI_GUID *Protocol, > + IN BOOLEAN Create > + ); > + > +/** > + Signal event for every protocol in protocol entry. > + > + @param Prot Protocol interface > + > +**/ > +VOID > +MmNotifyProtocol ( > + IN PROTOCOL_INTERFACE *Prot > + ); > + > +/** > + Finds the protocol instance for the requested handle and protocol. > + Note: This function doesn't do parameters checking, it's caller's resp= onsibility > + to pass in valid parameters. > + > + @param Handle The handle to search the protocol on > + @param Protocol GUID of the protocol > + @param Interface The interface for the protocol being se= arched > + > + @return Protocol instance (NULL: Not found) > + > +**/ > +PROTOCOL_INTERFACE * > +MmFindProtocolInterface ( > + IN IHANDLE *Handle, > + IN EFI_GUID *Protocol, > + IN VOID *Interface > + ); > + > +/** > + Removes Protocol from the protocol list (but not the handle list). > + > + @param Handle The handle to remove protocol on. > + @param Protocol GUID of the protocol to be moved > + @param Interface The interface of the protocol > + > + @return Protocol Entry > + > +**/ > +PROTOCOL_INTERFACE * > +MmRemoveInterfaceFromProtocol ( > + IN IHANDLE *Handle, > + IN EFI_GUID *Protocol, > + IN VOID *Interface > + ); > + > +/** > + This is the POSTFIX version of the dependency evaluator. This code do= es > + not need to handle Before or After, as it is not valid to call this > + routine in this case. POSTFIX means all the math is done on top of the= stack. > + > + @param DriverEntry DriverEntry element to update. > + > + @retval TRUE If driver is ready to run. > + @retval FALSE If driver is not ready to run or some fa= tal error > + was found. > + > +**/ > +BOOLEAN > +MmIsSchedulable ( > + IN EFI_MM_DRIVER_ENTRY *DriverEntry > + ); > + > +/** > + Dump MMRAM information. > + > +**/ > +VOID > +DumpMmramInfo ( > + VOID > + ); > + > +extern UINTN mMmramRangeCount; > +extern EFI_MMRAM_DESCRIPTOR *mMmramRanges; > +extern EFI_SYSTEM_TABLE *mEfiSystemTable; > + > +#endif > diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.inf b/StandaloneMmPkg/= Core/StandaloneMmCore.inf > new file mode 100644 > index 0000000000..c5eaa14ba3 > --- /dev/null > +++ b/StandaloneMmPkg/Core/StandaloneMmCore.inf > @@ -0,0 +1,80 @@ > +## @file > +# This module provide an SMM CIS compliant implementation of SMM Core. > +# > +# Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
> +# Copyright (c) 2016 - 2017, ARM Limited. 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 > +# http://opensource.org/licenses/bsd-license.php > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > +# > +## > + > +[Defines] > + INF_VERSION =3D 0x0001001A > + BASE_NAME =3D StandaloneMmCore > + FILE_GUID =3D 6E14B6FD-3600-4DD6-A17A-206B3B6DCE1= 6 > + MODULE_TYPE =3D MM_CORE_STANDALONE > + VERSION_STRING =3D 1.0 > + PI_SPECIFICATION_VERSION =3D 0x00010032 > + ENTRY_POINT =3D StandaloneMmMain > + > +# VALID_ARCHITECTURES =3D IA32 X64 AARCH64 > + > +[Sources] > + StandaloneMmCore.c > + StandaloneMmCore.h > + StandaloneMmCorePrivateData.h > + Page.c > + Pool.c > + Handle.c > + Locate.c > + Notify.c > + Dependency.c > + Dispatcher.c > + Mmi.c > + InstallConfigurationTable.c > + FwVol.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + StandaloneMmPkg/StandaloneMmPkg.dec > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + CacheMaintenanceLib > + DebugLib > + FvLib > + HobLib > + MemoryAllocationLib > + MemLib > + PeCoffLib > + ReportStatusCodeLib > + StandaloneMmCoreEntryPoint > + > +[Protocols] > + gEfiDxeMmReadyToLockProtocolGuid ## UNDEFINED # SmiHandler= Register > + gEfiMmReadyToLockProtocolGuid ## PRODUCES > + gEfiMmEndOfDxeProtocolGuid ## PRODUCES > + gEfiLoadedImageProtocolGuid ## PRODUCES > + gEfiMmConfigurationProtocolGuid ## CONSUMES > + > +[Guids] > + gAprioriGuid ## SOMETIMES_CONSUMES = ## File > + gEfiEventDxeDispatchGuid ## PRODUCES = ## GUID # SmiHandlerRegister > + gEfiEndOfDxeEventGroupGuid ## PRODUCES = ## GUID # SmiHandlerRegister > + ## SOMETIMES_CONSUMES ## GUID # Locate protocol > + ## SOMETIMES_PRODUCES ## GUID # SmiHandlerRegister > + gEdkiiMemoryProfileGuid > + gZeroGuid ## SOMETIMES_CONSUMES = ## GUID > + gEfiHobListGuid > + gMmCoreDataHobGuid > + gMmFvDispatchGuid > + gEfiEventLegacyBootGuid > + gEfiEventExitBootServicesGuid > + gEfiEventReadyToBootGuid > diff --git a/StandaloneMmPkg/Core/StandaloneMmCorePrivateData.h b/Standal= oneMmPkg/Core/StandaloneMmCorePrivateData.h > new file mode 100644 > index 0000000000..faedf3ff2d > --- /dev/null > +++ b/StandaloneMmPkg/Core/StandaloneMmCorePrivateData.h > @@ -0,0 +1,66 @@ > +/** @file > + The internal header file that declared a data structure that is shared > + between the MM IPL and the MM Core. > + > + Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
> + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. > + > +**/ > + > +#ifndef _STANDALONE_MM_CORE_PRIVATE_DATA_H_ > +#define _STANDALONE_MM_CORE_PRIVATE_DATA_H_ > + > +#include > + > +// > +// Page management > +// > + > +typedef struct { > + LIST_ENTRY Link; > + UINTN NumberOfPages; > +} FREE_PAGE_LIST; > + > +extern LIST_ENTRY mMmMemoryMap; > + > +// > +// Pool management > +// > + > +// > +// MIN_POOL_SHIFT must not be less than 5 > +// > +#define MIN_POOL_SHIFT 6 > +#define MIN_POOL_SIZE (1 << MIN_POOL_SHIFT) > + > +// > +// MAX_POOL_SHIFT must not be less than EFI_PAGE_SHIFT - 1 > +// > +#define MAX_POOL_SHIFT (EFI_PAGE_SHIFT - 1) > +#define MAX_POOL_SIZE (1 << MAX_POOL_SHIFT) > + > +// > +// MAX_POOL_INDEX are calculated by maximum and minimum pool sizes > +// > +#define MAX_POOL_INDEX (MAX_POOL_SHIFT - MIN_POOL_SHIFT + 1) > + > +typedef struct { > + UINTN Size; > + BOOLEAN Available; > +} POOL_HEADER; > + > +typedef struct { > + POOL_HEADER Header; > + LIST_ENTRY Link; > +} FREE_POOL_HEADER; > + > +extern LIST_ENTRY mMmPoolLists[MAX_POOL_INDEX]; > + > +#endif > diff --git a/StandaloneMmPkg/Include/Guid/MmFvDispatch.h b/StandaloneMmPk= g/Include/Guid/MmFvDispatch.h > new file mode 100644 > index 0000000000..fb194d3474 > --- /dev/null > +++ b/StandaloneMmPkg/Include/Guid/MmFvDispatch.h > @@ -0,0 +1,38 @@ > +/** @file > + GUIDs for MM Event. > + > +Copyright (c) 2015, Intel Corporation. All rights reserved.
> +Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
> + > +This program and the accompanying materials are licensed and made availa= ble under > +the terms and conditions of the BSD License that accompanies this distri= bution. > +The full text of the license may be found at > +http://opensource.org/licenses/bsd-license.php. > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. > + > +**/ > + > +#ifndef __MM_FV_DISPATCH_H__ > +#define __MM_FV_DISPATCH_H__ > + > +#define MM_FV_DISPATCH_GUID \ > + { 0xb65694cc, 0x9e3, 0x4c3b, { 0xb5, 0xcd, 0x5, 0xf4, 0x4d, 0x3c, 0xdb= , 0xff }} > + > +extern EFI_GUID gMmFvDispatchGuid; > + > +#pragma pack(1) > +typedef struct { > + EFI_PHYSICAL_ADDRESS Address; > + UINT64 Size; > +} EFI_MM_COMMUNICATE_FV_DISPATCH_DATA; > + > +typedef struct { > + EFI_GUID HeaderGuid; > + UINTN MessageLength; > + EFI_MM_COMMUNICATE_FV_DISPATCH_DATA Data; > +} EFI_MM_COMMUNICATE_FV_DISPATCH; > +#pragma pack() > + > +#endif > diff --git a/StandaloneMmPkg/Include/StandaloneMm.h b/StandaloneMmPkg/Inc= lude/StandaloneMm.h > new file mode 100644 > index 0000000000..0e420315bb > --- /dev/null > +++ b/StandaloneMmPkg/Include/StandaloneMm.h > @@ -0,0 +1,36 @@ > +/** @file > + Standalone MM. > + > +Copyright (c) 2015, Intel Corporation. All rights reserved.
> +Copyright (c) 2016 - 2017, ARM Limited. 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 > +http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. > + > +**/ > + > +#ifndef _STANDALONE_MM_H_ > +#define _STANDALONE_MM_H_ > + > +#include > + > +typedef > +EFI_STATUS > +(EFIAPI *MM_IMAGE_ENTRY_POINT) ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_MM_SYSTEM_TABLE *MmSystemTable > + ); > + > +typedef > +EFI_STATUS > +(EFIAPI *STANDALONE_MM_FOUNDATION_ENTRY_POINT) ( > + IN VOID *HobStart > + ); > + > +#endif > -- > 2.16.2 > IMPORTANT NOTICE: The contents of this email and any attachments are confid= ential and may also be privileged. If you are not the intended recipient, p= lease notify the sender immediately and do not disclose the contents to any= other person, use it for any purpose, or store or copy the information in = any medium. Thank you.