//
// 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);
}
Example #2
0
	EFI_RUNTIME_SERVICES* runtimeServicesInThunk							= static_cast<EFI_RUNTIME_SERVICES*>(ArchpThunkCodeStart);
	UINT32 efiTableSize														= sizeof(EFI_SYSTEM_TABLE64) + sizeof(EFI_RUNTIME_SERVICES64);
	efiTableSize															= (efiTableSize + systemTable32->NumberOfTableEntries * sizeof(EFI_CONFIGURATION_TABLE64) + 15) & ~15;
	UINT64* efiMapL4														= Add2Ptr(ArchpThunkDataStart, ArchpThunkDataSize - EFI_PAGE_SIZE, UINT64*);
	EFI_SYSTEM_TABLE64* systemTable64										= Add2Ptr(efiMapL4, -static_cast<INTN>(efiTableSize), EFI_SYSTEM_TABLE64*);
	EFI_RUNTIME_SERVICES64* runtimeServices64								= Add2Ptr(systemTable64, sizeof(EFI_SYSTEM_TABLE64), EFI_RUNTIME_SERVICES64*);
	EFI_CONFIGURATION_TABLE64* configurationTable64							= Add2Ptr(runtimeServices64, sizeof(EFI_RUNTIME_SERVICES64), EFI_CONFIGURATION_TABLE64*);

	//
	// setup system table64
	//
	systemTable64->Hdr.Signature											= EFI_SYSTEM_TABLE_SIGNATURE;
	systemTable64->Hdr.Revision												= EFI_SYSTEM_TABLE_REVISION;
	systemTable64->Hdr.Reserved												= 0;
	systemTable64->Hdr.HeaderSize											= sizeof(EFI_SYSTEM_TABLE64);
	systemTable64->FirmwareVendor											= ArchConvertPointerToAddress(systemTable32->FirmwareVendor) + thunkOffset;
	systemTable64->FirmwareRevision											= systemTable32->FirmwareRevision;
	systemTable64->Padding													= 0;
	systemTable64->ConsoleInHandle											= 0;
	systemTable64->ConIn													= 0;
	systemTable64->ConsoleOutHandle											= 0;
	systemTable64->ConOut													= 0;
	systemTable64->StandardErrorHandle										= 0;
	systemTable64->StdErr													= 0;
	systemTable64->RuntimeServices											= ArchConvertPointerToAddress(runtimeServices64) + thunkOffset;
	systemTable64->BootServices												= 0;
	systemTable64->NumberOfTableEntries										= systemTable32->NumberOfTableEntries;
	systemTable64->ConfigurationTable										= ArchConvertPointerToAddress(configurationTable64) + thunkOffset;

	//
	// setup configuration tables
//
// 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;
}