UEFI SMM Services ================= The Trusted Services project provides support for UEFI System Management Mode (SMM) services via the SMM Gateway secure partition. The SMM Gateway adopts the API Gateway design pattern, popular in microservices architecture. The pattern decouples clients from backend service providers using an API gateway that presents a domain specific interface to clients while delegating operations to a set of backend microservices. An API gateway will typically use multiple backend services and may perform protocol translation while presenting a single service entry point for clients. The SMM Gateway works in a similar manner - clients access SMM services using standard SMM protocol messages, carried by an RPC mechanism. Service requests are forwarded by the SMM Gateway to backend service providers for operations such as secure persistent storage and signature verification. SMM Gateway is intended to be used on non-EDK2 platforms as an alternative to the EDK2 StandaloneMM (StMM) component. The current SMM Gateway version only supports the SMM Variable service. Additional SMM service providers may be added to SMM Gateway if required. By deliberately limiting functionality and exploiting backend services, the SMM Gateway SP can be significantly lighter-weight than StMM. This option is intended to be used on more resource constrained devices that tend to use u-boot. There is of course the possibility that other SMM services will need to be supported in the future. In such cases, a judgement should be made as to whether StMM should be used rather than extending the SP. .. uml:: uml/SmmGatewayOverview.puml SMM Variable Service -------------------- Overview '''''''' UEFI Variable support is provided by the *smm_variable* service provider component. This service provider is structured in the same way as other service providers within the TS project. Features of this component are: * Source file location: ``components/service/smm_variable`` * Public interface definitions: ``protocols/service/smm_variable`` * Can be used with any RPC layer - not tied to MM Communicate RPC. * Volatile and non-volatile storage is accessed via instances of the common *storage_backend* interface. The *smm-gateway/opteesp* deployment integrates the *smm_variable* service provider with the following: * An MM Communicate based RPC endpoint. * A *mock_store* instance for volatile variables. * A *secure_storage_client* for non-volatile variables. During SP initialization, the *smm-gateway* uses pre-configured information to discover a backend secure storage SP for NV storage. The following diagram illustrates how the *smm_variable* service provider is integrated into the *smm-gateway*. .. image:: image/smm-gateway-layers.svg Because the *smm_variable* service provider is independent of any particular environment, alternative deployments are possible e.g. * *smm_variable* service provider running within a GP TA with storage off-loaded to the GP TEE Internal API. * *smm_variable* service provider running within a secure enclave with its own internal flash storage. Supported Functions ''''''''''''''''''' The *smm_variable* service provider supports the following functions: .. list-table:: :header-rows: 1 * - SMM Variable Function - Purpose - Backend service interaction * - SMM_VARIABLE_FUNCTION_GET_VARIABLE - Get variable data identified by GUID/name. - Query index and get object from appropriate storage backend. * - SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME - Called multiple times to enumerate stored variables. - Find variable in index and return next. * - SMM_VARIABLE_FUNCTION_SET_VARIABLE - Adds a new variable or updates an existing one. - | Sets object in storage backend and if necessary, updates index | and syncs to storage. * - SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO - Returns information about the variable store. - Iterates over stored variables to determine space used. * - SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE - Called by OS when boot phase is complete. - | Updates view of runtime state held by smm_variable service provider. | State variable used when implementing state dependent access control. * - SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET - | Set constraints that are checked on the SetVariable operation. | Allows a platform to set check policy. - | Variable index holds variable check constraints object for each variable. | This is updated by this function. * - SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET - Get the variable check constraints. - Reads the variable check constraints object. * - SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE - | Returns the maximum variable data size, excluding any | auth header. - | Considers size constraints imposed by backend stores and RPC response | payload constraints. Supported Variable Attributes ''''''''''''''''''''''''''''' The following variable attributes are supported: .. list-table:: :widths: 3 1 3 :header-rows: 1 * - SMM Variable Attribute - Support - Comment * - EFI_VARIABLE_NON_VOLATILE - yes - Determines which storage backend is used. * - EFI_VARIABLE_BOOTSERVICE_ACCESS - yes - Boot service access controlled by smm_variable service provider. * - EFI_VARIABLE_RUNTIME_ACCESS - yes - Runtime access controlled by smm_variable service provider. * - EFI_VARIABLE_HARDWARE_ERROR_RECORD - no - * - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS - no - * - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS - not yet - Will be needed for secure boot support * - EFI_VARIABLE_APPEND_WRITE - yes - Implemented by overwriting entire variable data. SMM Variable Tests '''''''''''''''''' The following test components exist for the SMM Variable service: .. list-table:: :header-rows: 1 * - Test Component - Description - Included in deployments * - ``component/service/smm_variable/backend/test`` - | Component tests for the variable_index and variable_store backend | components. Can be run in a native PC environment. - ``deployments/component-test/*`` * - ``component/service/smm_variable/test/service`` - | End-to-end service level tests that call service operations from | the perspective of a client.  Can be run in a native PC environment | or on the Arm target platform. - | ``deployments/ts-service-test/linux-pc`` | ``deployments/uefi-test/arm-linux`` SMM Gateway Build Configuration ------------------------------- The smm-gateway SP image may be built using the default configuration parameters defined within relevant source files. In practice, it is likely that at least some configuration values will need to be overridden. The following table lists build-time configuration parameters that may be overridden by global C pre-processor defines. .. list-table:: :widths: 2 2 2 1 :header-rows: 1 * - Config define - Usage - File - Default value * - SMM_GATEWAY_MAX_UEFI_VARIABLES - Maximum number of variables - ``deployments/smm-gateway/smm_gateway.c`` - 40 * - SMM_GATEWAY_NV_STORE_SN - The service ID for the backend NV variable store - ``deployments/smm-gateway/smm_gateway.c`` - Protected Storage SP MM Communicate RPC Layer ------------------------ To maintain compatibility with existing SMM service clients, an MM Communicate based RPC layer has been developed that uses the same 'carveout' buffer scheme as StMM. When SMM Gateway is used instead of StMM, existing SMM variable clients should interoperate seamlessly. The MM Communicate RPC components implement the standard TS RPC interfaces and can be used as a general purpose RPC for calls from normal world to secure world. The following MM Communicate RPC components have been added: * ``components/rpc/mm_communicate/endpoint/sp`` - an RPC endpoint that handles FFA direct calls with MM Communicate and SMM message carried in a shared 'carveout' buffer. Call requests are demultiplexed to the appropriate service interface based on the service GUID carried in the MM Communicate header.  Suitable for use in SP deployments. * ``components/rpc/mm_communicate/caller/linux`` - an RPC caller that calls service operations associated with the destination service interface from Linux user-space. Uses the MM Communicate protocol, sent over FFA using the Debug FFA kernel driver.  Service level tests that run against the SMM Gateway use this RPC caller for invoking SMM service operations. The following register mapping is assumed for FFA based direct calls to an SP that handles the MM Communicate RPC protocol: .. list-table:: :widths: 1 2 2 2 :header-rows: 1 * - Registers - FF-A layer - MM_COMMUNICATE Request - MM_COMMUNICATE Response * - W0 - Function ID - | FFA_MSG_SEND_DIRECT_REQ | (0x8400006F/0xC400006F) - | FFA_MSG_SEND_DIRECT_RESP | (0x84000070/0xC4000070) * - W1 - Source/Destination ID - Source/Destination ID - Source/Destination ID * - W2/X2 - Reserved - 0x00000000 - 0x00000000 * - W3/X3 - Parameter[0] - Address of the MM communication buffer - | ARM_SVC_ID_SP_EVENT_COMPLETE | (0x84000061/0xC4000061) * - W4/X4 - Parameter[1] - Size of the MM communication buffer - SUCCESS/[error code] * - W5/X5 - Parameter[2] - 0x00000000 - 0x00000000 * - W6/X6 - Parameter[3] - 0x00000000 - 0x00000000 * - W7/X7 - Parameter[4] - 0x00000000 - 0x00000000 -------------- *Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.* SPDX-License-Identifier: BSD-3-Clause