Xbe Loading Improvements

- Rather than copying the entire Xbe into the xbox address space, we
copy only the header
- Only sections marked as 'preload' are loaded at boot time
- All other sections are loaded/unloaded on demand by the running title,
via calls to XLoadSecton/XUnloadSection
- Fixed an off-by-one error in Xbe section name parsing
- Fix an incorrect assumption that section names are always
8 characters null-terminated. They are 9 characters, null padded
This commit is contained in:
Luke Usher 2017-10-17 17:25:03 +01:00
parent 853eea7bdb
commit 4b35db183c
5 changed files with 42 additions and 32 deletions

View File

@ -187,18 +187,18 @@ Xbe::Xbe(const char *x_szFilename)
{
printf("Xbe::Xbe: Reading Section Names...\n");
m_szSectionName = new char[m_Header.dwSections][9];
m_szSectionName = new char[m_Header.dwSections][10];
for(uint32 v=0;v<m_Header.dwSections;v++)
{
printf("Xbe::Xbe: Reading Section Name 0x%.04X...", v);
uint08 *sn = GetAddr(m_SectionHeader[v].dwSectionNameAddr);
memset(m_szSectionName[v], 0, 9);
memset(m_szSectionName[v], 0, 10);
if(sn != 0)
{
for(int b=0;b<8;b++)
for(int b=0;b<9;b++)
{
m_szSectionName[v][b] = sn[b];

View File

@ -222,8 +222,8 @@ class Xbe : public Error
#include "AlignPosfix1.h"
*m_TLS;
// Xbe section names, each 8 bytes max and null terminated
char (*m_szSectionName)[9];
// Xbe section names, stored null terminated
char (*m_szSectionName)[10];
// Xbe sections
uint08 **m_bzSection;
@ -360,4 +360,11 @@ const uint32 XBEIMAGE_MEDIA_TYPE_NONSECURE_HARD_DISK = 0x40000000;
const uint32 XBEIMAGE_MEDIA_TYPE_NONSECURE_MODE = 0x80000000;
const uint32 XBEIMAGE_MEDIA_TYPE_MEDIA_MASK = 0x00FFFFFF;
// section type flags for Xbe
const uint32 XBEIMAGE_SECTION_WRITEABLE = 0x00000001;
const uint32 XBEIMAGE_SECTION_PRELOAD = 0x00000002;
const uint32 XBEIMAGE_SECTION_EXECUTABLE = 0x00000004;
const uint32 XBEIMAGE_SECTION_INSERTFILE = 0x00000008;
const uint32 XBEIMAGE_SECTION_HEAD_PAGE_READONLY = 0x00000010;
const uint32 XBEIMAGE_SECTION_TAIL_PAGE_READONLY = 0x00000020;
#endif

View File

@ -177,7 +177,6 @@ void CxbxLaunchXbe(void(*Entry)())
__try
{
Entry();
}
__except (EmuException(GetExceptionInformation()))
{
@ -503,29 +502,18 @@ void CxbxKrnlMain(int argc, char* argv[])
// Determine memory size accordingly :
SIZE_T memorySize = (g_bIsChihiro ? CHIHIRO_MEMORY_SIZE : XBOX_MEMORY_SIZE);
// Copy over loaded Xbe Header to specified base address
// Copy over loaded Xbe Headers to specified base address
memcpy((void*)CxbxKrnl_Xbe->m_Header.dwBaseAddr, &CxbxKrnl_Xbe->m_Header, sizeof(Xbe::Header));
// Copy over the certificate
memcpy((void*)(CxbxKrnl_Xbe->m_Header.dwBaseAddr + sizeof(Xbe::Header)), CxbxKrnl_Xbe->m_HeaderEx, CxbxKrnl_Xbe->m_ExSize);
// Copy over the library versions
memcpy((void*)CxbxKrnl_Xbe->m_Header.dwLibraryVersionsAddr, CxbxKrnl_Xbe->m_LibraryVersion, CxbxKrnl_Xbe->m_Header.dwLibraryVersions * sizeof(DWORD));
// TODO : Actually, instead of copying from CxbxKrnl_Xbe, we should load the entire Xbe directly into memory, like Dxbx does - see _ReadXbeBlock()
// Verify no section would load outside virtual_memory_placeholder (which would overwrite Cxbx code)
// Load all sections marked as preload using the in-memory copy of the xbe header
xboxkrnl::PXBEIMAGE_SECTION sectionHeaders = (xboxkrnl::PXBEIMAGE_SECTION)CxbxKrnl_Xbe->m_Header.dwSectionHeadersAddr;
for (uint32 i = 0; i < CxbxKrnl_Xbe->m_Header.dwSections; i++) {
xbaddr section_end = CxbxKrnl_Xbe->m_SectionHeader[i].dwVirtualAddr + CxbxKrnl_Xbe->m_SectionHeader[i].dwSizeofRaw;
if (section_end >= XBE_MAX_VA)
{
CxbxPopupMessage("Couldn't load XBE section - please report this!");
return; // TODO : Halt(0);
if ((sectionHeaders[i].Flags & XBEIMAGE_SECTION_PRELOAD) != 0) {
xboxkrnl::XeLoadSection(&sectionHeaders[i]);
}
}
// Load all sections to their requested Virtual Address :
for (uint32 i = 0; i < CxbxKrnl_Xbe->m_Header.dwSections; i++) {
memcpy((void*)CxbxKrnl_Xbe->m_SectionHeader[i].dwVirtualAddr, CxbxKrnl_Xbe->m_bzSection[i], CxbxKrnl_Xbe->m_SectionHeader[i].dwSizeofRaw);
}
// We need to remember a few XbeHeader fields, so we can switch between a valid ExeHeader and XbeHeader :
StoreXbeImageHeader();

View File

@ -35,7 +35,6 @@
#define CXBXKRNL_H
#include "Cxbx.h"
#include "Common/Xbe.h"
#undef FIELD_OFFSET // prevent macro redefinition warnings

View File

@ -43,6 +43,7 @@ namespace xboxkrnl
#include <xboxkrnl/xboxkrnl.h> // For XeImageFileName, etc.
};
#include "CxbxKrnl.h" // For CxbxKrnl_Xbe
#include "Logging.h" // For LOG_FUNC()
#include "EmuKrnlLogging.h"
#include "Emu.h" // For EmuWarning()
@ -76,12 +77,24 @@ XBSYSAPI EXPORTNUM(327) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeLoadSection
LOG_FUNC_ARG(Section)
LOG_FUNC_END;
NTSTATUS ret = STATUS_SUCCESS;
NTSTATUS ret = STATUS_INVALID_HANDLE;
if (Section->SectionReferenceCount++ == 0) {
LOG_INCOMPLETE(); // TODO : Load section - probably lock this too
void* sectionData = CxbxKrnl_Xbe->FindSection((char*)std::string(Section->SectionName, 9).c_str());
if (sectionData != nullptr) {
// If the reference count was zero, load the section
if (Section->SectionReferenceCount == 0) {
// Clear the memory the section requires
memset(Section->VirtualAddress, 0, Section->VirtualSize);
// Copy the section data
memcpy(Section->VirtualAddress, sectionData, Section->FileSize);
}
// Increment the reference count
Section->SectionReferenceCount++;
ret = STATUS_SUCCESS;
}
RETURN(ret);
}
@ -101,15 +114,18 @@ XBSYSAPI EXPORTNUM(328) xboxkrnl::NTSTATUS NTAPI xboxkrnl::XeUnloadSection
LOG_FUNC_ARG(Section)
LOG_FUNC_END;
NTSTATUS ret = STATUS_SUCCESS;
NTSTATUS ret = STATUS_INVALID_PARAMETER;
// If the section was loaded, process it
if (Section->SectionReferenceCount > 0) {
if (--Section->SectionReferenceCount == 0) {
LOG_INCOMPLETE(); // TODO : Unload section - probably lock this too
// Decrement the reference count
Section->SectionReferenceCount -= 1;
// Free the section if necessary
if (Section->SectionReferenceCount == 0) {
memset(Section->VirtualAddress, 0, Section->VirtualSize);
}
}
else
ret = STATUS_INVALID_PARAMETER;
RETURN(ret);
}