VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware2/VBoxPkg/VBoxVariable/InitVariable.c@ 46284

Last change on this file since 46284 was 44611, checked in by vboxsync, 12 years ago

InitVariable.c: Removed debug code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.9 KB
Line 
1/* $Id: InitVariable.c 44611 2013-02-09 13:17:44Z vboxsync $ */
2/** @file
3 * InitVariable.h
4 */
5
6/*
7 * Copyright (C) 2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/** @file
19
20 Implment all four UEFI runtime variable services and
21 install variable architeture protocol.
22
23Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
24This program and the accompanying materials
25are licensed and made available under the terms and conditions of the BSD License
26which accompanies this distribution. The full text of the license may be found at
27http://opensource.org/licenses/bsd-license.php
28
29THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
30WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
31
32**/
33
34#include "Variable.h"
35
36
37EFI_EVENT mVirtualAddressChangeEvent = NULL;
38
39#ifdef VBOX
40# include <Library/PrintLib.h>
41# include <Library/TimerLib.h>
42# include "VBoxPkg.h"
43# include "DevEFI.h"
44# include "iprt/asm.h"
45
46
47static UINT32 VBoxReadNVRAM(UINT8 *pu8Buffer, UINT32 cbBuffer)
48{
49 UINT32 idxBuffer = 0;
50 for (idxBuffer = 0; idxBuffer < cbBuffer; ++idxBuffer)
51 pu8Buffer[idxBuffer] = ASMInU8(EFI_VARIABLE_OP);
52 return idxBuffer;
53}
54
55static inline void VBoxWriteNVRAMU32Param(UINT32 u32CodeParam, UINT32 u32Param)
56{
57 ASMOutU32(EFI_VARIABLE_OP, u32CodeParam);
58 ASMOutU32(EFI_VARIABLE_PARAM, u32Param);
59}
60
61static UINT32 VBoxWriteNVRAMByteArrayParam(const UINT8 *pbParam, UINT32 cbParam)
62{
63 UINT32 idxParam = 0;
64 for (idxParam = 0; idxParam < cbParam; ++idxParam)
65 ASMOutU8(EFI_VARIABLE_PARAM, pbParam[idxParam]);
66 return idxParam;
67}
68
69static void VBoxWriteNVRAMNameParam(const CHAR16 *pwszName)
70{
71 UINT32 i;
72 UINT32 cwcName = StrLen(pwszName);
73
74 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_UTF16);
75 for (i = 0; i <= cwcName; i++)
76 ASMOutU16(EFI_VARIABLE_PARAM, pwszName[i]);
77}
78
79static inline UINT32 VBoxWriteNVRAMGuidParam(const EFI_GUID *pGuid)
80{
81 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_GUID);
82 return VBoxWriteNVRAMByteArrayParam((UINT8 *)pGuid, sizeof(EFI_GUID));
83}
84
85static UINT32 VBoxWriteNVRAMDoOp(UINT32 u32Operation)
86{
87 UINT32 u32Rc;
88 LogFlowFuncEnter();
89 LogFlowFuncMarkVar(u32Operation, "%x");
90 VBoxWriteNVRAMU32Param(EFI_VM_VARIABLE_OP_START, u32Operation);
91
92 while ((u32Rc = ASMInU32(EFI_VARIABLE_OP)) == EFI_VARIABLE_OP_STATUS_BSY)
93 {
94#if 0
95 MicroSecondDelay (400);
96#endif
97 /* @todo: sleep here. bird: won't ever happen, so don't bother. */
98 }
99 LogFlowFuncMarkVar(u32Rc, "%x");
100 LogFlowFuncLeave();
101 return u32Rc;
102}
103#endif
104
105/**
106
107 This code finds variable in storage blocks (Volatile or Non-Volatile).
108
109 @param VariableName Name of Variable to be found.
110 @param VendorGuid Variable vendor GUID.
111 @param Attributes Attribute value of the variable found.
112 @param DataSize Size of Data found. If size is less than the
113 data, this value contains the required size.
114 @param Data Data pointer.
115
116 @return EFI_INVALID_PARAMETER Invalid parameter
117 @return EFI_SUCCESS Find the specified variable
118 @return EFI_NOT_FOUND Not found
119 @return EFI_BUFFER_TO_SMALL DataSize is too small for the result
120
121**/
122EFI_STATUS
123EFIAPI
124RuntimeServiceGetVariable (
125 IN CHAR16 *VariableName,
126 IN EFI_GUID *VendorGuid,
127 OUT UINT32 *Attributes OPTIONAL,
128 IN OUT UINTN *DataSize,
129 OUT VOID *Data
130 )
131{
132#ifndef VBOX
133 return EmuGetVariable (
134 VariableName,
135 VendorGuid,
136 Attributes OPTIONAL,
137 DataSize,
138 Data,
139 &mVariableModuleGlobal->VariableGlobal[Physical]
140 );
141#else
142 EFI_STATUS rc;
143 UINT32 u32Rc;
144
145 LogFlowFuncEnter();
146
147 /*
148 * Tell DevEFI to look for the specified variable.
149 */
150 VBoxWriteNVRAMGuidParam(VendorGuid);
151 VBoxWriteNVRAMNameParam(VariableName);
152 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY);
153 if (u32Rc == EFI_VARIABLE_OP_STATUS_OK)
154 {
155 /*
156 * Check if we got enought space for the value.
157 */
158 UINT32 VarLen;
159 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE_LENGTH);
160 VarLen = ASMInU32(EFI_VARIABLE_OP);
161 LogFlowFuncMarkVar(*DataSize, "%d");
162 LogFlowFuncMarkVar(VarLen, "%d");
163 if ( VarLen <= *DataSize
164 && Data)
165 {
166 /*
167 * We do, then read it and, if requrest, the attribute.
168 */
169 *DataSize = VarLen;
170 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE);
171 VBoxReadNVRAM((UINT8 *)Data, VarLen);
172
173 if (Attributes)
174 {
175 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_ATTRIBUTE);
176 *Attributes = ASMInU32(EFI_VARIABLE_OP);
177 LogFlowFuncMarkVar(Attributes, "%x");
178 }
179
180 rc = EFI_SUCCESS;
181 }
182 else
183 {
184 *DataSize = VarLen;
185 rc = EFI_BUFFER_TOO_SMALL;
186 }
187 }
188 else
189 {
190 rc = EFI_NOT_FOUND;
191 }
192
193 LogFlowFuncLeaveRC(rc);
194 return rc;
195#endif
196}
197
198/**
199
200 This code Finds the Next available variable.
201
202 @param VariableNameSize Size of the variable name
203 @param VariableName Pointer to variable name
204 @param VendorGuid Variable Vendor Guid
205
206 @return EFI_INVALID_PARAMETER Invalid parameter
207 @return EFI_SUCCESS Find the specified variable
208 @return EFI_NOT_FOUND Not found
209 @return EFI_BUFFER_TO_SMALL DataSize is too small for the result
210
211**/
212EFI_STATUS
213EFIAPI
214RuntimeServiceGetNextVariableName (
215 IN OUT UINTN *VariableNameSize,
216 IN OUT CHAR16 *VariableName,
217 IN OUT EFI_GUID *VendorGuid
218 )
219{
220#ifndef VBOX
221 return EmuGetNextVariableName (
222 VariableNameSize,
223 VariableName,
224 VendorGuid,
225 &mVariableModuleGlobal->VariableGlobal[Physical]
226 );
227#else
228 uint32_t u32Rc;
229 EFI_STATUS rc;
230 LogFlowFuncEnter();
231
232 /*
233 * Validate inputs.
234 */
235 if (!VariableNameSize || !VariableName || !VendorGuid)
236 {
237 LogFlowFuncLeaveRC(EFI_INVALID_PARAMETER);
238 return EFI_INVALID_PARAMETER;
239 }
240
241 /*
242 * Tell DevEFI which the current variable is, then ask for the next one.
243 */
244 if (!VariableName[0])
245 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY_REWIND);
246 else
247 {
248 VBoxWriteNVRAMGuidParam(VendorGuid);
249 VBoxWriteNVRAMNameParam(VariableName);
250 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY);
251 }
252 if (u32Rc == EFI_VARIABLE_OP_STATUS_OK)
253 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY_NEXT);
254 /** @todo We're supposed to skip stuff depending on attributes and
255 * runtime/boottime, at least if EmuGetNextVariableName is something
256 * to go by... */
257
258 if (u32Rc == EFI_VARIABLE_OP_STATUS_OK)
259 {
260 /*
261 * Output buffer check.
262 */
263 UINT32 cwcName;
264 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_LENGTH_UTF16);
265 cwcName = ASMInU32(EFI_VARIABLE_OP);
266 if ((cwcName + 1) * 2 <= *VariableNameSize) /* ASSUMES byte size is specified */
267 {
268 UINT32 i;
269
270 /*
271 * Read back the result.
272 */
273 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_GUID);
274 VBoxReadNVRAM((UINT8 *)VendorGuid, sizeof(EFI_GUID));
275
276 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_UTF16);
277 for (i = 0; i < cwcName; i++)
278 VariableName[i] = ASMInU16(EFI_VARIABLE_OP);
279 VariableName[i] = '\0';
280
281 rc = EFI_SUCCESS;
282 }
283 else
284 rc = EFI_BUFFER_TOO_SMALL;
285 *VariableNameSize = (cwcName + 1) * 2;
286 }
287 else
288 rc = EFI_NOT_FOUND; /* whatever */
289
290 LogFlowFuncLeaveRC(rc);
291 return rc;
292#endif
293}
294
295/**
296
297 This code sets variable in storage blocks (Volatile or Non-Volatile).
298
299 @param VariableName Name of Variable to be found
300 @param VendorGuid Variable vendor GUID
301 @param Attributes Attribute value of the variable found
302 @param DataSize Size of Data found. If size is less than the
303 data, this value contains the required size.
304 @param Data Data pointer
305
306 @return EFI_INVALID_PARAMETER Invalid parameter
307 @return EFI_SUCCESS Set successfully
308 @return EFI_OUT_OF_RESOURCES Resource not enough to set variable
309 @return EFI_NOT_FOUND Not found
310 @return EFI_WRITE_PROTECTED Variable is read-only
311
312**/
313EFI_STATUS
314EFIAPI
315RuntimeServiceSetVariable (
316 IN CHAR16 *VariableName,
317 IN EFI_GUID *VendorGuid,
318 IN UINT32 Attributes,
319 IN UINTN DataSize,
320 IN VOID *Data
321 )
322{
323#ifndef VBOX
324 return EmuSetVariable (
325 VariableName,
326 VendorGuid,
327 Attributes,
328 DataSize,
329 Data,
330 &mVariableModuleGlobal->VariableGlobal[Physical],
331 &mVariableModuleGlobal->VolatileLastVariableOffset,
332 &mVariableModuleGlobal->NonVolatileLastVariableOffset
333 );
334#else
335 UINT32 u32Rc;
336 LogFlowFuncEnter();
337 LogFlowFuncMarkVar(VendorGuid, "%g");
338 LogFlowFuncMarkVar(VariableName, "%s");
339 LogFlowFuncMarkVar(DataSize, "%d");
340 /* set guid */
341 VBoxWriteNVRAMGuidParam(VendorGuid);
342 /* set name */
343 VBoxWriteNVRAMNameParam(VariableName);
344 /* set attribute */
345 VBoxWriteNVRAMU32Param(EFI_VM_VARIABLE_OP_ATTRIBUTE, Attributes);
346 /* set value length */
347 VBoxWriteNVRAMU32Param(EFI_VM_VARIABLE_OP_VALUE_LENGTH, DataSize);
348 /* fill value bytes */
349 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE);
350 VBoxWriteNVRAMByteArrayParam(Data, DataSize);
351 /* start fetch operation */
352 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_ADD);
353 /* process errors */
354 LogFlowFuncLeave();
355 switch (u32Rc)
356 {
357 case EFI_VARIABLE_OP_STATUS_OK:
358 return EFI_SUCCESS;
359 case EFI_VARIABLE_OP_STATUS_NOT_WP:
360 default:
361 return EFI_WRITE_PROTECTED;
362 }
363#endif
364}
365
366/**
367
368 This code returns information about the EFI variables.
369
370 @param Attributes Attributes bitmask to specify the type of variables
371 on which to return information.
372 @param MaximumVariableStorageSize Pointer to the maximum size of the storage space available
373 for the EFI variables associated with the attributes specified.
374 @param RemainingVariableStorageSize Pointer to the remaining size of the storage space available
375 for EFI variables associated with the attributes specified.
376 @param MaximumVariableSize Pointer to the maximum size of an individual EFI variables
377 associated with the attributes specified.
378
379 @return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
380 @return EFI_SUCCESS Query successfully.
381 @return EFI_UNSUPPORTED The attribute is not supported on this platform.
382
383**/
384EFI_STATUS
385EFIAPI
386RuntimeServiceQueryVariableInfo (
387 IN UINT32 Attributes,
388 OUT UINT64 *MaximumVariableStorageSize,
389 OUT UINT64 *RemainingVariableStorageSize,
390 OUT UINT64 *MaximumVariableSize
391 )
392{
393#ifndef VBOX
394 return EmuQueryVariableInfo (
395 Attributes,
396 MaximumVariableStorageSize,
397 RemainingVariableStorageSize,
398 MaximumVariableSize,
399 &mVariableModuleGlobal->VariableGlobal[Physical]
400 );
401#else
402 *MaximumVariableStorageSize = 64 * 1024 * 1024;
403 *MaximumVariableSize = 1024;
404 *RemainingVariableStorageSize = 32 * 1024 * 1024;
405 return EFI_SUCCESS;
406#endif
407}
408
409/**
410 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
411
412 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
413 It convers pointer to new virtual address.
414
415 @param Event Event whose notification function is being invoked.
416 @param Context Pointer to the notification function's context.
417
418**/
419VOID
420EFIAPI
421VariableClassAddressChangeEvent (
422 IN EFI_EVENT Event,
423 IN VOID *Context
424 )
425{
426#ifndef VBOX
427 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);
428 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);
429 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);
430 EfiConvertPointer (
431 0x0,
432 (VOID **) &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase
433 );
434 EfiConvertPointer (
435 0x0,
436 (VOID **) &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase
437 );
438 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
439#endif
440}
441
442/**
443 EmuVariable Driver main entry point. The Variable driver places the 4 EFI
444 runtime services in the EFI System Table and installs arch protocols
445 for variable read and write services being available. It also registers
446 notification function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
447
448 @param[in] ImageHandle The firmware allocated handle for the EFI image.
449 @param[in] SystemTable A pointer to the EFI System Table.
450
451 @retval EFI_SUCCESS Variable service successfully initialized.
452
453**/
454EFI_STATUS
455EFIAPI
456VariableServiceInitialize (
457 IN EFI_HANDLE ImageHandle,
458 IN EFI_SYSTEM_TABLE *SystemTable
459 )
460{
461 EFI_HANDLE NewHandle;
462 EFI_STATUS Status;
463
464 Status = VariableCommonInitialize (ImageHandle, SystemTable);
465 ASSERT_EFI_ERROR (Status);
466
467 SystemTable->RuntimeServices->GetVariable = RuntimeServiceGetVariable;
468 SystemTable->RuntimeServices->GetNextVariableName = RuntimeServiceGetNextVariableName;
469 SystemTable->RuntimeServices->SetVariable = RuntimeServiceSetVariable;
470 SystemTable->RuntimeServices->QueryVariableInfo = RuntimeServiceQueryVariableInfo;
471
472 //
473 // Now install the Variable Runtime Architectural Protocol on a new handle
474 //
475 NewHandle = NULL;
476 Status = gBS->InstallMultipleProtocolInterfaces (
477 &NewHandle,
478 &gEfiVariableArchProtocolGuid,
479 NULL,
480 &gEfiVariableWriteArchProtocolGuid,
481 NULL,
482 NULL
483 );
484 ASSERT_EFI_ERROR (Status);
485
486 Status = gBS->CreateEventEx (
487 EVT_NOTIFY_SIGNAL,
488 TPL_NOTIFY,
489 VariableClassAddressChangeEvent,
490 NULL,
491 &gEfiEventVirtualAddressChangeGuid,
492 &mVirtualAddressChangeEvent
493 );
494 ASSERT_EFI_ERROR (Status);
495
496 /* Self Test */
497 {
498 EFI_GUID TestUUID = {0xe660597e, 0xb94d, 0x4209, {0x9c, 0x80, 0x18, 0x05, 0xb5, 0xd1, 0x9b, 0x69}};
499 const char *pszVariable0 = "This is test!!!";
500 const CHAR16 *pszVariable1 = L"This is test!!!";
501 char szTestVariable[512];
502#if 0
503 rc = runtime->SetVariable(&TestUUID,
504 NULL ,
505 (EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS| EFI_VARIABLE_RUNTIME_ACCESS),
506 0,
507 NULL );
508 ASSERT(rc == EFI_INVALID_PARAMETER);
509#endif
510 UINTN size = sizeof(szTestVariable),
511 rc = RuntimeServiceSetVariable(
512 L"Test0" ,
513 &TestUUID,
514 (EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS| EFI_VARIABLE_RUNTIME_ACCESS),
515 AsciiStrSize(pszVariable0),
516 (void *)pszVariable0);
517 ASSERT_EFI_ERROR(rc);
518 SetMem(szTestVariable, 512, 0);
519 rc = RuntimeServiceGetVariable(
520 L"Test0" ,
521 &TestUUID,
522 NULL,
523 &size,
524 (void *)szTestVariable);
525 LogFlowFuncMarkVar(szTestVariable, "%a");
526
527 ASSERT(CompareMem(szTestVariable, pszVariable0, size) == 0);
528
529 rc = RuntimeServiceSetVariable(
530 L"Test1" ,
531 &TestUUID,
532 (EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS| EFI_VARIABLE_RUNTIME_ACCESS),
533 StrSize(pszVariable1),
534 (void *)pszVariable1);
535 ASSERT_EFI_ERROR(rc);
536 SetMem(szTestVariable, 512, 0);
537 size = StrSize(pszVariable1);
538 rc = RuntimeServiceGetVariable(
539 L"Test1" ,
540 &TestUUID,
541 NULL,
542 &size,
543 (void *)szTestVariable);
544 LogFlowFuncMarkVar((CHAR16 *)szTestVariable, "%s");
545 ASSERT(CompareMem(szTestVariable, pszVariable1, size) == 0);
546 }
547
548 return EFI_SUCCESS;
549}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette