error=abort

// NOTE: THIS MAY NEED TO BE ADJUSTED
// change to reflect the total amount of ram in your system
define /r GetMaxMem()
{
  return 0x10000000; // 256 MB
}
.

define /r GetWord(Addr)
{
  unsigned long data;
  
  if( (Addr & 0x2) == 0 )
  {
    data = dword(Addr);
    data = data & 0xffff;
    //$printf "getword data is %x\n", data$;
    return data;
  }
  else
  {
    data = dword(Addr & 0xfffffffc);
    //data = data >> 16;
    data = data / 0x10000;
    //$printf "getword data is %x (1)\n", data$;
    return data;
  }
}
.

define /r ProcessPE32(imgstart)
unsigned long imgstart;
{
  unsigned long filehdrstart;
  unsigned long debugdirentryrva;
	unsigned long debugtype;
  unsigned long debugrva;
	unsigned long dwarfsig;
  unsigned long baseofcode;
  unsigned long baseofdata;
  unsigned long elfbase;
  char *elfpath;

	$printf "PE32 image found at %x",imgstart$;

	//$printf "PE file hdr offset %x",dword(imgstart+0x3C)$;

  // offset from dos hdr to PE file hdr
  filehdrstart = imgstart + dword(imgstart+0x3C);

  // offset to debug dir in PE hdrs
	//$printf "debug dir is at %x",(filehdrstart+0xA8)$;
	debugdirentryrva = dword(filehdrstart + 0xA8);
  if(debugdirentryrva == 0)
	{
		$printf "no debug dir for image at %x",imgstart$;
	  return;
	}

	//$printf "debug dir entry rva is %x",debugdirentryrva$;

	debugtype = dword(imgstart + debugdirentryrva + 0xc);
  if( (debugtype != 0xdf) && (debugtype != 0x2) )
	{
		$printf "debug type is not dwarf for image at %x",imgstart$;
		$printf "debug type is %x",debugtype$;
		return;
	}
	
	debugrva = dword(imgstart + debugdirentryrva + 0x14);
	dwarfsig = dword(imgstart + debugrva);
	if(dwarfsig != 0x66727764)
	{
		$printf "dwarf debug signature not found for image at %x",imgstart$;
	  return;
	}

  elfpath = (char *)(imgstart + debugrva + 0xc);

  baseofcode = imgstart + dword(filehdrstart + 0x28);
  baseofdata = imgstart + dword(filehdrstart + 0x2c);
 
  if( (baseofcode < baseofdata) && (baseofcode != 0) )
  {
		elfbase = baseofcode;
  }
  else
  {
    elfbase = baseofdata;
  }

	$printf "found path %s",elfpath$;
	$fprintf 50, "load /ni /np /a %s &0x%x\n",elfpath,elfbase$;
}
.

define /r ProcessTE(imgstart)
unsigned long imgstart;
{
  unsigned long strippedsize;
	unsigned long debugdirentryrva;
	unsigned long debugtype;
  unsigned long debugrva;
	unsigned long dwarfsig;
  unsigned long elfbase;
  char *elfpath;

	$printf "TE image found at %x",imgstart$;

  // determine pe header bytes removed to account for in rva references
  //strippedsize = word(imgstart + 0x6);
  //strippedsize = (dword(imgstart + 0x4) & 0xffff0000) >> 16;
  strippedsize = (dword(imgstart + 0x4) & 0xffff0000) / 0x10000;
  strippedsize = strippedsize - 0x28;

	debugdirentryrva = dword(imgstart + 0x20);
  if(debugdirentryrva == 0)
	{
		$printf "no debug dir for image at %x",imgstart$;
	  return;
	}
  debugdirentryrva = debugdirentryrva - strippedsize;

	//$printf "debug dir entry rva is %x",debugdirentryrva$;

	debugtype = dword(imgstart + debugdirentryrva + 0xc);
  if( (debugtype != 0xdf) && (debugtype != 0x2) )
	{
		$printf "debug type is not dwarf for image at %x",imgstart$;
		$printf "debug type is %x",debugtype$;
		return;
	}
	
	debugrva = dword(imgstart + debugdirentryrva + 0x14);
  debugrva = debugrva - strippedsize;
	dwarfsig = dword(imgstart + debugrva);
	if( (dwarfsig != 0x66727764) && (dwarfsig != 0x3031424e) )
	{
		$printf "dwarf debug signature not found for image at %x",imgstart$;
		$printf "found %x", dwarfsig$;
	  return;
	}
	
	if( dwarfsig == 0x66727764 )
	{
		elfpath = (char *)(imgstart + debugrva + 0xc);
    $printf "looking for elf path at 0x%x", elfpath$; 
  }
  else 
  {
    elfpath = (char *)(imgstart + debugrva + 0x10);
    $printf "looking for elf path at 0x%x", elfpath$; 
  }

  // elf base is baseofcode (we hope that for TE images it's not baseofdata)
  elfbase = imgstart + dword(imgstart + 0xc) - strippedsize;

	$printf "found path %s",elfpath$;
	$fprintf 50, "load /ni /np /a %s &0x%x\n",elfpath,elfbase$;
}
.

define /r ProcessFvSection(secstart)
unsigned long secstart;
{
  unsigned long sectionsize;
  unsigned char sectiontype;

	sectionsize = dword(secstart);
  //sectiontype = (sectionsize & 0xff000000) >> 24;
  sectiontype = (sectionsize & 0xff000000) / 0x1000000;
  sectionsize = sectionsize & 0x00ffffff;

	$printf "fv section at %x size %x type %x",secstart,sectionsize,sectiontype$;

	if(sectiontype == 0x10) // PE32
  {
		ProcessPE32(secstart+0x4);
	}
	else if(sectiontype == 0x12) // TE
	{
		ProcessTE(secstart+0x4);	
 	}
}
.

define /r ProcessFfsFile(ffsfilestart)
unsigned long ffsfilestart;
{
  unsigned long ffsfilesize;
  unsigned long ffsfiletype;
  unsigned long secoffset;
  unsigned long secsize;

  //ffsfiletype = byte(ffsfilestart + 0x12);
  ffsfilesize = dword(ffsfilestart + 0x14);
  //ffsfiletype = (ffsfilesize & 0xff000000) >> 24;
  ffsfiletype = (ffsfilesize & 0xff000000) / 0x1000000;
  ffsfilesize = ffsfilesize & 0x00ffffff;

  if(ffsfiletype == 0xff) return;

	$printf "ffs file at %x size %x type %x",ffsfilestart,ffsfilesize,ffsfiletype$;

  secoffset = ffsfilestart + 0x18;

  // loop through sections in file
  while(secoffset < (ffsfilestart + ffsfilesize))
	{
		// process fv section and increment section offset by size
    secsize = dword(secoffset) & 0x00ffffff;
    ProcessFvSection(secoffset);
		secoffset = secoffset + secsize;

	  // align to next 4 byte boundary
    if( (secoffset & 0x3) != 0 )
		{
			secoffset = secoffset + (0x4 - (secoffset & 0x3));
		}
	} // end section loop
}
.

define /r LoadPeiSec()
{
  unsigned long fvbase;
  unsigned long fvlen;
  unsigned long fvsig;
	unsigned long ffsoffset;
  unsigned long ffsfilesize;

  fvbase = FindFv();
	$printf "fvbase %x",fvbase$;

  // get fv signature field
  fvsig = dword(fvbase + 0x28);
  if(fvsig != 0x4856465F)
  {
		$printf "FV does not have proper signature, exiting"$;
    return 0;
  }

	$printf "FV signature found"$;

  $fopen 50, 'C:\loadfiles.inc'$;

  fvlen = dword(fvbase + 0x20);
  
  // first ffs file is after fv header, use headerlength field
  //ffsoffset = (dword(fvbase + 0x30) & 0xffff0000) >> 16;
  ffsoffset = (dword(fvbase + 0x30) & 0xffff0000) / 0x10000;
  ffsoffset = fvbase + GetWord(fvbase + 0x30);

  // loop through ffs files
  while(ffsoffset < (fvbase+fvlen))
	{
		// process ffs file and increment by ffs file size field
 		ProcessFfsFile(ffsoffset);    
 		ffsfilesize = (dword(ffsoffset + 0x14) & 0x00ffffff);
 		if(ffsfilesize == 0)
 		{
 		  break;
 		}
		ffsoffset = ffsoffset + ffsfilesize;
		

		// align to next 8 byte boundary
    if( (ffsoffset & 0x7) != 0 )
		{
			ffsoffset = ffsoffset + (0x8 - (ffsoffset & 0x7));
		}
	  
  } // end fv ffs loop

	$vclose 50$;

}
.

define /r FindSystemTable(TopOfRam)
unsigned long TopOfRam;
{
  unsigned long offset;
  
  $printf "FindSystemTable"$;
  $printf "top of mem is %x",TopOfRam$;
  
  offset = TopOfRam;
  
  // align to highest 4MB boundary
  offset = offset & 0xFFC00000;
  
  // start at top and look on 4MB boundaries for system table ptr structure
  while(offset > 0)
  {
    //$printf "checking %x",offset$;
    //$printf "value is %x",dword(offset)$;
    
    // low signature match
    if(dword(offset) == 0x20494249)
    {
      // high signature match
      if(dword(offset+4) == 0x54535953)
      {
        // less than 4GB?
        if(dword(offset+0x0c) == 0)
        {
          // less than top of ram?
          if(dword(offset+8) < TopOfRam)
          {
            return(dword(offset+8));
          }
        }
      }
    
    }
   
    if(offset < 0x400000) break;
    offset = offset - 0x400000; 
  }
  
  return 0;
}
.

define /r ProcessImage(ImageBase)
unsigned long ImageBase;
{
  $printf "ProcessImage %x", ImageBase$;
}
.

define /r FindDebugInfo(SystemTable)
unsigned long SystemTable;
{
  unsigned long   CfgTableEntries;
  unsigned long   ConfigTable;
  unsigned long   i;
  unsigned long   offset;
  unsigned long   dbghdr;
  unsigned long   dbgentries;
  unsigned long   dbgptr;
  unsigned long   dbginfo;
  unsigned long   loadedimg;
  
  $printf "FindDebugInfo"$;
  
  dbgentries = 0;
  CfgTableEntries = dword(SystemTable + 0x40);
  ConfigTable = dword(SystemTable + 0x44);
  
  $printf "config table is at %x (%d entries)", ConfigTable, CfgTableEntries$;
  
  // now search for debug info entry with guid 49152E77-1ADA-4764-B7A2-7AFEFED95E8B
  //	0x49152E77	0x47641ADA	0xFE7AA2B7	0x8B5ED9FE
  for(i=0; i<CfgTableEntries; i++)
  {
    offset = ConfigTable + (i*0x14);
    if(dword(offset) == 0x49152E77)
    {
      if(dword(offset+4) == 0x47641ADA)
      {
        if(dword(offset+8) == 0xFE7AA2B7)
        {
          if(dword(offset+0xc) == 0x8B5ED9FE)
          {
            dbghdr = dword(offset+0x10);
            dbgentries = dword(dbghdr + 4);
            dbgptr = dword(dbghdr + 8);
          }
        }
      }
    }
  }
  
  if(dbgentries == 0)
  {
    $printf "no debug entries found"$;
    return;
  }
  
  $printf "debug table at %x (%d entries)", dbgptr, dbgentries$;
  
  for(i=0; i<dbgentries; i++)
  {
    dbginfo = dword(dbgptr + (i*4));
    if(dbginfo != 0)
    {
      if(dword(dbginfo) == 1) // normal debug info type
      {
        loadedimg = dword(dbginfo + 4);
        ProcessPE32(dword(loadedimg + 0x20));
      }
    }
  }
}
.

define /r LoadDxe()
{
  unsigned long     maxmem;
  unsigned long     systbl;
  
  $printf "LoadDxe"$;
  
  $fopen 50, 'C:\loadfiles.inc'$;
  
  maxmem = GetMaxMem();
  systbl = FindSystemTable(maxmem);
  if(systbl != 0)
  {
    $printf "found system table at %x",systbl$;
    FindDebugInfo(systbl);
  }
  
  $vclose 50$;
}
.

define /r LoadRuntimeDxe()

{
  unsigned long   maxmem;
  unsigned long   SystemTable;
  unsigned long   CfgTableEntries;
  unsigned long   ConfigTable;
  unsigned long   i;
  unsigned long   offset;
  unsigned long   numentries;
  unsigned long   RuntimeDebugInfo;
  unsigned long   DebugInfoOffset;
  unsigned long   imgbase;
  
  $printf "LoadRuntimeDxe"$;
  
  $fopen 50, 'C:\loadfiles.inc'$;
  
  RuntimeDebugInfo = 0x80000010;
  
  if(RuntimeDebugInfo != 0)
  {
    numentries = dword(RuntimeDebugInfo);
    
    $printf "runtime debug info is at %x (%d entries)", RuntimeDebugInfo, numentries$;
    
    DebugInfoOffset = RuntimeDebugInfo + 0x4;
    for(i=0; i<numentries; i++)
    {
      imgbase = dword(DebugInfoOffset);
      if(imgbase != 0)
      {
        $printf "found image at %x",imgbase$;
        ProcessPE32(imgbase);
      }
      DebugInfoOffset = DebugInfoOffset + 0x4;
    }
  }
  
  $vclose 50$;
}
.
