SceKernelModulemgr: Difference between revisions

From Vita Development Wiki
Jump to navigation Jump to search
No edit summary
Tags: mobile edit mobile web edit
Line 316: Line 316:


<source lang="c">int SceKernelModulemgr_func_81009309(SceDecryptCtx *ctx, int seg_idx, void *membase, int arg4);</source>
<source lang="c">int SceKernelModulemgr_func_81009309(SceDecryptCtx *ctx, int seg_idx, void *membase, int arg4);</source>


called whenever self is loaded
called whenever self is loaded
Line 330: Line 332:


int SceKernelModulemgr_func_81001519(int a1, const char *path, SceUID modid, void *a4, uint32_t flags);
int SceKernelModulemgr_func_81001519(int a1, const char *path, SceUID modid, void *a4, uint32_t flags);
</source>
Reads the header from the passed fd and performs some checks.
<source lang="c">
[out] ctx
[in]  pid
[in]  fd
[in]  context_130
int SceKernelModulemgr_func_81008DC9(SceDecryptCtx *ctx, SceUID pid, SceUID fd, void *context_130);
</source>
</source>



Revision as of 14:54, 17 January 2020

SceKernelModulemgr is in charge of loading both user modules and kernel modules. SceSblAuthMgr facilitates the SELF decryption process and this library loads the ELF programs into memory along with linking with NIDs and relocation of ELF in position independent executables.

Module

This module exists only in non-secure world. The SELF can be found in os0:kd/modulemgr.skprx.

Known NIDs

Version Name World Privilege NID
1.69 SceKernelModulemgr Non-secure Kernel 0xAFDA75C2
3.57 SceKernelModulemgr Non-secure Kernel 0x8FDDA3C0
3.60 SceKernelModulemgr Non-secure Kernel 0x726C6635
3.65 SceKernelModulemgr Non-secure Kernel 0x781C6F50

Libraries

This module exports kernel and user libraries.

Known NIDs

Version Name World Visibility NID
1.69-3.60 SceModulemgrForKernel Non-secure Kernel 0xC445FA63
3.65 SceModulemgrForKernel Non-secure Kernel 0x92C9FFC2
1.69-3.65 SceModulemgrForDriver Non-secure Kernel 0xD4A60A52
1.69-3.65 SceModulemgr Non-secure User 0xEAED1616
3.57-3.60 SceBacktraceForDriver Non-secure Kernel 0x77CB3DD6
3.57-3.60 SceBacktrace Non-secure User 0xB07B6A3F

Types

// These types are defined in elfutils
typedef Elf32_Ehdr Elf32_Ehdr;
typedef Elf32_Phdr Elf32_Phdr;

typedef struct SCE_header {
	uint32_t magic;                 /* 53434500 = SCE\0 */
	uint32_t version;               /* header version 3*/
	uint16_t sdk_type;              /* */
	uint16_t header_type;           /* 1 self, 2 unknown, 3 pkg */
	uint32_t metadata_offset;       /* metadata offset */
	uint64_t header_len;            /* self header length */
	uint64_t elf_filesize;          /* ELF file length */
	uint64_t self_filesize;         /* SELF file length */
	uint64_t unknown;               /* UNKNOWN */
	uint64_t self_offset;           /* SELF offset */
	uint64_t appinfo_offset;        /* app info offset */
	uint64_t elf_offset;            /* ELF #1 offset */
	uint64_t phdr_offset;           /* program header offset */
	uint64_t shdr_offset;           /* section header offset */
	uint64_t section_info_offset;   /* section info offset */
	uint64_t sceversion_offset;     /* version offset */
	uint64_t controlinfo_offset;    /* control info offset */
	uint64_t controlinfo_size;      /* control info size */
	uint64_t padding;
} SCE_header;

typedef struct SCE_appinfo {
   uint64_t program_authority_id;  /* program authority id */
   uint32_t vendor_id;             /* vendor id */
   uint32_t self_type;             /* app type */
   uint64_t version;               /* app version */
   uint64_t padding;               /* UNKNOWN */
} SCE_appinfo;

typedef struct segment_info {
   uint64_t offset;
   uint64_t length;
   uint64_t compression; // 1 = uncompressed, 2 = compressed
   uint64_t encryption; // 1 = encrypted, 2 = plain
} segment_info;

typedef struct self_data_buffer {
   SCE_header sce_header;
   SCE_appinfo sce_appinfo;
   Elf32_Ehdr elf_hdr;
   
   //... data goes
   
} self_data_buffer;

typedef struct SceDecryptCtx { //size is 0x30
   self_data_buffer* self_header; // aligned buffer - based on (buffer_unaligned). 
                                  // points at SCE_header followed by SCE_appinfo
                                  // size is usually 0x1000
   int self_header_length;
   Elf32_Ehdr* elf_ptr; // pointer constructed with elf_offset
   Elf32_Phdr* phdr_ptr; // pointer constructed with phdr_offset

   uint8_t type; // ex: 2
   uint8_t init_completed;
   uint8_t unk_12;
   uint8_t unk_13;
   
   segment_info* section_info_ptr; // pointer constructed with section_info_offset
   void* buffer_unaligned; // SELF header data - size 0x103F - raw data read from file
   int sm_ctx; // obtained with sceSblAuthMgrOpenForKernel

   SceSblSmCommContext130* context_130;
   SceUID fd; // file descriptor of SELF file - obtained with sceIoOpenForDriver
   SceUID pid;
   uint32_t max_size;
} SceDecryptCtx;

typedef struct SceDecryptCtxGlobal { // size is 0x4C
	uint32_t unk_0;
	uint32_t unk_4;		// ex:3
	void *module_decrypt_buff_ptr1;
	int decrypt_size;	// max 0x10000

	int unk_10;		// 0 or 1 or 2
	int unk_14;		// ex:-1
	void *module_decrypt_buff_ptr2;
	int unk_1C;		// some size

	SceDecryptCtx *decrypt_ctx;
	SceUID evid;		// SceModuleMgrSelfDecryptComm event flag
	SceUID tid;		// SceModuleMgrSelfDecrypter   thread uid
	void *unk_2C;		// ksceDeflateDecompressPartial out. memblock

	int compressed_seg_size;
	uint32_t unk_34;	// unk_2C out size?
	uint16_t segment_number;
	uint16_t unk_3A;	// ex:0xFFFF

	SceDeflatePartialInputParam cbinfo;
} SceDecryptCtxGlobal;

typedef struct SceKernelFwInfo {
  SceSize size;
  char versionString[0x1C];
  SceUInt version;
  SceUInt unk_24;
} SceKernelFwInfo;

typedef struct SceKernelSegmentInfo {
  SceUInt size;   //!< this structure size (0x18)
  SceUInt perms;  //!< probably rwx in low bits
  void *vaddr;    //!< address in memory
  SceUInt memsz;  //!< size in memory
  SceUInt flags;  //!< meaning unknown
  SceUInt res;    //!< unused?
} SceKernelSegmentInfo;

typedef struct SceKernelModuleName {
  char s[0x1C];
} SceKernelModuleName;

typedef struct SceKernelModuleInfo { // size is 0x1B8
	SceSize size; //!< sizeof(SceKernelModuleInfo)
	SceUID modid;
	uint16_t modattr;
	uint8_t  modver[2];
	char name[0x1C];
	uint32_t unk28;
	void *start_entry;
	void *stop_entry;
	void *exit_entry;
	void *exidx_start;
	void *exidx_end;
	void *extab_start;
	void *extab_end;
	void *tls_start;
	SceSize tls_filesz;
	SceSize tls_memsz;
	char path[256];
	SceKernelSegmentInfo segments[4];
	SceUInt type;
} SceKernelModuleInfo;

typedef struct SceKernelSegmentInfo2 { // size is 0x14
  SceSize size; //!< sizeof(SceKernelSegmentInfo2)
  int perm;
  void *vaddr;
  uint32_t memsz;
  int unk_10;
} SceKernelSegmentInfo2;

typedef struct SceKernelModuleListInfo { //!< sizeof(SceKernelModuleListInfo)
  SceSize size;
  SceUID modid;
  uint32_t version;
  uint32_t module_version;
  uint32_t unk10;
  void *unk14;
  uint32_t unk18;
  void *unk1C;
  void *unk20;
  char module_name[28];
  uint32_t unk40;
  uint32_t unk44;
  uint32_t nid;
  int segments_num;
  union {
    struct {
      SceKernelSegmentInfo2 SegmentInfo[1];
      uint32_t addr[4];
    } seg1;
    struct {
      SceKernelSegmentInfo2 SegmentInfo[2];
      uint32_t addr[4];
    } seg2;
    struct {
      SceKernelSegmentInfo2 SegmentInfo[3];
      uint32_t addr[4];
    } seg3;
    struct {
      SceKernelSegmentInfo2 SegmentInfo[4];
      uint32_t addr[4];
    } seg4;
  };
} SceKernelModuleListInfo; // is for SceCoredump?

typedef struct SceKernelLibraryInfo { // size is 0x1C
    SceSize size; //!< sizeof(SceKernelLibraryInfo)
    uint16_t libver[2];
    uint32_t libnid;
    const char *libname;
    uint16_t nfunc;
    uint16_t nvar;
    uint32_t *nid_table;
    uint32_t *entry_table;
} SceKernelLibraryInfo;

/**
 * Module common macro
 */
#define SCE_KERNEL_START_SUCCESS		(0)				/**< Successful startup */
#define SCE_KERNEL_START_RESIDENT		SCE_KERNEL_START_SUCCESS	/**< Successful startup (resident) */
#define SCE_KERNEL_START_NO_RESIDENT		(1)				/**< Successful startup (not resident) */
#define SCE_KERNEL_START_FAILED			(2)				/**< Failed to start */

#define SCE_KERNEL_STOP_SUCCESS			(0)				/**< Successful stop */
#define SCE_KERNEL_STOP_FAIL			(1)				/**< Failed to stop */
#define SCE_KERNEL_STOP_CANCEL			SCE_KERNEL_STOP_FAIL		/**< Stop was cancelled */

/** Module attributes */
#define SCE_MODULE_ATTR_NONE			(0x0000)			/**< No attributes specified */

/** obsolete */
#define SCE_KERNEL_MODULE_ATTR_NONE		SCE_MODULE_ATTR_NONE

/**
 * option parameter for load module APIs
 */
typedef struct SceKernelLoadModuleOpt {
	SceSize		size;		/**< Size of structure itself */
} SceKernelLoadModuleOpt;

/**
 * option parameter for start module API
 */
typedef struct SceKernelStartModuleOpt {
	SceSize		size;		/**< size of structure itself */
	SceUInt32	flags;		/**< should be 0 */
	SceUInt32	prologue;	/**< should be 0 */
	SceUInt32	start;		/**< should be 0 */
} SceKernelStartModuleOpt;

/**
 * option parameter for stop module API
 */
typedef struct SceKernelStopModuleOpt {
	SceSize size;			/**< size of structure itself */
	SceUInt32 flags;		/**< should be 0 */
	SceUInt32 epilogue;		/**< should be 0 */
	SceUInt32 stop;			/**< should be 0 */
} SceKernelStopModuleOpt;

/**
 * option parameter for unload module APIs
 */
typedef struct SceKernelUnloadModuleOpt {
	SceSize		size;		/**< size of structure itself */
} SceKernelUnloadModuleOpt;


#define SCE_KERNEL_BACKTRACE_CONTEXT_CURRENT	(0x00000000)	/**< Backtrace current context */

#define SCE_KERNEL_BACKTRACE_MODE_USER		(0x00000000)	/**< User stack backtrace */
#define SCE_KERNEL_BACKTRACE_MODE_DONT_EXCEED	(0x00000002)	/**< Don't get stack depth */

/**
 * Structure that represents one stage of the call stack
 */
typedef struct	_SceKernelCallFrame {
	SceUIntVAddr	sp;		/**< stack pointer */
	SceUIntVAddr	pc;		/**< program counter */
} SceKernelCallFrame;

module decrypt threads

SceKernelModulemgr_func_8100910D

This thread keeps waiting at sceKernelWaitEventFlagForDriver until a module decrypt request comes.

bits of ksceKernelWaitEventFlag is 3.

common functions

Decrypt module to membase with current ctx.

int SceKernelModulemgr_func_81009309(SceDecryptCtx *ctx, int seg_idx, void *membase, int arg4);


called whenever self is loaded

flags
process image           : 0x4
normal module           : 0x1000
process module shared   : 0x8001
process module          : 0x8002
homebrew plugin         : 0x8000002
shared module           : 0x8008001
normal module ?         : 0x8008002

int SceKernelModulemgr_func_81001519(int a1, const char *path, SceUID modid, void *a4, uint32_t flags);



Reads the header from the passed fd and performs some checks.

[out] ctx
[in]  pid
[in]  fd
[in]  context_130

int SceKernelModulemgr_func_81008DC9(SceDecryptCtx *ctx, SceUID pid, SceUID fd, void *context_130);

Data segment layout

Offsets are for FW 3.60.

data section size is 0x203C0.

Offset Size Description
0x0000 0x34 unknown, all zero
0x0034 0x4 SceKernelFwInfo data Initialize flag
0x0038 0x4 pointer of SceClass. The first class obtained with sceKernelSysrootGetModulePrivateForKernel. used by only sceKernelFinalizeKblForKernel.
0x003C 0x4 pointer of SceClass. The third class obtained with sceKernelSysrootGetModulePrivateForKernel. SceUIDLibStubClass
0x0040 0x4 pointer of SceClass. The second class obtained with sceKernelSysrootGetModulePrivateForKernel. SceUIDLibraryClass
0x0044 0x4 Return value of SceThreadmgrForDriver_B645C7EF
0x0048 0x4 pointer of SceClass. The first class obtained with sceKernelSysrootGetModulePrivateForKernel. SceUIDModuleClass
0x004C 0x4 SceModuleMgr Mutex uid
0x0050 0x280 unknown
0x02D0 0x28 SceKernelFwInfo data
0x02F8 0x4 some thread id, check SceModulemgrForKernel_2A69385E
0x02FC 0x4 some kernel module uid, check SceModulemgrForKernel_2A69385E
0x0300 0x4 unk, used by SceModulemgrForKernel_3AD26B43
0x0304 0x4 some storage ptr. used by sceKernelMountBootfsForKernel, sceKernelUmountBootfsForKernel
0x0308 0x4 unk, used by SceModulemgrForKernel_60E176C8, SceModulemgrForKernel_9D20C9BB
0x030C 0x4 unk
0x0310 0x4 cpu_addr out (ksceKernelCpuSuspendIntr arg1)
0x0314 0x4 unk, some flag
0x0318 0x4 sceKernelGetMemBlockBaseForDriver membase out
0x031C 0x4 sceKernelAllocMemBlockForDriver ret
0x0320 0xC unk
0x032C 0x4 unk, used by SceModulemgrForKernel_F3CD647F
0x0330 0x4 unk, used by SceModulemgrForKernel_F3CD647F
0x0334 0x4 syscall table vaddr
0x0338 0x4 unk, related to syscall. used by SceKernelUtilsForDriver_875B2A1C
0x033C 0x4 unk
0x0340 0x4C SceDecryptCtxGlobal data
0x038C 0x34 unk, all zero
0x03C0 0x10000 module decrypt buff 1
0x103C0 0x10000 module decrypt buff 2
typedef struct SceKernelModulemgr_data_t // size is 0x203C0
{
	char unk_00[0x34];	 // unknown, all zero
	int is_FwInfo_init;
	SceClass *kbl_unload;
	SceClass *pSceUIDLibStubClass;
	SceClass *pSceUIDLibraryClass;
	int some_thread_res;
	SceClass *pSceUIDModuleClass;
	SceUID mutex_id;
	char unk_50[0x280];	 // unknown
	SceKernelFwInfo FwInfo;
	SceUID some_threadid;
	SceUID some_kernel_module_id;
	int unk_0x0300;
	void *bootfs_info;
	int unk_0x0308;
	int unk_0x030C;
	int cpu_addr;
	int some_flag;
	void *membase;
	SceUID memuid;
	int unk_0x0320[3];
	int unk_0x032C;
	int unk_0x0330;
	void *syscall_table;
	int some_syscall_info;
	int unk_0x033C;
	SceDecryptCtxGlobal g_decrypt_ctx;
	char unk_0x038C[0x34];
	char module_decrypt_buff1[0x10000];
	char module_decrypt_buff2[0x10000];
} SceKernelModulemgr_data_t;

Loading Sequence

When loading a module the sequence creates a SceModule structure to represent it.

typedef struct SceModule { // ?size is 0x3EC?
    u8 unk0[0x64];          // 0x0
    const char *filename;   // 0x64
    u8 unk1[0xC];           // 0x68
    Elf32_Ehdr ehdr;        // 0x74
    Elf32_Phdr phdr;        // 0xA8
    void *text_addr;        // 0x108
    SceUID text_uid;        // 0x10C
    u32 text_size;          // 0x110
    void *kernel_addr;      // 0x114
    SceUID kernel_uid;      // 0x118
    u8 unk2[0x2C8];         // 0x11C
    SceUID parent_pid;      // 0x3E4
    SceSblSmCommContext130* context_130; // 0x3E8
} SceModule;

SELF Decryption

The following code can decrypt a SELF located at path. Set user to 1 if decrypting a user module else 0 for kernel. Set pathid to 0 if you're decrypting the SELF at the right location (for example decrypting sysmem.skprx located in os0:). If you have copied the SELF elsewhere, you need to set the pathid to the right value for where the real path was. usecdram is for modules that are too large and won't fit in contiguous regular memory.

int decrypt_self(const char *path, const char *outprefix, int pathid, int usecdram, int user) {
    char outpath[256];
    int ctx;
    int ret;
    int pid;
    int fd = 0, wfd = 0;
    char *somebuf = NULL;
    char *hdr_buf = NULL, *hdr_buf_aligned;
    char *data_buf = NULL, *data_buf_aligned;
    int phdr;

    unsigned int hdr_size;

    // set up SBL decrypt context
    ret = sceSblAuthMgrOpenForKernel(&ctx);
    printf("sceSblAuthMgrOpenForKernel: 0x%08X, CTX: 0x%08X\n", ret, ctx);
    if (ret < 0)
        return 1;

    // set up this weird buffer
    somebuf = sceKernelLoadcoreKallocForKernel(0x10005, 0x130);
    printf("Weird buffer: 0x%08X\n", somebuf);
    if (somebuf == NULL)
        goto fail;
    memset(somebuf, 0, 0x130);
    if (ret < 0)
        goto fail;
    *(int *)(somebuf + 0x4) = user;
    *(u64_t *)(somebuf + 0x8) = 0x2808000000000001LL;
    *(u64_t *)(somebuf + 0x10) = 0xF000C000000080LL;
    *(u64_t *)(somebuf + 0x18) = 0xFFFFFFFF00000000LL;
    *(u64_t *)(somebuf + 0x30) = 0xC300003800980LL;
    *(u64_t *)(somebuf + 0x38) = 0x8009800000LL;
    *(u64_t *)(somebuf + 0x48) = 0xFFFFFFFF00000000LL;

    if (pathid) {
        *(int *)(somebuf + 0x128) = pathid;
    }
    else {
        ret = sceIoGetMediaTypeForDriver(0x10005, path, 1, somebuf + 0x128);
        printf("sceIoGetMediaTypeForDriver: 0x%08X\n", ret);
        if (ret < 0)
            goto fail;
    }

    // read header
    fd = sceIoOpenForDriver(path, 1, 0);
    printf("sceIoOpenForDriver: 0x%08X\n", fd);
    if (fd < 0)
        goto fail;
    hdr_buf = sceKernelLoadcoreKallocForKernel(0x10005, 0x1000+63);
    hdr_buf_aligned = (char *)(((int)hdr_buf + 63) & 0xFFFFFFC0);
    printf("Header buffer: 0x%08X, aligned: 0x%08X\n", hdr_buf, hdr_buf_aligned);
    if (hdr_buf == NULL)
        goto fail;
    ret = sceIoReadForDriver(fd, hdr_buf_aligned, 0x1000);
    printf("Header read: 0x%08X\n", ret);
    hdr_size = *(unsigned int *)(hdr_buf_aligned + 0x10);
    if (hdr_size > 0x1000) {
        printf("Header too large: 0x%08X\n", hdr_size);
        goto fail;
    }
    ret = sceIoLseekForDriver(fd, 0LL, 0);
    printf("Header rewind: 0x%08X\n", ret);

    // set up SBL decryption for this SELF
    ret = sceSblAuthMgrAuthHeaderForKernel(ctx, hdr_buf_aligned, hdr_size, somebuf);
    printf("sceSblAuthMgrAuthHeaderForKernel: 0x%08X\n", ret);
    if (ret < 0)
        goto fail;

    // set up read buffer
    data_buf = sceKernelLoadcoreKallocForKernel(0x10005, 0x10000+63);
    data_buf_aligned = (char *)(((int)data_buf + 63) & 0xFFFFFFC0);
    printf("Data buffer: 0x%08X, aligned: 0x%08X\n", data_buf, data_buf_aligned);
    if (data_buf == NULL)
        goto fail;

    // get sections
    int elf_offset = *(int*)(hdr_buf_aligned + 0x40);
    int num_segs = *(short*)(hdr_buf_aligned + elf_offset + 0x2C);
    printf("Number of segments to read: 0x%04X\n", num_segs);
    int info_offset = *(int*)(hdr_buf_aligned + 0x58);
    struct seg_info *segs = (struct seg_info *)(hdr_buf_aligned + info_offset);
    int phdr_offset = *(int*)(hdr_buf_aligned + 0x48);
    struct e_phdr *phdrs = (struct e_phdr *)(hdr_buf_aligned + phdr_offset);

    // decrypt sections
    int i;
    int total, to_read, num_read, off;
    int aligned_size;
    int blkid = 0;
    void *pgr_buf;
    for (i = 0; i < num_segs; i++) {
        sprintf(outpath, "%s.seg%u", outprefix, i);
        sceIoCloseForDriver(wfd);
        wfd = sceIoOpenForDriver(outpath, 0x602, 6);
        printf("sceIoOpenForDriver(%s): 0x%08X\n", outpath, wfd);
        if (wfd < 0)
            break;

        if (blkid)
            sceKernelFreeMemBlockForKernel(blkid);
        aligned_size = (phdrs[i].p_filesz + 4095) & 0xFFFFF000;
        if (usecdram)
            blkid = sceKernelAllocMemBlockForKernel("self_decrypt_buffer", 0x40404006, 0x4000000, NULL);
        else
            blkid = sceKernelAllocMemBlockForKernel("self_decrypt_buffer", 0x1020D006, aligned_size, NULL);
        printf("sceKernelAllocMemBlockForKernel: 0x%08X, size: 0x%08X\n", blkid, aligned_size);
        ret = sceKernelGetMemBlockBaseForKernel(blkid, &pgr_buf);
        printf("sceKernelGetMemBlockBaseForKernel: 0x%08X, base: 0x%08X\n", ret, pgr_buf);
        if (ret < 0)
            break;

        // setup buffer for output
        ret = sceSblAuthMgrSetupAuthSegmentForKernel(ctx, i, (u32_t)segs[i].length, pgr_buf, phdrs[i].p_filesz);
        printf("sceSblAuthMgrSetupAuthSegmentForKernel: 0x%08X\n", ret);
        if (ret < 0)
            break;

        ret = sceIoLseekForDriver(fd, segs[i].offset, 0);
        printf("sceIoLseekForDriver(0x%08X): 0x%08X\n", (u32_t)segs[i].offset, ret);
        if (ret < 0)
            break;
        total = (u32_t)segs[i].length;
        to_read = total > 0x10000 ? 0x10000 : total;
        off = 0;
        while (total > 0 && (num_read = sceIoReadForDriver(fd, data_buf_aligned+off, to_read)) > 0) {
            off += num_read;
            total -= num_read;
            if (num_read < to_read) {
                to_read -= num_read;
                continue;
            }

            ret = sceSblAuthMgrAuthSegmentForKernel(ctx, data_buf_aligned, off); // decrypt buffer
            printf("sceSblAuthMgrAuthSegmentForKernel: 0x%08X\n", ret);
            if (ret < 0)
                printf("!!! ERROR !!!\n");
            ret = sceSblAuthMgrLoadSegmentInternalForKernel(ctx, data_buf_aligned, off); // copy buffer to output
            printf("sceSblAuthMgrLoadSegmentInternalForKernel: 0x%08X\n", ret);
            if (ret < 0)
                printf("!!! ERROR !!!\n");

            off = 0;
            to_read = total > 0x10000 ? 0x10000 : total;
        }

        // write buffer
        off = 0;
        while ((off += sceIoWriteForDriver(wfd, pgr_buf+off, phdrs[i].p_filesz-off)) < phdrs[i].p_filesz);
    }
    if (blkid)
        sceKernelFreeMemBlockForKernel(blkid);
    sceIoCloseForDriver(wfd);

fail:
    sceSblAuthMgrCloseForKernel(ctx);
    if (fd)
        sceIoCloseForDriver(fd);
    if (somebuf)
        sceKernelLoadcoreKfreeForKernel(somebuf);
    if (hdr_buf)
        sceKernelLoadcoreKfreeForKernel(hdr_buf);
    if (data_buf)
        sceKernelLoadcoreKfreeForKernel(data_buf);
    return 1;
}

Module decryption and signature checks ("HENkaku patches" on 1.60)

See also SELF_Loading to see how these SceSblAuthMgr functions are used to decrypt SELFs.

The code below will patch signature checks and bypass module decryption and allow homebrews to run. The idea is to hook SceSblAuthMgr* calls that are imported to SceKernelModulemgr. The offsets are from 1.60, you will probably need to modify functions defines (set to addresses of functions) and INSTALL_HOOK second arguments (set to addresses of imports in SceKernelModulemgr). For old FWs like 1.60, as there is no kASLR, you can set hardcoded addresses, else take HENkaku code. As a bonus there's also patch_npdrm functions that patches SceNpDrm to bypass some DRM checks and allow unsigned packages to be installed, which you also need to modify addresses. See SceNpDrm#Package_integrity_checks.

// hardcoded addresses for 1.60
#define G_OUR_EBOOT *(unsigned*)(0x01E60000 - 0x14)
#define G_BUF *(unsigned*)(0x01E60000 - 0xC)
#define G_WRITTEN *(unsigned*)(0x01E60000 - 0x10)

#define Func(addr) ((unsigned(*)())(addr))

// Hardcoded addresses for 1.60
#define sceSblAuthMgrAuthHeaderForKernel Func(0x4BC6C9)
#define sceSblAuthMgrSetupAuthSegmentForKernel Func(0x4BC851)
#define sceSblAuthMgrAuthSegmentForKernel Func(0x4BC909)
#define sceSblAuthMgrLoadSegmentInternalForKernel Func(0x4BCA89)


// setup file decryption
unsigned sceSblAuthMgrAuthHeaderForKernel_patched(unsigned a1, unsigned a2, unsigned a3, unsigned a4) {
    unsigned res = sceSblAuthMgrAuthHeaderForKernel(a1, a2, a3, a4);

    if (res == 0x800f0624 || res == 0x800f0616 || res == 0x800f0024) {
        G_OUR_EBOOT = 1;

        // patch somebuf so our module actually runs
        unsigned *somebuf = (unsigned*)a4;
        somebuf[42] = 0x40;

        return 0;
    } else {
        G_OUR_EBOOT = 0;
    }
    return res;
}

// setup output buffer
unsigned sceSblAuthMgrSetupAuthSegmentForKernel_patched(unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5) {
    G_BUF = a4;
    G_WRITTEN = 0;
    if (G_OUR_EBOOT == 1) {
        return 0;
    }
    return sceSblAuthMgrSetupAuthSegmentForKernel(a1, a2, a3, a4, a5);
}

// decrypt
unsigned sceSblAuthMgrAuthSegmentForKernel_patched(unsigned a1, unsigned a2, unsigned a3) {
    if (G_OUR_EBOOT == 1) {
        return 0;
    }
    return sceSblAuthMgrAuthSegmentForKernel(a1, a2, a3);
}

// copy to output - not present on 3.60
unsigned sceSblAuthMgrLoadSegmentInternalForKernel_patched(unsigned a1, unsigned a2, unsigned a3) {
    if (G_OUR_EBOOT == 1) {
        memcpy((void*)(G_BUF + G_WRITTEN), (void*)a2, a3);
        G_WRITTEN += a3;
        return 0;
    }
    return sceSblAuthMgrLoadSegmentInternalForKernel(a1, a2, a3);
}

#define INSTALL_HOOK(func, addr) \
    { unsigned *target; \
    target = (unsigned*)addr; \
    *target++ = 0xE59FF000; /* ldr pc, [pc, #0] */ \
    *target++; /* doesn't matter */ \
    *target = (unsigned)func; \
    }

// hardcoded addresses for 1.60
void hook_install(void) {
    INSTALL_HOOK(sceSblAuthMgrLoadSegmentInternalForKernel_patched, 0x5BA9CC);
    INSTALL_HOOK(sceSblAuthMgrSetupAuthSegmentForKernel_patched, 0x5BA9DC);
    INSTALL_HOOK(sceSblAuthMgrAuthSegmentForKernel_patched, 0x5BAA0C);
    INSTALL_HOOK(sceSblAuthMgrAuthHeaderForKernel_patched, 0x5BAA1C);
}

unsigned get_module_base(const char *name) {
    int * modlist[MOD_LIST_SIZE];
    int modlist_records;
    int res;
    SceKernelModuleInfo modinfo;

    memset(modlist, 0, sizeof(modlist));
    modlist_records = MOD_LIST_SIZE;
    sceKernelGetModuleListForKernel(0x10005, 0x7FFFFFFF, 1, modlist, &modlist_records);

    for(int j = 0; j < modlist_records; j++) {
        memset(&modinfo, 0, sizeof(modinfo));
        res = sceKernelGetModuleInfoForKernel(modlist[j], &modinfo);
        if (strcmp(modinfo.name, name) == 0)
            return (unsigned)modinfo.module_top;
    }
    return 0;
}

// Hardcoded addresses for 1.60
void patch_npdrm(unsigned base) {
    unsigned *patch;
    // check where check_func[0] is called
    patch = (unsigned*)(base + 0x310);
    *patch = 0x47702001;
    // check where check_func[1] is called
    patch = (unsigned*)(base + 0xaa4);
    *patch = 0x47702001;

    // always return 1 in install_allowed
    patch = (unsigned*)(base + 0x2d64);
    *patch = 0x47702001;
    // patch error code 0x80870003
    patch = (unsigned*)(base + 0x4856);
    *patch = 0x2500;
    // second same error code
    patch = (unsigned*)(base + 0x35fe);
    *patch = 0x2600;
}

// Call this function from a thread
int hook(void) {
    fprintf("Hook start\n");

    unsigned prev_dacr;
    __asm__ volatile("mrc p15, 0, %0, c3, c0, 0" : "=r" (prev_dacr));
    __asm__ volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (-1));

    unsigned base_npdrm = get_module_base("SceNpDrm");
    fprintf("SceNpDrm base: 0x%08x\n", base_npdrm);
    patch_npdrm(base_npdrm);

    hook_install();

    __asm__ volatile("MCR    p15, 0, %0, c7, c5, 0" : : "r" (0)); // flush icache
    __asm__ volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (prev_dacr));

    sceKernelDelayThread(4*1000*1000);

    return 0;
}

SceModulemgrForKernel

sceKernelLibraryDBGetSyslibtraceCB

Version NID
0.990 0x3AE7F62F
3.60 not present

SceModulemgrForKernel_06D9392A

Version NID
0.990 0x06D9392A
3.60 not present
SceModulemgrForKernel_06D9392A(int modid, void *addr, int *out);

sceModulemgrLockLibDBForKernel

Version NID
0.990 0x37C2A1A5

sceModulemgrUnlockLibDBForKernel

Version NID
0.990 0x0751F162

SceModulemgrForKernel_2C2618D9

Version NID
0.990-3.60 0x2C2618D9

Used by sceKernelPrintBacktraceForDriver.

int SceModulemgrForKernel_2C2618D9(SceUID pid, void *a2, void *a3);

SceModulemgrForKernel_04ADDA3E

Version NID
0.990 0x04ADDA3E

sceKernelGetModuleIdByAddrForKernel

Version NID
0.990-3.60 0x0053BA4A
SceUID sceKernelGetModuleIdByAddrForKernel(SceUID pid, const void *module_addr);

sceKernelGetProcessEntryPointForKernel

Version NID
0.990 0xC72CA412
3.60 not present

sceKernelLoadcoreKallocForKernel

Version NID
0.990 0xB4A1DE31
void *sceKernelLoadcoreKallocForKernel(uint32_t size);

sceKernelFinalizeKblForKernel

Version NID
0.990-3.60 0xFDD7F646
3.65 0xB911516F

unload the ScePsp2BootConfig

void *sysroot_buffer = sceKernelGetSysrootBuffer;
kbl_modid = *(_DWORD *)(SceSysrootForKernel_CD70C9D7(sysroot_buffer) + 0x38);
sceKernelStopUnloadModuleForDriver(kbl_modid);
unk = *(_DWORD *)(SceSysrootForKernel_CD70C9D7(sysroot_buffer) + 0x34);
// then does other things with other sysroot functions

0.990

void sceKernelFinalizeKblForKernel(void);

3.60

int sceKernelFinalizeKblForKernel(void);

sceKernelRegisterSyscallForKernel

Version NID
3.60 0xB427025E
3.65-3.68 0x2E4A10A0
void sceKernelRegisterSyscallForKernel(uint32_t num, void *function);

sceKernelLoadPtLoadSegForFwloaderForKernel

Version NID
0.990-3.60 0x448810D5

sceKernelDecryptSelfByPathForKernel

Version NID
0.990-3.60 0x448810D5
3.65 0xA07063EA
int sceKernelDecryptSelfByPathForKernel(const char *path, int e_phnum, void *buffer, uint32_t bufsize, int zero_unk, uint32_t *bytes_read);

This is an easy way of decrypting SELFs but you are limited to the kinds of SELFs you can load in the current context (for example, you can't load user modules from kernel context). It is also susceptible to limitations of where the SELF can be loaded from. For example, you are not allowed to load SELFs found in os0: from ux0:. This is because it checks the PathId.

On 3.60, statically compiled self give an error.

sceKernelGetModuleListForKernel

Version NID
1.60-3.60 0x97CF7B4E
3.65 0xB72C75A4
int sceKernelGetModuleListForKernel(SceUID pid, int flags1, int flags2, SceUID *modids, SceSize *num);

sceKernelGetModuleList2ForKernel

Version NID
3.60 0x410E1D2E

Found by Princess

sceKernelGetModuleUidForKernel

Version NID
3.60 0x3B93CF88

Found by Princess

sceKernelGetModuleUidListForKernel

Version NID
3.60 0x1FDEAE16

Found by Princess

sceKernelGetModuleInfoForKernel

Version NID
3.60 0xD269F915
3.65 0xDAA90093
int sceKernelGetModuleInfoForKernel(SceUID pid, SceUID modid, SceKernelModuleInfo *info);

sceKernelGetModuleLibraryInfoForKernel

Version NID
3.60 0x6A655255

typedef struct SceKernelModuleLibraryInfo {
  SceSize size; //!< sizeof(SceKernelModuleLibraryInfo) : 0x120
  SceUID libid;
  uint32_t libnid;
  uint16_t libver[2];
  uint16_t entry_num_function;
  uint16_t entry_num_variable;
  uint16_t unk_0x14;
  uint16_t unk_0x16;
  char library_name[0x100]; // offset : 0x18
  uint32_t unk_0x118;
  SceUID modid2;
} SceKernelModuleLibraryInfo;

int sceKernelGetModuleLibraryInfoForKernel(SceUID pid, SceUID libid, SceKernelModuleLibraryInfo *info);

sceKernelGetProcessEntryPointForKernel

Version NID
0.990-3.60 0xFE303863

Temp name was sceKernelGetModuleInternalForKernel, sceKernelGetModuleCBForDebugger.

0.990:

void **sceKernelGetProcessEntryPointForKernel(SceUID modid);

3.60:

int sceKernelGetProcessEntryPointForKernel(SceUID modid, void **entrypoint);

sceKernelGetModuleLibExportListForKernel

Version NID
3.60 0xD4BF409C

typedef struct SceKernelModuleExportEntry {
	uint32_t libnid;
	const void *entry; // function ptr. or vars?
} SceKernelModuleExportEntry;

int sceKernelGetModuleLibExportListForKernel(SceUID pid, SceUID libid, SceKernelModuleExportEntry *list, SceSize *num, SceSize cpy_skip_num);

sceKernelGetProcessMainModuleForKernel

Version NID
3.60 0x20A27FA9
/**
 * @brief Get the main module for a given process.
 * @param pid The process to query.
 * @return the UID of the module else < 0 for an error.
 */
SceUID sceKernelGetProcessMainModuleForKernel(SceUID pid);

sceKernelGetModulePathForKernel

Version NID
3.60 0x779A1025

wrong name is sceKernelGetProcessMainModulePathForKernel

int sceKernelGetModulePathForKernel(SceUID modid, char *path, int pathlen);

sceKernelMountBootfsForKernel

Version NID
3.60 0x01360661
3.65 0x185FF1BC
int sceKernelMountBootfsForKernel(const char *bootImagePath);

sceKernelUmountBootfsForKernel

Version NID
3.60 0x9C838A6B
3.65 0xBD61AD4D
int sceKernelUmountBootfsForKernel(void);

sceKernelLoadModuleForPidForKernel

Version NID
3.60 0xFA21D8CB
/**
 * @brief Load module
 *
 * moduleFileName Loads the module specified by moduleFileName.
 * If the load is successful, the module identifier is returned as the return value.
 *
 * @param[in]	moduleFileName	file name
 * @param[in]	flags		flags
 * @param[in]	pOpt		option parameter, should be SCE_NULL
 * @retval	(>0)		module uid
 * @retval	(<0)		Error code
 */
SceUID sceKernelLoadModuleForPidForKernel(SceUID pid, const char *moduleFileName, SceUInt32 flags, const SceKernelLoadModuleOpt *pOpt);

sceKernelStartModuleForPidForKernel

Version NID
3.60 0x6DF745D5
// flags must be 0
// pOpt can be null

/**
 * @brief start module for process
 *
 * Starts the module specified by uid. When calling the start entry function,
 * the value specified by the args and argp arguments is passed as an argument.
 *
 * If the start process is successful, the library declared with AUTO_EXPORT will be registered.
 * Public processing is performed and the return value of the start entry function is stored in the area indicated by pRes.
 * If the start process fails, library registration and publishing will not be performed.
 *
 * SCE_KERNEL_START_NO_RESIDENT is returned as the return value of the start entry function
 * only if the module is automatically unloaded after executing the start entry function.
 * If SCE_KERNEL_START_FAILED is returned, the start process will fail.
 * At this time, the module is not unloaded. Modules that failed to start
 * It can be restarted with sceKernelStartModuleForPidForKernel().
 *
 * @param[in]	pid	process id
 * @param[in]	uid	module id
 * @param[in]	args	argument block size
 * @param[in]	argp	argument block address
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter, should be SCE_NULL
 * @param[out]	pRes	result of start entry
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
 */
int sceKernelStartModuleForPidForKernel(SceUID pid, SceUID uid, SceSize args, const void *argp, SceUInt32 flags, const SceKernelStartModuleOpt *pOpt, int *pRes);

sceKernelStopModuleForPidForKernel

Version NID
3.60 0x7BB4CE54
/**
 * @brief Stop module
 *
 * Stops the module specified by uid. When calling the stop entry function,
 * the values specified by the args and argp arguments are passed as arguments.
 *
 * If the stop process is successful, the library released from the module is deleted,
 * and the return value of the stop entry function is stored in the area indicated by pRes.
 * If stop processing fails, library deletion processing is not performed.
 *
 * Only when SCE_KERNEL_STOP_SUCCESS is returned as the return value of the
 * stop entry function, module stop processing succeeds.
 * If any other value is returned, module stop processing will fail.
 * The module that failed to stop can be restarted with sceKernelStopModuleForPidForKernel().
 *
 * @param[in]	pid	process id
 * @param[in]	uid	module id
 * @param[in]	args	argument block size
 * @param[in]	argp	argument block address
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter, should be SCE_NULL
 * @param[out]	pRes	result of stop entry
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
 */
int sceKernelStopModuleForPidForKernel(SceUID pid, SceUID uid, SceSize args, const void *argp, SceUInt32 flags, const SceKernelStopModuleOpt *pOpt, int *pRes);

sceKernelUnloadModuleForPidForKernel

Version NID
3.60 0x5972E2CC
/**
 * @brief Unload module
 *
 * Unloads the module specified by uid.
 *
 * @param[in]	pid     process id
 * @param[in]	uid     module id
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter
 *
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
int sceKernelUnloadModuleForPidForKernel(SceUID pid, SceUID uid, SceUInt32 flags, const SceKernelUnloadModuleOpt *pOpt);

sceKernelLoadProcessModulesForKernel

Temp name was sceKernelLoadPreloadingModulesForKernel. Was wrongly named sceKernelLoadStartDefaultSharedModulesForPidForKernel.

Version NID
1.69-3.60 0x3AD26B43

This loads the default shared modules for a process (only the ones that are actually imported). This includes, for example, SceLibKernel. Modules are loaded with flags 0x10000000 meaning that text pages can be shared. If dipsw 210 is set, then flag 0x1000 is set, meaning that if the existing page is found, do not share it but instead make a copy.

int sceKernelLoadProcessModulesForKernel(SceUID pid, void *unk_buf, int flags);

sceKernelLoadProcessImageForKernel

Version NID
0.990-3.60 0xAC4EABDB

typedef struct SceLoadProcessParam
{
	uint32_t sysver;
	char thread_name[0x20];
	uint32_t unk_0x24;		// ex:0x100000EC
	uint32_t unk_0x28;		// ex:0x6000
	uint32_t unk_0x2C;
	char unk_0x30[0x24];
	char module_name[0x1C];
	uint32_t unk_0x70;
	uint32_t unk_0x74;		// ex:0x790000
	void *unk_0x78;			// ex:0x81600814, data seg vaddr?
	char unk_0x7C[0x20];		// all 0xFF

	// more...
} SceLoadProcessParam;

/**
 * @brief load process image
 *
 * @param[in]    pid    - target pid
 * @param[in]    path   - path
 * @param[in]    a3     - unk, zero
 * @param[out]   a4
 * @param[out]   a5
 * @param[in]    a6     - unk, zero
 *
 * @return modid, < 0 on error.
 */
SceUID sceKernelLoadProcessImageForKernel(SceUID pid, const char *path, int a3, SceSelfAuthInfo *a4, SceLoadProcessParam *a5, int a6);

sceKernelUnloadProcessModulesForKernel

Temp name was sceKernelStopUnloadPreloadingModulesForKernel.

Version NID
0.990-3.60 0x0E33258E

sceKernelLoadcoreKfreeForKernel

Version NID
0.990-1.60 0xF4B2D8B8

Calls sceKernelFreeHeapMemoryForDriver.

sceKernelCallModuleSuspendEntryForKernel

Version NID
0.990 0x829E1C94

sceKernelLibraryDBGetLibEntHeadForKernel

Version NID
0.990 0x1100A1B8

SceModulemgrForKernel_19A65337

Version NID
0.990 0x19A65337

sceKernelLibraryDBSetSyslibtraceCBForKernel

Version NID
0.990 0x7E68D6EC

sceKernelStartProcessModulesForKernel

Version NID
3.60 0x432DCC7A
3.65 0x998C7AE9
int sceKernelStartProcessModulesForKernel(SceUID pid);

SceModulemgrForDriver

sceKernelGetModuleInfoByAddrForDriver

Version NID
0.990-3.60 0x1D9E0F7E

note : kernel only.

int sceKernelGetModuleInfoByAddrForDriver(const void *module_addr, SceKernelModuleInfo *info);

sceKernelRegisterLibaryForDriver

Version NID
0.990-3.60 0x861638AD

note : kernel only.

int sceKernelRegisterLibaryForDriver(const void *module_addr);

sceKernelReleaseLibaryForDriver

Version NID
0.990-3.60 0x0975B104

note : kernel only.

int sceKernelReleaseLibaryForDriver(const void *module_addr);

sceKernelGetModuleInfoForDriver

Version NID
0.990-1.69 0x36585DAF
3.60 moved to SceModulemgrForKernel

sceKernelSearchModuleByNameForDriver

Version NID
3.60 0xBBE1771C
SceUID sceKernelSearchModuleByNameForDriver(const char *module_name);

sceKernelGetSystemSwVersionForDriver

Version NID
0.940-3.60 0x5182E212
int sceKernelGetSystemSwVersionForDriver(SceKernelFwInfo *data);

sceKernelSetSystemSwVersionForDriver

Version NID
0.990-1.69 0x912AEB73
3.60 non existent. Integrated with sceKernelGetSystemSwVersionForDriver

sceKernelLoadStartModuleForDriver

Version NID
1.69-3.60 0x189BFBBB
/**
 * @brief PRX Load and start PRX
 *
 * moduleFileName After loading the PRX specified by the moduleFileName argument, start processing
 * is performed.
 *
 * During start processing, module_start () is called by a thread
 * that is initialized with SCE_KERNEL_DEFAULT_PRIORITY_USER as the priority
 * and SCE_KERNEL_STACK_SIZE_DEFAULT_USER_MAIN as the stack size.
 * When it is done, the argument block specified by the args and argp arguments are
 * copied to the thread stack and then passed to module_start().
 *
 * If loading and start processing is successful, the return value
 * of the start entry function is stored in the area indicated by pRes.
 *
 * If SCE_KERNEL_START_NO_RESIDENT is returned as the return value of module_start()
 * the module is not resident in memory and is automatically unloaded after module_start() is executed.
 * If SCE_KERNEL_START_FAILED is returned,
 * the PRX has failed to load. A PRX is resident (loaded) only if it
 * returns a value other than SCE_KERNEL_START_NO_RESIDENT
 * or SCE_KERNEL_START_FAILED, including SCE_KERNEL_START_RESIDENT.
 *
 * @param[in]	moduleFileName	file name
 * @param[in]	args		argument block size
 * @param[in]	argp		argument block address
 * @param[in]	flags		flags, should be 0
 * @param[in]	pOpt		option parameter, should be SCE_NULL
 * @param[out]	pRes		result of start entry
 *
 * @retval	(>0)		module uid
 * @retval	(<0)		Error code
 */
SceUID sceKernelLoadStartModuleForDriver(const char *moduleFileName, SceSize args, const void *argp, SceUInt32 flags, const SceKernelLoadModuleOpt *pOpt, int *pRes);

sceKernelLoadStartModuleForPidForDriver

Version NID
3.60 0x9D953C22
/**
 * @brief PRX Load and start PRX
 *
 * moduleFileName After loading the PRX specified by the moduleFileName argument, start processing
 * is performed.
 *
 * During start processing, module_start () is called by a thread
 * that is initialized with SCE_KERNEL_DEFAULT_PRIORITY_USER as the priority
 * and SCE_KERNEL_STACK_SIZE_DEFAULT_USER_MAIN as the stack size.
 * When it is done, the argument block specified by the args and argp arguments are
 * copied to the thread stack and then passed to module_start().
 *
 * If loading and start processing is successful, the return value
 * of the start entry function is stored in the area indicated by pRes.
 *
 * If SCE_KERNEL_START_NO_RESIDENT is returned as the return value of module_start()
 * the module is not resident in memory and is automatically unloaded after module_start() is executed.
 * If SCE_KERNEL_START_FAILED is returned,
 * the PRX has failed to load. A PRX is resident (loaded) only if it
 * returns a value other than SCE_KERNEL_START_NO_RESIDENT
 * or SCE_KERNEL_START_FAILED, including SCE_KERNEL_START_RESIDENT.
 *
 * @param[in]	pid		process id
 * @param[in]	moduleFileName	file name
 * @param[in]	args		argument block size
 * @param[in]	argp		argument block address
 * @param[in]	flags		flags, should be 0
 * @param[in]	pOpt		option parameter, should be SCE_NULL
 * @param[out]	pRes		result of start entry
 *
 * @retval	(>0)		module uid
 * @retval	(<0)		Error code
 */
SceUID sceKernelLoadStartModuleForPidForDriver(SceUID pid, const char *moduleFileName, SceSize args, const void *argp, SceUInt32 flags, const SceKernelLoadModuleOpt *pOpt, int *pRes);

sceKernelLoadStartSharedModuleForPidForDriver

Version NID
3.60 0xE2ADEF8D
/**
 * @brief PRX Load and start PRX
 *
 * moduleFileName After loading the PRX specified by the moduleFileName argument, start processing
 * is performed.
 *
 * During start processing, module_start () is called by a thread
 * that is initialized with SCE_KERNEL_DEFAULT_PRIORITY_USER as the priority
 * and SCE_KERNEL_STACK_SIZE_DEFAULT_USER_MAIN as the stack size.
 * When it is done, the argument block specified by the args and argp arguments are
 * copied to the thread stack and then passed to module_start().
 *
 * If loading and start processing is successful, the return value
 * of the start entry function is stored in the area indicated by pRes.
 *
 * If SCE_KERNEL_START_NO_RESIDENT is returned as the return value of module_start()
 * the module is not resident in memory and is automatically unloaded after module_start() is executed.
 * If SCE_KERNEL_START_FAILED is returned,
 * the PRX has failed to load. A PRX is resident (loaded) only if it
 * returns a value other than SCE_KERNEL_START_NO_RESIDENT
 * or SCE_KERNEL_START_FAILED, including SCE_KERNEL_START_RESIDENT.
 *
 * @param[in]	pid		process id
 * @param[in]	moduleFileName	file name
 * @param[in]	args		argument block size
 * @param[in]	argp		argument block address
 * @param[in]	flags		flags, should be 0
 * @param[in]	pOpt		option parameter, should be SCE_NULL
 * @param[out]	pRes		result of start entry
 *
 * @retval	(>0)		module uid
 * @retval	(<0)		Error code
 */
SceUID sceKernelLoadStartSharedModuleForPidForDriver(SceUID pid, const char *moduleFileName, SceSize args, const void *argp, SceUInt32 flags, const SceKernelLoadModuleOpt *pOpt, int *pRes);

sceKernelLoadModuleWithoutStartForDriver / sceKernelLoadModuleForDriver

Version NID
1.69-3.60 0x86D8D634
/**
 * @brief Load module
 *
 * moduleFileName Loads the module specified by moduleFileName.
 * If the load is successful, the module identifier is returned as the return value.
 *
 * @param[in]	moduleFileName	file name
 * @param[in]	flags		flags
 * @param[in]	pOpt		option parameter, should be SCE_NULL
 * @retval	(>0)		module uid
 * @retval	(<0)		Error code
 */
SceUID sceKernelLoadModuleForDriver(const char *moduleFileName, SceUInt32 flags, const SceKernelLoadModuleOpt *pOpt);

sceKernelStartModuleForDriver

Version NID
1.69-3.60 0x0675B682
// flags must be 0
// pOpt can be null

/**
 * @brief start module
 *
 * Starts the module specified by uid. When calling the start entry function,
 * the value specified by the args and argp arguments is passed as an argument.
 *
 * If the start process is successful, the library declared with AUTO_EXPORT will be registered.
 * Public processing is performed and the return value of the start entry function is stored in the area indicated by pRes.
 * If the start process fails, library registration and publishing will not be performed.
 *
 * SCE_KERNEL_START_NO_RESIDENT is returned as the return value of the start entry function
 * only if the module is automatically unloaded after executing the start entry function.
 * If SCE_KERNEL_START_FAILED is returned, the start process will fail.
 * At this time, the module is not unloaded. Modules that failed to start
 * It can be restarted with sceKernelStartModuleForDriver().
 *
 * @param[in]	uid	module id
 * @param[in]	args	argument block size
 * @param[in]	argp	argument block address
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter, should be SCE_NULL
 * @param[out]	pRes	result of start entry
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
 */
int sceKernelStartModuleForDriver(SceUID uid, SceSize args, const void *argp, SceUInt32 flags, const SceKernelStartModuleOpt *pOpt, int *pRes);

sceKernelStopUnloadModuleForDriver

Version NID
1.69-3.60 0x03B30B7E
// flags must be 0
// opt can be null

/**
 * @brief Stop and unload PRX
 *
 * After stopping the PRX specified by the uid argument, unloading is performed.
 *
 * During stop processing, module_stop() is called by a thread that is
 * initialized with SCE_KERNEL_DEFAULT_PRIORITY_USER as the priority
 * and SCE_KERNEL_STACK_SIZE_DEFAULT_USER_MAIN as the stack size.
 * When it is done, the argument blocks specified by the args and argp
 * arguments are copied onto the thread stack and then passed to module_stop().
 *
 * If the stop process is successful, the library released from PRX
 * is deleted and then unloaded, and the return value of
 * the stop entry function is stored in the area indicated by pRes.
 *
 * PRX stop and unload processing has failed only if SCE_KERNEL_STOP_CANCEL
 * is returned as the return value of module_stop().
 * If any other value is returned, stop and unload processing has succeeded.
 *
 * @param[in]	uid	module id
 * @param[in]	args	argument block size
 * @param[in]	argp	argument block address
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter, should be SCE_NULL
 * @param[out]	pRes	result of stop entry
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
 */
int sceKernelStopUnloadModuleForDriver(SceUID uid, SceSize args, const void *argp, SceUInt32 flags, const SceKernelUnloadModuleOpt *pOpt, int *pRes);

sceKernelStopUnloadModuleForPidForDriver

Version NID
3.60 0x49A3EDC7
/**
 * @brief Stop and unload PRX
 *
 * After stopping the PRX specified by the uid argument, unloading is performed.
 *
 * During stop processing, module_stop() is called by a thread that is
 * initialized with SCE_KERNEL_DEFAULT_PRIORITY_USER as the priority
 * and SCE_KERNEL_STACK_SIZE_DEFAULT_USER_MAIN as the stack size.
 * When it is done, the argument blocks specified by the args and argp
 * arguments are copied onto the thread stack and then passed to module_stop().
 *
 * If the stop process is successful, the library released from PRX
 * is deleted and then unloaded, and the return value of
 * the stop entry function is stored in the area indicated by pRes.
 *
 * PRX stop and unload processing has failed only if SCE_KERNEL_STOP_CANCEL
 * is returned as the return value of module_stop().
 * If any other value is returned, stop and unload processing has succeeded.
 *
 * @param[in]	pid	process id
 * @param[in]	uid	module id
 * @param[in]	args	argument block size
 * @param[in]	argp	argument block address
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter, should be SCE_NULL
 * @param[out]	pRes	result of stop entry
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
 */
int sceKernelStopUnloadModuleForPidForDriver(SceUID pid, SceUID uid, SceSize args, const void *argp, SceUInt32 flags, const SceKernelUnloadModuleOpt *pOpt, int *pRes);

sceKernelStopUnloadSharedModuleForPidForDriver

Version NID
3.60 0x02D3D0C1
int sceKernelStopUnloadSharedModuleForPidForDriver(SceUID pid, SceUID modid, SceSize args, void *argp, int flags, SceKernelULMOption *option, int *status);

sceKernelStopModuleForDriver

Version NID
1.69-3.60 0x100DAEB9
/**
 * @brief Stop module
 *
 * Stops the module specified by uid. When calling the stop entry function,
 * the values specified by the args and argp arguments are passed as arguments.
 *
 * If the stop process is successful, the library released from the module is deleted,
 * and the return value of the stop entry function is stored in the area indicated by pRes.
 * If stop processing fails, library deletion processing is not performed.
 *
 * Only when SCE_KERNEL_STOP_SUCCESS is returned as the return value of the
 * stop entry function, module stop processing succeeds.
 * If any other value is returned, module stop processing will fail.
 * The module that failed to stop can be restarted with sceKernelStopModuleForDriver().
 *
 * @param[in]	uid	module id
 * @param[in]	args	argument block size
 * @param[in]	argp	argument block address
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter, should be SCE_NULL
 * @param[out]	pRes	result of stop entry
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
 */
int sceKernelStopModuleForDriver(SceUID uid, SceSize args, const void *argp, SceUInt32 flags, const SceKernelStopModuleOpt *pOpt, int *pRes);

sceKernelUnloadModuleForDriver

Version NID
1.69-3.60 0x728E72A6

In 1.69 existed in SceModulemgrForKernel

/**
 * @brief Unload module
 *
 * Unloads the module specified by uid.
 *
 * @param[in]	uid     module id
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter
 *
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
int sceKernelUnloadModuleForDriver(SceUID uid, SceUInt32 flags, const SceKernelUnloadModuleOpt *pOpt);

load_with_logs

Version NID
0.990 0x57EE2372

SceModulemgr

__sceKernelLoadModuleWithoutStart

Version NID
0.990-1.69 0xA4E6DA4D
3.60 non existent
/**
 * @brief Load module
 *
 * moduleFileName Loads the module specified by moduleFileName.
 * If the load is successful, the module identifier is returned as the return value.
 *
 * @param[in]	moduleFileName	file name
 * @param[in]	flags		flags
 * @param[in]	pOpt		option parameter, should be SCE_NULL
 * @retval	(>0)		module uid
 * @retval	(<0)		Error code
 */
SceUID __sceKernelLoadModuleWithoutStart(const char *moduleFileName, SceUInt32 flags, const SceKernelLoadModuleOpt *pOpt);

_sceKernelLoadModule

Version NID
1.69 non existent
3.60 0xB4C5EF9E
/**
 * @brief Load module
 *
 * moduleFileName Loads the module specified by moduleFileName.
 * If the load is successful, the module identifier is returned as the return value.
 *
 * @param[in]	moduleFileName	file name
 * @param[in]	flags		flags
 * @param[in]	pOpt		option parameter, should be SCE_NULL
 * @retval	(>0)		module uid
 * @retval	(<0)		Error code
 */
SceUID _sceKernelLoadModule(const char *moduleFileName, SceUInt32 flags, const SceKernelLoadModuleOpt *pOpt);

_sceKernelLoadStartModule

Version NID
1.69 non existent
3.60 0x60647592
/**
 * @brief PRX Load and start PRX
 *
 * moduleFileName After loading the PRX specified by the moduleFileName argument, start processing
 * is performed.
 *
 * During start processing, module_start () is called by a thread
 * that is initialized with SCE_KERNEL_DEFAULT_PRIORITY_USER as the priority
 * and SCE_KERNEL_STACK_SIZE_DEFAULT_USER_MAIN as the stack size.
 * When it is done, the argument block specified by the args and argp arguments are
 * copied to the thread stack and then passed to module_start().
 *
 * If loading and start processing is successful, the return value
 * of the start entry function is stored in the area indicated by pRes.
 *
 * If SCE_KERNEL_START_NO_RESIDENT is returned as the return value of module_start()
 * the module is not resident in memory and is automatically unloaded after module_start() is executed.
 * If SCE_KERNEL_START_FAILED is returned,
 * the PRX has failed to load. A PRX is resident (loaded) only if it
 * returns a value other than SCE_KERNEL_START_NO_RESIDENT
 * or SCE_KERNEL_START_FAILED, including SCE_KERNEL_START_RESIDENT.
 *
 * @param[in]	moduleFileName	file name
 * @param[in]	args		argument block size
 * @param[in]	argp		argument block address
 * @param[in]	flags		flags, should be 0
 * @param[in]	pOpt		option parameter, should be SCE_NULL
 * @param[out]	pRes		result of start entry
 *
 * @retval	(>0)		module uid
 * @retval	(<0)		Error code
 */
SceUID _sceKernelLoadStartModule(const char *moduleFileName, SceSize args, const void *argp, SceUInt32 flags, const SceKernelLoadModuleOpt *pOpt, int *pRes);

__sceKernelStartModule

Version NID
0.990-1.69 0x1FD99C9F
3.60 non existent
/**
 * @brief start module
 *
 * Starts the module specified by uid. When calling the start entry function,
 * the value specified by the args and argp arguments is passed as an argument.
 *
 * If the start process is successful, the library declared with AUTO_EXPORT will be registered.
 * Public processing is performed and the return value of the start entry function is stored in the area indicated by pRes.
 * If the start process fails, library registration and publishing will not be performed.
 *
 * SCE_KERNEL_START_NO_RESIDENT is returned as the return value of the start entry function
 * only if the module is automatically unloaded after executing the start entry function.
 * If SCE_KERNEL_START_FAILED is returned, the start process will fail.
 * At this time, the module is not unloaded. Modules that failed to start
 * It can be restarted with __sceKernelStartModule().
 *
 * @param[in]	uid	module id
 * @param[in]	args	argument block size
 * @param[in]	argp	argument block address
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter, should be SCE_NULL
 * @param[out]	pRes	result of start entry
 * @retval		SCE_OK	success
 * @retval		(<0)	Error code
 */
int __sceKernelStartModule(SceUID uid, SceSize args, const void *argp, SceUInt32 flags, const SceKernelStartModuleOpt *pOpt, int *pRes);

_sceKernelStartModule

Version NID
1.69 non existent
3.60 0x72CD301F
/**
 * @brief start module
 *
 * Starts the module specified by uid. When calling the start entry function,
 * the value specified by the args and argp arguments is passed as an argument.
 *
 * If the start process is successful, the library declared with AUTO_EXPORT will be registered.
 * Public processing is performed and the return value of the start entry function is stored in the area indicated by pRes.
 * If the start process fails, library registration and publishing will not be performed.
 *
 * SCE_KERNEL_START_NO_RESIDENT is returned as the return value of the start entry function
 * only if the module is automatically unloaded after executing the start entry function.
 * If SCE_KERNEL_START_FAILED is returned, the start process will fail.
 * At this time, the module is not unloaded. Modules that failed to start
 * It can be restarted with _sceKernelStartModule().
 *
 * @param[in]	uid	module id
 * @param[in]	args	argument block size
 * @param[in]	argp	argument block address
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter, should be SCE_NULL
 * @param[out]	pRes	result of start entry
 * @retval		SCE_OK	success
 * @retval		(<0)	Error code
 */
int _sceKernelStartModule(SceUID uid, SceSize args, const void *argp, SceUInt32 flags, const SceKernelStartModuleOpt *pOpt, int *pRes);

__sceKernelStopModule

Version NID
0.990-1.69 0xBA49EA5C
3.60 non existent
/**
 * @brief Stop module
 *
 * Stops the module specified by uid. When calling the stop entry function,
 * the values specified by the args and argp arguments are passed as arguments.
 *
 * If the stop process is successful, the library released from the module is deleted,
 * and the return value of the stop entry function is stored in the area indicated by pRes.
 * If stop processing fails, library deletion processing is not performed.
 *
 * Only when SCE_KERNEL_STOP_SUCCESS is returned as the return value of the
 * stop entry function, module stop processing succeeds.
 * If any other value is returned, module stop processing will fail.
 * The module that failed to stop can be restarted with __sceKernelStopModule().
 *
 * @param[in]	uid	module id
 * @param[in]	args	argument block size
 * @param[in]	argp	argument block address
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter, should be SCE_NULL
 * @param[out]	pRes	result of stop entry
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
 */
int __sceKernelStopModule(SceUID uid, SceSize args, const void *argp, SceUInt32 flags, const SceKernelStopModuleOpt *pOpt, int *pRes);

_sceKernelStopModule

Version NID
1.69 non existent
3.60 0x086867A8
/**
 * @brief Stop module
 *
 * Stops the module specified by uid. When calling the stop entry function,
 * the values specified by the args and argp arguments are passed as arguments.
 *
 * If the stop process is successful, the library released from the module is deleted,
 * and the return value of the stop entry function is stored in the area indicated by pRes.
 * If stop processing fails, library deletion processing is not performed.
 *
 * Only when SCE_KERNEL_STOP_SUCCESS is returned as the return value of the
 * stop entry function, module stop processing succeeds.
 * If any other value is returned, module stop processing will fail.
 * The module that failed to stop can be restarted with _sceKernelStopModule().
 *
 * @param[in]	uid	module id
 * @param[in]	args	argument block size
 * @param[in]	argp	argument block address
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter, should be SCE_NULL
 * @param[out]	pRes	result of stop entry
 * @retval		SCE_OK	success
 * @retval		(<0)	Error code
 */
int _sceKernelStopModule(SceUID uid, SceSize args, const void *argp, SceUInt32 flags, const SceKernelStopModuleOpt *pOpt, int *pRes);

_sceKernelStopUnloadModule

Version NID
1.69 non existent
3.60 0x86EAEA0A
/**
 * @brief Stop and unload PRX
 *
 * After stopping the PRX specified by the uid argument, unloading is performed.
 *
 * During stop processing, module_stop() is called by a thread that is
 * initialized with SCE_KERNEL_DEFAULT_PRIORITY_USER as the priority
 * and SCE_KERNEL_STACK_SIZE_DEFAULT_USER_MAIN as the stack size.
 * When it is done, the argument blocks specified by the args and argp
 * arguments are copied onto the thread stack and then passed to module_stop().
 *
 * If the stop process is successful, the library released from PRX
 * is deleted and then unloaded, and the return value of
 * the stop entry function is stored in the area indicated by pRes.
 *
 * PRX stop and unload processing has failed only if SCE_KERNEL_STOP_CANCEL
 * is returned as the return value of module_stop().
 * If any other value is returned, stop and unload processing has succeeded.
 *
 * @param[in]	uid	module id
 * @param[in]	args	argument block size
 * @param[in]	argp	argument block address
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter, should be SCE_NULL
 * @param[out]	pRes	result of stop entry
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
 */
int _sceKernelStopUnloadModule(SceUID uid, SceSize args, const void *argp, SceUInt32 flags, const SceKernelUnloadModuleOpt *pOpt, int *pRes);

__sceKernelUnloadModuleWithoutStop

Version NID
0.990-1.69 0xE439E26B
3.60 non existent
/**
 * @brief Unload module
 *
 * Unloads the module specified by uid.
 *
 * @param[in]	uid     module id
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter
 *
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
int __sceKernelUnloadModuleWithoutStop(SceUID uid, SceUInt32 flags, const SceKernelUnloadModuleOpt *pOpt);

_sceKernelUnloadModule

Version NID
1.69 non existent
3.60 0x8E4A7716
/**
 * @brief Unload module
 *
 * Unloads the module specified by uid.
 *
 * @param[in]	uid     module id
 * @param[in]	flags	flags, should be 0
 * @param[in]	pOpt	option parameter
 *
 * @retval	SCE_OK	success
 * @retval	(<0)	Error code
int _sceKernelUnloadModule(SceUID uid, SceUInt32 flags, const SceKernelUnloadModuleOpt *pOpt);

__sceKernelOpenModule

Version NID
0.990-1.69 0x9C2A9A49
3.60 non existent

_sceKernelOpenModule

Version NID
1.69 non existent
3.60 0x9D674F45

__sceKernelCloseModule

Version NID
0.990-1.69 0x5303C52F
3.60 non existent

_sceKernelCloseModule

Version NID
1.69 non existent
3.60 0x849E78BE

sceKernelKttyWrite

Version NID
0.940-1.69 0x4D76CF9E
3.60 non existent

sceKernelPutc

Version NID
0.990-1.69 0x9D2FE122
3.60 non existent

sceKernelGetSystemSwVersion

Version NID
0.940-3.60 0x5182E212

sceKernelSetSystemSwVersion

Version NID
0.990-1.69 0x912AEB73
3.60 non existent

sceKernelGetAllowedSdkVersionOnSystem

Version NID
1.69-3.60 0x4397FC4E

sceKernelGetModuleList

Version NID
1.69-3.60 0x2EF2581F

sceKernelGetModuleIdByAddr

Version NID
1.69-3.60 0xF5798C7C

sceKernelGetModuleInfo

Version NID
1.69-3.60 0x36585DAF

sceKernelGetLibraryInfoByNID

Version NID
0.990 not present
1.69-3.60 0xEAEB1312
int sceKernelGetLibraryInfoByNID(SceUID modid, uint32_t libnid, SceKernelLibraryInfo *pInfo);

sceKernelIsCalledFromSysModule

Version NID
1.69 non existent
3.60 0x85E6D2BB

sceKernelInhibitLoadingModule

Version NID
1.69 non existent
3.60 0x6CED1F63

Added somewhere between 3.30 an 3.60 to prevent loading Sysmodules from webbrowser (see Vitasploit 2.00-3.36 and h-encore 3.65-3.68 writeup).

SceBacktraceForDriver

sceKernelBacktraceForDriver

Version NID
0.990-3.60 0x166B9C8C
// a4 size = 0x10
int sceKernelBacktraceForDriver(int a1, int a2, int a3, char* a4);

sceKernelPrintBacktraceForDriver

Version NID
0.990 0xC5608386
3.60 0x7C878F90

sceKernelBacktraceInternalForDriver

Version NID
0.990 0xCECD5584
3.60 0x888E99B8

SceBacktrace

_sceKernelBacktrace

Version NID
3.60 0xBF371A98

Calls sceKernelBacktraceForDriver.

/**
 * Get backtrace
 * - When called with pCallFrameBuffer=NULL, numBytesBuffer=0,
 *   only the depth of the call stack can be obtained as a return value.
 *
 * @param	threadId		Thread ID, or SCE_KERNEL_BACKTRACE_CONTEXT_xxx
 * @param	pCallFrameBuffer	Buffer to get call frame
 * @param	numBytesBuffer		Buffer size (byte)
 * @param	pNumReturn		Pointer that receives the acquired number of frames
 * @param	mode			Action mode
 * @retval	(0)			Call stack depth, or SCE_OK
 * @retval	(<0)			Error code
 * @note	Callable only with TOOL
 */
SceInt32 _sceKernelBacktrace(
	SceUID			threadId,		/**< Thread ID, SCE_KERNEL_BACKTRACE_* can be used. */
	SceKernelCallFrame	*pCallFrameBuffer,	/**< buffer for frames */
	SceSize			numBytesBuffer,		/**< buffer size */
	SceUInt32		*pNumReturn,		/**< number of frames gathered. */
	SceInt32		mode			/**< KERNEL or USER mode. / DONT_EXCEED */
);

_sceKernelPrintBacktrace

Version NID
0.990 0x21F00CF2

Calls sceKernelPrintBacktraceForDriver.

/**
 * Display backtrace
 * @param	processId	Process ID to which the frame belongs
 * @param	pCallFrame	Stack frame data
 * @param	numFrames	Maximum step
 * @retval	(0)		Success
 * @retval	(<0)		Error code
 */
SceInt32 _sceKernelPrintBacktrace(
	SceUID				processId,
	const SceKernelCallFrame	*pCallFrame,
	SceUInt32			numFrames
);