extern "C" bool LoadPE(char* filename, char* address, SPEFile* outPEFile) { void* fp = FsOpenFile(filename, 0); outPEFile->dosHeader = (SPEDOSHeader*)address; FsReadFile(fp, (char*)outPEFile->dosHeader, sizeof(SPEDOSHeader)); if (outPEFile->dosHeader->Magic != DOS_HEADER_MAGIC) { CDisplayDriver::PrintString("DOS_HEADER_MAGIC is wrong!"); FsCloseFile(fp); return false; } int dumpsize = outPEFile->dosHeader->HeaderAddress - sizeof(SPEDOSHeader); char* dump = new char[dumpsize]; FsReadFile(fp, dump, dumpsize); delete[] dump; outPEFile->peHeader = (SPEHeader*)(address + outPEFile->dosHeader->HeaderAddress); FsReadFile(fp, (char*)outPEFile->peHeader, sizeof(SPEHeader)); if (outPEFile->peHeader->Magic != PE_HEADER_MAGIC) { CDisplayDriver::PrintString("PE_HEADER_MAGIC is wrong!"); FsCloseFile(fp); return false; } outPEFile->peoHeader = (SPEOptionalHeader*)((char*)outPEFile->peHeader + sizeof(SPEHeader)); FsReadFile(fp, (char*)outPEFile->peoHeader, sizeof(SPEOptionalHeader)); CDisplayDriver::PrintString("%X", outPEFile->peoHeader->SizeOfImage); if (outPEFile->peoHeader->Magic != PE_OPTIONAL_MAGIC_64) { CDisplayDriver::PrintString("PE_OPTIONAL_MAGIC_64 is wrong!"); FsCloseFile(fp); return false; } outPEFile->dataDirectories = (SPEDataDirectories*)((char*)outPEFile->peoHeader + sizeof(SPEOptionalHeader)); FsReadFile(fp, (char*)outPEFile->dataDirectories, sizeof(SPEDataDirectories)); outPEFile->sections = new SPESection*[outPEFile->peHeader->NumberOfSections]; for (unsigned int i = 0; i < outPEFile->peHeader->NumberOfSections; ++i) { SFile* handle = (SFile*)fp; outPEFile->sections[i] = (SPESection*)((char*)outPEFile->dataDirectories + sizeof(SPEDataDirectories) + (i*sizeof(SPESection))); FsReadFile(fp, (char*)outPEFile->sections[i], sizeof(SPESection)); } for (unsigned int i = 0; i < outPEFile->peHeader->NumberOfSections; ++i) { if (outPEFile->sections[i]->SizeOfRawData == 0) { continue; } int dumpsize = outPEFile->sections[i]->PointerToRawData - ((SFile*)fp)->bytesread; char* dump = new char[dumpsize]; FsReadFile(fp, dump, dumpsize); delete[] dump; FsReadFile(fp, (char*)address + outPEFile->sections[i]->VirtualAddress, outPEFile->sections[i]->SizeOfRawData); } outPEFile->exportDirectoryTable = (SPEExportDirectoryTable*)((char*)address + outPEFile->dataDirectories->ExportTable.VirtualAddress); outPEFile->importDirectoryTable = (SPEImportDirectoryTable*)((char*)address + outPEFile->dataDirectories->ImportTable.VirtualAddress); if (*(unsigned long long*)outPEFile->importDirectoryTable) { SPEImportLookupTable* start = (SPEImportLookupTable*)(address + outPEFile->importDirectoryTable->ImportLookupTableRVA); int count = 0; while (*(unsigned long long*)start) { start++; count++; } start = (SPEImportLookupTable*)(address + outPEFile->importDirectoryTable->ImportLookupTableRVA); outPEFile->importLookups = new SPEImportLookupTable*[count]; int i = 0; while (*(unsigned long long*)start) { bool isOrdinal = start->LookupEntry & 0x8000000000000000; if (isOrdinal) { } else { unsigned long long HintNameRVA = start->LookupEntry & ~0x8000000000000000; SPEImportHintNameTable* HintNameTable = (SPEImportHintNameTable*)(address + HintNameRVA); //CDisplayDriver::PrintString("%s", &HintNameTable->Name); count++; } outPEFile->importLookups[i]->LookupEntry = *(unsigned long long*)start; start++; i++; } unsigned long long* startAddr = (unsigned long long*)(address + outPEFile->importDirectoryTable->ImportAddressTableRVA); while (*startAddr) { *startAddr += 0x20000; startAddr++; } } FsCloseFile(fp); return true; }
VOID LoadAndBootBootSector(IN OperatingSystemItem* OperatingSystem, IN USHORT OperatingSystemVersion) { ULONG_PTR SectionId; PCSTR SectionName = OperatingSystem->SystemPartition; CHAR FileName[260]; PFILE FilePointer; ULONG BytesRead; CHAR SettingName[80]; // Find all the message box settings and run them UiShowMessageBoxesInSection(SectionName); // Try to open the operating system section in the .ini file if (!IniOpenSection(SectionName, &SectionId)) { sprintf(SettingName, "Section [%s] not found in freeldr.ini.\n", SectionName); UiMessageBox(SettingName); return; } if (!IniReadSettingByName(SectionId, "BootSectorFile", FileName, sizeof(FileName))) { UiMessageBox("Boot sector file not specified for selected OS!"); return; } FilePointer = FsOpenFile(FileName); if (!FilePointer) { strcat(FileName, " not found."); UiMessageBox(FileName); return; } // Read boot sector if (!FsReadFile(FilePointer, 512, &BytesRead, (void*)0x7c00) || (BytesRead != 512)) { UiMessageBox("Unable to read boot sector."); return; } // Check for validity if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55) { UiMessageBox("Invalid boot sector magic (0xaa55)"); return; } UiUnInitialize("Booting..."); // Don't stop the floppy drive motor when we // are just booting a bootsector, or drive, or partition. // If we were to stop the floppy motor then // the BIOS wouldn't be informed and if the // next read is to a floppy then the BIOS will // still think the motor is on and this will // result in a read error. //DiskStopFloppyMotor(); //DisableA20(); ChainLoadBiosBootSectorCode(); }