]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c
d96a44304a3875a93d3c35f7b189ebf19685f5d2
[mirror_edk2.git] / EmbeddedPkg / Library / HalRuntimeServicesExampleLib / Variable.c
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<BR>
7 Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
8
9 All rights reserved. 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 *
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
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 *
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
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
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
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
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
283 LibVariableVirtualAddressChangeEvent (VOID)
284 {
285 EfiConvertPointer (0, (VOID **)&mVariableArray);
286 EfiConvertPointer (0, (VOID **)&mVariableArrayNextFree);
287 EfiConvertPointer (0, (VOID **)&mVariableArrayEnd);
288 }
289
290
291 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