]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Forms.c
1) Add in IfrParser so that the FrameworkHii->GetDefaultImage can scan UEFI IFR opcod...
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / Forms.c
1 /**@file
2 This file contains the form processing code to the HII database.
3
4 Copyright (c) 2006 - 2008 Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include "HiiDatabase.h"
17 #include "UefiIfrDefault.h"
18
19 EFI_STATUS
20 EFIAPI
21 HiiExportDatabase (
22 IN EFI_HII_PROTOCOL *This,
23 IN FRAMEWORK_EFI_HII_HANDLE Handle,
24 IN OUT UINTN *BufferSize,
25 OUT VOID *Buffer
26 )
27 /*++
28
29 Routine Description:
30
31 This function allows a program to extract a form or form package that has
32 previously been registered with the EFI HII database.
33
34 Arguments:
35
36 Returns:
37
38 --*/
39 {
40 ASSERT (FALSE);
41 return EFI_UNSUPPORTED;
42 }
43
44 EFI_STATUS
45 EFIAPI
46 HiiGetForms (
47 IN EFI_HII_PROTOCOL *This,
48 IN FRAMEWORK_EFI_HII_HANDLE Handle,
49 IN EFI_FORM_ID FormId,
50 IN OUT UINTN *BufferLengthTemp,
51 OUT UINT8 *Buffer
52 )
53 /*++
54
55 Routine Description:
56
57 This function allows a program to extract a form or form package that has
58 previously been registered with the EFI HII database.
59
60 Arguments:
61 This - A pointer to the EFI_HII_PROTOCOL instance.
62
63 Handle - Handle on which the form resides. Type FRAMEWORK_EFI_HII_HANDLE is defined in
64 EFI_HII_PROTOCOL.NewPack() in the Packages section.
65
66 FormId - The ID of the form to return. If the ID is zero, the entire form package is returned.
67 Type EFI_FORM_ID is defined in "Related Definitions" below.
68
69 BufferLength - On input, the length of the Buffer. On output, the length of the returned buffer, if
70 the length was sufficient and, if it was not, the length that is required to fit the
71 requested form(s).
72
73 Buffer - The buffer designed to receive the form(s).
74
75 Returns:
76
77 EFI_SUCCESS - Buffer filled with the requested forms. BufferLength
78 was updated.
79
80 EFI_INVALID_PARAMETER - The handle is unknown.
81
82 EFI_NOT_FOUND - A form on the requested handle cannot be found with the
83 requested FormId.
84
85 EFI_BUFFER_TOO_SMALL - The buffer provided was not large enough to allow the form to be stored.
86
87 --*/
88 {
89 ASSERT (FALSE);
90 return EFI_UNSUPPORTED;
91 }
92
93
94 EFI_STATUS
95 EFIAPI
96 HiiGetDefaultImage (
97 IN EFI_HII_PROTOCOL *This,
98 IN FRAMEWORK_EFI_HII_HANDLE Handle,
99 IN UINTN DefaultMask,
100 OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
101 )
102 /*++
103
104 Routine Description:
105
106 This function allows a program to extract the NV Image
107 that represents the default storage image
108
109 Arguments:
110 This - A pointer to the EFI_HII_PROTOCOL instance.
111 Handle - The HII handle from which will have default data retrieved.
112 UINTN - Mask used to retrieve the default image.
113 VariablePackList - Callee allocated, tightly-packed, link list data
114 structure that contain all default varaible packs
115 from the Hii Database.
116
117 Returns:
118 EFI_NOT_FOUND - If Hii database does not contain any default images.
119 EFI_INVALID_PARAMETER - Invalid input parameter.
120 EFI_SUCCESS - Operation successful.
121
122 --*/
123 {
124 LIST_ENTRY *UefiDefaults;
125 EFI_HII_HANDLE UefiHiiHandle;
126 EFI_STATUS Status;
127 EFI_HII_THUNK_PRIVATE_DATA *Private;
128
129 Private = EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
130
131 UefiHiiHandle = FrameworkHiiHandleToUefiHiiHandle (Private, Handle);
132 if (UefiHiiHandle == NULL) {
133 ASSERT (FALSE);
134 return EFI_INVALID_PARAMETER;
135 }
136
137 UefiDefaults = NULL;
138 Status = UefiIfrGetBufferTypeDefaults (UefiHiiHandle, &UefiDefaults);
139 if (EFI_ERROR (Status)) {
140 goto Done;
141 }
142
143 Status = UefiDefaultsToFrameworkDefaults (UefiDefaults, DefaultMask, VariablePackList);
144
145 Done:
146 FreeDefaultList (UefiDefaults);
147
148 return Status;
149 }
150
151 EFI_STATUS
152 ThunkUpdateFormCallBack (
153 IN EFI_HANDLE CallbackHandle,
154 IN CONST HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry
155 )
156 {
157 EFI_STATUS Status;
158 EFI_FORM_CALLBACK_PROTOCOL *FrameworkFormCallbackProtocol;
159 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccessProtocol;
160 EFI_HANDLE UefiDriverHandle;
161 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigAccessProtocolInstance;
162
163 Status = gBS->HandleProtocol (
164 CallbackHandle,
165 &gEfiFormCallbackProtocolGuid,
166 (VOID **) &FrameworkFormCallbackProtocol
167 );
168 if (EFI_ERROR (Status)) {
169 return EFI_INVALID_PARAMETER;
170 }
171
172 Status = mHiiDatabase->GetPackageListHandle (
173 mHiiDatabase,
174 HandleMapEntry->UefiHiiHandle,
175 &UefiDriverHandle
176 );
177 ASSERT_EFI_ERROR (Status);
178 Status = gBS->HandleProtocol (
179 UefiDriverHandle,
180 &gEfiHiiConfigAccessProtocolGuid,
181 (VOID **) &ConfigAccessProtocol
182 );
183 ASSERT_EFI_ERROR (Status);
184
185 ConfigAccessProtocolInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (ConfigAccessProtocol);
186
187 ConfigAccessProtocolInstance->FrameworkFormCallbackProtocol = FrameworkFormCallbackProtocol;
188
189 return EFI_SUCCESS;
190 }
191
192 #define LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL 0x1000
193
194 EFI_STATUS
195 AppendToUpdateBuffer (
196 IN CONST UINT8 *OpCodeBuf,
197 IN UINTN BufSize,
198 OUT EFI_HII_UPDATE_DATA *UefiData
199 )
200 {
201 UINT8 * NewBuff;
202
203 if (UefiData->Offset + BufSize > UefiData->BufferSize) {
204 NewBuff = AllocateCopyPool (UefiData->BufferSize + LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL, UefiData->Data);
205 if (NewBuff == NULL) {
206 return EFI_OUT_OF_RESOURCES;
207 }
208 UefiData->BufferSize += LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL;
209 FreePool (UefiData->Data);
210 UefiData->Data = NewBuff;
211 }
212
213 CopyMem (UefiData->Data + UefiData->Offset, OpCodeBuf, BufSize);
214 UefiData->Offset += (UINT32) BufSize;
215
216 return EFI_SUCCESS;
217 }
218
219 EFI_STATUS
220 F2UCreateSubtitleOpCode (
221 IN CONST FRAMEWORK_EFI_IFR_SUBTITLE *FwSubTitle,
222 OUT EFI_HII_UPDATE_DATA *UefiData
223 )
224 {
225 EFI_IFR_SUBTITLE USubTitle;
226
227 ZeroMem (&USubTitle, sizeof(USubTitle));
228
229 USubTitle.Header.OpCode = EFI_IFR_SUBTITLE_OP;
230 USubTitle.Header.Length = sizeof (EFI_IFR_SUBTITLE);
231
232 USubTitle.Statement.Prompt = FwSubTitle->SubTitle;
233
234 return AppendToUpdateBuffer ((UINT8 *)&USubTitle, sizeof(EFI_IFR_SUBTITLE), UefiData);
235 }
236
237 EFI_STATUS
238 F2UCreateTextOpCode (
239 IN CONST FRAMEWORK_EFI_IFR_TEXT *FwText,
240 OUT EFI_HII_UPDATE_DATA *UefiData
241 )
242 {
243 EFI_IFR_TEXT UText;
244
245 ZeroMem (&UText, sizeof(UText));
246
247 UText.Header.OpCode = EFI_IFR_TEXT_OP;
248 UText.Header.Length = sizeof (EFI_IFR_TEXT);
249
250 UText.Statement.Help = FwText->Help;
251
252 UText.Statement.Prompt = FwText->Text;
253 UText.TextTwo = FwText->TextTwo;
254
255 return AppendToUpdateBuffer ((UINT8 *) &UText, sizeof(EFI_IFR_TEXT), UefiData);
256 }
257
258
259 EFI_STATUS
260 ThunkFrameworkUpdateDataToUefiUpdateData (
261 IN CONST FRAMEWORK_EFI_HII_UPDATE_DATA *Data,
262 IN BOOLEAN AddData,
263 OUT EFI_HII_UPDATE_DATA **UefiData
264 )
265 {
266 FRAMEWORK_EFI_IFR_OP_HEADER *FrameworkOpcodeBuffer;
267 EFI_HII_UPDATE_DATA *UefiUpdateDataBuffer;
268 UINTN Index;
269 EFI_STATUS Status;
270
271 UefiUpdateDataBuffer = AllocateZeroPool (sizeof (EFI_HII_UPDATE_DATA));
272 if (UefiUpdateDataBuffer == NULL) {
273 return EFI_OUT_OF_RESOURCES;
274 }
275
276 UefiUpdateDataBuffer->Data = AllocateZeroPool (LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL);
277 if (UefiUpdateDataBuffer->Data == NULL) {
278 return EFI_OUT_OF_RESOURCES;
279 }
280
281 UefiUpdateDataBuffer->BufferSize = LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL;
282 UefiUpdateDataBuffer->Offset = 0;
283
284 FrameworkOpcodeBuffer = (FRAMEWORK_EFI_IFR_OP_HEADER *) &Data->Data;
285
286 for (Index = 0; Index < Data->DataCount; Index++) {
287 switch (FrameworkOpcodeBuffer->OpCode) {
288 case FRAMEWORK_EFI_IFR_SUBTITLE_OP:
289 Status = F2UCreateSubtitleOpCode ((FRAMEWORK_EFI_IFR_SUBTITLE *) FrameworkOpcodeBuffer, UefiUpdateDataBuffer);
290 break;
291
292 case FRAMEWORK_EFI_IFR_TEXT_OP:
293 Status = F2UCreateTextOpCode ((FRAMEWORK_EFI_IFR_TEXT *) FrameworkOpcodeBuffer, UefiUpdateDataBuffer);
294 break;
295
296 default:
297 ASSERT (FALSE);
298 return EFI_UNSUPPORTED;
299 }
300
301 if (EFI_ERROR (Status)) {
302 FreePool (UefiUpdateDataBuffer->Data);
303 FreePool (UefiUpdateDataBuffer);
304 return Status;
305 }
306
307 FrameworkOpcodeBuffer = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FrameworkOpcodeBuffer + FrameworkOpcodeBuffer->Length);
308 }
309
310 *UefiData = UefiUpdateDataBuffer;
311
312 return EFI_SUCCESS;
313 }
314
315 STATIC
316 EFI_STATUS
317 GetPackageDataFromPackageList (
318 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
319 IN UINT32 PackageIndex,
320 OUT UINT32 *BufferLen,
321 OUT EFI_HII_PACKAGE_HEADER **Buffer
322 )
323 {
324 UINT32 Index;
325 EFI_HII_PACKAGE_HEADER *Package;
326 UINT32 Offset;
327 UINT32 PackageListLength;
328 EFI_HII_PACKAGE_HEADER PackageHeader = {0, 0};
329
330 ASSERT(HiiPackageList != NULL);
331
332 if ((BufferLen == NULL) || (Buffer == NULL)) {
333 return EFI_INVALID_PARAMETER;
334 }
335
336 Package = NULL;
337 Index = 0;
338 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
339 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
340 while (Offset < PackageListLength) {
341 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
342 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
343 if (Index == PackageIndex) {
344 break;
345 }
346 Offset += PackageHeader.Length;
347 Index++;
348 }
349 if (Offset >= PackageListLength) {
350 //
351 // no package found in this Package List
352 //
353 return EFI_NOT_FOUND;
354 }
355
356 *BufferLen = PackageHeader.Length;
357 *Buffer = Package;
358 return EFI_SUCCESS;
359 }
360
361 /**
362 Check if Label exist in the IFR form package.
363
364 @param
365
366 **/
367 EFI_STATUS
368 LocateLabel (
369 IN CONST EFI_HII_PACKAGE_HEADER *Package,
370 IN EFI_FORM_LABEL Label,
371 OUT EFI_GUID *FormsetGuid,
372 OUT EFI_FORM_ID *FormId
373 )
374 {
375 UINTN Offset;
376 EFI_IFR_OP_HEADER *IfrOpHdr;
377 UINT8 ExtendOpCode;
378 UINT16 LabelNumber;
379 EFI_GUID InternalFormSetGuid;
380 EFI_FORM_ID InternalFormId;
381 BOOLEAN GetFormSet;
382 BOOLEAN GetForm;
383
384 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
385 Offset = sizeof (EFI_HII_PACKAGE_HEADER);
386
387 InternalFormId= 0;
388 ZeroMem (&InternalFormSetGuid, sizeof (EFI_GUID));
389 GetFormSet = FALSE;
390 GetForm = FALSE;
391
392 while (Offset < Package->Length) {
393 switch (IfrOpHdr->OpCode) {
394 case EFI_IFR_FORM_SET_OP :
395 CopyMem (&InternalFormSetGuid, &((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, sizeof (EFI_GUID));
396 GetFormSet = TRUE;
397 break;
398
399 case EFI_IFR_FORM_OP:
400 CopyMem (&InternalFormId, &((EFI_IFR_FORM *) IfrOpHdr)->FormId, sizeof (EFI_FORM_ID));
401 GetForm = TRUE;
402 break;
403
404 case EFI_IFR_GUID_OP :
405 ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;
406
407 if (ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) {
408 //
409 // Go to the next Op-Code
410 //
411 Offset += IfrOpHdr->Length;
412 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
413 continue;
414 }
415
416 CopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16));
417 if (LabelNumber == Label) {
418 ASSERT (GetForm && GetFormSet);
419 CopyGuid (FormsetGuid, &InternalFormSetGuid);
420 *FormId = InternalFormId;
421 return EFI_SUCCESS;
422 }
423
424
425 break;
426 default :
427 break;
428 }
429
430 //
431 // Go to the next Op-Code
432 //
433 Offset += IfrOpHdr->Length;
434 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
435 }
436
437 return EFI_NOT_FOUND;
438 }
439
440 /**
441 Find the first EFI_FORM_LABEL in FormSets for a given EFI_HII_HANLDE defined.
442
443 EFI_FORM_LABEL is a specific to Tiano implementation. The current implementation
444 does not restrict labels with same label value to be duplicated in either FormSet
445 scope or Form scope. This function will only locate the FIRST EFI_FORM_LABEL
446 with value as the same as the input Label in the Formset registered with UefiHiiHandle. The FormSet GUID
447 and Form ID is returned if such Label is found.
448
449
450 @retval EFI_INVALID_PARAMETER If UefiHiiHandle is not a valid handle.
451 @retval EFI_NOT_FOUND The package list identified by UefiHiiHandle deos not contain FormSet or
452 There is no Form ID with value Label found in all Form Sets in the pacakge
453 list.
454
455 @retval EFI_SUCCESS The first found Form ID is returned in FormId.
456 **/
457 EFI_STATUS
458 ThunkLocateFormId (
459 IN EFI_HII_HANDLE Handle,
460 IN EFI_FORM_LABEL Label,
461 OUT EFI_GUID *FormsetGuid,
462 OUT EFI_FORM_ID *FormId
463 )
464 {
465 EFI_STATUS Status;
466 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
467 UINT32 Index;
468 UINTN BufferSize;
469 EFI_HII_PACKAGE_HEADER PackageHeader;
470 EFI_HII_PACKAGE_HEADER *Package;
471 UINT32 PackageLength;
472
473 BufferSize = 0;
474 HiiPackageList = NULL;
475 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
476 if (Status == EFI_BUFFER_TOO_SMALL) {
477 HiiPackageList = AllocatePool (BufferSize);
478 ASSERT (HiiPackageList != NULL);
479
480 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
481 if (EFI_ERROR (Status)) {
482 goto Done;
483 }
484 }
485
486 for (Index = 0; ; Index++) {
487 Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package);
488 if (!EFI_ERROR (Status)) {
489 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
490 if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
491 Status = LocateLabel (Package, Label, FormsetGuid, FormId);
492 if (!EFI_ERROR(Status)) {
493 break;
494 }
495 }
496 } else {
497 break;
498 }
499 }
500
501
502 Done:
503 FreePool (HiiPackageList);
504
505 return Status;
506 }
507 EFI_STATUS
508 EFIAPI
509 HiiUpdateForm (
510 IN EFI_HII_PROTOCOL *This,
511 IN FRAMEWORK_EFI_HII_HANDLE Handle,
512 IN EFI_FORM_LABEL Label,
513 IN BOOLEAN AddData,
514 IN FRAMEWORK_EFI_HII_UPDATE_DATA *Data
515 )
516 /*++
517
518 Routine Description:
519 This function allows the caller to update a form that has
520 previously been registered with the EFI HII database.
521
522 Arguments:
523 Handle - Hii Handle associated with the Formset to modify
524 Label - Update information starting immediately after this label in the IFR
525 AddData - If TRUE, add data. If FALSE, remove data
526 Data - If adding data, this is the pointer to the data to add
527
528 Returns:
529 EFI_SUCCESS - Update success.
530 Other - Update fail.
531
532 --*/
533 {
534 EFI_STATUS Status;
535 EFI_HII_THUNK_PRIVATE_DATA *Private;
536 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry;
537 EFI_HII_UPDATE_DATA *UefiHiiUpdateData;
538 EFI_HII_HANDLE UefiHiiHandle;
539 EFI_GUID FormsetGuid;
540 EFI_FORM_ID FormId;
541
542 Status = EFI_SUCCESS;
543
544 Private = EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
545
546 HandleMapEntry = FrameworkHiiHandleToMapDatabaseEntry (Private, Handle);
547
548 if (HandleMapEntry == NULL) {
549 return EFI_NOT_FOUND;
550 }
551
552 if (Data->FormSetUpdate) {
553 Status = ThunkUpdateFormCallBack ((EFI_HANDLE) (UINTN) Data->FormCallbackHandle, HandleMapEntry);
554 if (EFI_ERROR (Status)) {
555 return Status;
556 }
557 }
558
559 if (Data->DataCount != 0) {
560 if (HandleMapEntry->IsPackageListWithOnlyStringPackages) {
561 UefiHiiHandle = TagGuidToUefiIfrHiiHandle (Private, &HandleMapEntry->TagGuid);
562
563 if (UefiHiiHandle == NULL) {
564 return EFI_INVALID_PARAMETER;
565 }
566 } else {
567 UefiHiiHandle = HandleMapEntry->UefiHiiHandle;
568 }
569
570 UefiHiiUpdateData = NULL;
571
572 ThunkFrameworkUpdateDataToUefiUpdateData (Data, AddData, &UefiHiiUpdateData);
573
574 Status = ThunkLocateFormId (UefiHiiHandle, Label, &FormsetGuid, &FormId);
575 ASSERT_EFI_ERROR (Status);
576
577 Status = IfrLibUpdateForm (UefiHiiHandle, &FormsetGuid, FormId, Label, AddData, UefiHiiUpdateData);
578 ASSERT_EFI_ERROR (Status);
579
580 if (UefiHiiUpdateData != NULL) {
581 SafeFreePool (UefiHiiUpdateData->Data);
582 SafeFreePool (UefiHiiUpdateData);
583 }
584 }
585
586 return Status;
587 }