text: /**
  
    funcs for checking decoded kernel in memory
    
    dmazar
  
  **/
  
  #include <Library/UefiLib.h>
  #include <Library/BaseMemoryLib.h>
  #include <Library/DebugLib.h>
  
  #include "DecodedKernelCheck.h"
  #include "AsmFuncs.h"
  #include "BootArgs.h"
  
  // monitoring AlocatePages
  extern UINT32 gKernelEntry;
  
  typedef struct {
  	char			*segname;
  	unsigned long	vmaddr;
  	long			vmsize;
  	long			filesize;
  	unsigned long	adler32;
  	unsigned char	ssample[8];
  	unsigned char	esample[8];
  } mySegData_t;
  	
  	 
  //from Chameleon:
  // i386:
  mySegData_t mySegData[] = { // segment, vmaddr, vmsize, filesize, adler32
          {"__TEXT", 0x200000, 0x568000, 0x568000, 0x9cea7b0b,
              {0xce, 0xfa, 0xed, 0xfe, 0x07, 0x00, 0x00, 0x00},
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
          },
          {"__DATA", 0x800000, 0x83000, 0x41000, 0x28829ec4,
              {0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74},
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
          },
          {"__INITGDT", 0x106000, 0x1000, 0x1000, 0xfad20d6d,
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
          },
          {"__INITPT", 0x100000, 0x6000, 0x6000, 0xa58b95ca,
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
              {0x83, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00}
          },
          {"__DESC", 0x883000, 0x3000, 0x3000, 0x26fe0f95,
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
          },
          {"__VECTORS", 0x886000, 0x1000, 0x1000, 0xc6ae0a5c,
              {0x14, 0x3c, 0x2c, 0x00, 0x29, 0x3c, 0x2c, 0x00},
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
          },
          {"__HIB", 0x108000, 0x7000, 0x7000, 0x99a0f193,
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
          },
          {"__SLEEP", 0x107000, 0x1000, 0x1000, 0x10000001,
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
          },
          {"__KLD", 0x887000, 0x13000, 0x13000, 0xf6d84329,
              {0x55, 0x89, 0xe5, 0x56, 0x83, 0xec, 0x04, 0xb8},
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
          },
          {"__PRELINK_TEXT", 0x932000, 0x1564000, 0x1564000, 0x874e72cf,
              {0xce, 0xfa, 0xed, 0xfe, 0x07, 0x00, 0x00, 0x00},
              {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
          },
          {"__PRELINK_INFO", 0x1e96000, 0x158000, 0x1575b8, 0x483406a5,
              {0x3c, 0x64, 0x69, 0x63, 0x74, 0x3e, 0x3c, 0x6b},
              {0x3c, 0x2f, 0x64, 0x69, 0x63, 0x74, 0x3e, 0x00}
          },
          {"__LINKEDIT", 0x89a000, 0x97428, 0x97428, 0x7802b8c4,
              {0x04, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00},
              {0x72, 0x65, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x00}
          },
  };
  int mySegDataNum = 12;
  //unsigned long rentry = 0x2c3db0;
  unsigned long rentryx64 = 0x2b8000;
  unsigned long rentry = 0x2b8000;
  unsigned char rentrySample[8] = {0x66, 0x8c, 0xdb, 0x8e, 0xc3, 0x89, 0xc5, 0x89};
  // i386
  // end from Chameleon
  
  /*
   * Adler32 from Chameleon
  */
  
  unsigned long OSSwapHostToBigInt32(unsigned long int32) {
  	return int32;
  }
  
  #define BASE 65521L /* largest prime smaller than 65536 */
  #define NMAX 5000
  // NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
  
  #define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
  #define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
  #define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
  #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
  #define DO16(buf)   DO8(buf,0); DO8(buf,8);
  
  unsigned long Adler32(unsigned char *buf, long len)
  {
  	unsigned long s1 = 1; // adler & 0xffff;
  	unsigned long s2 = 0; // (adler >> 16) & 0xffff;
  	unsigned long result;
  	int k;
  	
  	while (len > 0) {
  		k = len < NMAX ? len : NMAX;
  		len -= k;
  		while (k >= 16) {
  			DO16(buf);
  			buf += 16;
  			k -= 16;
  		}
  		if (k != 0) do {
  			s1 += *buf++;
  			s2 += s1;
  		} while (--k);
  		s1 %= BASE;
  		s2 %= BASE;
  	}
  	result = (s2 << 16) | s1;
  	// result is in big endian
  	return OSSwapHostToBigInt32(result);
  }
  
  
  
  
  void PrintSample(unsigned char *sample, int size) {
  	int i;
  	for (i = 0; i < size; i++) {
  		Print(L" %02x", *sample);
  		sample++;
  	}
  }
  
  
  EFI_STATUS
  EFIAPI
  CheckDecodedSegment (
  	mySegData_t				*sData
  	)
  {
  	EFI_STATUS				Status;
  	//UINTN					i;
  	unsigned char			*p;
  	unsigned long			adler32;
  	long					size;
  	
  	Status = EFI_SUCCESS;
  	
  	p = (UINT8 *)(UINTN) (sData->vmaddr + gRelocBase);
  	size = sData->vmsize > sData->filesize ? sData->filesize : sData->vmsize;
  	adler32 = Adler32(p, size);
  	
  	if (adler32 != sData->adler32) {
  		Status = EFI_CRC_ERROR;
  	}
  	
  	Print(L"Segment: %a, vmaddr=%lx, vmsize=%lx, filesize=%lx, adler32=%lx, our adler=%lx\n",
  		sData->segname, sData->vmaddr, sData->vmsize, sData->filesize, sData->adler32, adler32);
  	//Print(L"cham ssample:"); PrintSample(sData->ssample, 8); Print(L"\n");
  	//Print(L"uefi ssample:"); PrintSample(p, 8); Print(L"\n");
  	
  	return Status;
  }
  
  
  EFI_STATUS
  EFIAPI
  CheckDecodedKernel (
  		VOID
  	)
  {
  	EFI_STATUS				Status;
  	EFI_STATUS				segStatus;
  	int						i;
  	unsigned char			*p;
  	
  	Status = EFI_SUCCESS;
  	
  	for (i = 0; i < mySegDataNum; i++) {
  		segStatus = CheckDecodedSegment(&mySegData[i]);
  		if (EFI_ERROR (segStatus)) {
  			Status = segStatus;
  		}
  	}
  	
  	Print(L"rentry %lx:\ncham sample:", rentry); PrintSample(rentrySample, 8); Print(L"\n");
  	p = (UINT8 *)(UINTN) (rentry + gRelocBase);
  	Print(L"uefi sample:"); PrintSample(p, 8); Print(L"\n");
  	
  	Print(L"CheckDecodedKernel Status=%r\n");
  	return Status;
  }
  
  
  
  VOID
  EFIAPI
  DumpStack (
  		UINT64				RSP
  	)
  {
  	unsigned char			*p;
  	
  	Print(L"DumpStack RSP=%lx\n", RSP);
  	
  	p = (UINT8 *)(UINTN) RSP;
  	PrintSample(p, 64);
  	Print(L"\n");
  	
  	return;
  }
  