⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader.c

📁 可用于嵌入式编程学习
💻 C
📖 第 1 页 / 共 5 页
字号:
   ((cond)?(_NKDbgPrintfW printf_exp),1:0)

//extern int NKwvsprintfW(LPWSTR lpOut, LPCWSTR lpFmt, va_list lpParms, int maxchars);
static VOID _NKvDbgPrintfW(LPCWSTR lpszFmt, va_list lpParms) {
	static WCHAR rgchBuf[384];
	NKwvsprintfW(rgchBuf, lpszFmt, lpParms, sizeof(rgchBuf)/sizeof(WCHAR));
	OutputDebugStringW(rgchBuf);
}

static void _NKDbgPrintfW(LPCWSTR lpszFmt, ...)  {
    va_list arglist;
    va_start(arglist, lpszFmt);
    _NKvDbgPrintfW(lpszFmt, arglist);
    va_end(arglist);
}

#endif	// SHIP_BUILD

void KernelFindMemory(void) {
	ROMChain_t *pList;
	// *MUST* make the pointer uncached ( thus or in 0x20000000)
	if (OEMRomChain) {
		pList = OEMRomChain;
		while (pList->pNext)
			pList = pList->pNext;
		pList->pNext = ROMChain;
		ROMChain = OEMRomChain;
	}
	LogPtr = (fslog_t *)(pTOC->ulRAMFree | 0x20000000);
	RTLMSG(1,(L"Booting Windows CE version %d.%2.2d\r\n",CE_VERSION_MAJOR,CE_VERSION_MINOR));
	if (LogPtr->version != CURRENT_FSLOG_VERSION) {
		RTLMSG(1,(L"\r\nOld or invalid version stamp in kernel structures - starting clean!\r\n"));
		LogPtr->magic1 = LogPtr->magic2 = 0;
		LogPtr->version = CURRENT_FSLOG_VERSION;
	}
	if (LogPtr->magic1 != LOG_MAGIC) {
		DWORD fspages, memst, memlen, mainpages, secondpages;
		mainpages = (PAGEALIGN_DOWN(MainMemoryEndAddress) - PAGEALIGN_UP(pTOC->ulRAMFree))/PAGE_SIZE - 4096/PAGE_SIZE;
		LogPtr->fsmemblk[0].startptr = PAGEALIGN_UP(pTOC->ulRAMFree) + 4096;
		LogPtr->fsmemblk[0].extension = PAGEALIGN_UP(mainpages);
		mainpages -= LogPtr->fsmemblk[0].extension/PAGE_SIZE;
		LogPtr->fsmemblk[0].length = mainpages * PAGE_SIZE;
		LogPtr->fsmemblk[1].startptr = 0;
		LogPtr->fsmemblk[1].length = 0;
		LogPtr->fsmemblk[1].extension = 0;
		LogPtr->magic2 = 0;
		if (OEMGetExtensionDRAM(&memst,&memlen) && (memlen > (memst - PAGEALIGN_UP(memst)))) {
			memlen -= (PAGEALIGN_UP(memst) - memst);
			memst = PAGEALIGN_UP(memst);
			memlen = PAGEALIGN_DOWN(memlen);
			secondpages = memlen/PAGE_SIZE;
			LogPtr->fsmemblk[1].startptr = memst;
			LogPtr->fsmemblk[1].extension = PAGEALIGN_UP(secondpages);
			secondpages -= LogPtr->fsmemblk[1].extension/PAGE_SIZE;
			LogPtr->fsmemblk[1].length = secondpages * PAGE_SIZE;
		} else
			secondpages = 0;
		fspages = CalcFSPages(mainpages+secondpages);
		if (fspages * PAGE_SIZE > MAX_FILESYSTEM_HEAP_SIZE)
			fspages = MAX_FILESYSTEM_HEAP_SIZE/PAGE_SIZE;
		RTLMSG(1,(L"Configuring: Primary pages: %d, Secondary pages: %d, Filesystem pages = %d\r\n",
			mainpages,secondpages,fspages));

		LogPtr->pFSList = 0;

		fspages = CarveMem((LPBYTE)LogPtr->fsmemblk[0].startptr,LogPtr->fsmemblk[0].extension,LogPtr->fsmemblk[0].length,fspages);	
		fspages = CarveMem((LPBYTE)LogPtr->fsmemblk[1].startptr,LogPtr->fsmemblk[1].extension,LogPtr->fsmemblk[1].length,fspages);	
		SC_CacheSync(0);
		LogPtr->magic1 = LOG_MAGIC;
RTLMSG(1,(L"\r\nBooting kernel with clean memory configuration:\r\n"));
	} else {
RTLMSG(1,(L"\r\nBooting kernel with existing memory configuration:\r\n"));
	}
RTLMSG(1,(L"First : %8.8lx start, %8.8lx extension, %8.8lx length\r\n",
	LogPtr->fsmemblk[0].startptr,LogPtr->fsmemblk[0].extension,LogPtr->fsmemblk[0].length));
RTLMSG(1,(L"Second: %8.8lx start, %8.8lx extension, %8.8lx length\r\n",
	LogPtr->fsmemblk[1].startptr,LogPtr->fsmemblk[1].extension,LogPtr->fsmemblk[1].length));
	LogPtr->pKList = 0;
	MemoryInfo.pKData = (LPVOID)pTOC->ulRAMStart;
	MemoryInfo.pKEnd  = (LPVOID)MainMemoryEndAddress;
	if (LogPtr->fsmemblk[1].length) {
		if (LogPtr->fsmemblk[1].startptr < (DWORD)MemoryInfo.pKData)
			MemoryInfo.pKData = (LPVOID)LogPtr->fsmemblk[1].startptr;
		if (LogPtr->fsmemblk[1].startptr + LogPtr->fsmemblk[1].extension + LogPtr->fsmemblk[1].length > (DWORD)MemoryInfo.pKEnd)
			MemoryInfo.pKEnd = (LPVOID)(LogPtr->fsmemblk[1].startptr + LogPtr->fsmemblk[1].extension + LogPtr->fsmemblk[1].length);
	}
	MemoryInfo.cFi = 0;
	MemoryInfo.pFi = &FreeInfo[0];
	if (LogPtr->fsmemblk[1].length) {
		FreeInfo[MemoryInfo.cFi].pUseMap = (LPBYTE)LogPtr->fsmemblk[1].startptr;
		memset((LPVOID)LogPtr->fsmemblk[1].startptr,0,LogPtr->fsmemblk[1].extension);
		FreeInfo[MemoryInfo.cFi].paStart = GetPFN(LogPtr->fsmemblk[1].startptr+LogPtr->fsmemblk[1].extension-PAGE_SIZE)+PFN_INCR;
		FreeInfo[MemoryInfo.cFi].paEnd = FreeInfo[MemoryInfo.cFi].paStart + PFN_INCR * (LogPtr->fsmemblk[1].length/PAGE_SIZE);
		MemoryInfo.cFi++;
	}
	if (LogPtr->fsmemblk[0].length) {
		FreeInfo[MemoryInfo.cFi].pUseMap = (LPBYTE)LogPtr->fsmemblk[0].startptr;
		memset((LPVOID)LogPtr->fsmemblk[0].startptr,0,LogPtr->fsmemblk[0].extension);
		FreeInfo[MemoryInfo.cFi].paStart = GetPFN(LogPtr->fsmemblk[0].startptr+LogPtr->fsmemblk[0].extension-PAGE_SIZE)+PFN_INCR;
		FreeInfo[MemoryInfo.cFi].paEnd = FreeInfo[MemoryInfo.cFi].paStart + PFN_INCR * (LogPtr->fsmemblk[0].length/PAGE_SIZE);
		MemoryInfo.cFi++;
	}
	if (MemoryInfo.cFi != 2)
		memset(&FreeInfo[1],0,sizeof(FreeInfo[1]));
	GrabFSPages();
	KInfoTable[KINX_GWESHEAPINFO] = 0;
	KInfoTable[KINX_TIMEZONEBIAS] = 0;
}

// Relocate a page

BOOL RelocatePage(e32_lite *eptr, o32_lite *optr, ulong BasePtr, ulong BaseAdj, DWORD pMem, DWORD pData, DWORD prevdw) {
	DWORD Comp1, Comp2;
#if defined(MIPS16SUPPORT)
	DWORD PrevPage;
#endif
	struct info *blockptr, *blockstart;
	ulong blocksize;
	LPDWORD FixupAddress;
#ifndef x86
	LPWORD FixupAddressHi;
	BOOL MatchedReflo=FALSE;
#endif
	DWORD FixupValue;
	LPWORD currptr;
	DWORD offset;
	LeaveCriticalSection(&PagerCS);
	if (!(blocksize = eptr->e32_unit[FIX].size)) { // No relocations
		EnterCriticalSection(&PagerCS);
		return TRUE;
	}
	blockstart = blockptr = (struct info *)(ZeroPtr(BasePtr)+BaseAdj+eptr->e32_unit[FIX].rva);
	if (BaseAdj != ProcArray[0].dwVMBase)
		BaseAdj = 0;	// for processes
	DEBUGMSG(ZONE_LOADER1,(TEXT("Relocations: BasePtr = %8.8lx, BaseAdj = %8.8lx, VBase = %8.8lx, pMem = %8.8lx, pData = %8.8lx\r\n"),
		BasePtr,BaseAdj, eptr->e32_vbase, pMem, pData));
	if (!(offset = BasePtr - BaseAdj - eptr->e32_vbase)) {
		EnterCriticalSection(&PagerCS);
		return TRUE;                                                    // no adjustment needed
	}
	DEBUGMSG(ZONE_LOADER1,(TEXT("RelocatePage: Offset is %8.8lx\r\n"),offset));
	if ((ZeroPtr(pMem) >= ZeroPtr(BasePtr+eptr->e32_unit[FIX].rva)) &&
		(ZeroPtr(pMem) < ZeroPtr(BasePtr+eptr->e32_unit[FIX].rva+eptr->e32_unit[FIX].size))) {
		EnterCriticalSection(&PagerCS);
		return TRUE;
	}
	while (((ulong)blockptr < (ulong)blockstart + blocksize) && blockptr->size) {
		currptr = (LPWORD)(((ulong)blockptr)+sizeof(struct info));
		if ((ulong)currptr >= ((ulong)blockptr+blockptr->size)) {
			blockptr = (struct info *)(((ulong)blockptr)+blockptr->size);
			continue;
		}
#if defined(x86) || defined(MIPS16SUPPORT)
#define RELOC_LIMIT 8192
#else
#define RELOC_LIMIT 4096
#endif
		if ((ZeroPtr(BasePtr+blockptr->rva) > ZeroPtr(pMem)) || (ZeroPtr(BasePtr+blockptr->rva)+RELOC_LIMIT <= ZeroPtr(pMem))) {
			blockptr = (struct info *)(((ulong)blockptr)+blockptr->size);
			continue;
		}
		goto fixuppage;
	}
	EnterCriticalSection(&PagerCS);
	return TRUE;
fixuppage:
	DEBUGMSG(ZONE_LOADER1,(L"Fixing up %8.8lx %8.8lx, %8.8lx\r\n",blockptr->rva,optr->o32_rva,optr->o32_realaddr));
	while ((ulong)currptr < ((ulong)blockptr+blockptr->size)) {
#ifdef x86
		Comp1 = ZeroPtr(pMem);
		Comp2 = ZeroPtr(BasePtr + blockptr->rva);
		Comp1 = (Comp2 + 0x1000 == Comp1) ? 1 : 0;
#else
		Comp1 = ZeroPtr(pMem) - ZeroPtr(BasePtr + blockptr->rva);
		Comp2 = (DWORD)(*currptr&0xfff);
#if defined(MIPS16SUPPORT)
		// Comp1 is relative start of page being relocated
		// Comp2 is relative address of fixup
		// For MIPS16 jump, deal with fixups on this page or the preceding page
		// For all other fixups, deal with this page only
		if (*currptr>>12 == IMAGE_REL_BASED_MIPS_JMPADDR16) {
			if ((Comp1 > Comp2 + PAGE_SIZE) || (Comp1 + PAGE_SIZE <= Comp2)) {
				currptr++;
				continue;
			}
			// PrevPage: is fixup located on the page preceding the one being relocated?
			PrevPage = (Comp1 > Comp2);
			// Comp1: is fixup located in the block preceding the one that contains the current page?
			Comp1 = PrevPage && ((Comp1 & 0xfff) == 0);
		} else {
#endif
			if ((Comp1 > Comp2) || (Comp1 + PAGE_SIZE <= Comp2)) {
				if (*currptr>>12 == IMAGE_REL_BASED_HIGHADJ)
					currptr++;
				currptr++;
				continue;
			}
#if defined(MIPS16SUPPORT)
			// Comp1: is fixup located in the block preceding the one that contains the current page? (No.)
			Comp1 = 0;
		}
#endif
#endif
#if defined(x86) || defined(MIPS16SUPPORT)
		FixupAddress = (LPDWORD)(((pData&0xfffff000) + (*currptr&0xfff)) - 4096*Comp1);
#else
		FixupAddress = (LPDWORD)((pData&0xfffff000) + (*currptr&0xfff));
#endif
		DEBUGMSG(ZONE_LOADER2,(TEXT("type %d, low %8.8lx, page %8.8lx, addr %8.8lx, op %8.8lx\r\n"),
			(*currptr>>12)&0xf, (*currptr)&0x0fff,blockptr->rva,FixupAddress, *FixupAddress));
		switch (*currptr>>12) {
			case IMAGE_REL_BASED_ABSOLUTE: // Absolute - no fixup required.
				break;
#ifdef x86
			case IMAGE_REL_BASED_HIGHLOW: // Word - (32-bits) relocate the entire address.
				if (Comp1 && (((DWORD)FixupAddress & 0xfff) > 0xffc)) {
					switch ((DWORD)FixupAddress & 0x3) {
						case 1:
							FixupValue = (prevdw>>8) + (*((LPBYTE)FixupAddress+3) <<24 ) + offset;
							*((LPBYTE)FixupAddress+3) = (BYTE)(FixupValue >> 24);
							break;
						case 2:
							FixupValue = (prevdw>>16) + (*((LPWORD)FixupAddress+1) << 16) + offset;
							*((LPWORD)FixupAddress+1) = (WORD)(FixupValue >> 16);
							break;
						case 3:
							FixupValue = (prevdw>>24) + ((*(LPDWORD)((LPBYTE)FixupAddress+1)) << 8) + offset;
							*(LPWORD)((LPBYTE)FixupAddress+1) = (WORD)(FixupValue >> 8);
							*((LPBYTE)FixupAddress+3) = (BYTE)(FixupValue >> 24);
							break;
					}
				} else if (!Comp1) {
					if (((DWORD)FixupAddress & 0xfff) > 0xffc) {
						switch ((DWORD)FixupAddress & 0x3) {
							case 1:
								FixupValue = *(LPWORD)FixupAddress + (((DWORD)*((LPBYTE)FixupAddress+2))<<16) + offset;
								*(LPWORD)FixupAddress = (WORD)FixupValue;
								*((LPBYTE)FixupAddress+2) = (BYTE)(FixupValue>>16);
								break;
							case 2:
							    *(LPWORD)FixupAddress += (WORD)offset;
								break;
							case 3:
							    *(LPBYTE)FixupAddress += (BYTE)offset;
							    break;
						}
					} else
					    *FixupAddress += offset;
				}
			    break;
#else
			case IMAGE_REL_BASED_HIGH: // Save the address and go to get REF_LO paired with this one
				FixupAddressHi = (LPWORD)FixupAddress;
				MatchedReflo = TRUE;
				break;
			case IMAGE_REL_BASED_LOW: // Low - (16-bit) relocate high part too.
				if (MatchedReflo) {
					FixupValue = (DWORD)(long)((*FixupAddressHi) << 16) +
						*(LPWORD)FixupAddress + offset;
					*FixupAddressHi = (short)((FixupValue + 0x8000) >> 16);
					MatchedReflo = FALSE;
				} else
					FixupValue = *(short *)FixupAddress + offset;
				*(LPWORD)FixupAddress = (WORD)(FixupValue & 0xffff);
			    break;
			case IMAGE_REL_BASED_HIGHLOW: // Word - (32-bits) relocate the entire address.
					if ((DWORD)FixupAddress & 0x3)
					    *(UNALIGNED DWORD *)FixupAddress += (DWORD)offset;
					else
					    *FixupAddress += (DWORD)offset;
			    break;
			case IMAGE_REL_BASED_HIGHADJ: // 32 bit relocation of 16 bit high word, sign extended
				DEBUGMSG(ZONE_LOADER2,(TEXT("Grabbing extra data %8.8lx\r\n"),*(currptr+1)));
				*(LPWORD)FixupAddress += (WORD)((*(short *)(++currptr)+offset+0x8000)>>16);
				break;
			case IMAGE_REL_BASED_MIPS_JMPADDR: // jump to 26 bit target (shifted left 2)
			    FixupValue = ((*FixupAddress)&0x03ffffff) + (offset>>2);
				*FixupAddress = (*FixupAddress & 0xfc000000) | (FixupValue & 0x03ffffff);
				break;
#if defined(MIPS16SUPPORT)
			case IMAGE_REL_BASED_MIPS_JMPADDR16: // MIPS16 jal/jalx to 26 bit target (shifted left 2)
				if (PrevPage && (((DWORD)FixupAddress & (PAGE_SIZE-1)) == PAGE_SIZE-2)) {
					// Relocation is on previous page, crossing into the current one
					// Do this page's portion == last 2 bytes of jal/jalx == least-signif 16 bits of address
					*((LPWORD)FixupAddress+1) += (WORD)(offset >> 2);
					break;
				} else if (!PrevPage) {
					// Relocation is on this page. Put the most-signif bits in FixupValue
					FixupValue = (*(LPWORD)FixupAddress) & 0x03ff;
					FixupValue = ((FixupValue >> 5) | ((FixupValue & 0x1f) << 5)) << 16;
					if (((DWORD)FixupAddress & (PAGE_SIZE-1)) == PAGE_SIZE-2) {
						// We're at the end of the page. prevdw has the 2 bytes we peeked at on the next page,
						// so use them instead of loading them from FixupAddress+1
						FixupValue |= (WORD)prevdw;
						FixupValue += offset >> 2;
					} else {
						// All 32 bits are on this page. Go ahead and fixup last 2 bytes
						FixupValue |= *((LPWORD)FixupAddress+1);
						FixupValue += offset >> 2;
						*((LPWORD)FixupAddress+1) = (WORD)(FixupValue & 0xffff);
					}
					// In either case, we now have the right bits for the upper part of the address
					// Rescramble them and put them in the first 2 bytes of the fixup
					FixupValue = (FixupValue >> 16) & 0x3ff;
					*(LPWORD)FixupAddress = (WORD)((*(LPWORD)FixupAddress & 0xfc00) | (FixupValue >> 5) | ((FixupValue & 0x1f) << 5));
			    }
			    break;
#endif
#endif
			default :
				DEBUGMSG(ZONE_LOADER1,(TEXT("Not doing fixup type %d\r\n"),*currptr>>12));
				DEBUGCHK(0);
				break;
		}
		DEBUGMSG(ZONE_LOADER2,(TEXT("reloc complete, new op %8.8lx\r\n"),*FixupAddress));
		currptr++;
	}
#if defined(x86) || defined(MIPS16SUPPORT)
	if (Comp1) {
		blockptr = (struct info *)(((ulong)blockptr)+blockptr->size);
		if (((ulong)blockptr < (ulong)blockstart + blocksize) && blockptr->size) {
			currptr = (LPWORD)(((ulong)blockptr)+sizeof(struct info));
			if ((ulong)currptr < ((ulong)blockptr+blockptr->size))
				if ((ZeroPtr(BasePtr+blockptr->rva) <= ZeroPtr(pMem)) && (ZeroPtr(BasePtr+blockptr->rva)+4096 > ZeroPtr(pMem)))
					goto fixuppage;
		}
	}
#endif
	EnterCriticalSection(&PagerCS);
	return TRUE;
}

// Relocate a DLL or EXE

BOOL Relocate(e32_lite *eptr, o32_lite *oarry, ulong BasePtr, ulong BaseAdj) {
	o32_lite *dataptr;
	struct info *blockptr, *blockstart;
	ulong blocksize;
	LPDWORD FixupAddress;
	LPWORD FixupAddressHi, currptr;
	WORD curroff;
	DWORD FixupValue, offset;
	BOOL MatchedReflo=FALSE;
	int loop;

	if (!(blocksize = eptr->e32_unit[FIX].size)) // No relocations
		return TRUE;

	DEBUGMSG(ZONE_LOADER1,(TEXT("Relocations: BasePtr = %8.8lx, BaseAdj = %8.8lx, VBase = %8.8lx\r\n"),
		BasePtr,BaseAdj, eptr->e32_vbase));
	if (!(offset = BasePtr - BaseAdj - eptr->e32_vbase))
		return TRUE;                                                    // no adjustment needed
	DEBUGMSG(ZONE_LOADER1,(TEXT("Relocate: Offset is %8.8lx\r\n"),offset));
	blockstart = blockptr = (struct info *)(BasePtr+eptr->e32_unit[FIX].rva);
	while (((ulong)blockptr < (ulong)blockstart + blocksize) && blockptr->size) {
		currptr = (LPWORD)(((ulong)blockptr)+sizeof(struct info));
		if ((ulong)currptr >= ((ulong)blockptr+blockptr->size)) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -