Per UEFI spec, FORM_OPEN/FORM_CLOSE Callback function should be called for each question in the form when this form opens or closes.

Update SetupBrowser driver to call Callback function (FORM_OPEN/FORM_CLOSE) based on UEFI spec, and update all EDKII HII drivers to correctly handle FORM_OPEN and FORM_CLOSE call back. 


git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10560 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
lgao4 2010-06-02 02:05:47 +00:00
parent 2bd78c92c6
commit 5adb8db71e
8 changed files with 306 additions and 140 deletions

View File

@ -842,61 +842,67 @@ DriverCallback (
UINTN MyVarSize;
if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
//
// On FORM_OPEN event, update the form on-the-fly
//
PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
if (QuestionId == 0x1234) {
//
// Sample CallBack for UEFI FORM_OPEN action:
// Add Save action into Form 3 when Form 1 is opened.
// This will be done only in FORM_OPEN CallBack of question with ID 0x1234 from Form 1.
//
PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
//
// Initialize the container for dynamic opcodes
//
StartOpCodeHandle = HiiAllocateOpCodeHandle ();
ASSERT (StartOpCodeHandle != NULL);
//
// Initialize the container for dynamic opcodes
//
StartOpCodeHandle = HiiAllocateOpCodeHandle ();
ASSERT (StartOpCodeHandle != NULL);
//
// Create Hii Extend Label OpCode as the start opcode
//
StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
StartLabel->Number = LABEL_UPDATE2;
//
// Create Hii Extend Label OpCode as the start opcode
//
StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
StartLabel->Number = LABEL_UPDATE2;
HiiCreateActionOpCode (
StartOpCodeHandle, // Container for dynamic created opcodes
0x1238, // Question ID
STRING_TOKEN(STR_SAVE_TEXT), // Prompt text
STRING_TOKEN(STR_SAVE_TEXT), // Help text
EFI_IFR_FLAG_CALLBACK, // Question flag
0 // Action String ID
);
HiiUpdateForm (
PrivateData->HiiHandle[0], // HII handle
&mFormSetGuid, // Formset GUID
0x3, // Form ID
StartOpCodeHandle, // Label for where to insert opcodes
NULL // Insert data
HiiCreateActionOpCode (
StartOpCodeHandle, // Container for dynamic created opcodes
0x1238, // Question ID
STRING_TOKEN(STR_SAVE_TEXT), // Prompt text
STRING_TOKEN(STR_SAVE_TEXT), // Help text
EFI_IFR_FLAG_CALLBACK, // Question flag
0 // Action String ID
);
HiiFreeOpCodeHandle (StartOpCodeHandle);
HiiUpdateForm (
PrivateData->HiiHandle[0], // HII handle
&mFormSetGuid, // Formset GUID
0x3, // Form ID
StartOpCodeHandle, // Label for where to insert opcodes
NULL // Insert data
);
HiiFreeOpCodeHandle (StartOpCodeHandle);
}
return EFI_SUCCESS;
}
if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
//
// On FORM_CLOSE event, show up a pop-up
//
do {
CreatePopUp (
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
&Key,
L"",
L"You are going to leave the Form!",
L"Press ESC or ENTER to continue ...",
L"",
NULL
);
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
if (QuestionId == 0x5678) {
//
// Sample CallBack for UEFI FORM_CLOSE action:
// Show up a pop-up to specify Form 3 will be closed when exit Form 3.
//
do {
CreatePopUp (
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
&Key,
L"",
L"You are going to leave third Form!",
L"Press ESC or ENTER to continue ...",
L"",
NULL
);
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
}
return EFI_SUCCESS;
}
@ -1028,6 +1034,37 @@ DriverCallback (
NULL // Default Opcode is NULl
);
HiiCreateTextOpCode (
StartOpCodeHandle,
STRING_TOKEN(STR_TEXT_SAMPLE_HELP),
STRING_TOKEN(STR_TEXT_SAMPLE_HELP),
STRING_TOKEN(STR_TEXT_SAMPLE_STRING)
);
HiiCreateDateOpCode (
StartOpCodeHandle,
0x8004,
0x0,
0x0,
STRING_TOKEN(STR_DATE_SAMPLE_HELP),
STRING_TOKEN(STR_DATE_SAMPLE_HELP),
0,
QF_DATE_STORAGE_TIME,
NULL
);
HiiCreateTimeOpCode (
StartOpCodeHandle,
0x8005,
0x0,
0x0,
STRING_TOKEN(STR_TIME_SAMPLE_HELP),
STRING_TOKEN(STR_TIME_SAMPLE_HELP),
0,
QF_TIME_STORAGE_TIME,
NULL
);
HiiCreateGotoOpCode (
StartOpCodeHandle, // Container for dynamic created opcodes
1, // Target Form ID

View File

@ -562,6 +562,13 @@ IScsiFormCallback (
EFI_STATUS Status;
EFI_INPUT_KEY Key;
if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
//
// Do nothing for UEFI OPEN/CLOSE Action
//
return EFI_SUCCESS;
}
Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
//

View File

@ -670,6 +670,13 @@ Ip4FormCallback (
EFI_STATUS Status;
EFI_INPUT_KEY Key;
if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
//
// Do nothing for UEFI OPEN/CLOSE Action
//
return EFI_SUCCESS;
}
Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));

View File

@ -237,11 +237,20 @@ VlanCallback (
PrivateData = VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This);
if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
//
// On FORM_OPEN event, update current VLAN list
//
VlanUpdateForm (PrivateData);
if (QuestionId == VLAN_ADD_QUESTION_ID) {
//
// Update current VLAN list into Form when Form is opened.
// This will be done only in FORM_OPEN CallBack of question with VLAN_ADD_QUESTION_ID.
//
VlanUpdateForm (PrivateData);
}
return EFI_SUCCESS;
}
if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
//
// Do nothing for UEFI FORM_CLOSE action
//
return EFI_SUCCESS;
}

View File

@ -1334,7 +1334,14 @@ PlatOverMngrCallback (
EFI_STRING_ID NewStringToken;
EFI_INPUT_KEY Key;
PLAT_OVER_MNGR_DATA *FakeNvData;
if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
//
// Do nothing for UEFI OPEN/CLOSE Action
//
return EFI_SUCCESS;
}
Private = EFI_CALLBACK_INFO_FROM_THIS (This);
FakeNvData = &Private->FakeNvData;
if (!HiiGetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData)) {

View File

@ -842,6 +842,8 @@ FormUpdateNotify (
return EFI_SUCCESS;
}
BOOLEAN mFormCloseCallBack = FALSE;
/**
The worker function that send the displays to the screen. On output,
the selection made by user is returned.
@ -870,10 +872,16 @@ SetupBrowser (
EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
FORM_BROWSER_FORMSET *FormSet;
EFI_INPUT_KEY Key;
BOOLEAN FormOpenCallBack;
BOOLEAN SubmitFormIsRequired;
EFI_GUID CurrentFormSetGuid;
EFI_HII_HANDLE CurrentHiiHandle;
UINT16 CurrentFormId;
gMenuRefreshHead = NULL;
gResetRequired = FALSE;
FormSet = Selection->FormSet;
ConfigAccess = Selection->FormSet->ConfigAccess;
//
// Register notify for Form package update
@ -890,53 +898,6 @@ SetupBrowser (
return Status;
}
//
// Before display the formset, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN
//
ConfigAccess = Selection->FormSet->ConfigAccess;
if ((ConfigAccess != NULL) && (Selection->Action != UI_ACTION_REFRESH_FORMSET)) {
ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
mHiiPackageListUpdated = FALSE;
Status = ConfigAccess->Callback (
ConfigAccess,
EFI_BROWSER_ACTION_FORM_OPEN,
0,
EFI_IFR_TYPE_UNDEFINED,
NULL,
&ActionRequest
);
if (!EFI_ERROR (Status)) {
switch (ActionRequest) {
case EFI_BROWSER_ACTION_REQUEST_RESET:
gResetRequired = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
//
// Till now there is no uncommitted data, so ignore this request
//
break;
case EFI_BROWSER_ACTION_REQUEST_EXIT:
Selection->Action = UI_ACTION_EXIT;
break;
default:
break;
}
}
if (mHiiPackageListUpdated) {
//
// IFR is updated during callback, force to reparse the IFR binary
//
mHiiPackageListUpdated = FALSE;
Selection->Action = UI_ACTION_REFRESH_FORMSET;
goto Done;
}
}
//
// Initialize current settings of Questions in this FormSet
//
@ -950,7 +911,13 @@ SetupBrowser (
//
// Initialize Selection->Form
//
FormOpenCallBack = FALSE;
if (Selection->FormId == 0) {
//
// First Form will open.
//
FormOpenCallBack = TRUE;
//
// Zero FormId indicates display the first Form in a FormSet
//
@ -959,6 +926,12 @@ SetupBrowser (
Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);
Selection->FormId = Selection->Form->FormId;
} else {
if (Selection->Form == NULL) {
//
// First Form will open.
//
FormOpenCallBack = TRUE;
}
Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);
}
@ -989,12 +962,100 @@ SetupBrowser (
return EFI_NOT_FOUND;
}
}
//
// Keep current form information
//
CurrentHiiHandle = Selection->Handle;
CopyGuid (&CurrentFormSetGuid, &Selection->FormSetGuid);
CurrentFormId = Selection->FormId;
//
// Reset FormPackage update flag
//
mHiiPackageListUpdated = FALSE;
//
// Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN
// for each question with callback flag.
// New form may be the first form, or the different form after another form close.
//
if ((FormOpenCallBack || mFormCloseCallBack) && (ConfigAccess != NULL)) {
mFormCloseCallBack = FALSE;
//
// Go through each statement in this form
//
SubmitFormIsRequired = FALSE;
Link = GetFirstNode (&Selection->Form->StatementListHead);
while (!IsNull (&Selection->Form->StatementListHead, Link)) {
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
Link = GetNextNode (&Selection->Form->StatementListHead, Link);
if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {
continue;
}
//
// Check whether Statement is disabled.
//
if (Statement->DisableExpression != NULL) {
Status = EvaluateExpression (Selection->FormSet, Selection->Form, Statement->DisableExpression);
if (!EFI_ERROR (Status) &&
(Statement->DisableExpression->Result.Type == EFI_IFR_TYPE_BOOLEAN) &&
(Statement->DisableExpression->Result.Value.b)) {
continue;
}
}
ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
Status = ConfigAccess->Callback (
ConfigAccess,
EFI_BROWSER_ACTION_FORM_OPEN,
Statement->QuestionId,
EFI_IFR_TYPE_UNDEFINED,
NULL,
&ActionRequest
);
if (!EFI_ERROR (Status)) {
switch (ActionRequest) {
case EFI_BROWSER_ACTION_REQUEST_RESET:
gResetRequired = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
SubmitFormIsRequired = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_EXIT:
Selection->Action = UI_ACTION_EXIT;
gNvUpdateRequired = FALSE;
break;
default:
break;
}
}
}
if (SubmitFormIsRequired) {
SubmitForm (Selection->FormSet, Selection->Form);
}
//
// EXIT requests to close form.
//
if (Selection->Action == UI_ACTION_EXIT) {
goto Done;
}
//
// IFR is updated during callback of open form, force to reparse the IFR binary
//
if (mHiiPackageListUpdated) {
Selection->Action = UI_ACTION_REFRESH_FORMSET;
mHiiPackageListUpdated = FALSE;
goto Done;
}
}
//
// Load Questions' Value for display
//
@ -1003,6 +1064,12 @@ SetupBrowser (
return Status;
}
//
// EXIT requests to close form.
//
if (Selection->Action == UI_ACTION_EXIT) {
goto Done;
}
//
// IFR is updated during callback of read value, force to reparse the IFR binary
//
@ -1119,41 +1186,66 @@ SetupBrowser (
Selection->Action = UI_ACTION_REFRESH_FORMSET;
}
}
} while (Selection->Action == UI_ACTION_REFRESH_FORM);
//
// Before exit the formset, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE
//
if ((ConfigAccess != NULL) && (Selection->Action == UI_ACTION_EXIT)) {
ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
Status = ConfigAccess->Callback (
ConfigAccess,
EFI_BROWSER_ACTION_FORM_CLOSE,
0,
EFI_IFR_TYPE_UNDEFINED,
NULL,
&ActionRequest
);
//
// Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE
// for each question with callback flag.
//
mFormCloseCallBack = FALSE;
if ((ConfigAccess != NULL) &&
((Selection->Action == UI_ACTION_EXIT) ||
(Selection->Handle != CurrentHiiHandle) ||
(!CompareGuid (&CurrentFormSetGuid, &Selection->FormSetGuid)) ||
(Selection->FormId != CurrentFormId))) {
//
// Go through each statement in this form
//
mFormCloseCallBack = TRUE;
SubmitFormIsRequired = FALSE;
Link = GetFirstNode (&Selection->Form->StatementListHead);
while (!IsNull (&Selection->Form->StatementListHead, Link)) {
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
Link = GetNextNode (&Selection->Form->StatementListHead, Link);
if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {
continue;
}
if (!EFI_ERROR (Status)) {
switch (ActionRequest) {
case EFI_BROWSER_ACTION_REQUEST_RESET:
gResetRequired = TRUE;
break;
ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
Status = ConfigAccess->Callback (
ConfigAccess,
EFI_BROWSER_ACTION_FORM_CLOSE,
Statement->QuestionId,
EFI_IFR_TYPE_UNDEFINED,
NULL,
&ActionRequest
);
case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
if (!EFI_ERROR (Status)) {
switch (ActionRequest) {
case EFI_BROWSER_ACTION_REQUEST_RESET:
gResetRequired = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
SubmitFormIsRequired = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_EXIT:
Selection->Action = UI_ACTION_EXIT;
gNvUpdateRequired = FALSE;
break;
default:
break;
}
}
}
if (SubmitFormIsRequired) {
SubmitForm (Selection->FormSet, Selection->Form);
break;
case EFI_BROWSER_ACTION_REQUEST_EXIT:
gNvUpdateRequired = FALSE;
break;
default:
break;
}
}
}
} while (Selection->Action == UI_ACTION_REFRESH_FORM);
//
// Record the old formset

View File

@ -1679,10 +1679,9 @@ ValidateQuestion (
/**
Perform NoSubmit check for a Form.
Perform NoSubmit check for each Form in FormSet.
@param FormSet FormSet data structure.
@param Form Form data structure.
@retval EFI_SUCCESS Form validation pass.
@retval other Form validation failed.
@ -1690,24 +1689,32 @@ ValidateQuestion (
**/
EFI_STATUS
NoSubmitCheck (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_FORM *Form
IN FORM_BROWSER_FORMSET *FormSet
)
{
EFI_STATUS Status;
LIST_ENTRY *Link;
FORM_BROWSER_STATEMENT *Question;
FORM_BROWSER_FORM *Form;
LIST_ENTRY *LinkForm;
Link = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, Link)) {
Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
LinkForm = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, LinkForm)) {
Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);
Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);
if (EFI_ERROR (Status)) {
return Status;
Link = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, Link)) {
Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);
if (EFI_ERROR (Status)) {
return Status;
}
Link = GetNextNode (&Form->StatementListHead, Link);
}
Link = GetNextNode (&Form->StatementListHead, Link);
LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
}
return EFI_SUCCESS;
@ -1738,7 +1745,7 @@ SubmitForm (
//
// Validate the Form by NoSubmit check
//
Status = NoSubmitCheck (FormSet, Form);
Status = NoSubmitCheck (FormSet);
if (EFI_ERROR (Status)) {
return Status;
}