📄 loader.c
字号:
// *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 pageBOOL 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 EXEBOOL 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)) { blockptr = (struct info *)(((ulong)blockptr)+blockptr->size); continue; } dataptr = 0; while ((ulong)currptr < ((ulong)blockptr+blockptr->size)) { curroff = *currptr&0xfff; if (!curroff && !blockptr->rva) { currptr++; continue; } if (!dataptr || (dataptr->o32_rva > blockptr->rva + curroff) || (dataptr->o32_rva + dataptr->o32_vsize <= blockptr->rva + curroff)) { for (loop = 0; loop < eptr->e32_objcnt; loop++) { dataptr = &oarry[loop]; if ((dataptr->o32_rva <= blockptr->rva + curroff) && (dataptr->o32_rva+dataptr->o32_vsize > blockptr->rva + curroff)) break; } } DEBUGCHK(loop != eptr->e32_objcnt); FixupAddress = (LPDWORD)(blockptr->rva - dataptr->o32_rva + curroff + dataptr->o32_realaddr); 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; case IMAGE_REL_BASED_HIGH: // Save the address and go to get REF_LO paired with this one FixupAddressHi = (LPWORD)FixupAddress; MatchedReflo = TRUE; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -