EFI_STATUS EFIAPI StslRecordMessage ( IN EFI_STANDARD_TEST_LIBRARY_PROTOCOL *This, IN EFI_VERBOSE_LEVEL VerboseLevel, IN CHAR16 *Message, ... ) /*++ Routine Description: Records the test message. Arguments: This - Standard test library protocol instance. VerboseLevel - Minimal verbose level to record this message. For example, EFI_VERBOSE_LEVEL_QUIET means this message should be recorded even the test is run in QUIET mode. On the contrary, EFI_VERBOSE_LEVEL_EXHAUSTIVE means this message will only be recorded when the test is run in EXHAUSTIVE mode. Message - Format string for the detail test information. Returns: EFI_SUCCESS - record the message successfully. --*/ { EFI_STATUS Status; VA_LIST Marker; CHAR16 Buffer[EFI_MAX_PRINT_BUFFER]; STANDARD_TEST_PRIVATE_DATA *Private; Status = EFI_SUCCESS; Private = STANDARD_TEST_PRIVATE_DATA_FROM_STSL (This); if (VerboseLevel <= Private->VerboseLevel) { VA_START(Marker, Message); VSPrint (Buffer, EFI_MAX_PRINT_BUFFER, Message, Marker); VA_END (Marker); if ( EfiStrLen (Buffer) + 3 < EFI_MAX_PRINT_BUFFER ) { EfiStrCat (Buffer, L"\r\n"); } Status = StslWriteLogFile (Private, Buffer); } return Status; }
EFI_STATUS BBTestExtractConfigConformanceTestCheckpoint1 ( IN EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib, IN EFI_HII_CONFIG_ACCESS_PROTOCOL *HIIConfigAccess ) { EFI_STATUS Status; EFI_TEST_ASSERTION AssertionType; EFI_STRING Progress = NULL; EFI_STRING Results = NULL; EFI_STRING ResultsPtr = NULL; UINTN Len = 0; EFI_STRING Pointer = NULL; UINT8 IfMulti = 0; EFI_STRING Request = NULL; // // Call ExtractConfig with Request been <MultiConfigRequest> // Status = HIIConfigAccess->ExtractConfig ( HIIConfigAccess, NULL, &Progress, &Results ); if ( Status == EFI_SUCCESS ) { Len = StrLen(Results); // // Make sure the size of Request is enough to hold <MultiConfigRequest> // if original Results is not Multi // Request = (EFI_STRING) AllocateZeroPool ( 2 * Len + 2 + 256); if (Request == NULL) { FreePool(Results); return EFI_OUT_OF_RESOURCES; } } else { return Status; } Status = MultiAltRespToMultiReq (Results, Request); ResultsPtr = Request; FreePool(Results); Results = NULL; if ( EfiStrStr(Request, L"GUID=") != NULL ) { Pointer = EfiStrStr(Request, L"GUID="); Pointer++; if ( EfiStrStr(Pointer, L"GUID=") != NULL ) IfMulti = 1; } if ( IfMulti == 0 ) { EfiStrCat( Request, L"&GUID=970eb94aa0d449f7b980bdaa47d42527&NAME=006a0069006e0039&PATH=000acf&grag&star"); } Status = HIIConfigAccess->ExtractConfig ( HIIConfigAccess, Request, &Progress, &Results ); if ( (EFI_INVALID_PARAMETER != Status) || (EfiStrnCmp (Progress, L"&GUID=", 6) != 0) ) { AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gHIIConfigAccessBBTestConformanceAssertionGuid001, L"HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig - ExtractConfig() returns EFI_INVALID_PARAMETER with Request been <MultiConfigRequest>.", L"%a:%d: Status - %r", __FILE__, (UINTN)__LINE__, Status ); FreePool(Request); return EFI_SUCCESS; }
EFI_STATUS GetSelectionInputPopUp ( IN UI_MENU_SELECTION *Selection, IN UI_MENU_OPTION *MenuOption ) /*++ Routine Description: Get selection for OneOf and OrderedList (Left/Right will be ignored). Arguments: Selection - Pointer to current selection. MenuOption - Pointer to the current input menu. Returns: EFI_SUCCESS - If Option input is processed successfully EFI_DEVICE_ERROR - If operation fails --*/ { EFI_STATUS Status; EFI_INPUT_KEY Key; UINTN Index; CHAR16 *StringPtr; CHAR16 *TempStringPtr; UINTN Index2; UINTN TopOptionIndex; UINTN HighlightOptionIndex; UINTN Start; UINTN End; UINTN Top; UINTN Bottom; UINTN PopUpMenuLines; UINTN MenuLinesInView; UINTN PopUpWidth; CHAR16 Character; INT32 SavedAttribute; BOOLEAN ShowDownArrow; BOOLEAN ShowUpArrow; UINTN DimensionsWidth; UINTN DimensionsHeight; EFI_LIST_ENTRY *Link; BOOLEAN OrderedList; UINT8 *ValueArray; UINT8 ValueType; EFI_HII_VALUE HiiValue; EFI_HII_VALUE *HiiValueArray; UINTN OptionCount; QUESTION_OPTION *OneOfOption; QUESTION_OPTION *CurrentOption; FORM_BROWSER_STATEMENT *Question; DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; ValueArray = NULL; ValueType = 0; CurrentOption = NULL; ShowDownArrow = FALSE; ShowUpArrow = FALSE; StringPtr = EfiLibAllocateZeroPool ((gOptionBlockWidth + 1) * 2); ASSERT (StringPtr); Question = MenuOption->ThisTag; if (Question->Operand == EFI_IFR_ORDERED_LIST_OP) { ValueArray = Question->BufferValue; ValueType = Question->ValueType; OrderedList = TRUE; } else { OrderedList = FALSE; } // // Calculate Option count // if (OrderedList) { for (Index = 0; Index < Question->MaxContainers; Index++) { if (GetArrayData (ValueArray, ValueType, Index) == 0) { break; } } OptionCount = Index; } else { OptionCount = 0; Link = GetFirstNode (&Question->OptionListHead); while (!IsNull (&Question->OptionListHead, Link)) { OneOfOption = QUESTION_OPTION_FROM_LINK (Link); OptionCount++; Link = GetNextNode (&Question->OptionListHead, Link); } } // // Prepare HiiValue array // HiiValueArray = EfiLibAllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE)); ASSERT (HiiValueArray != NULL); Link = GetFirstNode (&Question->OptionListHead); for (Index = 0; Index < OptionCount; Index++) { if (OrderedList) { HiiValueArray[Index].Type = ValueType; HiiValueArray[Index].Value.u64 = GetArrayData (ValueArray, ValueType, Index); } else { OneOfOption = QUESTION_OPTION_FROM_LINK (Link); EfiCopyMem (&HiiValueArray[Index], &OneOfOption->Value, sizeof (EFI_HII_VALUE)); Link = GetNextNode (&Question->OptionListHead, Link); } } // // Move Suppressed Option to list tail // PopUpMenuLines = 0; for (Index = 0; Index < OptionCount; Index++) { OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]); if (OneOfOption == NULL) { return EFI_NOT_FOUND; } RemoveEntryList (&OneOfOption->Link); if ((OneOfOption->SuppressExpression != NULL) && (OneOfOption->SuppressExpression->Result.Value.b)) { // // This option is suppressed, insert to tail // InsertTailList (&Question->OptionListHead, &OneOfOption->Link); } else { // // Insert to head // InsertHeadList (&Question->OptionListHead, &OneOfOption->Link); PopUpMenuLines++; } } // // Get the number of one of options present and its size // PopUpWidth = 0; HighlightOptionIndex = 0; Link = GetFirstNode (&Question->OptionListHead); for (Index = 0; Index < PopUpMenuLines; Index++) { OneOfOption = QUESTION_OPTION_FROM_LINK (Link); StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle); if (EfiStrLen (StringPtr) > PopUpWidth) { PopUpWidth = EfiStrLen (StringPtr); } gBS->FreePool (StringPtr); if (!OrderedList && CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, NULL) == 0) { // // Find current selected Option for OneOf // HighlightOptionIndex = Index; } Link = GetNextNode (&Question->OptionListHead, Link); } // // Perform popup menu initialization. // PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT; SavedAttribute = gST->ConOut->Mode->Attribute; gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) { PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH; } Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn; End = Start + PopUpWidth + POPUP_FRAME_WIDTH; Top = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT; Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - 1; MenuLinesInView = Bottom - Top - 1; if (MenuLinesInView >= PopUpMenuLines) { Top = Top + (MenuLinesInView - PopUpMenuLines) / 2; Bottom = Top + PopUpMenuLines + 1; } else { ShowDownArrow = TRUE; } if (HighlightOptionIndex > (MenuLinesInView - 1)) { TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1; } else { TopOptionIndex = 0; } do { // // Clear that portion of the screen // ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND); // // Draw "One of" pop-up menu // Character = BOXDRAW_DOWN_RIGHT; PrintCharAt (Start, Top, Character); for (Index = Start; Index + 2 < End; Index++) { if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) { Character = GEOMETRICSHAPE_UP_TRIANGLE; } else { Character = BOXDRAW_HORIZONTAL; } PrintChar (Character); } Character = BOXDRAW_DOWN_LEFT; PrintChar (Character); Character = BOXDRAW_VERTICAL; for (Index = Top + 1; Index < Bottom; Index++) { PrintCharAt (Start, Index, Character); PrintCharAt (End - 1, Index, Character); } // // Move to top Option // Link = GetFirstNode (&Question->OptionListHead); for (Index = 0; Index < TopOptionIndex; Index++) { Link = GetNextNode (&Question->OptionListHead, Link); } // // Display the One of options // Index2 = Top + 1; for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) { OneOfOption = QUESTION_OPTION_FROM_LINK (Link); Link = GetNextNode (&Question->OptionListHead, Link); StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle); // // If the string occupies multiple lines, truncate it to fit in one line, // and append a "..." for indication. // if (EfiStrLen (StringPtr) > (PopUpWidth - 1)) { TempStringPtr = EfiLibAllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1)); ASSERT ( TempStringPtr != NULL ); EfiCopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5))); gBS->FreePool (StringPtr); StringPtr = TempStringPtr; EfiStrCat (StringPtr, L"..."); } if (Index == HighlightOptionIndex) { // // Highlight the selected one // CurrentOption = OneOfOption; gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND); PrintStringAt (Start + 2, Index2, StringPtr); gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); } else { gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); PrintStringAt (Start + 2, Index2, StringPtr); } Index2++; gBS->FreePool (StringPtr); } Character = BOXDRAW_UP_RIGHT; PrintCharAt (Start, Bottom, Character); for (Index = Start; Index + 2 < End; Index++) { if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) { Character = GEOMETRICSHAPE_DOWN_TRIANGLE; } else { Character = BOXDRAW_HORIZONTAL; } PrintChar (Character); } Character = BOXDRAW_UP_LEFT; PrintChar (Character); // // Get User selection // Key.UnicodeChar = CHAR_NULL; if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) { Key.ScanCode = gDirection; gDirection = 0; goto TheKey; } Status = WaitForKeyStroke (&Key); TheKey: switch (Key.UnicodeChar) { case '+': if (OrderedList) { if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) { // // Highlight reaches the top of the popup window, scroll one menu item. // TopOptionIndex--; ShowDownArrow = TRUE; } if (TopOptionIndex == 0) { ShowUpArrow = FALSE; } if (HighlightOptionIndex > 0) { HighlightOptionIndex--; SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link); } } break; case '-': // // If an ordered list op-code, we will allow for a popup of +/- keys // to create an ordered list of items // if (OrderedList) { if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) && (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) { // // Highlight reaches the bottom of the popup window, scroll one menu item. // TopOptionIndex++; ShowUpArrow = TRUE; } if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) { ShowDownArrow = FALSE; } if (HighlightOptionIndex < (PopUpMenuLines - 1)) { HighlightOptionIndex++; SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink); } } break; case CHAR_NULL: switch (Key.ScanCode) { case SCAN_UP: case SCAN_DOWN: if (Key.ScanCode == SCAN_UP) { if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) { // // Highlight reaches the top of the popup window, scroll one menu item. // TopOptionIndex--; ShowDownArrow = TRUE; } if (TopOptionIndex == 0) { ShowUpArrow = FALSE; } if (HighlightOptionIndex > 0) { HighlightOptionIndex--; } } else { if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) && (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) { // // Highlight reaches the bottom of the popup window, scroll one menu item. // TopOptionIndex++; ShowUpArrow = TRUE; } if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) { ShowDownArrow = FALSE; } if (HighlightOptionIndex < (PopUpMenuLines - 1)) { HighlightOptionIndex++; } } break; case SCAN_ESC: gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); // // Restore link list order for orderedlist // if (OrderedList) { HiiValue.Type = ValueType; HiiValue.Value.u64 = 0; for (Index = 0; Index < Question->MaxContainers; Index++) { HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index); if (HiiValue.Value.u64 == 0) { break; } OneOfOption = ValueToOption (Question, &HiiValue); if (OneOfOption == NULL) { return EFI_NOT_FOUND; } RemoveEntryList (&OneOfOption->Link); InsertTailList (&Question->OptionListHead, &OneOfOption->Link); } } gBS->FreePool (HiiValueArray); return EFI_DEVICE_ERROR; default: break; } break; case CHAR_CARRIAGE_RETURN: // // return the current selection // if (OrderedList) { Index = 0; Link = GetFirstNode (&Question->OptionListHead); while (!IsNull (&Question->OptionListHead, Link)) { OneOfOption = QUESTION_OPTION_FROM_LINK (Link); SetArrayData (ValueArray, ValueType, Index, OneOfOption->Value.Value.u64); Index++; if (Index > Question->MaxContainers) { break; } Link = GetNextNode (&Question->OptionListHead, Link); } } else { EfiCopyMem (&Question->HiiValue, &CurrentOption->Value, sizeof (EFI_HII_VALUE)); } gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); gBS->FreePool (HiiValueArray); Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF); if (EFI_ERROR (Status)) { // // Input value is not valid, restore Question Value // GetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE); } else { SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE); UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); } return Status; default: break; } } while (TRUE); // // Code will not reach here // return EFI_SUCCESS; }
EFI_STATUS ReadString ( IN UI_MENU_OPTION *MenuOption, IN CHAR16 *Prompt, OUT CHAR16 *StringPtr ) /*++ Routine Description: Get string or password input from user. Arguments: MenuOption - Pointer to the current input menu. Prompt - The prompt string shown on popup window. StringPtr - Destination for use input string. Returns: EFI_SUCCESS - If string input is read successfully EFI_DEVICE_ERROR - If operation fails --*/ { EFI_STATUS Status; EFI_INPUT_KEY Key; CHAR16 NullCharacter; UINTN ScreenSize; CHAR16 Space[2]; CHAR16 KeyPad[2]; CHAR16 *TempString; CHAR16 *BufferedString; UINTN Index; UINTN Count; UINTN Start; UINTN Top; UINTN DimensionsWidth; UINTN DimensionsHeight; BOOLEAN CursorVisible; UINTN Minimum; UINTN Maximum; FORM_BROWSER_STATEMENT *Question; BOOLEAN IsPassword; DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; NullCharacter = CHAR_NULL; ScreenSize = GetStringWidth (Prompt) / sizeof (CHAR16); Space[0] = L' '; Space[1] = CHAR_NULL; Question = MenuOption->ThisTag; Minimum = (UINTN) Question->Minimum; Maximum = (UINTN) Question->Maximum; if (Question->Operand == EFI_IFR_PASSWORD_OP) { IsPassword = TRUE; } else { IsPassword = FALSE; } TempString = EfiLibAllocateZeroPool ((Maximum + 1)* sizeof (CHAR16)); ASSERT (TempString); if (ScreenSize < (Maximum + 1)) { ScreenSize = Maximum + 1; } if ((ScreenSize + 2) > DimensionsWidth) { ScreenSize = DimensionsWidth - 2; } BufferedString = EfiLibAllocateZeroPool (ScreenSize * 2); ASSERT (BufferedString); Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1; Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1; // // Display prompt for string // CreatePopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter); gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY)); CursorVisible = gST->ConOut->Mode->CursorVisible; gST->ConOut->EnableCursor (gST->ConOut, TRUE); do { Status = WaitForKeyStroke (&Key); gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY)); switch (Key.UnicodeChar) { case CHAR_NULL: switch (Key.ScanCode) { case SCAN_LEFT: break; case SCAN_RIGHT: break; case SCAN_ESC: gBS->FreePool (TempString); gBS->FreePool (BufferedString); gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); return EFI_DEVICE_ERROR; default: break; } break; case CHAR_CARRIAGE_RETURN: if (GetStringWidth (StringPtr) >= ((Minimum + 1) * sizeof (CHAR16))) { gBS->FreePool (TempString); gBS->FreePool (BufferedString); gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); return EFI_SUCCESS; } else { // // Simply create a popup to tell the user that they had typed in too few characters. // To save code space, we can then treat this as an error and return back to the menu. // do { CreateDialog (4, TRUE, 0, NULL, &Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter); } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); gBS->FreePool (TempString); gBS->FreePool (BufferedString); gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); return EFI_DEVICE_ERROR; } break; case CHAR_BACKSPACE: if (StringPtr[0] != CHAR_NULL) { for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) { TempString[Index] = StringPtr[Index]; } // // Effectively truncate string by 1 character // TempString[Index - 1] = CHAR_NULL; EfiStrCpy (StringPtr, TempString); } default: // // If it is the beginning of the string, don't worry about checking maximum limits // if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) { StrnCpy (StringPtr, &Key.UnicodeChar, 1); StrnCpy (TempString, &Key.UnicodeChar, 1); } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) { KeyPad[0] = Key.UnicodeChar; KeyPad[1] = CHAR_NULL; EfiStrCat (StringPtr, KeyPad); EfiStrCat (TempString, KeyPad); } // // If the width of the input string is now larger than the screen, we nee to // adjust the index to start printing portions of the string // SetUnicodeMem (BufferedString, ScreenSize - 1, L' '); PrintStringAt (Start + 1, Top + 3, BufferedString); if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) { Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2; } else { Index = 0; } if (IsPassword) { gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3); } for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) { BufferedString[Count] = StringPtr[Index]; if (IsPassword) { PrintChar (L'*'); } } if (!IsPassword) { PrintStringAt (Start + 1, Top + 3, BufferedString); } break; } gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3); } while (TRUE); gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); return Status; }
EFI_STATUS MultiAltRespToMultiResp ( IN EFI_STRING Resp1, IN OUT EFI_STRING Resp2 ) { EFI_STRING Pointer1 = Resp1; EFI_STRING Pointer2 = NULL; EFI_STRING Pointer3 = Resp2; EFI_STRING CfgHdr = NULL; EFI_STRING FreePtr = NULL; CHAR8 Flag = 0; if (EfiStrnCmp (Pointer1, L"GUID=", 5) != 0) { return EFI_INVALID_PARAMETER; } Pointer2 = (EFI_STRING) AllocateZeroPool (2 * StrLen(Resp1) + 2); if (Pointer2 == NULL) { return EFI_OUT_OF_RESOURCES; } FreePtr = Pointer2; while (*Pointer1) { if (EfiStrnCmp (Pointer1, L"GUID=", 5) == 0) { CfgHdr = Pointer2; *(Pointer2++) = *(Pointer1++); while (*Pointer1 != L'&') { *(Pointer2++) = *(Pointer1++); } } if (EfiStrnCmp (Pointer1, L"&GUID=", 6) == 0) { *(Pointer2++) = *(Pointer1++); CfgHdr = Pointer2; while (*Pointer1 != L'&') { *(Pointer2++) = *(Pointer1++); } } if (EfiStrnCmp (Pointer1, L"&NAME=", 6) == 0) { *(Pointer2++) = *(Pointer1++); while (*Pointer1 != L'&') { *(Pointer2++) = *(Pointer1++); } } if (EfiStrnCmp (Pointer1, L"&PATH=", 6) == 0) { *(Pointer2++) = *(Pointer1++); while (*Pointer1 != L'&') { *(Pointer2++) = *(Pointer1++); } if (NULL == EfiStrStr(Resp2, CfgHdr)){ if (*Resp2 == L'G') *(Pointer3++) = L'&'; EfiStrCat(Resp2, CfgHdr); Pointer3 += StrLen(CfgHdr); Flag = 1; } else { Flag = 0; } } while ((Flag == 1) && (EfiStrnCmp (Pointer1, L"&GUID=", 6) != 0) && *Pointer1) { if (EfiStrnCmp (Pointer1, L"&OFFSET=", 8) == 0) { *(Pointer3++) = *(Pointer1++); while (*Pointer1 != L'&') { *(Pointer3++) = *(Pointer1++); } } if (EfiStrnCmp (Pointer1, L"&WIDTH=", 7) == 0) { *(Pointer3++) = *(Pointer1++); while (*Pointer1 != L'&') { *(Pointer3++) = *(Pointer1++); } } if (EfiStrnCmp (Pointer1, L"&VALUE=", 7) == 0) { *(Pointer3++) = *(Pointer1++); while (*Pointer1 != L'&' && *Pointer1) { *(Pointer3++) = *(Pointer1++); } } if (EfiStrnCmp (Pointer1, L"&ALTCFG=", 8) == 0) { Pointer1 += 8; while (*Pointer1 != L'&' && *Pointer1) { Pointer1++; } } if ((*Pointer1 == L'&') && (EfiStrnCmp (Pointer1, L"&GUID=", 6) != 0)) { *(Pointer3++) = *(Pointer1++); while (*Pointer1 != L'=') { *(Pointer3++) = *(Pointer1++); } while (*Pointer1 != L'&' && *Pointer1) { *(Pointer3++) = *(Pointer1++); } } } Pointer1++; } FreePool(FreePtr); return EFI_SUCCESS; }
CHAR16 * BOpt_AppendFileName ( IN CHAR16 *Str1, IN CHAR16 *Str2 ) /*++ Routine Description Append file name to existing file name. Arguments: Str1 - existing file name Str2 - file name to be appended Returns: Allocate a new string to hold the appended result. Caller is responsible to free the returned string. --*/ { UINTN Size1; UINTN Size2; CHAR16 *Str; CHAR16 *Ptr; CHAR16 *LastSlash; Size1 = EfiStrSize (Str1); Size2 = EfiStrSize (Str2); Str = EfiAllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); ASSERT (Str != NULL); EfiStrCat (Str, Str1); if (!((*Str == '\\') && (*(Str + 1) == 0))) { EfiStrCat (Str, L"\\"); } EfiStrCat (Str, Str2); Ptr = Str; LastSlash = Str; while (*Ptr != 0) { if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) != 0) { // // Convert \Name\..\ to \ // DO NOT convert the .. if it is at the end of the string. This will // break the .. behavior in changing directories. // EfiStrCpy (LastSlash, Ptr + 3); Ptr = LastSlash; } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') { // // Convert a \.\ to a \ // EfiStrCpy (Ptr, Ptr + 2); Ptr = LastSlash; } else if (*Ptr == '\\') { LastSlash = Ptr; } Ptr++; } return Str; }
EFI_STATUS EFIAPI SetOptionsCallback ( IN EFI_FORM_CALLBACK_PROTOCOL *This, IN UINT16 KeyValue, IN EFI_IFR_DATA_ARRAY *Data, OUT EFI_HII_CALLBACK_PACKET **Packet ) /*++ Routine Description: This is the function that is called to provide results data to the driver. This data consists of a unique key which is used to identify what data is either being passed back or being asked for. The callback function finish two main task: 1. Invoke the configuration protocol setoptions function according to user selection which is recorded by KeyValue. 2. Collect all the available driver and controller infos to update the formset. Arguments: KeyValue - A unique Goto OpCode callback value which record user's selection, In Set Options page, every item is associated to a goto IFR, and has a unique callback key. Data - No use here. Packet- No use here. Returns - Always successful --*/ { EFI_CALLBACK_INFO *Private; EFI_HII_UPDATE_DATA *UpdateData; EFI_STATUS Status; CHAR8 Language[4]; CHAR16 Lang[4]; UINTN LangSize; UINTN Index; UINTN ChoiceIndex; UINT8 *Location; UINTN DriverImageHandleCount; EFI_HANDLE *DriverImageHandleBuffer; EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration; EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; #if (EFI_SPECIFICATION_VERSION >= 0x00020000) EFI_COMPONENT_NAME_PROTOCOL *ComponentName; #else EFI_COMPONENT_NAME2_PROTOCOL *ComponentName; #endif EFI_FORM_BROWSER_PROTOCOL *FormBrowser; EFI_DEVICE_PATH_PROTOCOL *DevicePath; UINTN ControllerHandleIndex; CHAR16 *ControllerHandleName; BOOLEAN FreeControllerHandleName; UINTN ControllerHandleCount; EFI_HANDLE *ControllerHandleBuffer; UINTN ChildControllerHandleIndex; CHAR16 *ChildControllerHandleName; BOOLEAN FreeChildControllerHandleName; UINTN ChildControllerHandleCount; EFI_HANDLE *ChildControllerHandleBuffer; CHAR16 *NewString; STRING_REF NewStringToken; CHAR16 *DriverName; BOOLEAN FreeDriverName; EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED ActionRequired; Private = EFI_CALLBACK_INFO_FROM_THIS (This); // // Get current language to set options // LangSize = 0x3; Status = gRT->GetVariable ( L"Lang", &gEfiGlobalVariableGuid, NULL, &LangSize, Language ); ASSERT_EFI_ERROR (Status); Status = GetCurrentLanguage (Lang); ASSERT_EFI_ERROR (Status); // // Tast1: Invoke the configuration protocol setoptions function according to user selection. // KeyValue between 0x100~0x200 means user select a driver or device item in 'Set Options' dynamic page // if ((0x100 <= KeyValue) && (KeyValue <= 0x200)) { ChoiceIndex = KeyValue - 0x100; ActionRequired = 0; // // There should only be one Form Configuration protocol // Status = gBS->LocateProtocol ( &gEfiFormBrowserProtocolGuid, NULL, &FormBrowser ); ASSERT_EFI_ERROR (Status); // // Invoke the user selceted item's SetOptions function with corresponding driver or device handles // gST->ConOut->ClearScreen (gST->ConOut); mChoice[ChoiceIndex].DriverConfiguration->SetOptions ( mChoice[ChoiceIndex].DriverConfiguration, mChoice[ChoiceIndex].ControllerHandle, mChoice[ChoiceIndex].ChildControllerHandle, Language, &ActionRequired ); gST->ConOut->ClearScreen (gST->ConOut); // // Notify user the action required after SetOptions function finish, and do the action according to user intent // Status = ProcessActionRequired ( FormBrowser, Private, ActionRequired, mChoice[ChoiceIndex].DriverImageHandle, mChoice[ChoiceIndex].ControllerHandle, mChoice[ChoiceIndex].ChildControllerHandle ); gST->ConOut->ClearScreen (gST->ConOut); } // // Task 2: Collect all the available driver infos and update the formset. // The available driver is those drivers which install efi driver configuration protocol // // // Allocate memory to Update form // DriverImageHandleBuffer = NULL; ControllerHandleBuffer = NULL; ChildControllerHandleBuffer = NULL; UpdateData = NULL; UpdateData = EfiLibAllocateZeroPool (UPDATE_DATA_SIZE); ASSERT (UpdateData != NULL); // // Clear all the content in dynamic page // UpdateData->FormSetUpdate = FALSE; UpdateData->FormCallbackHandle = 0; UpdateData->FormUpdate = FALSE; UpdateData->FormTitle = 0; UpdateData->DataCount = 0xff; UpdateData->Data = NULL; Private->Hii->UpdateForm ( Private->Hii, Private->RegisteredHandle, (EFI_FORM_LABEL) 0x1234, // Label 0x1234 FALSE, // Remove Op-codes (will never remove form/endform) UpdateData // Significant value is UpdateData->DataCount ); // // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers, // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement // NewStringToken = (STRING_REF) STR_FIRST_REFRESH; NewString = GetString (Private, (STRING_REF) STR_REFRESH); ASSERT (NewString != NULL); Status = Private->Hii->NewString (Private->Hii, Lang, Private->RegisteredHandle, &NewStringToken, NewString); ASSERT_EFI_ERROR (Status); gBS->FreePool (NewString); NewStringToken = (STRING_REF) STR_FIRST_REFRESH_HELP; NewString = GetString (Private, (STRING_REF) STR_REFRESH_HELP); ASSERT (NewString != NULL); Status = Private->Hii->NewString (Private->Hii, Lang, Private->RegisteredHandle, &NewStringToken, NewString); ASSERT_EFI_ERROR (Status); gBS->FreePool (NewString); // // Get all drivers handles which has configuration protocol // DriverImageHandleCount = 0; Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiDriverConfigurationProtocolGuid, NULL, &DriverImageHandleCount, &DriverImageHandleBuffer ); // // Scan every driver image handle to get its and its managed device and child device info, // including Component name/image name/device handle and so on. Create and associate a item // in Set Option page to very driver and its managed device and child device // ChoiceIndex = 0; // Item index in Set Option page for (Index = 0; (Index < DriverImageHandleCount) && (ChoiceIndex < MAX_CHOICE_NUM); Index++) { // // step1 : get the driver info // DriverConfiguration = NULL; Status = gBS->OpenProtocol ( DriverImageHandleBuffer[Index], &gEfiDriverConfigurationProtocolGuid, (VOID **) &DriverConfiguration, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); ASSERT_EFI_ERROR (Status); DriverBinding =NULL; Status = gBS->OpenProtocol ( DriverImageHandleBuffer[Index], &gEfiDriverBindingProtocolGuid, (VOID **) &DriverBinding, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { continue; } LoadedImage = NULL; Status = gBS->OpenProtocol ( DriverBinding->ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { LoadedImage = NULL; } ComponentName = NULL; Status = gBS->OpenProtocol ( DriverBinding->ImageHandle, #if (EFI_SPECIFICATION_VERSION >= 0x00020000) &gEfiComponentName2ProtocolGuid, #else &gEfiComponentNameProtocolGuid, #endif (VOID **) &ComponentName, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR(Status)) { return EFI_UNSUPPORTED; } // // Get the driver name // First try to get its component name, if fail, get its image name then // Status = EFI_UNSUPPORTED; DriverName = NULL; FreeDriverName = FALSE; if ((ComponentName != NULL) && (ComponentName->GetDriverName != NULL)) { Status = ComponentName->GetDriverName ( ComponentName, Language, &DriverName ); } if (EFI_ERROR (Status) && (LoadedImage != NULL)) { DriverName = GetImageName (LoadedImage); } if (DriverName == NULL) { DriverName = GetString (Private, (STRING_REF) STR_DRIVER_DEFAULT_NAME); ASSERT (DriverName != NULL); FreeDriverName = TRUE; // the DriverName string need to free pool } // // Create a item for the driver in set options page // Clear the Update buffer // UpdateData->FormSetUpdate = FALSE; UpdateData->FormCallbackHandle = 0; UpdateData->FormUpdate = FALSE; UpdateData->FormTitle = 0; UpdateData->DataCount = 0; Location = (UINT8 *) &UpdateData->Data; // // Export the driver name string and create item in set options page // NewString = EfiLibAllocateZeroPool (EfiStrSize (DriverName) + EfiStrSize (L" |-")); EfiStrCat (NewString, L" |-"); EfiStrCat (NewString, DriverName); NewStringToken = mChoice[ChoiceIndex].DescriptionToken; Status = Private->Hii->NewString (Private->Hii, NULL, Private->RegisteredHandle, &NewStringToken, NewString); ASSERT_EFI_ERROR (Status); gBS->FreePool (NewString); if (FreeDriverName) { gBS->FreePool (DriverName); } CreateGotoOpCode ( 0x1234, NewStringToken, // Description String Token STR_GOTO_HELP_DRIVER, // Description Help String Token EFI_IFR_FLAG_INTERACTIVE, // Flag designating callback is active (UINT16) ChoiceIndex + 0x100, // Callback key value Location // Buffer to fill with op-code ); // // Update the buffer items number and adjust next item address to new one // UpdateData->DataCount +=1 ; Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; // // Associate callback key with setoptions function related parameters to used by Task 1 // mChoice[ChoiceIndex].DriverImageHandle = DriverImageHandleBuffer[Index]; mChoice[ChoiceIndex].DriverConfiguration = DriverConfiguration; mChoice[ChoiceIndex].ControllerHandle = NULL; mChoice[ChoiceIndex].ChildControllerHandle = NULL; mChoice[ChoiceIndex].DescriptionToken = NewStringToken; ChoiceIndex++; // // step2 : get the driver direct managed device info // // // Get the driver all direct managed devices handles // Status = GetDeviceHandlesManagedByDriver ( DriverImageHandleBuffer[Index], &ControllerHandleCount, // Get managed devices count &ControllerHandleBuffer // return all handles in buffer ); if (ControllerHandleBuffer == NULL) { continue; } for (ControllerHandleIndex = 0; ControllerHandleIndex < ControllerHandleCount; ControllerHandleIndex++) { // // Get the managed device name // First try to get its component name, if fail, get its device path then // The component name string need not free pool, but the device path string and default string need safe free pool after export the string to Hii database // FreeControllerHandleName = FALSE; ControllerHandleName = NULL; Status = EFI_UNSUPPORTED; if ((ComponentName != NULL) && (ComponentName->GetControllerName != NULL)) { Status = ComponentName->GetControllerName ( ComponentName, ControllerHandleBuffer[ControllerHandleIndex], NULL, Language, &ControllerHandleName ); } if (EFI_ERROR (Status)) { Status = gBS->OpenProtocol ( ControllerHandleBuffer[ControllerHandleIndex], &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { ControllerHandleName = DevicePathToStr ( DevicePath ); FreeControllerHandleName = TRUE; // the Controller Handle Name string need to free pool } } if (ControllerHandleName == NULL) { ControllerHandleName = GetString (Private, (STRING_REF) STR_DRIVER_CONTROLLER_DEFAULT_NAME); ASSERT (ControllerHandleName != NULL); FreeControllerHandleName = TRUE; // the Controller Handle Name string need to free pool } // // do some alignment for NewString if needed // AlignmentItem (ControllerHandleName, L" |-", &NewString); NewStringToken = mChoice[ChoiceIndex].DescriptionToken; Private->Hii->NewString ( Private->Hii, NULL, Private->RegisteredHandle, &NewStringToken, NewString ); gBS->FreePool (NewString); if (FreeControllerHandleName) { gBS->FreePool (ControllerHandleName); } CreateGotoOpCode ( 0x1234, NewStringToken, // Description String Token STR_GOTO_HELP_DEVICE, // Description Help String Token EFI_IFR_FLAG_INTERACTIVE, // Flag designating callback is active (UINT16) ChoiceIndex + 0x100, // Callback key value Location // Buffer to fill with op-code ); // // Update the buffer items number and adjust next item address to new one // UpdateData->DataCount +=1 ; Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; // // Associate callback key with setoptions function related parameters to used by Task 1 // mChoice[ChoiceIndex].DriverImageHandle = DriverImageHandleBuffer[Index]; mChoice[ChoiceIndex].DriverConfiguration = DriverConfiguration; mChoice[ChoiceIndex].ControllerHandle = ControllerHandleBuffer[ControllerHandleIndex]; mChoice[ChoiceIndex].ChildControllerHandle = NULL; mChoice[ChoiceIndex].DescriptionToken = NewStringToken; ChoiceIndex++; // // step3 : get the infos of child devices created by the driver // Status = GetChildDeviceHandlesManagedByDriver ( DriverImageHandleBuffer[Index], ControllerHandleBuffer[ControllerHandleIndex], &ChildControllerHandleCount, // Get managed devices count &ChildControllerHandleBuffer // return all handles in buffer ); for (ChildControllerHandleIndex = 0; ChildControllerHandleIndex < ChildControllerHandleCount; ChildControllerHandleIndex++) { // // Get the managed child device name // First try to get its component name, if fail, get its device path then // The component name string need not free pool, but the device path string need safe free pool after export the string to Hii database // FreeChildControllerHandleName = FALSE; ChildControllerHandleName = NULL; Status = EFI_UNSUPPORTED; if ((ComponentName != NULL) && (ComponentName->GetDriverName != NULL)) { Status = ComponentName->GetControllerName ( ComponentName, ControllerHandleBuffer[ControllerHandleIndex], ChildControllerHandleBuffer[ChildControllerHandleIndex], Language, &ChildControllerHandleName ); } if (EFI_ERROR (Status)) { Status = gBS->OpenProtocol ( ChildControllerHandleBuffer[ChildControllerHandleIndex], &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { ChildControllerHandleName = DevicePathToStr ( DevicePath ); FreeChildControllerHandleName = TRUE; // the Child Controller Handle Name string need to free pool } } if (ChildControllerHandleName == NULL) { ChildControllerHandleName = GetString (Private, (STRING_REF) STR_DRIVER_CHILD_CONTROLLER_DEFAULT_NAME); ASSERT (ChildControllerHandleName != NULL); FreeChildControllerHandleName = TRUE; // the Controller Handle Name string need to free pool } // // do some alignment for NewString if needed // AlignmentItem (ChildControllerHandleName, L" |--", &NewString); NewStringToken = mChoice[ChoiceIndex].DescriptionToken; Private->Hii->NewString ( Private->Hii, NULL, Private->RegisteredHandle, &NewStringToken, NewString ); gBS->FreePool (NewString); if (FreeChildControllerHandleName) { gBS->FreePool (ChildControllerHandleName); } CreateGotoOpCode ( 0x1234, NewStringToken, // Description String Token STR_GOTO_HELP_CHILD_DEVICE, // Description Help String Token EFI_IFR_FLAG_INTERACTIVE, // Flag designating callback is active (UINT16) ChoiceIndex + 0x100, // Callback key value Location // Buffer to fill with op-code ); // // Update the buffer items number and adjust next item address to new one // UpdateData->DataCount +=1 ; Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; // // Associate callback key with setoptions function related parameters to used by Task 1 // mChoice[ChoiceIndex].DriverImageHandle = DriverImageHandleBuffer[Index]; mChoice[ChoiceIndex].DriverConfiguration = DriverConfiguration; mChoice[ChoiceIndex].ControllerHandle = ControllerHandleBuffer[ControllerHandleIndex]; mChoice[ChoiceIndex].ChildControllerHandle = ChildControllerHandleBuffer[ChildControllerHandleIndex]; mChoice[ChoiceIndex].DescriptionToken = NewStringToken; ChoiceIndex++; } if (ChildControllerHandleBuffer != NULL) { gBS->FreePool (ChildControllerHandleBuffer); } } // // Update Set Option page form // Private->Hii->UpdateForm ( Private->Hii, Private->RegisteredHandle, (EFI_FORM_LABEL) 0x1234, TRUE, UpdateData ); if (ControllerHandleBuffer != NULL) { gBS->FreePool (ControllerHandleBuffer); } } gBS->FreePool (UpdateData); if (DriverImageHandleBuffer != NULL) { gBS->FreePool (DriverImageHandleBuffer); } return EFI_SUCCESS; }
EFI_STATUS EFIAPI StslRecordAssertion ( IN EFI_STANDARD_TEST_LIBRARY_PROTOCOL *This, IN EFI_TEST_ASSERTION Type, IN EFI_GUID EventId, IN CHAR16 *Description, IN CHAR16 *Detail, ... ) /*++ Routine Description: Records the test result. Arguments: This - Standard test library protocol instance. Type - Test result. EventId - GUID for the checkpoint. Description - Simple description for the checkpoint. Detail - Format string for the detail test information. Returns: EFI_SUCCESS - record the assertion successfully. EFI_BAD_BUFFER_SIZE - the Description string is too long. EFI_INVALID_PARAMETER - invalid Type. --*/ { EFI_STATUS Status; VA_LIST Marker; CHAR16 Buffer[EFI_MAX_PRINT_BUFFER]; CHAR16 AssertionType[10]; STANDARD_TEST_PRIVATE_DATA *Private; Private = STANDARD_TEST_PRIVATE_DATA_FROM_STSL (This); // // Check the parameter // if (EfiStrLen (Description) + 14 > EFI_MAX_PRINT_BUFFER) { return EFI_BAD_BUFFER_SIZE; } // // Write log file detail data // switch (Type) { case EFI_TEST_ASSERTION_PASSED: EfiStrCpy (AssertionType, L"PASS"); Private->PassCount ++; break; case EFI_TEST_ASSERTION_WARNING: EfiStrCpy (AssertionType, L"WARNING"); Private->WarningCount ++; break; case EFI_TEST_ASSERTION_FAILED: EfiStrCpy (AssertionType, L"FAILURE"); Private->FailCount ++; break; default: return EFI_INVALID_PARAMETER; break; } SPrint (Buffer, EFI_MAX_PRINT_BUFFER, L"%s -- %s\n", Description, AssertionType); Status = StslWriteLogFile (Private, Buffer); if (EFI_ERROR (Status)) { return Status; } SPrint (Buffer, EFI_MAX_PRINT_BUFFER, L"%g\n", &EventId); Status = StslWriteLogFile (Private, Buffer); if (EFI_ERROR (Status)) { return Status; } VA_START(Marker, Detail); VSPrint (Buffer, EFI_MAX_PRINT_BUFFER, Detail, Marker); VA_END (Marker); if ( EfiStrLen (Buffer) + 5 < EFI_MAX_PRINT_BUFFER ) { EfiStrCat (Buffer, L"\r\n\r\n"); } Status = StslWriteLogFile (Private, Buffer); if (EFI_ERROR (Status)) { return Status; } // // write key file detail line // SPrint (Buffer, EFI_MAX_PRINT_BUFFER, L"%g:%s|%s:", &EventId, AssertionType, Description); Status = StslWriteKeyFile (Private, Buffer); if (EFI_ERROR (Status)) { return Status; } VA_START(Marker, Detail); VSPrint (Buffer, EFI_MAX_PRINT_BUFFER, Detail, Marker); VA_END (Marker); if ( EfiStrLen (Buffer) + 3 < EFI_MAX_PRINT_BUFFER ) { EfiStrCat (Buffer, L"\r\n"); } Status = StslWriteKeyFile (Private, Buffer); if (EFI_ERROR (Status)) { return Status; } return Status; }
EFI_STATUS EFIAPI UpdateBindingDriverSelectPage ( IN EFI_CALLBACK_INFO *Private, IN UINT16 KeyValue, IN EFI_IFR_DATA_ARRAY *Data ) /*++ Routine Description: Prepare to let user select the drivers which need mapping with the device controller selected in first page Arguments: KeyValue - The callback key value of device controller item in first page Data - EFI_IFR_DATA_ARRAY data. Packet- No use here. Returns - Always successful --*/ { EFI_HII_UPDATE_DATA *UpdateData; EFI_STATUS Status; UINTN Index; UINT8 *Location; CHAR16 *NewString; STRING_REF NewStringToken; STRING_REF NewStringHelpToken; UINTN DriverImageHandleCount; EFI_DRIVER_BINDING_PROTOCOL *DriverBindingInterface; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; CHAR16 *DriverName; BOOLEAN FreeDriverName; EFI_DEVICE_PATH_PROTOCOL *LoadedImageHandleDevicePath; EFI_DEVICE_PATH_PROTOCOL *TatalFilePath; EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride; EFI_HANDLE DriverBindingHandle; // // If user select a controller item in the first page the following code will be run. // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown // //First acquire the list of Loaded Image Protocols, and then when want the name of the driver, look up all the Driver Binding Protocols // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol. // then use the Component Name Protocol on the same handle as the first matching Driver Binding Protocol to look up the name of the driver. // mCurrentPage = 0x02; // // Switch the item callback key value to its NO. in mDevicePathHandleBuffer // mSelectedCtrIndex = KeyValue - 0x100; ASSERT (0 <= mSelectedCtrIndex < MAX_CHOICE_NUM); mLastSavedDriverImageNum = 0; // // Clear all the content in dynamic page // UpdateData = NULL; UpdateData = EfiLibAllocateZeroPool (UPDATE_DATA_SIZE); ASSERT (UpdateData != NULL); UpdateData->FormSetUpdate = FALSE; UpdateData->FormCallbackHandle = 0; UpdateData->FormUpdate = FALSE; UpdateData->FormTitle = 0; UpdateData->DataCount = 0xff; UpdateData->Data = NULL; Private->Hii->UpdateForm ( Private->Hii, Private->RegisteredHandle, (EFI_FORM_LABEL) 0x1200, // Label 0x1234 FALSE, // Remove Op-codes (will never remove form/endform) UpdateData // Significant value is UpdateData->DataCount ); // // Show all driver which support loaded image protocol in second page // DriverImageHandleCount = 0; Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiLoadedImageProtocolGuid, NULL, &DriverImageHandleCount, &mDriverImageHandleBuffer ); if (EFI_ERROR (Status) || (DriverImageHandleCount == 0)) { return EFI_NOT_FOUND; } mDriverImageHandleCount = DriverImageHandleCount; for (Index = 0; Index < DriverImageHandleCount; Index++) { // // Step1: Get the driver image total file path for help string and the driver name. // // // Find driver's Loaded Image protocol // LoadedImage =NULL; Status = gBS->OpenProtocol ( mDriverImageHandleBuffer[Index], &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { ((MyIfrNVData *) Data->NvRamMap)->DriSelection[Index] = 0; continue; } mDriverImageProtocol[Index] = LoadedImage; // // Find its related driver binding protocol // DriverBindingInterface = NULL; DriverBindingHandle = NULL; DriverBindingInterface = LibGetBindingProtocolFromImageHandle ( mDriverImageHandleBuffer[Index], &DriverBindingHandle ); if (DriverBindingInterface == NULL) { ((MyIfrNVData *) Data->NvRamMap)->DriSelection[Index] = 0; continue; } // // Get the driver image total file path for help string // LoadedImageHandleDevicePath = NULL; Status = gBS->HandleProtocol ( LoadedImage->DeviceHandle, &gEfiDevicePathProtocolGuid, &LoadedImageHandleDevicePath ); if (EFI_ERROR (Status)) { ((MyIfrNVData *) Data->NvRamMap)->DriSelection[Index] = 0; continue; } if (((MyIfrNVData *) Data->NvRamMap)->PciDeviceFilter == 0x01) { // // only care the driver which is in a Pci device option rom, // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom // if (!EFI_ERROR (Status)) { Status = gBS->HandleProtocol( LoadedImage->DeviceHandle, &gEfiBusSpecificDriverOverrideProtocolGuid, &BusSpecificDriverOverride ); if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) { ((MyIfrNVData *) Data->NvRamMap)->DriSelection[Index] = 0; continue; } } else { ((MyIfrNVData *) Data->NvRamMap)->DriSelection[Index] = 0; continue; } } TatalFilePath = NULL; TatalFilePath = EfiAppendDevicePath (LoadedImageHandleDevicePath, LoadedImage->FilePath); // // For driver name, try to get its component name, if fail, get its image name, // if also fail, give a default name. // FreeDriverName = FALSE; DriverName = GetComponentName (DriverBindingHandle); if (DriverName == NULL) { // // get its image name // DriverName = GetImageName (LoadedImage); } if (DriverName == NULL) { // // give a default name // DriverName = GetString (Private, (STRING_REF) STR_DRIVER_DEFAULT_NAME); ASSERT (DriverName != NULL); FreeDriverName = TRUE; // the DriverName string need to free pool } // // Step2 Export the driver name string and create check box item in second page // // // Clear the Update buffer // UpdateData->FormSetUpdate = FALSE; UpdateData->FormCallbackHandle = 0; UpdateData->FormUpdate = FALSE; UpdateData->FormTitle = 0; UpdateData->DataCount = 0; Location = (UINT8 *) &UpdateData->Data; // // First create the driver image name // NewString = EfiLibAllocateZeroPool (EfiStrSize (DriverName)); if (EFI_ERROR (LibCheckMapping (mControllerDevicePathProtocol[mSelectedCtrIndex], TatalFilePath, &mMappingDataBase, NULL, NULL))) { ((MyIfrNVData *) Data->NvRamMap)->DriSelection[Index] = 0x00; } else { ((MyIfrNVData *) Data->NvRamMap)->DriSelection[Index] = 0x01; mLastSavedDriverImageNum++; } EfiStrCat (NewString, DriverName); NewStringToken = mDriverImageToken[Index]; Status = Private->Hii->NewString (Private->Hii, NULL, Private->RegisteredHandle, &NewStringToken, NewString); mDriverImageToken[Index] = NewStringToken; ASSERT_EFI_ERROR (Status); gBS->FreePool (NewString); if (FreeDriverName) { gBS->FreePool (DriverName); } // // Second create the driver image device path as item help string // if (TatalFilePath == NULL) { DriverName = EfiLibAllocateZeroPool (EfiStrSize (L"This driver device path and file path are both NULL! Maybe it is a Option Rom driver. Can not save it!")); EfiStrCat (DriverName, L"This driver device path and file path are both NULL! Maybe it is a Option Rom driver. Can not save it!"); } else { DriverName = DevicePathToStr (TatalFilePath); } NewString = EfiLibAllocateZeroPool (EfiStrSize (DriverName)); EfiStrCat (NewString, DriverName); NewStringHelpToken = mDriverImageFilePathToken[Index]; Status = Private->Hii->NewString (Private->Hii, NULL, Private->RegisteredHandle, &NewStringHelpToken, NewString); mDriverImageFilePathToken[Index] = NewStringHelpToken; ASSERT_EFI_ERROR (Status); gBS->FreePool (NewString); gBS->FreePool (DriverName); CreateCheckBoxOpCode ( (UINT16) (DRIVER_SELECTION_QUESTION_ID + Index), (UINT8) 1, NewStringToken, // Description String Token NewStringHelpToken, // Description Help String Token EFI_IFR_FLAG_INTERACTIVE, // Flag designating callback is active (UINT16) Index + 0x500, // Callback key value Location // Buffer to fill with op-code ); UpdateData->DataCount +=1 ; Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; // // Update second page form // Private->Hii->UpdateForm ( Private->Hii, Private->RegisteredHandle, (EFI_FORM_LABEL) 0x1200, TRUE, UpdateData ); } gBS->FreePool (UpdateData); return EFI_SUCCESS; }
EFI_STATUS EFIAPI UpdateDeviceSelectPage ( IN EFI_CALLBACK_INFO *Private, IN UINT16 KeyValue, IN EFI_IFR_DATA_ARRAY *Data ) /*++ Routine Description: Prepare the first page to let user select the device controller which need to add mapping drivers Arguments: KeyValue - No use here. Data - EFI_IFR_DATA_ARRAY data. Packet- No use here. Returns - Always successful --*/ { EFI_HII_UPDATE_DATA *UpdateData; EFI_STATUS Status; UINTN LangSize; UINTN Index; UINT8 *Location; UINTN DevicePathHandleCount; CHAR16 *NewString; STRING_REF NewStringToken; CHAR16 *ControllerName; EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath; EFI_PCI_IO_PROTOCOL *PciIo; EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride; mCurrentPage = 0x01; // // Following code will be run if user select 'Refresh' in first page // During first page, user will see all currnet controller device path in system, // select any device path will go to second page to select its overrides drivers // LangSize = 0x3; Status = gRT->GetVariable ( L"Lang", &gEfiGlobalVariableGuid, NULL, &LangSize, mLanguage ); ASSERT_EFI_ERROR (Status); Status = GetCurrentLanguage (mLang); ASSERT_EFI_ERROR (Status); // // Initial the mapping database in memory // LibFreeMappingDatabase (&mMappingDataBase); Status = LibInitOverridesMapping (&mMappingDataBase); // // Clear all the content in the first page // UpdateData = NULL; UpdateData = EfiLibAllocateZeroPool (UPDATE_DATA_SIZE); ASSERT (UpdateData != NULL); UpdateData->FormSetUpdate = FALSE; UpdateData->FormCallbackHandle = 0; UpdateData->FormUpdate = FALSE; UpdateData->FormTitle = 0; UpdateData->DataCount = 0xff; UpdateData->Data = NULL; Private->Hii->UpdateForm ( Private->Hii, Private->RegisteredHandle, (EFI_FORM_LABEL) 0x1234, // Label 0x1234 FALSE, // Remove Op-codes (will never remove form/endform) UpdateData // Significant value is UpdateData->DataCount ); // // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers, // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement // NewStringToken = (STRING_REF) STR_FIRST_REFRESH; NewString = GetString (Private, (STRING_REF) STR_REFRESH); ASSERT (NewString != NULL); Status = Private->Hii->NewString (Private->Hii, mLang, Private->RegisteredHandle, &NewStringToken, NewString); ASSERT_EFI_ERROR (Status); gBS->FreePool (NewString); NewStringToken = (STRING_REF) STR_FIRST_REFRESH_HELP; NewString = GetString (Private, (STRING_REF) STR_REFRESH_HELP); ASSERT (NewString != NULL); Status = Private->Hii->NewString (Private->Hii, mLang, Private->RegisteredHandle, &NewStringToken, NewString); ASSERT_EFI_ERROR (Status); gBS->FreePool (NewString); // // created needed controller device item in first page // DevicePathHandleCount = 0; Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &DevicePathHandleCount, &mDevicePathHandleBuffer ); if (EFI_ERROR (Status) || (DevicePathHandleCount == 0)) { return EFI_SUCCESS; } for (Index = 0; Index < DevicePathHandleCount; Index++) { if (((MyIfrNVData *) Data->NvRamMap)->PciDeviceFilter == 0x01) { // // Only care PCI device which contain efi driver in its option rom. // // // Check whether it is a pci device // ControllerDevicePath = NULL; Status = gBS->OpenProtocol ( mDevicePathHandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { continue; } // // Check whether it contain efi driver in its option rom // Status = gBS->HandleProtocol( mDevicePathHandleBuffer[Index], &gEfiBusSpecificDriverOverrideProtocolGuid, &BusSpecificDriverOverride ); if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) { continue; } } ControllerDevicePath = NULL; Status = gBS->OpenProtocol ( mDevicePathHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &ControllerDevicePath, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); ASSERT_EFI_ERROR (Status); // // Save the device path protocol interface // mControllerDevicePathProtocol[Index] = ControllerDevicePath; // // Get the driver name // ControllerName = DevicePathToStr (ControllerDevicePath); // // Create a item for the driver in set options page // Clear the Update buffer // UpdateData->FormSetUpdate = FALSE; UpdateData->FormCallbackHandle = 0; UpdateData->FormUpdate = FALSE; UpdateData->FormTitle = 0; UpdateData->DataCount = 0; Location = (UINT8 *) &UpdateData->Data; // // Export the driver name string and create item in set options page // NewString = EfiLibAllocateZeroPool (EfiStrSize (ControllerName) + EfiStrSize (L"--")); if (EFI_ERROR (LibCheckMapping (ControllerDevicePath,NULL, &mMappingDataBase, NULL, NULL))) { EfiStrCat (NewString, L"--"); } else { EfiStrCat (NewString, L"**"); } EfiStrCat (NewString, ControllerName); NewStringToken = mControllerToken[Index]; Status = Private->Hii->NewString (Private->Hii, NULL, Private->RegisteredHandle, &NewStringToken, NewString); ASSERT_EFI_ERROR (Status); gBS->FreePool (NewString); // // Save the device path string toke for next access use // mControllerToken[Index] = NewStringToken; CreateGotoOpCode ( 0x1200, NewStringToken, // Description String Token STR_GOTO_HELP_DRIVER, // Description Help String Token EFI_IFR_FLAG_INTERACTIVE, // Flag designating callback is active (UINT16) Index + 0x100, // Callback key value Location // Buffer to fill with op-code ); // // Update the buffer items number and adjust next item address to new one // UpdateData->DataCount +=1 ; Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; // // Update first page form // Private->Hii->UpdateForm ( Private->Hii, Private->RegisteredHandle, (EFI_FORM_LABEL) 0x1234, TRUE, UpdateData ); } gBS->FreePool (UpdateData); return EFI_SUCCESS; }
EFI_STATUS IfrCatenate ( IN FORM_BROWSER_FORMSET *FormSet, OUT EFI_HII_VALUE *Result ) /*++ Routine Description: Evaluate opcode EFI_IFR_CATENATE. Arguments: FormSet - Formset which contains this opcode. Result - Evaluation result for this opcode. Returns: EFI_SUCCESS - Opcode evaluation success. Other - Opcode evaluation failed. --*/ { EFI_STATUS Status; EFI_HII_VALUE Value; CHAR16 *String[2]; UINTN Index; CHAR16 *StringPtr; // // String[0] - The second string // String[1] - The first string // String[0] = NULL; String[1] = NULL; StringPtr = NULL; Status = EFI_SUCCESS; for (Index = 0; Index < 2; Index++) { Status = PopExpression (&Value); if (EFI_ERROR (Status)) { goto Done; } if (Value.Type != EFI_IFR_TYPE_STRING) { Status = EFI_UNSUPPORTED; goto Done; } String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle); if (String== NULL) { Status = EFI_NOT_FOUND; goto Done; } } StringPtr= EfiLibAllocatePool (EfiStrSize (String[1]) + EfiStrSize (String[0])); ASSERT (StringPtr != NULL); EfiStrCpy (StringPtr, String[1]); EfiStrCat (StringPtr, String[0]); Result->Type = EFI_IFR_TYPE_STRING; Result->Value.string = NewString (StringPtr, FormSet->HiiHandle); Done: EfiLibSafeFreePool (String[0]); EfiLibSafeFreePool (String[1]); EfiLibSafeFreePool (StringPtr); return Status; }
VOID UpdateConModePage ( IN BMM_CALLBACK_DATA *CallbackData ) /*++ Routine Description: Refresh the text mode page Arguments: CallbackData - BMM_CALLBACK_DATA Returns: None. --*/ { UINTN Mode; UINTN Index; UINTN Col; UINTN Row; CHAR16 RowString[50]; CHAR16 ModeString[50]; UINTN MaxMode; UINTN ValidMode; EFI_STRING_ID *ModeToken; IFR_OPTION *IfrOptionList; EFI_STATUS Status; EFI_SIMPLE_TEXT_OUT_PROTOCOL *ConOut; ConOut = gST->ConOut; Index = 0; ValidMode = 0; MaxMode = (UINTN) (ConOut->Mode->MaxMode); CallbackData->BmmAskSaveOrNot = TRUE; UpdatePageStart (CallbackData); // // Check valid mode // for (Mode = 0; Mode < MaxMode; Mode++) { Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); if (EFI_ERROR (Status)) { continue; } ValidMode++; } if (ValidMode == 0) { return; } IfrOptionList = EfiAllocateZeroPool (sizeof (IFR_OPTION) * ValidMode); ASSERT(IfrOptionList != NULL); ModeToken = EfiAllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode); ASSERT(ModeToken != NULL); // // Determin which mode should be the first entry in menu // GetConsoleOutMode (CallbackData); // // Build text mode options // for (Mode = 0; Mode < MaxMode; Mode++) { Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row); if (EFI_ERROR (Status)) { continue; } // // Build mode string Column x Row // EfiValueToString (ModeString, Col, 0, 0); EfiStrCat (ModeString, L" x "); EfiValueToString (RowString, Row, 0, 0); EfiStrCat (ModeString, RowString); IfrLibNewString (CallbackData->BmmHiiHandle, &ModeToken[Index], ModeString); IfrOptionList[Index].StringToken = ModeToken[Index]; IfrOptionList[Index].Value.u16 = (UINT16) Mode; if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) { IfrOptionList[Index].Flags = EFI_IFR_OPTION_DEFAULT; } else { IfrOptionList[Index].Flags = 0; } Index++; } CreateOneOfOpCode ( CON_MODE_QUESTION_ID, VARSTORE_ID_BOOT_MAINT, CON_MODE_VAR_OFFSET, STRING_TOKEN (STR_CON_MODE_SETUP), STRING_TOKEN (STR_CON_MODE_SETUP), EFI_IFR_FLAG_RESET_REQUIRED, EFI_IFR_NUMERIC_SIZE_2, IfrOptionList, ValidMode, &gUpdateData ); SafeFreePool (IfrOptionList); SafeFreePool (ModeToken); UpdatePageEnd (CallbackData); }
VOID AlignmentItem ( IN CHAR16 *ControllerHandleName, IN CHAR16 *PrefixString, IN OUT CHAR16 **NewString ) /*++ Routine Description: Do controller item string swap and alignment if needed. The alignment is the length of PrefixString. Because controller device path is too long sometime and cannot be presented in one line, and the browser automatic swap will break the necessary alignment, so do some additional process for the problem. Arguments: ControllerHandleName - a pointer to the controller real device path string PrefixString- a pointer to the prefix string NewString - a pointer to the string which will be presented by the browser Returns: None --*/ { CHAR16 *PadString; UINTN PtrIndex; UINTN IndexOffset; UINTN Width; CHAR16 *NewStringSwapped; UINTN SwapLineNum; UINTN SwapLine; // // Register the device name string and create item in set options page // *NewString = EfiLibAllocateZeroPool (EfiStrSize (ControllerHandleName) + EfiStrSize (PrefixString)); EfiStrCat (*NewString, PrefixString); EfiStrCat (*NewString, ControllerHandleName); // // Add pad chars into the string for string swap in set options page to solve following two issue: // Issue1: Our form browser will do the string swap according to the spaces in the string, so // if a string is too long and without space in it, the string position will be ugly. // The driver need add some spaces to control the swap in the long and no space string. // Issue2: If browser find a space to do swap, it will not show any other space directly followed it in swap position. // So if you want to use the space to do the alignment in swapped new line, you need add another char(e.g '.') in it. // e.g. if the item max lenth is 5, then the following string need add some space and '.' to get right presentation // '12345678901234567890' --------> ' 12345 . 67890 . 12345 . 67890' , and presentation is below // | 12345 // |. 67890 // |. 12345 // |. 67890 // if ((EfiStrLen (*NewString)/SWAP_LENGTH > 0) && (EfiStrLen (PrefixString) > 0)) { // // Prepare the pad string according to the PrefixString length // the pad string is string of ' ', except of the NO2 charater which is '.' // PadString = EfiLibAllocateZeroPool (EfiStrSize (PrefixString) + 2); for (PtrIndex = 0; PtrIndex < (EfiStrLen (PrefixString) + 1); PtrIndex++) { PadString[PtrIndex] = ' '; } PadString[1] = '.'; Width = SWAP_LENGTH - EfiStrLen (PrefixString); SwapLineNum = EfiStrLen (ControllerHandleName)/Width; NewStringSwapped = EfiLibAllocateZeroPool (EfiStrSize (ControllerHandleName) + EfiStrSize (PrefixString) + SwapLineNum * EfiStrSize (PadString)); ASSERT (NewStringSwapped != NULL); IndexOffset = 0; EfiStrCpy (NewStringSwapped, PrefixString); IndexOffset += EfiStrLen (PrefixString); for (SwapLine = 0; SwapLine < SwapLineNum; SwapLine++) { EfiStrnCpy (&NewStringSwapped[IndexOffset], &ControllerHandleName[SwapLine * Width], Width ); IndexOffset += Width; EfiStrnCpy (&NewStringSwapped[IndexOffset], PadString, EfiStrLen (PadString) ); IndexOffset += EfiStrLen (PadString); } EfiStrCat (NewStringSwapped, &ControllerHandleName[SwapLine * Width]); gBS->FreePool (PadString); gBS->FreePool (*NewString); *NewString = NewStringSwapped; } return; }