/*
 * PROJECT:         EFI Windows Loader
 * LICENSE:         GPL - See COPYING in the top level directory
 * FILE:            freeldr/winldr/conversion.c
 * PURPOSE:         Physical <-> Virtual addressing mode conversions
 * PROGRAMMERS:     Aleksey Bragin (aleksey@reactos.org)
 */

/* INCLUDES ***************************************************************/

#include <freeldr.h>

//#include <ndk/ldrtypes.h>
#include <debug.h>

DBG_DEFAULT_CHANNEL(WINDOWS);

/* FUNCTIONS **************************************************************/

#ifndef _ZOOM2_
/* Arch-specific addresses translation implementation */
PVOID
VaToPa(PVOID Va)
{
	return (PVOID)((ULONG_PTR)Va & ~KSEG0_BASE);
}

PVOID
PaToVa(PVOID Pa)
{
	return (PVOID)((ULONG_PTR)Pa | KSEG0_BASE);
}
#else
PVOID
VaToPa(PVOID Va)
{
    return Va;
}

PVOID
PaToVa(PVOID Pa)
{
    return Pa;
}
#endif

VOID
List_PaToVa(PLIST_ENTRY ListHeadPa)
{
	PLIST_ENTRY EntryPa, NextPa;

	/* List must be properly initialized */
	ASSERT(ListHeadPa->Flink != 0);
	ASSERT(ListHeadPa->Blink != 0);

	/* Loop the list in physical address space */
	EntryPa = ListHeadPa->Flink;
	while (EntryPa != ListHeadPa)
	{
		/* Save the physical address of the next entry */
		NextPa = EntryPa->Flink;

		/* Convert the addresses of this entry */
		EntryPa->Flink = PaToVa(EntryPa->Flink);
		EntryPa->Blink = PaToVa(EntryPa->Blink);

		/* Go to the next entry */
		EntryPa = NextPa;
	}

	/* Finally convert the list head */
	ListHeadPa->Flink = PaToVa(ListHeadPa->Flink);
	ListHeadPa->Blink = PaToVa(ListHeadPa->Blink);
}

// This function converts only Child->Child, and calls itself for each Sibling
VOID
ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start)
{
	PCONFIGURATION_COMPONENT_DATA Child;
	PCONFIGURATION_COMPONENT_DATA Sibling;

	TRACE("ConvertConfigToVA(Start 0x%X)\n", Start);
	Child = Start;

	while (Child != NULL)
	{
		if (Child->ConfigurationData)
			Child->ConfigurationData = PaToVa(Child->ConfigurationData);

		if (Child->Child)
			Child->Child = PaToVa(Child->Child);

		if (Child->Parent)
			Child->Parent = PaToVa(Child->Parent);

		if (Child->Sibling)
			Child->Sibling = PaToVa(Child->Sibling);

		if (Child->ComponentEntry.Identifier)
			Child->ComponentEntry.Identifier = PaToVa(Child->ComponentEntry.Identifier);

		TRACE("Device 0x%X class %d type %d id '%s', parent %p\n", Child,
			Child->ComponentEntry.Class, Child->ComponentEntry.Type, VaToPa(Child->ComponentEntry.Identifier), Child->Parent);

		// Go through siblings list
		Sibling = VaToPa(Child->Sibling);
		while (Sibling != NULL)
		{
			if (Sibling->ConfigurationData)
				Sibling->ConfigurationData = PaToVa(Sibling->ConfigurationData);

			if (Sibling->Child)
				Sibling->Child = PaToVa(Sibling->Child);

			if (Sibling->Parent)
				Sibling->Parent = PaToVa(Sibling->Parent);

			if (Sibling->Sibling)
				Sibling->Sibling = PaToVa(Sibling->Sibling);

			if (Sibling->ComponentEntry.Identifier)
				Sibling->ComponentEntry.Identifier = PaToVa(Sibling->ComponentEntry.Identifier);

			TRACE("Device 0x%X class %d type %d id '%s', parent %p\n", Sibling,
				Sibling->ComponentEntry.Class, Sibling->ComponentEntry.Type, VaToPa(Sibling->ComponentEntry.Identifier), Sibling->Parent);

			// Recurse into the Child tree
			if (VaToPa(Sibling->Child) != NULL)
				ConvertConfigToVA(VaToPa(Sibling->Child));

			Sibling = VaToPa(Sibling->Sibling);
		}

		// Go to the next child
		Child = VaToPa(Child->Child);
	}
}
