コード例 #1
0
/**
  Returns the size of a device path in bytes.

  This function returns the size, in bytes, of the device path data structure specified by
  DevicePath including the end of device path node.  If DevicePath is NULL, then 0 is returned.

  @param  DevicePath                 A pointer to a device path data structure.

  @return The size of a device path in bytes.

**/
UINTN
EFIAPI
GlueGetDevicePathSize (
  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath
  )
{
  CONST EFI_DEVICE_PATH_PROTOCOL  *Start;

  if (DevicePath == NULL) {
    return 0;
  }

  //
  // Search for the end of the device path structure
  //
  Start = DevicePath;
  while (!EfiIsDevicePathEnd (DevicePath)) {
    DevicePath = EfiNextDevicePathNode (DevicePath);
  }

  //
  // Compute the size and add back in the size of the end device path structure
  //
  return ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
}
コード例 #2
0
//
// get node count
//
UINTN DevPathGetNodeCount(EFI_DEVICE_PATH_PROTOCOL* devicePath)
{
	if(!devicePath)
		return 0;

	UINTN retValue															= 0;
	for(; !EfiIsDevicePathEnd(devicePath); retValue += 1)
		devicePath															= EfiNextDevicePathNode(devicePath);
	return retValue;
}
コード例 #3
0
//
// get node
//
EFI_DEVICE_PATH_PROTOCOL* DevPathGetNode(EFI_DEVICE_PATH_PROTOCOL* devicePath, UINT8 type, UINT8 subType)
{
	while(!EfiIsDevicePathEnd(devicePath))
	{
		if(EfiDevicePathType(devicePath) == type && devicePath->SubType == subType)
			return devicePath;

		devicePath															= EfiNextDevicePathNode(devicePath);
	}
	return nullptr;
}
コード例 #4
0
//
// check net
//
BOOLEAN DevPathHasMacAddressNode(EFI_DEVICE_PATH_PROTOCOL* devicePath)
{
	while(!EfiIsDevicePathEnd(devicePath))
	{
		if(EfiDevicePathType(devicePath) == MESSAGING_DEVICE_PATH && devicePath->SubType == MSG_MAC_ADDR_DP)
			return TRUE;

		devicePath															= EfiNextDevicePathNode(devicePath);
	}
	return FALSE;
}
コード例 #5
0
//
// get device path size
//
UINTN DevPathGetSize(EFI_DEVICE_PATH_PROTOCOL* devicePath)
{
	if(!devicePath)
		return 0;

	EFI_DEVICE_PATH_PROTOCOL* start											= devicePath;
	while(!EfiIsDevicePathEnd(devicePath))
		devicePath															= EfiNextDevicePathNode(devicePath);

	return ArchConvertPointerToAddress(devicePath) - ArchConvertPointerToAddress(start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
}
コード例 #6
0
//
// get partition number
//
UINT32 DevPathGetPartitionNumber(EFI_DEVICE_PATH_PROTOCOL* devicePath)
{
	while(!EfiIsDevicePathEnd(devicePath))
	{
		if(EfiDevicePathType(devicePath) == MEDIA_DEVICE_PATH && devicePath->SubType == MEDIA_HARDDRIVE_DP)
		{
			HARDDRIVE_DEVICE_PATH* hardDriveDevicePath						= _CR(devicePath, HARDDRIVE_DEVICE_PATH, Header);
			if(hardDriveDevicePath->SignatureType == SIGNATURE_TYPE_GUID && hardDriveDevicePath->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER)
				return hardDriveDevicePath->PartitionNumber;
		}

		devicePath															= EfiNextDevicePathNode(devicePath);
	}
	return static_cast<UINT32>(-1);
}
コード例 #7
0
ファイル: kernel_info.cpp プロジェクト: mathewmerrick/osquery
std::string getCanonicalEfiDevicePath(const CFDataRef& data) {
  std::string path;

  // Iterate through the EFI_DEVICE_PATH_PROTOCOL stacked structs.
  auto bytes = CFDataGetBytePtr((CFDataRef)data);
  size_t length = CFDataGetLength((CFDataRef)data);
  size_t search_offset = 0;

  while ((search_offset + sizeof(EFI_DEVICE_PATH_PROTOCOL)) < length) {
    auto node = (const EFI_DEVICE_PATH_PROTOCOL*)(bytes + search_offset);
    if (EfiIsDevicePathEnd(node)) {
      // End of the EFI device path stacked structs.
      break;
    }

    if (EfiDevicePathNodeLength(node) + search_offset > length) {
      // Malformed EFI device header.
      break;
    }

    // Only support paths and hard drive partitions.
    if (EfiDevicePathType(node) == MEDIA_DEVICE_PATH) {
      if (node->SubType == MEDIA_FILEPATH_DP) {
        for (int i = 0; i < EfiDevicePathNodeLength(node); i += 2) {
          // Strip UTF16 characters to UTF8.
          path += (((char*)(node)) + sizeof(EFI_DEVICE_PATH_PROTOCOL))[i];
        }
      } else if (node->SubType == MEDIA_HARDDRIVE_DP) {
        // Extract the device UUID to later join with block devices.
        auto uuid = ((const HARDDRIVE_DEVICE_PATH*)node)->Signature;
        boost::uuids::uuid hdd_signature = {{
          uuid[3], uuid[2], uuid[1], uuid[0],
          uuid[5], uuid[4],
          uuid[7], uuid[6],
          uuid[8], uuid[9],
          uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15],
        }};
        path += boost::to_upper_copy(boost::uuids::to_string(hdd_signature));
      }
    }

    search_offset += EfiDevicePathNodeLength(node);
  }

  return path;
}
コード例 #8
0
//
// get partition handle by number
//
EFI_HANDLE DevPathGetPartitionHandleByNumber(EFI_DEVICE_PATH_PROTOCOL* referencePath, UINT32 number)
{
	UINTN nodeCount															= DevPathGetNodeCount(referencePath);
	if(!nodeCount)
		return nullptr;

	UINTN count																= 0;
	EFI_HANDLE* handleArray													= nullptr;
	if(EFI_ERROR(EfiBootServices->LocateHandleBuffer(ByProtocol, &EfiBlockIoProtocolGuid, nullptr, &count, &handleArray)))
		return nullptr;

	EFI_HANDLE retValue														= nullptr;
	for(UINTN i = 0; i < count; i ++)
	{
		EFI_HANDLE theHandle												= handleArray[i];
		if(!theHandle)
			continue;

		EFI_DEVICE_PATH_PROTOCOL* devicePath								= DevPathGetDevicePathProtocol(theHandle);
		if(!devicePath)
			continue;

		if(DevPathGetNodeCount(devicePath) != nodeCount)
			continue;

		EFI_DEVICE_PATH_PROTOCOL* pathA										= referencePath;
		EFI_DEVICE_PATH_PROTOCOL* pathB										= devicePath;
		BOOLEAN checkResult													= TRUE;
		for(UINTN i = 0; i < nodeCount && !EfiIsDevicePathEnd(pathA) && !EfiIsDevicePathEnd(pathB); i ++)
		{
			if(EfiDevicePathNodeLength(pathA) != EfiDevicePathNodeLength(pathB))
			{
				checkResult													= FALSE;
				break;
			}

		#if 0
			if(pathA->Type == MESSAGING_DEVICE_PATH && pathA->SubType == MSG_VENDOR_DP && !memcmp(pathA + 1, &EfiDevicePathMessagingSASGuid, sizeof(EFI_GUID)))
			{
				SAS_DEVICE_PATH* sasA										= _CR(pathA, SAS_DEVICE_PATH, Header);
				SAS_DEVICE_PATH* sasB										= _CR(pathB, SAS_DEVICE_PATH, Header);
				if(sasA->SasAddress != sasB->SasAddress || sasA->Lun != sasB->Lun || sasA->RelativeTargetPort != sasB->RelativeTargetPort)
				{
					checkResult												= FALSE;
					break;
				}
			}
		#endif

			if(memcmp(pathA, pathB, EfiDevicePathNodeLength(pathA)))
			{
				checkResult													= FALSE;
				break;
			}
		}
		if(!checkResult)
			continue;

		if(DevPathGetPartitionNumber(devicePath) != number)
			continue;

		retValue															= theHandle;
		break;
	}

	MmFreePool(handleArray);
	return retValue;
}
コード例 #9
0
//
// get utf8 name
//
CHAR8* DevPathExtractFilePathName(EFI_DEVICE_PATH_PROTOCOL* devicePath, BOOLEAN fullPath)
{
	FILEPATH_DEVICE_PATH* startFilePath										= nullptr;
	FILEPATH_DEVICE_PATH* endFilePath										= nullptr;
	UINTN totalLength														= 0;
	while(!EfiIsDevicePathEnd(devicePath))
	{
		if(devicePath->Type == MEDIA_DEVICE_PATH && devicePath->SubType == MEDIA_FILEPATH_DP)
		{
			endFilePath														= _CR(devicePath, FILEPATH_DEVICE_PATH, Header);
			totalLength														+= DevicePathNodeLength(devicePath) - SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(CHAR16);
			if(!startFilePath)
				startFilePath												= endFilePath;
		}
		else if(startFilePath)
		{
			break;
		}

		devicePath															= EfiNextDevicePathNode(devicePath);
	}

	if(!startFilePath)
		return nullptr;

	CHAR16* pathName														= nullptr;
	CHAR16* allocatedPathName												= nullptr;
	UINTN pathLength														= 0;
	if(startFilePath != endFilePath)
	{
		allocatedPathName													= static_cast<CHAR16*>(MmAllocatePool(totalLength));
		if(!allocatedPathName)
			return nullptr;

		pathName															= allocatedPathName;
		while(TRUE)
		{
			UINTN length													= (DevicePathNodeLength(&startFilePath->Header) - SIZE_OF_FILEPATH_DEVICE_PATH) / sizeof(CHAR16);
			for(UINTN i = 0; i < length && startFilePath->PathName[i]; i ++, pathLength ++)
				pathName[pathLength]										= startFilePath->PathName[i];

			if(startFilePath == endFilePath)
				break;

			startFilePath													= _CR(EfiNextDevicePathNode(&startFilePath->Header), FILEPATH_DEVICE_PATH, Header);
		}
	}
	else
	{
		pathName															= startFilePath->PathName;
		pathLength															= (DevicePathNodeLength(&startFilePath->Header) - SIZE_OF_FILEPATH_DEVICE_PATH) / sizeof(CHAR16);
		while(!pathName[pathLength - 1] && pathLength)
			pathLength														-= 1;
	}

	CHAR16* lastDirectory													= nullptr;
	for(UINTN i = 0; i < pathLength && pathName[i]; i ++)
	{
		if(pathName[i] == L'\\' || pathName[i] == L'/')
			lastDirectory													= pathName + i;
	}

	if(lastDirectory && !fullPath)
		lastDirectory														+= 1;
	else
		lastDirectory														= pathName;

	CHAR8* retValue															= BlAllocateUtf8FromUnicode(lastDirectory, pathName + pathLength - lastDirectory);
	if(retValue)
		BlConvertPathSeparator(retValue, '/', '\\');
	if(allocatedPathName)
		MmFreePool(allocatedPathName);
	return retValue;
}
コード例 #10
0
//
// append file path
//
EFI_DEVICE_PATH_PROTOCOL* DevPathAppendLastComponent(EFI_DEVICE_PATH_PROTOCOL* devicePath, CHAR8 CONST* fileName, BOOLEAN replaceLastComponent)
{
	UINTN fileNameLength													= strlen(fileName);
	UINTN length															= DevPathGetSize(devicePath) + (fileNameLength + 1) * sizeof(CHAR16);
	EFI_DEVICE_PATH_PROTOCOL* newDevicePath									= static_cast<EFI_DEVICE_PATH_PROTOCOL*>(MmAllocatePool(length));
	if(!newDevicePath)
		return nullptr;

	EFI_DEVICE_PATH_PROTOCOL* dstDevicePath									= newDevicePath;
	EFI_DEVICE_PATH_PROTOCOL* srcDevicePath									= devicePath;
	FILEPATH_DEVICE_PATH* srcFilePath										= nullptr;
	FILEPATH_DEVICE_PATH* dstFilePath										= nullptr;

	while(!EfiIsDevicePathEnd(srcDevicePath))
	{
		if(EfiDevicePathType(srcDevicePath) == MEDIA_DEVICE_PATH && srcDevicePath->SubType == MEDIA_FILEPATH_DP)
		{
			srcFilePath														= _CR(srcDevicePath, FILEPATH_DEVICE_PATH, Header);
			dstFilePath														= _CR(dstDevicePath, FILEPATH_DEVICE_PATH, Header);
		}

		memcpy(dstDevicePath, srcDevicePath, DevicePathNodeLength(srcDevicePath));
		srcDevicePath														= EfiNextDevicePathNode(srcDevicePath);
		dstDevicePath														= EfiNextDevicePathNode(dstDevicePath);
	}

	if(!srcFilePath || !dstFilePath)
	{
		MmFreePool(newDevicePath);
		return nullptr;
	}

	dstFilePath->Header.Type												= MEDIA_DEVICE_PATH;
	dstFilePath->Header.SubType												= MEDIA_FILEPATH_DP;
	UINTN writePosition														= 0;

	if(replaceLastComponent)
	{
		CHAR16* pathName													= srcFilePath->PathName;
		CHAR16* lastDirectory												= nullptr;
		UINTN pathLength													= (DevicePathNodeLength(&srcFilePath->Header) - SIZE_OF_FILEPATH_DEVICE_PATH) / sizeof(CHAR16);
		for(UINTN i = 0; i < pathLength && pathName[i]; i ++)
		{
			if(pathName[i] == L'\\' || pathName[i] == L'/')
				lastDirectory												= pathName + i;
		}

		if(lastDirectory)
			lastDirectory													+= 1;
		else
			lastDirectory													= pathName;

		writePosition														= lastDirectory - pathName;
	}
	else
	{
		writePosition														= (DevicePathNodeLength(&srcFilePath->Header) - SIZE_OF_FILEPATH_DEVICE_PATH) / sizeof(CHAR16);
		while(!srcFilePath->PathName[writePosition - 1] && writePosition)
			writePosition													-= 1;
	}

	UINTN usedLength														= ArchConvertPointerToAddress(dstFilePath->PathName + writePosition) - ArchConvertPointerToAddress(newDevicePath);
	BlUtf8ToUnicode(fileName, fileNameLength, dstFilePath->PathName + writePosition, (length - usedLength - END_DEVICE_PATH_LENGTH) / sizeof(CHAR16));
	UINTN nodeLength														= SIZE_OF_FILEPATH_DEVICE_PATH + (wcslen(dstFilePath->PathName) + 1) * sizeof(CHAR16);
	SetDevicePathNodeLength(&dstFilePath->Header, nodeLength);
	EFI_DEVICE_PATH_PROTOCOL* endOfPath										= NextDevicePathNode(&dstFilePath->Header);
	SetDevicePathEndNode(endOfPath);
	return newDevicePath;
}