• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Variable services implemented from system memory
3 
4   There is just a single runtime memory buffer that contans all the data.
5 
6   Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
7   Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
8 
9   This program and the accompanying materials
10   are licensed and made available under the terms and conditions of the BSD License
11   which accompanies this distribution.  The full text of the license may be found at
12   http://opensource.org/licenses/bsd-license.php
13 
14   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 
17 
18 **/
19 
20 
21 UINT64    mMaximumVariableStorageSize;
22 UINT64    mRemainingVariableStorageSize;
23 UINT64    mMaximumVariableSize;
24 
25 typedef struct {
26   EFI_GUID        VendorGuid;
27   UINT32          Attribute;
28   UINTN           DataSize;
29 } VARIABLE_ARRAY_ENTRY;
30 // CHAR16         VariableName[]
31 // UINT8          Data[]
32 
33 VARIABLE_ARRAY_ENTRY  *mVariableArray         = NULL;
34 VARIABLE_ARRAY_ENTRY  *mVariableArrayNextFree = NULL;
35 VARIABLE_ARRAY_ENTRY  *mVariableArrayEnd      = NULL;
36 
37 
38 VARIABLE_ARRAY_ENTRY  *
AddEntry(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)39 AddEntry (
40   IN CHAR16        *VariableName,
41   IN EFI_GUID      *VendorGuid,
42   IN UINT32        Attributes,
43   IN UINTN         DataSize,
44   IN VOID          *Data
45   )
46 {
47   UINTN                   Size;
48   UINTN                   SizeOfString;
49   VARIABLE_ARRAY_ENTRY    *Entry;
50   EFI_TPL                 CurrentTpl;
51 
52 
53   SizeOfString = StrSize (VariableName);
54   Size = SizeOfString + sizeof (VARIABLE_ARRAY_ENTRY) + DataSize;
55   if ((VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + Size) > mVariableArrayEnd) {
56     // ran out of space
57     return NULL;
58   }
59 
60   if (!EfiAtRuntime ()) {
61     // Enter critical section
62     CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
63   }
64 
65   Entry = mVariableArrayNextFree;
66   CopyGuid (&Entry->VendorGuid, VendorGuid);
67   Entry->Attribute = Attributes;
68   Entry->DataSize = DataSize;
69   StrCpy ((CHAR16 *)++mVariableArrayNextFree, VariableName);
70   mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + SizeOfString);
71   CopyMem (mVariableArrayNextFree, Data, DataSize);
72   mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + DataSize);
73 
74   if (!EfiAtRuntime ()) {
75     // Exit Critical section
76     gBS->RestoreTPL (CurrentTpl);
77   }
78 
79   return Entry;
80 }
81 
82 VOID
DeleteEntry(IN VARIABLE_ARRAY_ENTRY * Entry)83 DeleteEntry (
84   IN  VARIABLE_ARRAY_ENTRY *Entry
85   )
86 {
87   UINTN       Size;
88   UINT8       *Data;
89   EFI_TPL     CurrentTpl;
90 
91   Size = StrSize ((CHAR16 *)(Entry + 1)) + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize;
92   Data = ((UINT8 *)Entry) + Size;
93 
94   CopyMem (Entry, Data, (UINTN)mVariableArrayNextFree - (UINTN)Data);
95 
96   if (!EfiAtRuntime ()) {
97     // Enter critical section
98     CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
99   }
100 
101   mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) - Size);
102 
103   if (!EfiAtRuntime ()) {
104     // Exit Critical section
105     gBS->RestoreTPL (CurrentTpl);
106   }
107 }
108 
109 
110 VARIABLE_ARRAY_ENTRY *
GetVariableArrayEntry(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,OUT VOID ** Data OPTIONAL)111 GetVariableArrayEntry (
112   IN CHAR16        *VariableName,
113   IN EFI_GUID      *VendorGuid,
114   OUT VOID         **Data          OPTIONAL
115   )
116 {
117   VARIABLE_ARRAY_ENTRY    *Entry;
118   UINTN                   Size;
119 
120   if (*VariableName == L'\0') {
121     // by definition first entry is null-terminated string
122     if (mVariableArray == mVariableArrayNextFree) {
123       return NULL;
124     }
125     return mVariableArray;
126   }
127 
128   for (Entry = mVariableArray; Entry < mVariableArrayEnd;) {
129     if (CompareGuid (VendorGuid, &Entry->VendorGuid)) {
130       if (StrCmp (VariableName, (CHAR16 *)(Entry + 1))) {
131         Size = StrSize ((CHAR16 *)(Entry + 1));
132         if (Data != NULL) {
133           *Data = (VOID *)(((UINT8 *)Entry) + (Size + sizeof (VARIABLE_ARRAY_ENTRY)));
134         }
135         return Entry;
136       }
137     }
138 
139     Size = StrSize ((CHAR16 *)(Entry + 1)) + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize;
140     Entry = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)Entry) + Size);
141   }
142 
143   return NULL;
144 }
145 
146 
147 EFI_STATUS
LibGetVariable(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,OUT UINT32 * Attributes OPTIONAL,IN OUT UINTN * DataSize,OUT VOID * Data)148 LibGetVariable (
149   IN CHAR16        *VariableName,
150   IN EFI_GUID      *VendorGuid,
151   OUT UINT32       *Attributes OPTIONAL,
152   IN OUT UINTN     *DataSize,
153   OUT VOID         *Data
154   )
155 {
156   VARIABLE_ARRAY_ENTRY    *Entry;
157   VOID                    *InternalData;
158 
159   if (EfiAtRuntime () && (Attributes != NULL)) {
160     if ((*Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) {
161       return EFI_NOT_FOUND;
162     }
163   }
164 
165   Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData);
166   if (Entry == NULL) {
167     return EFI_NOT_FOUND;
168   }
169 
170   if (*DataSize < Entry->DataSize) {
171     *DataSize = Entry->DataSize;
172     return EFI_BUFFER_TOO_SMALL;
173   }
174 
175   *DataSize = Entry->DataSize;
176   if (Attributes != NULL) {
177     *Attributes = Entry->Attribute;
178   }
179 
180   CopyMem (Data, InternalData, *DataSize);
181   return EFI_SUCCESS;
182 }
183 
184 
185 EFI_STATUS
LibGetNextVariableName(IN OUT UINTN * VariableNameSize,IN OUT CHAR16 * VariableName,IN OUT EFI_GUID * VendorGuid)186 LibGetNextVariableName (
187   IN OUT UINTN     *VariableNameSize,
188   IN OUT CHAR16    *VariableName,
189   IN OUT EFI_GUID  *VendorGuid
190   )
191 {
192   VARIABLE_ARRAY_ENTRY    *Entry;
193   VOID                    *InternalData;
194   UINTN                   StringSize;
195   BOOLEAN                 Done;
196 
197   for (Done = FALSE; !Done; ) {
198     Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData);
199     if (Entry == NULL) {
200       return EFI_NOT_FOUND;
201     }
202 
203     // If we are at runtime skip variables that do not have the Runitme attribute set.
204     Done = (EfiAtRuntime () && ((Entry->Attribute & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) ? FALSE : TRUE;
205   }
206 
207   StringSize = StrSize ((CHAR16 *)(Entry + 1));
208   Entry = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)Entry) + (StringSize + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize));
209   if (Entry >= mVariableArrayEnd) {
210     return EFI_NOT_FOUND;
211   }
212 
213   if (*VariableNameSize < StringSize) {
214     *VariableNameSize = StringSize;
215     return EFI_BUFFER_TOO_SMALL;
216   }
217 
218   *VariableNameSize = StringSize;
219   CopyMem (VariableName, (CHAR16 *)(Entry + 1), StringSize);
220   CopyMem (VendorGuid, &Entry->VendorGuid, sizeof (EFI_GUID));
221   return EFI_SUCCESS;
222 }
223 
224 
225 
226 EFI_STATUS
LibSetVariable(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)227 LibSetVariable (
228   IN CHAR16        *VariableName,
229   IN EFI_GUID      *VendorGuid,
230   IN UINT32        Attributes,
231   IN UINTN         DataSize,
232   IN VOID          *Data
233   )
234 {
235   VARIABLE_ARRAY_ENTRY    *Entry;
236   VOID                    *InternalData;
237 
238   if (EfiAtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
239     return EFI_NOT_FOUND;
240   }
241 
242   Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData);
243   if (Entry == NULL) {
244     if (DataSize == 0) {
245       return EFI_NOT_FOUND;
246     }
247     Entry = AddEntry (VariableName, VendorGuid, Attributes, DataSize, Data);
248     return (Entry == NULL) ? EFI_OUT_OF_RESOURCES : EFI_SUCCESS;
249 
250   } else if (DataSize == 0) {
251     // DataSize is zero so delete
252     DeleteEntry (Entry);
253   } else if (DataSize == Entry->DataSize) {
254     // No change is size so just update the store
255     Entry->Attribute |= Attributes;
256     CopyMem (InternalData, Data, DataSize);
257   } else {
258     // Grow the entry by deleting and adding back. Don't lose previous Attributes
259     Attributes |= Entry->Attribute;
260     DeleteEntry (Entry);
261     Entry = AddEntry (VariableName, VendorGuid, Attributes, DataSize, Data);
262     return (Entry == NULL) ? EFI_OUT_OF_RESOURCES : EFI_SUCCESS;
263   }
264 }
265 
266 
267 EFI_STATUS
LibQueryVariableInfo(IN UINT32 Attributes,OUT UINT64 * MaximumVariableStorageSize,OUT UINT64 * RemainingVariableStorageSize,OUT UINT64 * MaximumVariableSize)268 LibQueryVariableInfo (
269   IN  UINT32                 Attributes,
270   OUT UINT64                 *MaximumVariableStorageSize,
271   OUT UINT64                 *RemainingVariableStorageSize,
272   OUT UINT64                 *MaximumVariableSize
273   )
274 {
275   *MaximumVariableStorageSize   = mMaximumVariableStorageSize;
276   *RemainingVariableStorageSize = mRemainingVariableStorageSize;
277   *MaximumVariableStorageSize   = mRemainingVariableStorageSize;
278   return EFI_SUCCESS;
279 }
280 
281 
282 VOID
LibVariableVirtualAddressChangeEvent(VOID)283 LibVariableVirtualAddressChangeEvent (VOID)
284 {
285   EfiConvertPointer (0, (VOID **)&mVariableArray);
286   EfiConvertPointer (0, (VOID **)&mVariableArrayNextFree);
287   EfiConvertPointer (0, (VOID **)&mVariableArrayEnd);
288 }
289 
290 
291 VOID
LibVariableInitialize(VOID)292 LibVariableInitialize (VOID)
293 {
294   UINTN     Size;
295 
296   Size = PcdGet32 (PcdEmbeddedMemVariableStoreSize);
297   mVariableArray = mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)AllocateRuntimePool (Size);
298   ASSERT (mVariableArray != NULL);
299 
300   mVariableArrayEnd = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArray) + Size);
301 
302   mMaximumVariableStorageSize   = Size - sizeof (VARIABLE_ARRAY_ENTRY);
303   mRemainingVariableStorageSize = mMaximumVariableStorageSize;
304   mMaximumVariableSize          = mMaximumVariableStorageSize;
305 }
306 
307