summaryrefslogtreecommitdiff
path: root/Library/SmmAmiBufferValidationLib.c
blob: acc9a3d8d2235504a0c44ced582193f994798b47 (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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
//**********************************************************************
//**********************************************************************
//**                                                                  **
//**        (C)Copyright 1985-2014, American Megatrends, Inc.         **
//**                                                                  **
//**                       All Rights Reserved.                       **
//**                                                                  **
//**      5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093        **
//**                                                                  **
//**                       Phone: (770)-246-8600                      **
//**                                                                  **
//**********************************************************************
//**********************************************************************

//**********************************************************************
// $Header: /Alaska/SOURCE/Modules/AmiBufferValidationLib/SmmAmiBufferValidationLib.c 4     1/06/15 10:21a Aaronp $
//
// $Revision: 4 $
//
// $Date: 1/06/15 10:21a $
//**********************************************************************
// Revision History
// ----------------
// $Log: /Alaska/SOURCE/Modules/AmiBufferValidationLib/SmmAmiBufferValidationLib.c $
// 
// 4     1/06/15 10:21a Aaronp
// [TAG]  		EIP198890
// [Category]  	Improvement
// [Description]  	Use of CORE_COMBINED_VERSION requires Token.h to be
// included.
// 
// 3     12/30/14 4:08p Aaronp
// [TAG]  		EIP198005 
// [Category]  	Improvement
// [Description]  	Added support for pre PI 1.2
// 
// 2     11/26/14 10:33a Aaronp
// Updated function headers with additional information that was added to
// the AptioV component.
// 
// 1     11/07/14 12:07p Aaronp
// Initial addition of AmiBufferValidationLib
// 
//**********************************************************************

//**********************************************************************
//<AMI_FHDR_START>
//
// Name:	SmmAmiBufferValidationLib.c
//
// Description:	Source file that defines the AmiBufferValidationLib functions
//              used for validating that buffer addresses and MMIO addreses
//              do not reside in SMM. The file also provides a function to
//              validate that a buffer does reside in SMM.
//
//<AMI_FHDR_END>
//**********************************************************************
#include <Token.h>
#include <AmiDxeLib.h>
#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)
#include <Protocol/SmmAccess2.h>
#else
#include <Protocol/SmmAccess.h>
#endif

/// Internal list of SMRAM regions
EFI_SMRAM_DESCRIPTOR *SmmAmiBufferValidationLibSmramRanges = NULL;

/// Number of SMRAM regions in the internal list
UINTN SmmAmiBufferValidationLibNumberOfSmramRange = 0;

//<AMI_PHDR_START>
//----------------------------------------------------------------------------
//  Procedure:      AmiValidateMemoryBuffer
//
//  Description:    Function verifies the buffer to make sure its address range is legal for a memory buffer. A legal memory 
//                  buffer is one that lies entirely outside of SMRAM.  SMI handlers that receive buffer address and/or size 
//                  from outside of SMM at runtime must validate the buffer using this function prior to using it or passing 
//                  to other SMM interfaces.
//
//  Input:
//      VOID *Buffer - Buffer address 
//      UINTN BufferSize - Size of the Buffer
//
//  Output:
//      EFI_SUCCESS - The buffer address range is valid and can be safely used.
//      EFI_ACCESS_DENIED - The buffer can't be used because its address range overlaps with protected area such as SMRAM.
//      EFI_INVALID_PARAMETER - The buffer can't be used because its address range is invalid.
//      EFI_NOT_FOUND - The buffer can't be used because its validity cannot be verified. Normally due to the SMRAM ranges were not available.
//----------------------------------------------------------------------------
//<AMI_PHDR_END>
EFI_STATUS AmiValidateMemoryBuffer(VOID* Buffer, UINTN BufferSize){
	UINTN  i;
	UINTN BufferAddress;

	if (SmmAmiBufferValidationLibNumberOfSmramRange==0) return EFI_NOT_FOUND;

	BufferAddress = (UINTN)Buffer;
	if (BufferAddress + BufferSize < BufferAddress) return EFI_INVALID_PARAMETER; // overflow
	for (i = 0; i < SmmAmiBufferValidationLibNumberOfSmramRange; i ++) {
		if (    BufferAddress >= SmmAmiBufferValidationLibSmramRanges[i].CpuStart
    	     && BufferAddress < SmmAmiBufferValidationLibSmramRanges[i].CpuStart + SmmAmiBufferValidationLibSmramRanges[i].PhysicalSize
    	) return EFI_ACCESS_DENIED; // Buffer starts in SMRAM
        if (    BufferAddress < SmmAmiBufferValidationLibSmramRanges[i].CpuStart
    	     && BufferAddress+BufferSize > SmmAmiBufferValidationLibSmramRanges[i].CpuStart
        ) return EFI_ACCESS_DENIED; // Buffer overlaps with SMRAM
	}
	
	return EFI_SUCCESS;
}

//<AMI_PHDR_START>
//----------------------------------------------------------------------------
//  Procedure:      AmiValidateMmioBuffer
//
//  Description:    Function verifies the buffer to make sure its address range is legal for a MMIO buffer.  A legal MMIO buffer is one that lies 
//                  entirely outside of SMRAM.  SMI handlers that receive a buffer address and/or size from outside of SMM at runtime must validate 
//                  the buffer using this function prior to using the MMIO Buffer or passing to other SMM interfaces.
//
//  Input:
//      VOID *Buffer - Buffer address 
//      UINTN BufferSize - Size of the Buffer
//
//  Output:
//      EFI_SUCCESS - The buffer address range is valid and can be safely used.
//      EFI_ACCESS_DENIED - The buffer can't be used because its address range overlaps with protected area such as SMRAM.
//      EFI_INVALID_PARAMETER - The buffer can't be used because its address range is invalid.
//      EFI_NOT_FOUND - The buffer can't be used because its validity cannot be verified. Normally due to the SMRAM ranges were not available.
//----------------------------------------------------------------------------
//<AMI_PHDR_END>
EFI_STATUS AmiValidateMmioBuffer(VOID* Buffer, UINTN BufferSize){
	return AmiValidateMemoryBuffer(Buffer,BufferSize);
}

//<AMI_PHDR_START>
//----------------------------------------------------------------------------
//  Procedure:      AmiValidateSmramBuffer
//
//  Description:    Function verifies the buffer to make sure it wholly resides in the SMRAM.
//
//  Input:
//      IN VOID *Buffer - Buffer address 
//      IN UINTN BufferSize - Size of the Buffer
//
//  Output:
//      EFI_SUCCESS - The buffer resides in the SMRAM and can be safely used.
//      EFI_ACCESS_DENIED - The buffer can't be used because at least one byte of the buffer is outside of SMRAM.
//      EFI_INVALID_PARAMETER - The buffer can't be used because its address range is invalid.
//      EFI_NOT_FOUND - The buffer can't be used because its validity cannot be verified. Normally due to the SMRAM ranges were not available.
//----------------------------------------------------------------------------
//<AMI_PHDR_END>
EFI_STATUS AmiValidateSmramBuffer(VOID* Buffer, UINTN BufferSize){
	UINTN  i;
	UINTN BufferAddress;

	if (SmmAmiBufferValidationLibNumberOfSmramRange==0) return EFI_NOT_FOUND;

	BufferAddress = (UINTN)Buffer;
	if (BufferAddress + BufferSize < BufferAddress) return EFI_INVALID_PARAMETER; // overflow
	for (i = 0; i < SmmAmiBufferValidationLibNumberOfSmramRange; i ++) {
		if (    BufferAddress >= SmmAmiBufferValidationLibSmramRanges[i].CpuStart
    	     && BufferAddress+BufferSize <= SmmAmiBufferValidationLibSmramRanges[i].CpuStart + SmmAmiBufferValidationLibSmramRanges[i].PhysicalSize
    	) return EFI_SUCCESS; // Entire Buffer is in SMRAM
	}
	
	return EFI_ACCESS_DENIED;
}

//<AMI_PHDR_START>
//----------------------------------------------------------------------------
//  Procedure:      InitAmiBufferValidationLib
//
//  Description:    Performs the necessary initialization so that the buffer validation functions will operate 
//                  correctly when they are called.
//
//  Input:
//  IN EFI_HANDLE ImageHandle - The handle of this image
//  IN EFI_SYSTEM_TABLE *SystemTable - Pointer to the EFI_SYSTEM_TABLE
//
//  Output:
//      EFI_NOT_FOUND - The Smm Access protocol could not be found
//      EFI_OUT_OF_RESOURCES - An allocation failed because it could not find any memory resources 
//      EFI_INVALID_PARAMETER - An invalid parameter was passed to one of the functions
//      EFI_SUCCESS - The necessary functions were initialized
//----------------------------------------------------------------------------
//<AMI_PHDR_END>
EFI_STATUS EFIAPI InitAmiBufferValidationLib(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable){
    EFI_STATUS Status;
#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)
    EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
#else	
    EFI_SMM_ACCESS_PROTOCOL *SmmAccess;
#endif	
    UINTN Size;

#if defined(CORE_COMBINED_VERSION)&&(CORE_COMBINED_VERSION>0x4028a)
    InitAmiSmmLib(ImageHandle,SystemTable);
#endif

    // Get SMRAM information
#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)	
    Status = pBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
#else	
    Status = pBS->LocateProtocol (&gEfiSmmAccessProtocolGuid, NULL, (VOID **)&SmmAccess);
#endif	
    if (EFI_ERROR(Status)) return Status;
    
    Size = 0;
    Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);
    if (Status != EFI_BUFFER_TOO_SMALL) return Status;
    Status = pSmst->SmmAllocatePool (EfiRuntimeServicesData, Size, (VOID **)&SmmAmiBufferValidationLibSmramRanges);
    if (EFI_ERROR(Status)){
    	SmmAmiBufferValidationLibSmramRanges = NULL;
    	return Status;
    }
    Status = SmmAccess->GetCapabilities (SmmAccess, &Size, SmmAmiBufferValidationLibSmramRanges);
    if (EFI_ERROR(Status)){
    	pSmst->SmmFreePool (SmmAmiBufferValidationLibSmramRanges);
    	SmmAmiBufferValidationLibSmramRanges = NULL;
    	return Status;
    }
    SmmAmiBufferValidationLibNumberOfSmramRange = Size / sizeof (EFI_SMRAM_DESCRIPTOR);

    return EFI_SUCCESS;
}

//**********************************************************************
//**********************************************************************
//**                                                                  **
//**        (C)Copyright 1985-2014, American Megatrends, Inc.         **
//**                                                                  **
//**                       All Rights Reserved.                       **
//**                                                                  **
//**      5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093        **
//**                                                                  **
//**                       Phone: (770)-246-8600                      **
//**                                                                  **
//**********************************************************************
//**********************************************************************