VirtualBox

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

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

debug more later

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.5 KB
Line 
1/* $Id: InitVariable.c 44593 2013-02-08 05:28:02Z 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 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_GUID);
151 VBoxWriteNVRAMGuidParam(VendorGuid);
152 VBoxWriteNVRAMNameParam(VariableName);
153
154 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY);
155 if (u32Rc == EFI_VARIABLE_OP_STATUS_OK)
156 {
157 /*
158 * Check if we got enought space for the value.
159 */
160 UINT32 VarLen;
161 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE_LENGTH);
162 VarLen = ASMInU32(EFI_VARIABLE_OP);
163 LogFlowFuncMarkVar(*DataSize, "%d");
164 LogFlowFuncMarkVar(VarLen, "%d");
165 if ( VarLen <= *DataSize
166 && Data)
167 {
168 /*
169 * We do, then read it and, if requrest, the attribute.
170 */
171 *DataSize = VarLen;
172 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE);
173 VBoxReadNVRAM((UINT8 *)Data, VarLen);
174
175 if (Attributes)
176 {
177 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_ATTRIBUTE);
178 *Attributes = ASMInU32(EFI_VARIABLE_OP);
179 LogFlowFuncMarkVar(Attributes, "%x");
180 }
181
182 rc = EFI_SUCCESS;
183 }
184 else
185 {
186 *DataSize = VarLen;
187 rc = EFI_BUFFER_TOO_SMALL;
188 }
189 }
190 else
191 {
192 rc = EFI_NOT_FOUND;
193 }
194
195 LogFlowFuncLeaveRC(rc);
196 return rc;
197#endif
198}
199
200/**
201
202 This code Finds the Next available variable.
203
204 @param VariableNameSize Size of the variable name
205 @param VariableName Pointer to variable name
206 @param VendorGuid Variable Vendor Guid
207
208 @return EFI_INVALID_PARAMETER Invalid parameter
209 @return EFI_SUCCESS Find the specified variable
210 @return EFI_NOT_FOUND Not found
211 @return EFI_BUFFER_TO_SMALL DataSize is too small for the result
212
213**/
214EFI_STATUS
215EFIAPI
216RuntimeServiceGetNextVariableName (
217 IN OUT UINTN *VariableNameSize,
218 IN OUT CHAR16 *VariableName,
219 IN OUT EFI_GUID *VendorGuid
220 )
221{
222#ifndef VBOX
223 return EmuGetNextVariableName (
224 VariableNameSize,
225 VariableName,
226 VendorGuid,
227 &mVariableModuleGlobal->VariableGlobal[Physical]
228 );
229#else
230 uint32_t u32Rc;
231 EFI_STATUS rc;
232 LogFlowFuncEnter();
233
234 /*
235 * Tell DevEFI which the current variable is, then ask for the next one.
236 */
237 VBoxWriteNVRAMGuidParam(VendorGuid);
238 VBoxWriteNVRAMNameParam(VariableName);
239
240 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY);
241 //if (u32Rc == EFI_VARIABLE_OP_STATUS_OK) - debug
242 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY_NEXT);
243
244 if (u32Rc == EFI_VARIABLE_OP_STATUS_OK)
245 {
246 /*
247 * Output buffer check.
248 */
249 UINT32 cwcName;
250 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_LENGTH_UTF16);
251 cwcName = ASMInU32(EFI_VARIABLE_OP);
252 if (cwcName * 2 < *VariableNameSize) /* ASSUMES byte size is specified */
253 {
254 UINT32 i;
255
256 /*
257 * Read back the result.
258 */
259 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_GUID);
260 VBoxReadNVRAM((UINT8 *)VendorGuid, sizeof(EFI_GUID));
261
262 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_UTF16);
263 for (i = 0; i < cwcName; i++)
264 VariableName[i] = ASMInU16(EFI_VARIABLE_OP);
265 VariableName[i] = '\0';
266
267 *VariableNameSize = cwcName * 2;
268 rc = EFI_SUCCESS;
269 }
270 else
271 {
272 rc = EFI_BUFFER_TOO_SMALL;
273 *VariableNameSize = (cwcName + 1) * 2;
274 }
275 }
276 else
277 rc = EFI_NOT_FOUND; /* whatever */
278
279 LogFlowFuncLeaveRC(rc);
280 return rc;
281#endif
282}
283
284/**
285
286 This code sets variable in storage blocks (Volatile or Non-Volatile).
287
288 @param VariableName Name of Variable to be found
289 @param VendorGuid Variable vendor GUID
290 @param Attributes Attribute value of the variable found
291 @param DataSize Size of Data found. If size is less than the
292 data, this value contains the required size.
293 @param Data Data pointer
294
295 @return EFI_INVALID_PARAMETER Invalid parameter
296 @return EFI_SUCCESS Set successfully
297 @return EFI_OUT_OF_RESOURCES Resource not enough to set variable
298 @return EFI_NOT_FOUND Not found
299 @return EFI_WRITE_PROTECTED Variable is read-only
300
301**/
302EFI_STATUS
303EFIAPI
304RuntimeServiceSetVariable (
305 IN CHAR16 *VariableName,
306 IN EFI_GUID *VendorGuid,
307 IN UINT32 Attributes,
308 IN UINTN DataSize,
309 IN VOID *Data
310 )
311{
312#ifndef VBOX
313 return EmuSetVariable (
314 VariableName,
315 VendorGuid,
316 Attributes,
317 DataSize,
318 Data,
319 &mVariableModuleGlobal->VariableGlobal[Physical],
320 &mVariableModuleGlobal->VolatileLastVariableOffset,
321 &mVariableModuleGlobal->NonVolatileLastVariableOffset
322 );
323#else
324 UINT32 u32Rc;
325 LogFlowFuncEnter();
326 LogFlowFuncMarkVar(VendorGuid, "%g");
327 LogFlowFuncMarkVar(VariableName, "%s");
328 LogFlowFuncMarkVar(DataSize, "%d");
329 /* set guid */
330 VBoxWriteNVRAMGuidParam(VendorGuid);
331 /* set name */
332 VBoxWriteNVRAMNameParam(VariableName);
333 /* set attribute */
334 VBoxWriteNVRAMU32Param(EFI_VM_VARIABLE_OP_ATTRIBUTE, Attributes);
335 /* set value length */
336 VBoxWriteNVRAMU32Param(EFI_VM_VARIABLE_OP_VALUE_LENGTH, DataSize);
337 /* fill value bytes */
338 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE);
339 VBoxWriteNVRAMByteArrayParam(Data, DataSize);
340 /* start fetch operation */
341 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_ADD);
342 /* process errors */
343 LogFlowFuncLeave();
344 switch (u32Rc)
345 {
346 case EFI_VARIABLE_OP_STATUS_OK:
347 return EFI_SUCCESS;
348 case EFI_VARIABLE_OP_STATUS_NOT_WP:
349 default:
350 return EFI_WRITE_PROTECTED;
351 }
352#endif
353}
354
355/**
356
357 This code returns information about the EFI variables.
358
359 @param Attributes Attributes bitmask to specify the type of variables
360 on which to return information.
361 @param MaximumVariableStorageSize Pointer to the maximum size of the storage space available
362 for the EFI variables associated with the attributes specified.
363 @param RemainingVariableStorageSize Pointer to the remaining size of the storage space available
364 for EFI variables associated with the attributes specified.
365 @param MaximumVariableSize Pointer to the maximum size of an individual EFI variables
366 associated with the attributes specified.
367
368 @return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
369 @return EFI_SUCCESS Query successfully.
370 @return EFI_UNSUPPORTED The attribute is not supported on this platform.
371
372**/
373EFI_STATUS
374EFIAPI
375RuntimeServiceQueryVariableInfo (
376 IN UINT32 Attributes,
377 OUT UINT64 *MaximumVariableStorageSize,
378 OUT UINT64 *RemainingVariableStorageSize,
379 OUT UINT64 *MaximumVariableSize
380 )
381{
382#ifndef VBOX
383 return EmuQueryVariableInfo (
384 Attributes,
385 MaximumVariableStorageSize,
386 RemainingVariableStorageSize,
387 MaximumVariableSize,
388 &mVariableModuleGlobal->VariableGlobal[Physical]
389 );
390#else
391 *MaximumVariableStorageSize = 64 * 1024 * 1024;
392 *MaximumVariableSize = 1024;
393 *RemainingVariableStorageSize = 32 * 1024 * 1024;
394 return EFI_SUCCESS;
395#endif
396}
397
398/**
399 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
400
401 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
402 It convers pointer to new virtual address.
403
404 @param Event Event whose notification function is being invoked.
405 @param Context Pointer to the notification function's context.
406
407**/
408VOID
409EFIAPI
410VariableClassAddressChangeEvent (
411 IN EFI_EVENT Event,
412 IN VOID *Context
413 )
414{
415#ifndef VBOX
416 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);
417 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);
418 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);
419 EfiConvertPointer (
420 0x0,
421 (VOID **) &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase
422 );
423 EfiConvertPointer (
424 0x0,
425 (VOID **) &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase
426 );
427 EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
428#endif
429}
430
431/**
432 EmuVariable Driver main entry point. The Variable driver places the 4 EFI
433 runtime services in the EFI System Table and installs arch protocols
434 for variable read and write services being available. It also registers
435 notification function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
436
437 @param[in] ImageHandle The firmware allocated handle for the EFI image.
438 @param[in] SystemTable A pointer to the EFI System Table.
439
440 @retval EFI_SUCCESS Variable service successfully initialized.
441
442**/
443EFI_STATUS
444EFIAPI
445VariableServiceInitialize (
446 IN EFI_HANDLE ImageHandle,
447 IN EFI_SYSTEM_TABLE *SystemTable
448 )
449{
450 EFI_HANDLE NewHandle;
451 EFI_STATUS Status;
452
453 Status = VariableCommonInitialize (ImageHandle, SystemTable);
454 ASSERT_EFI_ERROR (Status);
455
456 SystemTable->RuntimeServices->GetVariable = RuntimeServiceGetVariable;
457 SystemTable->RuntimeServices->GetNextVariableName = RuntimeServiceGetNextVariableName;
458 SystemTable->RuntimeServices->SetVariable = RuntimeServiceSetVariable;
459 SystemTable->RuntimeServices->QueryVariableInfo = RuntimeServiceQueryVariableInfo;
460
461 //
462 // Now install the Variable Runtime Architectural Protocol on a new handle
463 //
464 NewHandle = NULL;
465 Status = gBS->InstallMultipleProtocolInterfaces (
466 &NewHandle,
467 &gEfiVariableArchProtocolGuid,
468 NULL,
469 &gEfiVariableWriteArchProtocolGuid,
470 NULL,
471 NULL
472 );
473 ASSERT_EFI_ERROR (Status);
474
475 Status = gBS->CreateEventEx (
476 EVT_NOTIFY_SIGNAL,
477 TPL_NOTIFY,
478 VariableClassAddressChangeEvent,
479 NULL,
480 &gEfiEventVirtualAddressChangeGuid,
481 &mVirtualAddressChangeEvent
482 );
483 ASSERT_EFI_ERROR (Status);
484
485 /* Self Test */
486 {
487 EFI_GUID TestUUID = {0xe660597e, 0xb94d, 0x4209, {0x9c, 0x80, 0x18, 0x05, 0xb5, 0xd1, 0x9b, 0x69}};
488 const char *pszVariable0 = "This is test!!!";
489 const CHAR16 *pszVariable1 = L"This is test!!!";
490 char szTestVariable[512];
491#if 0
492 rc = runtime->SetVariable(&TestUUID,
493 NULL ,
494 (EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS| EFI_VARIABLE_RUNTIME_ACCESS),
495 0,
496 NULL );
497 ASSERT(rc == EFI_INVALID_PARAMETER);
498#endif
499 UINTN size = sizeof(szTestVariable),
500 rc = RuntimeServiceSetVariable(
501 L"Test0" ,
502 &TestUUID,
503 (EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS| EFI_VARIABLE_RUNTIME_ACCESS),
504 AsciiStrSize(pszVariable0),
505 (void *)pszVariable0);
506 ASSERT_EFI_ERROR(rc);
507 SetMem(szTestVariable, 512, 0);
508 rc = RuntimeServiceGetVariable(
509 L"Test0" ,
510 &TestUUID,
511 NULL,
512 &size,
513 (void *)szTestVariable);
514 LogFlowFuncMarkVar(szTestVariable, "%a");
515
516 ASSERT(CompareMem(szTestVariable, pszVariable0, size) == 0);
517
518 rc = RuntimeServiceSetVariable(
519 L"Test1" ,
520 &TestUUID,
521 (EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS| EFI_VARIABLE_RUNTIME_ACCESS),
522 StrSize(pszVariable1),
523 (void *)pszVariable1);
524 ASSERT_EFI_ERROR(rc);
525 SetMem(szTestVariable, 512, 0);
526 size = StrSize(pszVariable1);
527 rc = RuntimeServiceGetVariable(
528 L"Test1" ,
529 &TestUUID,
530 NULL,
531 &size,
532 (void *)szTestVariable);
533 LogFlowFuncMarkVar((CHAR16 *)szTestVariable, "%s");
534 ASSERT(CompareMem(szTestVariable, pszVariable1, size) == 0);
535 }
536
537 return EFI_SUCCESS;
538}
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