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