[solved] sceKernelLoadModule in kernel mode

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

Moderators: cheriff, TyRaNiD

Post Reply
Beuc
Posts: 33
Joined: Thu Mar 26, 2009 5:04 am
Location: holland

[solved] sceKernelLoadModule in kernel mode

Post by Beuc »

Hi,

I'm trying to load a module from within a kernel module.

When I use:

Code: Select all

SceUID modid = sceKernelLoadModule("hello.prx", 0, &option);
from the kernel module, it returns 0x80020149 (SCE_KERNEL_ERROR_ILLEGAL_PERM_CALL).

I tried using USE_KERNEL_LIBS=1 to allow the kernel to use user-mode (as per I read at http://forums.ps2dev.org/viewtopic.php?p=66785), but that doesn't seem to work. pspSdkSetK1(0) doesn't help either.

How should I use sceKernelLoadModule in kernel mode?
Last edited by Beuc on Thu May 21, 2009 7:15 pm, edited 1 time in total.
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

First of all when making a kernel module always use USE_KERNEL_LIBS=1 and USE_KERNEL_LIBC=1 or you'll end up with bloated code like 100KiB for a kernel module which would normally be 2KiB. And you're ideally not supposed to use user functions from kernel mode either. Find a way without the user functions.

Regarding your problem:
The cwd may not be set. Give the full path for hello.prx

The &options struct may not be set properly. Anyway it's not necessary for simple loading so make it NULL..

It may not work from inside module_start and some non-thread contexts. Make sure you are calling it from a thread.
Beuc
Posts: 33
Joined: Thu Mar 26, 2009 5:04 am
Location: holland

Post by Beuc »

Thanks Torch.

Here's the code, I'm trying to follow your advice:

Code: Select all

#include <pspsdk.h>
#include <pspkernel.h>
#include <string.h>
#include <stdio.h>

PSP_MODULE_INFO&#40;"nanofe", 0x1007, 1, 0&#41;;
PSP_MAIN_THREAD_ATTR&#40;PSP_THREAD_ATTR_USER&#41;;

int plugin_thread &#40;SceSize argc, void* argp&#41;
&#123;
  char buf&#91;100&#93;;

  SceUID fd = sceIoOpen &#40;"host0&#58;/plugin_pspain.dat",
			 PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777&#41;;
  if &#40;fd < 0&#41;
    return -1;

  SceKernelLMOption option;
  memset&#40;&option, 0, sizeof&#40;option&#41;&#41;;
  option.size = sizeof&#40;option&#41;;
  option.mpidtext = 2;
  option.mpiddata = 2;
  option.position = 0;
  option.access = 1;
  char args&#91;2048&#93;;

  u32 k1 = pspSdkSetK1&#40;0&#41;; 

  //SceUID &#40;* sceKernelLoadModule_k&#41;&#40;const char *path, int flags, SceKernelLMOption *option&#41;;
  //sceKernelLoadModule_k = &#40;void *&#41;FindProc&#40;"sceModuleManager", "ModuleMgrForKernel", 0x977de386&#41;; 

  sceKernelDelayThread&#40;1000 * 1000&#41;;
  while&#40;!sceKernelFindModuleByName&#40;"sceKernelLibrary"&#41;&#41; sceKernelDelayThread&#40;100 * 1000&#41;;
  SceUID modid = sceKernelLoadModule&#40;"ms0&#58;/PSP/GAME/meminfo-prx-large/hello.prx", 0, NULL&#41;;

  sceIoWrite &#40;fd, "modid=", 7&#41;;
  sprintf&#40;buf, "%p\n", modid&#41;;
  sceIoWrite &#40;fd, buf, 100&#41;;
  int mresult;
  sceKernelStartModule&#40;modid, 0, args, &mresult, NULL&#41;;
  sceIoWrite &#40;fd, "end\n", 4&#41;;

  pspSdkSetK1&#40;k1&#41;; 

  sceIoClose &#40;fd&#41;;

  // Completely free all memory
  sceKernelSelfStopUnloadModule&#40;1, 0, NULL&#41;;
  return 0;

&#125;

int
module_start &#40;SceSize argc, void* argp&#41;
&#123;
  u32 func = 0x80000000 | &#40;u32&#41;plugin_thread;
  SceUID thread = sceKernelCreateThread&#40;"plugin_thread",
					&#40;void*&#41;func, 0x30, 0x10000, 0, NULL&#41;;
  if &#40;thread >= 0&#41; &#123;
    sceKernelStartThread &#40;thread, argc, argp&#41;;
  &#125;
  return 0;
&#125;
and Makefile:

Code: Select all

PSP_LARGE_MEMORY=1
TARGET = plugin
OBJS = module.o

CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $&#40;CFLAGS&#41; -fno-exceptions -fno-rtti
ASFLAGS = $&#40;CFLAGS&#41;

LDFLAGS += -mno-crt0 -nostartfiles

BUILD_PRX=1
PSP_FW_VERSION=303
#USE_PSPSDK_LIBC=1
USE_KERNEL_LIBC=1 
USE_KERNEL_LIBS=1 

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = plugin

PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;

include $&#40;PSPSDK&#41;/lib/build.mak

Torch wrote:First of all when making a kernel module always use USE_KERNEL_LIBS=1 and USE_KERNEL_LIBC=1 or you'll end up with bloated code like 100KiB for a kernel module which would normally be 2KiB.
Hmm, I get a 72kB .prx.
Torch wrote:And you're ideally not supposed to use user functions from kernel mode either. Find a way without the user functions.
Well I don't have a clue about loading the module otherwise. Any lead?
Torch wrote: Regarding your problem:
The cwd may not be set. Give the full path for hello.prx
It doesn't help, but in fact even specifying "blah" will return 0x80020149.
The &options struct may not be set properly. Anyway it's not necessary for simple loading so make it NULL..
Neither :/
It may not work from inside module_start and some non-thread contexts. Make sure you are calling it from a thread.
It's in a thread already.
Beuc
Posts: 33
Joined: Thu Mar 26, 2009 5:04 am
Location: holland

Post by Beuc »

Beuc wrote:

Code: Select all

USE_KERNEL_LIBC=1 
USE_KERNEL_LIBS=1 
Hmmm, it doesn't show on the forum but did you know that a trailing space in 'USE_KERNEL_LIBC=1 ' can seriously mess you build? Just learnt about it XD

Arrrrrrrrrrrrrrrrrrrrrrrrrrgh!!!
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

Lot of unnecessary crap in your code. And yes the trailing spaces in the makefile lines screw things up.

Not tested, but this should be enough.

Code: Select all

#include <pspsdk.h>
#include <pspkernel.h>
#include <string.h>
#include <stdio.h>

PSP_MODULE_INFO&#40;"nanofe", 0x1000, 1, 0&#41;; //0x1007 cannot be stopped and unloaded
PSP_MAIN_THREAD_ATTR&#40;0&#41;; //0 for kernel thread

int plugin_thread &#40;SceSize argc, void* argp&#41;
&#123;
  sceIoChdir&#40;argp&#41;; //Might need to append trailing / here.
  char buf&#91;100&#93;;

  SceUID fd = sceIoOpen &#40;"host0&#58;/plugin_pspain.dat",
          PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777&#41;;
  if &#40;fd < 0&#41;
    return -1;

  SceUID modid = sceKernelLoadModule&#40;"ms0&#58;/PSP/GAME/meminfo-prx-large/hello.prx", 0, NULL&#41;;

  sceIoWrite &#40;fd, "modid=", 7&#41;;
  sprintf&#40;buf, "%p\n", modid&#41;;
  sceIoWrite &#40;fd, buf, 100&#41;;
  int mresult;
  sceKernelStartModule&#40;modid, 0, NULL, &mresult, NULL&#41;; //why args for 0 length. pass NULL instead?
  sceIoWrite &#40;fd, "end\n", 4&#41;;

  sceIoClose &#40;fd&#41;;

  // Completely free all memory
  sceKernelSelfStopUnloadModule&#40;1, 0, NULL&#41;;
  return 0;

&#125;

int module_start &#40;SceSize argc, void* argp&#41;
&#123;
  SceUID thread = sceKernelCreateThread&#40;"plugin_thread",
               plugin_thread, 0x30, 0x10000, 0, NULL&#41;; //this is enough
  if &#40;thread >= 0&#41; &#123;
    sceKernelStartThread &#40;thread, argc, argp&#41;;
  &#125;
  return 0;
&#125; 
Beuc
Posts: 33
Joined: Thu Mar 26, 2009 5:04 am
Location: holland

Post by Beuc »

Thanks for your answer.
Torch wrote:Lot of unnecessary crap in your code. And yes the trailing spaces in the makefile lines screw things up.
Yes, the code was as-is, since I was aiming at getting something that worked before trying to trim it.

I wasn't clear, but actually the Makefile bug was the only thing to fix :]

Code: Select all

sceIoChdir&#40;argp&#41;; //Might need to append trailing / here.
I'd say we need to remove the file part, as argp is normally the path to the current executable. To make things simple I built full paths (getcwd() + "stuff.prx") from the SDL front-end.

For reference, here's the code:

Code: Select all

#include <pspsdk.h>
#include <pspkernel.h>
#include <string.h>

PSP_MODULE_INFO&#40;"klauncher", 0x1000, 1, 0&#41;;
PSP_MAIN_THREAD_ATTR&#40;0&#41;; // kernel thread

int klauncher_thread &#40;SceSize args, char* argp&#41;
&#123;
  SceUID modid = sceKernelLoadModule&#40;argp, 0, NULL&#41;;
  if &#40;modid > 0&#41;
    &#123;
      int ignored_mresult;
      sceKernelStartModule&#40;modid, args, argp, &ignored_mresult, NULL&#41;;
    &#125;
  
  // Completely free all memory
  sceKernelSelfStopUnloadModule&#40;1, 0, NULL&#41;;

  return 0;
&#125;

int
module_start &#40;SceSize args, char* argp&#41;
&#123;
  /* We need to run sceKernelLoadModule from a thread */
  SceUID thread = sceKernelCreateThread&#40;"klauncher_thread",
					&#40;void*&#41;klauncher_thread, 0x30, 0x10000, 0, NULL&#41;;
  if &#40;thread >= 0&#41; &#123;
    /* Drop first argument &#40;path to current module&#41; */
    int i = 0;
    while&#40;argp&#91;i&#93; != '\0'&#41; i++;
    i++;
    sceKernelStartThread &#40;thread, args-i, argp+i&#41;;
  &#125;
  return 0;
&#125;
and Makefile:

Code: Select all

TARGET = klauncher
OBJS = klauncher.o

CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $&#40;CFLAGS&#41; -fno-exceptions -fno-rtti

LDFLAGS += -mno-crt0 -nostartfiles

BUILD_PRX=1
#PSP_FW_VERSION=303

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = klauncher

PSP_LARGE_MEMORY=1
USE_KERNEL_LIBC=1
USE_KERNEL_LIBS=1

PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;
include $&#40;PSPSDK&#41;/lib/build.mak
Post Reply