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
|
/** @file
VarCheckHiiLib Dependency library.
It sends HII variable checking data to SMM via the MM Communication protocol.
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Protocol/MmCommunication.h>
#include <Guid/PiSmmCommunicationRegionTable.h>
#include "InternalVarCheckStructure.h"
#include "VarCheckHiiGen.h"
#include "VarCheckHii.h"
#include <Library/UefiLib.h>
#include <Guid/EventGroup.h>
extern VAR_CHECK_HII_VARIABLE_HEADER *mVarCheckHiiBin;
extern UINTN mVarCheckHiiBinSize;
EFI_GUID gVarCheckReceivedHiiBinHandlerGuid = VAR_CHECK_RECEIVED_HII_BIN_HANDLER_GUID;
/**
Sends HII variable checking data to SMM at the end of DXE phase.
This function is triggered by the End of DXE. It locates a memory
region for MM communication, prepares the communication buffer with HII variable
checking data, and communicates with SMM using the MM Communication protocol.
@param[in] Event Event whose notification function is being invoked.
@param[in] Context The pointer to the notification function's context, which
is implementation-dependent.
**/
VOID
EFIAPI
VarCheckHiiLibSmmEndOfDxeNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
EFI_MM_COMMUNICATION_PROTOCOL *MmCommunication;
EFI_MM_COMMUNICATE_HEADER *CommHeader;
EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;
EFI_MEMORY_DESCRIPTOR *MmCommMemRegion;
UINTN CommBufferSize;
UINTN Index;
VAR_CHECK_HII_VARIABLE_HEADER *VarCheckHiiVariable;
DEBUG ((DEBUG_INFO, "%a starts.\n", __func__));
VarCheckHiiGen ();
if ((mVarCheckHiiBinSize == 0) || (mVarCheckHiiBin == NULL)) {
DEBUG ((DEBUG_INFO, "%a: mVarCheckHiiBinSize = 0x%x, mVarCheckHiiBin = 0x%x \n", __func__, mVarCheckHiiBinSize, mVarCheckHiiBin));
return;
}
//
// Retrieve SMM Communication Region Table
//
Status = EfiGetSystemConfigurationTable (
&gEdkiiPiSmmCommunicationRegionTableGuid,
(VOID **)&PiSmmCommunicationRegionTable
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Failed to get PiSmmCommunicationRegionTable - %r\n", __func__, Status));
return;
}
ASSERT (PiSmmCommunicationRegionTable != NULL);
//
// Find a memory region for MM communication
//
CommBufferSize = 0;
MmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *)(PiSmmCommunicationRegionTable + 1);
for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {
if (MmCommMemRegion->Type == EfiConventionalMemory) {
CommBufferSize = EFI_PAGES_TO_SIZE ((UINTN)MmCommMemRegion->NumberOfPages);
if (CommBufferSize >= (sizeof (EFI_MM_COMMUNICATE_HEADER) + mVarCheckHiiBinSize)) {
break;
}
}
MmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MmCommMemRegion + PiSmmCommunicationRegionTable->DescriptorSize);
}
if (Index >= PiSmmCommunicationRegionTable->NumberOfEntries) {
DEBUG ((DEBUG_ERROR, "%a: Failed to find a suitable memory region for MM communication!\n", __func__));
return;
}
//
// Prepare the communication buffer
//
CommHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)MmCommMemRegion->PhysicalStart;
CommBufferSize = OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) + mVarCheckHiiBinSize;
ZeroMem (CommHeader, CommBufferSize);
CopyGuid (&CommHeader->HeaderGuid, &gVarCheckReceivedHiiBinHandlerGuid);
CommHeader->MessageLength = mVarCheckHiiBinSize;
VarCheckHiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *)(CommHeader->Data);
CopyMem (VarCheckHiiVariable, mVarCheckHiiBin, mVarCheckHiiBinSize);
//
// Locate the MM Communication protocol and signal SMI
//
Status = gBS->LocateProtocol (&gEfiMmCommunicationProtocolGuid, NULL, (VOID **)&MmCommunication);
if (!EFI_ERROR (Status)) {
Status = MmCommunication->Communicate (MmCommunication, CommHeader, &CommBufferSize);
DEBUG ((DEBUG_INFO, "%a: Communicate to smm environment = %r\n", __func__, Status));
} else {
DEBUG ((DEBUG_ERROR, "%a: Failed to locate MmCommunication protocol - %r\n", __func__, Status));
return;
}
DEBUG ((DEBUG_INFO, "%a ends.\n", __func__));
return;
}
/**
Constructor function of the VarCheckHiiLibMmDependency.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the Management mode System Table.
@retval EFI_SUCCESS The protocol was successfully installed into the DXE database.
**/
EFI_STATUS
EFIAPI
VarCheckHiiLibMmDependencyConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_EVENT Event;
DEBUG ((DEBUG_INFO, "%a starts.\n", __func__));
Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, VarCheckHiiLibSmmEndOfDxeNotify, NULL, &gEfiEndOfDxeEventGroupGuid, &Event);
ASSERT_EFI_ERROR (Status);
DEBUG ((DEBUG_INFO, "%a ends.\n", __func__));
return Status;
}
|