VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.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: 72.8 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#include "RedfishPlatformConfigDxe.h"
12#include "RedfishPlatformConfigImpl.h"
13
14extern REDFISH_PLATFORM_CONFIG_PRIVATE *mRedfishPlatformConfigPrivate;
15
16/**
17 Debug dump HII string.
18
19 @param[in] HiiHandle HII handle instance
20 @param[in] StringId HII string to dump
21
22 @retval EFI_SUCCESS Dump HII string successfully
23 @retval Others Errors occur
24
25**/
26EFI_STATUS
27DumpHiiString (
28 IN EFI_HII_HANDLE HiiHandle,
29 IN EFI_STRING_ID StringId
30 )
31{
32 EFI_STRING String;
33
34 if ((HiiHandle == NULL) || (StringId == 0)) {
35 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "???"));
36 return EFI_INVALID_PARAMETER;
37 }
38
39 String = HiiGetString (HiiHandle, StringId, NULL);
40 if (String == NULL) {
41 return EFI_NOT_FOUND;
42 }
43
44 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%s", String));
45 FreePool (String);
46
47 return EFI_SUCCESS;
48}
49
50/**
51 Debug dump HII form-set data.
52
53 @param[in] FormsetPrivate HII form-set private instance.
54
55 @retval EFI_SUCCESS Dump form-set successfully
56 @retval Others Errors occur
57
58**/
59EFI_STATUS
60DumpFormset (
61 IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate
62 )
63{
64 LIST_ENTRY *HiiFormLink;
65 LIST_ENTRY *HiiNextFormLink;
66 REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate;
67 LIST_ENTRY *HiiStatementLink;
68 LIST_ENTRY *HiiNextStatementLink;
69 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate;
70 UINTN Index;
71
72 if (FormsetPrivate == NULL) {
73 return EFI_INVALID_PARAMETER;
74 }
75
76 Index = 0;
77 HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList);
78 while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) {
79 HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);
80 HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList, HiiFormLink);
81
82 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " [%d] form: %d title: ", ++Index, HiiFormPrivate->Id));
83 DumpHiiString (FormsetPrivate->HiiHandle, HiiFormPrivate->Title);
84 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "\n"));
85
86 HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
87 while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
88 HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
89 HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);
90
91 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " QID: 0x%x Prompt: ", HiiStatementPrivate->QuestionId));
92 DumpHiiString (FormsetPrivate->HiiHandle, HiiStatementPrivate->Description);
93 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "\n"));
94
95 HiiStatementLink = HiiNextStatementLink;
96 }
97
98 HiiFormLink = HiiNextFormLink;
99 }
100
101 return EFI_SUCCESS;
102}
103
104/**
105 Debug dump HII form-set list.
106
107 @param[in] FormsetList Form-set list instance
108
109 @retval EFI_SUCCESS Dump list successfully
110 @retval Others Errors occur
111
112**/
113EFI_STATUS
114DumpFormsetList (
115 IN LIST_ENTRY *FormsetList
116 )
117{
118 LIST_ENTRY *HiiFormsetLink;
119 LIST_ENTRY *HiiFormsetNextLink;
120 REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate;
121 UINTN Index;
122
123 if (FormsetList == NULL) {
124 return EFI_INVALID_PARAMETER;
125 }
126
127 if (IsListEmpty (FormsetList)) {
128 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Empty formset list\n", __func__));
129 return EFI_SUCCESS;
130 }
131
132 Index = 0;
133 HiiFormsetLink = GetFirstNode (FormsetList);
134 while (!IsNull (FormsetList, HiiFormsetLink)) {
135 HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
136 HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
137
138 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "[%d] HII Handle: 0x%x formset: %g at %s\n", ++Index, HiiFormsetPrivate->HiiHandle, &HiiFormsetPrivate->Guid, HiiFormsetPrivate->DevicePathStr));
139 DumpFormset (HiiFormsetPrivate);
140
141 HiiFormsetLink = HiiFormsetNextLink;
142 }
143
144 return EFI_SUCCESS;
145}
146
147/**
148 Return the HII string length. We don't check word alignment
149 of the input string as same as the checking in StrLen
150 function, because the HII string in the database is compact
151 at the byte alignment.
152
153 @param[in] String Input UCS format string.
154
155 @retval Length of the string.
156
157**/
158UINTN
159EFIAPI
160HiiStrLen (
161 IN CONST CHAR16 *String
162 )
163{
164 UINTN Length;
165
166 ASSERT (String != NULL);
167
168 for (Length = 0; *String != L'\0'; String++, Length++) {
169 }
170
171 return Length;
172}
173
174/**
175 Return the HII string size. We don't check word alignment
176 of the input string as same as the checking in StrLen
177 function, because the HII string in the database is compact
178 at the byte alignment.
179
180 @param[in] String Input UCS format string.
181
182 @retval Size of the string.
183
184**/
185UINTN
186EFIAPI
187HiiStrSize (
188 IN CONST CHAR16 *String
189 )
190{
191 return (HiiStrLen (String) + 1) * sizeof (*String);
192}
193
194/**
195 Compare two HII strings. We don't check word alignment
196 of the input string as same as the checking in StrLen
197 function, because the HII string in the database is compact
198 at the byte alignment.
199
200 @param[in] FirstString Input UCS format of string to search.
201 @param[in] SecondString Input UCS format of string to look for in
202 FirstString;
203
204 @retval 0 The strings are identical.
205 !0 The strings are not identical.
206
207**/
208INTN
209EFIAPI
210HiiStrCmp (
211 IN CONST CHAR16 *FirstString,
212 IN CONST CHAR16 *SecondString
213 )
214{
215 //
216 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength
217 //
218 ASSERT (HiiStrSize (FirstString) != 0);
219 ASSERT (HiiStrSize (SecondString) != 0);
220
221 while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {
222 FirstString++;
223 SecondString++;
224 }
225
226 return *FirstString - *SecondString;
227}
228
229/**
230 Delete a string from HII Package List by given HiiHandle.
231
232 @param[in] StringId Id of the string in HII database.
233 @param[in] HiiHandle The HII package list handle.
234
235 @retval EFI_SUCCESS The string was deleted successfully.
236 @retval EFI_INVALID_PARAMETER StringId is zero.
237
238**/
239EFI_STATUS
240HiiDeleteString (
241 IN EFI_STRING_ID StringId,
242 IN EFI_HII_HANDLE HiiHandle
243 )
244{
245 CHAR16 NullChar;
246
247 if (StringId == 0x00) {
248 return EFI_INVALID_PARAMETER;
249 }
250
251 NullChar = CHAR_NULL;
252 HiiSetString (HiiHandle, StringId, &NullChar, NULL);
253
254 return EFI_SUCCESS;
255}
256
257/**
258 Retrieves a unicode string from a string package in a given language. The
259 returned string is allocated using AllocatePool(). The caller is responsible
260 for freeing the allocated buffer using FreePool().
261
262 If HiiHandle is NULL, then ASSERT().
263 If StringId is 0, then ASSET.
264
265 @param[in] HiiHandle A handle that was previously registered in the HII Database.
266 @param[in] Language The specified configure language to get string.
267 @param[in] StringId The identifier of the string to retrieved from the string
268 package associated with HiiHandle.
269
270 @retval NULL The string specified by StringId is not present in the string package.
271 @retval Other The string was returned.
272
273**/
274EFI_STRING
275HiiGetRedfishString (
276 IN EFI_HII_HANDLE HiiHandle,
277 IN CHAR8 *Language,
278 IN EFI_STRING_ID StringId
279 )
280{
281 EFI_STATUS Status;
282 UINTN StringSize;
283 CHAR16 TempString;
284 EFI_STRING String;
285
286 if ((mRedfishPlatformConfigPrivate->HiiString == NULL) || (HiiHandle == NULL) || (StringId == 0) || IS_EMPTY_STRING (Language)) {
287 ASSERT (FALSE);
288 return NULL;
289 }
290
291 //
292 // Retrieve the size of the string in the string package for the BestLanguage
293 //
294 StringSize = 0;
295 Status = mRedfishPlatformConfigPrivate->HiiString->GetString (
296 mRedfishPlatformConfigPrivate->HiiString,
297 Language,
298 HiiHandle,
299 StringId,
300 &TempString,
301 &StringSize,
302 NULL
303 );
304 //
305 // If GetString() returns EFI_SUCCESS for a zero size,
306 // then there are no supported languages registered for HiiHandle. If GetString()
307 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
308 // in the HII Database
309 //
310 if (Status != EFI_BUFFER_TOO_SMALL) {
311 return NULL;
312 }
313
314 //
315 // Allocate a buffer for the return string
316 //
317 String = AllocateZeroPool (StringSize);
318 if (String == NULL) {
319 return NULL;
320 }
321
322 //
323 // Retrieve the string from the string package
324 //
325 Status = mRedfishPlatformConfigPrivate->HiiString->GetString (
326 mRedfishPlatformConfigPrivate->HiiString,
327 Language,
328 HiiHandle,
329 StringId,
330 String,
331 &StringSize,
332 NULL
333 );
334 if (EFI_ERROR (Status)) {
335 //
336 // Free the buffer and return NULL if the supported languages can not be retrieved.
337 //
338 FreePool (String);
339 String = NULL;
340 }
341
342 //
343 // Return the Null-terminated Unicode string
344 //
345 return String;
346}
347
348/**
349 Retrieves a ASCII string from a string package in a given language. The
350 returned string is allocated using AllocatePool(). The caller is responsible
351 for freeing the allocated buffer using FreePool().
352
353 If HiiHandle is NULL, then ASSERT().
354 If StringId is 0, then ASSET.
355
356 @param[in] HiiHandle A handle that was previously registered in the HII Database.
357 @param[in] Language The specified configure language to get string.
358 @param[in] StringId The identifier of the string to retrieved from the string
359 package associated with HiiHandle.
360
361 @retval NULL The string specified by StringId is not present in the string package.
362 @retval Other The string was returned.
363
364**/
365CHAR8 *
366HiiGetRedfishAsciiString (
367 IN EFI_HII_HANDLE HiiHandle,
368 IN CHAR8 *Language,
369 IN EFI_STRING_ID StringId
370 )
371{
372 EFI_STRING HiiString;
373 CHAR8 *AsciiString;
374
375 HiiString = HiiGetRedfishString (HiiHandle, Language, StringId);
376 if (HiiString == NULL) {
377 DEBUG ((DEBUG_ERROR, "%a: Can not find string ID: 0x%x with %a\n", __func__, StringId, Language));
378 return NULL;
379 }
380
381 AsciiString = StrToAsciiStr (HiiString);
382 FreePool (HiiString);
383
384 return AsciiString;
385}
386
387/**
388 Get ASCII string from HII database in English language. The returned string is allocated
389 using AllocatePool(). The caller is responsible for freeing the allocated buffer using
390 FreePool().
391
392 @param[in] HiiHandle A handle that was previously registered in the HII Database.
393 @param[in] StringId The identifier of the string to retrieved from the string
394 package associated with HiiHandle.
395
396 @retval NULL The string specified by StringId is not present in the string package.
397 @retval Other The string was returned.
398
399**/
400CHAR8 *
401HiiGetEnglishAsciiString (
402 IN EFI_HII_HANDLE HiiHandle,
403 IN EFI_STRING_ID StringId
404 )
405{
406 EFI_STRING HiiString;
407 CHAR8 *AsciiString;
408
409 HiiString = HiiGetRedfishString (HiiHandle, ENGLISH_LANGUAGE_CODE, StringId);
410 if (HiiString == NULL) {
411 DEBUG ((DEBUG_ERROR, "%a: Can not find string ID: 0x%x with %a\n", __func__, StringId, ENGLISH_LANGUAGE_CODE));
412 return NULL;
413 }
414
415 AsciiString = StrToAsciiStr (HiiString);
416 FreePool (HiiString);
417
418 return AsciiString;
419}
420
421/**
422 Check and see if this is supported schema or not.
423
424 @param[in] SupportedSchema The list of supported schema.
425 @param[in] Schema Schema string to be checked.
426
427 @retval BOOLEAN TRUE if this is supported schema. FALSE otherwise.
428
429**/
430BOOLEAN
431CheckSupportedSchema (
432 IN REDFISH_PLATFORM_CONFIG_SCHEMA *SupportedSchema,
433 IN CHAR8 *Schema
434 )
435{
436 UINTN Index;
437
438 if ((SupportedSchema == NULL) || IS_EMPTY_STRING (Schema)) {
439 return FALSE;
440 }
441
442 if (SupportedSchema->Count == 0) {
443 return FALSE;
444 }
445
446 for (Index = 0; Index < SupportedSchema->Count; Index++) {
447 if (AsciiStrCmp (SupportedSchema->SchemaList[Index], Schema) == 0) {
448 return TRUE;
449 }
450 }
451
452 return FALSE;
453}
454
455/**
456 Get the list of supported schema from the given HII handle.
457
458 @param[in] HiiHandle HII handle instance.
459 @param[out] SupportedSchema Supported schema on this HII handle.
460
461 @retval EFI_SUCCESS Schema list is returned.
462 @retval EFI_INVALID_PARAMETER HiiHandle is NULL or SupportedSchema is NULL.
463 @retval EFI_NOT_FOUND No supported schema found.
464 @retval EFI_OUT_OF_RESOURCES System is out of memory.
465
466**/
467EFI_STATUS
468GetSupportedSchema (
469 IN EFI_HII_HANDLE HiiHandle,
470 OUT REDFISH_PLATFORM_CONFIG_SCHEMA *SupportedSchema
471 )
472{
473 CHAR8 *SupportedLanguages;
474 UINTN Index;
475 UINTN LangIndex;
476 UINTN Count;
477 UINTN StrSize;
478 UINTN ListIndex;
479
480 if ((HiiHandle == NULL) || (SupportedSchema == NULL)) {
481 return EFI_INVALID_PARAMETER;
482 }
483
484 SupportedSchema->Count = 0;
485
486 SupportedLanguages = HiiGetSupportedLanguages (HiiHandle);
487 if (SupportedLanguages == NULL) {
488 return EFI_NOT_FOUND;
489 }
490
491 Index = 0;
492 LangIndex = 0;
493 Count = 0;
494 while (TRUE) {
495 if ((SupportedLanguages[Index] == ';') || (SupportedLanguages[Index] == '\0')) {
496 if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) {
497 ++Count;
498 }
499
500 LangIndex = Index + 1;
501 }
502
503 if (SupportedLanguages[Index] == '\0') {
504 break;
505 }
506
507 ++Index;
508 }
509
510 if (Count == 0) {
511 return EFI_NOT_FOUND;
512 }
513
514 SupportedSchema->Count = Count;
515 SupportedSchema->SchemaList = AllocatePool (sizeof (CHAR8 *) * Count);
516 if (SupportedSchema->SchemaList == NULL) {
517 return EFI_OUT_OF_RESOURCES;
518 }
519
520 Index = 0;
521 LangIndex = 0;
522 ListIndex = 0;
523 while (TRUE) {
524 if ((SupportedLanguages[Index] == ';') || (SupportedLanguages[Index] == '\0')) {
525 if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) {
526 StrSize = Index - LangIndex;
527 SupportedSchema->SchemaList[ListIndex] = AllocateCopyPool ((StrSize + 1), &SupportedLanguages[LangIndex]);
528 SupportedSchema->SchemaList[ListIndex][StrSize] = '\0';
529 ++ListIndex;
530 }
531
532 LangIndex = Index + 1;
533 }
534
535 if (SupportedLanguages[Index] == '\0') {
536 break;
537 }
538
539 ++Index;
540 }
541
542 return EFI_SUCCESS;
543}
544
545/**
546 Search and find statement private instance by given regular expression pattern
547 which describes the Configure Language.
548
549 @param[in] RegularExpressionProtocol Regular express protocol.
550 @param[in] FormsetList Form-set list to search.
551 @param[in] Schema Schema to be matched.
552 @param[in] Pattern Regular expression pattern.
553 @param[out] StatementList Statement list that match above pattern.
554
555 @retval EFI_SUCCESS Statement list is returned.
556 @retval EFI_INVALID_PARAMETER Input parameter is NULL.
557 @retval EFI_NOT_READY Regular express protocol is NULL.
558 @retval EFI_NOT_FOUND No statement is found.
559 @retval EFI_OUT_OF_RESOURCES System is out of memory.
560
561**/
562EFI_STATUS
563GetStatementPrivateByConfigureLangRegex (
564 IN EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol,
565 IN LIST_ENTRY *FormsetList,
566 IN CHAR8 *Schema,
567 IN EFI_STRING Pattern,
568 OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST *StatementList
569 )
570{
571 LIST_ENTRY *HiiFormsetLink;
572 LIST_ENTRY *HiiFormsetNextLink;
573 REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate;
574 LIST_ENTRY *HiiFormLink;
575 LIST_ENTRY *HiiNextFormLink;
576 REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate;
577 LIST_ENTRY *HiiStatementLink;
578 LIST_ENTRY *HiiNextStatementLink;
579 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate;
580 EFI_STRING TmpString;
581 UINTN CaptureCount;
582 BOOLEAN IsMatch;
583 EFI_STATUS Status;
584 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF *StatementRef;
585
586 if ((FormsetList == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Pattern) || (StatementList == NULL)) {
587 return EFI_INVALID_PARAMETER;
588 }
589
590 if (RegularExpressionProtocol == NULL) {
591 return EFI_NOT_READY;
592 }
593
594 StatementList->Count = 0;
595 InitializeListHead (&StatementList->StatementList);
596
597 if (IsListEmpty (FormsetList)) {
598 return EFI_NOT_FOUND;
599 }
600
601 HiiFormsetLink = GetFirstNode (FormsetList);
602 while (!IsNull (FormsetList, HiiFormsetLink)) {
603 HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
604 HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
605
606 //
607 // Performance check.
608 // If there is no desired Redfish schema found, skip this formset.
609 //
610 if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema)) {
611 HiiFormsetLink = HiiFormsetNextLink;
612 continue;
613 }
614
615 HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList);
616 while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) {
617 HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink);
618 HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);
619
620 HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
621 while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
622 HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);
623 HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
624
625 if ((HiiStatementPrivate->Description != 0) &&
626 (RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_ALLOW_SUPPRESSED) || !HiiStatementPrivate->Suppressed))
627 {
628 TmpString = HiiStatementPrivate->XuefiRedfishStr;
629 if (TmpString != NULL) {
630 Status = RegularExpressionProtocol->MatchString (
631 RegularExpressionProtocol,
632 TmpString,
633 Pattern,
634 &gEfiRegexSyntaxTypePerlGuid,
635 &IsMatch,
636 NULL,
637 &CaptureCount
638 );
639 if (EFI_ERROR (Status)) {
640 DEBUG ((DEBUG_ERROR, "%a: MatchString \"%s\" failed: %r\n", __func__, Pattern, Status));
641 ASSERT (FALSE);
642 return Status;
643 }
644
645 //
646 // Found
647 //
648 if (IsMatch) {
649 StatementRef = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF));
650 if (StatementRef == NULL) {
651 return EFI_OUT_OF_RESOURCES;
652 }
653
654 StatementRef->Statement = HiiStatementPrivate;
655 InsertTailList (&StatementList->StatementList, &StatementRef->Link);
656 ++StatementList->Count;
657 }
658 } else {
659 if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
660 DEBUG ((DEBUG_ERROR, "%a: HiiStatementPrivate->XuefiRedfishStr is NULL, x-UEFI-string has something wrong.\n", __func__));
661 ASSERT (FALSE);
662 }
663 }
664 }
665
666 HiiStatementLink = HiiNextStatementLink;
667 }
668
669 HiiFormLink = HiiNextFormLink;
670 }
671
672 HiiFormsetLink = HiiFormsetNextLink;
673 }
674
675 return EFI_SUCCESS;
676}
677
678/**
679 Get statement private instance by the given configure language.
680
681 @param[in] FormsetList Form-set list to search.
682 @param[in] Schema Schema to be matched.
683 @param[in] ConfigureLang Configure language.
684
685 @retval REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE * Pointer to statement private instance.
686
687**/
688REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *
689GetStatementPrivateByConfigureLang (
690 IN LIST_ENTRY *FormsetList,
691 IN CHAR8 *Schema,
692 IN EFI_STRING ConfigureLang
693 )
694{
695 LIST_ENTRY *HiiFormsetLink;
696 LIST_ENTRY *HiiFormsetNextLink;
697 REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate;
698 LIST_ENTRY *HiiFormLink;
699 LIST_ENTRY *HiiNextFormLink;
700 REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate;
701 LIST_ENTRY *HiiStatementLink;
702 LIST_ENTRY *HiiNextStatementLink;
703 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate;
704 EFI_STRING TmpString;
705 UINTN Index;
706
707 if ((FormsetList == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang)) {
708 return NULL;
709 }
710
711 if (IsListEmpty (FormsetList)) {
712 return NULL;
713 }
714
715 Index = 0;
716 HiiFormsetLink = GetFirstNode (FormsetList);
717 while (!IsNull (FormsetList, HiiFormsetLink)) {
718 HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
719 HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
720
721 //
722 // Performance check.
723 // If there is no desired Redfish schema found, skip this formset.
724 //
725 if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema)) {
726 HiiFormsetLink = HiiFormsetNextLink;
727 continue;
728 }
729
730 HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList);
731 while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) {
732 HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink);
733 HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);
734
735 HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
736 while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
737 HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);
738 HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
739
740 if ((HiiStatementPrivate->Description != 0) &&
741 (RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_ALLOW_SUPPRESSED) || !HiiStatementPrivate->Suppressed))
742 {
743 TmpString = HiiStatementPrivate->XuefiRedfishStr;
744 if (TmpString != NULL) {
745 Index++;
746 DEBUG_REDFISH_THIS_MODULE (
747 REDFISH_PLATFORM_CONFIG_DEBUG_CONFIG_LANG_SEARCH,
748 "%a: [%d] check %s in QID: 0x%x form: 0x%x formset: %g\n",
749 __func__,
750 Index,
751 ConfigureLang,
752 HiiStatementPrivate->QuestionId,
753 HiiFormPrivate->Id,
754 &HiiFormsetPrivate->Guid
755 );
756 if (HiiStrCmp (TmpString, ConfigureLang) == 0) {
757 return HiiStatementPrivate;
758 }
759 } else {
760 if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
761 DEBUG ((DEBUG_ERROR, "%a: HiiStatementPrivate->XuefiRedfishStr is NULL, x-UEFI-string has something wrong.\n", __func__));
762 ASSERT (FALSE);
763 }
764 }
765 }
766
767 HiiStatementLink = HiiNextStatementLink;
768 }
769
770 HiiFormLink = HiiNextFormLink;
771 }
772
773 HiiFormsetLink = HiiFormsetNextLink;
774 }
775
776 return NULL;
777}
778
779/**
780 Get form-set private instance by the given HII handle.
781
782 @param[in] HiiHandle HII handle instance.
783 @param[in] FormsetList Form-set list to search.
784
785 @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * Pointer to form-set private instance.
786
787**/
788REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *
789GetFormsetPrivateByHiiHandle (
790 IN EFI_HII_HANDLE HiiHandle,
791 IN LIST_ENTRY *FormsetList
792 )
793{
794 LIST_ENTRY *HiiFormsetLink;
795 LIST_ENTRY *HiiFormsetNextLink;
796 REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate;
797
798 if ((HiiHandle == NULL) || (FormsetList == NULL)) {
799 return NULL;
800 }
801
802 if (IsListEmpty (FormsetList)) {
803 return NULL;
804 }
805
806 HiiFormsetLink = GetFirstNode (FormsetList);
807 while (!IsNull (FormsetList, HiiFormsetLink)) {
808 HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
809 HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
810
811 if (HiiFormsetPrivate->HiiHandle == HiiHandle) {
812 return HiiFormsetPrivate;
813 }
814
815 HiiFormsetLink = HiiFormsetNextLink;
816 }
817
818 return NULL;
819}
820
821/**
822 Release x-UEFI-string related information.
823
824 @param[in] FormsetPrivate Pointer to HII form-set private instance.
825
826 @retval EFI_STATUS
827
828**/
829EFI_STATUS
830ReleaseXuefiStringDatabase (
831 IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate
832 )
833{
834 REDFISH_X_UEFI_STRING_DATABASE *ThisDatabase;
835 REDFISH_X_UEFI_STRING_DATABASE *PreDatabase;
836 REDFISH_X_UEFI_STRINGS_ARRAY *ThisStringArray;
837 REDFISH_X_UEFI_STRINGS_ARRAY *PreStringArray;
838 BOOLEAN EndDatabase;
839 BOOLEAN EndArray;
840
841 if (FormsetPrivate->HiiPackageListHeader != NULL) {
842 FreePool (FormsetPrivate->HiiPackageListHeader);
843 }
844
845 // Walk through x-UEFI-redfish string database.
846 if (!IsListEmpty (&FormsetPrivate->XuefiRedfishStringDatabase)) {
847 EndDatabase = FALSE;
848 ThisDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)GetFirstNode (&FormsetPrivate->XuefiRedfishStringDatabase);
849 while (!EndDatabase) {
850 // Walk through string arrays.
851 if (!IsListEmpty (&ThisDatabase->XuefiRedfishStringArrays)) {
852 EndArray = FALSE;
853 ThisStringArray = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetFirstNode (&ThisDatabase->XuefiRedfishStringArrays);
854 while (!EndArray) {
855 // Remove this array
856 FreePool (ThisStringArray->ArrayEntryAddress);
857 EndArray = IsNodeAtEnd (&ThisDatabase->XuefiRedfishStringArrays, &ThisStringArray->NextArray);
858 PreStringArray = ThisStringArray;
859 if (!EndArray) {
860 ThisStringArray = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetNextNode (&ThisDatabase->XuefiRedfishStringArrays, &ThisStringArray->NextArray);
861 }
862
863 RemoveEntryList (&PreStringArray->NextArray);
864 FreePool (PreStringArray);
865 }
866 }
867
868 //
869 // Remove this database
870 //
871 EndDatabase = IsNodeAtEnd (&FormsetPrivate->XuefiRedfishStringDatabase, &ThisDatabase->NextXuefiRedfishLanguage);
872 PreDatabase = ThisDatabase;
873 if (!EndDatabase) {
874 ThisDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)GetNextNode (&FormsetPrivate->XuefiRedfishStringDatabase, &ThisDatabase->NextXuefiRedfishLanguage);
875 }
876
877 RemoveEntryList (&PreDatabase->NextXuefiRedfishLanguage);
878 FreePool (PreDatabase);
879 }
880 }
881
882 return EFI_SUCCESS;
883}
884
885/**
886 Release formset and all the forms and statements that belong to this formset.
887
888 @param[in] FormsetPrivate Pointer to HII form-set private instance.
889
890 @retval EFI_STATUS
891
892**/
893EFI_STATUS
894ReleaseFormset (
895 IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate
896 )
897{
898 LIST_ENTRY *HiiFormLink;
899 LIST_ENTRY *HiiNextFormLink;
900 REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate;
901 LIST_ENTRY *HiiStatementLink;
902 LIST_ENTRY *HiiNextStatementLink;
903 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate;
904 UINTN Index;
905
906 if (FormsetPrivate == NULL) {
907 return EFI_INVALID_PARAMETER;
908 }
909
910 HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList);
911 while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) {
912 HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);
913 HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList, HiiFormLink);
914
915 HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
916 while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
917 HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
918 HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);
919
920 //
921 // HiiStatementPrivate->HiiStatement will be released in DestroyFormSet().
922 //
923 RemoveEntryList (&HiiStatementPrivate->Link);
924 FreePool (HiiStatementPrivate);
925 HiiStatementLink = HiiNextStatementLink;
926 }
927
928 //
929 // HiiStatementPrivate->HiiForm will be released in DestroyFormSet().
930 //
931
932 RemoveEntryList (&HiiFormPrivate->Link);
933 FreePool (HiiFormPrivate);
934 HiiFormLink = HiiNextFormLink;
935 }
936
937 if (FormsetPrivate->HiiFormSet != NULL) {
938 DestroyFormSet (FormsetPrivate->HiiFormSet);
939 FormsetPrivate->HiiFormSet = NULL;
940 }
941
942 if (FormsetPrivate->DevicePathStr != NULL) {
943 FreePool (FormsetPrivate->DevicePathStr);
944 }
945
946 //
947 // Release schema list
948 //
949 if (FormsetPrivate->SupportedSchema.SchemaList != NULL) {
950 for (Index = 0; Index < FormsetPrivate->SupportedSchema.Count; Index++) {
951 FreePool (FormsetPrivate->SupportedSchema.SchemaList[Index]);
952 }
953
954 FreePool (FormsetPrivate->SupportedSchema.SchemaList);
955 FormsetPrivate->SupportedSchema.SchemaList = NULL;
956 FormsetPrivate->SupportedSchema.Count = 0;
957 }
958
959 ReleaseXuefiStringDatabase (FormsetPrivate);
960
961 return EFI_SUCCESS;
962}
963
964/**
965 Create new form-set instance.
966
967 @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * Pointer to newly created form-set private instance.
968
969**/
970REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *
971NewFormsetPrivate (
972 VOID
973 )
974{
975 REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *NewFormsetPrivate;
976
977 NewFormsetPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE));
978 if (NewFormsetPrivate == NULL) {
979 return NULL;
980 }
981
982 //
983 // Initial newly created formset private data.
984 //
985 InitializeListHead (&NewFormsetPrivate->HiiFormList);
986 InitializeListHead (&NewFormsetPrivate->XuefiRedfishStringDatabase);
987
988 return NewFormsetPrivate;
989}
990
991/**
992 Create new x-UEFI-redfish string array.
993
994 @param[in] XuefiRedfishStringDatabase The x-UEFI-redfish string database.
995
996 @retval EFI_OUT_OF_RESOURCES Not enough memory for creating a new array.
997 EFI_SUCCESS New array is created successfully.
998
999**/
1000EFI_STATUS
1001NewRedfishXuefiStringArray (
1002 IN REDFISH_X_UEFI_STRING_DATABASE *XuefiRedfishStringDatabase
1003 )
1004{
1005 REDFISH_X_UEFI_STRINGS_ARRAY *ArrayAddress;
1006
1007 // Initial first REDFISH_X_UEFI_STRINGS_ARRAY memory.
1008 ArrayAddress = (REDFISH_X_UEFI_STRINGS_ARRAY *)AllocateZeroPool (sizeof (REDFISH_X_UEFI_STRINGS_ARRAY));
1009 if (ArrayAddress == NULL) {
1010 DEBUG ((DEBUG_ERROR, "%a: Failed to allocate REDFISH_X_UEFI_STRINGS_ARRAY.\n", __func__));
1011 return EFI_OUT_OF_RESOURCES;
1012 }
1013
1014 InitializeListHead (&ArrayAddress->NextArray);
1015
1016 // Allocate memory buffer for REDFISH_X_UEFI_STRINGS_ARRAY_ELEMENT elements.
1017 ArrayAddress->ArrayEntryAddress = \
1018 (REDFISH_X_UEFI_STRINGS_ARRAY_ELEMENT *)AllocateZeroPool (sizeof (REDFISH_X_UEFI_STRINGS_ARRAY_ELEMENT) * X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER);
1019 if (ArrayAddress->ArrayEntryAddress == NULL) {
1020 FreePool (ArrayAddress);
1021 DEBUG ((DEBUG_ERROR, "%a: Failed to allocate array for REDFISH_X_UEFI_STRINGS_ARRAY_ELEMENTs.\n", __func__));
1022 return EFI_OUT_OF_RESOURCES;
1023 }
1024
1025 XuefiRedfishStringDatabase->StringsArrayBlocks++;
1026 InsertTailList (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays, &ArrayAddress->NextArray);
1027 return EFI_SUCCESS;
1028}
1029
1030/**
1031 Get the pointer of x-UEFI-redfish database or create a new database.
1032
1033 @param[in] FormsetPrivate Pointer to HII form-set private instance.
1034 @param[in] HiiStringPackageHeader HII string package header.
1035
1036 @retval Pointer to REDFISH_X_UEFI_STRING_DATABASE.
1037 If NULL, it fails to obtain x-UEFI-redfish database.
1038
1039**/
1040REDFISH_X_UEFI_STRING_DATABASE *
1041GetExistOrCreateXuefiStringDatabase (
1042 IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate,
1043 IN EFI_HII_STRING_PACKAGE_HDR *HiiStringPackageHeader
1044 )
1045{
1046 EFI_STATUS Status;
1047 BOOLEAN CreateNewOne;
1048 REDFISH_X_UEFI_STRING_DATABASE *XuefiRedfishStringDatabase;
1049
1050 CreateNewOne = TRUE;
1051 XuefiRedfishStringDatabase = NULL;
1052 if (!IsListEmpty (&FormsetPrivate->XuefiRedfishStringDatabase)) {
1053 XuefiRedfishStringDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)GetFirstNode (&FormsetPrivate->XuefiRedfishStringDatabase);
1054
1055 while (TRUE) {
1056 if (AsciiStriCmp (XuefiRedfishStringDatabase->XuefiRedfishLanguage, HiiStringPackageHeader->Language) == 0) {
1057 CreateNewOne = FALSE;
1058 break;
1059 }
1060
1061 if (IsNodeAtEnd (&FormsetPrivate->XuefiRedfishStringDatabase, &XuefiRedfishStringDatabase->NextXuefiRedfishLanguage)) {
1062 break;
1063 }
1064
1065 XuefiRedfishStringDatabase = \
1066 (REDFISH_X_UEFI_STRING_DATABASE *)GetNextNode (&FormsetPrivate->XuefiRedfishStringDatabase, &XuefiRedfishStringDatabase->NextXuefiRedfishLanguage);
1067 }
1068 }
1069
1070 if (CreateNewOne) {
1071 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " Creating x-UEFI-redfish (%a) string database...\n", HiiStringPackageHeader->Language));
1072 XuefiRedfishStringDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)AllocateZeroPool (sizeof (REDFISH_X_UEFI_STRING_DATABASE));
1073 if (XuefiRedfishStringDatabase == NULL) {
1074 DEBUG ((DEBUG_ERROR, " Failed to allocate REDFISH_X_UEFI_STRING_DATABASE.\n"));
1075 return NULL;
1076 }
1077
1078 InitializeListHead (&XuefiRedfishStringDatabase->NextXuefiRedfishLanguage);
1079 InitializeListHead (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays);
1080 XuefiRedfishStringDatabase->StringsArrayBlocks = 0;
1081 XuefiRedfishStringDatabase->XuefiRedfishLanguage = HiiStringPackageHeader->Language;
1082
1083 Status = NewRedfishXuefiStringArray (XuefiRedfishStringDatabase);
1084 if (EFI_ERROR (Status)) {
1085 FreePool (XuefiRedfishStringDatabase);
1086 return NULL;
1087 }
1088
1089 DEBUG ((
1090 DEBUG_REDFISH_PLATFORM_CONFIG,
1091 " x-UEFI-redfish (%a):\n String array is added to XuefiRedfishStringDatabase, total %d arrays now.\n",
1092 XuefiRedfishStringDatabase->XuefiRedfishLanguage,
1093 XuefiRedfishStringDatabase->StringsArrayBlocks
1094 ));
1095
1096 // Link string database to FormsetPrivate.
1097 InsertTailList (&FormsetPrivate->XuefiRedfishStringDatabase, &XuefiRedfishStringDatabase->NextXuefiRedfishLanguage);
1098 }
1099
1100 return XuefiRedfishStringDatabase;
1101}
1102
1103/**
1104 Check and allocate a new x-UEFI-redfish array if it is insufficient for the
1105 newly added x-UEFI-redfish string.
1106
1107 @param[in] FormsetPrivate Pointer to HII form-set private instance.
1108 @param[in] XuefiRedfishStringDatabase Pointer to the x-UEFI-redfish database.
1109 @param[in] StringId String ID added to database.
1110
1111 @retval EFI_SUCCESS The size of x-UEFI-string array is adjusted or
1112 is not required to be adjusted.
1113 Otherwise, refer to the error code returned from NewRedfishXuefiStringArray().
1114
1115**/
1116EFI_STATUS
1117RedfishXuefiStringAdjustArrays (
1118 IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate,
1119 IN REDFISH_X_UEFI_STRING_DATABASE *XuefiRedfishStringDatabase,
1120 IN EFI_STRING_ID StringId
1121 )
1122{
1123 EFI_STATUS Status;
1124
1125 while (((StringId + X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) / X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) > (UINT16)XuefiRedfishStringDatabase->StringsArrayBlocks) {
1126 Status = NewRedfishXuefiStringArray (XuefiRedfishStringDatabase);
1127 if (EFI_ERROR (Status)) {
1128 DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-UEFI-string array", __func__));
1129 return Status;
1130 }
1131 }
1132
1133 return EFI_SUCCESS;
1134}
1135
1136/**
1137 Insert a x-UEFI-redfish string to database.
1138
1139 @param[in] FormsetPrivate Pointer to HII form-set private instance.
1140 @param[in] HiiStringPackageHeader Pointer to HII string package.
1141 @param[in] StringId The HII string ID
1142 @param[in] StringTextPtr Pointer to HII string text.
1143
1144 @retval EFI_SUCCESS The HII string is added to database.
1145 EFI_LOAD_ERROR Something wrong when insert an HII string
1146 to database.
1147
1148**/
1149EFI_STATUS
1150RedfishXuefiStringInsertDatabase (
1151 IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate,
1152 IN EFI_HII_STRING_PACKAGE_HDR *HiiStringPackageHeader,
1153 IN EFI_STRING_ID StringId,
1154 IN CHAR16 *StringTextPtr
1155 )
1156{
1157 EFI_STATUS Status;
1158 UINTN StringIdOffset;
1159 REDFISH_X_UEFI_STRING_DATABASE *XuefiRedfishStringDatabase;
1160 REDFISH_X_UEFI_STRINGS_ARRAY *ThisArray;
1161
1162 XuefiRedfishStringDatabase = GetExistOrCreateXuefiStringDatabase (FormsetPrivate, HiiStringPackageHeader);
1163 if (XuefiRedfishStringDatabase == NULL) {
1164 DEBUG ((DEBUG_ERROR, "%a: Failed to get REDFISH_X_UEFI_STRING_DATABASE of x-UEFI-redfish language %a.\n", __func__, HiiStringPackageHeader->Language));
1165 ReleaseXuefiStringDatabase (FormsetPrivate);
1166 return EFI_LOAD_ERROR;
1167 }
1168
1169 Status = RedfishXuefiStringAdjustArrays (FormsetPrivate, XuefiRedfishStringDatabase, StringId);
1170 if (EFI_ERROR (Status)) {
1171 DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-UEFI-redfish string array.\n", __func__));
1172 ReleaseXuefiStringDatabase (FormsetPrivate);
1173 return EFI_LOAD_ERROR;
1174 }
1175
1176 // Insert string to x-UEFI-redfish string array.
1177 StringIdOffset = (UINTN)StringId;
1178 ThisArray = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetFirstNode (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays);
1179 while (StringIdOffset >= X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) {
1180 ThisArray = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetNextNode (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays, &ThisArray->NextArray);
1181 StringIdOffset -= X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER;
1182 }
1183
1184 // Insert string
1185 (ThisArray->ArrayEntryAddress + StringIdOffset)->StringId = StringId;
1186 (ThisArray->ArrayEntryAddress + StringIdOffset)->UcsString = StringTextPtr;
1187
1188 DEBUG_REDFISH_THIS_MODULE (
1189 REDFISH_PLATFORM_CONFIG_DEBUG_STRING_DATABASE,
1190 " Insert string ID: (%d) to database\n x-UEFI-string: \"%s\"\n Language: %a.\n",
1191 StringId,
1192 StringTextPtr,
1193 HiiStringPackageHeader->Language
1194 );
1195 return EFI_SUCCESS;
1196}
1197
1198/**
1199 Get x-UEFI-redfish string and language by string ID.
1200
1201 @param[in] FormsetPrivate Pointer to HII form-set private instance.
1202 @param[in] HiiStringPackageHeader HII string package header.
1203 @param[out] TotalStringAdded Return the total strings added to database.
1204
1205 @retval TRUE x-UEFI-redfish string and ID map is inserted to database.
1206 FALSE Something is wrong when insert x-UEFI-redfish string and ID map.
1207
1208**/
1209BOOLEAN
1210CreateXuefiLanguageStringIdMap (
1211 IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate,
1212 IN EFI_HII_STRING_PACKAGE_HDR *HiiStringPackageHeader,
1213 OUT UINTN *TotalStringAdded
1214 )
1215{
1216 EFI_STATUS Status;
1217 UINT8 *BlockHdr;
1218 EFI_STRING_ID CurrentStringId;
1219 UINTN BlockSize;
1220 UINTN Index;
1221 UINT8 *StringTextPtr;
1222 UINTN Offset;
1223 UINT16 StringCount;
1224 UINT16 SkipCount;
1225 UINT8 Length8;
1226 EFI_HII_SIBT_EXT2_BLOCK Ext2;
1227 UINT32 Length32;
1228 UINT8 *StringBlockInfo;
1229 UINTN StringsAdded;
1230
1231 StringsAdded = 0;
1232
1233 //
1234 // Parse the string blocks to get the string text and font.
1235 //
1236 StringBlockInfo = (UINT8 *)((UINTN)HiiStringPackageHeader + HiiStringPackageHeader->StringInfoOffset);
1237 BlockHdr = StringBlockInfo;
1238 BlockSize = 0;
1239 Offset = 0;
1240 CurrentStringId = 1;
1241 while (*BlockHdr != EFI_HII_SIBT_END) {
1242 switch (*BlockHdr) {
1243 case EFI_HII_SIBT_STRING_SCSU:
1244 Offset = sizeof (EFI_HII_STRING_BLOCK);
1245 StringTextPtr = BlockHdr + Offset;
1246 BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
1247 CurrentStringId++;
1248 break;
1249
1250 case EFI_HII_SIBT_STRING_SCSU_FONT:
1251 Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
1252 StringTextPtr = BlockHdr + Offset;
1253 BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
1254 CurrentStringId++;
1255 break;
1256
1257 case EFI_HII_SIBT_STRINGS_SCSU:
1258 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
1259 StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));
1260 BlockSize += StringTextPtr - BlockHdr;
1261
1262 for (Index = 0; Index < StringCount; Index++) {
1263 BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
1264 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
1265 CurrentStringId++;
1266 }
1267
1268 break;
1269
1270 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
1271 CopyMem (
1272 &StringCount,
1273 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
1274 sizeof (UINT16)
1275 );
1276 StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));
1277 BlockSize += StringTextPtr - BlockHdr;
1278
1279 for (Index = 0; Index < StringCount; Index++) {
1280 BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
1281 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
1282 CurrentStringId++;
1283 }
1284
1285 break;
1286
1287 case EFI_HII_SIBT_STRING_UCS2:
1288 Offset = sizeof (EFI_HII_STRING_BLOCK);
1289 StringTextPtr = BlockHdr + Offset;
1290
1291 // x-UEFI-redfish string is always encoded as UCS and started with '/'.
1292 if (*StringTextPtr == (UINT16)'/') {
1293 Status = RedfishXuefiStringInsertDatabase (
1294 FormsetPrivate,
1295 HiiStringPackageHeader,
1296 CurrentStringId,
1297 (CHAR16 *)StringTextPtr
1298 );
1299 if (EFI_ERROR (Status)) {
1300 DEBUG ((DEBUG_ERROR, "%a: Failed to insert x-UEFI-redfish string %s.\n", __func__, StringTextPtr));
1301 return FALSE;
1302 }
1303
1304 StringsAdded++;
1305 }
1306
1307 BlockSize += (Offset + HiiStrSize ((CHAR16 *)StringTextPtr));
1308 CurrentStringId++;
1309 break;
1310
1311 case EFI_HII_SIBT_STRING_UCS2_FONT:
1312 Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
1313 StringTextPtr = BlockHdr + Offset;
1314 BlockSize += (Offset + HiiStrSize ((CHAR16 *)StringTextPtr));
1315 CurrentStringId++;
1316 break;
1317
1318 case EFI_HII_SIBT_STRINGS_UCS2:
1319 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
1320 StringTextPtr = BlockHdr + Offset;
1321 BlockSize += Offset;
1322 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
1323 for (Index = 0; Index < StringCount; Index++) {
1324 BlockSize += HiiStrSize ((CHAR16 *)StringTextPtr);
1325 StringTextPtr = StringTextPtr + HiiStrSize ((CHAR16 *)StringTextPtr);
1326 CurrentStringId++;
1327 }
1328
1329 break;
1330
1331 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
1332 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
1333 StringTextPtr = BlockHdr + Offset;
1334 BlockSize += Offset;
1335 CopyMem (
1336 &StringCount,
1337 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
1338 sizeof (UINT16)
1339 );
1340 for (Index = 0; Index < StringCount; Index++) {
1341 BlockSize += HiiStrSize ((CHAR16 *)StringTextPtr);
1342 StringTextPtr = StringTextPtr + HiiStrSize ((CHAR16 *)StringTextPtr);
1343 CurrentStringId++;
1344 }
1345
1346 break;
1347
1348 case EFI_HII_SIBT_DUPLICATE:
1349 BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
1350 CurrentStringId++;
1351 break;
1352
1353 case EFI_HII_SIBT_SKIP1:
1354 SkipCount = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
1355 CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
1356 BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
1357 break;
1358
1359 case EFI_HII_SIBT_SKIP2:
1360 CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
1361 CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
1362 BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
1363 break;
1364
1365 case EFI_HII_SIBT_EXT1:
1366 CopyMem (
1367 &Length8,
1368 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
1369 sizeof (UINT8)
1370 );
1371 BlockSize += Length8;
1372 break;
1373
1374 case EFI_HII_SIBT_EXT2:
1375 CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
1376 BlockSize += Ext2.Length;
1377 break;
1378
1379 case EFI_HII_SIBT_EXT4:
1380 CopyMem (
1381 &Length32,
1382 (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
1383 sizeof (UINT32)
1384 );
1385
1386 BlockSize += Length32;
1387 break;
1388
1389 default:
1390 break;
1391 }
1392
1393 BlockHdr = (UINT8 *)(StringBlockInfo + BlockSize);
1394 }
1395
1396 *TotalStringAdded = StringsAdded;
1397 return TRUE;
1398}
1399
1400/**
1401 Get x-UEFI-redfish string and language by string ID.
1402
1403 @param[in] FormsetPrivate Pointer to HII form-set private instance.
1404 @param[in] StringId The HII string ID.
1405 @param[out] String Optionally return USC string.
1406 @param[out] Language Optionally return x-UEFI-redfish language.
1407 @param[out] XuefiStringDatabase Optionally return x-UEFI-redfish database.
1408
1409 @retval EFI_SUCCESS String information is returned.
1410 EFI_INVALID_PARAMETER One of the given parameters to this function is
1411 invalid.
1412 EFI_NOT_FOUND String is not found.
1413
1414**/
1415EFI_STATUS
1416GetXuefiStringAndLangByStringId (
1417 IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate,
1418 IN EFI_STRING_ID StringId,
1419 OUT CHAR16 **String OPTIONAL,
1420 OUT CHAR8 **Language OPTIONAL,
1421 OUT REDFISH_X_UEFI_STRING_DATABASE **XuefiStringDatabase OPTIONAL
1422 )
1423{
1424 REDFISH_X_UEFI_STRING_DATABASE *XuefiRedfishStringDatabase;
1425 REDFISH_X_UEFI_STRINGS_ARRAY *StringArray;
1426 UINT16 StringIndex;
1427
1428 if ((String == NULL) && (Language == NULL) && (XuefiStringDatabase == NULL)) {
1429 DEBUG ((DEBUG_ERROR, "%a: Invalid parameters for this function.\n", __func__));
1430 return EFI_INVALID_PARAMETER;
1431 }
1432
1433 if (IsListEmpty (&FormsetPrivate->XuefiRedfishStringDatabase)) {
1434 return EFI_NOT_FOUND;
1435 }
1436
1437 XuefiRedfishStringDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)GetFirstNode (&FormsetPrivate->XuefiRedfishStringDatabase);
1438 while (TRUE) {
1439 if (Language != NULL) {
1440 *Language = XuefiRedfishStringDatabase->XuefiRedfishLanguage;
1441 }
1442
1443 StringArray = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetFirstNode (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays);
1444
1445 // Loop to the correct string array.
1446 StringIndex = StringId;
1447 while (StringIndex >= X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) {
1448 if (IsNodeAtEnd (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays, &StringArray->NextArray)) {
1449 goto ErrorExit;
1450 }
1451
1452 StringArray = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetNextNode (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays, &StringArray->NextArray);
1453 StringIndex -= X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER;
1454 }
1455
1456 //
1457 // NOTE: The string ID in the formset is a unique number.
1458 // If the string in the array is NULL, then the matched string ID
1459 // should be in another x-UEFI-redfish database.
1460 //
1461 if ((StringArray->ArrayEntryAddress + StringIndex)->UcsString != NULL) {
1462 //
1463 // String ID is belong to this x-uef-redfish language database.
1464 //
1465 if (String != NULL) {
1466 *String = (StringArray->ArrayEntryAddress + StringIndex)->UcsString;
1467 }
1468
1469 if (XuefiStringDatabase != NULL) {
1470 *XuefiStringDatabase = XuefiRedfishStringDatabase;
1471 }
1472
1473 return EFI_SUCCESS;
1474 }
1475
1476 if (IsNodeAtEnd (&FormsetPrivate->XuefiRedfishStringDatabase, &XuefiRedfishStringDatabase->NextXuefiRedfishLanguage)) {
1477 return EFI_NOT_FOUND;
1478 }
1479
1480 XuefiRedfishStringDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)GetNextNode (
1481 &FormsetPrivate->XuefiRedfishStringDatabase,
1482 &XuefiRedfishStringDatabase->NextXuefiRedfishLanguage
1483 );
1484 }
1485
1486ErrorExit:;
1487 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: String ID (%d) is not in any x-uef-redfish string databases.\n", __func__, StringId));
1488 return EFI_NOT_FOUND;
1489}
1490
1491/**
1492 Build a x-UEFI-redfish database for the newly added x-UEFI-redfish language.
1493
1494 @param[in] FormsetPrivate Pointer to HII form-set private instance.
1495
1496**/
1497VOID
1498BuildXUefiRedfishStringDatabase (
1499 IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate
1500 )
1501{
1502 EFI_STATUS Status;
1503 UINTN BufferSize;
1504 EFI_HII_PACKAGE_HEADER *PackageHeader;
1505 UINTN EndingPackageAddress;
1506 EFI_HII_STRING_PACKAGE_HDR *HiiStringPackageHeader;
1507 UINTN SupportedSchemaLangCount;
1508 CHAR8 **SupportedSchemaLang;
1509 BOOLEAN StringIdMapIsBuilt;
1510 UINTN TotalStringsAdded;
1511 UINTN NumberPackageStrings;
1512
1513 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Building x-UEFI-redfish string database, HII Formset GUID - %g.\n", __func__, FormsetPrivate->Guid));
1514
1515 BufferSize = 0;
1516 Status = mRedfishPlatformConfigPrivate->HiiDatabase->ExportPackageLists (
1517 mRedfishPlatformConfigPrivate->HiiDatabase,
1518 FormsetPrivate->HiiHandle,
1519 &BufferSize,
1520 FormsetPrivate->HiiPackageListHeader
1521 );
1522 if (Status != EFI_BUFFER_TOO_SMALL) {
1523 DEBUG ((DEBUG_ERROR, " Failed to export package list.\n"));
1524 return;
1525 }
1526
1527 FormsetPrivate->HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER *)AllocateZeroPool (BufferSize);
1528 if (FormsetPrivate->HiiPackageListHeader == NULL) {
1529 DEBUG ((DEBUG_ERROR, " Failed to allocate memory for the exported package list.\n"));
1530 return;
1531 }
1532
1533 Status = mRedfishPlatformConfigPrivate->HiiDatabase->ExportPackageLists (
1534 mRedfishPlatformConfigPrivate->HiiDatabase,
1535 FormsetPrivate->HiiHandle,
1536 &BufferSize,
1537 FormsetPrivate->HiiPackageListHeader
1538 );
1539 if (EFI_ERROR (Status)) {
1540 FreePool (FormsetPrivate->HiiPackageListHeader);
1541 FormsetPrivate->HiiPackageListHeader = NULL;
1542 return;
1543 }
1544
1545 TotalStringsAdded = 0;
1546 //
1547 // Finding the string package.
1548 //
1549 EndingPackageAddress = (UINTN)FormsetPrivate->HiiPackageListHeader + FormsetPrivate->HiiPackageListHeader->PackageLength;
1550 PackageHeader = (EFI_HII_PACKAGE_HEADER *)(FormsetPrivate->HiiPackageListHeader + 1);
1551 SupportedSchemaLang = FormsetPrivate->SupportedSchema.SchemaList;
1552 while ((UINTN)PackageHeader < EndingPackageAddress) {
1553 switch (PackageHeader->Type) {
1554 case EFI_HII_PACKAGE_STRINGS:
1555 StringIdMapIsBuilt = FALSE;
1556 HiiStringPackageHeader = (EFI_HII_STRING_PACKAGE_HDR *)PackageHeader;
1557
1558 // Check if this is the string package for x-UEFI-redfish
1559 for (SupportedSchemaLangCount = 0;
1560 SupportedSchemaLangCount < FormsetPrivate->SupportedSchema.Count;
1561 SupportedSchemaLangCount++
1562 )
1563 {
1564 if (AsciiStrnCmp (
1565 *(SupportedSchemaLang + SupportedSchemaLangCount),
1566 HiiStringPackageHeader->Language,
1567 AsciiStrLen (HiiStringPackageHeader->Language)
1568 ) == 0)
1569 {
1570 StringIdMapIsBuilt = CreateXuefiLanguageStringIdMap (FormsetPrivate, HiiStringPackageHeader, &NumberPackageStrings);
1571 if (StringIdMapIsBuilt) {
1572 TotalStringsAdded += NumberPackageStrings;
1573 }
1574
1575 break;
1576 }
1577 }
1578
1579 if (StringIdMapIsBuilt == FALSE) {
1580 if (AsciiStrStr (HiiStringPackageHeader->Language, X_UEFI_SCHEMA_PREFIX) == NULL) {
1581 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " No need to build x-UEFI-redfish string ID map for HII language %a\n", HiiStringPackageHeader->Language));
1582 } else {
1583 DEBUG ((DEBUG_ERROR, " Failed to build x-UEFI-redfish string ID map of HII language %a\n", HiiStringPackageHeader->Language));
1584 }
1585 }
1586
1587 default:
1588 PackageHeader = (EFI_HII_PACKAGE_HEADER *)((UINTN)PackageHeader + PackageHeader->Length);
1589 }
1590 }
1591
1592 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " Total %d x-UEFI-redfish config language are added.\n", TotalStringsAdded));
1593}
1594
1595/**
1596 Load the HII formset from the given HII handle.
1597
1598 @param[in] HiiHandle Target HII handle to load.
1599 @param[out] FormsetPrivate The formset private data.
1600
1601 @retval EFI_STATUS The formset is loaded successfully.
1602 @retval EFI_UNSUPPORTED This formset doesn't have any x-UEFI-redfish configuration.
1603
1604**/
1605EFI_STATUS
1606LoadFormset (
1607 IN EFI_HII_HANDLE HiiHandle,
1608 OUT REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate
1609 )
1610{
1611 EFI_STATUS Status;
1612 HII_FORMSET *HiiFormSet;
1613 HII_FORM *HiiForm;
1614 LIST_ENTRY *HiiFormLink;
1615 REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate;
1616 HII_STATEMENT *HiiStatement;
1617 LIST_ENTRY *HiiStatementLink;
1618 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate;
1619 EFI_GUID ZeroGuid;
1620 EXPRESS_RESULT ExpressionResult;
1621 CHAR16 *String;
1622
1623 if ((HiiHandle == NULL) || (FormsetPrivate == NULL)) {
1624 return EFI_INVALID_PARAMETER;
1625 }
1626
1627 HiiFormSet = AllocateZeroPool (sizeof (HII_FORMSET));
1628 if (HiiFormSet == NULL) {
1629 DEBUG ((DEBUG_ERROR, "%a: No memory resource for HII_FORMSET - %g\n", __func__, FormsetPrivate->Guid));
1630 return EFI_OUT_OF_RESOURCES;
1631 }
1632
1633 //
1634 // Find HII formset by the given HII handle.
1635 //
1636 ZeroMem (&ZeroGuid, sizeof (ZeroGuid));
1637 Status = CreateFormSetFromHiiHandle (HiiHandle, &ZeroGuid, HiiFormSet);
1638 if (EFI_ERROR (Status) || IsListEmpty (&HiiFormSet->FormListHead)) {
1639 DEBUG ((DEBUG_ERROR, "%a: Formset not found by HII handle - %g\n", __func__, FormsetPrivate->Guid));
1640 Status = EFI_NOT_FOUND;
1641 goto ErrorExit;
1642 }
1643
1644 //
1645 // Initialize formset
1646 //
1647 InitializeFormSet (HiiFormSet);
1648
1649 //
1650 // Initialize formset private data.
1651 //
1652 FormsetPrivate->HiiFormSet = HiiFormSet;
1653 FormsetPrivate->HiiHandle = HiiHandle;
1654 CopyGuid (&FormsetPrivate->Guid, &HiiFormSet->Guid);
1655 FormsetPrivate->DevicePathStr = ConvertDevicePathToText (HiiFormSet->DevicePath, FALSE, FALSE);
1656 Status = GetSupportedSchema (FormsetPrivate->HiiHandle, &FormsetPrivate->SupportedSchema);
1657 if (EFI_ERROR (Status)) {
1658 if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
1659 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: No x-UEFI-redfish configuration found on the formset - %g\n", __func__, FormsetPrivate->Guid));
1660 //
1661 // If there is no x-UEFI-redfish language in this form-set, we don't add formset
1662 // since we don't need to build menu path for attribute registry.
1663 //
1664 return EFI_UNSUPPORTED;
1665 }
1666 } else {
1667 // Building x-UEFI-redfish string database
1668 BuildXUefiRedfishStringDatabase (FormsetPrivate);
1669 }
1670
1671 HiiFormLink = GetFirstNode (&HiiFormSet->FormListHead);
1672 while (!IsNull (&HiiFormSet->FormListHead, HiiFormLink)) {
1673 HiiForm = HII_FORM_FROM_LINK (HiiFormLink);
1674
1675 HiiFormPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE));
1676 if (HiiFormPrivate == NULL) {
1677 Status = EFI_OUT_OF_RESOURCES;
1678 DEBUG ((DEBUG_ERROR, "%a: No memory resource for REDFISH_PLATFORM_CONFIG_FORM_PRIVATE.\n", __func__));
1679 goto ErrorExit;
1680 }
1681
1682 //
1683 // Initialize form private data.
1684 //
1685 HiiFormPrivate->HiiForm = HiiForm;
1686 HiiFormPrivate->Id = HiiForm->FormId;
1687 HiiFormPrivate->Title = HiiForm->FormTitle;
1688 HiiFormPrivate->ParentFormset = FormsetPrivate;
1689 HiiFormPrivate->Suppressed = FALSE;
1690 InitializeListHead (&HiiFormPrivate->StatementList);
1691
1692 if ((HiiForm->SuppressExpression != NULL) &&
1693 (EvaluateExpressionList (HiiForm->SuppressExpression, TRUE, HiiFormSet, HiiForm) == ExpressSuppress))
1694 {
1695 HiiFormPrivate->Suppressed = TRUE;
1696 }
1697
1698 HiiStatementLink = GetFirstNode (&HiiForm->StatementListHead);
1699 while (!IsNull (&HiiForm->StatementListHead, HiiStatementLink)) {
1700 HiiStatement = HII_STATEMENT_FROM_LINK (HiiStatementLink);
1701
1702 HiiStatementPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE));
1703 if (HiiStatementPrivate == NULL) {
1704 DEBUG ((DEBUG_ERROR, "%a: No memory resource for REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE.\n", __func__));
1705 Status = EFI_OUT_OF_RESOURCES;
1706 goto ErrorExit;
1707 }
1708
1709 //
1710 // Initialize statement private data.
1711 //
1712 HiiStatementPrivate->HiiStatement = HiiStatement;
1713 HiiStatementPrivate->QuestionId = HiiStatement->QuestionId;
1714 HiiStatementPrivate->Description = HiiStatement->Prompt;
1715 HiiStatementPrivate->Help = HiiStatement->Help;
1716 HiiStatementPrivate->ParentForm = HiiFormPrivate;
1717 HiiStatementPrivate->Flags = HiiStatement->QuestionFlags;
1718 HiiStatementPrivate->StatementData.NumMaximum = HiiStatement->ExtraData.NumData.Maximum;
1719 HiiStatementPrivate->StatementData.NumMinimum = HiiStatement->ExtraData.NumData.Minimum;
1720 HiiStatementPrivate->StatementData.NumStep = HiiStatement->ExtraData.NumData.Step;
1721 HiiStatementPrivate->StatementData.StrMaxSize = HiiStatement->ExtraData.StrData.MaxSize;
1722 HiiStatementPrivate->StatementData.StrMinSize = HiiStatement->ExtraData.StrData.MinSize;
1723 HiiStatementPrivate->Suppressed = FALSE;
1724 HiiStatementPrivate->GrayedOut = FALSE;
1725
1726 //
1727 // Expression
1728 //
1729 if (HiiFormPrivate->Suppressed) {
1730 HiiStatementPrivate->Suppressed = TRUE;
1731 } else {
1732 if (HiiStatement->ExpressionList != NULL) {
1733 ExpressionResult = EvaluateExpressionList (HiiStatement->ExpressionList, TRUE, HiiFormSet, HiiForm);
1734 if (ExpressionResult == ExpressGrayOut) {
1735 HiiStatementPrivate->GrayedOut = TRUE;
1736 } else if (ExpressionResult == ExpressSuppress) {
1737 HiiStatementPrivate->Suppressed = TRUE;
1738 }
1739 }
1740 }
1741
1742 // Get x-UEFI-redfish string using String ID.
1743 Status = GetXuefiStringAndLangByStringId (FormsetPrivate, HiiStatementPrivate->Description, &String, NULL, NULL);
1744 if (!EFI_ERROR (Status)) {
1745 HiiStatementPrivate->XuefiRedfishStr = String;
1746 //
1747 // Attach to statement list.
1748 //
1749 InsertTailList (&HiiFormPrivate->StatementList, &HiiStatementPrivate->Link);
1750 } else {
1751 if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
1752 //
1753 // If there is no x-UEFI-redfish language for this statement, we don't add this statement
1754 // since we don't need to build menu path for attribute registry.
1755 //
1756 FreePool (HiiStatementPrivate);
1757 } else {
1758 //
1759 // This is not x-UEFI-redfish string and we don't cache its string for searching Redfish configure language.
1760 // When caller wants the string, we will read English string by calling HiiGetString().
1761 //
1762 HiiStatementPrivate->XuefiRedfishStr = NULL;
1763 //
1764 // Attach to statement list.
1765 //
1766 InsertTailList (&HiiFormPrivate->StatementList, &HiiStatementPrivate->Link);
1767 }
1768 }
1769
1770 HiiStatementLink = GetNextNode (&HiiForm->StatementListHead, HiiStatementLink);
1771 }
1772
1773 //
1774 // Attach to form list.
1775 //
1776 InsertTailList (&FormsetPrivate->HiiFormList, &HiiFormPrivate->Link);
1777 HiiFormLink = GetNextNode (&HiiFormSet->FormListHead, HiiFormLink);
1778 }
1779
1780 return EFI_SUCCESS;
1781
1782ErrorExit:
1783
1784 //
1785 // Release HiiFormSet if HiiFormSet is not linked to FormsetPrivate yet.
1786 //
1787 if ((HiiFormSet != NULL) && (FormsetPrivate->HiiFormSet != HiiFormSet)) {
1788 DestroyFormSet (HiiFormSet);
1789 }
1790
1791 //
1792 // Release resource when error happens.
1793 //
1794 ReleaseFormset (FormsetPrivate);
1795
1796 return Status;
1797}
1798
1799/**
1800 Load formset list on given HII handle.
1801
1802 @param[in] HiiHandle HII handle to load formset list.
1803 @param[out] FormsetList Pointer to formset list returned on given handle.
1804
1805 @retval EFI_STATUS
1806
1807**/
1808EFI_STATUS
1809LoadFormsetList (
1810 IN EFI_HII_HANDLE *HiiHandle,
1811 OUT LIST_ENTRY *FormsetList
1812 )
1813{
1814 EFI_STATUS Status;
1815 REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate;
1816
1817 if ((HiiHandle == NULL) || (FormsetList == NULL)) {
1818 return EFI_INVALID_PARAMETER;
1819 }
1820
1821 FormsetPrivate = GetFormsetPrivateByHiiHandle (HiiHandle, FormsetList);
1822 if (FormsetPrivate != NULL) {
1823 return EFI_ALREADY_STARTED;
1824 }
1825
1826 FormsetPrivate = NewFormsetPrivate ();
1827 if (FormsetPrivate == NULL) {
1828 DEBUG ((DEBUG_ERROR, "%a: out of resource\n", __func__));
1829 return EFI_OUT_OF_RESOURCES;
1830 }
1831
1832 //
1833 // Load formset on the given HII handle.
1834 //
1835 Status = LoadFormset (HiiHandle, FormsetPrivate);
1836 if (EFI_ERROR (Status)) {
1837 DEBUG ((DEBUG_ERROR, "%a: Formset is not loaded for edk2 redfish: %r\n", __func__, Status));
1838 FreePool (FormsetPrivate);
1839 return Status;
1840 }
1841
1842 //
1843 // Attach to cache list.
1844 //
1845 InsertTailList (FormsetList, &FormsetPrivate->Link);
1846
1847 DEBUG_CODE (
1848 if (RedfishPlatformConfigDebugProp (REDFISH_PLATFORM_CONFIG_DEBUG_DUMP_FORMSET)) {
1849 DumpFormsetList (FormsetList);
1850 }
1851
1852 );
1853
1854 return EFI_SUCCESS;
1855}
1856
1857/**
1858 Release formset list and all the forms that belong to this formset.
1859
1860 @param[in] FormsetList Pointer to formset list that needs to be
1861 released.
1862
1863 @retval EFI_STATUS
1864
1865**/
1866EFI_STATUS
1867ReleaseFormsetList (
1868 IN LIST_ENTRY *FormsetList
1869 )
1870{
1871 LIST_ENTRY *HiiFormsetLink;
1872 LIST_ENTRY *HiiFormsetNextLink;
1873 REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate;
1874
1875 if (FormsetList == NULL) {
1876 return EFI_INVALID_PARAMETER;
1877 }
1878
1879 if (IsListEmpty (FormsetList)) {
1880 return EFI_SUCCESS;
1881 }
1882
1883 HiiFormsetLink = GetFirstNode (FormsetList);
1884 while (!IsNull (FormsetList, HiiFormsetLink)) {
1885 HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
1886 HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
1887
1888 //
1889 // Detach from list.
1890 //
1891 RemoveEntryList (&HiiFormsetPrivate->Link);
1892 ReleaseFormset (HiiFormsetPrivate);
1893 FreePool (HiiFormsetPrivate);
1894 HiiFormsetLink = HiiFormsetNextLink;
1895 }
1896
1897 return EFI_SUCCESS;
1898}
1899
1900/**
1901 Get all pending list.
1902
1903 @param[in] HiiHandle HII handle instance.
1904 @param[in] PendingList Pending list to keep pending data.
1905
1906 @retval REDFISH_PLATFORM_CONFIG_PENDING_LIST * Pointer to pending list data.
1907
1908**/
1909REDFISH_PLATFORM_CONFIG_PENDING_LIST *
1910GetPendingList (
1911 IN EFI_HII_HANDLE *HiiHandle,
1912 IN LIST_ENTRY *PendingList
1913 )
1914{
1915 LIST_ENTRY *PendingListLink;
1916 REDFISH_PLATFORM_CONFIG_PENDING_LIST *Target;
1917
1918 if ((HiiHandle == NULL) || (PendingList == NULL)) {
1919 return NULL;
1920 }
1921
1922 if (IsListEmpty (PendingList)) {
1923 return NULL;
1924 }
1925
1926 PendingListLink = GetFirstNode (PendingList);
1927 while (!IsNull (PendingList, PendingListLink)) {
1928 Target = REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingListLink);
1929
1930 if (Target->HiiHandle == HiiHandle) {
1931 return Target;
1932 }
1933
1934 PendingListLink = GetNextNode (PendingList, PendingListLink);
1935 }
1936
1937 return NULL;
1938}
1939
1940/**
1941 When HII database is updated. Keep updated HII handle into pending list so
1942 we can process them later.
1943
1944 @param[in] HiiHandle HII handle instance.
1945 @param[in] PendingList Pending list to keep HII handle which is recently updated.
1946
1947 @retval EFI_SUCCESS HII handle is saved in pending list.
1948 @retval EFI_INVALID_PARAMETER HiiHandle is NULL or PendingList is NULL.
1949 @retval EFI_OUT_OF_RESOURCES System is out of memory.
1950
1951**/
1952EFI_STATUS
1953NotifyFormsetUpdate (
1954 IN EFI_HII_HANDLE *HiiHandle,
1955 IN LIST_ENTRY *PendingList
1956 )
1957{
1958 REDFISH_PLATFORM_CONFIG_PENDING_LIST *TargetPendingList;
1959
1960 if ((HiiHandle == NULL) || (PendingList == NULL)) {
1961 return EFI_INVALID_PARAMETER;
1962 }
1963
1964 //
1965 // Check and see if this HII handle is processed already.
1966 //
1967 TargetPendingList = GetPendingList (HiiHandle, PendingList);
1968 if (TargetPendingList != NULL) {
1969 TargetPendingList->IsDeleted = FALSE;
1970 DEBUG_CODE (
1971 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: HII handle: 0x%x is updated\n", __func__, HiiHandle));
1972 );
1973 return EFI_SUCCESS;
1974 }
1975
1976 TargetPendingList = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PENDING_LIST));
1977 if (TargetPendingList == NULL) {
1978 return EFI_OUT_OF_RESOURCES;
1979 }
1980
1981 TargetPendingList->HiiHandle = HiiHandle;
1982 TargetPendingList->IsDeleted = FALSE;
1983
1984 InsertTailList (PendingList, &TargetPendingList->Link);
1985
1986 DEBUG_CODE (
1987 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: HII handle: 0x%x is created\n", __func__, HiiHandle));
1988 );
1989
1990 return EFI_SUCCESS;
1991}
1992
1993/**
1994 When HII database is updated and form-set is deleted. Keep deleted HII handle into pending list so
1995 we can process them later.
1996
1997 @param[in] HiiHandle HII handle instance.
1998 @param[in] PendingList Pending list to keep HII handle which is recently updated.
1999
2000 @retval EFI_SUCCESS HII handle is saved in pending list.
2001 @retval EFI_INVALID_PARAMETER HiiHandle is NULL or PendingList is NULL.
2002 @retval EFI_OUT_OF_RESOURCES System is out of memory.
2003
2004**/
2005EFI_STATUS
2006NotifyFormsetDeleted (
2007 IN EFI_HII_HANDLE *HiiHandle,
2008 IN LIST_ENTRY *PendingList
2009 )
2010{
2011 REDFISH_PLATFORM_CONFIG_PENDING_LIST *TargetPendingList;
2012
2013 if ((HiiHandle == NULL) || (PendingList == NULL)) {
2014 return EFI_INVALID_PARAMETER;
2015 }
2016
2017 //
2018 // Check and see if this HII handle is processed already.
2019 //
2020 TargetPendingList = GetPendingList (HiiHandle, PendingList);
2021 if (TargetPendingList != NULL) {
2022 TargetPendingList->IsDeleted = TRUE;
2023 DEBUG_CODE (
2024 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: HII handle: 0x%x is updated and deleted\n", __func__, HiiHandle));
2025 );
2026 return EFI_SUCCESS;
2027 }
2028
2029 TargetPendingList = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PENDING_LIST));
2030 if (TargetPendingList == NULL) {
2031 return EFI_OUT_OF_RESOURCES;
2032 }
2033
2034 TargetPendingList->HiiHandle = HiiHandle;
2035 TargetPendingList->IsDeleted = TRUE;
2036
2037 InsertTailList (PendingList, &TargetPendingList->Link);
2038
2039 DEBUG_CODE (
2040 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: HII handle: 0x%x is deleted\n", __func__, HiiHandle));
2041 );
2042
2043 return EFI_SUCCESS;
2044}
2045
2046/**
2047 There are HII database update and we need to process them accordingly so that we
2048 won't use stale data. This function will parse updated HII handle again in order
2049 to get updated data-set.
2050
2051 @param[in] FormsetList List to keep HII form-set.
2052 @param[in] PendingList List to keep HII handle that is updated.
2053
2054 @retval EFI_SUCCESS HII handle is saved in pending list.
2055 @retval EFI_INVALID_PARAMETER FormsetList is NULL or PendingList is NULL.
2056
2057**/
2058EFI_STATUS
2059ProcessPendingList (
2060 IN LIST_ENTRY *FormsetList,
2061 IN LIST_ENTRY *PendingList
2062 )
2063{
2064 LIST_ENTRY *PendingListLink;
2065 LIST_ENTRY *PendingListNextLink;
2066 REDFISH_PLATFORM_CONFIG_PENDING_LIST *Target;
2067 REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate;
2068 EFI_STATUS Status;
2069
2070 if ((FormsetList == NULL) || (PendingList == NULL)) {
2071 return EFI_INVALID_PARAMETER;
2072 }
2073
2074 if (IsListEmpty (PendingList)) {
2075 return EFI_SUCCESS;
2076 }
2077
2078 PendingListLink = GetFirstNode (PendingList);
2079 while (!IsNull (PendingList, PendingListLink)) {
2080 PendingListNextLink = GetNextNode (PendingList, PendingListLink);
2081 Target = REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingListLink);
2082
2083 if (Target->IsDeleted) {
2084 //
2085 // The HII resource on this HII handle is removed. Release the formset.
2086 //
2087 FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle, FormsetList);
2088 if (FormsetPrivate != NULL) {
2089 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: formset: %g is removed because driver release HII resource it already\n", __func__, FormsetPrivate->Guid));
2090 RemoveEntryList (&FormsetPrivate->Link);
2091 ReleaseFormset (FormsetPrivate);
2092 FreePool (FormsetPrivate);
2093 } else {
2094 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: formset on HII handle 0x%x was removed already\n", __func__, Target->HiiHandle));
2095 }
2096 } else {
2097 //
2098 // The HII resource on this HII handle is updated/removed.
2099 //
2100 FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle, FormsetList);
2101 if (FormsetPrivate != NULL) {
2102 //
2103 // HII formset already exist, release it and query again.
2104 //
2105 DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: formset: %g is updated. Release current formset\n", __func__, &FormsetPrivate->Guid));
2106 RemoveEntryList (&FormsetPrivate->Link);
2107 ReleaseFormset (FormsetPrivate);
2108 FreePool (FormsetPrivate);
2109 }
2110
2111 Status = LoadFormsetList (Target->HiiHandle, FormsetList);
2112 if (EFI_ERROR (Status)) {
2113 if (Status == EFI_UNSUPPORTED) {
2114 DEBUG ((DEBUG_ERROR, " The formset has no x-UEFI-redfish configurations.\n"));
2115 } else {
2116 DEBUG ((DEBUG_ERROR, " load formset from HII handle: 0x%x failed: %r\n", Target->HiiHandle, Status));
2117 }
2118 }
2119 }
2120
2121 //
2122 // Detach it from list first.
2123 //
2124 RemoveEntryList (&Target->Link);
2125 FreePool (Target);
2126
2127 PendingListLink = PendingListNextLink;
2128 }
2129
2130 return EFI_SUCCESS;
2131}
2132
2133/**
2134 Release all resource in statement list.
2135
2136 @param[in] StatementList Statement list to be released.
2137
2138 @retval EFI_SUCCESS All resource are released.
2139 @retval EFI_INVALID_PARAMETER StatementList is NULL.
2140
2141**/
2142EFI_STATUS
2143ReleaseStatementList (
2144 IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST *StatementList
2145 )
2146{
2147 REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF *StatementRef;
2148 LIST_ENTRY *NextLink;
2149
2150 if (StatementList == NULL) {
2151 return EFI_INVALID_PARAMETER;
2152 }
2153
2154 if (IsListEmpty (&StatementList->StatementList)) {
2155 return EFI_SUCCESS;
2156 }
2157
2158 NextLink = GetFirstNode (&StatementList->StatementList);
2159 while (!IsNull (&StatementList->StatementList, NextLink)) {
2160 StatementRef = REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink);
2161 NextLink = GetNextNode (&StatementList->StatementList, NextLink);
2162
2163 RemoveEntryList (&StatementRef->Link);
2164 FreePool (StatementRef);
2165 }
2166
2167 return EFI_SUCCESS;
2168}
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