844 lines
24 KiB
C
844 lines
24 KiB
C
/** @file
|
|
CrVariableUpdate
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2016, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
#include "CrVariableUpdate.h"
|
|
|
|
CHAR16 *mConInVarName = L"ConIn";
|
|
CHAR16 *mConOutVarName = L"ConOut";
|
|
EFI_GUID *mConVarGuid = &gEfiGlobalVariableGuid;
|
|
CR_DEVICES_SETTING_HEAD_NODE mCrVarDeviceHead;
|
|
|
|
extern UINT32 mCrBaudRateTable[];
|
|
|
|
VOID
|
|
InitializeCrDeviceList (
|
|
VOID
|
|
)
|
|
{
|
|
InitializeListHead (&mCrVarDeviceHead.Link);
|
|
mCrVarDeviceHead.CrDevVarCount = 0;
|
|
}
|
|
|
|
/**
|
|
Status is Exist and Port enable
|
|
|
|
@param
|
|
|
|
@retval
|
|
|
|
**/
|
|
EFI_DEVICE_PATH*
|
|
BuildCrActiveDevicePath (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH_PROTOCOL *DevPath;
|
|
EFI_DEVICE_PATH_PROTOCOL *PrevDevPath;
|
|
UINTN DeviceCount;
|
|
|
|
LIST_ENTRY *Link;
|
|
CR_DEVICES_SETTING_NODE *CrDevNode;
|
|
|
|
DevPath = NULL;
|
|
PrevDevPath = NULL;
|
|
DeviceCount = 0;
|
|
|
|
Link = GetFirstNode (&mCrVarDeviceHead.Link);
|
|
|
|
while (!IsNull (&mCrVarDeviceHead.Link, Link)) {
|
|
CrDevNode = CR_DEVICE_SETTING_FROM_THIS (Link);
|
|
//
|
|
// **Note: The network device is independent control.
|
|
// So didn't add device path here.
|
|
//
|
|
if ( CrDevNode->CrSetting->Exist == FALSE ||
|
|
CrDevNode->CrSetting->Attribute.PortEnable == FALSE
|
|
) {
|
|
Link = GetNextNode (&mCrVarDeviceHead.Link, Link);
|
|
continue;
|
|
}
|
|
DevPath = AppendDevicePathInstance (PrevDevPath, GetDevicePathFromCrDevSetting (CrDevNode->CrSetting));
|
|
CrSafeFreePool (PrevDevPath);
|
|
PrevDevPath = DevPath;
|
|
|
|
CrDevNode->AddIntoConVar = TRUE;
|
|
Link = GetNextNode (&mCrVarDeviceHead.Link, Link);
|
|
}
|
|
return DevPath;
|
|
}
|
|
|
|
BOOLEAN
|
|
IsDevNodeInvalidOrAreadyUsed (
|
|
IN CR_DEVICES_SETTING_NODE *CrDevNode
|
|
)
|
|
{
|
|
if (CrDevNode->CrSetting->ItemType == ASTERISK_ITEM ||
|
|
CrDevNode->CrSetting->ItemType == INVALID_ITEM ||
|
|
CrDevNode->AddIntoConVar == TRUE
|
|
) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
UpdateDevicesExistStatus (
|
|
VOID
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
CR_DEVICES_SETTING_NODE *CrDevNode;
|
|
EFI_DEVICE_PATH *DevPath;
|
|
EFI_HANDLE Handle;
|
|
EFI_STATUS Status;
|
|
|
|
DEBUG ((DEBUG_INFO, "\nCr << %a >>\n", __FUNCTION__));
|
|
|
|
Link = GetFirstNode (&mCrVarDeviceHead.Link);
|
|
while (!IsNull (&mCrVarDeviceHead.Link, Link)) {
|
|
CrDevNode = CR_DEVICE_SETTING_FROM_THIS (Link);
|
|
|
|
if (IsDevNodeInvalidOrAreadyUsed (CrDevNode) ) {
|
|
Link = GetNextNode (&mCrVarDeviceHead.Link, Link);
|
|
continue;
|
|
}
|
|
|
|
DevPath = GetDevicePathFromCrDevSetting (CrDevNode->CrSetting);
|
|
Status = gBS->LocateDevicePath (&gH2OCrUart16550AccessProtocolGuid, &DevPath, &Handle);
|
|
|
|
DEBUG ((DEBUG_INFO, " Not used CrDevVar%d : %s, Locate 16550:%r\n", CrDevNode->VarIndex, CrDevNode->CrSetting->DevName, Status));
|
|
|
|
if (Status == EFI_SUCCESS && CrDevNode->CrSetting->Exist == FALSE) {
|
|
DEBUG ((DEBUG_INFO, " ->Now appear\n"));
|
|
CrDevNode->CrSetting->Exist = TRUE;
|
|
UpdateOrDeleteCrDevVarWithDevInfo (CrDevNode->VarIndex ,CrDevNode->CrSetting);
|
|
|
|
} else if (EFI_ERROR(Status) && CrDevNode->CrSetting->Exist == TRUE){
|
|
DEBUG ((DEBUG_INFO, " ->Now disappear\n"));
|
|
CrDevNode->CrSetting->Exist = FALSE;
|
|
UpdateOrDeleteCrDevVarWithDevInfo (CrDevNode->VarIndex ,CrDevNode->CrSetting);
|
|
}
|
|
|
|
Link = GetNextNode (&mCrVarDeviceHead.Link, Link);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CheckAndSaveConnectResult (
|
|
IN CHAR16 *ConVarName,
|
|
IN EFI_GUID *ConVarGuid
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
CR_DEVICES_SETTING_NODE *CrDevNode;
|
|
EFI_DEVICE_PATH *VarConsole;
|
|
|
|
DEBUG ((DEBUG_INFO, "\nCr << %a >>\n", __FUNCTION__));
|
|
|
|
VarConsole = NULL;
|
|
VarConsole = CommonGetVariableData (ConVarName, ConVarGuid);
|
|
if (VarConsole == NULL) {
|
|
return;
|
|
}
|
|
|
|
Link = GetFirstNode (&mCrVarDeviceHead.Link);
|
|
while (!IsNull (&mCrVarDeviceHead.Link, Link)) {
|
|
CrDevNode = CR_DEVICE_SETTING_FROM_THIS (Link);
|
|
|
|
if (CrDevNode->AddIntoConVar == FALSE) {
|
|
Link = GetNextNode (&mCrVarDeviceHead.Link, Link);
|
|
continue;
|
|
}
|
|
|
|
if (!IsInclusiveOfSelectDevPath (VarConsole, GetDevicePathFromCrDevSetting (CrDevNode->CrSetting))) {
|
|
DEBUG ((EFI_D_INFO, " CrDevVar%d :%s not exist\n", CrDevNode->VarIndex, CrDevNode->CrSetting->DevName));
|
|
CrDevNode->AddIntoConVar = FALSE;
|
|
CrDevNode->CrSetting->Exist = FALSE;
|
|
CrDevNode->CrSetting->Attribute.PortEnable = FALSE;
|
|
//
|
|
// If device not exist and this device not in PCD, then delete this variable
|
|
//
|
|
UpdateOrDeleteCrDevVarWithDevInfo (CrDevNode->VarIndex ,CrDevNode->CrSetting);
|
|
}
|
|
|
|
Link = GetNextNode (&mCrVarDeviceHead.Link, Link);
|
|
}
|
|
CrSafeFreePool (VarConsole);
|
|
}
|
|
|
|
VOID
|
|
CreateCrDeviceVarList (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
CR_DEVICE_SETTING *CrSetting;
|
|
CR_DEVICES_SETTING_NODE *Node;
|
|
EFI_STATUS Status;
|
|
|
|
DEBUG ((DEBUG_INFO, "\nCr << %a >>\n", __FUNCTION__));
|
|
|
|
if (!mCrEnable) {
|
|
mCrVarDeviceHead.CrDevVarCount = 0;
|
|
return;
|
|
}
|
|
|
|
for (Index = 0; Index < MAX_CR_DEVICE_VARIABLE; Index++) {
|
|
Status = GetCrDevInfoFromVariable (Index, &CrSetting);
|
|
if (EFI_ERROR(Status) || CrSetting == NULL) {
|
|
continue;
|
|
}
|
|
|
|
Node = AllocateZeroPool (sizeof (CR_DEVICES_SETTING_NODE));
|
|
if (Node == NULL) {
|
|
CrSafeFreePool (CrSetting);
|
|
ASSERT (0);
|
|
break;
|
|
}
|
|
|
|
Node->CrSetting = CrSetting;
|
|
Node->VarIndex = Index;
|
|
InsertTailList (&mCrVarDeviceHead.Link, &Node->Link);
|
|
mCrVarDeviceHead.CrDevVarCount ++;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FreeCrDevicesVarList (
|
|
VOID
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
CR_DEVICES_SETTING_NODE *CrDevNode;
|
|
|
|
Link = GetFirstNode (&mCrVarDeviceHead.Link);
|
|
|
|
while (!IsNull (&mCrVarDeviceHead.Link, Link)) {
|
|
CrDevNode = CR_DEVICE_SETTING_FROM_THIS (Link);
|
|
Link = RemoveEntryList (Link);
|
|
gBS->FreePool (CrDevNode->CrSetting);
|
|
gBS->FreePool (CrDevNode);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CreateNewActiveCrDevice (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH *NewCrActiveDevice;
|
|
UINTN Size;
|
|
|
|
NewCrActiveDevice = NULL;
|
|
NewCrActiveDevice = BuildCrActiveDevicePath ();
|
|
|
|
Size = (NewCrActiveDevice == NULL)? 0 : GetDevicePathSize (NewCrActiveDevice);
|
|
|
|
CommonSetVariable (
|
|
CR_ACTIVE_VARIABLE_NAME,
|
|
&gH2OCrConfigurationGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
Size,
|
|
NewCrActiveDevice
|
|
);
|
|
CrSafeFreePool (NewCrActiveDevice);
|
|
}
|
|
|
|
BOOLEAN
|
|
IsChildDevicePath (
|
|
IN EFI_DEVICE_PATH *ChildDevPath,
|
|
IN EFI_DEVICE_PATH *ParentDevPath
|
|
)
|
|
{
|
|
UINTN Size;
|
|
|
|
Size = GetDevicePathSize (ParentDevPath) - sizeof (EFI_DEVICE_PATH);
|
|
|
|
if (CompareMem (ChildDevPath, ParentDevPath, Size) == 0) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
IsDevicePathAlreadyInCrDevVar (
|
|
IN EFI_DEVICE_PATH *SubsetPath
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
CR_DEVICES_SETTING_NODE *CrDevNode;
|
|
|
|
Link = GetFirstNode (&mCrVarDeviceHead.Link);
|
|
|
|
while (!IsNull (&mCrVarDeviceHead.Link, Link)) {
|
|
CrDevNode = CR_DEVICE_SETTING_FROM_THIS (Link);
|
|
|
|
if (CrDevNode->CrSetting->ItemType == INVALID_ITEM ||
|
|
CrDevNode->CrSetting->ItemType == ASTERISK_ITEM
|
|
) {
|
|
Link = GetNextNode (&mCrVarDeviceHead.Link, Link);
|
|
continue;
|
|
}
|
|
|
|
if (IsChildDevicePath (GetDevicePathFromCrDevSetting (CrDevNode->CrSetting), SubsetPath)) {
|
|
return TRUE;
|
|
}
|
|
Link = GetNextNode (&mCrVarDeviceHead.Link, Link);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
IsChildDevPathOfAsteriskDevPath (
|
|
IN EFI_DEVICE_PATH *ChildDevPath
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
CR_DEVICES_SETTING_NODE *CrDevNode;
|
|
|
|
Link = GetFirstNode (&mCrVarDeviceHead.Link);
|
|
|
|
while (!IsNull (&mCrVarDeviceHead.Link, Link)) {
|
|
CrDevNode = CR_DEVICE_SETTING_FROM_THIS (Link);
|
|
|
|
if (CrDevNode->CrSetting->ItemType == ASTERISK_ITEM) {
|
|
return IsChildDevicePath (ChildDevPath, GetDevicePathFromCrDevSetting (CrDevNode->CrSetting) );
|
|
}
|
|
Link = GetNextNode (&mCrVarDeviceHead.Link, Link);
|
|
}
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
VOID
|
|
FindAsteriskDevicePath (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE *HandleBuffer;
|
|
EFI_DEVICE_PATH *ChildDevPath;
|
|
UINTN HandleCount;
|
|
UINTN Index;
|
|
H2O_UART_16550_ACCESS_PROTOCOL *Interface;
|
|
|
|
DEBUG ((DEBUG_INFO, "\nCr << %a >>\n", __FUNCTION__));
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gH2OCrUart16550AccessProtocolGuid,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
for (Index = 0; Index < HandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, &ChildDevPath);
|
|
DEBUG ((DEBUG_INFO, " 16550 DevPath: %s\n", ConvertDevicePathToText ((const EFI_DEVICE_PATH *)ChildDevPath, FALSE, TRUE)));
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
if (IsDevicePathAlreadyInCrDevVar (ChildDevPath)) {
|
|
DEBUG ((EFI_D_INFO, " ->AlreadyInCrDevVar\n"));
|
|
continue;
|
|
}
|
|
|
|
if (IsChildDevPathOfAsteriskDevPath (ChildDevPath) == FALSE) {
|
|
DEBUG ((EFI_D_INFO, " ->Not Child DPath Of Asterisk DPath.\n"));
|
|
continue;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (HandleBuffer[Index], &gH2OCrUart16550AccessProtocolGuid, &Interface);
|
|
if (EFI_ERROR(Status)) {
|
|
continue;
|
|
}
|
|
|
|
CreateNewCrDeviceVariable (
|
|
Interface->DeviceInfo->DeviceName,
|
|
ChildDevPath
|
|
);
|
|
|
|
mCrVarDeviceHead.CrDevVarCount++;
|
|
}
|
|
|
|
CrSafeFreePool(HandleBuffer);
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
@param
|
|
|
|
@retval
|
|
|
|
**/
|
|
VOID
|
|
UpdateConInConOutVarFromActiveDevicePath (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH *NewActiveDevPath;
|
|
EFI_DEVICE_PATH *OldActiveDevPath;
|
|
|
|
NewActiveDevPath = NULL;
|
|
OldActiveDevPath = NULL;
|
|
|
|
NewActiveDevPath = BuildCrActiveDevicePath ();
|
|
OldActiveDevPath = CommonGetVariableData (CR_ACTIVE_VARIABLE_NAME, &gH2OCrConfigurationGuid);
|
|
|
|
if (mCrVarDeviceHead.CrDevVarCount == 0 || mCrEnable == FALSE) {
|
|
//
|
|
// Delete Console Redirection device path from ComIn/Out Variable
|
|
//
|
|
if(OldActiveDevPath != NULL) {
|
|
UpdateConsoleVariable (mConInVarName, mConVarGuid, NULL, OldActiveDevPath);
|
|
UpdateConsoleVariable (mConOutVarName, mConVarGuid, NULL, OldActiveDevPath);
|
|
|
|
CommonSetVariable (
|
|
CR_ACTIVE_VARIABLE_NAME,
|
|
&gH2OCrConfigurationGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
0,
|
|
OldActiveDevPath
|
|
);
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// Update Console Redirection device path from ComIn/Out Variable
|
|
//
|
|
if (IsEqualDevicePath (NewActiveDevPath, OldActiveDevPath) == TRUE) {
|
|
UpdateConsoleVariable (mConInVarName, mConVarGuid, NewActiveDevPath, NULL);
|
|
UpdateConsoleVariable (mConOutVarName, mConVarGuid, NewActiveDevPath, NULL);
|
|
|
|
} else {
|
|
UpdateConsoleVariable (mConInVarName, mConVarGuid, NewActiveDevPath, OldActiveDevPath);
|
|
UpdateConsoleVariable (mConOutVarName, mConVarGuid, NewActiveDevPath, OldActiveDevPath);
|
|
|
|
CommonSetVariable (
|
|
CR_ACTIVE_VARIABLE_NAME,
|
|
&gH2OCrConfigurationGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
GetDevicePathSize (NewActiveDevPath),
|
|
NewActiveDevPath
|
|
);
|
|
}
|
|
}
|
|
|
|
CrSafeFreePool (NewActiveDevPath);
|
|
CrSafeFreePool (OldActiveDevPath);
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
UpdateConsoleVariable (
|
|
IN CHAR16 *ConVarName,
|
|
IN EFI_GUID *ConVarGuid,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN DevicePathSize;
|
|
BOOLEAN VarChanged;
|
|
EFI_DEVICE_PATH_PROTOCOL *VarConsole;
|
|
EFI_DEVICE_PATH_PROTOCOL *OldVarConsole;
|
|
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *PrevDevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *VarConsoleInstance;
|
|
EFI_DEVICE_PATH_PROTOCOL *CustomizedInstance;
|
|
|
|
|
|
VarChanged = FALSE;
|
|
VarConsole = NULL;
|
|
DevicePathSize = 0;
|
|
NewDevicePath = NULL;
|
|
Status = EFI_UNSUPPORTED;
|
|
|
|
if (CustomizedConDevicePath == ExclusiveDevicePath) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
VarConsole = CommonGetVariableData (ConVarName, ConVarGuid);
|
|
|
|
OldVarConsole = VarConsole;
|
|
|
|
if (ExclusiveDevicePath != NULL && VarConsole != NULL) {
|
|
while (VarConsole != NULL) {
|
|
|
|
VarConsoleInstance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);
|
|
|
|
if (!IsInclusiveOfSelectDevPath (ExclusiveDevicePath, VarConsoleInstance)) {
|
|
PrevDevicePath = NewDevicePath;
|
|
NewDevicePath = AppendDevicePathInstance (PrevDevicePath, VarConsoleInstance);
|
|
if (PrevDevicePath != NULL)
|
|
gBS->FreePool (PrevDevicePath);
|
|
}
|
|
else {
|
|
VarChanged = TRUE;
|
|
}
|
|
gBS->FreePool (VarConsoleInstance);
|
|
}
|
|
}
|
|
else {
|
|
NewDevicePath = DuplicateDevicePath (VarConsole);
|
|
}
|
|
|
|
while (CustomizedConDevicePath != NULL) {
|
|
|
|
CustomizedInstance = GetNextDevicePathInstance (&CustomizedConDevicePath, &DevicePathSize);
|
|
|
|
if (!IsInclusiveOfSelectDevPath (NewDevicePath, CustomizedInstance)) {
|
|
VarChanged = TRUE;
|
|
PrevDevicePath = NewDevicePath;
|
|
NewDevicePath = AppendDevicePathInstance (PrevDevicePath, CustomizedInstance);
|
|
if (PrevDevicePath != NULL)
|
|
gBS->FreePool (PrevDevicePath);
|
|
}
|
|
|
|
gBS->FreePool (CustomizedInstance);
|
|
|
|
}
|
|
|
|
if (OldVarConsole != NULL) {
|
|
gBS->FreePool (OldVarConsole);
|
|
}
|
|
|
|
//
|
|
// Update the variable of the default console
|
|
//
|
|
if (VarChanged) {
|
|
UINT32 Attributes;
|
|
CHAR16 *StringPtr;
|
|
|
|
StringPtr = ConVarName;
|
|
|
|
//
|
|
// If the variable includes "Dev" at last, we consider
|
|
// it does not support NV attribute.
|
|
//
|
|
while (*StringPtr != L'\0') {
|
|
StringPtr++;
|
|
}
|
|
|
|
if ( (((INTN)((UINTN)StringPtr - (UINTN)ConVarName) / sizeof (CHAR16)) > 3) &&
|
|
(*(StringPtr - 3) == L'D') &&
|
|
(*(StringPtr - 2) == L'e') &&
|
|
(*(StringPtr - 1) == L'v')
|
|
) {
|
|
Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
|
|
} else {
|
|
Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
|
|
}
|
|
|
|
CommonSetVariable (
|
|
ConVarName,
|
|
ConVarGuid,
|
|
Attributes,
|
|
GetDevicePathSize (NewDevicePath),
|
|
NewDevicePath
|
|
);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
|
|
|
/**
|
|
Function compares a device path data structure to that of all the nodes of a
|
|
second device path instance.
|
|
|
|
@param DevPathPool A pointer to a multi-instance device path data
|
|
structure.
|
|
@param Single A pointer to a single-instance device path data
|
|
structure.
|
|
|
|
@retval TRUE If the Single device path is contained within Multi device path.
|
|
@retval FALSE The Single device path is not match within Multi device path.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
IsInclusiveOfSelectDevPath (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevPathPool,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *SelectDevPath
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
|
|
UINTN Size;
|
|
|
|
if (DevPathPool == NULL || SelectDevPath == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
DevicePath = DevPathPool;
|
|
DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
|
|
|
|
//
|
|
// Search for the match of 'Single' in 'DevPathPool'
|
|
//
|
|
while (DevicePathInst != NULL) {
|
|
//
|
|
// If the single device path is found in multiple device paths,
|
|
// return success
|
|
//
|
|
if (CompareMem (SelectDevPath, DevicePathInst, Size) == 0) {
|
|
FreePool (DevicePathInst);
|
|
return TRUE;
|
|
}
|
|
|
|
FreePool (DevicePathInst);
|
|
DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Compare two device path instances
|
|
|
|
@param [in] DevicePath1 The first device path to be compared
|
|
@param [in] DevicePath2 The second device path to be compared
|
|
|
|
@return TRUE The two device paths are the same
|
|
@retval FALSE The two device paths are not the same
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsEqualDevicePath (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
|
|
)
|
|
{
|
|
UINTN DevicePathSize1;
|
|
UINTN DevicePathSize2;
|
|
UINTN Value;
|
|
|
|
DevicePathSize1 = GetDevicePathSize (DevicePath1);
|
|
DevicePathSize2 = GetDevicePathSize (DevicePath2);
|
|
|
|
if (DevicePathSize1 != DevicePathSize2)
|
|
return FALSE;
|
|
|
|
if (DevicePathSize1 == 0)
|
|
return TRUE;
|
|
|
|
Value = CompareMem (DevicePath1, DevicePath2, DevicePathSize1);
|
|
|
|
if (Value == 0)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Verify DataBits value
|
|
|
|
@param [in] DataBits The value which user want to set to DataBits field
|
|
|
|
@return UINT8 The valid DataBits value
|
|
|
|
**/
|
|
UINT8
|
|
VerifyDataBits (
|
|
IN UINT8 DataBits
|
|
)
|
|
{
|
|
if ((DataBits == 7) || (DataBits == 8)) {
|
|
return DataBits;
|
|
} else {
|
|
return 8;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Verify StopBits value
|
|
|
|
@param [in] StopBits The value which user want to set to StopBits field
|
|
|
|
@return UINT8 The valid StopBits value
|
|
|
|
**/
|
|
UINT8
|
|
VerifyStopBits (
|
|
IN UINT8 StopBits
|
|
)
|
|
{
|
|
if ((StopBits == OneStopBit) || (StopBits == TwoStopBits)) {
|
|
return StopBits;
|
|
} else {
|
|
return OneStopBit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Verify Parity value
|
|
|
|
@param [in] Parity The value which user want to set to Parity field
|
|
|
|
@return UINT8 The valid Parity value
|
|
|
|
**/
|
|
UINT8
|
|
VerifyParity (
|
|
IN UINT8 Parity
|
|
)
|
|
{
|
|
if ((Parity >= NoParity) && (Parity <= OddParity)) {
|
|
return Parity;
|
|
} else {
|
|
return NoParity;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
UpdateCrDeviceSetting (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH_PROTOCOL *DevPath;
|
|
EFI_DEVICE_PATH_PROTOCOL *TempPath;
|
|
UART_DEVICE_PATH *Uart;
|
|
CR_DEVICES_SETTING_NODE *CrDevNode;
|
|
EFI_STATUS Status;
|
|
LIST_ENTRY *Link;
|
|
BOOLEAN UpdateCrDev;
|
|
UINT8 Index;
|
|
H2O_SERIAL_ATTRIBS SerialAttribs;
|
|
|
|
DEBUG ((DEBUG_INFO, "\nCr << %a >>\n", __FUNCTION__));
|
|
|
|
DevPath = NULL;
|
|
TempPath = NULL;
|
|
Uart = NULL;
|
|
UpdateCrDev = FALSE;
|
|
|
|
Link = GetFirstNode (&mCrVarDeviceHead.Link);
|
|
|
|
while (!IsNull (&mCrVarDeviceHead.Link, Link)) {
|
|
CrDevNode = CR_DEVICE_SETTING_FROM_THIS (Link);
|
|
|
|
if ((CrDevNode->CrSetting->Exist == FALSE) ||
|
|
(CrDevNode->CrSetting->Attribute.PortEnable == FALSE)) {
|
|
Link = GetNextNode (&mCrVarDeviceHead.Link, Link);
|
|
continue;
|
|
}
|
|
|
|
DevPath = GetDevicePathFromCrDevSetting (CrDevNode->CrSetting);
|
|
DEBUG ((DEBUG_INFO, " %s\n", CrDevNode->CrSetting->DevName));
|
|
DEBUG ((DEBUG_INFO, " Old Setting\n"));
|
|
DEBUG ((DEBUG_INFO, " Exist:%d, ItemType:%d, PortEnable:%d, Global:%d, TerminalType:%d, BaudRate:%d, Parity:%d, DataBits:%d, StopBits:%d, FlowControl:%d\n",
|
|
CrDevNode->CrSetting->Exist,
|
|
CrDevNode->CrSetting->ItemType,
|
|
CrDevNode->CrSetting->Attribute.PortEnable,
|
|
CrDevNode->CrSetting->Attribute.UseGlobalSetting,
|
|
CrDevNode->CrSetting->Attribute.TerminalType,
|
|
CrDevNode->CrSetting->Attribute.BaudRate,
|
|
CrDevNode->CrSetting->Attribute.Parity,
|
|
CrDevNode->CrSetting->Attribute.DataBits,
|
|
CrDevNode->CrSetting->Attribute.StopBits,
|
|
CrDevNode->CrSetting->Attribute.FlowControl
|
|
));
|
|
DEBUG ((DEBUG_INFO, " DevicePath: %s\n", ConvertDevicePathToText ((const EFI_DEVICE_PATH *)DevPath, FALSE, TRUE)));
|
|
|
|
SerialAttribs.Size = sizeof (H2O_SERIAL_ATTRIBS);
|
|
SerialAttribs.BaudRate = mCrBaudRateTable[CrDevNode->CrSetting->Attribute.BaudRate];
|
|
SerialAttribs.Parity = CrDevNode->CrSetting->Attribute.Parity;
|
|
SerialAttribs.StopBits = CrDevNode->CrSetting->Attribute.StopBits;
|
|
SerialAttribs.DataBits = CrDevNode->CrSetting->Attribute.DataBits;
|
|
SerialAttribs.Present = CrDevNode->CrSetting->Attribute.PortEnable;
|
|
SerialAttribs.Timeout = 0;
|
|
SerialAttribs.ReceiveFifoDepth = 0;
|
|
SerialAttribs.TransmitFifoDepth = 0;
|
|
SerialAttribs.DevicePath = DevPath;
|
|
SerialAttribs.MaxDevicePathSize = 60;
|
|
|
|
Status = H2OGetSerialAttribsConfig (&SerialAttribs);
|
|
if (Status != EFI_MEDIA_CHANGED && Status != EFI_UNSUPPORTED) {
|
|
CrDevNode->CrSetting->Exist = FALSE;
|
|
CrDevNode->CrSetting->Attribute.PortEnable = FALSE;
|
|
} else {
|
|
for (Index = 0; mCrBaudRateTable[Index] != 0; Index++) {
|
|
if (SerialAttribs.BaudRate == mCrBaudRateTable[Index]) {
|
|
break;
|
|
}
|
|
}
|
|
CrDevNode->CrSetting->Attribute.BaudRate = (mCrBaudRateTable[Index] == 0) ? --Index : Index;
|
|
CrDevNode->CrSetting->Attribute.Parity = VerifyParity (SerialAttribs.Parity);
|
|
CrDevNode->CrSetting->Attribute.DataBits = VerifyDataBits (SerialAttribs.DataBits);
|
|
CrDevNode->CrSetting->Attribute.StopBits = VerifyStopBits (SerialAttribs.StopBits);
|
|
CrDevNode->CrSetting->Attribute.PortEnable = (SerialAttribs.Present == 0) ? 0 : 1;
|
|
if (Status == EFI_MEDIA_CHANGED) {
|
|
CrDevNode->CrSetting->Attribute.UseGlobalSetting = 0;
|
|
}
|
|
if (CrDevNode->CrSetting->Attribute.PortEnable == FALSE) {
|
|
CrDevNode->CrSetting->Exist = FALSE;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, " New CR Setting\n"));
|
|
DEBUG ((DEBUG_INFO, " Exist:%d, ItemType:%d, PortEnable:%d, Global:%d, TerminalType:%d, BaudRate:%d, Parity:%d, DataBits:%d, StopBits:%d, FlowControl:%d\n",
|
|
CrDevNode->CrSetting->Exist,
|
|
CrDevNode->CrSetting->ItemType,
|
|
CrDevNode->CrSetting->Attribute.PortEnable,
|
|
CrDevNode->CrSetting->Attribute.UseGlobalSetting,
|
|
CrDevNode->CrSetting->Attribute.TerminalType,
|
|
CrDevNode->CrSetting->Attribute.BaudRate,
|
|
CrDevNode->CrSetting->Attribute.Parity,
|
|
CrDevNode->CrSetting->Attribute.DataBits,
|
|
CrDevNode->CrSetting->Attribute.StopBits,
|
|
CrDevNode->CrSetting->Attribute.FlowControl
|
|
));
|
|
|
|
UpdateCrDev = TRUE;
|
|
}
|
|
|
|
if (UpdateCrDev) {
|
|
UpdateOrDeleteCrDevVarWithDevInfo (CrDevNode->VarIndex ,CrDevNode->CrSetting);
|
|
|
|
//
|
|
// Update UART node information
|
|
//
|
|
TempPath = DevPath;
|
|
while (!IsDevicePathEnd(TempPath)) {
|
|
if (TempPath->Type == MESSAGING_DEVICE_PATH && TempPath->SubType == MSG_UART_DP) {
|
|
Uart = (UART_DEVICE_PATH *)TempPath;
|
|
Uart->BaudRate = mCrBaudRateTable[CrDevNode->CrSetting->Attribute.BaudRate];
|
|
Uart->DataBits = CrDevNode->CrSetting->Attribute.DataBits;
|
|
Uart->StopBits = CrDevNode->CrSetting->Attribute.StopBits;
|
|
Uart->Parity = CrDevNode->CrSetting->Attribute.Parity;
|
|
break;
|
|
}
|
|
TempPath = NextDevicePathNode(TempPath);
|
|
}
|
|
DEBUG ((DEBUG_INFO, " New DevicePath: %s\n", ConvertDevicePathToText (GetDevicePathFromCrDevSetting (CrDevNode->CrSetting), FALSE, TRUE)));
|
|
|
|
UpdateCrDev = FALSE;
|
|
}
|
|
|
|
Link = GetNextNode (&mCrVarDeviceHead.Link, Link);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|