]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
MdeModulePkg: Fix device path when boot manager menu is from different FV
[mirror_edk2.git] / MdeModulePkg / Library / VariablePolicyHelperLib / VariablePolicyHelperLib.c
CommitLineData
b6104bec
BB
1/** @file -- VariablePolicyHelperLib.c\r
2This library contains helper functions for marshalling and registering\r
3new policies with the VariablePolicy infrastructure.\r
4\r
5This library is currently written against VariablePolicy revision 0x00010000.\r
6\r
7Copyright (c) Microsoft Corporation.\r
8SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10**/\r
11\r
12#include <Uefi.h>\r
13\r
14#include <Library/BaseLib.h>\r
15#include <Library/DebugLib.h>\r
16#include <Library/BaseMemoryLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
18\r
19#include <Protocol/VariablePolicy.h>\r
20\r
21/**\r
22 This internal helper function populates the header structure,\r
23 all common fields, and takes care of fix-ups.\r
24\r
25 NOTE: Only use this internally. Assumes correctly-sized buffers.\r
26\r
27 @param[out] EntPtr Pointer to the buffer to be populated.\r
28 @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.\r
29 @param[in] MinSize MinSize for the VariablePolicy.\r
30 @param[in] MaxSize MaxSize for the VariablePolicy.\r
31 @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.\r
32 @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.\r
33 @param[in] LockPolicyType LockPolicyType for the VariablePolicy.\r
34\r
35**/\r
36STATIC\r
37VOID\r
38PopulateCommonData (\r
39 OUT VARIABLE_POLICY_ENTRY *EntPtr,\r
40 IN CONST EFI_GUID *Namespace,\r
41 IN UINT32 MinSize,\r
42 IN UINT32 MaxSize,\r
43 IN UINT32 AttributesMustHave,\r
44 IN UINT32 AttributesCantHave,\r
45 IN UINT8 LockPolicyType\r
46 )\r
47{\r
48 EntPtr->Version = VARIABLE_POLICY_ENTRY_REVISION;\r
49 CopyGuid( &EntPtr->Namespace, Namespace );\r
50 EntPtr->MinSize = MinSize;\r
51 EntPtr->MaxSize = MaxSize;\r
52 EntPtr->AttributesMustHave = AttributesMustHave;\r
53 EntPtr->AttributesCantHave = AttributesCantHave;\r
54 EntPtr->LockPolicyType = LockPolicyType;\r
55\r
56 // NOTE: As a heler, fix up MaxSize for compatibility with the old model.\r
57 if (EntPtr->MaxSize == 0) {\r
58 EntPtr->MaxSize = VARIABLE_POLICY_NO_MAX_SIZE;\r
59 }\r
60\r
61 return;\r
62}\r
63\r
64\r
65/**\r
66 This helper function will allocate and populate a new VariablePolicy\r
67 structure for a policy that does not contain any sub-structures (such as\r
68 VARIABLE_LOCK_ON_VAR_STATE_POLICY).\r
69\r
70 NOTE: Caller will need to free structure once finished.\r
71\r
72 @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.\r
73 @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.\r
74 Otherwise, will create a policy that targets an entire namespace.\r
75 @param[in] MinSize MinSize for the VariablePolicy.\r
76 @param[in] MaxSize MaxSize for the VariablePolicy.\r
77 @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.\r
78 @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.\r
79 @param[in] LockPolicyType LockPolicyType for the VariablePolicy.\r
80 @param[out] NewEntry If successful, will be set to a pointer to the allocated buffer containing the\r
81 new policy.\r
82\r
83 @retval EFI_SUCCESS Operation completed successfully and structure is populated.\r
84 @retval EFI_INVALID_PARAMETER Namespace is NULL.\r
85 @retval EFI_INVALID_PARAMETER LockPolicyType is invalid for a basic structure.\r
86 @retval EFI_BUFFER_TOO_SMALL Finished structure would not fit in UINT16 size.\r
87 @retval EFI_OUT_OF_RESOURCES Could not allocate sufficient space for structure.\r
88\r
89**/\r
90EFI_STATUS\r
91EFIAPI\r
92CreateBasicVariablePolicy (\r
93 IN CONST EFI_GUID *Namespace,\r
94 IN CONST CHAR16 *Name OPTIONAL,\r
95 IN UINT32 MinSize,\r
96 IN UINT32 MaxSize,\r
97 IN UINT32 AttributesMustHave,\r
98 IN UINT32 AttributesCantHave,\r
99 IN UINT8 LockPolicyType,\r
100 OUT VARIABLE_POLICY_ENTRY **NewEntry\r
101 )\r
102{\r
103 UINTN TotalSize;\r
104 UINTN NameSize;\r
105 VARIABLE_POLICY_ENTRY *EntPtr;\r
106 CHAR16 *CopyName;\r
107\r
108 // Check some initial invalid parameters for this function.\r
109 if (Namespace == NULL || NewEntry == NULL) {\r
110 return EFI_INVALID_PARAMETER;\r
111 }\r
112 if (LockPolicyType != VARIABLE_POLICY_TYPE_NO_LOCK &&\r
113 LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_NOW &&\r
114 LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_ON_CREATE) {\r
115 return EFI_INVALID_PARAMETER;\r
116 }\r
117\r
aa759653
LG
118 //\r
119 // Set NameSize to suppress incorrect compiler/analyzer warnings\r
120 //\r
121 NameSize = 0;\r
122\r
b6104bec
BB
123 // Now we've gotta determine the total size of the buffer required for\r
124 // the VariablePolicy structure.\r
125 TotalSize = sizeof( VARIABLE_POLICY_ENTRY );\r
126 if (Name != NULL) {\r
127 NameSize = StrnSizeS( Name, MAX_UINT16 );\r
128 TotalSize += NameSize;\r
129 }\r
130 // Make sure the size fits within a VARIABLE_POLICY_ENTRY.Size.\r
131 ASSERT( TotalSize <= MAX_UINT16 );\r
132 if (TotalSize > MAX_UINT16) {\r
133 return EFI_BUFFER_TOO_SMALL;\r
134 }\r
135\r
136 // Allocate a buffer to hold all the data. We're on the home stretch.\r
137 *NewEntry = AllocatePool( TotalSize );\r
138 if (*NewEntry == NULL) {\r
139 return EFI_OUT_OF_RESOURCES;\r
140 }\r
141\r
142 // If we're still here, we're basically done.\r
143 // Copy the data and GET... OUT....\r
144 EntPtr = *NewEntry;\r
145 PopulateCommonData ( EntPtr,\r
146 Namespace,\r
147 MinSize,\r
148 MaxSize,\r
149 AttributesMustHave,\r
150 AttributesCantHave,\r
151 LockPolicyType );\r
152 EntPtr->Size = (UINT16)TotalSize; // This is safe because we've already checked.\r
153 EntPtr->OffsetToName = sizeof(VARIABLE_POLICY_ENTRY);\r
154 if (Name != NULL) {\r
155 CopyName = (CHAR16*)((UINT8*)EntPtr + EntPtr->OffsetToName);\r
156 CopyMem( CopyName, Name, NameSize );\r
157 }\r
158\r
159 return EFI_SUCCESS;\r
160}\r
161\r
162\r
163/**\r
164 This helper function will allocate and populate a new VariablePolicy\r
165 structure for a policy with a lock type of VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE.\r
166\r
167 NOTE: Caller will need to free structure once finished.\r
168\r
169 @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.\r
170 @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.\r
171 Otherwise, will create a policy that targets an entire namespace.\r
172 @param[in] MinSize MinSize for the VariablePolicy.\r
173 @param[in] MaxSize MaxSize for the VariablePolicy.\r
174 @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.\r
175 @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.\r
176 @param[in] VarStateNamespace Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.\r
177 @param[in] VarStateValue Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.\r
178 @param[in] VarStateName Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.\r
179 @param[out] NewEntry If successful, will be set to a pointer to the allocated buffer containing the\r
180 new policy.\r
181\r
182 @retval EFI_SUCCESS Operation completed successfully and structure is populated.\r
183 @retval EFI_INVALID_PARAMETER Namespace, VarStateNamespace, VarStateName is NULL.\r
184 @retval EFI_BUFFER_TOO_SMALL Finished structure would not fit in UINT16 size.\r
185 @retval EFI_OUT_OF_RESOURCES Could not allocate sufficient space for structure.\r
186\r
187**/\r
188EFI_STATUS\r
189EFIAPI\r
190CreateVarStateVariablePolicy (\r
191 IN CONST EFI_GUID *Namespace,\r
192 IN CONST CHAR16 *Name OPTIONAL,\r
193 IN UINT32 MinSize,\r
194 IN UINT32 MaxSize,\r
195 IN UINT32 AttributesMustHave,\r
196 IN UINT32 AttributesCantHave,\r
197 IN CONST EFI_GUID *VarStateNamespace,\r
198 IN UINT8 VarStateValue,\r
199 IN CONST CHAR16 *VarStateName,\r
200 OUT VARIABLE_POLICY_ENTRY **NewEntry\r
201 )\r
202{\r
203 UINTN TotalSize;\r
204 UINTN NameSize;\r
205 UINTN VarStateNameSize;\r
206 VARIABLE_POLICY_ENTRY *EntPtr;\r
207 CHAR16 *CopyName;\r
208 VARIABLE_LOCK_ON_VAR_STATE_POLICY *CopyPolicy;\r
209\r
210 // Check some initial invalid parameters for this function.\r
211 if (Namespace == NULL || VarStateNamespace == NULL ||\r
212 VarStateName == NULL || NewEntry == NULL) {\r
213 return EFI_INVALID_PARAMETER;\r
214 }\r
215\r
216 // Now we've gotta determine the total size of the buffer required for\r
217 // the VariablePolicy structure.\r
218 VarStateNameSize = StrnSizeS( VarStateName, MAX_UINT16 );\r
219 TotalSize = sizeof( VARIABLE_POLICY_ENTRY ) +\r
220 sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) +\r
221 VarStateNameSize;\r
222 if (Name != NULL) {\r
223 NameSize = StrnSizeS( Name, MAX_UINT16 );\r
224 TotalSize += NameSize;\r
225 }\r
226 // Make sure the size fits within a VARIABLE_POLICY_ENTRY.Size.\r
227 ASSERT( TotalSize <= MAX_UINT16 );\r
228 if (TotalSize > MAX_UINT16) {\r
229 return EFI_BUFFER_TOO_SMALL;\r
230 }\r
231\r
232 // Allocate a buffer to hold all the data. We're on the home stretch.\r
233 *NewEntry = AllocatePool( TotalSize );\r
234 if (*NewEntry == NULL) {\r
235 return EFI_OUT_OF_RESOURCES;\r
236 }\r
237\r
238 // If we're still here, we're basically done.\r
239 // Copy the data and GET... OUT....\r
240 EntPtr = *NewEntry;\r
241 PopulateCommonData ( EntPtr,\r
242 Namespace,\r
243 MinSize,\r
244 MaxSize,\r
245 AttributesMustHave,\r
246 AttributesCantHave,\r
247 VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE );\r
248 EntPtr->Size = (UINT16)TotalSize; // This is safe because we've already checked.\r
249 EntPtr->OffsetToName = sizeof(VARIABLE_POLICY_ENTRY) +\r
250 sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) +\r
251 (UINT16)VarStateNameSize;\r
252\r
253 CopyPolicy = (VARIABLE_LOCK_ON_VAR_STATE_POLICY*)((UINT8*)EntPtr + sizeof(VARIABLE_POLICY_ENTRY));\r
254 CopyName = (CHAR16*)((UINT8*)CopyPolicy + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY));\r
255 CopyGuid( &CopyPolicy->Namespace, VarStateNamespace );\r
256 CopyPolicy->Value = VarStateValue;\r
257 CopyMem( CopyName, VarStateName, VarStateNameSize );\r
258\r
259 if (Name != NULL) {\r
260 CopyName = (CHAR16*)((UINT8*)EntPtr + EntPtr->OffsetToName);\r
261 CopyMem( CopyName, Name, NameSize );\r
262 }\r
263\r
264 return EFI_SUCCESS;\r
265}\r
266\r
267\r
268/**\r
269 This helper function does everything that CreateBasicVariablePolicy() does, but also\r
270 uses the passed in protocol to register the policy with the infrastructure.\r
271 Does not return a buffer, does not require the caller to free anything.\r
272\r
273 @param[in] VariablePolicy Pointer to a valid instance of the VariablePolicy protocol.\r
274 @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.\r
275 @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.\r
276 Otherwise, will create a policy that targets an entire namespace.\r
277 @param[in] MinSize MinSize for the VariablePolicy.\r
278 @param[in] MaxSize MaxSize for the VariablePolicy.\r
279 @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.\r
280 @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.\r
281 @param[in] LockPolicyType LockPolicyType for the VariablePolicy.\r
282\r
283 @retval EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.\r
284 @retval EFI_STATUS Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().\r
285\r
286**/\r
287EFI_STATUS\r
288EFIAPI\r
289RegisterBasicVariablePolicy (\r
290 IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,\r
291 IN CONST EFI_GUID *Namespace,\r
292 IN CONST CHAR16 *Name OPTIONAL,\r
293 IN UINT32 MinSize,\r
294 IN UINT32 MaxSize,\r
295 IN UINT32 AttributesMustHave,\r
296 IN UINT32 AttributesCantHave,\r
297 IN UINT8 LockPolicyType\r
298 )\r
299{\r
300 VARIABLE_POLICY_ENTRY *NewEntry;\r
301 EFI_STATUS Status;\r
302\r
303 // Check the simple things.\r
304 if (VariablePolicy == NULL) {\r
305 return EFI_INVALID_PARAMETER;\r
306 }\r
307\r
308 // Create the new entry and make sure that everything worked.\r
309 NewEntry = NULL;\r
310 Status = CreateBasicVariablePolicy( Namespace,\r
311 Name,\r
312 MinSize,\r
313 MaxSize,\r
314 AttributesMustHave,\r
315 AttributesCantHave,\r
316 LockPolicyType,\r
317 &NewEntry );\r
318\r
319 // If that was successful, attempt to register the new policy.\r
320 if (!EFI_ERROR( Status )) {\r
321 Status = VariablePolicy->RegisterVariablePolicy( NewEntry );\r
322 }\r
323\r
324 // If we allocated the buffer, free the buffer.\r
325 if (NewEntry != NULL) {\r
326 FreePool( NewEntry );\r
327 }\r
328\r
329 return Status;\r
330}\r
331\r
332\r
333/**\r
334 This helper function does everything that CreateBasicVariablePolicy() does, but also\r
335 uses the passed in protocol to register the policy with the infrastructure.\r
336 Does not return a buffer, does not require the caller to free anything.\r
337\r
338 @param[in] VariablePolicy Pointer to a valid instance of the VariablePolicy protocol.\r
339 @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.\r
340 @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.\r
341 Otherwise, will create a policy that targets an entire namespace.\r
342 @param[in] MinSize MinSize for the VariablePolicy.\r
343 @param[in] MaxSize MaxSize for the VariablePolicy.\r
344 @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.\r
345 @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.\r
346 @param[in] VarStateNamespace Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.\r
347 @param[in] VarStateName Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.\r
348 @param[in] VarStateValue Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.\r
349\r
350 @retval EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.\r
351 @retval EFI_STATUS Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().\r
352\r
353**/\r
354EFI_STATUS\r
355EFIAPI\r
356RegisterVarStateVariablePolicy (\r
357 IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,\r
358 IN CONST EFI_GUID *Namespace,\r
359 IN CONST CHAR16 *Name OPTIONAL,\r
360 IN UINT32 MinSize,\r
361 IN UINT32 MaxSize,\r
362 IN UINT32 AttributesMustHave,\r
363 IN UINT32 AttributesCantHave,\r
364 IN CONST EFI_GUID *VarStateNamespace,\r
365 IN CONST CHAR16 *VarStateName,\r
366 IN UINT8 VarStateValue\r
367 )\r
368{\r
369 VARIABLE_POLICY_ENTRY *NewEntry;\r
370 EFI_STATUS Status;\r
371\r
372 // Check the simple things.\r
373 if (VariablePolicy == NULL) {\r
374 return EFI_INVALID_PARAMETER;\r
375 }\r
376\r
377 // Create the new entry and make sure that everything worked.\r
378 NewEntry = NULL;\r
379 Status = CreateVarStateVariablePolicy( Namespace,\r
380 Name,\r
381 MinSize,\r
382 MaxSize,\r
383 AttributesMustHave,\r
384 AttributesCantHave,\r
385 VarStateNamespace,\r
386 VarStateValue,\r
387 VarStateName,\r
388 &NewEntry );\r
389\r
390 // If that was successful, attempt to register the new policy.\r
391 if (!EFI_ERROR( Status )) {\r
392 Status = VariablePolicy->RegisterVariablePolicy( NewEntry );\r
393 }\r
394\r
395 // If we allocated the buffer, free the buffer.\r
396 if (NewEntry != NULL) {\r
397 FreePool( NewEntry );\r
398 }\r
399\r
400 return Status;\r
401}\r