]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Variable/Pei/Variable.c
Change C functions, xxxSizeOfVariable(), to MACRO, which can avoid the ICC compile...
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / Pei / Variable.c
1 /*++
2
3 Copyright (c) 2006 - 2007 Intel Corporation. <BR>
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 Module Name:
12
13 Variable.c
14
15 Abstract:
16
17 PEIM to provide the Variable functionality
18
19 --*/
20
21
22 #include "Variable.h"
23
24 //
25 // Module globals
26 //
27 static EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi = {
28 PeiGetVariable,
29 PeiGetNextVariableName
30 };
31
32 static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = {
33 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
34 &gEfiPeiReadOnlyVariable2PpiGuid,
35 &mVariablePpi
36 };
37
38 EFI_GUID mEfiVariableIndexTableGuid = EFI_VARIABLE_INDEX_TABLE_GUID;
39
40 EFI_STATUS
41 EFIAPI
42 PeimInitializeVariableServices (
43 IN EFI_FFS_FILE_HEADER *FfsHeader,
44 IN EFI_PEI_SERVICES **PeiServices
45 )
46 /*++
47
48 Routine Description:
49
50 Provide the functionality of the variable services.
51
52 Arguments:
53
54 FfsHeadher - The FFS file header
55 PeiServices - General purpose services available to every PEIM.
56
57 Returns:
58
59 Status - EFI_SUCCESS if the interface could be successfully
60 installed
61
62 --*/
63 {
64 //
65 // Publish the variable capability to other modules
66 //
67 return (**PeiServices).InstallPpi ((CONST EFI_PEI_SERVICES **)PeiServices, &mPpiListVariable);
68
69 }
70
71 VARIABLE_HEADER *
72 GetStartPointer (
73 IN VARIABLE_STORE_HEADER *VarStoreHeader
74 )
75 /*++
76
77 Routine Description:
78
79 This code gets the pointer to the first variable memory pointer byte
80
81 Arguments:
82
83 VarStoreHeader Pointer to the Variable Store Header.
84
85 Returns:
86
87 VARIABLE_HEADER* Pointer to last unavailable Variable Header
88
89 --*/
90 {
91 //
92 // The end of variable store
93 //
94 return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
95 }
96
97 VARIABLE_HEADER *
98 GetEndPointer (
99 IN VARIABLE_STORE_HEADER *VarStoreHeader
100 )
101 /*++
102
103 Routine Description:
104
105 This code gets the pointer to the last variable memory pointer byte
106
107 Arguments:
108
109 VarStoreHeader Pointer to the Variable Store Header.
110
111 Returns:
112
113 VARIABLE_HEADER* Pointer to last unavailable Variable Header
114
115 --*/
116 {
117 //
118 // The end of variable store
119 //
120 return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
121 }
122
123 STATIC
124 VARIABLE_HEADER *
125 GetNextVariablePtr (
126 IN VARIABLE_HEADER *Variable
127 )
128 /*++
129
130 Routine Description:
131
132 This code checks if variable header is valid or not.
133
134 Arguments:
135 Variable Pointer to the Variable Header.
136
137 Returns:
138 TRUE Variable header is valid.
139 FALSE Variable header is not valid.
140
141 --*/
142 {
143 return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) GET_VARIABLE_DATA_PTR (Variable) + DATASIZE_OF_VARIABLE (Variable) + GET_PAD_SIZE (DATASIZE_OF_VARIABLE (Variable)));
144 }
145
146 STATIC
147 BOOLEAN
148 EFIAPI
149 IsValidVariableHeader (
150 IN VARIABLE_HEADER *Variable
151 )
152 /*++
153
154 Routine Description:
155
156 This code checks if variable header is valid or not.
157
158 Arguments:
159 Variable Pointer to the Variable Header.
160
161 Returns:
162 TRUE Variable header is valid.
163 FALSE Variable header is not valid.
164
165 --*/
166 {
167 if (Variable == NULL || Variable->StartId != VARIABLE_DATA ) {
168 return FALSE;
169 }
170
171 return TRUE;
172 }
173
174 STATIC
175 VARIABLE_STORE_STATUS
176 EFIAPI
177 GetVariableStoreStatus (
178 IN VARIABLE_STORE_HEADER *VarStoreHeader
179 )
180 /*++
181
182 Routine Description:
183
184 This code gets the pointer to the variable name.
185
186 Arguments:
187
188 VarStoreHeader Pointer to the Variable Store Header.
189
190 Returns:
191
192 EfiRaw Variable store is raw
193 EfiValid Variable store is valid
194 EfiInvalid Variable store is invalid
195
196 --*/
197 {
198 if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&
199 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
200 VarStoreHeader->State == VARIABLE_STORE_HEALTHY
201 ) {
202
203 return EfiValid;
204 }
205
206 if (VarStoreHeader->Signature == 0xffffffff &&
207 VarStoreHeader->Size == 0xffffffff &&
208 VarStoreHeader->Format == 0xff &&
209 VarStoreHeader->State == 0xff
210 ) {
211
212 return EfiRaw;
213 } else {
214 return EfiInvalid;
215 }
216 }
217
218 STATIC
219 EFI_STATUS
220 CompareWithValidVariable (
221 IN VARIABLE_HEADER *Variable,
222 IN CONST CHAR16 *VariableName,
223 IN CONST EFI_GUID *VendorGuid,
224 OUT VARIABLE_POINTER_TRACK *PtrTrack
225 )
226 /*++
227
228 Routine Description:
229
230 This function compares a variable with variable entries in database
231
232 Arguments:
233
234 Variable - Pointer to the variable in our database
235 VariableName - Name of the variable to compare to 'Variable'
236 VendorGuid - GUID of the variable to compare to 'Variable'
237 PtrTrack - Variable Track Pointer structure that contains
238 Variable Information.
239
240 Returns:
241
242 EFI_SUCCESS - Found match variable
243 EFI_NOT_FOUND - Variable not found
244
245 --*/
246 {
247 if (VariableName[0] == 0) {
248 PtrTrack->CurrPtr = Variable;
249 return EFI_SUCCESS;
250 } else {
251 //
252 // Don't use CompareGuid function here for performance reasons.
253 // Instead we compare the GUID a UINT32 at a time and branch
254 // on the first failed comparison.
255 //
256 if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&
257 (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&
258 (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&
259 (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])
260 ) {
261 ASSERT (NAMESIZE_OF_VARIABLE (Variable) != 0);
262 if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), NAMESIZE_OF_VARIABLE (Variable))) {
263 PtrTrack->CurrPtr = Variable;
264 return EFI_SUCCESS;
265 }
266 }
267 }
268
269 return EFI_NOT_FOUND;
270 }
271
272 STATIC
273 EFI_STATUS
274 EFIAPI
275 FindVariable (
276 IN EFI_PEI_SERVICES **PeiServices,
277 IN CONST CHAR16 *VariableName,
278 IN CONST EFI_GUID *VendorGuid,
279 OUT VARIABLE_POINTER_TRACK *PtrTrack
280 )
281 /*++
282
283 Routine Description:
284
285 This code finds variable in storage blocks (Non-Volatile)
286
287 Arguments:
288
289 PeiServices - General purpose services available to every PEIM.
290 VariableName - Name of the variable to be found
291 VendorGuid - Vendor GUID to be found.
292 PtrTrack - Variable Track Pointer structure that contains
293 Variable Information.
294
295 Returns:
296
297 EFI_SUCCESS - Variable found successfully
298 EFI_NOT_FOUND - Variable not found
299 EFI_INVALID_PARAMETER - Invalid variable name
300
301 --*/
302 {
303 EFI_HOB_GUID_TYPE *GuidHob;
304 VARIABLE_STORE_HEADER *VariableStoreHeader;
305 VARIABLE_HEADER *Variable;
306 VARIABLE_HEADER *MaxIndex;
307 VARIABLE_INDEX_TABLE *IndexTable;
308 UINT32 Count;
309 UINT8 *VariableBase;
310
311 if (VariableName != 0 && VendorGuid == NULL) {
312 return EFI_INVALID_PARAMETER;
313 }
314 //
315 // No Variable Address equals zero, so 0 as initial value is safe.
316 //
317 MaxIndex = 0;
318
319 GuidHob = GetFirstGuidHob (&mEfiVariableIndexTableGuid);
320 if (GuidHob == NULL) {
321 IndexTable = BuildGuidHob (&mEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));
322 IndexTable->Length = 0;
323 IndexTable->StartPtr = NULL;
324 IndexTable->EndPtr = NULL;
325 IndexTable->GoneThrough = 0;
326 } else {
327 IndexTable = GET_GUID_HOB_DATA (GuidHob);
328 for (Count = 0; Count < IndexTable->Length; Count++)
329 {
330 MaxIndex = GetVariableByIndex (IndexTable, Count);
331
332 if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
333 PtrTrack->StartPtr = IndexTable->StartPtr;
334 PtrTrack->EndPtr = IndexTable->EndPtr;
335
336 return EFI_SUCCESS;
337 }
338 }
339
340 if (IndexTable->GoneThrough) {
341 return EFI_NOT_FOUND;
342 }
343 }
344 //
345 // If not found in HOB, then let's start from the MaxIndex we've found.
346 //
347 if (MaxIndex != NULL) {
348 Variable = GetNextVariablePtr (MaxIndex);
349 } else {
350 if (IndexTable->StartPtr || IndexTable->EndPtr) {
351 Variable = IndexTable->StartPtr;
352 } else {
353 VariableBase = (UINT8 *) (UINTN) PcdGet32 (PcdFlashNvStorageVariableBase);
354 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (VariableBase + \
355 ((EFI_FIRMWARE_VOLUME_HEADER *) (VariableBase)) -> HeaderLength);
356
357 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
358 return EFI_UNSUPPORTED;
359 }
360
361 if (~VariableStoreHeader->Size == 0) {
362 return EFI_NOT_FOUND;
363 }
364 //
365 // Find the variable by walk through non-volatile variable store
366 //
367 IndexTable->StartPtr = GetStartPointer (VariableStoreHeader);
368 IndexTable->EndPtr = GetEndPointer (VariableStoreHeader);
369
370 //
371 // Start Pointers for the variable.
372 // Actual Data Pointer where data can be written.
373 //
374 Variable = IndexTable->StartPtr;
375 }
376 }
377 //
378 // Find the variable by walk through non-volatile variable store
379 //
380 PtrTrack->StartPtr = IndexTable->StartPtr;
381 PtrTrack->EndPtr = IndexTable->EndPtr;
382
383 while (IsValidVariableHeader (Variable) && (Variable <= IndexTable->EndPtr)) {
384 if (Variable->State == VAR_ADDED) {
385 //
386 // Record Variable in VariableIndex HOB
387 //
388 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME)
389 {
390 VariableIndexTableUpdate (IndexTable, Variable);
391 }
392
393 if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
394 return EFI_SUCCESS;
395 }
396 }
397
398 Variable = GetNextVariablePtr (Variable);
399 }
400 //
401 // If gone through the VariableStore, that means we never find in Firmware any more.
402 //
403 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) {
404 IndexTable->GoneThrough = 1;
405 }
406
407 PtrTrack->CurrPtr = NULL;
408
409 return EFI_NOT_FOUND;
410 }
411
412 EFI_STATUS
413 EFIAPI
414 PeiGetVariable (
415 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
416 IN CONST CHAR16 *VariableName,
417 IN CONST EFI_GUID *VariableGuid,
418 OUT UINT32 *Attributes,
419 IN OUT UINTN *DataSize,
420 OUT VOID *Data
421 )
422 /*++
423
424 Routine Description:
425
426 Provide the read variable functionality of the variable services.
427
428 Arguments:
429
430 PeiServices - General purpose services available to every PEIM.
431
432 VariableName - The variable name
433
434 VendorGuid - The vendor's GUID
435
436 Attributes - Pointer to the attribute
437
438 DataSize - Size of data
439
440 Data - Pointer to data
441
442 Returns:
443
444 EFI_SUCCESS - The interface could be successfully installed
445
446 EFI_NOT_FOUND - The variable could not be discovered
447
448 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
449
450 --*/
451 {
452 VARIABLE_POINTER_TRACK Variable;
453 UINTN VarDataSize;
454 EFI_STATUS Status;
455 EFI_PEI_SERVICES **PeiServices;
456
457 PeiServices = GetPeiServicesTablePointer ();
458 if (VariableName == NULL || VariableGuid == NULL) {
459 return EFI_INVALID_PARAMETER;
460 }
461 //
462 // Find existing variable
463 //
464 Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);
465 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
466 return Status;
467 }
468 //
469 // Get data size
470 //
471 VarDataSize = DATASIZE_OF_VARIABLE (Variable.CurrPtr);
472 if (*DataSize >= VarDataSize) {
473 (*PeiServices)->CopyMem (Data, GET_VARIABLE_DATA_PTR (Variable.CurrPtr), VarDataSize);
474
475 if (Attributes != NULL) {
476 *Attributes = Variable.CurrPtr->Attributes;
477 }
478
479 *DataSize = VarDataSize;
480 return EFI_SUCCESS;
481 } else {
482 *DataSize = VarDataSize;
483 return EFI_BUFFER_TOO_SMALL;
484 }
485 }
486
487 EFI_STATUS
488 EFIAPI
489 PeiGetNextVariableName (
490 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
491 IN OUT UINTN *VariableNameSize,
492 IN OUT CHAR16 *VariableName,
493 IN OUT EFI_GUID *VariableGuid
494 )
495 /*++
496
497 Routine Description:
498
499 Provide the get next variable functionality of the variable services.
500
501 Arguments:
502
503 PeiServices - General purpose services available to every PEIM.
504 VariabvleNameSize - The variable name's size.
505 VariableName - A pointer to the variable's name.
506 VariableGuid - A pointer to the EFI_GUID structure.
507
508 VariableNameSize - Size of the variable name
509
510 VariableName - The variable name
511
512 VendorGuid - The vendor's GUID
513
514 Returns:
515
516 EFI_SUCCESS - The interface could be successfully installed
517
518 EFI_NOT_FOUND - The variable could not be discovered
519
520 --*/
521 {
522 VARIABLE_POINTER_TRACK Variable;
523 UINTN VarNameSize;
524 EFI_STATUS Status;
525 EFI_PEI_SERVICES **PeiServices;
526
527 PeiServices = GetPeiServicesTablePointer ();
528 if (VariableName == NULL) {
529 return EFI_INVALID_PARAMETER;
530 }
531
532 Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);
533 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
534 return Status;
535 }
536
537 if (VariableName[0] != 0) {
538 //
539 // If variable name is not NULL, get next variable
540 //
541 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
542 }
543
544 while (!(Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL)) {
545 if (IsValidVariableHeader (Variable.CurrPtr)) {
546 if (Variable.CurrPtr->State == VAR_ADDED) {
547 ASSERT (NAMESIZE_OF_VARIABLE (Variable.CurrPtr) != 0);
548
549 VarNameSize = (UINTN) NAMESIZE_OF_VARIABLE (Variable.CurrPtr);
550 if (VarNameSize <= *VariableNameSize) {
551 (*PeiServices)->CopyMem (VariableName, GET_VARIABLE_NAME_PTR (Variable.CurrPtr), VarNameSize);
552
553 (*PeiServices)->CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));
554
555 Status = EFI_SUCCESS;
556 } else {
557 Status = EFI_BUFFER_TOO_SMALL;
558 }
559
560 *VariableNameSize = VarNameSize;
561 return Status;
562 //
563 // Variable is found
564 //
565 } else {
566 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
567 }
568 } else {
569 break;
570 }
571 }
572
573 return EFI_NOT_FOUND;
574 }