VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c

Last change on this file was 105670, checked in by vboxsync, 7 months ago

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

  • Property svn:eol-style set to native
File size: 84.3 KB
Line 
1/** @file
2 The implementation of EDKII Redfish Platform Config Protocol.
3
4 (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
5 Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
6 Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10**/
11
12#include "RedfishPlatformConfigDxe.h"
13#include "RedfishPlatformConfigImpl.h"
14
15REDFISH_PLATFORM_CONFIG_PRIVATE *mRedfishPlatformConfigPrivate = NULL;
16
17/**
18 Create a new stack instance with given stack size.
19
20 @param[in] StackSize The size of stack.
21
22 @retval REDFISH_STACK * Pointer to created stack.
23 @retval NULL Out of resource.
24
25**/
26REDFISH_STACK *
27NewRedfishStack (
28 IN UINTN StackSize
29 )
30{
31 REDFISH_STACK *Buffer;
32
33 if (StackSize == 0) {
34 return NULL;
35 }
36
37 Buffer = AllocateZeroPool (sizeof (REDFISH_STACK));
38 if (Buffer == NULL) {
39 return NULL;
40 }
41
42 Buffer->Pool = AllocateZeroPool (sizeof (VOID *) * StackSize);
43 if (Buffer->Pool == NULL) {
44 FreePool (Buffer);
45 return NULL;
46 }
47
48 Buffer->Size = StackSize;
49 Buffer->Index = 0;
50
51 return Buffer;
52}
53
54/**
55 Release stack buffer.
56
57 @param[in] Stack Pointer to stack instance.
58
59**/
60VOID
61ReleaseRedfishStack (
62 IN REDFISH_STACK *Stack
63 )
64{
65 if (Stack == NULL) {
66 return;
67 }
68
69 FreePool (Stack->Pool);
70 FreePool (Stack);
71}
72
73/**
74 Check and see if stack is empty or not.
75
76 @param[in] Stack Pointer to stack instance.
77
78 @retval TRUE Stack is empty.
79 @retval FALSE Stack is not empty.
80
81**/
82BOOLEAN
83IsEmptyRedfishStack (
84 IN REDFISH_STACK *Stack
85 )
86{
87 return (Stack->Index == 0);
88}
89
90/**
91 Push an item to stack.
92
93 @param[in] Stack Pointer to stack instance.
94 @param[in] Data Pointer to data.
95
96 @retval EFI_OUT_OF_RESOURCES Stack is full.
97 @retval EFI_SUCCESS Item is pushed successfully.
98
99**/
100EFI_STATUS
101PushRedfishStack (
102 IN REDFISH_STACK *Stack,
103 IN VOID *Data
104 )
105{
106 if (Stack->Index == Stack->Size) {
107 return EFI_OUT_OF_RESOURCES;
108 }
109
110 Stack->Pool[Stack->Index] = Data;
111 Stack->Index += 1;
112
113 return EFI_SUCCESS;
114}
115
116/**
117 Pop an item from stack.
118
119 @param[in] Stack Pointer to stack instance.
120
121 @retval VOID * Pointer to popped item.
122 @retval NULL Stack is empty.
123
124**/
125VOID *
126PopRedfishStack (
127 IN REDFISH_STACK *Stack
128 )
129{
130 if (IsEmptyRedfishStack (Stack)) {
131 return NULL;
132 }
133
134 Stack->Index -= 1;
135 return Stack->Pool[Stack->Index];
136}
137
138/**
139 Seach forms in this HII package and find which form links to give form.
140
141 @param[in] FormPrivate Pointer to form private instance.
142
143 @retval REDFISH_PLATFORM_CONFIG_FORM_PRIVATE Pointer to target form
144 @retval NULL No form links to give form.
145
146**/
147REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *
148FindFormLinkToThis (
149 IN REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *FormPrivate
150 )
151{
152 LIST_ENTRY *HiiFormLink;
153 LIST_ENTRY *HiiNextFormLink;
154 REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate;
155 LIST_ENTRY *HiiStatementLink;
156 LIST_ENTRY *HiiNextStatementLink;
157 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate;
158 REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate;
159
160 if (FormPrivate == NULL) {
161 return NULL;
162 }
163
164 HiiFormsetPrivate = FormPrivate->ParentFormset;
165
166 if (IsListEmpty (&HiiFormsetPrivate->HiiFormList)) {
167 return NULL;
168 }
169
170 HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList);
171 while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) {
172 HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);
173 HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink);
174
175 //
176 // Skip myself
177 //
178 if (HiiFormPrivate == FormPrivate) {
179 HiiFormLink = HiiNextFormLink;
180 continue;
181 }
182
183 HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
184 while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
185 HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
186 HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);
187
188 //
189 // Check go-to opcode and find form ID. If form ID is the same ID as given form,
190 // this go-to opcode links to given form.
191 //
192 if ((HiiStatementPrivate->HiiStatement->Operand == EFI_IFR_REF_OP) &&
193 (HiiStatementPrivate->HiiStatement->Value.Value.ref.FormId == FormPrivate->HiiForm->FormId))
194 {
195 return HiiFormPrivate;
196 }
197
198 HiiStatementLink = HiiNextStatementLink;
199 }
200
201 HiiFormLink = HiiNextFormLink;
202 }
203
204 return NULL;
205}
206
207/**
208 Debug dump HII statement value.
209
210 @param[in] ErrorLevel DEBUG macro error level
211 @param[in] Value HII statement value to dump
212 @param[in] Message Debug message
213
214 @retval EFI_SUCCESS Dump HII statement value successfully
215 @retval Others Errors occur
216
217**/
218EFI_STATUS
219DumpHiiStatementValue (
220 IN UINTN ErrorLevel,
221 IN HII_STATEMENT_VALUE *Value,
222 IN CHAR8 *Message OPTIONAL
223 )
224{
225 UINT64 Data;
226
227 if (Value == NULL) {
228 return EFI_INVALID_PARAMETER;
229 }
230
231 switch (Value->Type) {
232 case EFI_IFR_TYPE_NUM_SIZE_8:
233 Data = Value->Value.u8;
234 break;
235 case EFI_IFR_TYPE_NUM_SIZE_16:
236 Data = Value->Value.u16;
237 break;
238 case EFI_IFR_TYPE_NUM_SIZE_32:
239 Data = Value->Value.u32;
240 break;
241 case EFI_IFR_TYPE_NUM_SIZE_64:
242 Data = Value->Value.u64;
243 break;
244 case EFI_IFR_TYPE_BOOLEAN:
245 Data = (Value->Value.b ? 1 : 0);
246 break;
247 default:
248 DEBUG ((ErrorLevel, "%a: unsupported type: 0x%x\n", __func__, Value->Type));
249 return EFI_UNSUPPORTED;
250 }
251
252 if (IS_EMPTY_STRING (Message)) {
253 DEBUG ((ErrorLevel, "0x%lx\n", Data));
254 } else {
255 DEBUG ((ErrorLevel, "%a: 0x%lx\n", Message, Data));
256 }
257
258 return EFI_SUCCESS;
259}
260
261/**
262 Debug dump HII statement prompt string.
263
264 @param[in] ErrorLevel DEBUG macro error level
265 @param[in] HiiHandle HII handle instance
266 @param[in] HiiStatement HII statement
267 @param[in] Message Debug message
268
269 @retval EFI_SUCCESS Dump HII statement string successfully
270 @retval Others Errors occur
271
272**/
273EFI_STATUS
274DumpHiiStatementPrompt (
275 IN UINTN ErrorLevel,
276 IN EFI_HII_HANDLE HiiHandle,
277 IN HII_STATEMENT *HiiStatement,
278 IN CHAR8 *Message OPTIONAL
279 )
280{
281 EFI_STRING String;
282
283 if ((HiiHandle == NULL) || (HiiStatement == NULL)) {
284 return EFI_INVALID_PARAMETER;
285 }
286
287 if (HiiStatement->Prompt == 0) {
288 return EFI_NOT_FOUND;
289 }
290
291 String = HiiGetString (HiiHandle, HiiStatement->Prompt, NULL);
292 if (String == NULL) {
293 return EFI_NOT_FOUND;
294 }
295
296 if (IS_EMPTY_STRING (Message)) {
297 DEBUG ((ErrorLevel, "%s\n", String));
298 } else {
299 DEBUG ((ErrorLevel, "%a: %s\n", Message, String));
300 }
301
302 FreePool (String);
303
304 return EFI_SUCCESS;
305}
306
307/**
308 Build the menu path to given statement instance. It is caller's
309 responsibility to free returned string buffer.
310
311 @param[in] StatementPrivate Pointer to statement private instance.
312
313 @retval CHAR8 * Menu path to given statement.
314 @retval NULL Can not find menu path.
315
316**/
317CHAR8 *
318BuildMenuPath (
319 IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *StatementPrivate
320 )
321{
322 REDFISH_STACK *FormStack;
323 REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *FormPrivate;
324 UINTN OldBufferSize;
325 UINTN NewBufferSize;
326 CHAR8 *Buffer;
327 CHAR8 *FormTitle;
328 EFI_STATUS Status;
329
330 Buffer = NULL;
331 OldBufferSize = 0;
332 NewBufferSize = 0;
333 FormStack = NewRedfishStack (REDFISH_MENU_PATH_SIZE);
334 if (FormStack == NULL) {
335 return NULL;
336 }
337
338 //
339 // Build form link stack
340 //
341 FormPrivate = StatementPrivate->ParentForm;
342 Status = PushRedfishStack (FormStack, (VOID *)FormPrivate);
343 if (EFI_ERROR (Status)) {
344 goto RELEASE;
345 }
346
347 do {
348 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "F(%d) <-", FormPrivate->Id));
349 FormPrivate = FindFormLinkToThis (FormPrivate);
350 if (FormPrivate == NULL) {
351 break;
352 }
353
354 PushRedfishStack (FormStack, (VOID *)FormPrivate);
355 if (EFI_ERROR (Status)) {
356 break;
357 }
358 } while (TRUE);
359
360 if (IsEmptyRedfishStack (FormStack)) {
361 goto RELEASE;
362 }
363
364 //
365 // Initial Buffer to empty string for error case.
366 //
367 OldBufferSize = AsciiStrSize ("");
368 Buffer = AllocateCopyPool (OldBufferSize, "");
369 if (Buffer == NULL) {
370 goto RELEASE;
371 }
372
373 //
374 // Build menu path in string format
375 //
376 FormPrivate = (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *)PopRedfishStack (FormStack);
377 while (FormPrivate != NULL) {
378 FormTitle = HiiGetEnglishAsciiString (FormPrivate->ParentFormset->HiiHandle, FormPrivate->Title);
379 if (FormTitle != NULL) {
380 NewBufferSize = AsciiStrSize (FormTitle) + OldBufferSize;
381 Buffer = ReallocatePool (OldBufferSize, NewBufferSize, Buffer);
382 if (Buffer == NULL) {
383 goto RELEASE;
384 }
385
386 OldBufferSize = NewBufferSize;
387 AsciiStrCatS (Buffer, OldBufferSize, "/");
388 AsciiStrCatS (Buffer, OldBufferSize, FormTitle);
389 FreePool (FormTitle);
390 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " %a\n", Buffer));
391 }
392
393 FormPrivate = (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *)PopRedfishStack (FormStack);
394 }
395
396RELEASE:
397
398 ReleaseRedfishStack (FormStack);
399
400 return Buffer;
401}
402
403/**
404 Get the attribute name from config language.
405
406 For example: /Bios/Attributes/BiosOption1 is config language
407 and attribute name is BiosOption1.
408
409 @param[in] ConfigLanguage Config language string.
410
411 @retval CHAR8 * Attribute name string.
412 @retval NULL Can not find attribute name.
413
414**/
415CHAR8 *
416GetAttributeNameFromConfigLanguage (
417 IN CHAR8 *ConfigLanguage
418 )
419{
420 CHAR8 *attributeName;
421 CHAR8 *Pointer;
422 UINTN StrLen;
423 UINTN Index;
424 UINTN AttrStrLen;
425
426 if (IS_EMPTY_STRING (ConfigLanguage)) {
427 return NULL;
428 }
429
430 attributeName = NULL;
431 Pointer = NULL;
432 AttrStrLen = 0;
433 StrLen = AsciiStrLen (ConfigLanguage);
434
435 if (ConfigLanguage[StrLen - 1] == '/') {
436 //
437 // wrong format
438 //
439 DEBUG ((DEBUG_ERROR, "%a: invalid format: %a\n", __func__, ConfigLanguage));
440 ASSERT (FALSE);
441 return NULL;
442 }
443
444 Index = StrLen;
445 while (TRUE) {
446 Index -= 1;
447
448 if (ConfigLanguage[Index] == '/') {
449 Pointer = &ConfigLanguage[Index + 1];
450 break;
451 }
452
453 if (Index == 0) {
454 break;
455 }
456 }
457
458 //
459 // Not found. There is no '/' in input string.
460 //
461 if (Pointer == NULL) {
462 return NULL;
463 }
464
465 AttrStrLen = StrLen - Index;
466 attributeName = AllocateCopyPool (AttrStrLen, Pointer);
467
468 return attributeName;
469}
470
471/**
472 Convert one-of options to string array in Redfish attribute.
473
474 @param[in] HiiHandle HII handle.
475 @param[in] SchemaName Schema string.
476 @param[in] StatementPrivate Pointer to statement instance.
477 @param[out] Values Attribute value array.
478
479 @retval EFI_SUCCESS Options are converted successfully.
480 @retval Other Error occurs.
481
482**/
483EFI_STATUS
484OneOfStatementToAttributeValues (
485 IN EFI_HII_HANDLE HiiHandle,
486 IN CHAR8 *SchemaName,
487 IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *StatementPrivate,
488 OUT EDKII_REDFISH_POSSIBLE_VALUES *Values
489 )
490{
491 LIST_ENTRY *Link;
492 HII_QUESTION_OPTION *Option;
493 UINTN Index;
494 HII_STATEMENT *HiiStatement;
495
496 if ((HiiHandle == NULL) || (StatementPrivate == NULL) || (Values == NULL)) {
497 return EFI_INVALID_PARAMETER;
498 }
499
500 HiiStatement = StatementPrivate->HiiStatement;
501 ASSERT (HiiStatement != NULL);
502
503 if (IsListEmpty (&HiiStatement->OptionListHead)) {
504 return EFI_NOT_FOUND;
505 }
506
507 //
508 // Loop through the option to get count
509 //
510 Values->ValueCount = 0;
511 Link = GetFirstNode (&HiiStatement->OptionListHead);
512 while (!IsNull (&HiiStatement->OptionListHead, Link)) {
513 Option = HII_QUESTION_OPTION_FROM_LINK (Link);
514
515 if ((Option->SuppressExpression != NULL) &&
516 (EvaluateExpressionList (Option->SuppressExpression, TRUE, StatementPrivate->ParentForm->ParentFormset->HiiFormSet, StatementPrivate->ParentForm->HiiForm) != ExpressFalse))
517 {
518 Link = GetNextNode (&HiiStatement->OptionListHead, Link);
519 continue;
520 }
521
522 Values->ValueCount += 1;
523 Link = GetNextNode (&HiiStatement->OptionListHead, Link);
524 }
525
526 Values->ValueArray = AllocateZeroPool (sizeof (EDKII_REDFISH_ATTRIBUTE_VALUE) * Values->ValueCount);
527 if (Values->ValueArray == NULL) {
528 Values->ValueCount = 0;
529 return EFI_OUT_OF_RESOURCES;
530 }
531
532 Index = 0;
533 Link = GetFirstNode (&HiiStatement->OptionListHead);
534 while (!IsNull (&HiiStatement->OptionListHead, Link)) {
535 Option = HII_QUESTION_OPTION_FROM_LINK (Link);
536
537 if ((Option->SuppressExpression != NULL) &&
538 (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))
539 {
540 Link = GetNextNode (&HiiStatement->OptionListHead, Link);
541 continue;
542 }
543
544 if (Option->Text != 0) {
545 Values->ValueArray[Index].ValueName = HiiGetRedfishAsciiString (HiiHandle, SchemaName, Option->Text);
546 Values->ValueArray[Index].ValueDisplayName = HiiGetEnglishAsciiString (HiiHandle, Option->Text);
547 }
548
549 Index += 1;
550 Link = GetNextNode (&HiiStatement->OptionListHead, Link);
551 }
552
553 return EFI_SUCCESS;
554}
555
556/**
557 Return Redfish attribute type from given HII statement operand.
558
559 @param[in] HiiStatement Target HII statement.
560
561 @retval EDKII_REDFISH_ATTRIBUTE_TYPES Attribute type.
562
563**/
564EDKII_REDFISH_ATTRIBUTE_TYPES
565HiiStatementToAttributeType (
566 IN HII_STATEMENT *HiiStatement
567 )
568{
569 EDKII_REDFISH_ATTRIBUTE_TYPES type;
570
571 if (HiiStatement == NULL) {
572 return RedfishAttributeTypeUnknown;
573 }
574
575 type = RedfishAttributeTypeUnknown;
576 switch (HiiStatement->Operand) {
577 case EFI_IFR_ONE_OF_OP:
578 case EFI_IFR_ORDERED_LIST_OP:
579 type = RedfishAttributeTypeEnumeration;
580 break;
581 case EFI_IFR_STRING_OP:
582 type = RedfishAttributeTypeString;
583 break;
584 case EFI_IFR_NUMERIC_OP:
585 type = RedfishAttributeTypeInteger;
586 break;
587 case EFI_IFR_CHECKBOX_OP:
588 type = RedfishAttributeTypeBoolean;
589 break;
590 case EFI_IFR_DATE_OP:
591 case EFI_IFR_TIME_OP:
592 default:
593 DEBUG ((DEBUG_ERROR, "%a: unsupported operand: 0x%x\n", __func__, HiiStatement->Operand));
594 break;
595 }
596
597 return type;
598}
599
600/**
601 Zero extend integer/boolean to UINT64 for comparing.
602
603 @param Value HII Value to be converted.
604
605**/
606UINT64
607ExtendHiiValueToU64 (
608 IN HII_STATEMENT_VALUE *Value
609 )
610{
611 UINT64 Temp;
612
613 Temp = 0;
614 switch (Value->Type) {
615 case EFI_IFR_TYPE_NUM_SIZE_8:
616 Temp = Value->Value.u8;
617 break;
618
619 case EFI_IFR_TYPE_NUM_SIZE_16:
620 Temp = Value->Value.u16;
621 break;
622
623 case EFI_IFR_TYPE_NUM_SIZE_32:
624 Temp = Value->Value.u32;
625 break;
626
627 case EFI_IFR_TYPE_BOOLEAN:
628 Temp = Value->Value.b;
629 break;
630
631 case EFI_IFR_TYPE_TIME:
632 case EFI_IFR_TYPE_DATE:
633 default:
634 break;
635 }
636
637 return Temp;
638}
639
640/**
641 Set value of a data element in an Array by its Index in ordered list buffer.
642
643 @param Array The data array.
644 @param Type Type of the data in this array.
645 @param Index Zero based index for data in this array.
646 @param Value The value to be set.
647
648**/
649VOID
650OrderedListSetArrayData (
651 IN VOID *Array,
652 IN UINT8 Type,
653 IN UINTN Index,
654 IN UINT64 Value
655 )
656{
657 ASSERT (Array != NULL);
658
659 switch (Type) {
660 case EFI_IFR_TYPE_NUM_SIZE_8:
661 *(((UINT8 *)Array) + Index) = (UINT8)Value;
662 break;
663
664 case EFI_IFR_TYPE_NUM_SIZE_16:
665 *(((UINT16 *)Array) + Index) = (UINT16)Value;
666 break;
667
668 case EFI_IFR_TYPE_NUM_SIZE_32:
669 *(((UINT32 *)Array) + Index) = (UINT32)Value;
670 break;
671
672 case EFI_IFR_TYPE_NUM_SIZE_64:
673 *(((UINT64 *)Array) + Index) = (UINT64)Value;
674 break;
675
676 default:
677 break;
678 }
679}
680
681/**
682 Return data element in an Array by its Index in ordered list array buffer.
683
684 @param Array The data array.
685 @param Type Type of the data in this array.
686 @param Index Zero based index for data in this array.
687
688 @retval Value The data to be returned
689
690**/
691UINT64
692OrderedListGetArrayData (
693 IN VOID *Array,
694 IN UINT8 Type,
695 IN UINTN Index
696 )
697{
698 UINT64 Data;
699
700 ASSERT (Array != NULL);
701
702 Data = 0;
703 switch (Type) {
704 case EFI_IFR_TYPE_NUM_SIZE_8:
705 Data = (UINT64)*(((UINT8 *)Array) + Index);
706 break;
707
708 case EFI_IFR_TYPE_NUM_SIZE_16:
709 Data = (UINT64)*(((UINT16 *)Array) + Index);
710 break;
711
712 case EFI_IFR_TYPE_NUM_SIZE_32:
713 Data = (UINT64)*(((UINT32 *)Array) + Index);
714 break;
715
716 case EFI_IFR_TYPE_NUM_SIZE_64:
717 Data = (UINT64)*(((UINT64 *)Array) + Index);
718 break;
719
720 default:
721 break;
722 }
723
724 return Data;
725}
726
727/**
728 Find string ID of option if its value equals to given value.
729
730 @param[in] HiiStatement Statement to search.
731 @param[in] Value Target value.
732
733 @retval EFI_SUCCESS HII value is returned successfully.
734 @retval Others Errors occur
735
736**/
737EFI_STRING_ID
738OrderedListOptionValueToStringId (
739 IN HII_STATEMENT *HiiStatement,
740 IN UINT64 Value
741 )
742{
743 LIST_ENTRY *Link;
744 HII_QUESTION_OPTION *Option;
745 UINT64 CurrentValue;
746
747 if (HiiStatement == NULL) {
748 return 0;
749 }
750
751 if (HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) {
752 return 0;
753 }
754
755 if (IsListEmpty (&HiiStatement->OptionListHead)) {
756 return 0;
757 }
758
759 Link = GetFirstNode (&HiiStatement->OptionListHead);
760 while (!IsNull (&HiiStatement->OptionListHead, Link)) {
761 Option = HII_QUESTION_OPTION_FROM_LINK (Link);
762
763 CurrentValue = ExtendHiiValueToU64 (&Option->Value);
764 if (Value == CurrentValue) {
765 return Option->Text;
766 }
767
768 Link = GetNextNode (&HiiStatement->OptionListHead, Link);
769 }
770
771 return 0;
772}
773
774/**
775 Compare two value in HII statement format.
776
777 @param[in] Value1 First value to compare.
778 @param[in] Value2 Second value to be compared.
779
780 @retval INTN 0 is returned when two values are equal.
781 1 is returned when first value is greater than second value.
782 -1 is returned when second value is greater than first value.
783
784**/
785INTN
786CompareHiiStatementValue (
787 IN HII_STATEMENT_VALUE *Value1,
788 IN HII_STATEMENT_VALUE *Value2
789 )
790{
791 INTN Result;
792 UINT64 Data1;
793 UINT64 Data2;
794
795 if ((Value1 == NULL) || (Value2 == NULL)) {
796 return -1;
797 }
798
799 switch (Value1->Type) {
800 case EFI_IFR_TYPE_NUM_SIZE_8:
801 Data1 = Value1->Value.u8;
802 break;
803 case EFI_IFR_TYPE_NUM_SIZE_16:
804 Data1 = Value1->Value.u16;
805 break;
806 case EFI_IFR_TYPE_NUM_SIZE_32:
807 Data1 = Value1->Value.u32;
808 break;
809 case EFI_IFR_TYPE_NUM_SIZE_64:
810 Data1 = Value1->Value.u64;
811 break;
812 case EFI_IFR_TYPE_BOOLEAN:
813 Data1 = (Value1->Value.b ? 1 : 0);
814 break;
815 default:
816 return -1;
817 }
818
819 switch (Value2->Type) {
820 case EFI_IFR_TYPE_NUM_SIZE_8:
821 Data2 = Value2->Value.u8;
822 break;
823 case EFI_IFR_TYPE_NUM_SIZE_16:
824 Data2 = Value2->Value.u16;
825 break;
826 case EFI_IFR_TYPE_NUM_SIZE_32:
827 Data2 = Value2->Value.u32;
828 break;
829 case EFI_IFR_TYPE_NUM_SIZE_64:
830 Data2 = Value2->Value.u64;
831 break;
832 case EFI_IFR_TYPE_BOOLEAN:
833 Data2 = (Value2->Value.b ? 1 : 0);
834 break;
835 default:
836 return -1;
837 }
838
839 Result = (Data1 == Data2 ? 0 : (Data1 > Data2 ? 1 : -1));
840
841 return Result;
842}
843
844/**
845 Convert HII value to the string in HII one-of opcode.
846
847 @param[in] HiiStatement HII Statement private instance
848 @param[in] Value HII Statement value
849
850 @retval EFI_STRING_ID The string ID in HII database.
851 0 is returned when something goes wrong.
852
853**/
854EFI_STRING_ID
855HiiValueToOneOfOptionStringId (
856 IN HII_STATEMENT *HiiStatement,
857 IN HII_STATEMENT_VALUE *Value
858 )
859{
860 LIST_ENTRY *Link;
861 HII_QUESTION_OPTION *Option;
862
863 if ((HiiStatement == NULL) || (Value == NULL)) {
864 return 0;
865 }
866
867 if (HiiStatement->Operand != EFI_IFR_ONE_OF_OP) {
868 return 0;
869 }
870
871 if (IsListEmpty (&HiiStatement->OptionListHead)) {
872 return 0;
873 }
874
875 Link = GetFirstNode (&HiiStatement->OptionListHead);
876 while (!IsNull (&HiiStatement->OptionListHead, Link)) {
877 Option = HII_QUESTION_OPTION_FROM_LINK (Link);
878
879 if (CompareHiiStatementValue (Value, &Option->Value) == 0) {
880 return Option->Text;
881 }
882
883 Link = GetNextNode (&HiiStatement->OptionListHead, Link);
884 }
885
886 return 0;
887}
888
889/**
890 Convert HII string to the value in HII one-of opcode.
891
892 @param[in] Statement Statement private instance
893 @param[in] Schema Schema string
894 @param[in] HiiString Input string
895 @param[out] Value Value returned
896
897 @retval EFI_SUCCESS HII value is returned successfully.
898 @retval Others Errors occur
899
900**/
901EFI_STATUS
902HiiStringToOneOfOptionValue (
903 IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement,
904 IN CHAR8 *Schema,
905 IN EFI_STRING HiiString,
906 OUT HII_STATEMENT_VALUE *Value
907 )
908{
909 LIST_ENTRY *Link;
910 HII_QUESTION_OPTION *Option;
911 EFI_STRING TmpString;
912 BOOLEAN Found;
913
914 if ((Statement == NULL) || IS_EMPTY_STRING (HiiString) || (Value == NULL)) {
915 return EFI_INVALID_PARAMETER;
916 }
917
918 if (Statement->HiiStatement->Operand != EFI_IFR_ONE_OF_OP) {
919 return EFI_UNSUPPORTED;
920 }
921
922 if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) {
923 return EFI_NOT_FOUND;
924 }
925
926 Found = FALSE;
927 Link = GetFirstNode (&Statement->HiiStatement->OptionListHead);
928 while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) {
929 Option = HII_QUESTION_OPTION_FROM_LINK (Link);
930
931 TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, Schema, Option->Text);
932 if (TmpString == NULL) {
933 TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, ENGLISH_LANGUAGE_CODE, Option->Text);
934 }
935
936 if (TmpString != NULL) {
937 if (StrCmp (TmpString, HiiString) == 0) {
938 CopyMem (Value, &Option->Value, sizeof (HII_STATEMENT_VALUE));
939 Found = TRUE;
940 }
941
942 FreePool (TmpString);
943 }
944
945 if (Found) {
946 return EFI_SUCCESS;
947 }
948
949 Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link);
950 }
951
952 return EFI_NOT_FOUND;
953}
954
955/**
956 Convert HII value to numeric value in Redfish format.
957
958 @param[in] Value Value to be converted.
959 @param[out] RedfishValue Value in Redfish format.
960
961 @retval EFI_SUCCESS Redfish value is returned successfully.
962 @retval Others Errors occur
963
964**/
965EFI_STATUS
966HiiValueToRedfishNumeric (
967 IN HII_STATEMENT_VALUE *Value,
968 OUT EDKII_REDFISH_VALUE *RedfishValue
969 )
970{
971 if ((Value == NULL) || (RedfishValue == NULL)) {
972 return EFI_INVALID_PARAMETER;
973 }
974
975 switch (Value->Type) {
976 case EFI_IFR_TYPE_NUM_SIZE_8:
977 RedfishValue->Type = RedfishValueTypeInteger;
978 RedfishValue->Value.Integer = (INT64)Value->Value.u8;
979 break;
980 case EFI_IFR_TYPE_NUM_SIZE_16:
981 RedfishValue->Type = RedfishValueTypeInteger;
982 RedfishValue->Value.Integer = (INT64)Value->Value.u16;
983 break;
984 case EFI_IFR_TYPE_NUM_SIZE_32:
985 RedfishValue->Type = RedfishValueTypeInteger;
986 RedfishValue->Value.Integer = (INT64)Value->Value.u32;
987 break;
988 case EFI_IFR_TYPE_NUM_SIZE_64:
989 RedfishValue->Type = RedfishValueTypeInteger;
990 RedfishValue->Value.Integer = (INT64)Value->Value.u64;
991 break;
992 case EFI_IFR_TYPE_BOOLEAN:
993 RedfishValue->Type = RedfishValueTypeBoolean;
994 RedfishValue->Value.Boolean = Value->Value.b;
995 break;
996 default:
997 RedfishValue->Type = RedfishValueTypeUnknown;
998 DEBUG ((DEBUG_ERROR, "%a: Unsupported value type: 0x%x\n", __func__, Value->Type));
999 break;
1000 }
1001
1002 return EFI_SUCCESS;
1003}
1004
1005/**
1006 Convert numeric value in Redfish format to HII value.
1007
1008 @param[in] RedfishValue Value in Redfish format to be converted.
1009 @param[out] Value HII value returned.
1010
1011 @retval EFI_SUCCESS HII value is returned successfully.
1012 @retval Others Errors occur
1013
1014**/
1015EFI_STATUS
1016RedfishNumericToHiiValue (
1017 IN EDKII_REDFISH_VALUE *RedfishValue,
1018 OUT HII_STATEMENT_VALUE *Value
1019 )
1020{
1021 if ((Value == NULL) || (RedfishValue == NULL)) {
1022 return EFI_INVALID_PARAMETER;
1023 }
1024
1025 switch (RedfishValue->Type) {
1026 case RedfishValueTypeInteger:
1027 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1028 Value->Value.u64 = (UINT64)RedfishValue->Value.Integer;
1029 break;
1030 case RedfishValueTypeBoolean:
1031 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1032 Value->Value.b = RedfishValue->Value.Boolean;
1033 break;
1034 default:
1035 Value->Type = EFI_IFR_TYPE_UNDEFINED;
1036 break;
1037 }
1038
1039 return EFI_SUCCESS;
1040}
1041
1042/**
1043 Dump the value in ordered list buffer.
1044
1045 @param[in] OrderedListStatement Ordered list statement.
1046
1047**/
1048VOID
1049DumpOrderedListValue (
1050 IN HII_STATEMENT *OrderedListStatement
1051 )
1052{
1053 UINT8 *Value8;
1054 UINT16 *Value16;
1055 UINT32 *Value32;
1056 UINT64 *Value64;
1057 UINTN Count;
1058 UINTN Index;
1059
1060 if ((OrderedListStatement == NULL) || (OrderedListStatement->Operand != EFI_IFR_ORDERED_LIST_OP)) {
1061 return;
1062 }
1063
1064 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "Value.Type= 0x%x\n", OrderedListStatement->Value.Type));
1065 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "Value.BufferValueType= 0x%x\n", OrderedListStatement->Value.BufferValueType));
1066 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "Value.BufferLen= 0x%x\n", OrderedListStatement->Value.BufferLen));
1067 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "Value.Buffer= 0x%x\n", OrderedListStatement->Value.Buffer));
1068 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "Value.MaxContainers= 0x%x\n", OrderedListStatement->ExtraData.OrderListData.MaxContainers));
1069 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "StorageWidth= 0x%x\n", OrderedListStatement->StorageWidth));
1070
1071 if (OrderedListStatement->Value.Buffer == NULL) {
1072 return;
1073 }
1074
1075 Value8 = NULL;
1076 Value16 = NULL;
1077 Value32 = NULL;
1078 Value64 = NULL;
1079 Count = 0;
1080
1081 switch (OrderedListStatement->Value.BufferValueType) {
1082 case EFI_IFR_TYPE_NUM_SIZE_8:
1083 Value8 = (UINT8 *)OrderedListStatement->Value.Buffer;
1084 Count = OrderedListStatement->StorageWidth / sizeof (UINT8);
1085 for (Index = 0; Index < Count; Index++) {
1086 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%d ", Value8[Index]));
1087 }
1088
1089 break;
1090 case EFI_IFR_TYPE_NUM_SIZE_16:
1091 Value16 = (UINT16 *)OrderedListStatement->Value.Buffer;
1092 Count = OrderedListStatement->StorageWidth / sizeof (UINT16);
1093 for (Index = 0; Index < Count; Index++) {
1094 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%d ", Value16[Index]));
1095 }
1096
1097 break;
1098 case EFI_IFR_TYPE_NUM_SIZE_32:
1099 Value32 = (UINT32 *)OrderedListStatement->Value.Buffer;
1100 Count = OrderedListStatement->StorageWidth / sizeof (UINT32);
1101 for (Index = 0; Index < Count; Index++) {
1102 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%d ", Value32[Index]));
1103 }
1104
1105 break;
1106 case EFI_IFR_TYPE_NUM_SIZE_64:
1107 Value64 = (UINT64 *)OrderedListStatement->Value.Buffer;
1108 Count = OrderedListStatement->StorageWidth / sizeof (UINT64);
1109 for (Index = 0; Index < Count; Index++) {
1110 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%d ", Value64[Index]));
1111 }
1112
1113 break;
1114 default:
1115 Value8 = (UINT8 *)OrderedListStatement->Value.Buffer;
1116 Count = OrderedListStatement->StorageWidth / sizeof (UINT8);
1117 for (Index = 0; Index < Count; Index++) {
1118 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%d ", Value8[Index]));
1119 }
1120
1121 break;
1122 }
1123
1124 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "\n"));
1125}
1126
1127/**
1128 Convert HII value to the string in HII ordered list opcode. It's caller's
1129 responsibility to free returned buffer using FreePool().
1130
1131 @param[in] HiiStatement HII Statement private instance
1132 @param[out] ReturnSize The size of returned array
1133
1134 @retval EFI_STRING_ID The string ID array for options in ordered list.
1135
1136**/
1137EFI_STRING_ID *
1138HiiValueToOrderedListOptionStringId (
1139 IN HII_STATEMENT *HiiStatement,
1140 OUT UINTN *ReturnSize
1141 )
1142{
1143 LIST_ENTRY *Link;
1144 UINTN OptionCount;
1145 EFI_STRING_ID *ReturnedArray;
1146 UINTN Index;
1147 UINT64 Value;
1148
1149 if ((HiiStatement == NULL) || (ReturnSize == NULL)) {
1150 return NULL;
1151 }
1152
1153 *ReturnSize = 0;
1154
1155 if (HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) {
1156 return NULL;
1157 }
1158
1159 if (IsListEmpty (&HiiStatement->OptionListHead)) {
1160 return NULL;
1161 }
1162
1163 DEBUG_CODE (
1164 DumpOrderedListValue (HiiStatement);
1165 );
1166
1167 OptionCount = 0;
1168 Link = GetFirstNode (&HiiStatement->OptionListHead);
1169 while (!IsNull (&HiiStatement->OptionListHead, Link)) {
1170 ++OptionCount;
1171 Link = GetNextNode (&HiiStatement->OptionListHead, Link);
1172 }
1173
1174 *ReturnSize = OptionCount;
1175 ReturnedArray = AllocatePool (sizeof (EFI_STRING_ID) * OptionCount);
1176 if (ReturnedArray == NULL) {
1177 DEBUG ((DEBUG_ERROR, "%a: out of resource\n", __func__));
1178 *ReturnSize = 0;
1179 return NULL;
1180 }
1181
1182 for (Index = 0; Index < OptionCount; Index++) {
1183 Value = OrderedListGetArrayData (HiiStatement->Value.Buffer, HiiStatement->Value.BufferValueType, Index);
1184 ReturnedArray[Index] = OrderedListOptionValueToStringId (HiiStatement, Value);
1185 }
1186
1187 return ReturnedArray;
1188}
1189
1190/**
1191 Convert HII string to the value in HII ordered list opcode.
1192
1193 @param[in] Statement Statement private instance
1194 @param[in] Schema Schema string
1195 @param[in] HiiString Input string
1196 @param[out] Value Value returned
1197
1198 @retval EFI_SUCCESS HII value is returned successfully.
1199 @retval Others Errors occur
1200
1201**/
1202EFI_STATUS
1203HiiStringToOrderedListOptionValue (
1204 IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement,
1205 IN CHAR8 *Schema,
1206 IN EFI_STRING HiiString,
1207 OUT UINT64 *Value
1208 )
1209{
1210 LIST_ENTRY *Link;
1211 HII_QUESTION_OPTION *Option;
1212 EFI_STRING TmpString;
1213 BOOLEAN Found;
1214
1215 if ((Statement == NULL) || IS_EMPTY_STRING (HiiString) || (Value == NULL)) {
1216 return EFI_INVALID_PARAMETER;
1217 }
1218
1219 *Value = 0;
1220
1221 if (Statement->HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) {
1222 return EFI_UNSUPPORTED;
1223 }
1224
1225 if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) {
1226 return EFI_NOT_FOUND;
1227 }
1228
1229 Found = FALSE;
1230 Link = GetFirstNode (&Statement->HiiStatement->OptionListHead);
1231 while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) {
1232 Option = HII_QUESTION_OPTION_FROM_LINK (Link);
1233
1234 TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, Schema, Option->Text);
1235 if (TmpString == NULL) {
1236 TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, ENGLISH_LANGUAGE_CODE, Option->Text);
1237 }
1238
1239 if (TmpString != NULL) {
1240 if (StrCmp (TmpString, HiiString) == 0) {
1241 *Value = ExtendHiiValueToU64 (&Option->Value);
1242 Found = TRUE;
1243 }
1244
1245 FreePool (TmpString);
1246 }
1247
1248 if (Found) {
1249 return EFI_SUCCESS;
1250 }
1251
1252 Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link);
1253 }
1254
1255 return EFI_NOT_FOUND;
1256}
1257
1258/**
1259 Convert HII value to Redfish value.
1260
1261 @param[in] HiiHandle HII handle.
1262 @param[in] FullSchema Schema string.
1263 @param[in] HiiStatement HII statement.
1264 @param[in] Value Value to be converted.
1265 @param[out] RedfishValue Value in Redfish format.
1266
1267 @retval EFI_SUCCESS Redfish value is returned successfully.
1268 @retval Others Errors occur
1269
1270**/
1271EFI_STATUS
1272HiiValueToRedfishValue (
1273 IN EFI_HII_HANDLE HiiHandle,
1274 IN CHAR8 *FullSchema,
1275 IN HII_STATEMENT *HiiStatement,
1276 IN HII_STATEMENT_VALUE *Value,
1277 OUT EDKII_REDFISH_VALUE *RedfishValue
1278 )
1279{
1280 EFI_STATUS Status;
1281 EFI_STRING_ID StringId;
1282 UINTN Index;
1283 UINTN Count;
1284 EFI_STRING_ID *StringIdArray;
1285 CHAR8 NullChar;
1286
1287 if ((HiiHandle == NULL) || (HiiStatement == NULL) || (Value == NULL) || (RedfishValue == NULL) || IS_EMPTY_STRING (FullSchema)) {
1288 return EFI_INVALID_PARAMETER;
1289 }
1290
1291 StringIdArray = NULL;
1292 Count = 0;
1293 Status = EFI_SUCCESS;
1294 NullChar = '\0';
1295
1296 switch (HiiStatement->Operand) {
1297 case EFI_IFR_ONE_OF_OP:
1298 StringId = HiiValueToOneOfOptionStringId (HiiStatement, Value);
1299 if (StringId == 0) {
1300 //
1301 // Print prompt string of HII statement for ease of debugging
1302 //
1303 DumpHiiStatementPrompt (DEBUG_ERROR, HiiHandle, HiiStatement, "Can not find string ID");
1304 DumpHiiStatementValue (DEBUG_ERROR, Value, "Current value");
1305 ASSERT (FALSE);
1306 Status = EFI_DEVICE_ERROR;
1307 break;
1308 }
1309
1310 RedfishValue->Value.Buffer = HiiGetRedfishAsciiString (HiiHandle, FullSchema, StringId);
1311 if (RedfishValue->Value.Buffer == NULL) {
1312 Status = EFI_OUT_OF_RESOURCES;
1313 break;
1314 }
1315
1316 RedfishValue->Type = RedfishValueTypeString;
1317 break;
1318 case EFI_IFR_STRING_OP:
1319 if (Value->Type != EFI_IFR_TYPE_STRING) {
1320 ASSERT (FALSE);
1321 Status = EFI_DEVICE_ERROR;
1322 break;
1323 }
1324
1325 if (Value->Buffer == NULL) {
1326 RedfishValue->Value.Buffer = AllocateCopyPool (sizeof (NullChar), &NullChar);
1327 } else {
1328 RedfishValue->Value.Buffer = StrToAsciiStr ((EFI_STRING)Value->Buffer);
1329 }
1330
1331 if (RedfishValue->Value.Buffer == NULL) {
1332 Status = EFI_OUT_OF_RESOURCES;
1333 break;
1334 }
1335
1336 RedfishValue->Type = RedfishValueTypeString;
1337 break;
1338 case EFI_IFR_CHECKBOX_OP:
1339 //
1340 // There is case where HII driver defines UINT8 for checked-box opcode storage.
1341 // IFR compiler will assign EFI_IFR_TYPE_NUM_SIZE_8 to its value type instead of
1342 // EFI_IFR_TYPE_BOOLEAN. We do a patch here and use boolean value type for this
1343 // case.
1344 //
1345 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
1346 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1347 }
1348
1349 case EFI_IFR_NUMERIC_OP:
1350 Status = HiiValueToRedfishNumeric (Value, RedfishValue);
1351 if (EFI_ERROR (Status)) {
1352 DEBUG ((DEBUG_ERROR, "%a: failed to convert HII value to Redfish value: %r\n", __func__, Status));
1353 break;
1354 }
1355
1356 break;
1357 case EFI_IFR_ACTION_OP:
1358 if (Value->Type != EFI_IFR_TYPE_ACTION) {
1359 ASSERT (FALSE);
1360 Status = EFI_DEVICE_ERROR;
1361 break;
1362 }
1363
1364 //
1365 // Action has no value. Just return unknown type.
1366 //
1367 RedfishValue->Type = RedfishValueTypeUnknown;
1368 break;
1369 case EFI_IFR_ORDERED_LIST_OP:
1370 StringIdArray = HiiValueToOrderedListOptionStringId (HiiStatement, &Count);
1371 if (StringIdArray == NULL) {
1372 //
1373 // Print prompt string of HII statement for ease of debugging
1374 //
1375 DumpHiiStatementPrompt (DEBUG_ERROR, HiiHandle, HiiStatement, "Can not get string ID array");
1376 ASSERT (FALSE);
1377 Status = EFI_DEVICE_ERROR;
1378 break;
1379 }
1380
1381 RedfishValue->Value.StringArray = AllocatePool (sizeof (CHAR8 *) * Count);
1382 if (RedfishValue->Value.StringArray == NULL) {
1383 //
1384 // Print prompt string of HII statement for ease of debugging
1385 //
1386 DumpHiiStatementPrompt (DEBUG_ERROR, HiiHandle, HiiStatement, "Can not allocate memory");
1387 ASSERT (FALSE);
1388 Status = EFI_OUT_OF_RESOURCES;
1389 break;
1390 }
1391
1392 for (Index = 0; Index < Count; Index++) {
1393 if (StringIdArray[Index] == 0) {
1394 //
1395 // Print prompt string of HII statement for ease of debugging
1396 //
1397 DumpHiiStatementPrompt (DEBUG_ERROR, HiiHandle, HiiStatement, "String ID in array is 0");
1398 ASSERT (FALSE);
1399 }
1400
1401 RedfishValue->Value.StringArray[Index] = HiiGetRedfishAsciiString (HiiHandle, FullSchema, StringIdArray[Index]);
1402 ASSERT (RedfishValue->Value.StringArray[Index] != NULL);
1403 }
1404
1405 RedfishValue->ArrayCount = Count;
1406 RedfishValue->Type = RedfishValueTypeStringArray;
1407
1408 FreePool (StringIdArray);
1409 break;
1410 case EFI_IFR_TEXT_OP:
1411 //
1412 // Use text two as the value
1413 //
1414 if (HiiStatement->ExtraData.TextTwo == 0x00) {
1415 Status = EFI_NOT_FOUND;
1416 break;
1417 }
1418
1419 RedfishValue->Value.Buffer = HiiGetRedfishAsciiString (HiiHandle, FullSchema, HiiStatement->ExtraData.TextTwo);
1420 if (RedfishValue->Value.Buffer == NULL) {
1421 //
1422 // No x-UEFI-redfish string defined. Try to get string in English.
1423 //
1424 RedfishValue->Value.Buffer = HiiGetEnglishAsciiString (HiiHandle, HiiStatement->ExtraData.TextTwo);
1425 }
1426
1427 if (RedfishValue->Value.Buffer == NULL) {
1428 Status = EFI_OUT_OF_RESOURCES;
1429 break;
1430 }
1431
1432 RedfishValue->Type = RedfishValueTypeString;
1433 break;
1434 default:
1435 DEBUG ((DEBUG_ERROR, "%a: catch unsupported type: 0x%x! Please contact with author if we need to support this type.\n", __func__, HiiStatement->Operand));
1436 ASSERT (FALSE);
1437 Status = EFI_UNSUPPORTED;
1438 break;
1439 }
1440
1441 return Status;
1442}
1443
1444/**
1445 Convert input ascii string to unicode string. It's caller's
1446 responsibility to free returned buffer using FreePool().
1447
1448 @param[in] AsciiString Ascii string to be converted.
1449
1450 @retval CHAR16 * Unicode string on return.
1451
1452**/
1453EFI_STRING
1454StrToUnicodeStr (
1455 IN CHAR8 *AsciiString
1456 )
1457{
1458 UINTN StringLen;
1459 EFI_STRING Buffer;
1460 EFI_STATUS Status;
1461
1462 if (AsciiString == NULL) {
1463 return NULL;
1464 }
1465
1466 StringLen = AsciiStrLen (AsciiString) + 1;
1467 Buffer = AllocatePool (StringLen * sizeof (CHAR16));
1468 if (Buffer == NULL) {
1469 return NULL;
1470 }
1471
1472 Status = AsciiStrToUnicodeStrS (AsciiString, Buffer, StringLen);
1473 if (EFI_ERROR (Status)) {
1474 FreePool (Buffer);
1475 return NULL;
1476 }
1477
1478 return Buffer;
1479}
1480
1481/**
1482 Convert input unicode string to ascii string. It's caller's
1483 responsibility to free returned buffer using FreePool().
1484
1485 @param[in] UnicodeString Unicode string to be converted.
1486
1487 @retval CHAR8 * Ascii string on return.
1488
1489**/
1490CHAR8 *
1491StrToAsciiStr (
1492 IN EFI_STRING UnicodeString
1493 )
1494{
1495 UINTN StringLen;
1496 CHAR8 *Buffer;
1497 EFI_STATUS Status;
1498
1499 if (UnicodeString == NULL) {
1500 return NULL;
1501 }
1502
1503 StringLen = HiiStrLen (UnicodeString) + 1;
1504 Buffer = AllocatePool (StringLen * sizeof (CHAR8));
1505 if (Buffer == NULL) {
1506 return NULL;
1507 }
1508
1509 Status = UnicodeStrToAsciiStrS (UnicodeString, Buffer, StringLen);
1510 if (EFI_ERROR (Status)) {
1511 FreePool (Buffer);
1512 return NULL;
1513 }
1514
1515 return Buffer;
1516}
1517
1518/**
1519 Return the full Redfish schema string from the given Schema and Version.
1520
1521 Returned schema string is: Schema + '.' + Version
1522
1523 @param[in] Schema Schema string
1524 @param[in] Version Schema version string
1525
1526 @retval CHAR8 * Schema string. NULL when errors occur.
1527
1528**/
1529CHAR8 *
1530GetFullSchemaString (
1531 IN CHAR8 *Schema,
1532 IN CHAR8 *Version
1533 )
1534{
1535 UINTN Size;
1536 CHAR8 *FullName;
1537
1538 if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version)) {
1539 return NULL;
1540 }
1541
1542 Size = AsciiStrSize (CONFIGURE_LANGUAGE_PREFIX) + AsciiStrSize (Schema) + AsciiStrSize (Version);
1543
1544 FullName = AllocatePool (Size);
1545 if (FullName == NULL) {
1546 DEBUG ((DEBUG_ERROR, "%a: out-of-resource\n", __func__));
1547 return NULL;
1548 }
1549
1550 AsciiSPrint (FullName, Size, "%a%a.%a", CONFIGURE_LANGUAGE_PREFIX, Schema, Version);
1551
1552 return FullName;
1553}
1554
1555/**
1556 Common implementation to get statement private instance.
1557
1558 @param[in] RedfishPlatformConfigPrivate Private instance.
1559 @param[in] Schema Redfish schema string.
1560 @param[in] ConfigureLang Configure language that refers to this statement.
1561 @param[out] Statement Statement instance
1562
1563 @retval EFI_SUCCESS HII value is returned successfully.
1564 @retval Others Errors occur
1565
1566**/
1567EFI_STATUS
1568RedfishPlatformConfigGetStatementCommon (
1569 IN REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate,
1570 IN CHAR8 *Schema,
1571 IN EFI_STRING ConfigureLang,
1572 OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE **Statement
1573 )
1574{
1575 EFI_STATUS Status;
1576 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement;
1577
1578 if ((RedfishPlatformConfigPrivate == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang) || (Statement == NULL)) {
1579 return EFI_INVALID_PARAMETER;
1580 }
1581
1582 *Statement = NULL;
1583
1584 Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);
1585 if (EFI_ERROR (Status)) {
1586 DEBUG ((DEBUG_ERROR, "%a: ProcessPendingList failure: %r\n", __func__, Status));
1587 return Status;
1588 }
1589
1590 TargetStatement = GetStatementPrivateByConfigureLang (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang);
1591 if (TargetStatement == NULL) {
1592 DEBUG ((DEBUG_ERROR, "%a: No match HII statement is found by the given %s in schema %a\n", __func__, ConfigureLang, Schema));
1593 return EFI_NOT_FOUND;
1594 }
1595
1596 //
1597 // Find current HII question value.
1598 //
1599 Status = GetQuestionValue (
1600 TargetStatement->ParentForm->ParentFormset->HiiFormSet,
1601 TargetStatement->ParentForm->HiiForm,
1602 TargetStatement->HiiStatement,
1603 GetSetValueWithBuffer
1604 );
1605 if (EFI_ERROR (Status)) {
1606 DEBUG ((DEBUG_ERROR, "%a: failed to get question current value: %r\n", __func__, Status));
1607 return Status;
1608 }
1609
1610 if (TargetStatement->HiiStatement->Value.Type == EFI_IFR_TYPE_UNDEFINED) {
1611 return EFI_DEVICE_ERROR;
1612 }
1613
1614 //
1615 // Return Value.
1616 //
1617 *Statement = TargetStatement;
1618
1619 return EFI_SUCCESS;
1620}
1621
1622/**
1623 Get Redfish value with the given Schema and Configure Language.
1624
1625 @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
1626 @param[in] Schema The Redfish schema to query.
1627 @param[in] Version The Redfish version to query.
1628 @param[in] ConfigureLang The target value which match this configure Language.
1629 @param[out] Value The returned value.
1630
1631 @retval EFI_SUCCESS Value is returned successfully.
1632 @retval Others Some error happened.
1633
1634**/
1635EFI_STATUS
1636EFIAPI
1637RedfishPlatformConfigProtocolGetValue (
1638 IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
1639 IN CHAR8 *Schema,
1640 IN CHAR8 *Version,
1641 IN EFI_STRING ConfigureLang,
1642 OUT EDKII_REDFISH_VALUE *Value
1643 )
1644{
1645 EFI_STATUS Status;
1646 REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate;
1647 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement;
1648 CHAR8 *FullSchema;
1649
1650 if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || (Value == NULL)) {
1651 return EFI_INVALID_PARAMETER;
1652 }
1653
1654 RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
1655 Value->Type = RedfishValueTypeUnknown;
1656 Value->ArrayCount = 0;
1657 FullSchema = NULL;
1658
1659 FullSchema = GetFullSchemaString (Schema, Version);
1660 if (FullSchema == NULL) {
1661 return EFI_OUT_OF_RESOURCES;
1662 }
1663
1664 Status = RedfishPlatformConfigGetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &TargetStatement);
1665 if (EFI_ERROR (Status)) {
1666 goto RELEASE_RESOURCE;
1667 }
1668
1669 if (TargetStatement->Suppressed) {
1670 Status = EFI_ACCESS_DENIED;
1671 goto RELEASE_RESOURCE;
1672 }
1673
1674 Status = HiiValueToRedfishValue (
1675 TargetStatement->ParentForm->ParentFormset->HiiHandle,
1676 FullSchema,
1677 TargetStatement->HiiStatement,
1678 &TargetStatement->HiiStatement->Value,
1679 Value
1680 );
1681 if (EFI_ERROR (Status)) {
1682 DEBUG ((DEBUG_ERROR, "%a: HiiValueToRedfishValue failed: %r\n", __func__, Status));
1683 }
1684
1685RELEASE_RESOURCE:
1686
1687 if (FullSchema != NULL) {
1688 FreePool (FullSchema);
1689 }
1690
1691 return Status;
1692}
1693
1694/**
1695 Function to save question value into HII database.
1696
1697 @param[in] HiiFormset HII form-set instance
1698 @param[in] HiiForm HII form instance
1699 @param[in] HiiStatement HII statement that keeps new value.
1700 @param[in] Value New value to apply.
1701
1702 @retval EFI_SUCCESS HII value is returned successfully.
1703 @retval Others Errors occur
1704
1705**/
1706EFI_STATUS
1707RedfishPlatformConfigSaveQuestionValue (
1708 IN HII_FORMSET *HiiFormset,
1709 IN HII_FORM *HiiForm,
1710 IN HII_STATEMENT *HiiStatement,
1711 IN HII_STATEMENT_VALUE *Value
1712 )
1713{
1714 EFI_STATUS Status;
1715
1716 if ((HiiFormset == NULL) || (HiiForm == NULL) || (HiiStatement == NULL) || (Value == NULL)) {
1717 return EFI_INVALID_PARAMETER;
1718 }
1719
1720 Status = SetQuestionValue (
1721 HiiFormset,
1722 HiiForm,
1723 HiiStatement,
1724 Value
1725 );
1726 if (EFI_ERROR (Status)) {
1727 DEBUG ((DEBUG_ERROR, "%a: failed to set question value: %r\n", __func__, Status));
1728 return Status;
1729 }
1730
1731 Status = SubmitForm (HiiFormset, HiiForm);
1732 if (EFI_ERROR (Status)) {
1733 DEBUG ((DEBUG_ERROR, "%a: failed to submit form: %r\n", __func__, Status));
1734 return Status;
1735 }
1736
1737 return EFI_SUCCESS;
1738}
1739
1740/**
1741 Common implementation to set statement private instance.
1742
1743 @param[in] RedfishPlatformConfigPrivate Private instance.
1744 @param[in] Schema Redfish schema string.
1745 @param[in] ConfigureLang Configure language that refers to this statement.
1746 @param[in] StatementValue Statement value.
1747
1748 @retval EFI_SUCCESS HII value is returned successfully.
1749 @retval Others Errors occur
1750
1751**/
1752EFI_STATUS
1753RedfishPlatformConfigSetStatementCommon (
1754 IN REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate,
1755 IN CHAR8 *Schema,
1756 IN EFI_STRING ConfigureLang,
1757 IN HII_STATEMENT_VALUE *StatementValue
1758 )
1759{
1760 EFI_STATUS Status;
1761 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement;
1762 EFI_STRING TempBuffer;
1763 UINT8 *StringArray;
1764 UINTN Index;
1765 UINT64 Value;
1766 CHAR8 **CharArray;
1767
1768 if ((RedfishPlatformConfigPrivate == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang) || (StatementValue == NULL)) {
1769 return EFI_INVALID_PARAMETER;
1770 }
1771
1772 TempBuffer = NULL;
1773 StringArray = NULL;
1774
1775 Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);
1776 if (EFI_ERROR (Status)) {
1777 DEBUG ((DEBUG_ERROR, "%a: ProcessPendingList failure: %r\n", __func__, Status));
1778 return Status;
1779 }
1780
1781 TargetStatement = GetStatementPrivateByConfigureLang (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang);
1782 if (TargetStatement == NULL) {
1783 DEBUG ((DEBUG_ERROR, "%a: No match HII statement is found by the given %s in schema %a\n", __func__, ConfigureLang, Schema));
1784 return EFI_NOT_FOUND;
1785 }
1786
1787 if (StatementValue->Type != TargetStatement->HiiStatement->Value.Type) {
1788 //
1789 // We treat one-of type as string in Redfish. But one-of statement is not
1790 // in string format from HII point of view. Do a patch here.
1791 //
1792 if ((TargetStatement->HiiStatement->Operand == EFI_IFR_ONE_OF_OP) && (StatementValue->Type == EFI_IFR_TYPE_STRING)) {
1793 //
1794 // Keep input buffer to TempBuffer because StatementValue will be
1795 // assigned in HiiStringToOneOfOptionValue().
1796 //
1797 TempBuffer = (EFI_STRING)StatementValue->Buffer;
1798 StatementValue->Buffer = NULL;
1799 StatementValue->BufferLen = 0;
1800
1801 Status = HiiStringToOneOfOptionValue (TargetStatement, Schema, TempBuffer, StatementValue);
1802 if (EFI_ERROR (Status)) {
1803 DEBUG ((DEBUG_ERROR, "%a: failed to find option value by the given %s\n", __func__, TempBuffer));
1804 FreePool (TempBuffer);
1805 return EFI_NOT_FOUND;
1806 }
1807
1808 FreePool (TempBuffer);
1809 } else if ((TargetStatement->HiiStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (StatementValue->Type == EFI_IFR_TYPE_STRING)) {
1810 //
1811 // We treat ordered list type as string in Redfish. But ordered list statement is not
1812 // in string format from HII point of view. Do a patch here.
1813 //
1814 StringArray = AllocateZeroPool (TargetStatement->HiiStatement->StorageWidth);
1815 if (StringArray == NULL) {
1816 return EFI_OUT_OF_RESOURCES;
1817 }
1818
1819 //
1820 // Arrange new option order from input string array
1821 //
1822 CharArray = (CHAR8 **)StatementValue->Buffer;
1823 for (Index = 0; Index < StatementValue->BufferLen; Index++) {
1824 TempBuffer = StrToUnicodeStr (CharArray[Index]);
1825 if (TempBuffer == NULL) {
1826 return EFI_OUT_OF_RESOURCES;
1827 }
1828
1829 Status = HiiStringToOrderedListOptionValue (TargetStatement, Schema, TempBuffer, &Value);
1830 if (EFI_ERROR (Status)) {
1831 ASSERT (FALSE);
1832 continue;
1833 }
1834
1835 FreePool (TempBuffer);
1836 OrderedListSetArrayData (StringArray, TargetStatement->HiiStatement->Value.BufferValueType, Index, Value);
1837 }
1838
1839 StatementValue->Type = EFI_IFR_TYPE_BUFFER;
1840 StatementValue->Buffer = StringArray;
1841 StatementValue->BufferLen = TargetStatement->HiiStatement->StorageWidth;
1842 StatementValue->BufferValueType = TargetStatement->HiiStatement->Value.BufferValueType;
1843 } else if ((TargetStatement->HiiStatement->Operand == EFI_IFR_NUMERIC_OP) && (StatementValue->Type == EFI_IFR_TYPE_NUM_SIZE_64)) {
1844 //
1845 // Redfish only has numeric value type and it does not care about the value size.
1846 // Do a patch here so we have proper value size applied.
1847 //
1848 StatementValue->Type = TargetStatement->HiiStatement->Value.Type;
1849 } else {
1850 DEBUG ((DEBUG_ERROR, "%a: catch value type mismatch! input type: 0x%x but target value type: 0x%x\n", __func__, StatementValue->Type, TargetStatement->HiiStatement->Value.Type));
1851 ASSERT (FALSE);
1852 }
1853 }
1854
1855 if ((TargetStatement->HiiStatement->Operand == EFI_IFR_STRING_OP) && (StatementValue->Type == EFI_IFR_TYPE_STRING)) {
1856 //
1857 // Create string ID for new string.
1858 //
1859 StatementValue->Value.string = HiiSetString (TargetStatement->ParentForm->ParentFormset->HiiHandle, 0x00, (EFI_STRING)StatementValue->Buffer, NULL);
1860 if (StatementValue->Value.string == 0) {
1861 DEBUG ((DEBUG_ERROR, "%a: can not create string id\n", __func__));
1862 return EFI_OUT_OF_RESOURCES;
1863 }
1864 }
1865
1866 Status = RedfishPlatformConfigSaveQuestionValue (
1867 TargetStatement->ParentForm->ParentFormset->HiiFormSet,
1868 TargetStatement->ParentForm->HiiForm,
1869 TargetStatement->HiiStatement,
1870 StatementValue
1871 );
1872 if (EFI_ERROR (Status)) {
1873 DEBUG ((DEBUG_ERROR, "%a: failed to save question value: %r\n", __func__, Status));
1874 }
1875
1876 if ((TargetStatement->HiiStatement->Operand == EFI_IFR_STRING_OP) && (StatementValue->Type == EFI_IFR_TYPE_STRING)) {
1877 if (StatementValue->Value.string != 0) {
1878 // Delete HII string which was created for HII statement operand = EFI_IFR_STRING_OP and Type = EFI_IFR_TYPE_STRING.
1879 HiiDeleteString (StatementValue->Value.string, TargetStatement->ParentForm->ParentFormset->HiiHandle);
1880 }
1881 }
1882
1883 return Status;
1884}
1885
1886/**
1887 Set Redfish value with the given Schema and Configure Language.
1888
1889 @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
1890 @param[in] Schema The Redfish schema to query.
1891 @param[in] Version The Redfish version to query.
1892 @param[in] ConfigureLang The target value which match this configure Language.
1893 @param[in] Value The value to set.
1894
1895 @retval EFI_SUCCESS Value is returned successfully.
1896 @retval Others Some error happened.
1897
1898**/
1899EFI_STATUS
1900EFIAPI
1901RedfishPlatformConfigProtocolSetValue (
1902 IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
1903 IN CHAR8 *Schema,
1904 IN CHAR8 *Version,
1905 IN EFI_STRING ConfigureLang,
1906 IN EDKII_REDFISH_VALUE Value
1907 )
1908{
1909 EFI_STATUS Status;
1910 REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate;
1911 CHAR8 *FullSchema;
1912 HII_STATEMENT_VALUE NewValue;
1913
1914 if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang)) {
1915 return EFI_INVALID_PARAMETER;
1916 }
1917
1918 if ((Value.Type == RedfishValueTypeUnknown) || (Value.Type >= RedfishValueTypeMax)) {
1919 return EFI_INVALID_PARAMETER;
1920 }
1921
1922 RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
1923 FullSchema = NULL;
1924
1925 FullSchema = GetFullSchemaString (Schema, Version);
1926 if (FullSchema == NULL) {
1927 return EFI_OUT_OF_RESOURCES;
1928 }
1929
1930 ZeroMem (&NewValue, sizeof (HII_STATEMENT_VALUE));
1931
1932 switch (Value.Type) {
1933 case RedfishValueTypeInteger:
1934 case RedfishValueTypeBoolean:
1935 Status = RedfishNumericToHiiValue (&Value, &NewValue);
1936 if (EFI_ERROR (Status)) {
1937 DEBUG ((DEBUG_ERROR, "%a: failed to convert Redfish value to Hii value: %r\n", __func__, Status));
1938 goto RELEASE_RESOURCE;
1939 }
1940
1941 break;
1942 case RedfishValueTypeString:
1943 if (Value.Value.Buffer == NULL) {
1944 Status = EFI_INVALID_PARAMETER;
1945 goto RELEASE_RESOURCE;
1946 }
1947
1948 NewValue.Type = EFI_IFR_TYPE_STRING;
1949 NewValue.BufferLen = (UINT16)(AsciiStrSize (Value.Value.Buffer) * sizeof (CHAR16));
1950 NewValue.Buffer = (UINT8 *)StrToUnicodeStr (Value.Value.Buffer);
1951 if (NewValue.Buffer == NULL) {
1952 Status = EFI_OUT_OF_RESOURCES;
1953 goto RELEASE_RESOURCE;
1954 }
1955
1956 break;
1957 case RedfishValueTypeStringArray:
1958 NewValue.Type = EFI_IFR_TYPE_STRING;
1959 NewValue.BufferLen = (UINT16)Value.ArrayCount;
1960 NewValue.Buffer = (UINT8 *)Value.Value.StringArray;
1961 break;
1962 default:
1963 ASSERT (FALSE);
1964 break;
1965 }
1966
1967 Status = RedfishPlatformConfigSetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &NewValue);
1968 if (EFI_ERROR (Status)) {
1969 DEBUG ((DEBUG_ERROR, "%a: failed to set value to statement: %r\n", __func__, Status));
1970 }
1971
1972RELEASE_RESOURCE:
1973
1974 if (FullSchema != NULL) {
1975 FreePool (FullSchema);
1976 }
1977
1978 if ((Value.Type == RedfishValueTypeString) && (NewValue.Buffer != NULL)) {
1979 FreePool (NewValue.Buffer);
1980 }
1981
1982 return Status;
1983}
1984
1985/**
1986 Get the list of Configure Language from platform configuration by the given Schema and RegexPattern.
1987
1988 @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
1989 @param[in] Schema The Redfish schema to query.
1990 @param[in] Version The Redfish version to query.
1991 @param[in] RegexPattern The target Configure Language pattern. This is used for regular expression matching.
1992 @param[out] ConfigureLangList The list of Configure Language.
1993 @param[out] Count The number of Configure Language in ConfigureLangList.
1994
1995 @retval EFI_SUCCESS ConfigureLangList is returned successfully.
1996 @retval Others Some error happened.
1997
1998**/
1999EFI_STATUS
2000EFIAPI
2001RedfishPlatformConfigProtocolGetConfigureLang (
2002 IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
2003 IN CHAR8 *Schema,
2004 IN CHAR8 *Version,
2005 IN EFI_STRING RegexPattern,
2006 OUT EFI_STRING **ConfigureLangList,
2007 OUT UINTN *Count
2008 )
2009{
2010 REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate;
2011 EFI_STATUS Status;
2012 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST StatementList;
2013 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF *StatementRef;
2014 LIST_ENTRY *NextLink;
2015 EFI_STRING *TmpConfigureLangList;
2016 UINTN Index;
2017 CHAR8 *FullSchema;
2018
2019 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Harvest config language of %a_%a (Regex: %s).\n", __func__, Schema, Version, RegexPattern));
2020
2021 if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || (Count == NULL) || (ConfigureLangList == NULL) || IS_EMPTY_STRING (RegexPattern)) {
2022 return EFI_INVALID_PARAMETER;
2023 }
2024
2025 ZeroMem (&StatementList, sizeof (StatementList));
2026 *Count = 0;
2027 *ConfigureLangList = NULL;
2028 FullSchema = NULL;
2029 TmpConfigureLangList = NULL;
2030 RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
2031
2032 Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);
2033 if (EFI_ERROR (Status)) {
2034 DEBUG ((DEBUG_ERROR, "%a: ProcessPendingList failure: %r\n", __func__, Status));
2035 return Status;
2036 }
2037
2038 FullSchema = GetFullSchemaString (Schema, Version);
2039 if (FullSchema == NULL) {
2040 return EFI_OUT_OF_RESOURCES;
2041 }
2042
2043 Status = GetStatementPrivateByConfigureLangRegex (
2044 RedfishPlatformConfigPrivate->RegularExpressionProtocol,
2045 &RedfishPlatformConfigPrivate->FormsetList,
2046 FullSchema,
2047 RegexPattern,
2048 &StatementList
2049 );
2050 if (EFI_ERROR (Status)) {
2051 DEBUG ((DEBUG_ERROR, "%a: GetStatementPrivateByConfigureLangRegex failure: %r\n", __func__, Status));
2052 goto RELEASE_RESOURCE;
2053 }
2054
2055 if (!IsListEmpty (&StatementList.StatementList)) {
2056 TmpConfigureLangList = AllocateZeroPool (sizeof (CHAR16 *) * StatementList.Count);
2057 if (TmpConfigureLangList == NULL) {
2058 Status = EFI_OUT_OF_RESOURCES;
2059 goto RELEASE_RESOURCE;
2060 }
2061
2062 Index = 0;
2063 NextLink = GetFirstNode (&StatementList.StatementList);
2064 while (!IsNull (&StatementList.StatementList, NextLink)) {
2065 StatementRef = REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink);
2066 NextLink = GetNextNode (&StatementList.StatementList, NextLink);
2067
2068 ASSERT (StatementRef->Statement->Description != 0);
2069 if (StatementRef->Statement->Description != 0) {
2070 ASSERT (StatementRef->Statement->XuefiRedfishStr != NULL);
2071 TmpConfigureLangList[Index] = AllocateCopyPool (HiiStrSize (StatementRef->Statement->XuefiRedfishStr), (VOID *)StatementRef->Statement->XuefiRedfishStr);
2072 ++Index;
2073 }
2074 }
2075 }
2076
2077 *Count = StatementList.Count;
2078 *ConfigureLangList = TmpConfigureLangList;
2079
2080 DEBUG_REDFISH_THIS_MODULE (
2081 REDFISH_PLATFORM_CONFIG_DEBUG_CONFIG_LANG_REGEX,
2082 "%a: Number of configure language strings harvested: %d\n",
2083 __func__,
2084 StatementList.Count
2085 );
2086
2087 DEBUG_REDFISH_THIS_MODULE_CODE (
2088 REDFISH_PLATFORM_CONFIG_DEBUG_CONFIG_LANG_REGEX,
2089 DEBUG_REDFISH (DEBUG_REDFISH_COMPONENT_PLATFORM_CONFIG_DXE, "%a: Number of configure language strings harvested: %d\n", __func__, StatementList.Count);
2090 for (Index = 0; Index < *Count; Index++) {
2091 DEBUG_REDFISH (DEBUG_REDFISH_COMPONENT_PLATFORM_CONFIG_DXE, " (%d) %s\n", Index, TmpConfigureLangList[Index]);
2092 }
2093
2094 );
2095
2096RELEASE_RESOURCE:
2097
2098 if (FullSchema != NULL) {
2099 FreePool (FullSchema);
2100 }
2101
2102 if (StatementList.Count > 0) {
2103 ReleaseStatementList (&StatementList);
2104 }
2105
2106 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: exit.\n", __func__));
2107 return Status;
2108}
2109
2110/**
2111 Get the list of supported Redfish schema from platform configuration.
2112
2113 @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
2114 @param[out] SupportedSchema The supported schema list which is separated by ';'.
2115 For example: "x-UEFI-redfish-Memory.v1_7_1;x-UEFI-redfish-Boot.v1_0_1"
2116 The SupportedSchema is allocated by the callee. It's caller's
2117 responsibility to free this buffer using FreePool().
2118
2119 @retval EFI_SUCCESS Schema is returned successfully.
2120 @retval Others Some error happened.
2121
2122**/
2123EFI_STATUS
2124EFIAPI
2125RedfishPlatformConfigProtocolGetSupportedSchema (
2126 IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
2127 OUT CHAR8 **SupportedSchema
2128 )
2129{
2130 REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate;
2131 EFI_STATUS Status;
2132 LIST_ENTRY *HiiFormsetLink;
2133 LIST_ENTRY *HiiFormsetNextLink;
2134 REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate;
2135 UINTN Index;
2136 UINTN StringSize;
2137 CHAR8 *StringBuffer;
2138 UINTN StringIndex;
2139
2140 if ((This == NULL) || (SupportedSchema == NULL)) {
2141 return EFI_INVALID_PARAMETER;
2142 }
2143
2144 *SupportedSchema = NULL;
2145
2146 RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
2147
2148 Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);
2149 if (EFI_ERROR (Status)) {
2150 DEBUG ((DEBUG_ERROR, "%a: ProcessPendingList failure: %r\n", __func__, Status));
2151 return Status;
2152 }
2153
2154 if (IsListEmpty (&RedfishPlatformConfigPrivate->FormsetList)) {
2155 return EFI_NOT_FOUND;
2156 }
2157
2158 //
2159 // Calculate for string buffer size.
2160 //
2161 StringSize = 0;
2162 HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate->FormsetList);
2163 while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink)) {
2164 HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink);
2165 HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
2166
2167 if (HiiFormsetPrivate->SupportedSchema.Count > 0) {
2168 for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count; Index++) {
2169 StringSize += AsciiStrSize (HiiFormsetPrivate->SupportedSchema.SchemaList[Index]);
2170 }
2171 }
2172
2173 HiiFormsetLink = HiiFormsetNextLink;
2174 }
2175
2176 if (StringSize == 0) {
2177 return EFI_NOT_FOUND;
2178 }
2179
2180 StringBuffer = AllocatePool (StringSize);
2181 if (StringBuffer == NULL) {
2182 return EFI_OUT_OF_RESOURCES;
2183 }
2184
2185 StringIndex = 0;
2186 HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate->FormsetList);
2187 while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink)) {
2188 HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink);
2189 HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
2190
2191 if (HiiFormsetPrivate->SupportedSchema.Count > 0) {
2192 for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count; Index++) {
2193 AsciiStrCpyS (&StringBuffer[StringIndex], (StringSize - StringIndex), HiiFormsetPrivate->SupportedSchema.SchemaList[Index]);
2194 StringIndex += AsciiStrLen (HiiFormsetPrivate->SupportedSchema.SchemaList[Index]);
2195 StringBuffer[StringIndex] = ';';
2196 ++StringIndex;
2197 }
2198 }
2199
2200 HiiFormsetLink = HiiFormsetNextLink;
2201 }
2202
2203 StringBuffer[--StringIndex] = '\0';
2204
2205 *SupportedSchema = StringBuffer;
2206
2207 return EFI_SUCCESS;
2208}
2209
2210/**
2211 Get Redfish default value with the given Schema and Configure Language.
2212
2213 @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
2214 @param[in] Schema The Redfish schema to query.
2215 @param[in] Version The Redfish version to query.
2216 @param[in] ConfigureLang The target value which match this configure Language.
2217 @param[in] DefaultClass The UEFI defined default class.
2218 Please refer to UEFI spec. 33.2.5.8 "defaults" for details.
2219 @param[out] Value The returned value.
2220
2221 @retval EFI_SUCCESS Value is returned successfully.
2222 @retval Others Some error happened.
2223
2224**/
2225EFI_STATUS
2226EFIAPI
2227RedfishPlatformConfigProtocolGetDefaultValue (
2228 IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
2229 IN CHAR8 *Schema,
2230 IN CHAR8 *Version,
2231 IN EFI_STRING ConfigureLang,
2232 IN UINT16 DefaultClass,
2233 OUT EDKII_REDFISH_VALUE *Value
2234 )
2235{
2236 EFI_STATUS Status;
2237 REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate;
2238 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement;
2239 CHAR8 *FullSchema;
2240 HII_STATEMENT_VALUE DefaultValue;
2241
2242 if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || (Value == NULL)) {
2243 return EFI_INVALID_PARAMETER;
2244 }
2245
2246 RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
2247 ZeroMem (&DefaultValue, sizeof (HII_STATEMENT_VALUE));
2248 ZeroMem (Value, sizeof (EDKII_REDFISH_VALUE));
2249
2250 FullSchema = NULL;
2251 FullSchema = GetFullSchemaString (Schema, Version);
2252 if (FullSchema == NULL) {
2253 return EFI_OUT_OF_RESOURCES;
2254 }
2255
2256 Status = RedfishPlatformConfigGetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &TargetStatement);
2257 if (EFI_ERROR (Status)) {
2258 goto RELEASE_RESOURCE;
2259 }
2260
2261 if (TargetStatement->Suppressed) {
2262 Status = EFI_ACCESS_DENIED;
2263 goto RELEASE_RESOURCE;
2264 }
2265
2266 Status = GetQuestionDefault (TargetStatement->ParentForm->ParentFormset->HiiFormSet, TargetStatement->ParentForm->HiiForm, TargetStatement->HiiStatement, DefaultClass, &DefaultValue);
2267 if (EFI_ERROR (Status)) {
2268 DEBUG ((DEBUG_ERROR, "%a: GetQuestionDefault failed: %r\n", __func__, Status));
2269 goto RELEASE_RESOURCE;
2270 }
2271
2272 Status = HiiValueToRedfishValue (
2273 TargetStatement->ParentForm->ParentFormset->HiiHandle,
2274 FullSchema,
2275 TargetStatement->HiiStatement,
2276 &DefaultValue,
2277 Value
2278 );
2279 if (EFI_ERROR (Status)) {
2280 DEBUG ((DEBUG_ERROR, "%a: HiiValueToRedfishValue failed: %r\n", __func__, Status));
2281 }
2282
2283RELEASE_RESOURCE:
2284
2285 if (FullSchema != NULL) {
2286 FreePool (FullSchema);
2287 }
2288
2289 return Status;
2290}
2291
2292/**
2293 Get Redfish attribute value with the given Schema and Configure Language.
2294
2295 @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
2296 @param[in] Schema The Redfish schema to query.
2297 @param[in] Version The Redfish version to query.
2298 @param[in] ConfigureLang The target value which match this configure Language.
2299 @param[out] AttributeValue The attribute value.
2300
2301 @retval EFI_SUCCESS Value is returned successfully.
2302 @retval Others Some error happened.
2303
2304**/
2305EFI_STATUS
2306EFIAPI
2307RedfishPlatformConfigProtocolGetAttribute (
2308 IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
2309 IN CHAR8 *Schema,
2310 IN CHAR8 *Version,
2311 IN EFI_STRING ConfigureLang,
2312 OUT EDKII_REDFISH_ATTRIBUTE *AttributeValue
2313 )
2314{
2315 EFI_STATUS Status;
2316 REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate;
2317 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement;
2318 CHAR8 *FullSchema;
2319 CHAR8 *Buffer;
2320
2321 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Entry\n", __func__));
2322 if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || (AttributeValue == NULL)) {
2323 return EFI_INVALID_PARAMETER;
2324 }
2325
2326 RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
2327 ZeroMem (AttributeValue, sizeof (EDKII_REDFISH_ATTRIBUTE));
2328 FullSchema = NULL;
2329 FullSchema = GetFullSchemaString (Schema, Version);
2330 if (FullSchema == NULL) {
2331 return EFI_OUT_OF_RESOURCES;
2332 }
2333
2334 Status = RedfishPlatformConfigGetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &TargetStatement);
2335 if (EFI_ERROR (Status)) {
2336 goto RELEASE_RESOURCE;
2337 }
2338
2339 if (TargetStatement->Description != 0) {
2340 AttributeValue->AttributeName = HiiGetRedfishAsciiString (TargetStatement->ParentForm->ParentFormset->HiiHandle, FullSchema, TargetStatement->Description);
2341 Buffer = GetAttributeNameFromConfigLanguage (AttributeValue->AttributeName);
2342 if (Buffer != NULL) {
2343 FreePool (AttributeValue->AttributeName);
2344 AttributeValue->AttributeName = Buffer;
2345 }
2346
2347 AttributeValue->DisplayName = HiiGetEnglishAsciiString (TargetStatement->ParentForm->ParentFormset->HiiHandle, TargetStatement->Description);
2348 }
2349
2350 if (TargetStatement->Help != 0) {
2351 AttributeValue->HelpText = HiiGetEnglishAsciiString (TargetStatement->ParentForm->ParentFormset->HiiHandle, TargetStatement->Help);
2352 }
2353
2354 AttributeValue->ReadOnly = ((TargetStatement->Flags & EFI_IFR_FLAG_READ_ONLY) == 0 ? FALSE : TRUE);
2355 AttributeValue->ResetRequired = ((TargetStatement->Flags & EFI_IFR_FLAG_RESET_REQUIRED) == 0 ? FALSE : TRUE);
2356 AttributeValue->Type = HiiStatementToAttributeType (TargetStatement->HiiStatement);
2357 AttributeValue->Suppress = TargetStatement->Suppressed;
2358 AttributeValue->GrayedOut = TargetStatement->GrayedOut;
2359
2360 //
2361 // Build up menu path
2362 //
2363 if (RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
2364 AttributeValue->MenuPath = BuildMenuPath (TargetStatement);
2365 if (AttributeValue->MenuPath == NULL) {
2366 DEBUG ((DEBUG_ERROR, "%a: failed to build menu path for \"%a\"\n", __func__, AttributeValue->AttributeName));
2367 }
2368 }
2369
2370 //
2371 // Deal with maximum and minimum
2372 //
2373 if (AttributeValue->Type == RedfishAttributeTypeString) {
2374 AttributeValue->StrMaxSize = TargetStatement->StatementData.StrMaxSize;
2375 AttributeValue->StrMinSize = TargetStatement->StatementData.StrMinSize;
2376 } else if (AttributeValue->Type == RedfishAttributeTypeInteger) {
2377 AttributeValue->NumMaximum = TargetStatement->StatementData.NumMaximum;
2378 AttributeValue->NumMinimum = TargetStatement->StatementData.NumMinimum;
2379 AttributeValue->NumStep = TargetStatement->StatementData.NumStep;
2380 }
2381
2382 //
2383 // Provide value array if this is enumeration type.
2384 //
2385 if (TargetStatement->HiiStatement->Operand == EFI_IFR_ONE_OF_OP) {
2386 Status = OneOfStatementToAttributeValues (TargetStatement->ParentForm->ParentFormset->HiiHandle, FullSchema, TargetStatement, &AttributeValue->Values);
2387 if (EFI_ERROR (Status)) {
2388 DEBUG ((DEBUG_ERROR, "%a: failed to convert one-of options to attribute values: %r\n", __func__, Status));
2389 }
2390 }
2391
2392RELEASE_RESOURCE:
2393
2394 if (FullSchema != NULL) {
2395 FreePool (FullSchema);
2396 }
2397
2398 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Exit\n", __func__));
2399 return Status;
2400}
2401
2402/**
2403 Functions which are registered to receive notification of
2404 database events have this prototype. The actual event is encoded
2405 in NotifyType. The following table describes how PackageType,
2406 PackageGuid, Handle, and Package are used for each of the
2407 notification types.
2408
2409 @param[in] PackageType Package type of the notification.
2410 @param[in] PackageGuid If PackageType is
2411 EFI_HII_PACKAGE_TYPE_GUID, then this is
2412 the pointer to the GUID from the Guid
2413 field of EFI_HII_PACKAGE_GUID_HEADER.
2414 Otherwise, it must be NULL.
2415 @param[in] Package Points to the package referred to by the
2416 notification Handle The handle of the package
2417 list which contains the specified package.
2418 @param[in] Handle The HII handle.
2419 @param[in] NotifyType The type of change concerning the
2420 database. See
2421 EFI_HII_DATABASE_NOTIFY_TYPE.
2422
2423**/
2424EFI_STATUS
2425EFIAPI
2426RedfishPlatformConfigFormUpdateNotify (
2427 IN UINT8 PackageType,
2428 IN CONST EFI_GUID *PackageGuid,
2429 IN CONST EFI_HII_PACKAGE_HEADER *Package,
2430 IN EFI_HII_HANDLE Handle,
2431 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
2432 )
2433{
2434 EFI_STATUS Status;
2435
2436 if ((NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK) || (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK)) {
2437 //
2438 // HII formset on this handle is updated by driver during run-time. The formset needs to be reloaded.
2439 //
2440 Status = NotifyFormsetUpdate (Handle, &mRedfishPlatformConfigPrivate->PendingList);
2441 if (EFI_ERROR (Status)) {
2442 DEBUG ((DEBUG_ERROR, "%a: failed to notify updated formset of HII handle: 0x%x\n", __func__, Handle));
2443 return Status;
2444 }
2445 } else if (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK) {
2446 //
2447 // HII resource is removed. The formset is no longer exist.
2448 //
2449 Status = NotifyFormsetDeleted (Handle, &mRedfishPlatformConfigPrivate->PendingList);
2450 if (EFI_ERROR (Status)) {
2451 DEBUG ((DEBUG_ERROR, "%a: failed to notify deleted formset of HII handle: 0x%x\n", __func__, Handle));
2452 return Status;
2453 }
2454 }
2455
2456 return EFI_SUCCESS;
2457}
2458
2459/**
2460 This is a EFI_HII_STRING_PROTOCOL notification event handler.
2461
2462 Install HII package notification.
2463
2464 @param[in] Event Event whose notification function is being invoked.
2465 @param[in] Context Pointer to the notification function's context.
2466
2467**/
2468VOID
2469EFIAPI
2470HiiStringProtocolInstalled (
2471 IN EFI_EVENT Event,
2472 IN VOID *Context
2473 )
2474{
2475 EFI_STATUS Status;
2476
2477 //
2478 // Locate HII database protocol.
2479 //
2480 Status = gBS->LocateProtocol (
2481 &gEfiHiiStringProtocolGuid,
2482 NULL,
2483 (VOID **)&mRedfishPlatformConfigPrivate->HiiString
2484 );
2485 if (EFI_ERROR (Status)) {
2486 DEBUG ((DEBUG_ERROR, "%a: locate EFI_HII_STRING_PROTOCOL failure: %r\n", __func__, Status));
2487 return;
2488 }
2489
2490 gBS->CloseEvent (Event);
2491 mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent = NULL;
2492}
2493
2494/**
2495 This is a EFI_HII_DATABASE_PROTOCOL notification event handler.
2496
2497 Install HII package notification.
2498
2499 @param[in] Event Event whose notification function is being invoked.
2500 @param[in] Context Pointer to the notification function's context.
2501
2502**/
2503VOID
2504EFIAPI
2505HiiDatabaseProtocolInstalled (
2506 IN EFI_EVENT Event,
2507 IN VOID *Context
2508 )
2509{
2510 EFI_STATUS Status;
2511
2512 //
2513 // Locate HII database protocol.
2514 //
2515 Status = gBS->LocateProtocol (
2516 &gEfiHiiDatabaseProtocolGuid,
2517 NULL,
2518 (VOID **)&mRedfishPlatformConfigPrivate->HiiDatabase
2519 );
2520 if (EFI_ERROR (Status)) {
2521 DEBUG ((DEBUG_ERROR, "%a: locate EFI_HII_DATABASE_PROTOCOL failure: %r\n", __func__, Status));
2522 return;
2523 }
2524
2525 //
2526 // Register package notification when new form package is installed.
2527 //
2528 Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify (
2529 mRedfishPlatformConfigPrivate->HiiDatabase,
2530 EFI_HII_PACKAGE_FORMS,
2531 NULL,
2532 RedfishPlatformConfigFormUpdateNotify,
2533 EFI_HII_DATABASE_NOTIFY_NEW_PACK,
2534 &mRedfishPlatformConfigPrivate->NotifyHandle
2535 );
2536 if (EFI_ERROR (Status)) {
2537 DEBUG ((DEBUG_ERROR, "%a: RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __func__, Status));
2538 }
2539
2540 //
2541 // Register package notification when new form package is updated.
2542 //
2543 Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify (
2544 mRedfishPlatformConfigPrivate->HiiDatabase,
2545 EFI_HII_PACKAGE_FORMS,
2546 NULL,
2547 RedfishPlatformConfigFormUpdateNotify,
2548 EFI_HII_DATABASE_NOTIFY_ADD_PACK,
2549 &mRedfishPlatformConfigPrivate->NotifyHandle
2550 );
2551 if (EFI_ERROR (Status)) {
2552 DEBUG ((DEBUG_ERROR, "%a: RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __func__, Status));
2553 }
2554
2555 gBS->CloseEvent (Event);
2556 mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent = NULL;
2557}
2558
2559/**
2560 This is a EFI_REGULAR_EXPRESSION_PROTOCOL notification event handler.
2561
2562 @param[in] Event Event whose notification function is being invoked.
2563 @param[in] Context Pointer to the notification function's context.
2564
2565**/
2566VOID
2567EFIAPI
2568RegexProtocolInstalled (
2569 IN EFI_EVENT Event,
2570 IN VOID *Context
2571 )
2572{
2573 EFI_STATUS Status;
2574
2575 //
2576 // Locate regular expression protocol.
2577 //
2578 Status = gBS->LocateProtocol (
2579 &gEfiRegularExpressionProtocolGuid,
2580 NULL,
2581 (VOID **)&mRedfishPlatformConfigPrivate->RegularExpressionProtocol
2582 );
2583 if (EFI_ERROR (Status)) {
2584 DEBUG ((DEBUG_ERROR, "%a: locate EFI_REGULAR_EXPRESSION_PROTOCOL failure: %r\n", __func__, Status));
2585 return;
2586 }
2587
2588 gBS->CloseEvent (Event);
2589 mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent = NULL;
2590}
2591
2592/**
2593 Unloads an image.
2594
2595 @param ImageHandle Handle that identifies the image to be unloaded.
2596
2597 @retval EFI_SUCCESS The image has been unloaded.
2598 @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
2599
2600**/
2601EFI_STATUS
2602EFIAPI
2603RedfishPlatformConfigDxeUnload (
2604 IN EFI_HANDLE ImageHandle
2605 )
2606{
2607 EFI_STATUS Status;
2608
2609 if (mRedfishPlatformConfigPrivate != NULL) {
2610 Status = gBS->UninstallProtocolInterface (
2611 mRedfishPlatformConfigPrivate->ImageHandle,
2612 &gEdkIIRedfishPlatformConfigProtocolGuid,
2613 (VOID *)&mRedfishPlatformConfigPrivate->Protocol
2614 );
2615 if (EFI_ERROR (Status)) {
2616 DEBUG ((DEBUG_ERROR, "%a: can not uninstall gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __func__, Status));
2617 ASSERT (FALSE);
2618 }
2619
2620 //
2621 // Close events
2622 //
2623 if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent != NULL) {
2624 gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent);
2625 }
2626
2627 if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent != NULL) {
2628 gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent);
2629 }
2630
2631 if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent != NULL) {
2632 gBS->CloseEvent (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent);
2633 }
2634
2635 //
2636 // Unregister package notification.
2637 //
2638 if (mRedfishPlatformConfigPrivate->NotifyHandle != NULL) {
2639 mRedfishPlatformConfigPrivate->HiiDatabase->UnregisterPackageNotify (
2640 mRedfishPlatformConfigPrivate->HiiDatabase,
2641 mRedfishPlatformConfigPrivate->NotifyHandle
2642 );
2643 }
2644
2645 ReleaseFormsetList (&mRedfishPlatformConfigPrivate->FormsetList);
2646 FreePool (mRedfishPlatformConfigPrivate);
2647 mRedfishPlatformConfigPrivate = NULL;
2648 }
2649
2650 return EFI_SUCCESS;
2651}
2652
2653/**
2654 This is the declaration of an EFI image entry point. This entry point is
2655 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
2656 both device drivers and bus drivers.
2657
2658 @param ImageHandle The firmware allocated handle for the UEFI image.
2659 @param SystemTable A pointer to the EFI System Table.
2660
2661 @retval EFI_SUCCESS The operation completed successfully.
2662 @retval Others An unexpected error occurred.
2663**/
2664EFI_STATUS
2665EFIAPI
2666RedfishPlatformConfigDxeEntryPoint (
2667 IN EFI_HANDLE ImageHandle,
2668 IN EFI_SYSTEM_TABLE *SystemTable
2669 )
2670{
2671 EFI_STATUS Status;
2672
2673 mRedfishPlatformConfigPrivate = (REDFISH_PLATFORM_CONFIG_PRIVATE *)AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PRIVATE));
2674 if (mRedfishPlatformConfigPrivate == NULL) {
2675 DEBUG ((DEBUG_ERROR, "%a: can not allocate pool for REDFISH_PLATFORM_CONFIG_PRIVATE\n", __func__));
2676 ASSERT (FALSE);
2677 return EFI_OUT_OF_RESOURCES;
2678 }
2679
2680 //
2681 // Protocol initialization
2682 //
2683 mRedfishPlatformConfigPrivate->ImageHandle = ImageHandle;
2684 mRedfishPlatformConfigPrivate->Protocol.Revision = REDFISH_PLATFORM_CONFIG_VERSION;
2685 mRedfishPlatformConfigPrivate->Protocol.GetValue = RedfishPlatformConfigProtocolGetValue;
2686 mRedfishPlatformConfigPrivate->Protocol.SetValue = RedfishPlatformConfigProtocolSetValue;
2687 mRedfishPlatformConfigPrivate->Protocol.GetConfigureLang = RedfishPlatformConfigProtocolGetConfigureLang;
2688 mRedfishPlatformConfigPrivate->Protocol.GetSupportedSchema = RedfishPlatformConfigProtocolGetSupportedSchema;
2689 mRedfishPlatformConfigPrivate->Protocol.GetAttribute = RedfishPlatformConfigProtocolGetAttribute;
2690 mRedfishPlatformConfigPrivate->Protocol.GetDefaultValue = RedfishPlatformConfigProtocolGetDefaultValue;
2691
2692 InitializeListHead (&mRedfishPlatformConfigPrivate->FormsetList);
2693 InitializeListHead (&mRedfishPlatformConfigPrivate->PendingList);
2694
2695 Status = gBS->InstallProtocolInterface (
2696 &ImageHandle,
2697 &gEdkIIRedfishPlatformConfigProtocolGuid,
2698 EFI_NATIVE_INTERFACE,
2699 (VOID *)&mRedfishPlatformConfigPrivate->Protocol
2700 );
2701 if (EFI_ERROR (Status)) {
2702 DEBUG ((DEBUG_ERROR, "%a: can not install gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __func__, Status));
2703 ASSERT (FALSE);
2704 }
2705
2706 //
2707 // Install protocol notification if HII database protocol is installed.
2708 //
2709 mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent (
2710 &gEfiHiiDatabaseProtocolGuid,
2711 TPL_CALLBACK,
2712 HiiDatabaseProtocolInstalled,
2713 NULL,
2714 &mRedfishPlatformConfigPrivate->HiiDbNotify.Registration
2715 );
2716 if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent == NULL) {
2717 DEBUG ((DEBUG_ERROR, "%a: failed to create protocol notification for gEfiHiiDatabaseProtocolGuid\n", __func__));
2718 ASSERT (FALSE);
2719 }
2720
2721 //
2722 // Install protocol notification if HII string protocol is installed.
2723 //
2724 mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent (
2725 &gEfiHiiStringProtocolGuid,
2726 TPL_CALLBACK,
2727 HiiStringProtocolInstalled,
2728 NULL,
2729 &mRedfishPlatformConfigPrivate->HiiStringNotify.Registration
2730 );
2731 if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent == NULL) {
2732 DEBUG ((DEBUG_ERROR, "%a: failed to create protocol notification for gEfiHiiStringProtocolGuid\n", __func__));
2733 ASSERT (FALSE);
2734 }
2735
2736 //
2737 // Install protocol notification if regular expression protocol is installed.
2738 //
2739 mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent (
2740 &gEfiRegularExpressionProtocolGuid,
2741 TPL_CALLBACK,
2742 RegexProtocolInstalled,
2743 NULL,
2744 &mRedfishPlatformConfigPrivate->RegexNotify.Registration
2745 );
2746 if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent == NULL) {
2747 DEBUG ((DEBUG_ERROR, "%a: failed to create protocol notification for gEfiRegularExpressionProtocolGuid\n", __func__));
2748 ASSERT (FALSE);
2749 }
2750
2751 return EFI_SUCCESS;
2752}
Note: See TracBrowser for help on using the repository browser.

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