]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/ConfigAccess.c
Add in some features for the thunk layer:
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / ConfigAccess.c
CommitLineData
ebbd2793 1/**@file\r
2 This file contains functions related to Config Access Protocols installed by\r
3 by HII Thunk Modules which is used to thunk UEFI Config Access Callback to \r
4 Framework HII Callback.\r
5 \r
6Copyright (c) 2008, Intel Corporation\r
7All rights reserved. This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "HiiDatabase.h"\r
18\r
19HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE ConfigAccessProtocolInstanceTempate = {\r
20 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_SIGNATURE,\r
21 {\r
22 ThunkExtractConfig,\r
23 ThunkRouteConfig,\r
24 ThunkCallback\r
25 }, //ConfigAccessProtocol\r
26 NULL, //FrameworkFormCallbackProtocol\r
27 {NULL, NULL} //ConfigAccessStorageListHead\r
28};\r
29\r
30EFI_HII_PACKAGE_HEADER *\r
31GetIfrFormSet (\r
32 IN CONST EFI_HII_PACKAGES *Packages\r
33 )\r
34{\r
35 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;\r
36 EFI_HII_PACKAGE_HEADER *IfrPackage;\r
37 UINTN Index;\r
38\r
39 ASSERT (Packages != NULL);\r
40\r
41 IfrPackage = NULL;\r
42\r
43 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));\r
44 for (Index = 0; Index < Packages->NumberOfPackages; Index++) {\r
45 //\r
46 // BugBug: The current UEFI HII build tool generate a binary in the format defined in: \r
47 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in\r
48 // this binary is with same package type. So the returned IfrPackNum and StringPackNum\r
49 // may not be the exact number of valid package number in the binary generated \r
50 // by HII Build tool.\r
51 //\r
52 switch (TianoAutogenPackageHdrArray[Index]->PackageHeader.Type) {\r
53 case EFI_HII_PACKAGE_FORM:\r
54 return &TianoAutogenPackageHdrArray[Index]->PackageHeader;\r
55 break;\r
56\r
57 case EFI_HII_PACKAGE_STRINGS:\r
58 case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
59 break;\r
60\r
61 //\r
62 // The following fonts are invalid for a module that using Framework to UEFI thunk layer.\r
63 //\r
64 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
65 case EFI_HII_PACKAGE_FONTS:\r
66 case EFI_HII_PACKAGE_IMAGES:\r
67 default:\r
68 ASSERT (FALSE);\r
69 break;\r
70 }\r
71 }\r
72\r
73 return (EFI_HII_PACKAGE_HEADER *) NULL;\r
74}\r
75\r
76EFI_STATUS\r
77GetBufferStorage (\r
78 IN CONST EFI_HII_PACKAGE_HEADER *FormSetPackage,\r
79 OUT LIST_ENTRY *BufferStorageListHead\r
80 )\r
81{\r
82 UINTN OpCodeOffset;\r
83 UINTN OpCodeLength;\r
84 UINT8 *OpCodeData;\r
85 UINT8 Operand;\r
86 EFI_IFR_VARSTORE *VarStoreOpCode;\r
87 HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey;\r
88\r
89 OpCodeOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
90 while (OpCodeOffset < FormSetPackage->Length) {\r
91 OpCodeData = (UINT8 *) FormSetPackage + OpCodeOffset;\r
92\r
93 OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
94 OpCodeOffset += OpCodeLength;\r
95 Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
96\r
97 if (Operand == EFI_IFR_VARSTORE_OP) {\r
98 VarStoreOpCode = (EFI_IFR_VARSTORE *)OpCodeData;\r
99 BufferStorageKey = AllocateZeroPool (sizeof (*BufferStorageKey));\r
100 if (BufferStorageKey == NULL) {\r
101 return EFI_OUT_OF_RESOURCES;\r
102 }\r
103 CopyGuid (&BufferStorageKey->Guid, &VarStoreOpCode->Guid);\r
104\r
105 BufferStorageKey->Name = AllocateZeroPool (AsciiStrSize (VarStoreOpCode->Name) * 2);\r
106 AsciiStrToUnicodeStr (VarStoreOpCode->Name, BufferStorageKey->Name);\r
107\r
108 BufferStorageKey->VarStoreId = VarStoreOpCode->VarStoreId;\r
109\r
110 BufferStorageKey->Size = VarStoreOpCode->Size;\r
111 BufferStorageKey->Signature = HII_TRHUNK_BUFFER_STORAGE_KEY_SIGNATURE;\r
112\r
113 InsertTailList (BufferStorageListHead, &BufferStorageKey->List);\r
114 }\r
115 }\r
116 return EFI_SUCCESS;\r
117}\r
118 \r
119\r
120EFI_STATUS\r
121InstallDefaultUefiConfigAccessProtocol (\r
122 IN CONST EFI_HII_PACKAGES *Packages,\r
123 OUT EFI_HANDLE *Handle,\r
124 IN OUT HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *MapEntry\r
125 )\r
126{\r
127 EFI_HII_PACKAGE_HEADER *FormSetPackage;\r
128 EFI_STATUS Status;\r
129 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigAccessInstance;\r
130\r
131 Status = HiiLibCreateHiiDriverHandle (Handle);\r
132 ConfigAccessInstance = AllocateCopyPool (\r
133 sizeof (HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE), \r
134 &ConfigAccessProtocolInstanceTempate\r
135 );\r
136 InitializeListHead (&ConfigAccessInstance->ConfigAccessBufferStorageListHead);\r
137\r
138 //\r
139 // We assume there is only one formset package in each Forms Package\r
140 //\r
141 FormSetPackage = GetIfrFormSet (Packages);\r
142 Status = GetBufferStorage (FormSetPackage, &ConfigAccessInstance->ConfigAccessBufferStorageListHead);\r
143 if (EFI_ERROR (Status)) {\r
144 FreePool (ConfigAccessInstance);\r
145 ASSERT (FALSE);\r
146 return Status;\r
147 }\r
148\r
149 Status = gBS->InstallMultipleProtocolInterfaces (\r
150 Handle,\r
151 &gEfiHiiConfigAccessProtocolGuid,\r
152 &ConfigAccessInstance->ConfigAccessProtocol,\r
153 NULL\r
154 );\r
155 ASSERT_EFI_ERROR (Status);\r
156 if (EFI_ERROR (Status)) {\r
157 FreePool (ConfigAccessInstance);\r
158 return Status;\r
159 }\r
160 \r
161 return EFI_SUCCESS;\r
162}\r
163\r
164EFI_STATUS\r
165RouteConfigToFrameworkFormCallBack (\r
166 IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
167 IN EFI_FORM_CALLBACK_PROTOCOL *FrameworkFormCallBack,\r
168 IN VOID *Data,\r
169 IN UINTN DataSize\r
170 )\r
171{\r
172 EFI_STATUS Status;\r
173 BOOLEAN ResetRequired;\r
174\r
175 Status = FrameworkFormCallBack->NvWrite (\r
176 FrameworkFormCallBack, \r
177 BufferStorageKey->Name,\r
178 &BufferStorageKey->Guid,\r
179 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
180 DataSize,\r
181 Data,\r
182 &ResetRequired\r
183 );\r
184 return Status;\r
185}\r
186\r
187EFI_STATUS\r
188ExtractConfigFromFrameworkFormCallBack (\r
189 IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
190 IN EFI_FORM_CALLBACK_PROTOCOL *FrameworkFormCallBack,\r
191 OUT VOID **Data,\r
192 OUT UINTN *DataSize\r
193 )\r
194{\r
195 EFI_STATUS Status;\r
196\r
197 *DataSize = 0;\r
198 *Data = NULL;\r
199 \r
200 Status = FrameworkFormCallBack->NvRead (\r
201 FrameworkFormCallBack, \r
202 BufferStorageKey->Name,\r
203 &BufferStorageKey->Guid,\r
204 NULL,\r
205 DataSize,\r
206 *Data\r
207 );\r
208 if (Status == EFI_BUFFER_TOO_SMALL) {\r
209 if (BufferStorageKey->Size != *DataSize) {\r
210 ASSERT (FALSE);\r
211 return EFI_INVALID_PARAMETER;\r
212 }\r
213\r
214 *Data = AllocateZeroPool (*DataSize);\r
215 if (Data == NULL) {\r
216 return EFI_OUT_OF_RESOURCES;\r
217 }\r
218\r
219 FrameworkFormCallBack->NvRead (\r
220 FrameworkFormCallBack, \r
221 BufferStorageKey->Name,\r
222 &BufferStorageKey->Guid,\r
223 NULL,\r
224 DataSize,\r
225 *Data\r
226 );\r
227 }\r
228\r
229 return Status;\r
230}\r
231\r
232EFI_STATUS\r
233RouteConfigToUefiVariable (\r
234 IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
235 IN VOID *Data,\r
236 IN UINTN DataSize\r
237 )\r
238{\r
239 return gRT->SetVariable (\r
240 BufferStorageKey->Name,\r
241 &BufferStorageKey->Guid,\r
242 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
243 DataSize,\r
244 Data\r
245 );\r
246 \r
247}\r
248EFI_STATUS\r
249ExtractConfigFromUefiVariable (\r
250 IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
251 OUT VOID **Data,\r
252 OUT UINTN *DataSize\r
253 )\r
254{\r
255 EFI_STATUS Status;\r
256\r
257 *DataSize = 0;\r
258 *Data = NULL;\r
259 Status = gRT->GetVariable (\r
260 BufferStorageKey->Name,\r
261 &BufferStorageKey->Guid,\r
262 NULL,\r
263 DataSize,\r
264 *Data\r
265 );\r
266 if (Status == EFI_BUFFER_TOO_SMALL) {\r
267\r
268 if (BufferStorageKey->Size != *DataSize) {\r
269 ASSERT (FALSE);\r
270 return EFI_INVALID_PARAMETER;\r
271 }\r
272\r
273 *Data = AllocateZeroPool (*DataSize);\r
274 if (Data == NULL) {\r
275 return EFI_OUT_OF_RESOURCES;\r
276 }\r
277\r
278 Status = gRT->GetVariable (\r
279 BufferStorageKey->Name,\r
280 &BufferStorageKey->Guid,\r
281 NULL,\r
282 DataSize,\r
283 *Data\r
284 );\r
285 }\r
286\r
287 return Status;\r
288}\r
289\r
290\r
291EFI_STATUS\r
292EFIAPI\r
293ThunkExtractConfig (\r
294 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
295 IN CONST EFI_STRING Request,\r
296 OUT EFI_STRING *Progress,\r
297 OUT EFI_STRING *Results\r
298 )\r
299{\r
300 EFI_STATUS Status;\r
301 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigaAccessInstance;\r
302 LIST_ENTRY *ListEntry;\r
303 HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey;\r
304 VOID *Data;\r
305 UINTN DataSize;\r
306\r
307 Data = NULL;\r
308 ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
309\r
310 ListEntry = GetFirstNode (&ConfigaAccessInstance->ConfigAccessBufferStorageListHead);\r
311 if (ListEntry == NULL) {\r
312 ASSERT (FALSE);\r
313 return EFI_INVALID_PARAMETER;\r
314 }\r
315 \r
316 BufferStorageKey = HII_TRHUNK_BUFFER_STORAGE_KEY_FROM_LIST_ENTRY (ListEntry);\r
317\r
318 if (ConfigaAccessInstance->FrameworkFormCallbackProtocol == NULL ||\r
319 ConfigaAccessInstance->FrameworkFormCallbackProtocol->NvRead == NULL) {\r
320 Status = ExtractConfigFromUefiVariable (\r
321 BufferStorageKey,\r
322 &Data,\r
323 &DataSize\r
324 );\r
325 } else {\r
326 Status = ExtractConfigFromFrameworkFormCallBack (\r
327 BufferStorageKey,\r
328 ConfigaAccessInstance->FrameworkFormCallbackProtocol,\r
329 &Data,\r
330 &DataSize\r
331 );\r
332 }\r
333 \r
334 if (!EFI_ERROR (Status)) {\r
335 Status = mUefiConfigRoutingProtocol->BlockToConfig (\r
336 mUefiConfigRoutingProtocol,\r
337 Request,\r
338 Data,\r
339 DataSize,\r
340 Results,\r
341 Progress\r
342 );\r
343 }\r
344\r
345 SafeFreePool (Data);\r
346 return Status;\r
347}\r
348\r
349\r
350EFI_STATUS\r
351EFIAPI\r
352ThunkRouteConfig (\r
353 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
354 IN CONST EFI_STRING Configuration,\r
355 OUT EFI_STRING *Progress\r
356 )\r
357{\r
358 EFI_STATUS Status;\r
359 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigaAccessInstance;\r
360 LIST_ENTRY *ListEntry;\r
361 HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey;\r
362 VOID *Data;\r
363 UINTN DataSize;\r
364 UINTN LastModifiedByteIndex;\r
365\r
366 Data = NULL;\r
367 ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
368\r
369 ListEntry = GetFirstNode (&ConfigaAccessInstance->ConfigAccessBufferStorageListHead);\r
370 if (ListEntry == NULL) {\r
371 ASSERT (FALSE);\r
372 return EFI_INVALID_PARAMETER;\r
373 }\r
374\r
375 BufferStorageKey = HII_TRHUNK_BUFFER_STORAGE_KEY_FROM_LIST_ENTRY (ListEntry);\r
376\r
377 Data = AllocateZeroPool (BufferStorageKey->Size);\r
378 if (Data == NULL) {\r
379 return EFI_OUT_OF_RESOURCES;\r
380 }\r
381 Status = mUefiConfigRoutingProtocol->ConfigToBlock (\r
382 mUefiConfigRoutingProtocol,\r
383 Configuration,\r
384 Data,\r
385 &LastModifiedByteIndex,\r
386 Progress\r
387 );\r
388\r
389 if (EFI_ERROR (Status)) {\r
390 goto Done;\r
391 }\r
392\r
393 DataSize = BufferStorageKey->Size;\r
394 if (ConfigaAccessInstance->FrameworkFormCallbackProtocol == NULL ||\r
395 ConfigaAccessInstance->FrameworkFormCallbackProtocol->NvRead == NULL) {\r
396 Status = RouteConfigToUefiVariable (\r
397 BufferStorageKey,\r
398 Data,\r
399 DataSize\r
400 );\r
401 } else {\r
402 Status = RouteConfigToFrameworkFormCallBack (\r
403 BufferStorageKey,\r
404 ConfigaAccessInstance->FrameworkFormCallbackProtocol,\r
405 Data,\r
406 DataSize\r
407 );\r
408 }\r
409\r
410Done: \r
411 SafeFreePool (Data);\r
412 return Status;\r
413}\r
414\r
415EFI_STATUS\r
416EFIAPI\r
417ThunkCallback (\r
418 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
419 IN EFI_BROWSER_ACTION Action,\r
420 IN EFI_QUESTION_ID QuestionId,\r
421 IN UINT8 Type,\r
422 IN EFI_IFR_TYPE_VALUE *Value,\r
423 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
424 )\r
425{\r
426 EFI_STATUS Status;\r
427 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigaAccessInstance;\r
428 EFI_FORM_CALLBACK_PROTOCOL *FrameworkFormCallbackProtocol;\r
429 EFI_HII_CALLBACK_PACKET *Packet;\r
430 FRAMEWORK_EFI_IFR_DATA_ARRAY Data;\r
431 FRAMEWORK_EFI_IFR_DATA_ENTRY *DataEntry;\r
432 EFI_FORM_CALLBACK Callback; \r
433\r
434 ASSERT (This != NULL);\r
435 ASSERT (Value != NULL);\r
436 ASSERT (ActionRequest != NULL);\r
437\r
438 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
439\r
440 ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
441\r
442 FrameworkFormCallbackProtocol = ConfigaAccessInstance->FrameworkFormCallbackProtocol;\r
443 if (FrameworkFormCallbackProtocol == NULL) {\r
444 return EFI_UNSUPPORTED;\r
445 }\r
446 Callback = FrameworkFormCallbackProtocol->Callback;\r
447\r
448 Status = Callback (\r
449 FrameworkFormCallbackProtocol,\r
450 QuestionId,\r
451 &Data,\r
452 &Packet\r
453 );\r
454\r
455 //\r
456 // Callback require browser to perform action\r
457 //\r
458 if (Packet != NULL) {\r
459 if (Packet->DataArray.EntryCount == 1 && Packet->DataArray.NvRamMap == NULL) {\r
460 DataEntry = (FRAMEWORK_EFI_IFR_DATA_ENTRY *) ((UINT8 *) Packet + sizeof (FRAMEWORK_EFI_IFR_DATA_ARRAY));\r
461 switch (DataEntry->Flags) {\r
462 case EXIT_REQUIRED:\r
463 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
464 break;\r
465 case SAVE_REQUIRED:\r
466 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
467 break;\r
468 case RESET_REQUIRED:\r
469 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
470 break;\r
471 default:\r
472 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
473 break; \r
474 }\r
475 }\r
476 }\r
477 \r
478 return Status;\r
479}\r
480\r