 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
Cpasjuste
Joined: 29 May 2005 Posts: 214
|
Posted: Fri May 16, 2008 6:34 pm Post subject: sceKernelAllocPartitionMemory 64b aligned ? |
|
|
Hi, i'm not sure how to 64b align an allocation made with "sceKernelAllocPartitionMemory".
I want to use the "sceKernelLoadModuleBuffer" function from a kernel mode module, so i need to extract and read the binary (data.psp) into user memory with sceKernelAllocPartitionMemory, then load it. Some help would be great.
Here is the non-working code i writed for now, crashing when the module is loaded :
main.c :
| Code: |
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* main.c - Basic ELF template
*
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
*
* $Id: main.c 1888 2006-05-01 08:47:04Z tyranid $
* $HeadURL$
*/
#include <pspkernel.h>
#include <pspdebug.h>
#include <psploadexec_kernel.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/* Define the module info section */
PSP_MODULE_INFO("test", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);
PSP_MAIN_THREAD_STACK_SIZE_KB(0);
char PBPMagic[] = { 0x00, 0x50, 0x42, 0x50 };
char PsfMagic[] = "\0PSF";
char PsfDefaultFile[] = "PARAM.SFO";
typedef struct {
char signature[4];
int version;
int offset[8];
} HEADER;
char *filename[8] = { "PARAM.SFO", "ICON0.PNG", "ICON1.PMF", "UKNOWN.PNG", "PIC1.PNG", "SND0.AT3", "UNKNOWN.PSP", "UNKNOWN.PSAR" };
int extractStartBin(char *filename)
{
printf("extractStartBin started\n");
HEADER header;
int loop0, infile, size;
printf("sceIoOpen(%s,PSP_O_RDONLY, 0777);\n", filename);
if(!(infile = sceIoOpen(filename, PSP_O_RDONLY, 0777)))
{
printf("FAIL => sceIoOpen(%s,PSP_O_RDONLY, 0777);\n", filename);
return -1;
}
printf("Reading %d bytes to memory\n", sizeof(HEADER));
if(memset(&header, 0, sizeof(HEADER)) < 0) printf("FAIL => memset(&header, 0, sizeof(HEADER))\n");
if (sceIoRead(infile, &header, sizeof(HEADER)) < 0)
{
printf("FAIL => sceIoRead(infile, &header, sizeof(HEADER))\n");
return -1;
}
if (memcmp(header.signature, PBPMagic, 4))
{
printf("FAIL => memcmp(header.signature,PBPMagic,4)\n");
return -1;
}
for (loop0=0; loop0<7; loop0++)
{
size = header.offset[loop0 + 1] - header.offset[loop0];
printf("loop=%i\n", loop0);
printf("Allocating %i byte of memory\n", size);
SceUID mem = sceKernelAllocPartitionMemory(2, "block", 0, size, NULL);
void *buffer = (void*)sceKernelGetBlockHeadAddr(mem);
if (!buffer)
{
printf("Could not allocate buffer (size = %i)\n", size);
}
else
{
if (sceIoRead(infile, buffer, size) < 0)
{
printf("Could not read %s (size = %i)\n", filename, size);
}
else
{
if (loop0==6)
{
if(size < 1)
{
sceIoClose(infile);
}
else
{
printf("DATA.PSP FOUND\n");
sceIoClose(infile);
printf("Loading module\n");
SceUID modid = sceKernelLoadModuleBuffer(buffer, size, 0, NULL);
if(modid >= 0)
{
//modid = sceKernelStartModule(modid, len, (void *) args, &status, NULL);
printf("SUCCESS => sceKernelStartModule\n");
}
else
{
printf("FAIL => could not load module || Error => %x\n", modid);
return 0;
}
}
}
}
}
//sceKernelFreePartitionMemory(mem);
}
if (sceIoClose(infile) < 0) printf("infile already closed\n");
printf("getPSP done\n");
return 0;
}
int threadMain(SceSize args, void *argp)
{
sceKernelDelayThread(10000);
printf("\n\n");
extractStartBin("host0:/EBOOT.PBP");
printf("done.\n");
sceKernelSelfStopUnloadModule(0, 0, NULL);
return 0;
}
int module_start(SceSize args, void *argp)
{
SceUID main_thid = sceKernelCreateThread("test_main", threadMain, 6, 64*1024, 0, NULL);
if(main_thid >= 0) sceKernelStartThread(main_thid, args, argp);
return 0;
}
int module_stop(SceSize args, void *argp)
{
return 0;
}
|
makefile :
| Code: |
TARGET = test
OBJS = main.o
BUILD_PRX=1
USE_KERNEL_LIBC=1
USE_KERNEL_LIBS=1
INCDIR = ../include
LIBDIR = ../lib
CFLAGS = -Os -G0 -Wall -fno-strict-aliasing -fno-builtin-printf
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LDFLAGS = -mno-crt0 -nostartfiles
LIBS = -lpspsysmem_kernel -lpspmodulemgr_kernel -lpspkubridge
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build_prx.mak
|
|
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Fri May 16, 2008 7:48 pm Post subject: |
|
|
| If all you need is a 64 byte aligned buffer, allocate (size + 63), then use (ptr + 63) & ~63. |
|
| Back to top |
|
 |
Cpasjuste
Joined: 29 May 2005 Posts: 214
|
Posted: Fri May 16, 2008 9:02 pm Post subject: |
|
|
Thanks for the advice JF. Unfortunately i'm not able to allocate it correctly with sceKernelAllocPartitionMemory while i have no problem with malloc.
Here is the function i'm trying to use :
| Code: |
uint8_t mem = sceKernelAllocPartitionMemory(2, "block", 0, size+63, NULL);
void *buffer = (void*)sceKernelGetBlockHeadAddr((mem+63) & ~63);
|
Sorry for my ignorance, any hint would be cool. |
|
| Back to top |
|
 |
pspZorba
Joined: 22 Sep 2007 Posts: 156 Location: NY
|
Posted: Fri May 16, 2008 10:34 pm Post subject: |
|
|
HI Cpasjuste,
could you try (change the first arg)
| Code: | sceKernelAllocPartitionMemory(1, "block", 0, size, NULL);
|
[edit] and by the way add something like
PSP_HEAP_SIZE_KB( 2048);
PSP_MAIN_THREAD_STACK_SIZE_KB( 2048);
that could help
[/edit] _________________ --pspZorba--
NO to K1.5 ! |
|
| Back to top |
|
 |
Cpasjuste
Joined: 29 May 2005 Posts: 214
|
Posted: Fri May 16, 2008 11:49 pm Post subject: |
|
|
Hi pspZorba.
My main problem is that i'm in kernel mode, so i can't allocate 2048Kb of memory directly (it's why i'm using sceKernelAllocPartitionMemory to alloc the memory in user partition).
From my (poor) point of view, i think something like this should be better :
| Code: |
SceUID mem = sceKernelAllocPartitionMemory(2, "block", 0, size+63, NULL);
uint8_t *buffer = (uint8_t*)sceKernelGetBlockHeadAddr(mem);
void *newbuffer = (buffer + 63) & ~63;
|
but i get an invalid operande error. |
|
| Back to top |
|
 |
pspZorba
Joined: 22 Sep 2007 Posts: 156 Location: NY
|
Posted: Sat May 17, 2008 2:04 am Post subject: |
|
|
it's strange because the code I wrote (above) is an extraction of one of my prx in kernel mode.
so I was able to do allocate the 2048 (but you can set less than that), here is an extract of my prx, with Kmalloc, Kfree and Kmemset and a sample of use wihich works fine for me.
| Code: |
PSP_MODULE_INFO("zorbaprx", PSP_MODULE_KERNEL, MY_HOMEBREW_MAJOR_VERSION, MY_HOMEBREW_MINOR_VERSION);
PSP_MAIN_THREAD_ATTR(0);
PSP_HEAP_SIZE_KB( 2048);
PSP_MAIN_THREAD_STACK_SIZE_KB( 2048);
//those two functions are madatory !
int module_start(SceSize args, void *argp)
{
return 0;
}
int module_stop()
{
return 0;
}
void *Kmalloc( SceSize size, SceUID *memid)
{
*memid = sceKernelAllocPartitionMemory(1, "mybuffer", 0, size, NULL);
/*this will alloc the ram you need:
*arg1: in the kernel partition (1 or 3(mirror)) if you want user use 2
*arg2: buffer name not much interesting if you only need to alloch usefull to search for allocations in the uid lists
*arg3: this can be 0 => alloc in the lowest adress 1 alloc in the highest adress 2 alloc in a user determined adress
*arg4: num*byte of space to alloc
*arg5: if arg3 = 2 adress to alloc to
*
*but you aren't done you need the adress were your allocation starts :)
*/
return( sceKernelGetBlockHeadAddr(*memid) );
}
void Kfree( SceUID memid)
{
//then to free it:
sceKernelFreePartitionMemory(memid);
}
void Kmemset( void *p, u8 c, int len)
{
int i;
for( i=0; i<len; i++)
((u8 *)p)[i] =c;
}
int foo( ...)
{
u32 k1;
u8 *buffer;
SceUID memid;
int size=128;
//k1 stuff
k1 = pspSdkSetK1(0);
//buffer allocation (malloc is not availlable in kernel mode
buffer = Kmalloc( size *sizeof( u8), &memid);
if( buffer==NULL) return -1;
...
|
_________________ --pspZorba--
NO to K1.5 ! |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Sat May 17, 2008 6:51 am Post subject: |
|
|
| Cpasjuste wrote: | Hi pspZorba.
My main problem is that i'm in kernel mode, so i can't allocate 2048Kb of memory directly (it's why i'm using sceKernelAllocPartitionMemory to alloc the memory in user partition).
From my (poor) point of view, i think something like this should be better :
| Code: |
SceUID mem = sceKernelAllocPartitionMemory(2, "block", 0, size+63, NULL);
uint8_t *buffer = (uint8_t*)sceKernelGetBlockHeadAddr(mem);
void *newbuffer = (buffer + 63) & ~63;
|
but i get an invalid operande error. |
That's pretty much what you should be doing. What is giving the error in the above code? |
|
| Back to top |
|
 |
Jim

Joined: 02 Jul 2005 Posts: 487 Location: Sydney
|
|
| Back to top |
|
 |
moonlight
Joined: 26 Oct 2005 Posts: 567
|
Posted: Sat May 17, 2008 7:06 am Post subject: |
|
|
What gives error is probably the "&". Juse use some casts:
| Code: |
uint8_t *buffer = (uint8_t*)sceKernelGetBlockHeadAddr(mem);
void *newbuffer = (void *)(((u32)buffer + 63) & ~63);
|
|
|
| Back to top |
|
 |
pspZorba
Joined: 22 Sep 2007 Posts: 156 Location: NY
|
Posted: Sat May 17, 2008 10:03 am Post subject: |
|
|
I was wondering, since the allocated address is in the user space, do you need to use the k1 stuff ?
[edit] if yes, that could be the reason of your crash Cpasjuste[/edit] _________________ --pspZorba--
NO to K1.5 ! |
|
| Back to top |
|
 |
Cpasjuste
Joined: 29 May 2005 Posts: 214
|
Posted: Sat May 17, 2008 9:07 pm Post subject: |
|
|
Thanks for all your help.
Unfortunatly, i'm still unable to use the sceKernelLoadModuleBuffer function.
Here is my final code which seems ok : http://rafb.net/p/nPBZl784.html
Here is my error :
| Code: |
Exception - Address load/inst fetch
Thread ID - 0x0091911B
Th Name - SceKernelModmgrWorker
Module ID - 0x00CBEC27
Mod Name - SystemControl
EPC - 0x880662E8
Cause - 0x10000010
BadVAddr - 0x000809D2
Status - 0x00088603
zr:0x00000000 at:0xDEADBEEF v0:0x00000001 v1:0x00000001
a0:0x000809D2 a1:0x882FA590 a2:0x00000000 a3:0x00000000
t0:0x882FA650 t1:0x00000000 t2:0x882FA650 t3:0x00000000
t4:0x00000000 t5:0x00000000 t6:0x00000000 t7:0x00000000
s0:0x882FA590 s1:0x000809D2 s2:0x882FA590 s3:0xDEADBEEF
s4:0x88200D84 s5:0xDEADBEEF s6:0x882FA6E0 s7:0x00000000
t8:0x00000000 t9:0x88300000 k0:0x00000000 k1:0x00000000
gp:0x8806C120 sp:0x882FA320 fp:0x882FA660 ra:0x88067810
0x880662E8: 0x8C830000 '....' - lw $v1, 0($a0)
|
|
|
| Back to top |
|
 |
pspZorba
Joined: 22 Sep 2007 Posts: 156 Location: NY
|
Posted: Sun May 18, 2008 1:16 am Post subject: |
|
|
Hi Cpasjuste,
1) I think your filename (char *) is coming from user space so you have to do the k1 stuff earlier in your code ( when I try your code, if I don't set k1 , I can't even do the first sceIoRead).
2) for me the code crash in the sceIoRead line 141 in the last loop. if you read less bytes the code doesn't crash (but I can't go further since I didn't read all datas).
so it looks like an overflow. It could come from a stack pb, actually sceIoRead certainly needs a certain amount of the stack (like printf).
ps: btw you should initialized the variable 'done' , because in the 5 first loops when you do sceKernelFreePartitionMemory it is not and you may have a problem. And you should test sceKernelAllocPartitionMemory as well rather than the buffer to check if the alocation was successful _________________ --pspZorba--
NO to K1.5 ! |
|
| Back to top |
|
 |
Cpasjuste
Joined: 29 May 2005 Posts: 214
|
Posted: Sun May 18, 2008 1:38 am Post subject: |
|
|
Thanks again pspZorba :)
I'm not sure the problem is in sceIoRead, when i uncomment the sceKernelLoadFromBuffer function, the executable (data.psp) is always correctly loaded in memory, i verify it under psplink. I have dumped the memory where it is loaded and it's 100% the same as the DATA.PSP binary extracted from the eboot with pbpunpacker, and can be loaded under psplink.
The thing that seems strange for me is that with or without the 64b aligned buffer, the executable is always loaded at the same address (0x8804000), is it normal ? |
|
| Back to top |
|
 |
pspZorba
Joined: 22 Sep 2007 Posts: 156 Location: NY
|
Posted: Sun May 18, 2008 3:05 am Post subject: |
|
|
well I don't know if 0x8804000 is a valid address, but it is a 64-memaligned address, so it is normal that 0x8804000 is the same as (((0x8804000)+ 63) & ~63).
either you are lucky or sceKernelAllocPartitionMemory gives always a memaligned allocation.
for me it really crashs in the secIoRead but that could be normal since I don't use the same prx loader nor the same makefile (don't use kubridge, just stick to pspsdk) as you.
ps: rather doing a loop to reach the part you read in the pbp, you should do something like :
| Code: |
offset = header.offset[6] - header.offset[0];
size = header.offset[7] - header.offset[6];
SceUID mem = sceKernelAllocPartitionMemory( blblbla);
if( mem<0) return -1;
void *buffer = sceKernelGetBlockHeadAddr blbalabla
if (!buffer) { return -1;}
//we go at the start of DATA.PSP
ret = sceIoLseek( infile , offset, PSP_SEEK_SET);
if( ret<0) return -1;
ret = sceIoRead(infile, buffer, size);
if( ret<0) return -1;
sceIoClose(infile);
loadStartModuleBuffer(buffer, size, 0, NULL);
|
even if it's not a lot more efficient, it's more elegant. _________________ --pspZorba--
NO to K1.5 ! |
|
| Back to top |
|
 |
TyRaNiD
Joined: 18 Jan 2004 Posts: 918
|
Posted: Sun May 18, 2008 4:33 am Post subject: |
|
|
The reason for the crash dump you posted is probably cause the load buffer function has its parameters wrong, for some strange reason sony played with order of those functions so sometimes it is buffer, length and sometimes length, buffer
Try prototyping it as :
SceUID sceKernelLoadModuleBuffer(SceSize bufsize, void *buf, int flags, SceKernelLMOption *option);
Instead and see if it fixed it ;) |
|
| Back to top |
|
 |
Cpasjuste
Joined: 29 May 2005 Posts: 214
|
Posted: Sun May 18, 2008 8:41 am Post subject: |
|
|
Many thanks to all of you, i can now load and start an executable from a buffer in kernel mode. Tyranid was right, lenght and buffer was not in the good order :)
Now i still encounter another problem, with some executable loaded/started from a buffer, i get a 0x80020132 error (partition mismatch) while it's working great with other modules. Any idea ?
I will post the final code soon if someone come on the forum for this ...
pspZorba, i think you where right, buffer allocated with sceKernelAllocPartitionMemory seems to always be 64b aligned. |
|
| Back to top |
|
 |
pspZorba
Joined: 22 Sep 2007 Posts: 156 Location: NY
|
Posted: Sun May 18, 2008 9:34 am Post subject: |
|
|
It is a pure supposition but I would bet that the ones that doesn't work are eboot(s) that run in kernel mode.
As you load them in the user partition they probably create this error.
You can easily check that.
If it is the case the solution is to check the eboot (I don't know how but it must be in the header ) and load it in the kernel or user partition...
A solution for the check is may be just this error code ! if you get it try to load the eboot in the kernel partition _________________ --pspZorba--
NO to K1.5 ! |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|