/** This function update the "DriverOrder" EFI Variable based on BMM Formset's NV map. It then refresh DriverOptionMenu with the new "DriverOrder" list. @param CallbackData The BMM context data. @retval EFI_SUCCESS The function complete successfully. @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. **/ EFI_STATUS Var_UpdateDriverOrder ( IN BMM_CALLBACK_DATA *CallbackData ) { EFI_STATUS Status; UINT16 Index; UINT16 *DriverOrderList; UINT16 *NewDriverOrderList; UINTN DriverOrderListSize; DriverOrderList = NULL; DriverOrderListSize = 0; // // First check whether DriverOrder is present in current configuration // DriverOrderList = BdsLibGetVariableAndSize ( L"DriverOrder", &gEfiGlobalVariableGuid, &DriverOrderListSize ); NewDriverOrderList = AllocateZeroPool (DriverOrderListSize); if (NewDriverOrderList == NULL) { return EFI_OUT_OF_RESOURCES; } // // If exists, delete it to hold new DriverOrder // if (DriverOrderList != NULL) { EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); FreePool (DriverOrderList); } ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0]))); for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1); } Status = gRT->SetVariable ( L"DriverOrder", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, DriverOrderListSize, NewDriverOrderList ); // // Changing the content without increasing its size with current variable implementation shouldn't fail. // ASSERT_EFI_ERROR (Status); BOpt_FreeMenu (&DriverOptionMenu); BOpt_GetDriverOptions (CallbackData); return EFI_SUCCESS; }
/** This function update the "DriverOrder" EFI Variable based on BMM Formset's NV map. It then refresh DriverOptionMenu with the new "DriverOrder" list. @param CallbackData The BMM context data. @retval EFI_SUCCESS The function complete successfully. @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function. @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. **/ EFI_STATUS Var_UpdateDriverOrder ( IN BMM_CALLBACK_DATA *CallbackData ) { EFI_STATUS Status; UINT16 Index; UINT16 *DriverOrderList; UINT16 *NewDriverOrderList; UINTN DriverOrderListSize; DriverOrderList = NULL; DriverOrderListSize = 0; // // First check whether DriverOrder is present in current configuration // GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize); NewDriverOrderList = AllocateZeroPool (DriverOrderListSize); if (NewDriverOrderList == NULL) { return EFI_OUT_OF_RESOURCES; } // // If exists, delete it to hold new DriverOrder // if (DriverOrderList != NULL) { EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); FreePool (DriverOrderList); } ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder) / sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder[0]))); for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.DriverOptionOrder[Index] - 1); } Status = gRT->SetVariable ( L"DriverOrder", &gEfiGlobalVariableGuid, VAR_FLAG, DriverOrderListSize, NewDriverOrderList ); if (EFI_ERROR (Status)) { return Status; } BOpt_FreeMenu (&DriverOptionMenu); BOpt_GetDriverOptions (CallbackData); return EFI_SUCCESS; }
/** Initialized all Menu Option List. @param CallbackData The BMM context data. **/ VOID InitAllMenu ( IN BMM_CALLBACK_DATA *CallbackData ) { InitializeListHead (&BootOptionMenu.Head); InitializeListHead (&DriverOptionMenu.Head); BOpt_GetBootOptions (CallbackData); BOpt_GetDriverOptions (CallbackData); BOpt_FindDrivers (); InitializeListHead (&ConsoleInpMenu.Head); InitializeListHead (&ConsoleOutMenu.Head); InitializeListHead (&ConsoleErrMenu.Head); InitializeListHead (&TerminalMenu.Head); LocateSerialIo (); GetAllConsoles (); mAllMenuInit = TRUE; }
/** This function processes the results of changes in configuration. When user select a interactive opcode, this callback will be triggered. Based on the Question(QuestionId) that triggers the callback, the corresponding actions is performed. It handles: 1) the addition of boot option. 2) the addition of driver option. 3) exit from file browser 4) update of file content if a dir is selected. 5) boot the file if a file is selected in "boot from file" @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param Action Specifies the type of action taken by the browser. @param QuestionId A unique value which is sent to the original exporting driver so that it can identify the type of data to expect. @param Type The type of value for the question. @param Value A pointer to the data being sent to the original exporting driver. @param ActionRequest On return, points to the action requested by the callback function. @retval EFI_SUCCESS The callback successfully handled the action. @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved. @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. @retval EFI_INVALID_PARAMETER If paramter Value or ActionRequest is NULL. **/ EFI_STATUS EFIAPI FileExplorerCallback ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN EFI_BROWSER_ACTION Action, IN EFI_QUESTION_ID QuestionId, IN UINT8 Type, IN EFI_IFR_TYPE_VALUE *Value, OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest ) { BMM_CALLBACK_DATA *Private; FILE_EXPLORER_NV_DATA *NvRamMap; EFI_STATUS Status; if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { // // Do nothing for other UEFI Action. Only do call back when data is changed. // return EFI_UNSUPPORTED; } Status = EFI_SUCCESS; Private = FE_CALLBACK_DATA_FROM_THIS (This); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; // // Retrieve uncommitted data from Form Browser // NvRamMap = &Private->FeFakeNvData; HiiGetBrowserData (&mFileExplorerGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap); if (Action == EFI_BROWSER_ACTION_CHANGED) { if ((Value == NULL) || (ActionRequest == NULL)) { return EFI_INVALID_PARAMETER; } if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) { // // Apply changes and exit formset // if (FileExplorerStateAddBootOption == Private->FeCurrentState) { Status = Var_UpdateBootOption (Private, NvRamMap); if (EFI_ERROR (Status)) { return Status; } BOpt_GetBootOptions (Private); CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu); } else if (FileExplorerStateAddDriverOptionState == Private->FeCurrentState) { Status = Var_UpdateDriverOption ( Private, Private->FeHiiHandle, NvRamMap->DescriptionData, NvRamMap->OptionalData, NvRamMap->ForceReconnect ); if (EFI_ERROR (Status)) { return Status; } BOpt_GetDriverOptions (Private); CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu); } *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) { // // Discard changes and exit formset // NvRamMap->OptionalData[0] = 0x0000; NvRamMap->DescriptionData[0] = 0x0000; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } else if (QuestionId < FILE_OPTION_OFFSET) { // // Exit File Explorer formset // *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } } else if (Action == EFI_BROWSER_ACTION_CHANGING) { if (Value == NULL) { return EFI_INVALID_PARAMETER; } if (QuestionId >= FILE_OPTION_OFFSET) { UpdateFileExplorer (Private, QuestionId); } } return Status; }
/** This function applies changes in a driver's configuration. Input is a Configuration, which has the routing data for this driver followed by name / value configuration pairs. The driver must apply those pairs to its configurable storage. If the driver's configuration is stored in a linear block of data and the driver's name / value pairs are in <BlockConfig> format, it may use the ConfigToBlock helper function (above) to simplify the job. Currently not implemented. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param[in] Configuration A null-terminated Unicode string in <ConfigString> format. @param[out] Progress A pointer to a string filled in with the offset of the most recent '&' before the first failing name / value pair (or the beginn ing of the string if the failure is in the first name / value pair) or the terminating NULL if all was successful. @retval EFI_SUCCESS The results have been distributed or are awaiting distribution. @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the results that must be stored awaiting possible future protocols. @retval EFI_INVALID_PARAMETERS Passing in a NULL for the Results parameter would result in this type of error. @retval EFI_NOT_FOUND Target for the specified routing data was not found. **/ EFI_STATUS EFIAPI FileExplorerRouteConfig ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN CONST EFI_STRING Configuration, OUT EFI_STRING *Progress ) { EFI_STATUS Status; UINTN BufferSize; EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; FILE_EXPLORER_NV_DATA *FeData; BMM_CALLBACK_DATA *Private; if (Progress == NULL) { return EFI_INVALID_PARAMETER; } *Progress = Configuration; if (Configuration == NULL) { return EFI_INVALID_PARAMETER; } // // Check routing data in <ConfigHdr>. // Note: there is no name for Name/Value storage, only GUID will be checked // if (!HiiIsConfigHdrMatch (Configuration, &gFileExploreFormSetGuid, mFileExplorerStorageName)) { return EFI_NOT_FOUND; } Status = gBS->LocateProtocol ( &gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID**) &ConfigRouting ); if (EFI_ERROR (Status)) { return Status; } Private = FE_CALLBACK_DATA_FROM_THIS (This); // // Get Buffer Storage data from EFI variable // BufferSize = sizeof (FILE_EXPLORER_NV_DATA ); FeData = &Private->FeFakeNvData; // // Convert <ConfigResp> to buffer data by helper function ConfigToBlock() // Status = ConfigRouting->ConfigToBlock ( ConfigRouting, Configuration, (UINT8 *) FeData, &BufferSize, Progress ); ASSERT_EFI_ERROR (Status); if (FeData->BootDescriptionData[0] != 0x00 || FeData->BootOptionalData[0] != 0x00) { Status = Var_UpdateBootOption (Private, FeData); if (EFI_ERROR (Status)) { return Status; } BOpt_GetBootOptions (Private); CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu); } if (FeData->DriverDescriptionData[0] != 0x00 || FeData->DriverOptionalData[0] != 0x00) { Status = Var_UpdateDriverOption ( Private, Private->FeHiiHandle, FeData->DriverDescriptionData, FeData->DriverOptionalData, FeData->ForceReconnect ); if (EFI_ERROR (Status)) { return Status; } BOpt_GetDriverOptions (Private); CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu); } return EFI_SUCCESS; }
/** Function handling request to apply changes for BMM pages. @param Private Pointer to callback data buffer. @param CurrentFakeNVMap Pointer to buffer holding data of various values used by BMM @param FormId ID of the form which has sent the request to apply change. @retval EFI_SUCCESS Change successfully applied. @retval Other Error occurs while trying to apply changes. **/ EFI_STATUS ApplyChangeHandler ( IN BMM_CALLBACK_DATA *Private, IN BMM_FAKE_NV_DATA *CurrentFakeNVMap, IN EFI_FORM_ID FormId ) { BM_CONSOLE_CONTEXT *NewConsoleContext; BM_TERMINAL_CONTEXT *NewTerminalContext; BM_LOAD_CONTEXT *NewLoadContext; BM_MENU_ENTRY *NewMenuEntry; EFI_STATUS Status; UINT16 Index; Status = EFI_SUCCESS; switch (FormId) { case FORM_SET_FD_ORDER_ID: case FORM_SET_HD_ORDER_ID: case FORM_SET_CD_ORDER_ID: case FORM_SET_NET_ORDER_ID: case FORM_SET_BEV_ORDER_ID: Var_UpdateBBSOption (Private); break; case FORM_BOOT_DEL_ID: for (Index = 0; ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (CurrentFakeNVMap->OptionDel) / sizeof (CurrentFakeNVMap->OptionDel[0])))); Index ++) { NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = CurrentFakeNVMap->OptionDel[Index]; } Var_DelBootOption (); break; case FORM_DRV_DEL_ID: for (Index = 0; ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (CurrentFakeNVMap->OptionDel) / sizeof (CurrentFakeNVMap->OptionDel[0])))); Index++) { NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = CurrentFakeNVMap->OptionDel[Index]; } Var_DelDriverOption (); break; case FORM_BOOT_CHG_ID: Status = Var_UpdateBootOrder (Private); break; case FORM_DRV_CHG_ID: Status = Var_UpdateDriverOrder (Private); break; case FORM_TIME_OUT_ID: Status = gRT->SetVariable ( L"Timeout", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, sizeof (UINT16), &(CurrentFakeNVMap->BootTimeOut) ); ASSERT_EFI_ERROR(Status); Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut; break; case FORM_BOOT_NEXT_ID: Status = Var_UpdateBootNext (Private); break; case FORM_CON_MODE_ID: Status = Var_UpdateConMode (Private); break; case FORM_CON_COM_SETUP_ID: NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal); ASSERT (NewMenuEntry != NULL); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate; ASSERT (CurrentFakeNVMap->COMBaudRate < (sizeof (BaudRateList) / sizeof (BaudRateList[0]))); NewTerminalContext->BaudRate = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value; NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate; ASSERT (CurrentFakeNVMap->COMDataRate < (sizeof (DataBitsList) / sizeof (DataBitsList[0]))); NewTerminalContext->DataBits = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value; NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits; ASSERT (CurrentFakeNVMap->COMStopBits < (sizeof (StopBitsList) / sizeof (StopBitsList[0]))); NewTerminalContext->StopBits = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value; NewTerminalContext->ParityIndex = CurrentFakeNVMap->COMParity; ASSERT (CurrentFakeNVMap->COMParity < (sizeof (ParityList) / sizeof (ParityList[0]))); NewTerminalContext->Parity = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value; NewTerminalContext->TerminalType = CurrentFakeNVMap->COMTerminalType; NewTerminalContext->FlowControl = CurrentFakeNVMap->COMFlowControl; ChangeTerminalDevicePath ( &(NewTerminalContext->DevicePath), FALSE ); Var_UpdateConsoleInpOption (); Var_UpdateConsoleOutOption (); Var_UpdateErrorOutOption (); break; case FORM_CON_IN_ID: for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index); NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index < MAX_MENU_NUMBER); NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; } for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index + ConsoleInpMenu.MenuNumber < MAX_MENU_NUMBER); NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber]; } Var_UpdateConsoleInpOption (); break; case FORM_CON_OUT_ID: for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index); NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index < MAX_MENU_NUMBER); NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; } for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index + ConsoleOutMenu.MenuNumber < MAX_MENU_NUMBER); NewTerminalContext->IsConOut = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber]; } Var_UpdateConsoleOutOption (); break; case FORM_CON_ERR_ID: for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index); NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index < MAX_MENU_NUMBER); NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; } for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index + ConsoleErrMenu.MenuNumber < MAX_MENU_NUMBER); NewTerminalContext->IsStdErr = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber]; } Var_UpdateErrorOutOption (); break; case FORM_DRV_ADD_HANDLE_DESC_ID: Status = Var_UpdateDriverOption ( Private, Private->BmmHiiHandle, CurrentFakeNVMap->DriverAddHandleDesc, CurrentFakeNVMap->DriverAddHandleOptionalData, CurrentFakeNVMap->DriverAddForceReconnect ); if (EFI_ERROR (Status)) { goto Error; } BOpt_GetDriverOptions (Private); CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu); break; default: break; } Error: return Status; }
EFI_STATUS EFIAPI FileExplorerCallback ( IN EFI_FORM_CALLBACK_PROTOCOL *This, IN UINT16 KeyValue, IN EFI_IFR_DATA_ARRAY *Data, OUT EFI_HII_CALLBACK_PACKET **Packet ) /*++ Routine Description: Callback Function for file exploration and file interaction. Arguments: This - File explorer callback protocol pointer. KeyValue - Key value to identify the type of data to expect. Data - A pointer to the data being sent to the original exporting driver. Packet - A pointer to a packet of information which a driver passes back to the browser. Returns: EFI_SUCCESS - Callback ended successfully. Others - Contain some errors. --*/ { BMM_CALLBACK_DATA *Private; FILE_EXPLORER_NV_DATA *NvRamMap; EFI_STATUS Status; Status = EFI_SUCCESS; Private = FE_CALLBACK_DATA_FROM_THIS (This); UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->FeCallbackHandle; NvRamMap = (FILE_EXPLORER_NV_DATA *) Data->NvRamMap; if (KEY_VALUE_SAVE_AND_EXIT == KeyValue) { // // Apply changes and exit formset. // if (ADD_BOOT_OPTION_STATE == Private->FeCurrentState) { Status = Var_UpdateBootOption (Private, NvRamMap); if (EFI_ERROR (Status)) { return Status; } BOpt_GetBootOptions (Private); CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu); } else if (ADD_DRIVER_OPTION_STATE == Private->FeCurrentState) { Status = Var_UpdateDriverOption ( Private, Private->FeHiiHandle, NvRamMap->DescriptionData, NvRamMap->OptionalData, NvRamMap->ForceReconnect ); if (EFI_ERROR (Status)) { return Status; } BOpt_GetDriverOptions (Private); CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu); } CreateCallbackPacket (Packet, EXIT_REQUIRED | NV_NOT_CHANGED); } else if (KEY_VALUE_NO_SAVE_AND_EXIT == KeyValue) { // // Discard changes and exit formset. // NvRamMap->OptionalData[0] = 0x0000; NvRamMap->DescriptionData[0] = 0x0000; CreateCallbackPacket (Packet, EXIT_REQUIRED | NV_NOT_CHANGED); } else if (KeyValue < FILE_OPTION_OFFSET) { // // Exit File Explorer formset. // CreateCallbackPacket (Packet, EXIT_REQUIRED); } else { if (UpdateFileExplorer (Private, KeyValue)) { CreateCallbackPacket (Packet, EXIT_REQUIRED); } } return Status; }
/** This function applies changes in a driver's configuration. Input is a Configuration, which has the routing data for this driver followed by name / value configuration pairs. The driver must apply those pairs to its configurable storage. If the driver's configuration is stored in a linear block of data and the driver's name / value pairs are in <BlockConfig> format, it may use the ConfigToBlock helper function (above) to simplify the job. Currently not implemented. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param[in] Configuration A null-terminated Unicode string in <ConfigString> format. @param[out] Progress A pointer to a string filled in with the offset of the most recent '&' before the first failing name / value pair (or the beginn ing of the string if the failure is in the first name / value pair) or the terminating NULL if all was successful. @retval EFI_SUCCESS The results have been distributed or are awaiting distribution. @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the results that must be stored awaiting possible future protocols. @retval EFI_INVALID_PARAMETERS Passing in a NULL for the Results parameter would result in this type of error. @retval EFI_NOT_FOUND Target for the specified routing data was not found. **/ EFI_STATUS EFIAPI BootMaintRouteConfig ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN CONST EFI_STRING Configuration, OUT EFI_STRING *Progress ) { EFI_STATUS Status; UINTN BufferSize; EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; BMM_FAKE_NV_DATA *NewBmmData; BMM_FAKE_NV_DATA *OldBmmData; BM_CONSOLE_CONTEXT *NewConsoleContext; BM_TERMINAL_CONTEXT *NewTerminalContext; BM_MENU_ENTRY *NewMenuEntry; BM_LOAD_CONTEXT *NewLoadContext; UINT16 Index; BOOLEAN TerminalAttChange; BMM_CALLBACK_DATA *Private; if (Progress == NULL) { return EFI_INVALID_PARAMETER; } *Progress = Configuration; if (Configuration == NULL) { return EFI_INVALID_PARAMETER; } // // Check routing data in <ConfigHdr>. // Note: there is no name for Name/Value storage, only GUID will be checked // if (!HiiIsConfigHdrMatch (Configuration, &mBootMaintGuid, mBootMaintStorageName)) { return EFI_NOT_FOUND; } Status = gBS->LocateProtocol ( &gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&ConfigRouting ); if (EFI_ERROR (Status)) { return Status; } Private = BMM_CALLBACK_DATA_FROM_THIS (This); // // Get Buffer Storage data from EFI variable // BufferSize = sizeof (BMM_FAKE_NV_DATA); OldBmmData = &Private->BmmOldFakeNVData; NewBmmData = &Private->BmmFakeNvData; // // Convert <ConfigResp> to buffer data by helper function ConfigToBlock() // Status = ConfigRouting->ConfigToBlock ( ConfigRouting, Configuration, (UINT8 *) NewBmmData, &BufferSize, Progress ); ASSERT_EFI_ERROR (Status); // // Compare new and old BMM configuration data and only do action for modified item to // avoid setting unnecessary non-volatile variable // // // Check data which located in BMM main page and save the settings if need // if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) { Status = Var_UpdateBootNext (Private); } // // Check data which located in Boot Options Menu and save the settings if need // if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) { for (Index = 0; ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0])))); Index ++) { NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = NewBmmData->BootOptionDel[Index]; NewBmmData->BootOptionDel[Index] = FALSE; NewBmmData->BootOptionDelMark[Index] = FALSE; } Var_DelBootOption (); } if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) { Status = Var_UpdateBootOrder (Private); } if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0){ Status = gRT->SetVariable( L"Timeout", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, sizeof(UINT16), &(NewBmmData->BootTimeOut) ); if (EFI_ERROR (Status)) { // // If set variable fail, and don't have the appropriate error status for RouteConfig fuction to return, // just return the EFI_NOT_FOUND. // if (Status == EFI_OUT_OF_RESOURCES) { return Status; } else { return EFI_NOT_FOUND; } } Private->BmmOldFakeNVData.BootTimeOut = NewBmmData->BootTimeOut; } // // Check data which located in Driver Options Menu and save the settings if need // if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) { for (Index = 0; ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0])))); Index++) { NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = NewBmmData->DriverOptionDel[Index]; NewBmmData->DriverOptionDel[Index] = FALSE; NewBmmData->DriverOptionDelMark[Index] = FALSE; } Var_DelDriverOption (); } if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) { Status = Var_UpdateDriverOrder (Private); } if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0){ Var_UpdateConMode(Private); } TerminalAttChange = FALSE; for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { // // only need update modified items // if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) == 0 && CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) == 0 && CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) == 0 && CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) == 0 && CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) == 0 && CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) == 0) { continue; } NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); ASSERT (NewMenuEntry != NULL); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; NewTerminalContext->BaudRateIndex = NewBmmData->COMBaudRate[Index]; ASSERT (NewBmmData->COMBaudRate[Index] < (sizeof (BaudRateList) / sizeof (BaudRateList[0]))); NewTerminalContext->BaudRate = BaudRateList[NewBmmData->COMBaudRate[Index]].Value; NewTerminalContext->DataBitsIndex = NewBmmData->COMDataRate[Index]; ASSERT (NewBmmData->COMDataRate[Index] < (sizeof (DataBitsList) / sizeof (DataBitsList[0]))); NewTerminalContext->DataBits = (UINT8) DataBitsList[NewBmmData->COMDataRate[Index]].Value; NewTerminalContext->StopBitsIndex = NewBmmData->COMStopBits[Index]; ASSERT (NewBmmData->COMStopBits[Index] < (sizeof (StopBitsList) / sizeof (StopBitsList[0]))); NewTerminalContext->StopBits = (UINT8) StopBitsList[NewBmmData->COMStopBits[Index]].Value; NewTerminalContext->ParityIndex = NewBmmData->COMParity[Index]; ASSERT (NewBmmData->COMParity[Index] < (sizeof (ParityList) / sizeof (ParityList[0]))); NewTerminalContext->Parity = (UINT8) ParityList[NewBmmData->COMParity[Index]].Value; NewTerminalContext->TerminalType = NewBmmData->COMTerminalType[Index]; NewTerminalContext->FlowControl = NewBmmData->COMFlowControl[Index]; ChangeTerminalDevicePath ( NewTerminalContext->DevicePath, FALSE ); TerminalAttChange = TRUE; } if (TerminalAttChange) { Var_UpdateConsoleInpOption (); Var_UpdateConsoleOutOption (); Var_UpdateErrorOutOption (); } // // Check data which located in Console Options Menu and save the settings if need // if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 0){ for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++){ NewMenuEntry = BOpt_GetMenuEntry(&ConsoleInpMenu, Index); NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext; ASSERT (Index < MAX_MENU_NUMBER); NewConsoleContext->IsActive = NewBmmData->ConsoleInCheck[Index]; } for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index + ConsoleInpMenu.MenuNumber < MAX_MENU_NUMBER); NewTerminalContext->IsConIn = NewBmmData->ConsoleInCheck[Index + ConsoleInpMenu.MenuNumber]; } Var_UpdateConsoleInpOption(); } if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 0){ for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++){ NewMenuEntry = BOpt_GetMenuEntry(&ConsoleOutMenu, Index); NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext; ASSERT (Index < MAX_MENU_NUMBER); NewConsoleContext->IsActive = NewBmmData->ConsoleOutCheck[Index]; } for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index + ConsoleOutMenu.MenuNumber < MAX_MENU_NUMBER); NewTerminalContext->IsConOut = NewBmmData->ConsoleOutCheck[Index + ConsoleOutMenu.MenuNumber]; } Var_UpdateConsoleOutOption(); } if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 0){ for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++){ NewMenuEntry = BOpt_GetMenuEntry(&ConsoleErrMenu, Index); NewConsoleContext = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext; ASSERT (Index < MAX_MENU_NUMBER); NewConsoleContext->IsActive = NewBmmData->ConsoleErrCheck[Index]; } for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index + ConsoleErrMenu.MenuNumber < MAX_MENU_NUMBER); NewTerminalContext->IsStdErr = NewBmmData->ConsoleErrCheck[Index + ConsoleErrMenu.MenuNumber]; } Var_UpdateErrorOutOption(); } if (CompareMem (NewBmmData->BootDescriptionData, OldBmmData->BootDescriptionData, sizeof (NewBmmData->BootDescriptionData)) != 0 || CompareMem (NewBmmData->BootOptionalData, OldBmmData->BootOptionalData, sizeof (NewBmmData->BootOptionalData)) != 0) { Status = Var_UpdateBootOption (Private); NewBmmData->BootOptionChanged = FALSE; if (EFI_ERROR (Status)) { return Status; } BOpt_GetBootOptions (Private); } if (CompareMem (NewBmmData->DriverDescriptionData, OldBmmData->DriverDescriptionData, sizeof (NewBmmData->DriverDescriptionData)) != 0 || CompareMem (NewBmmData->DriverOptionalData, OldBmmData->DriverOptionalData, sizeof (NewBmmData->DriverOptionalData)) != 0) { Status = Var_UpdateDriverOption ( Private, Private->BmmHiiHandle, NewBmmData->DriverDescriptionData, NewBmmData->DriverOptionalData, NewBmmData->ForceReconnect ); NewBmmData->DriverOptionChanged = FALSE; NewBmmData->ForceReconnect = TRUE; if (EFI_ERROR (Status)) { return Status; } BOpt_GetDriverOptions (Private); } // // After user do the save action, need to update OldBmmData. // CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA)); return EFI_SUCCESS; }