]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c
UefiCpuPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / UefiCpuPkg / PiSmmCommunication / PiSmmCommunicationSmm.c
1 /** @file
2 PiSmmCommunication SMM Driver.
3
4 Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <PiSmm.h>
10 #include <Library/UefiDriverEntryPoint.h>
11 #include <Library/UefiBootServicesTableLib.h>
12 #include <Library/UefiRuntimeServicesTableLib.h>
13 #include <Library/SmmServicesTableLib.h>
14 #include <Library/BaseLib.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/SmmMemLib.h>
18 #include <Protocol/SmmSwDispatch2.h>
19 #include <Protocol/SmmCommunication.h>
20 #include <Ppi/SmmCommunication.h>
21
22 #include "PiSmmCommunicationPrivate.h"
23
24 EFI_SMM_COMMUNICATION_CONTEXT mSmmCommunicationContext = {
25 SMM_COMMUNICATION_SIGNATURE
26 };
27
28 /**
29 Set SMM communication context.
30 **/
31 VOID
32 SetCommunicationContext (
33 VOID
34 )
35 {
36 EFI_STATUS Status;
37
38 Status = gSmst->SmmInstallConfigurationTable (
39 gSmst,
40 &gEfiPeiSmmCommunicationPpiGuid,
41 &mSmmCommunicationContext,
42 sizeof(mSmmCommunicationContext)
43 );
44 ASSERT_EFI_ERROR (Status);
45 }
46
47 /**
48 Dispatch function for a Software SMI handler.
49
50 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
51 @param Context Points to an optional handler context which was specified when the
52 handler was registered.
53 @param CommBuffer A pointer to a collection of data in memory that will
54 be conveyed from a non-SMM environment into an SMM environment.
55 @param CommBufferSize The size of the CommBuffer.
56
57 @retval EFI_SUCCESS Command is handled successfully.
58
59 **/
60 EFI_STATUS
61 EFIAPI
62 PiSmmCommunicationHandler (
63 IN EFI_HANDLE DispatchHandle,
64 IN CONST VOID *Context OPTIONAL,
65 IN OUT VOID *CommBuffer OPTIONAL,
66 IN OUT UINTN *CommBufferSize OPTIONAL
67 )
68 {
69 UINTN CommSize;
70 EFI_STATUS Status;
71 EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;
72 EFI_PHYSICAL_ADDRESS *BufferPtrAddress;
73
74 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Enter\n"));
75
76 BufferPtrAddress = (EFI_PHYSICAL_ADDRESS *)(UINTN)mSmmCommunicationContext.BufferPtrAddress;
77 CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)(UINTN)*BufferPtrAddress;
78 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateHeader - %x\n", CommunicateHeader));
79 if (CommunicateHeader == NULL) {
80 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler is NULL, needn't to call dispatch function\n"));
81 Status = EFI_SUCCESS;
82 } else {
83 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicateHeader, OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data))) {
84 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateHeader invalid - 0x%x\n", CommunicateHeader));
85 Status = EFI_SUCCESS;
86 goto Done;
87 }
88
89 CommSize = (UINTN)CommunicateHeader->MessageLength;
90 if (!SmmIsBufferOutsideSmmValid ((UINTN)&CommunicateHeader->Data[0], CommSize)) {
91 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateData invalid - 0x%x\n", &CommunicateHeader->Data[0]));
92 Status = EFI_SUCCESS;
93 goto Done;
94 }
95
96 //
97 // Call dispatch function
98 //
99 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Data - %x\n", &CommunicateHeader->Data[0]));
100 Status = gSmst->SmiManage (
101 &CommunicateHeader->HeaderGuid,
102 NULL,
103 &CommunicateHeader->Data[0],
104 &CommSize
105 );
106 }
107
108 Done:
109 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler %r\n", Status));
110 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Exit\n"));
111
112 return (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_INTERRUPT_PENDING;
113 }
114
115 /**
116 Allocate EfiACPIMemoryNVS below 4G memory address.
117
118 This function allocates EfiACPIMemoryNVS below 4G memory address.
119
120 @param Size Size of memory to allocate.
121
122 @return Allocated address for output.
123
124 **/
125 VOID*
126 AllocateAcpiNvsMemoryBelow4G (
127 IN UINTN Size
128 )
129 {
130 UINTN Pages;
131 EFI_PHYSICAL_ADDRESS Address;
132 EFI_STATUS Status;
133 VOID* Buffer;
134
135 Pages = EFI_SIZE_TO_PAGES (Size);
136 Address = 0xffffffff;
137
138 Status = gBS->AllocatePages (
139 AllocateMaxAddress,
140 EfiACPIMemoryNVS,
141 Pages,
142 &Address
143 );
144 ASSERT_EFI_ERROR (Status);
145
146 Buffer = (VOID *) (UINTN) Address;
147 ZeroMem (Buffer, Size);
148
149 return Buffer;
150 }
151
152 /**
153 Entry Point for PI SMM communication SMM driver.
154
155 @param[in] ImageHandle Image handle of this driver.
156 @param[in] SystemTable A Pointer to the EFI System Table.
157
158 @retval EFI_SUCEESS
159 @return Others Some error occurs.
160 **/
161 EFI_STATUS
162 EFIAPI
163 PiSmmCommunicationSmmEntryPoint (
164 IN EFI_HANDLE ImageHandle,
165 IN EFI_SYSTEM_TABLE *SystemTable
166 )
167 {
168 EFI_STATUS Status;
169 EFI_SMM_SW_DISPATCH2_PROTOCOL *SmmSwDispatch2;
170 EFI_SMM_SW_REGISTER_CONTEXT SmmSwDispatchContext;
171 EFI_HANDLE DispatchHandle;
172 EFI_PHYSICAL_ADDRESS *BufferPtrAddress;
173
174 //
175 // Register software SMI handler
176 //
177 Status = gSmst->SmmLocateProtocol (
178 &gEfiSmmSwDispatch2ProtocolGuid,
179 NULL,
180 (VOID **)&SmmSwDispatch2
181 );
182 ASSERT_EFI_ERROR (Status);
183
184 SmmSwDispatchContext.SwSmiInputValue = (UINTN)-1;
185 Status = SmmSwDispatch2->Register (
186 SmmSwDispatch2,
187 PiSmmCommunicationHandler,
188 &SmmSwDispatchContext,
189 &DispatchHandle
190 );
191 ASSERT_EFI_ERROR (Status);
192
193 DEBUG ((EFI_D_INFO, "SmmCommunication SwSmi: %x\n", (UINTN)SmmSwDispatchContext.SwSmiInputValue));
194
195 BufferPtrAddress = AllocateAcpiNvsMemoryBelow4G (sizeof(EFI_PHYSICAL_ADDRESS));
196 ASSERT (BufferPtrAddress != NULL);
197 DEBUG ((EFI_D_INFO, "SmmCommunication BufferPtrAddress: 0x%016lx, BufferPtr: 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)BufferPtrAddress, *BufferPtrAddress));
198
199 //
200 // Save context
201 //
202 mSmmCommunicationContext.SwSmiNumber = (UINT32)SmmSwDispatchContext.SwSmiInputValue;
203 mSmmCommunicationContext.BufferPtrAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)BufferPtrAddress;
204 SetCommunicationContext ();
205
206 return Status;
207 }