sceKernelAllocPartitionMemory 64b aligned ?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Cpasjuste
Posts: 214
Joined: Sun May 29, 2005 8:28 am

sceKernelAllocPartitionMemory 64b aligned ?

Post by Cpasjuste »

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: Select all

/*
 * 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 &#40;c&#41; 2005 Marcus R. Brown <[email protected]>
 * Copyright &#40;c&#41; 2005 James Forshaw <[email protected]>
 * Copyright &#40;c&#41; 2005 John Kelley <[email protected]>
 *
 * $Id&#58; main.c 1888 2006-05-01 08&#58;47&#58;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&#40;"test", 0x1000, 1, 1&#41;;
PSP_MAIN_THREAD_ATTR&#40;0&#41;;
PSP_MAIN_THREAD_STACK_SIZE_KB&#40;0&#41;;

char PBPMagic&#91;&#93; = &#123; 0x00, 0x50, 0x42, 0x50 &#125;;
char PsfMagic&#91;&#93; = "\0PSF";
char PsfDefaultFile&#91;&#93; = "PARAM.SFO"; 

typedef struct &#123; 
	char signature&#91;4&#93;; 
	int version; 
	int offset&#91;8&#93;; 
&#125; HEADER;

char *filename&#91;8&#93; = &#123; "PARAM.SFO", "ICON0.PNG", "ICON1.PMF", "UKNOWN.PNG", "PIC1.PNG", "SND0.AT3", "UNKNOWN.PSP", "UNKNOWN.PSAR" &#125;;

int extractStartBin&#40;char *filename&#41;
&#123;

	printf&#40;"extractStartBin started\n"&#41;;

	HEADER header; 
	int loop0, infile, size;

	printf&#40;"sceIoOpen&#40;%s,PSP_O_RDONLY, 0777&#41;;\n", filename&#41;;
	if&#40;!&#40;infile = sceIoOpen&#40;filename, PSP_O_RDONLY, 0777&#41;&#41;&#41;
	&#123;
		printf&#40;"FAIL => sceIoOpen&#40;%s,PSP_O_RDONLY, 0777&#41;;\n", filename&#41;;
		return -1;
	&#125;

	printf&#40;"Reading %d bytes to memory\n", sizeof&#40;HEADER&#41;&#41;;
	if&#40;memset&#40;&header, 0, sizeof&#40;HEADER&#41;&#41; < 0&#41; printf&#40;"FAIL => memset&#40;&header, 0, sizeof&#40;HEADER&#41;&#41;\n"&#41;;

	if &#40;sceIoRead&#40;infile, &header, sizeof&#40;HEADER&#41;&#41; < 0&#41; 
	&#123;
		printf&#40;"FAIL => sceIoRead&#40;infile, &header, sizeof&#40;HEADER&#41;&#41;\n"&#41;;
		return -1;
	&#125;

	if &#40;memcmp&#40;header.signature, PBPMagic, 4&#41;&#41;
	&#123;
		printf&#40;"FAIL => memcmp&#40;header.signature,PBPMagic,4&#41;\n"&#41;;
		return -1;
	&#125;

	for &#40;loop0=0; loop0<7; loop0++&#41; 
	&#123; 
		size = header.offset&#91;loop0 + 1&#93; - header.offset&#91;loop0&#93;;

		printf&#40;"loop=%i\n", loop0&#41;;
		printf&#40;"Allocating %i byte of memory\n", size&#41;;
		SceUID mem = sceKernelAllocPartitionMemory&#40;2, "block", 0, size, NULL&#41;;

		void *buffer = &#40;void*&#41;sceKernelGetBlockHeadAddr&#40;mem&#41;;

		if &#40;!buffer&#41; 
		&#123;
			printf&#40;"Could not allocate buffer &#40;size = %i&#41;\n", size&#41;;
		&#125;
		else
		&#123;
			if &#40;sceIoRead&#40;infile, buffer, size&#41; < 0&#41;
			&#123;
				printf&#40;"Could not read %s &#40;size = %i&#41;\n", filename, size&#41;;
			&#125;
			else
			&#123;
				if &#40;loop0==6&#41;
				&#123;
					if&#40;size < 1&#41;
					&#123;
						sceIoClose&#40;infile&#41;;
					&#125;
					else 
					&#123;
						printf&#40;"DATA.PSP FOUND\n"&#41;;
						sceIoClose&#40;infile&#41;;

						printf&#40;"Loading module\n"&#41;;
						SceUID modid = sceKernelLoadModuleBuffer&#40;buffer, size, 0, NULL&#41;;


						if&#40;modid >= 0&#41;

						&#123;		

							//modid = sceKernelStartModule&#40;modid, len, &#40;void *&#41; args, &status, NULL&#41;;
							printf&#40;"SUCCESS => sceKernelStartModule\n"&#41;;

						&#125;

						else

						&#123;
							printf&#40;"FAIL => could not load module || Error => %x\n", modid&#41;;

							return 0;

						&#125;
					&#125;
				&#125;
			&#125;
		&#125;
		//sceKernelFreePartitionMemory&#40;mem&#41;;
	&#125;
	if &#40;sceIoClose&#40;infile&#41; < 0&#41; printf&#40;"infile already closed\n"&#41;;

	printf&#40;"getPSP done\n"&#41;;
	return 0;
&#125;

int threadMain&#40;SceSize args, void *argp&#41;
&#123;
	sceKernelDelayThread&#40;10000&#41;;
	printf&#40;"\n\n"&#41;;

	extractStartBin&#40;"host0&#58;/EBOOT.PBP"&#41;;
	
	printf&#40;"done.\n"&#41;;
	sceKernelSelfStopUnloadModule&#40;0, 0, NULL&#41;;
	
	return 0;
&#125;

int module_start&#40;SceSize args, void *argp&#41;

&#123;

	SceUID main_thid = sceKernelCreateThread&#40;"test_main", threadMain, 6, 64*1024, 0, NULL&#41;;

	if&#40;main_thid >= 0&#41; sceKernelStartThread&#40;main_thid, args, argp&#41;;


	return 0;

&#125;



int module_stop&#40;SceSize args, void *argp&#41;

&#123;

	return 0;

&#125;
makefile :

Code: Select all

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 = $&#40;CFLAGS&#41; -fno-exceptions -fno-rtti

ASFLAGS = $&#40;CFLAGS&#41;

LDFLAGS = -mno-crt0 -nostartfiles

LIBS = -lpspsysmem_kernel -lpspmodulemgr_kernel -lpspkubridge

PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;
include $&#40;PSPSDK&#41;/lib/build_prx.mak
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

If all you need is a 64 byte aligned buffer, allocate (size + 63), then use (ptr + 63) & ~63.
Cpasjuste
Posts: 214
Joined: Sun May 29, 2005 8:28 am

Post by Cpasjuste »

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: Select all

uint8_t mem = sceKernelAllocPartitionMemory&#40;2, "block", 0, size+63, NULL&#41;;

void *buffer = &#40;void*&#41;sceKernelGetBlockHeadAddr&#40;&#40;mem+63&#41; & ~63&#41;;
Sorry for my ignorance, any hint would be cool.
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

HI Cpasjuste,

could you try (change the first arg)

Code: Select all

sceKernelAllocPartitionMemory&#40;1, "block", 0, size, NULL&#41;; 
[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 !
Cpasjuste
Posts: 214
Joined: Sun May 29, 2005 8:28 am

Post by Cpasjuste »

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: Select all

SceUID mem = sceKernelAllocPartitionMemory&#40;2, "block", 0, size+63, NULL&#41;;

uint8_t *buffer = &#40;uint8_t*&#41;sceKernelGetBlockHeadAddr&#40;mem&#41;;
void *newbuffer = &#40;buffer + 63&#41; & ~63;
but i get an invalid operande error.
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

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: Select all


PSP_MODULE_INFO&#40;"zorbaprx", PSP_MODULE_KERNEL, MY_HOMEBREW_MAJOR_VERSION, MY_HOMEBREW_MINOR_VERSION&#41;;
PSP_MAIN_THREAD_ATTR&#40;0&#41;;

PSP_HEAP_SIZE_KB&#40; 2048&#41;;
PSP_MAIN_THREAD_STACK_SIZE_KB&#40; 2048&#41;;


//those two functions are madatory !
int module_start&#40;SceSize args, void *argp&#41;
&#123;
   return 0;
&#125;

int module_stop&#40;&#41;
&#123;
   return 0;
&#125;



void *Kmalloc&#40; SceSize  size, SceUID *memid&#41;
&#123;
	*memid = sceKernelAllocPartitionMemory&#40;1, "mybuffer", 0, size, NULL&#41;;
	/*this will alloc the ram you need&#58;
	*arg1&#58; in the kernel partition &#40;1 or 3&#40;mirror&#41;&#41; if you want user use 2
	*arg2&#58; buffer name not much interesting if you only need to alloch usefull to search for allocations in the uid lists
	*arg3&#58; this can be 0 => alloc in the lowest adress 1 alloc in the highest adress 2 alloc in a user determined adress
	*arg4&#58; num*byte of space to alloc
	*arg5&#58; if arg3 = 2 adress to alloc to
	*
	*but you aren't done you need the adress were your allocation starts &#58;&#41;
	*/
	return&#40; sceKernelGetBlockHeadAddr&#40;*memid&#41; &#41;;

&#125;

void Kfree&#40; SceUID memid&#41;
&#123;
	//then to free it&#58;
	sceKernelFreePartitionMemory&#40;memid&#41;; 
&#125;

void Kmemset&#40; void *p, u8 c, int len&#41;
&#123;
	int i;
	for&#40; i=0; i<len; i++&#41;
	  &#40;&#40;u8 *&#41;p&#41;&#91;i&#93; =c; 
&#125;




int foo&#40; ...&#41;
&#123;
	u32 k1;

 	u8 *buffer;

 	SceUID memid;
	int size=128;
 	
	//k1 stuff
	k1 = pspSdkSetK1&#40;0&#41;; 
 		
	//buffer allocation &#40;malloc is not availlable in kernel mode
	buffer = Kmalloc&#40; size *sizeof&#40; u8&#41;, &memid&#41;;
	if&#40; buffer==NULL&#41; return -1;
	
	
 ...	

--pspZorba--
NO to K1.5 !
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

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: Select all

SceUID mem = sceKernelAllocPartitionMemory&#40;2, "block", 0, size+63, NULL&#41;;

uint8_t *buffer = &#40;uint8_t*&#41;sceKernelGetBlockHeadAddr&#40;mem&#41;;
void *newbuffer = &#40;buffer + 63&#41; & ~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?
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

need cast to uint in last line
moonlight
Posts: 567
Joined: Wed Oct 26, 2005 7:46 pm

Post by moonlight »

What gives error is probably the "&". Juse use some casts:

Code: Select all

uint8_t *buffer = &#40;uint8_t*&#41;sceKernelGetBlockHeadAddr&#40;mem&#41;;
void *newbuffer = &#40;void *&#41;&#40;&#40;&#40;u32&#41;buffer + 63&#41; & ~63&#41;; 
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

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 !
Cpasjuste
Posts: 214
Joined: Sun May 29, 2005 8:28 am

Post by Cpasjuste »

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: Select all

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&#58;0x00000000 at&#58;0xDEADBEEF v0&#58;0x00000001 v1&#58;0x00000001
a0&#58;0x000809D2 a1&#58;0x882FA590 a2&#58;0x00000000 a3&#58;0x00000000
t0&#58;0x882FA650 t1&#58;0x00000000 t2&#58;0x882FA650 t3&#58;0x00000000
t4&#58;0x00000000 t5&#58;0x00000000 t6&#58;0x00000000 t7&#58;0x00000000
s0&#58;0x882FA590 s1&#58;0x000809D2 s2&#58;0x882FA590 s3&#58;0xDEADBEEF
s4&#58;0x88200D84 s5&#58;0xDEADBEEF s6&#58;0x882FA6E0 s7&#58;0x00000000
t8&#58;0x00000000 t9&#58;0x88300000 k0&#58;0x00000000 k1&#58;0x00000000
gp&#58;0x8806C120 sp&#58;0x882FA320 fp&#58;0x882FA660 ra&#58;0x88067810
0x880662E8&#58; 0x8C830000 '....' - lw         $v1, 0&#40;$a0&#41;
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

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 !
Cpasjuste
Posts: 214
Joined: Sun May 29, 2005 8:28 am

Post by Cpasjuste »

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 ?
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

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: Select all

 
    offset = header.offset&#91;6&#93; - header.offset&#91;0&#93;;
    size = header.offset&#91;7&#93; - header.offset&#91;6&#93;;

    SceUID mem = sceKernelAllocPartitionMemory&#40; blblbla&#41;;
    if&#40; mem<0&#41; return -1;

   void *buffer = sceKernelGetBlockHeadAddr  blbalabla
    if &#40;!buffer&#41; &#123; return -1;&#125;

    //we go at the start of DATA.PSP
    ret = sceIoLseek&#40; infile , offset, PSP_SEEK_SET&#41;;
    if&#40; ret<0&#41; return -1;

    ret = sceIoRead&#40;infile, buffer, size&#41;;
    if&#40; ret<0&#41; return -1;

    sceIoClose&#40;infile&#41;;
    
    loadStartModuleBuffer&#40;buffer, size, 0, NULL&#41;;
even if it's not a lot more efficient, it's more elegant.
--pspZorba--
NO to K1.5 !
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

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 ;)
Cpasjuste
Posts: 214
Joined: Sun May 29, 2005 8:28 am

Post by Cpasjuste »

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.
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

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 !
Post Reply