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