]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Variable/Pei/Variable.c
Align the header of variable from 1 to 4, which can avoid the size of variable conten...
[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 UINT32
124 NameSizeOfVariable (
125 IN VARIABLE_HEADER *Variable
126 )
127 {
128 //
129 // Check whether the header is valid fully;
130 // Tricky: The unprogramed data in FLASH equals 0xff.
131 //
132 if (Variable->DataSize == (UINT32) -1 ||
133 Variable->Attributes == (UINT32) -1 ||
134 Variable->NameSize == (UINT32) -1) {
135 return 0;
136 }
137 return Variable->NameSize;
138 }
139
140 UINT32
141 DataSizeOfVariable (
142 IN VARIABLE_HEADER *Variable
143 )
144 {
145 //
146 // Check whether the header is valid fully;
147 // Tricky: The unprogramed data in FLASH equals 0xff.
148 //
149 if (Variable->DataSize == (UINT32) -1 ||
150 Variable->Attributes == (UINT32) -1 ||
151 Variable->NameSize == (UINT32) -1) {
152 return 0;
153 }
154 return Variable->DataSize;
155 }
156
157 UINT32
158 AttributesOfVariable (
159 IN VARIABLE_HEADER *Variable
160 )
161 {
162
163 //
164 // Check whether the header is valid fully;
165 // Tricky: The unprogramed data in FLASH equals 0xff.
166 //
167 if (Variable->DataSize == (UINT32) -1 ||
168 Variable->Attributes == (UINT32) -1 ||
169 Variable->NameSize == (UINT32) -1) {
170 return 0;
171 }
172 return Variable->Attributes;
173 }
174
175
176 STATIC
177 VARIABLE_HEADER *
178 GetNextVariablePtr (
179 IN VARIABLE_HEADER *Variable
180 )
181 /*++
182
183 Routine Description:
184
185 This code checks if variable header is valid or not.
186
187 Arguments:
188 Variable Pointer to the Variable Header.
189
190 Returns:
191 TRUE Variable header is valid.
192 FALSE Variable header is not valid.
193
194 --*/
195 {
196 return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) GET_VARIABLE_DATA_PTR (Variable) + DataSizeOfVariable (Variable) + GET_PAD_SIZE (DataSizeOfVariable (Variable)));
197 }
198
199 STATIC
200 BOOLEAN
201 EFIAPI
202 IsValidVariableHeader (
203 IN VARIABLE_HEADER *Variable
204 )
205 /*++
206
207 Routine Description:
208
209 This code checks if variable header is valid or not.
210
211 Arguments:
212 Variable Pointer to the Variable Header.
213
214 Returns:
215 TRUE Variable header is valid.
216 FALSE Variable header is not valid.
217
218 --*/
219 {
220 if (Variable == NULL || Variable->StartId != VARIABLE_DATA ) {
221 return FALSE;
222 }
223
224 return TRUE;
225 }
226
227 STATIC
228 VARIABLE_STORE_STATUS
229 EFIAPI
230 GetVariableStoreStatus (
231 IN VARIABLE_STORE_HEADER *VarStoreHeader
232 )
233 /*++
234
235 Routine Description:
236
237 This code gets the pointer to the variable name.
238
239 Arguments:
240
241 VarStoreHeader Pointer to the Variable Store Header.
242
243 Returns:
244
245 EfiRaw Variable store is raw
246 EfiValid Variable store is valid
247 EfiInvalid Variable store is invalid
248
249 --*/
250 {
251 if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&
252 VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
253 VarStoreHeader->State == VARIABLE_STORE_HEALTHY
254 ) {
255
256 return EfiValid;
257 }
258
259 if (VarStoreHeader->Signature == 0xffffffff &&
260 VarStoreHeader->Size == 0xffffffff &&
261 VarStoreHeader->Format == 0xff &&
262 VarStoreHeader->State == 0xff
263 ) {
264
265 return EfiRaw;
266 } else {
267 return EfiInvalid;
268 }
269 }
270
271 STATIC
272 EFI_STATUS
273 CompareWithValidVariable (
274 IN VARIABLE_HEADER *Variable,
275 IN CONST CHAR16 *VariableName,
276 IN CONST EFI_GUID *VendorGuid,
277 OUT VARIABLE_POINTER_TRACK *PtrTrack
278 )
279 /*++
280
281 Routine Description:
282
283 This function compares a variable with variable entries in database
284
285 Arguments:
286
287 Variable - Pointer to the variable in our database
288 VariableName - Name of the variable to compare to 'Variable'
289 VendorGuid - GUID of the variable to compare to 'Variable'
290 PtrTrack - Variable Track Pointer structure that contains
291 Variable Information.
292
293 Returns:
294
295 EFI_SUCCESS - Found match variable
296 EFI_NOT_FOUND - Variable not found
297
298 --*/
299 {
300 if (VariableName[0] == 0) {
301 PtrTrack->CurrPtr = Variable;
302 return EFI_SUCCESS;
303 } else {
304 //
305 // Don't use CompareGuid function here for performance reasons.
306 // Instead we compare the GUID a UINT32 at a time and branch
307 // on the first failed comparison.
308 //
309 if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&
310 (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&
311 (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&
312 (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])
313 ) {
314 ASSERT (NameSizeOfVariable (Variable) != 0);
315 if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), NameSizeOfVariable (Variable))) {
316 PtrTrack->CurrPtr = Variable;
317 return EFI_SUCCESS;
318 }
319 }
320 }
321
322 return EFI_NOT_FOUND;
323 }
324
325 STATIC
326 EFI_STATUS
327 EFIAPI
328 FindVariable (
329 IN EFI_PEI_SERVICES **PeiServices,
330 IN CONST CHAR16 *VariableName,
331 IN CONST EFI_GUID *VendorGuid,
332 OUT VARIABLE_POINTER_TRACK *PtrTrack
333 )
334 /*++
335
336 Routine Description:
337
338 This code finds variable in storage blocks (Non-Volatile)
339
340 Arguments:
341
342 PeiServices - General purpose services available to every PEIM.
343 VariableName - Name of the variable to be found
344 VendorGuid - Vendor GUID to be found.
345 PtrTrack - Variable Track Pointer structure that contains
346 Variable Information.
347
348 Returns:
349
350 EFI_SUCCESS - Variable found successfully
351 EFI_NOT_FOUND - Variable not found
352 EFI_INVALID_PARAMETER - Invalid variable name
353
354 --*/
355 {
356 EFI_HOB_GUID_TYPE *GuidHob;
357 VARIABLE_STORE_HEADER *VariableStoreHeader;
358 VARIABLE_HEADER *Variable;
359 VARIABLE_HEADER *MaxIndex;
360 VARIABLE_INDEX_TABLE *IndexTable;
361 UINT32 Count;
362 UINT8 *VariableBase;
363
364 if (VariableName != 0 && VendorGuid == NULL) {
365 return EFI_INVALID_PARAMETER;
366 }
367 //
368 // No Variable Address equals zero, so 0 as initial value is safe.
369 //
370 MaxIndex = 0;
371
372 GuidHob = GetFirstGuidHob (&mEfiVariableIndexTableGuid);
373 if (GuidHob == NULL) {
374 IndexTable = BuildGuidHob (&mEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));
375 IndexTable->Length = 0;
376 IndexTable->StartPtr = NULL;
377 IndexTable->EndPtr = NULL;
378 IndexTable->GoneThrough = 0;
379 } else {
380 IndexTable = GET_GUID_HOB_DATA (GuidHob);
381 for (Count = 0; Count < IndexTable->Length; Count++)
382 {
383 MaxIndex = GetVariableByIndex (IndexTable, Count);
384
385 if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
386 PtrTrack->StartPtr = IndexTable->StartPtr;
387 PtrTrack->EndPtr = IndexTable->EndPtr;
388
389 return EFI_SUCCESS;
390 }
391 }
392
393 if (IndexTable->GoneThrough) {
394 return EFI_NOT_FOUND;
395 }
396 }
397 //
398 // If not found in HOB, then let's start from the MaxIndex we've found.
399 //
400 if (MaxIndex != NULL) {
401 Variable = GetNextVariablePtr (MaxIndex);
402 } else {
403 if (IndexTable->StartPtr || IndexTable->EndPtr) {
404 Variable = IndexTable->StartPtr;
405 } else {
406 VariableBase = (UINT8 *) (UINTN) PcdGet32 (PcdFlashNvStorageVariableBase);
407 VariableStoreHeader = (VARIABLE_STORE_HEADER *) (VariableBase + \
408 ((EFI_FIRMWARE_VOLUME_HEADER *) (VariableBase)) -> HeaderLength);
409
410 if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
411 return EFI_UNSUPPORTED;
412 }
413
414 if (~VariableStoreHeader->Size == 0) {
415 return EFI_NOT_FOUND;
416 }
417 //
418 // Find the variable by walk through non-volatile variable store
419 //
420 IndexTable->StartPtr = GetStartPointer (VariableStoreHeader);
421 IndexTable->EndPtr = GetEndPointer (VariableStoreHeader);
422
423 //
424 // Start Pointers for the variable.
425 // Actual Data Pointer where data can be written.
426 //
427 Variable = IndexTable->StartPtr;
428 }
429 }
430 //
431 // Find the variable by walk through non-volatile variable store
432 //
433 PtrTrack->StartPtr = IndexTable->StartPtr;
434 PtrTrack->EndPtr = IndexTable->EndPtr;
435
436 while (IsValidVariableHeader (Variable) && (Variable <= IndexTable->EndPtr)) {
437 if (Variable->State == VAR_ADDED) {
438 //
439 // Record Variable in VariableIndex HOB
440 //
441 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME)
442 {
443 VariableIndexTableUpdate (IndexTable, Variable);
444 }
445
446 if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
447 return EFI_SUCCESS;
448 }
449 }
450
451 Variable = GetNextVariablePtr (Variable);
452 }
453 //
454 // If gone through the VariableStore, that means we never find in Firmware any more.
455 //
456 if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) {
457 IndexTable->GoneThrough = 1;
458 }
459
460 PtrTrack->CurrPtr = NULL;
461
462 return EFI_NOT_FOUND;
463 }
464
465 EFI_STATUS
466 EFIAPI
467 PeiGetVariable (
468 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
469 IN CONST CHAR16 *VariableName,
470 IN CONST EFI_GUID *VariableGuid,
471 OUT UINT32 *Attributes,
472 IN OUT UINTN *DataSize,
473 OUT VOID *Data
474 )
475 /*++
476
477 Routine Description:
478
479 Provide the read variable functionality of the variable services.
480
481 Arguments:
482
483 PeiServices - General purpose services available to every PEIM.
484
485 VariableName - The variable name
486
487 VendorGuid - The vendor's GUID
488
489 Attributes - Pointer to the attribute
490
491 DataSize - Size of data
492
493 Data - Pointer to data
494
495 Returns:
496
497 EFI_SUCCESS - The interface could be successfully installed
498
499 EFI_NOT_FOUND - The variable could not be discovered
500
501 EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough
502
503 --*/
504 {
505 VARIABLE_POINTER_TRACK Variable;
506 UINTN VarDataSize;
507 EFI_STATUS Status;
508 EFI_PEI_SERVICES **PeiServices;
509
510 PeiServices = GetPeiServicesTablePointer ();
511 if (VariableName == NULL || VariableGuid == NULL) {
512 return EFI_INVALID_PARAMETER;
513 }
514 //
515 // Find existing variable
516 //
517 Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);
518 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
519 return Status;
520 }
521 //
522 // Get data size
523 //
524 VarDataSize = DataSizeOfVariable (Variable.CurrPtr);
525 if (*DataSize >= VarDataSize) {
526 (*PeiServices)->CopyMem (Data, GET_VARIABLE_DATA_PTR (Variable.CurrPtr), VarDataSize);
527
528 if (Attributes != NULL) {
529 *Attributes = Variable.CurrPtr->Attributes;
530 }
531
532 *DataSize = VarDataSize;
533 return EFI_SUCCESS;
534 } else {
535 *DataSize = VarDataSize;
536 return EFI_BUFFER_TOO_SMALL;
537 }
538 }
539
540 EFI_STATUS
541 EFIAPI
542 PeiGetNextVariableName (
543 IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
544 IN OUT UINTN *VariableNameSize,
545 IN OUT CHAR16 *VariableName,
546 IN OUT EFI_GUID *VariableGuid
547 )
548 /*++
549
550 Routine Description:
551
552 Provide the get next variable functionality of the variable services.
553
554 Arguments:
555
556 PeiServices - General purpose services available to every PEIM.
557 VariabvleNameSize - The variable name's size.
558 VariableName - A pointer to the variable's name.
559 VariableGuid - A pointer to the EFI_GUID structure.
560
561 VariableNameSize - Size of the variable name
562
563 VariableName - The variable name
564
565 VendorGuid - The vendor's GUID
566
567 Returns:
568
569 EFI_SUCCESS - The interface could be successfully installed
570
571 EFI_NOT_FOUND - The variable could not be discovered
572
573 --*/
574 {
575 VARIABLE_POINTER_TRACK Variable;
576 UINTN VarNameSize;
577 EFI_STATUS Status;
578 EFI_PEI_SERVICES **PeiServices;
579
580 PeiServices = GetPeiServicesTablePointer ();
581 if (VariableName == NULL) {
582 return EFI_INVALID_PARAMETER;
583 }
584
585 Status = FindVariable (PeiServices, VariableName, VariableGuid, &Variable);
586 if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
587 return Status;
588 }
589
590 if (VariableName[0] != 0) {
591 //
592 // If variable name is not NULL, get next variable
593 //
594 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
595 }
596
597 while (!(Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL)) {
598 if (IsValidVariableHeader (Variable.CurrPtr)) {
599 if (Variable.CurrPtr->State == VAR_ADDED) {
600 ASSERT (NameSizeOfVariable (Variable.CurrPtr) != 0);
601
602 VarNameSize = (UINTN) NameSizeOfVariable (Variable.CurrPtr);
603 if (VarNameSize <= *VariableNameSize) {
604 (*PeiServices)->CopyMem (VariableName, GET_VARIABLE_NAME_PTR (Variable.CurrPtr), VarNameSize);
605
606 (*PeiServices)->CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));
607
608 Status = EFI_SUCCESS;
609 } else {
610 Status = EFI_BUFFER_TOO_SMALL;
611 }
612
613 *VariableNameSize = VarNameSize;
614 return Status;
615 //
616 // Variable is found
617 //
618 } else {
619 Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
620 }
621 } else {
622 break;
623 }
624 }
625
626 return EFI_NOT_FOUND;
627 }