/** @file
Device Abstraction: Search device list for a matching device.
Copyright (c) 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include
#include
#include
#include
#include
#include
#include
#include
/** Find a DeviceNode matching DevName or DevProto, or both.
If DevName is NULL, then the device name is not used in the search.
If DevProto is NULL, then the protocol GUID is not used in the search.
If both are NULL, then INVALID_PARAMETER is returned.
If both DevName and DevProto are specified, then both must match.
If both are specified but only one matches, then DEVICE_ERROR is returned.
@param DevName Name of the Device Abstraction to find.
@param DevProto GUID of the Protocol associated with the Device Abstraction.
@param Node Pointer to the pointer to receive the found Device Node's address.
@retval RETURN_SUCCESS The desired Device Node was found.
@retval RETURN_INVALID_PARAMETER Both DevName and DevProto are NULL or Node is NULL.
@retval RETURN_DEVICE_ERROR DevName matched but DevProto did not.
@retval RETURN_NOT_FOUND The desired device was not found.
**/
EFI_STATUS
EFIAPI
__DevSearch(
IN CHAR16 *DevName,
IN GUID *DevProto,
OUT DeviceNode **Node
)
{
RETURN_STATUS Status = RETURN_NOT_FOUND;
DeviceNode *WorkNode;
INT32 DevMatched;
if(((DevName == NULL) && (DevProto == NULL)) || (Node == NULL)) {
Status = RETURN_INVALID_PARAMETER;
}
else {
if(IsListEmpty((LIST_ENTRY *)&daDeviceList)) {
Status = RETURN_NOT_FOUND;
}
else {
/* Traverse the list of Device Nodes hunting for a match */
WorkNode = (DeviceNode *)GetFirstNode((LIST_ENTRY *)&daDeviceList);
do {
/* Use DevMatched to keep track of the three match conditions. */
DevMatched = 0;
if(DevName != NULL) {
++DevMatched;
if(wcsncmp(DevName, WorkNode->DevName, wcslen(WorkNode->DevName)) == 0) {
++DevMatched;
}
}
/* At this point, DevMatched has one of the following values:
0 DevName == NULL, no name comparison
1 DevName did not match WorkNode's name
2 DevName MATCHED
*/
if((DevMatched != 1) && (DevProto != NULL) && (WorkNode->DevProto != NULL)) {
/* Only bother with the GUID comparison if:
* There was NOT a name mismatch
* DevProto is NOT NULL -- there is a GUID to compare
* WorkNode->DevProto is NOT NULL
*/
if(CompareGuid(DevProto, WorkNode->DevProto)) {
// GUIDs matched, we found it
Status = RETURN_SUCCESS;
*Node = WorkNode;
break;
}
else {
// GUIDs did not match
if(DevMatched == 2) {
// Name matched, GUID did not!
Status = RETURN_DEVICE_ERROR;
break; // Don't try any more, we have an internal problem
}
}
}
else {
if(DevMatched == 2) {
// Device Name matched, GUIDs skipped
Status = RETURN_SUCCESS;
*Node = WorkNode;
break;
}
}
// Check the next device in the list
WorkNode = (DeviceNode *)GetNextNode(&daDeviceList, (LIST_ENTRY *)WorkNode);
} while(&daDeviceList != (LIST_ENTRY *)WorkNode);
}
}
return Status;
}