summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.c
blob: c1ee55bb2e158a57d6b7f8cf9529fbee3909a4e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/** @file

  Implementation functions and structures for var check services.
  This file provides functions and structures to register and handle variable checks
  in the Standalone MM environment, specifically for HII variables.

Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/MmServicesTableLib.h>
#include <Protocol/MmCommunication.h>
#include <Library/VarCheckLib.h>

#include "VarCheckHii.h"
#include "VarCheckHiiLibCommon.h"

//
// In the standalone setup, mVarCheckHiiBin is used for sending, while mVarCheckHiiBinMmReceived is used for receiving,
// while in the traditional setup, mVarCheckHiiBin is used for both sending and receiving.
//
VAR_CHECK_HII_VARIABLE_HEADER  *mMmReceivedVarCheckHiiBin         = NULL;
UINTN                          mMmReceivedVarCheckHiiBinSize      = 0;
EFI_GUID                       gVarCheckReceivedHiiBinHandlerGuid = VAR_CHECK_RECEIVED_HII_BIN_HANDLER_GUID;

/**
  Registers a handler for HII variable checks in MM environment.
  This function is intended to be called to register a handler for checking variables
  in the Standalone MM environment. It allocates memory for the variable
  check data and copies the data from the communication buffer.

  @param[in] DispatchHandle    The handle of the dispatch function.
  @param[in] Context           Optional context for the handler, not used in this implementation.
  @param CommBuffer        The buffer of data being passed in.
  @param CommBufferSize    The size of the data being passed in.
  @retval EFI_SUCCESS           Registration and memory allocation were successful.
  @retval EFI_INVALID_PARAMETER The CommBuffer or CommBufferSize is NULL.
  @retval EFI_ACCESS_DENIED     The buffer size is invalid or the buffer is in an invalid location.
  @retval EFI_OUT_OF_RESOURCES  Memory allocation for the variable check data failed.

**/
EFI_STATUS
EFIAPI
VarCheckHiiLibReceiveHiiBinHandler (
  IN EFI_HANDLE  DispatchHandle,
  IN CONST VOID  *Context        OPTIONAL,
  IN OUT VOID    *CommBuffer     OPTIONAL,
  IN OUT UINTN   *CommBufferSize OPTIONAL
  )
{
  EFI_STATUS  Status;

  //
  // If input is invalid, stop processing this SMI
  //
  if ((CommBuffer == NULL) || (CommBufferSize == NULL)) {
    return EFI_SUCCESS;
  }

  mMmReceivedVarCheckHiiBinSize = *CommBufferSize;

  if (mMmReceivedVarCheckHiiBinSize < sizeof (VAR_CHECK_HII_VARIABLE_HEADER)) {
    DEBUG ((DEBUG_ERROR, "%a: MM Communication buffer size is invalid for this handler!\n", __func__));
    return EFI_ACCESS_DENIED;
  }

  mMmReceivedVarCheckHiiBin = AllocateZeroPool (mMmReceivedVarCheckHiiBinSize);
  if (mMmReceivedVarCheckHiiBin == NULL) {
    DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory for mVarCheckHiiBinMm\n", __func__));
    return EFI_OUT_OF_RESOURCES;
  }

  CopyMem (mMmReceivedVarCheckHiiBin, CommBuffer, mMmReceivedVarCheckHiiBinSize);
  if (DispatchHandle != NULL) {
    Status = gMmst->MmiHandlerUnRegister (DispatchHandle);
  }

  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "%a: Failed to unregister handler - %r!\n", __func__, Status));
  } else {
    DEBUG ((DEBUG_INFO, "%a: Handler unregistered successfully.\n", __func__));
  }

  return EFI_SUCCESS;
}

/**

  Sets the variable check handler for HII.
  This function registers a handler that will be invoked for variable checks
  in the HII environment. It allows for custom validation logic to be implemented
  for setting HII variables.
  @param[in] VariableName               Name of Variable to set.
  @param[in] VendorGuid                 Variable vendor GUID.
  @param[in] Attributes                 Attribute value of the variable.
  @param[in] DataSize                   Size of Data to set.
  @param[in] Data                       Data pointer.

**/
EFI_STATUS
EFIAPI
SetVariableCheckHandlerHii (
  IN CHAR16    *VariableName,
  IN EFI_GUID  *VendorGuid,
  IN UINT32    Attributes,
  IN UINTN     DataSize,
  IN VOID      *Data
  )
{
  return CheckHiiVariableCommon (mMmReceivedVarCheckHiiBin, mMmReceivedVarCheckHiiBinSize, VariableName, VendorGuid, Attributes, DataSize, Data);
}

/**
  Constructor function for variable check library in Standalone MM.
  This function registers a handler for variable checks and sets up the environment
  for variable checking in the Standalone MM environment.
  @param[in] ImageHandle       The firmware allocated handle for the EFI image.
  @param[in] SystemTable       A pointer to the EFI system table.
  @retval EFI_SUCCESS          The constructor executed successfully.
  @retval Others               An error occurred during execution.

**/
EFI_STATUS
EFIAPI
VarCheckHiiLibConstructorStandaloneMm (
  IN EFI_HANDLE           ImageHandle,
  IN EFI_MM_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;
  EFI_HANDLE  DispatchHandle;

  DEBUG ((DEBUG_INFO, "%a: starts.\n", __func__));
  //
  // Register a handler to recieve the HII variable checking data.
  //
  Status = gMmst->MmiHandlerRegister (VarCheckHiiLibReceiveHiiBinHandler, &gVarCheckReceivedHiiBinHandlerGuid, &DispatchHandle);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "%a: Failed to register handler - %r!\n", __func__, Status));

    return Status;
  }

  VarCheckLibRegisterAddressPointer ((VOID **)&mMmReceivedVarCheckHiiBin);
  VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerHii);
  DEBUG ((DEBUG_INFO, "%a: ends.\n", __func__));
  return EFI_SUCCESS;
}