/** @file\r
HII Library implementation that uses DXE protocols and services.\r
\r
- Copyright (c) 2006 - 2010, Intel Corporation<BR>\r
- All rights reserved. This program and the accompanying materials\r
+ Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
http://opensource.org/licenses/bsd-license.php\r
to packages terminated by a NULL.\r
\r
@retval NULL A HII Handle has already been registered in the HII Database with\r
- the same PackageListGuid.\r
+ the same PackageListGuid and DeviceHandle.\r
@retval NULL The HII Handle could not be created.\r
@retval NULL An empty list of packages was passed in.\r
@retval NULL All packages are empty.\r
\r
default:\r
return EFI_INVALID_PARAMETER;\r
- break;\r
}\r
\r
return EFI_SUCCESS;\r
UINT16 Offset;\r
UINT16 Width;\r
UINT64 VarValue;\r
+ EFI_IFR_TYPE_VALUE TmpValue;\r
LIST_ENTRY *Link;\r
UINT8 *VarBuffer;\r
UINTN MaxBufferSize;\r
// Get Offset by Question header\r
//\r
Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
- Width = sizeof (BOOLEAN);\r
+ Width = (UINT16) sizeof (BOOLEAN);\r
//\r
// Check whether this question is in current block array.\r
//\r
//\r
// Check current value is the value of one of option.\r
//\r
- if (VarValue == IfrOneOfOption->Value.u64) {\r
+ ASSERT (IfrOneOfOption->Type <= EFI_IFR_TYPE_NUM_SIZE_64);\r
+ ZeroMem (&TmpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
+ CopyMem (&TmpValue, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
+ if (VarValue == TmpValue.u64) {\r
//\r
// The value is one of option value.\r
// Set OpCode to Zero, don't need check again.\r
UINT32 Index;\r
EFI_GUID *VarGuid;\r
EFI_STRING VarName;\r
- EFI_STRING_ID DefaultName;\r
\r
- UINT8 *PackageData;\r
- UINTN IfrOffset;\r
- EFI_IFR_OP_HEADER *IfrOpHdr;\r
EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
- UINT32 PackageOffset; \r
UINTN PackageListLength;\r
- EFI_HII_PACKAGE_HEADER PacakgeHeader;\r
EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- \r
+\r
ConfigAltResp = NULL;\r
ConfigResp = NULL;\r
VarGuid = NULL;\r
Index = 0;\r
TempDriverHandle = NULL;\r
HiiHandle = NULL;\r
- PackageData = NULL;\r
HiiPackageList = NULL;\r
\r
//\r
Status = EFI_SUCCESS;\r
goto NextConfigAltResp;\r
}\r
- \r
- //\r
- // 2. Get DefaultName string ID by parsing the PacakgeList \r
- //\r
\r
//\r
- // Get HiiPackage by HiiHandle\r
+ // 2. Get HiiPackage by HiiHandle\r
//\r
PackageListLength = 0;\r
HiiPackageList = NULL;\r
goto Done;\r
}\r
\r
- //\r
- // Parse the form package and get the default name string ID.\r
- //\r
- if (ActionType == ACTION_SET_DEFAUTL_VALUE) {\r
- PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
- Status = EFI_NOT_FOUND;\r
- while (PackageOffset < PackageListLength) {\r
- CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));\r
- \r
- //\r
- // Parse IFR opcode to get default store opcode\r
- //\r
- if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
- IfrOffset = sizeof (PacakgeHeader);\r
- PackageData = (UINT8 *) HiiPackageList + PackageOffset;\r
- while (IfrOffset < PacakgeHeader.Length) {\r
- IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset);\r
- //\r
- // Match DefaultId to find its DefaultName\r
- //\r
- if (IfrOpHdr->OpCode == EFI_IFR_DEFAULTSTORE_OP) {\r
- if (((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId == DefaultId) {\r
- DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;\r
- Status = EFI_SUCCESS;\r
- break;\r
- }\r
- }\r
- IfrOffset += IfrOpHdr->Length;\r
- }\r
- //\r
- // Only one form is in a package list.\r
- //\r
- break;\r
- }\r
- \r
- //\r
- // Go to next package.\r
- //\r
- PackageOffset += PacakgeHeader.Length; \r
- }\r
- \r
- //\r
- // Not found the matched default string ID\r
- //\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_SUCCESS;\r
- goto NextConfigAltResp;\r
- }\r
- }\r
- \r
//\r
// 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
- // Get the default configuration string according to the found default name string ID.\r
+ // Get the default configuration string according to the default ID.\r
//\r
Status = gHiiConfigRouting->GetAltConfig (\r
gHiiConfigRouting,\r
VarGuid,\r
VarName,\r
DevicePath,\r
- (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultName:NULL, // it can be NULL to get the current setting.\r
+ (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultId:NULL, // it can be NULL to get the current setting.\r
&ConfigResp\r
);\r
\r
If it is NULL, all current configuration for the\r
entirety of the current HII database will be validated.\r
\r
- @retval TURE Current configuration is valid.\r
+ @retval TRUE Current configuration is valid.\r
@retval FALSE Current configuration is invalid.\r
**/\r
BOOLEAN\r
OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE),\r
OpCodeBuffer->Buffer\r
);\r
- if (Buffer == NULL) {\r
- return NULL;\r
- }\r
+ ASSERT (Buffer != NULL);\r
OpCodeBuffer->Buffer = Buffer;\r
OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE);\r
}\r
OpCode.Type = Type;\r
CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
\r
- return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, sizeof (OpCode));\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, OFFSET_OF(EFI_IFR_ONE_OF_OPTION, Value) + mHiiDefaultTypeToWidth[Type]);\r
}\r
\r
/**\r
OpCode.DefaultId = DefaultId;\r
CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
\r
- return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, sizeof (OpCode));\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, OFFSET_OF(EFI_IFR_DEFAULT, Value) + mHiiDefaultTypeToWidth[Type]);\r
}\r
\r
/**\r
{\r
EFI_IFR_ACTION OpCode;\r
\r
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
\r
ZeroMem (&OpCode, sizeof (OpCode));\r
OpCode.Question.QuestionId = QuestionId;\r
{\r
EFI_IFR_REF OpCode;\r
\r
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
\r
ZeroMem (&OpCode, sizeof (OpCode));\r
OpCode.Question.Header.Prompt = Prompt;\r
EFI_IFR_CHECKBOX OpCode;\r
UINTN Position;\r
\r
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
\r
ZeroMem (&OpCode, sizeof (OpCode));\r
OpCode.Question.QuestionId = QuestionId;\r
{\r
EFI_IFR_NUMERIC OpCode;\r
UINTN Position;\r
+ UINTN Length;\r
\r
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
\r
+ Length = 0;\r
ZeroMem (&OpCode, sizeof (OpCode));\r
OpCode.Question.QuestionId = QuestionId;\r
OpCode.Question.VarStoreId = VarStoreId;\r
OpCode.data.u8.MinValue = (UINT8)Minimum;\r
OpCode.data.u8.MaxValue = (UINT8)Maximum;\r
OpCode.data.u8.Step = (UINT8)Step;\r
+ Length = 3;\r
break;\r
\r
case EFI_IFR_NUMERIC_SIZE_2:\r
OpCode.data.u16.MinValue = (UINT16)Minimum;\r
OpCode.data.u16.MaxValue = (UINT16)Maximum;\r
OpCode.data.u16.Step = (UINT16)Step;\r
+ Length = 6;\r
break;\r
\r
case EFI_IFR_NUMERIC_SIZE_4:\r
OpCode.data.u32.MinValue = (UINT32)Minimum;\r
OpCode.data.u32.MaxValue = (UINT32)Maximum;\r
OpCode.data.u32.Step = (UINT32)Step;\r
+ Length = 12;\r
break;\r
\r
case EFI_IFR_NUMERIC_SIZE_8:\r
OpCode.data.u64.MinValue = Minimum;\r
OpCode.data.u64.MaxValue = Maximum;\r
OpCode.data.u64.Step = Step;\r
+ Length = 24;\r
break;\r
}\r
\r
+ Length += OFFSET_OF (EFI_IFR_NUMERIC, data);\r
+\r
if (DefaultsOpCodeHandle == NULL) {\r
- return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode));\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length);\r
}\r
\r
Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
- InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode), 0, 1);\r
+ InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length, 0, 1);\r
InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
HiiCreateEndOpCode (OpCodeHandle);\r
return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
EFI_IFR_STRING OpCode;\r
UINTN Position;\r
\r
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
\r
ZeroMem (&OpCode, sizeof (OpCode));\r
OpCode.Question.Header.Prompt = Prompt;\r
{\r
EFI_IFR_ONE_OF OpCode;\r
UINTN Position;\r
+ UINTN Length;\r
\r
ASSERT (OptionsOpCodeHandle != NULL);\r
ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
OpCode.Question.Flags = QuestionFlags;\r
OpCode.Flags = OneOfFlags;\r
\r
+ Length = OFFSET_OF (EFI_IFR_ONE_OF, data);\r
+ Length += (1 << (OneOfFlags & EFI_IFR_NUMERIC_SIZE)) * 3;\r
+\r
Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
- InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, sizeof (OpCode), 0, 1);\r
+ InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, Length, 0, 1);\r
InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);\r
if (DefaultsOpCodeHandle != NULL) {\r
InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
}\r
\r
+/**\r
+ Create EFI_IFR_TEXT_OP opcode.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] Prompt String ID for Prompt.\r
+ @param[in] Help String ID for Help.\r
+ @param[in] TextTwo String ID for TextTwo.\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateTextOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN EFI_STRING_ID TextTwo\r
+ )\r
+{\r
+ EFI_IFR_TEXT OpCode;\r
+\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Statement.Prompt = Prompt;\r
+ OpCode.Statement.Help = Help;\r
+ OpCode.TextTwo = TextTwo;\r
+\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TEXT_OP, sizeof (OpCode));\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_DATE_OP opcode.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
+ If any reserved bits are set in DateFlags, then ASSERT().\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] QuestionId Question ID\r
+ @param[in] VarStoreId Storage ID, optional. If DateFlags is not\r
+ QF_DATE_STORAGE_NORMAL, this parameter is ignored.\r
+ @param[in] VarOffset Offset in Storage, optional. If DateFlags is not\r
+ QF_DATE_STORAGE_NORMAL, this parameter is ignored.\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] QuestionFlags Flags in Question Header\r
+ @param[in] DateFlags Flags for date opcode\r
+ @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
+ is an optional parameter that may be NULL.\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateDateOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId, OPTIONAL\r
+ IN UINT16 VarOffset, OPTIONAL\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 DateFlags,\r
+ IN VOID *DefaultsOpCodeHandle OPTIONAL\r
+ )\r
+{\r
+ EFI_IFR_DATE OpCode;\r
+ UINTN Position;\r
+\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
+ ASSERT ((DateFlags & (~(EFI_QF_DATE_YEAR_SUPPRESS | EFI_QF_DATE_MONTH_SUPPRESS | EFI_QF_DATE_DAY_SUPPRESS | EFI_QF_DATE_STORAGE))) == 0);\r
+\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.VarStoreId = VarStoreId;\r
+ OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.Flags = DateFlags;\r
+\r
+ if (DefaultsOpCodeHandle == NULL) {\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode));\r
+ }\r
+\r
+ Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+ InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode), 0, 1);\r
+ InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+ HiiCreateEndOpCode (OpCodeHandle);\r
+ return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_TIME_OP opcode.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
+ If any reserved bits are set in TimeFlags, then ASSERT().\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] QuestionId Question ID\r
+ @param[in] VarStoreId Storage ID, optional. If TimeFlags is not\r
+ QF_TIME_STORAGE_NORMAL, this parameter is ignored.\r
+ @param[in] VarOffset Offset in Storage, optional. If TimeFlags is not\r
+ QF_TIME_STORAGE_NORMAL, this parameter is ignored.\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] QuestionFlags Flags in Question Header\r
+ @param[in] TimeFlags Flags for time opcode\r
+ @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
+ is an optional parameter that may be NULL.\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateTimeOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId, OPTIONAL\r
+ IN UINT16 VarOffset, OPTIONAL\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 TimeFlags,\r
+ IN VOID *DefaultsOpCodeHandle OPTIONAL\r
+ )\r
+{\r
+ EFI_IFR_TIME OpCode;\r
+ UINTN Position;\r
+\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
+ ASSERT ((TimeFlags & (~(QF_TIME_HOUR_SUPPRESS | QF_TIME_MINUTE_SUPPRESS | QF_TIME_SECOND_SUPPRESS | QF_TIME_STORAGE))) == 0);\r
+\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.VarStoreId = VarStoreId;\r
+ OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.Flags = TimeFlags;\r
+\r
+ if (DefaultsOpCodeHandle == NULL) {\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode));\r
+ }\r
+\r
+ Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+ InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode), 0, 1);\r
+ InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+ HiiCreateEndOpCode (OpCodeHandle);\r
+ return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
+}\r
+\r
/**\r
This is the internal worker function to update the data in\r
a form specified by FormSetGuid, FormId and Label.\r