Enable new "ref5" opcode in browser.

Signed-off-by:ydong10
Reviewed-by:lgao4






git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11913 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
ydong10 2011-06-28 06:41:28 +00:00
parent 2ed77d0de5
commit 8ca6180f21
6 changed files with 236 additions and 147 deletions

View File

@ -1143,6 +1143,10 @@ ParseOpCodes (
ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_TIME);
break;
case EFI_IFR_TYPE_REF:
ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_REF);
break;
case EFI_IFR_TYPE_OTHER:
case EFI_IFR_TYPE_UNDEFINED:
case EFI_IFR_TYPE_ACTION:
@ -1548,19 +1552,25 @@ ParseOpCodes (
case EFI_IFR_REF_OP:
CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
ASSERT (CurrentStatement != NULL);
CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_UNDEFINED;
CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
Value = &CurrentStatement->HiiValue;
Value->Type = EFI_IFR_TYPE_REF;
if (OpCodeLength >= sizeof (EFI_IFR_REF)) {
CopyMem (&Value->Value.ref.FormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
CopyMem (&Value->Value.ref.QuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
CopyMem (&Value->Value.ref.FormSetGuid, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
CopyMem (&Value->Value.ref.DevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
}
}
}
}
CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_REF);
InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
break;
case EFI_IFR_ONE_OF_OP:

View File

@ -1162,6 +1162,14 @@ ProcessCallBackFunction (
default:
break;
}
//
// According the spec, return value from call back of "changing" and
// "retrieve" should update to the question's temp buffer.
//
if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {
SetQuestionValue(Selection->FormSet,Selection->Form, Question,TRUE);
}
} else if (Status == EFI_UNSUPPORTED) {
//
// If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.
@ -1384,11 +1392,18 @@ SetupBrowser (
(Statement->Operand != EFI_IFR_PASSWORD_OP)) {
Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);
if ((EFI_ERROR (Status)) && (Status != EFI_UNSUPPORTED)) {
if (Statement->Operand == EFI_IFR_REF_OP && Selection->Action != UI_ACTION_EXIT) {
//
// Callback return error status other than EFI_UNSUPPORTED
// Process dynamic update ref opcode.
//
if (Statement->Operand == EFI_IFR_REF_OP) {
if (!EFI_ERROR (Status)) {
Status = ProcessGotoOpCode(Statement, Selection, NULL, NULL);
}
//
// Callback return error status or status return from process goto opcode.
//
if (EFI_ERROR (Status)) {
//
// Cross reference will not be taken
//

View File

@ -2643,6 +2643,16 @@ LoadFormConfig (
HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);
}
//
// According the spec, ref opcode try to get value from call back with "retrieve" type.
//
if ((Question->Operand == EFI_IFR_REF_OP) && (FormSet->ConfigAccess != NULL)) {
Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Check whether EfiVarstore with CallBack can be got.
//

View File

@ -372,10 +372,6 @@ typedef struct {
UINT64 Step;
EFI_DEFAULT_ID DefaultId; // for EFI_IFR_RESET_BUTTON
EFI_FORM_ID RefFormId; // for EFI_IFR_REF
EFI_QUESTION_ID RefQuestionId; // for EFI_IFR_REF2
EFI_GUID RefFormSetId; // for EFI_IFR_REF3
EFI_STRING_ID RefDevicePath; // for EFI_IFR_REF4
EFI_GUID RefreshGuid; // for EFI_IFR_REFRESH_ID
//

View File

@ -1649,6 +1649,175 @@ DevicePathToHiiHandle (
return HiiHandle;
}
/**
Process the goto op code, update the info in the selection structure.
@param Statement The statement belong to goto op code.
@param Selection The selection info.
@param Repaint Whether need to repaint the menu.
@param NewLine Whether need to create new line.
@retval EFI_SUCCESS The menu process successfully.
@return Other value if the process failed.
**/
EFI_STATUS
ProcessGotoOpCode (
IN OUT FORM_BROWSER_STATEMENT *Statement,
IN OUT UI_MENU_SELECTION *Selection,
OUT BOOLEAN *Repaint,
OUT BOOLEAN *NewLine
)
{
CHAR16 *StringPtr;
UINTN BufferSize;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
CHAR16 TemStr[2];
UINT8 *DevicePathBuffer;
UINTN Index;
UINT8 DigitUint8;
FORM_BROWSER_FORM *RefForm;
EFI_INPUT_KEY Key;
EFI_STATUS Status;
UI_MENU_LIST *MenuList;
Status = EFI_SUCCESS;
if (Statement->HiiValue.Value.ref.DevicePath != 0) {
if (Selection->Form->ModalForm) {
return Status;
}
//
// Goto another Hii Package list
//
Selection->Action = UI_ACTION_REFRESH_FORMSET;
StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);
if (StringPtr == NULL) {
//
// No device path string not found, exit
//
Selection->Action = UI_ACTION_EXIT;
Selection->Statement = NULL;
return Status;
}
BufferSize = StrLen (StringPtr) / 2;
DevicePath = AllocatePool (BufferSize);
ASSERT (DevicePath != NULL);
//
// Convert from Device Path String to DevicePath Buffer in the reverse order.
//
DevicePathBuffer = (UINT8 *) DevicePath;
for (Index = 0; StringPtr[Index] != L'\0'; Index ++) {
TemStr[0] = StringPtr[Index];
DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
if (DigitUint8 == 0 && TemStr[0] != L'0') {
//
// Invalid Hex Char as the tail.
//
break;
}
if ((Index & 1) == 0) {
DevicePathBuffer [Index/2] = DigitUint8;
} else {
DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);
}
}
Selection->Handle = DevicePathToHiiHandle (DevicePath);
if (Selection->Handle == NULL) {
//
// If target Hii Handle not found, exit
//
Selection->Action = UI_ACTION_EXIT;
Selection->Statement = NULL;
return Status;
}
FreePool (StringPtr);
FreePool (DevicePath);
CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));
Selection->FormId = Statement->HiiValue.Value.ref.FormId;
Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
} else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {
if (Selection->Form->ModalForm) {
return Status;
}
//
// Goto another Formset, check for uncommitted data
//
Selection->Action = UI_ACTION_REFRESH_FORMSET;
CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));
Selection->FormId = Statement->HiiValue.Value.ref.FormId;
Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
} else if (Statement->HiiValue.Value.ref.FormId != 0) {
//
// Check whether target From is suppressed.
//
RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);
if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {
Status = EvaluateExpression (Selection->FormSet, RefForm, RefForm->SuppressExpression);
if (EFI_ERROR (Status)) {
return Status;
}
if (RefForm->SuppressExpression->Result.Value.b) {
//
// Form is suppressed.
//
do {
CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
if (Repaint != NULL) {
*Repaint = TRUE;
}
return Status;
}
}
//
// Goto another form inside this formset,
//
Selection->Action = UI_ACTION_REFRESH_FORM;
//
// Link current form so that we can always go back when someone hits the ESC
//
MenuList = UiFindMenuList (&Selection->FormSetGuid, Statement->HiiValue.Value.ref.FormId);
if (MenuList == NULL && Selection->CurrentMenu != NULL) {
MenuList = UiAddMenuList (Selection->CurrentMenu, &Selection->FormSetGuid, Statement->HiiValue.Value.ref.FormId);
}
Selection->FormId = Statement->HiiValue.Value.ref.FormId;
Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
} else if (Statement->HiiValue.Value.ref.QuestionId != 0) {
//
// Goto another Question
//
Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
Selection->Action = UI_ACTION_REFRESH_FORM;
} else {
if (Repaint != NULL) {
*Repaint = TRUE;
}
if (NewLine != NULL) {
*NewLine = TRUE;
}
}
} else {
if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
Selection->Action = UI_ACTION_REFRESH_FORM;
}
}
return Status;
}
/**
Display menu and wait for user to select one menu option, then return it.
If AutoBoot is enabled, then if user doesn't select any option,
@ -1704,16 +1873,9 @@ UiDisplayMenu (
MENU_REFRESH_ENTRY *MenuUpdateEntry;
UI_SCREEN_OPERATION ScreenOperation;
UINT8 MinRefreshInterval;
UINTN BufferSize;
UINT16 DefaultId;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
FORM_BROWSER_STATEMENT *Statement;
CHAR16 TemStr[2];
UINT8 *DevicePathBuffer;
UINT8 DigitUint8;
UI_MENU_LIST *CurrentMenu;
UI_MENU_LIST *MenuList;
FORM_BROWSER_FORM *RefForm;
UINTN ModalSkipColumn;
CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
@ -1736,7 +1898,6 @@ UiDisplayMenu (
NextMenuOption = NULL;
PreviousMenuOption = NULL;
SavedMenuOption = NULL;
RefForm = NULL;
ModalSkipColumn = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 6;
ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
@ -2613,130 +2774,7 @@ UiDisplayMenu (
switch (Statement->Operand) {
case EFI_IFR_REF_OP:
if (Statement->RefDevicePath != 0) {
if (Selection->Form->ModalForm) {
break;
}
//
// Goto another Hii Package list
//
Selection->Action = UI_ACTION_REFRESH_FORMSET;
StringPtr = GetToken (Statement->RefDevicePath, Selection->FormSet->HiiHandle);
if (StringPtr == NULL) {
//
// No device path string not found, exit
//
Selection->Action = UI_ACTION_EXIT;
Selection->Statement = NULL;
break;
}
BufferSize = StrLen (StringPtr) / 2;
DevicePath = AllocatePool (BufferSize);
ASSERT (DevicePath != NULL);
//
// Convert from Device Path String to DevicePath Buffer in the reverse order.
//
DevicePathBuffer = (UINT8 *) DevicePath;
for (Index = 0; StringPtr[Index] != L'\0'; Index ++) {
TemStr[0] = StringPtr[Index];
DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
if (DigitUint8 == 0 && TemStr[0] != L'0') {
//
// Invalid Hex Char as the tail.
//
break;
}
if ((Index & 1) == 0) {
DevicePathBuffer [Index/2] = DigitUint8;
} else {
DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);
}
}
Selection->Handle = DevicePathToHiiHandle (DevicePath);
if (Selection->Handle == NULL) {
//
// If target Hii Handle not found, exit
//
Selection->Action = UI_ACTION_EXIT;
Selection->Statement = NULL;
break;
}
FreePool (StringPtr);
FreePool (DevicePath);
CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));
Selection->FormId = Statement->RefFormId;
Selection->QuestionId = Statement->RefQuestionId;
} else if (!CompareGuid (&Statement->RefFormSetId, &gZeroGuid)) {
if (Selection->Form->ModalForm) {
break;
}
//
// Goto another Formset, check for uncommitted data
//
Selection->Action = UI_ACTION_REFRESH_FORMSET;
CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));
Selection->FormId = Statement->RefFormId;
Selection->QuestionId = Statement->RefQuestionId;
} else if (Statement->RefFormId != 0) {
//
// Check whether target From is suppressed.
//
RefForm = IdToForm (Selection->FormSet, Statement->RefFormId);
if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {
Status = EvaluateExpression (Selection->FormSet, RefForm, RefForm->SuppressExpression);
if (EFI_ERROR (Status)) {
return Status;
}
if (RefForm->SuppressExpression->Result.Value.b) {
//
// Form is suppressed.
//
do {
CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
Repaint = TRUE;
break;
}
}
//
// Goto another form inside this formset,
//
Selection->Action = UI_ACTION_REFRESH_FORM;
//
// Link current form so that we can always go back when someone hits the ESC
//
MenuList = UiFindMenuList (&Selection->FormSetGuid, Statement->RefFormId);
if (MenuList == NULL) {
MenuList = UiAddMenuList (CurrentMenu, &Selection->FormSetGuid, Statement->RefFormId);
}
Selection->FormId = Statement->RefFormId;
Selection->QuestionId = Statement->RefQuestionId;
} else if (Statement->RefQuestionId != 0) {
//
// Goto another Question
//
Selection->QuestionId = Statement->RefQuestionId;
if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
Selection->Action = UI_ACTION_REFRESH_FORM;
} else {
Repaint = TRUE;
NewLine = TRUE;
break;
}
}
ProcessGotoOpCode(Statement, Selection, &Repaint, &NewLine);
break;
case EFI_IFR_ACTION_OP:

View File

@ -331,6 +331,26 @@ FreeBrowserStrings (
VOID
);
/**
Process the goto op code, update the info in the selection structure.
@param Statement The statement belong to goto op code.
@param Selection The selection info.
@param Repaint Whether need to repaint the menu.
@param NewLine Whether need to create new line.
@retval EFI_SUCCESS The menu process successfully.
@return Other value if the process failed.
**/
EFI_STATUS
ProcessGotoOpCode (
IN OUT FORM_BROWSER_STATEMENT *Statement,
IN OUT UI_MENU_SELECTION *Selection,
OUT BOOLEAN *Repaint,
OUT BOOLEAN *NewLine
);
/**
The worker function that send the displays to the screen. On output,
the selection made by user is returned.