📄 loader.c
字号:
((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 + -