/** @file | |
The device manager reference implementation | |
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "DeviceManager.h" | |
DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = { | |
DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE, | |
NULL, | |
NULL, | |
{ | |
DeviceManagerExtractConfig, | |
DeviceManagerRouteConfig, | |
DeviceManagerCallback | |
} | |
}; | |
#define MAX_MAC_ADDRESS_NODE_LIST_LEN 10 | |
EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID; | |
// | |
// Which Mac Address string is select | |
// it will decide what menu need to show in the NETWORK_DEVICE_FORM_ID form. | |
// | |
EFI_STRING mSelectedMacAddrString; | |
// | |
// The Mac Address show in the NETWORK_DEVICE_LIST_FORM_ID | |
// | |
MAC_ADDRESS_NODE_LIST mMacDeviceList; | |
HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath = { | |
{ | |
{ | |
HARDWARE_DEVICE_PATH, | |
HW_VENDOR_DP, | |
{ | |
(UINT8) (sizeof (VENDOR_DEVICE_PATH)), | |
(UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) | |
} | |
}, | |
// | |
// {102579A0-3686-466e-ACD8-80C087044F4A} | |
// | |
{ 0x102579a0, 0x3686, 0x466e, { 0xac, 0xd8, 0x80, 0xc0, 0x87, 0x4, 0x4f, 0x4a } } | |
}, | |
{ | |
END_DEVICE_PATH_TYPE, | |
END_ENTIRE_DEVICE_PATH_SUBTYPE, | |
{ | |
(UINT8) (END_DEVICE_PATH_LENGTH), | |
(UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) | |
} | |
} | |
}; | |
/** | |
Extract device path for given HII handle and class guid. | |
@param Handle The HII handle. | |
@retval NULL Fail to get the device path string. | |
@return PathString Get the device path string. | |
**/ | |
CHAR16 * | |
DmExtractDevicePathFromHiiHandle ( | |
IN EFI_HII_HANDLE Handle | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_HANDLE DriverHandle; | |
ASSERT (Handle != NULL); | |
if (Handle == NULL) { | |
return NULL; | |
} | |
Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle); | |
if (EFI_ERROR (Status)) { | |
return NULL; | |
} | |
// | |
// Get device path string. | |
// | |
return ConvertDevicePathToText(DevicePathFromHandle (DriverHandle), FALSE, FALSE); | |
} | |
/** | |
Get the mac address string from the device path. | |
if the device path has the vlan, get the vanid also. | |
@param MacAddressNode Device path begin with mac address | |
@param PBuffer Output string buffer contain mac address. | |
**/ | |
BOOLEAN | |
GetMacAddressString( | |
IN MAC_ADDR_DEVICE_PATH *MacAddressNode, | |
OUT CHAR16 **PBuffer | |
) | |
{ | |
UINTN HwAddressSize; | |
UINTN Index; | |
UINT8 *HwAddress; | |
EFI_DEVICE_PATH_PROTOCOL *Node; | |
UINT16 VlanId; | |
CHAR16 *String; | |
UINTN BufferLen; | |
VlanId = 0; | |
String = NULL; | |
ASSERT(MacAddressNode != NULL); | |
HwAddressSize = sizeof (EFI_MAC_ADDRESS); | |
if (MacAddressNode->IfType == 0x01 || MacAddressNode->IfType == 0x00) { | |
HwAddressSize = 6; | |
} | |
// | |
// The output format is MAC:XX:XX:XX:...\XXXX | |
// The size is the Number size + ":" size + Vlan size(\XXXX) + End | |
// | |
BufferLen = (4 + 2 * HwAddressSize + (HwAddressSize - 1) + 5 + 1) * sizeof (CHAR16); | |
String = AllocateZeroPool (BufferLen); | |
if (String == NULL) { | |
return FALSE; | |
} | |
*PBuffer = String; | |
StrCpyS(String, BufferLen / sizeof (CHAR16), L"MAC:"); | |
String += 4; | |
// | |
// Convert the MAC address into a unicode string. | |
// | |
HwAddress = &MacAddressNode->MacAddress.Addr[0]; | |
for (Index = 0; Index < HwAddressSize; Index++) { | |
UnicodeValueToStringS ( | |
String, | |
BufferLen - ((UINTN)String - (UINTN)*PBuffer), | |
PREFIX_ZERO | RADIX_HEX, | |
*(HwAddress++), | |
2 | |
); | |
String += StrnLenS (String, (BufferLen - ((UINTN)String - (UINTN)*PBuffer)) / sizeof (CHAR16)); | |
if (Index < HwAddressSize - 1) { | |
*String++ = L':'; | |
} | |
} | |
// | |
// If VLAN is configured, it will need extra 5 characters like "\0005". | |
// Plus one unicode character for the null-terminator. | |
// | |
Node = (EFI_DEVICE_PATH_PROTOCOL *)MacAddressNode; | |
while (!IsDevicePathEnd (Node)) { | |
if (Node->Type == MESSAGING_DEVICE_PATH && Node->SubType == MSG_VLAN_DP) { | |
VlanId = ((VLAN_DEVICE_PATH *) Node)->VlanId; | |
} | |
Node = NextDevicePathNode (Node); | |
} | |
if (VlanId != 0) { | |
*String++ = L'\\'; | |
UnicodeValueToStringS ( | |
String, | |
BufferLen - ((UINTN)String - (UINTN)*PBuffer), | |
PREFIX_ZERO | RADIX_HEX, | |
VlanId, | |
4 | |
); | |
String += StrnLenS (String, (BufferLen - ((UINTN)String - (UINTN)*PBuffer)) / sizeof (CHAR16)); | |
} | |
// | |
// Null terminate the Unicode string | |
// | |
*String = L'\0'; | |
return TRUE; | |
} | |
/** | |
Save question id and prompt id to the mac device list. | |
If the same mac address has saved yet, no need to add more. | |
@param MacAddrString Mac address string. | |
@retval EFI_SUCCESS Add the item is successful. | |
@return Other values if failed to Add the item. | |
**/ | |
BOOLEAN | |
AddIdToMacDeviceList ( | |
IN EFI_STRING MacAddrString | |
) | |
{ | |
MENU_INFO_ITEM *TempDeviceList; | |
UINTN Index; | |
EFI_STRING StoredString; | |
EFI_STRING_ID PromptId; | |
EFI_HII_HANDLE HiiHandle; | |
HiiHandle = gDeviceManagerPrivate.HiiHandle; | |
TempDeviceList = NULL; | |
for (Index = 0; Index < mMacDeviceList.CurListLen; Index ++) { | |
StoredString = HiiGetString (HiiHandle, mMacDeviceList.NodeList[Index].PromptId, NULL); | |
if (StoredString == NULL) { | |
return FALSE; | |
} | |
// | |
// Already has save the same mac address to the list. | |
// | |
if (StrCmp (MacAddrString, StoredString) == 0) { | |
return FALSE; | |
} | |
} | |
PromptId = HiiSetString(HiiHandle, 0, MacAddrString, NULL); | |
// | |
// If not in the list, save it. | |
// | |
if (mMacDeviceList.MaxListLen > mMacDeviceList.CurListLen + 1) { | |
mMacDeviceList.NodeList[mMacDeviceList.CurListLen].PromptId = PromptId; | |
mMacDeviceList.NodeList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET); | |
} else { | |
mMacDeviceList.MaxListLen += MAX_MAC_ADDRESS_NODE_LIST_LEN; | |
if (mMacDeviceList.CurListLen != 0) { | |
TempDeviceList = ReallocatePool ( | |
sizeof (MENU_INFO_ITEM) * mMacDeviceList.CurListLen, | |
sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen, | |
mMacDeviceList.NodeList | |
); | |
} else { | |
TempDeviceList = (MENU_INFO_ITEM *)AllocatePool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen); | |
} | |
if (TempDeviceList == NULL) { | |
return FALSE; | |
} | |
TempDeviceList[mMacDeviceList.CurListLen].PromptId = PromptId; | |
TempDeviceList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET); | |
mMacDeviceList.NodeList = TempDeviceList; | |
} | |
mMacDeviceList.CurListLen ++; | |
return TRUE; | |
} | |
/** | |
Check the devcie path, try to find whether it has mac address path. | |
In this function, first need to check whether this path has mac address path. | |
second, when the mac address device path has find, also need to deicide whether | |
need to add this mac address relate info to the menu. | |
@param *Node Input device which need to be check. | |
@param NextShowFormId FormId Which need to be show. | |
@param *NeedAddItem Whether need to add the menu in the network device list. | |
@retval TRUE Has mac address device path. | |
@retval FALSE NOT Has mac address device path. | |
**/ | |
BOOLEAN | |
IsMacAddressDevicePath ( | |
IN VOID *Node, | |
IN EFI_FORM_ID NextShowFormId, | |
OUT BOOLEAN *NeedAddItem | |
) | |
{ | |
EFI_DEVICE_PATH_PROTOCOL *DevicePath; | |
CHAR16 *Buffer; | |
BOOLEAN ReturnVal; | |
ASSERT (Node != NULL); | |
*NeedAddItem = FALSE; | |
ReturnVal = FALSE; | |
Buffer = NULL; | |
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node; | |
// | |
// find the partition device path node | |
// | |
while (!IsDevicePathEnd (DevicePath)) { | |
if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && | |
(DevicePathSubType (DevicePath) == MSG_MAC_ADDR_DP)) { | |
ReturnVal = TRUE; | |
if (DEVICE_MANAGER_FORM_ID == NextShowFormId) { | |
*NeedAddItem = TRUE; | |
break; | |
} | |
if (!GetMacAddressString((MAC_ADDR_DEVICE_PATH*)DevicePath, &Buffer)) { | |
break; | |
} | |
if (NETWORK_DEVICE_FORM_ID == NextShowFormId) { | |
if (StrCmp (Buffer, mSelectedMacAddrString) == 0) { | |
*NeedAddItem = TRUE; | |
} | |
break; | |
} | |
if (NETWORK_DEVICE_LIST_FORM_ID == NextShowFormId) { | |
// | |
// Same handle may has two network child handle, so the questionid | |
// has the offset of SAME_HANDLE_KEY_OFFSET. | |
// | |
if (AddIdToMacDeviceList (Buffer)) { | |
*NeedAddItem = TRUE; | |
} | |
break; | |
} | |
} | |
DevicePath = NextDevicePathNode (DevicePath); | |
} | |
if (Buffer != NULL) { | |
FreePool (Buffer); | |
} | |
return ReturnVal; | |
} | |
/** | |
Check to see if the device path is for the network device. | |
@param Handle The HII handle which include the mac address device path. | |
@param NextShowFormId The FormId of the form which will be show next time. | |
@param ItemCount The new add Mac address item count. | |
@retval TRUE Need to add new item in the menu. | |
@return FALSE Do not need to add the menu about the network. | |
**/ | |
BOOLEAN | |
IsNeedAddNetworkMenu ( | |
IN EFI_HII_HANDLE Handle, | |
IN EFI_FORM_ID NextShowFormId, | |
OUT UINTN *ItemCount | |
) | |
{ | |
EFI_STATUS Status; | |
UINTN EntryCount; | |
UINTN Index; | |
EFI_HANDLE DriverHandle; | |
EFI_HANDLE ControllerHandle; | |
EFI_DEVICE_PATH_PROTOCOL *DevicePath; | |
EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; | |
EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath; | |
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; | |
BOOLEAN IsNeedAdd; | |
IsNeedAdd = FALSE; | |
OpenInfoBuffer = NULL; | |
if ((Handle == NULL) || (ItemCount == NULL)) { | |
return FALSE; | |
} | |
*ItemCount = 0; | |
Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle); | |
if (EFI_ERROR (Status)) { | |
return FALSE; | |
} | |
// | |
// Get the device path by the got Driver handle . | |
// | |
Status = gBS->HandleProtocol (DriverHandle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath); | |
if (EFI_ERROR (Status)) { | |
return FALSE; | |
} | |
TmpDevicePath = DevicePath; | |
// | |
// Check whether this device path include mac address device path. | |
// If this path has mac address path, get the value whether need | |
// add this info to the menu and return. | |
// Else check more about the child handle devcie path. | |
// | |
if (IsMacAddressDevicePath(TmpDevicePath, NextShowFormId,&IsNeedAdd)) { | |
if ((NETWORK_DEVICE_LIST_FORM_ID == NextShowFormId) && IsNeedAdd) { | |
(*ItemCount) = 1; | |
} | |
return IsNeedAdd; | |
} | |
// | |
// Search whether this path is the controller path, not he child handle path. | |
// And the child handle has the network devcie connected. | |
// | |
TmpDevicePath = DevicePath; | |
Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &TmpDevicePath, &ControllerHandle); | |
if (EFI_ERROR (Status)) { | |
return FALSE; | |
} | |
if (!IsDevicePathEnd (TmpDevicePath)) { | |
return FALSE; | |
} | |
// | |
// Retrieve the list of agents that are consuming the specific protocol | |
// on ControllerHandle. | |
// The buffer point by OpenInfoBuffer need be free at this function. | |
// | |
Status = gBS->OpenProtocolInformation ( | |
ControllerHandle, | |
&gEfiPciIoProtocolGuid, | |
&OpenInfoBuffer, | |
&EntryCount | |
); | |
if (EFI_ERROR (Status)) { | |
return FALSE; | |
} | |
// | |
// Inspect if ChildHandle is one of the agents. | |
// | |
Status = EFI_UNSUPPORTED; | |
for (Index = 0; Index < EntryCount; Index++) { | |
// | |
// Query all the children created by the controller handle's driver | |
// | |
if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { | |
Status = gBS->OpenProtocol ( | |
OpenInfoBuffer[Index].ControllerHandle, | |
&gEfiDevicePathProtocolGuid, | |
(VOID **) &ChildDevicePath, | |
NULL, | |
NULL, | |
EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
); | |
if (EFI_ERROR (Status)) { | |
continue; | |
} | |
// | |
// Check whether this device path include mac address device path. | |
// | |
if (!IsMacAddressDevicePath(ChildDevicePath, NextShowFormId,&IsNeedAdd)) { | |
// | |
// If this path not has mac address path, check the other. | |
// | |
continue; | |
} else { | |
// | |
// If need to update the NETWORK_DEVICE_LIST_FORM, try to get more. | |
// | |
if ((NETWORK_DEVICE_LIST_FORM_ID == NextShowFormId)) { | |
if (IsNeedAdd) { | |
(*ItemCount) += 1; | |
} | |
continue; | |
} else { | |
// | |
// If need to update other form, return whether need to add to the menu. | |
// | |
goto Done; | |
} | |
} | |
} | |
} | |
Done: | |
if (OpenInfoBuffer != NULL) { | |
FreePool (OpenInfoBuffer); | |
} | |
return IsNeedAdd; | |
} | |
/** | |
Dynamic create Hii information for Device Manager. | |
@param NextShowFormId The FormId which need to be show. | |
**/ | |
VOID | |
CreateDeviceManagerForm( | |
IN EFI_FORM_ID NextShowFormId | |
) | |
{ | |
UINTN Index; | |
EFI_STRING String; | |
EFI_STRING_ID Token; | |
EFI_STRING_ID TokenHelp; | |
EFI_HII_HANDLE *HiiHandles; | |
EFI_HII_HANDLE HiiHandle; | |
EFI_GUID FormSetGuid; | |
VOID *StartOpCodeHandle; | |
VOID *EndOpCodeHandle; | |
EFI_IFR_GUID_LABEL *StartLabel; | |
EFI_IFR_GUID_LABEL *EndLabel; | |
BOOLEAN AddNetworkMenu; | |
UINTN AddItemCount; | |
UINTN NewStringLen; | |
EFI_STRING NewStringTitle; | |
CHAR16 *DevicePathStr; | |
EFI_STRING_ID DevicePathId; | |
EFI_IFR_FORM_SET *Buffer; | |
UINTN BufferSize; | |
UINT8 ClassGuidNum; | |
EFI_GUID *ClassGuid; | |
UINTN TempSize; | |
UINT8 *Ptr; | |
EFI_STATUS Status; | |
TempSize =0; | |
BufferSize = 0; | |
Buffer = NULL; | |
HiiHandle = gDeviceManagerPrivate.HiiHandle; | |
AddNetworkMenu = FALSE; | |
AddItemCount = 0; | |
// | |
// If need show the Network device list form, clear the old save list first. | |
// | |
if ((NextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) && (mMacDeviceList.CurListLen > 0)) { | |
mMacDeviceList.CurListLen = 0; | |
} | |
// | |
// Update the network device form titile. | |
// | |
if (NextShowFormId == NETWORK_DEVICE_FORM_ID) { | |
String = HiiGetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE_HEAD), NULL); | |
if (String == NULL) { | |
return; | |
} | |
NewStringLen = StrLen (mSelectedMacAddrString) * 2; | |
NewStringLen += (StrLen (String) + 2) * 2; | |
NewStringTitle = AllocatePool (NewStringLen); | |
UnicodeSPrint (NewStringTitle, NewStringLen, L"%s %s", String, mSelectedMacAddrString); | |
HiiSetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NewStringTitle, NULL); | |
FreePool (String); | |
FreePool (NewStringTitle); | |
} | |
// | |
// Allocate space for creation of UpdateData Buffer | |
// | |
StartOpCodeHandle = HiiAllocateOpCodeHandle (); | |
ASSERT (StartOpCodeHandle != NULL); | |
EndOpCodeHandle = HiiAllocateOpCodeHandle (); | |
ASSERT (EndOpCodeHandle != NULL); | |
// | |
// Create Hii Extend Label OpCode as the start opcode | |
// | |
StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); | |
StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; | |
// | |
// According to the next show Form id(mNextShowFormId) to decide which form need to update. | |
// | |
StartLabel->Number = (UINT16) (LABEL_FORM_ID_OFFSET + NextShowFormId); | |
// | |
// Create Hii Extend Label OpCode as the end opcode | |
// | |
EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); | |
EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; | |
EndLabel->Number = LABEL_END; | |
// | |
// Get all the Hii handles | |
// | |
HiiHandles = HiiGetHiiHandles (NULL); | |
ASSERT (HiiHandles != NULL); | |
// | |
// Search for formset of each class type | |
// | |
for (Index = 0; HiiHandles[Index] != NULL; Index++) { | |
Status = HiiGetFormSetFromHiiHandle(HiiHandles[Index], &Buffer,&BufferSize); | |
if (EFI_ERROR (Status)){ | |
continue; | |
} | |
Ptr = (UINT8 *)Buffer; | |
while(TempSize < BufferSize) { | |
TempSize += ((EFI_IFR_OP_HEADER *) Ptr)->Length; | |
if (((EFI_IFR_OP_HEADER *) Ptr)->Length <= OFFSET_OF (EFI_IFR_FORM_SET, Flags)){ | |
Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length; | |
continue; | |
} | |
ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *)Ptr)->Flags & 0x3); | |
ClassGuid = (EFI_GUID *) (VOID *)(Ptr + sizeof (EFI_IFR_FORM_SET)); | |
while (ClassGuidNum-- > 0) { | |
if (CompareGuid (&gEfiHiiPlatformSetupFormsetGuid, ClassGuid)== 0) { | |
ClassGuid ++; | |
continue; | |
} | |
String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->FormSetTitle, NULL); | |
if (String == NULL) { | |
String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL); | |
ASSERT (String != NULL); | |
} | |
Token = HiiSetString (HiiHandle, 0, String, NULL); | |
FreePool (String); | |
String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->Help, NULL); | |
if (String == NULL) { | |
String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL); | |
ASSERT (String != NULL); | |
} | |
TokenHelp = HiiSetString (HiiHandle, 0, String, NULL); | |
FreePool (String); | |
CopyMem (&FormSetGuid, &((EFI_IFR_FORM_SET *) Ptr)->Guid, sizeof (EFI_GUID)); | |
// | |
// Network device process | |
// | |
if (IsNeedAddNetworkMenu (HiiHandles[Index], NextShowFormId,&AddItemCount)) { | |
if (NextShowFormId == DEVICE_MANAGER_FORM_ID) { | |
// | |
// Only show one menu item "Network Config" in the device manger form. | |
// | |
if (!AddNetworkMenu) { | |
AddNetworkMenu = TRUE; | |
HiiCreateGotoOpCode ( | |
StartOpCodeHandle, | |
NETWORK_DEVICE_LIST_FORM_ID, | |
STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_TITLE), | |
STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_HELP), | |
EFI_IFR_FLAG_CALLBACK, | |
(EFI_QUESTION_ID) QUESTION_NETWORK_DEVICE_ID | |
); | |
} | |
} else if (NextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) { | |
// | |
// In network device list form, same mac address device only show one menu. | |
// | |
while (AddItemCount > 0) { | |
HiiCreateGotoOpCode ( | |
StartOpCodeHandle, | |
NETWORK_DEVICE_FORM_ID, | |
mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].PromptId, | |
STRING_TOKEN (STR_NETWORK_DEVICE_HELP), | |
EFI_IFR_FLAG_CALLBACK, | |
mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].QuestionId | |
); | |
AddItemCount -= 1; | |
} | |
} else if (NextShowFormId == NETWORK_DEVICE_FORM_ID) { | |
// | |
// In network device form, only the selected mac address device need to be show. | |
// | |
DevicePathStr = DmExtractDevicePathFromHiiHandle(HiiHandles[Index]); | |
DevicePathId = 0; | |
if (DevicePathStr != NULL){ | |
DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL); | |
FreePool(DevicePathStr); | |
} | |
HiiCreateGotoExOpCode ( | |
StartOpCodeHandle, | |
0, | |
Token, | |
TokenHelp, | |
0, | |
(EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET), | |
0, | |
&FormSetGuid, | |
DevicePathId | |
); | |
} | |
} else { | |
// | |
// Not network device process, only need to show at device manger form. | |
// | |
if (NextShowFormId == DEVICE_MANAGER_FORM_ID) { | |
DevicePathStr = DmExtractDevicePathFromHiiHandle(HiiHandles[Index]); | |
DevicePathId = 0; | |
if (DevicePathStr != NULL){ | |
DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL); | |
FreePool(DevicePathStr); | |
} | |
HiiCreateGotoExOpCode ( | |
StartOpCodeHandle, | |
0, | |
Token, | |
TokenHelp, | |
0, | |
(EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET), | |
0, | |
&FormSetGuid, | |
DevicePathId | |
); | |
} | |
} | |
break; | |
} | |
Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length; | |
} | |
FreePool(Buffer); | |
Buffer = NULL; | |
TempSize = 0; | |
BufferSize = 0; | |
} | |
HiiUpdateForm ( | |
HiiHandle, | |
&mDeviceManagerGuid, | |
NextShowFormId, | |
StartOpCodeHandle, | |
EndOpCodeHandle | |
); | |
HiiFreeOpCodeHandle (StartOpCodeHandle); | |
HiiFreeOpCodeHandle (EndOpCodeHandle); | |
FreePool (HiiHandles); | |
} | |
/** | |
This function allows a caller to extract the current configuration for one | |
or more named elements from the target driver. | |
@param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. | |
@param Request A null-terminated Unicode string in <ConfigRequest> format. | |
@param Progress On return, points to a character in the Request string. | |
Points to the string's null terminator if request was successful. | |
Points to the most recent '&' before the first failing name/value | |
pair (or the beginning of the string if the failure is in the | |
first name/value pair) if the request was not successful. | |
@param Results A null-terminated Unicode string in <ConfigAltResp> format which | |
has all values filled in for the names in the Request string. | |
String to be allocated by the called function. | |
@retval EFI_SUCCESS The Results is filled with the requested values. | |
@retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. | |
@retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. | |
@retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
DeviceManagerExtractConfig ( | |
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
IN CONST EFI_STRING Request, | |
OUT EFI_STRING *Progress, | |
OUT EFI_STRING *Results | |
) | |
{ | |
if (Progress == NULL || Results == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
*Progress = Request; | |
return EFI_NOT_FOUND; | |
} | |
/** | |
This function processes the results of changes in configuration. | |
@param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. | |
@param Configuration A null-terminated Unicode string in <ConfigResp> format. | |
@param Progress A pointer to a string filled in with the offset of the most | |
recent '&' before the first failing name/value pair (or the | |
beginning 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 is processed successfully. | |
@retval EFI_INVALID_PARAMETER Configuration is NULL. | |
@retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
DeviceManagerRouteConfig ( | |
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
IN CONST EFI_STRING Configuration, | |
OUT EFI_STRING *Progress | |
) | |
{ | |
if (Configuration == NULL || Progress == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
*Progress = Configuration; | |
return EFI_NOT_FOUND; | |
} | |
/** | |
This function is invoked if user selected a interactive opcode from Device Manager's | |
Formset. If user set VBIOS, the new value is saved to EFI variable. | |
@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_INVALID_PARAMETER The setup browser call this function with invalid parameters. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
DeviceManagerCallback ( | |
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 | |
) | |
{ | |
UINTN CurIndex; | |
if (Action != EFI_BROWSER_ACTION_CHANGING) { | |
// | |
// Do nothing for other UEFI Action. Only do call back when data is changed. | |
// | |
return EFI_UNSUPPORTED; | |
} | |
if ((Value == NULL) || (ActionRequest == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if ((QuestionId < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET) && (QuestionId >= NETWORK_DEVICE_LIST_KEY_OFFSET)) { | |
// | |
// If user select the mac address, need to record mac address string to support next form show. | |
// | |
for (CurIndex = 0; CurIndex < mMacDeviceList.CurListLen; CurIndex ++) { | |
if (mMacDeviceList.NodeList[CurIndex].QuestionId == QuestionId) { | |
mSelectedMacAddrString = HiiGetString (gDeviceManagerPrivate.HiiHandle, mMacDeviceList.NodeList[CurIndex].PromptId, NULL); | |
} | |
} | |
CreateDeviceManagerForm(NETWORK_DEVICE_FORM_ID); | |
} else if(QuestionId == QUESTION_NETWORK_DEVICE_ID){ | |
CreateDeviceManagerForm(NETWORK_DEVICE_LIST_FORM_ID); | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Install Boot Manager Menu driver. | |
@param ImageHandle The image handle. | |
@param SystemTable The system table. | |
@retval EFI_SUCEESS Install Boot manager menu success. | |
@retval Other Return error status. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
DeviceManagerUiLibConstructor ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
EFI_STATUS Status; | |
gDeviceManagerPrivate.DriverHandle = NULL; | |
Status = gBS->InstallMultipleProtocolInterfaces ( | |
&gDeviceManagerPrivate.DriverHandle, | |
&gEfiDevicePathProtocolGuid, | |
&mDeviceManagerHiiVendorDevicePath, | |
&gEfiHiiConfigAccessProtocolGuid, | |
&gDeviceManagerPrivate.ConfigAccess, | |
NULL | |
); | |
ASSERT_EFI_ERROR (Status); | |
// | |
// Publish our HII data. | |
// | |
gDeviceManagerPrivate.HiiHandle = HiiAddPackages ( | |
&mDeviceManagerGuid, | |
gDeviceManagerPrivate.DriverHandle, | |
DeviceManagerVfrBin, | |
DeviceManagerUiLibStrings, | |
NULL | |
); | |
ASSERT (gDeviceManagerPrivate.HiiHandle != NULL); | |
// | |
// The device manager form contains a page listing all the network | |
// controllers in the system. This list can only be populated if all | |
// handles have been connected, so do it here. | |
// | |
EfiBootManagerConnectAll (); | |
// | |
// Update boot manager page | |
// | |
CreateDeviceManagerForm (DEVICE_MANAGER_FORM_ID); | |
return EFI_SUCCESS; | |
} | |
/** | |
Unloads the application and its installed protocol. | |
@param ImageHandle Handle that identifies the image to be unloaded. | |
@param SystemTable The system table. | |
@retval EFI_SUCCESS The image has been unloaded. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
DeviceManagerUiLibDestructor( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
EFI_STATUS Status; | |
Status = gBS->UninstallMultipleProtocolInterfaces ( | |
gDeviceManagerPrivate.DriverHandle, | |
&gEfiDevicePathProtocolGuid, | |
&mDeviceManagerHiiVendorDevicePath, | |
&gEfiHiiConfigAccessProtocolGuid, | |
&gDeviceManagerPrivate.ConfigAccess, | |
NULL | |
); | |
ASSERT_EFI_ERROR (Status); | |
HiiRemovePackages (gDeviceManagerPrivate.HiiHandle); | |
return EFI_SUCCESS; | |
} | |