Discuss the development of new homebrew software, tools and libraries.
Moderators: cheriff , TyRaNiD
johnmph
Posts: 119 Joined: Sat Jul 23, 2005 11:48 pm
Post
by johnmph » Fri Mar 24, 2006 7:22 am
I tried some reverse engineering with sceKernelCanReleaseLibrary function.
Here what i found :
Structures (temporary name) :
Code: Select all
typedef struct ModuleLibRelease // Module Library Release
{
u32 unk1; // ?
struct ModuleLibRelease *next; // Next structure
u32 unk2; // ?
u16 unk3; // ?
u16 unk4; // sceKernelCanReleaseLibrary verification (unk4 & 0x8)
} ModuleLibRelease;
typedef struct ModuleLib // Module Library
{
struct ModuleLib *next; // Next structure
u32 unk1[4];
SceLibraryEntryTable *lib; // Library pointer
ModuleLibRelease *release; // ModuleLibRelease pointer
} ModuleLib;
Functions :
mfic, mtic opcode informations based on
http://forums.ps2dev.org/viewtopic.php?t=4598 post
Code: Select all
u32 sceKernelSuspendInterrupts (void)
{
u32 i;
asm(
"mfic %0, $0\n"
"mtic $0, $0\n"
"nop\n" // For uncached (7 nop)
"nop\n"
"nop\n"
"nop\n"
"nop\n"
"nop\n"
"nop\n"
: "=r"(i)
);
return i;
}
void sceKernelResumeInterrupts (u32 i)
{
u32 temp;
asm(
"mtic %1, $0\n"
"nop\n" // For uncached (7 nop)
"nop\n"
"nop\n"
"nop\n"
"nop\n"
"nop\n"
"nop\n"
: "=r"(temp)
: "r"(i)
);
}
u32 sceKernelCanReleaseLibrary (SceLibraryEntryTable *lib)
// Reverse engineering of sceKernelCanReleaseLibrary function
// Return 0x0 if library lib can be release else error code
{
ModuleLib *modLib;
ModuleLibRelease *release;
u32 i;
// Suspend interrupts
i = sceKernelSuspendInterrupts();
modLib = (ModuleLib *) 0x8801AF40; // Address of first structure in 1.50 version
// Browse array
while (modLib)
{
if (modLib->lib == lib) break; // If library found, break
modLib = modLib->next; // Next structure
}
// If not found, exit
if (!(modLib))
{
// Resume interrupts
sceKernelResumeInterrupts(i);
// OK
return 0;
}
// Get the "release array"
release = modLib->release;
// Browse the array
while (release)
{
if (!(release->unk4 & 0x8)) // Error, exit with error message and kprintf
{
kprintf("sceKernelCanReleaseLibrary : %s ...",lib->libname);
// Resume interrupts
sceKernelResumeInterrupts(i);
return 0x8002013E;
}
release = release->next; // Next structure
}
// Resume interrupts
sceKernelResumeInterrupts(i);
// OK
return 0;
}
If you want unload a module which normally can not be unloaded, set modLib->release to NULL (for each library in module).
After you will be able to release the module (stop and unload).
hubevolution
Posts: 32 Joined: Wed Mar 17, 2004 6:59 pm
Post
by hubevolution » Fri Mar 24, 2006 5:08 pm
this will allow module unloading without patching it even if the module has the no_stop flag set on ?
johnmph
Posts: 119 Joined: Sat Jul 23, 2005 11:48 pm
Post
by johnmph » Fri Mar 24, 2006 8:27 pm
hubevolution wrote: this will allow module unloading without patching it even if the module has the no_stop flag set on ?
Yes you can but you must also patch the flag, this is a small function to unload a module :
Code: Select all
u32 modulePatchLibraryForRelease (SceLibraryEntryTable *lib)
{
ModuleLib *modLib;
u32 i;
// Suspend interrups
i = sceKernelSuspendInterrupts();
modLib = (ModuleLib *) 0x8801AF40; // Address of first structure in 1.50 version
// Browse array
while (modLib)
{
if (modLib->lib == lib) break; // If library found, break
modLib = modLib->next; // Next structure
}
// If found, patch release pointer
if (modLib) modLib->release = NULL;
// Resume interrupts
sceKernelResumeInterrupts(i);
// OK
return 0;
}
u32 modulePatchForRelease (const char *name)
{
SceModule *mod;
SceLibraryEntryTable *entryTable, *entryEnd;
// Find module address
mod = sceKernelFindModuleByName(name);
// If bad module
if ((((long) mod) & 0xFF000000) != 0x88000000) return 1;
if ((mod->stub_top - mod->ent_top) < 40) return 1;
// Patch attributes
mod->attribute = 0x1006;
// Find entry table info
entryTable = (SceLibraryEntryTable *) ((u32 *) mod->ent_top);
entryEnd = (SceLibraryEntryTable *) (((u8 *) mod->ent_top) + mod->ent_size);
// Entry loop
while (entryTable < entryEnd)
{
if (entryTable->libname)
{
// Patch library for release
modulePatchLibraryForRelease(entryTable);
}
// Next entry
entryTable = (SceLibraryEntryTable *) (((u32 *) entryTable) + entryTable->len);
}
return 0;
}
u32 moduleUnload (const char *name)
{
SceModule *mod;
SceUID modid;
u32 ret;
// Patch module
modulePatchForRelease(name);
// Find module address
mod = sceKernelFindModuleByName(name);
// If not found, exit
if (!(mod)) return SCE_KERNEL_ERROR_UNKNOWN_MODULE;
// Stop module
modid = mod->modid;
ret = sceKernelStopModule(modid,0,NULL,NULL,NULL);
if (!(ret & 0x80000000)) ret = sceKernelUnloadModule(modid);
return ret;
}
I tried with sceVaudio_driver module and it works.
hubevolution
Posts: 32 Joined: Wed Mar 17, 2004 6:59 pm
Post
by hubevolution » Fri Mar 24, 2006 9:01 pm
well great work at least a clean method to unload modules !
hubevolution
Posts: 32 Joined: Wed Mar 17, 2004 6:59 pm
Post
by hubevolution » Mon Mar 27, 2006 3:54 pm
I tried to unload sysmem.prx (sceSystemMemoryManager) but when I realod it from a simulated flash0: (mounted on the memstick) psp crashes ... I can unload and reload many other modules but sysmem.prx seems that cannot be unloaded ... even tried to do the unload/reload between disabling/reenabling interrupts but no way ... any clue ?
Fanjita
Posts: 217 Joined: Wed Sep 28, 2005 9:31 am
Post
by Fanjita » Mon Mar 27, 2006 7:55 pm
hubevolution wrote: I tried to unload sysmem.prx (sceSystemMemoryManager) but when I realod it from a simulated flash0: (mounted on the memstick) psp crashes ... I can unload and reload many other modules but sysmem.prx seems that cannot be unloaded ... even tried to do the unload/reload between disabling/reenabling interrupts but no way ... any clue ?
PResumably that module holds some state info about the memory allocation in the system, and you'd need to find some way to save / reinject that state into the new module?
hubevolution
Posts: 32 Joined: Wed Mar 17, 2004 6:59 pm
Post
by hubevolution » Mon Mar 27, 2006 8:04 pm
that means that unloading the module will cause the previous memory allocation "tables/infos" to be lost ... and when reloading the module it will start from scratch without knowing that there was previously allocated memory corrupting it and failing access to that when requested ... that sounds realistic !
Mirko-psp
Posts: 6 Joined: Tue Mar 14, 2006 5:15 am
Post
by Mirko-psp » Tue Mar 28, 2006 5:18 am
hey hube ;)
MPH you have load the sysmem.prx on mph gameloader???