Difference between revisions of "NSKBL"

From Vita Development Wiki
Jump to navigation Jump to search
 
(61 intermediate revisions by 3 users not shown)
Line 1: Line 1:
NSKBL is a program that performs emmc setup, base kernel module loading, etc. during PSVita boot.
+
The Non-Secure Kernel Boot Loader (NSKBL) is the first program that runs on ARM cores in Non-Secure state. As its name indicate, it has the role of initializing the Non-Secure state environment and loading the kernel from storage.
  
 
== Module ==
 
== Module ==
  
The non-secure kernel bootloader contains an embedded and likely stripped version of [[SceSysmem]], [[SceKernelModulemgr]], [[SceSblSmschedProxy]], [[SceExcpmgr]], [[SceKernelIntrMgr]], [[SceSblAuthMgr]], [[SceProcessmgr]] (maybe), [[SceSdif]], [[SceIofilemgr]] (Simple version?), and some other core drivers.
+
NSKBL is made of stripped down versions of some Non-Secure kernel modules along with code using all these functions to prepare the non-secure environment and load the next stage.
  
== How to debug NSKBL ==
+
Reduced versions of the following modules are embedded in NSKBL:
 +
* [[SceSysmem]]
 +
* [[SceKernelModulemgr]]
 +
* [[SceExcpmgr]]
 +
* [[SceKernelIntrMgr]]
 +
* [[SceSblAuthMgr]]
 +
* [[SceSblSmschedProxy]]
 +
* [[SceLowio]] (only parts of the Pervasive submodule)
 +
* [[SceSdif]]
 +
** <code>iofilemgr_if</code> serves as a thin wrapper around [[SceSdif]] for compatibility
 +
*** Only <code>sceIoOpen</code>, <code>sceIoLseek</code>, <code>sceIoRead</code> and <code>sceIoClose</code> are provided
 +
*** This is just a '''wrapper'''. [[SceIofilemgr]] is '''not''' included in NSKBL!
  
NSKBL supports sd0: for debugging.
+
It is very likely that the embedded modules in NSKBL are built from the same source tree as the Non-Secure kernel modules.
 +
This can be inferred from debugging information contained in some modules (line numbers in NSKBL and module equivalent match).
  
sysroot->boot_type_indicator_1:0x40000 is required.
+
== Notes ==
 +
 
 +
=== How to debug NSKBL ===
 +
 
 +
NSKBL supports sd0: for debugging. pKblParam->boot_type_indicator_1 = 0x40000 is required.
 +
 
 +
=== sceIoOpen(?) error code 0x803FF007 ===
 +
 
 +
This error can occur if the file is fragmented.
 +
 
 +
== NSKBL walk through ==
 +
 
 +
This section aims to provide an overview of the tasks performed by NSKBL. This description is based on System Software version 3.50 and later. Older versions may behave differently. See also [[NSKBL Subroutines]].
 +
 
 +
=== Reset ===
 +
 
 +
The NSKBL reset vector, located at <code>0x51000000</code>, is the first instruction executed in Non-Secure state, with the MMU turned off.
 +
It jumps to a small ASM function that disables interrupts (<code>cpsid if</code>), clears exclusive access requests (<code>clrex</code>), invalidates all caches, sets up stacks for all processors modes, and calls <code>boot</code>.
 +
 
 +
=== <code>boot</code> ===
 +
 
 +
This function is responsible for turning on the MMU. It partially initializes the <code>SceKernelBootParam</code>, copies the [[KBL Param]] from <code>0x40200100</code> (where it was placed by [[SKBL]]) and prints the <code>Starting PSP2 Kernel Boot Loader (Non-secure)</code> message.
 +
 
 +
The <code>SceKernelBootParam</code> initialization includes allocating physical and virtual pages for things like page tables, TTBR, fixed heaps, Sysroot, PhyPageTable, etc. The virtual address for the smaller mappings is randomized in the first 1 MiB of the address space (255 page-sized slots - first slot is reserved for NULL page), while larger allocations are randomized in the first 16 MiB (15 section-sized slots - slot 0 is reserved for the small ASLR mappings). A few mappings are exempted from randomization, like the identity mapping of <code>0x51000000</code>-<code>0x51FFFFFF</code> where NSKBL resides. This memory range is mapped as RWX and seems to be the only RWX mapping in the Non-Secure kernel.
 +
 
 +
After all these mappings are complete, the MMU is turned on along with caches, branch predictor, and a few other things via the <code>SCTLR</code>. At this point, <code>boot</code> is done and <code>sceKblMain</code> is called.
 +
 
 +
=== <code>sceKblMain</code> ===
 +
 
 +
This function runs with the MMU enabled and receives a partially filled-in <code>SceKernelBootParam</code> from <code>boot()</code>.
 +
 
 +
This function begins with a call to <code>sceKernelSysrootStart</code> which initializes the Sysroot structure. The slack space after the structure in the <code>SceSysroot</code> mapping (which is 16KiB-sized) is turned into a "heap" as part of this process. Memory allocation needs are serviced from this space using <code>sceKernelSysrootAlloc</code>. At this point, there are no other kernel heaps available. Sysroot status is set to 1 by this function.
 +
 
 +
After the Sysroot is initialized, <code>sceKernelSysmemStart</code> is called, which initializes the embedded [[SceSysmem]] module. It is at this stage that all the Sysmem object classes are created. Sysroot status is set to 2 then 3 by this function. Kernel heaps are available after the Sysroot status is set to 3 i.e. when this function returns.
 +
 
 +
Now that Sysmem is initialized, 16-KiB-sized <code>SceKernelBootStackCoreX</code> memory blocks are allocated, and execution is transfered to <code>main2</code> after switching the stack pointer to these memblocks. Up until now, the stack it used was located in NSKBL <code>.bss</code> section.
 +
 
 +
=== <code>main2</code> ===
 +
 
 +
The <code>main2</code> function receives a filled-up <code>SceKernelBootParam</code> from <code>sceKblMain()</code>.
 +
 
 +
After setting the Sysroot status to 4, the remaining embedded modules are started (in order: <code>sceKernelModulemgrStart()</code>, [[SceExcpmgr]] start, <code>sceKernelIntrMgrStart</code>, <code>sceSblAuthMgrStart()</code> and [[SceSblSmschedProxy]] start). Once the embedded modules are started, Sysroot status is set to 0x10 and the final NSKBL function is called.
 +
 
 +
=== Final function ===
 +
 
 +
The final function receives the same <code>SceKernelBootParam</code> as <code>main2</code>.
 +
 
 +
It first calls [[NSKBL#sceSdStandaloneInitForKernel|sceSdStandaloneInit]] then loads and caches the <code>gcauthmgr</code>, <code>rmauth</code> and <code>encdec_w_portability</code> security modules.
 +
 
 +
After this, it loads [[ScePsp2BootConfig|<code>os0:kd/psp2bootconfig.skprx</code>]], links the [[NSKBL#SceKblForKernel|SceKblForKernel library]] to the module, and starts it with <code>SceKernelBootParam</code> address as <code>argp</code>.
 +
 
 +
NSKBL has now handed over control and simply remains resident until it is unmapped by [[SceSysStateMgr]]. See also [[SceKernelModulemgr#sceKernelFinalizeKblForKernel]].
  
 
== Types ==
 
== Types ==
  
 
<source lang="C">
 
<source lang="C">
 +
 +
typedef struct KBPMemoryRegion {
 +
    SceUIntPtr pbase;
 +
    SceSize psize;
 +
} KBPMemoryRegion;
 +
 +
typedef struct KBPMappingInfo {
 +
    char *name;        //<! Name of the mapping
 +
    SceUIntPtr pbase;    //<! Base physical address of the mapping
 +
    SceUIntPtr vbase;    //<! Base virtual address of the mapping
 +
    SceSize psize;    //<! Size of the physical range of the mapping??
 +
    SceSize vsize;    //<! Size of the virtual range of the mapping?? - Usually equal to psize, but may be bigger.
 +
    SceUInt32 extraHigh; //<! Sometimes used as extraHigh for some memblock allocations? Exact meaning unknown.
 +
    // psize + extraHigh must always be equal to vsize
 +
} KBPMappingInfo;
 +
 +
typedef struct KBPBootStackInfo {
 +
    unsigned unk0[2];
 +
    SceUIntPtr ttbcr;
 +
    SceUInt32 dacr;
 +
    SceUInt32 asid;
 +
    SceSize size;
 +
    SceUID blkId;      //<! UID of the stack's memblock
 +
    void *stackBottom; //<! = memblock.vbase + size
 +
} KBPBootStackInfo;
 +
 +
// This structure is passed as argp of modules like sysmem.skprx, etc
 +
// 0x51030100 on NSKBL
 +
typedef struct SceKernelBootParam { // Size is 0x310-bytes in 3.60-3.65 and 4.00. Layout appears to be identical.
 +
  SSceSize size;                //<! Size of this structure
 +
  SceBool secure;              //<! Is secure state? Always 0 in NSKBL
 +
  SceUInt32 num_memory;          //<! Number of filled elements in the next field
 +
  KBPMemoryRegion memory[4];    //<! Physical memory ranges usable by NSKBL and kernel
 +
  SceKblParam *pKblParam;        //<! Pointer to KBL Param
 +
  unsigned unk30[5];
 +
  SceUInt32 SoCInfo;              //<! = *(u32*)PERVASIVE_MISC
 +
  SceUInt32 pmisc_unk4;          //<! = *(u32*)(PERVASIVE_MISC + 4)
 +
  SceUInt32 KermitRevision;      //<! = SoCInfo & 0x1FFFF
 +
  SceUInt32 hwDependent[2];      //<! Depends on pKBLParam->hardwareInfo
 +
  KBPMappingInfo ttbr0;          //<! "SceKernelTTBR0", ASLR vbase, psize 0x4000
 +
  unsigned ttbr0_maxAddress;    //<! Maximal address covered by TTBR0
 +
  unsigned sizeTTBR0Address;    //<! Size of the address space covered by TTBR0
 +
  KBPMappingInfo ttbr1;          //<! "SceKernelTTBR1", ASLR vbase, psize 0x4000
 +
  unsigned sizeTTBR1Address;    //<! Size of the address space covered by TTBR1
 +
  void *L2PT000_mapbase;        //<! First vaddr mapped by "SceKernelL2PageTable000"
 +
  KPBMappingInfo reset;          //<! "SceKernelReset", vbase 0, psize 0x1000, extraHigh 0x3000
 +
  KBPMappingInfo excpEntry;      //<! "SceKernelExceptionEntry", ASLR vbase, psize 0x1000, extraHigh 0x1000
 +
  KBPMappingInfo l2pt000;        //<! "SceKernelL2PageTable000", ASLR vbase, psize 0x1000, extraHigh 0x1000
 +
  KBPMappingInfo l2vector;      //<! "SceKernelL2Vector", ASLR vbase, psize 0x4000, extraHigh 0x4000
 +
  KBPMappingInfo sysroot;        //<! "SceSysroot", ASLR vbase, psize 0x4000
 +
  KBPMappingInfo fh32b;          //<! "SceKernelFixedHeap32B", ASLR vbase, psize 0x10000
 +
  KBPMappingInfo fh48b;          //<! "SceKernelFixedHeap48B", ASLR vbase, psize 0x10000
 +
  KBPMappingInfo fh64b;          //<! "SceKernelFixedHeap64B", ASLR vbase, psize 0x10000
 +
  KBPMappingInfo fhUIDEntry;    //<! "SceKernelFixedHeapUIDEntry", ASLR vbase, psize 0x10000
 +
  KBPMappingInfo fhL2Object;    //<! "SceKernelFixedHeapForL2Object", ASLR vbase, psize 0x1000, extraHigh 0x1000
 +
  KBPMappingInfo unk188;        //<! Unused? NOTE: ASLR vbase = randomize in 255 slots, MegaASLR vbase = randomize in 15 slots
 +
  KBPMappingInfo phypage;        //<! "SceKernelPhyPageTable", MegaASLR vbase, psize 0x80000
 +
  KBPMappingInfo phypageHigh;    //<! "SceKernelPhyPageTableHigh", MegaASLR vbase, psize 0x80000, pbase 0x77F00000
 +
  KBPMappingInfo bootkernimg;    //<! "SceBootKernelImage", vbase=pbase=0x51000000, psize 0x1000000, extraHigh 0x1000000
 +
  KBPMappingInfo hwreg;          //<! Unnamed. vbase=pbase=0xE0000000, psize 0x8000000
 +
  SceCorelockContext *pCorelock;
 +
  KBPBootStackInfo bootCpu[4];  //<! bootCpu[X] corresponds to CPUX's info. Stack is pivoted to this when calling main2.
 +
  SceSysroot *pSysroot;                //<! Pointer to Sysroot structure
 +
  unsigned unk288;                      //<! Related to L2PageTable000? Always 0.
 +
  void *pL2PageTable000;                //<! Base address of the L2PageTable000
 +
  void *resetVector;                    //<! Goes into VBAR. = excpEntry.vbase + 0x100
 +
  SceKernelPhyMemPart *phyMemPartKD;    //<! "SceKernelPhyMemPartKD"
 +
  SceKernelPhyMemPart *phyMemPartTool;  //<! "SceKernelPhyMemPartTool". May be NULL
 +
  PhyPage *pPageKernelReset;            //<! PhyPage object describing the pages backing SceKernelReset
 +
  PhyPage *pPageL2PageTable000;        //<! PhyPage object describing the pages backing SceKernelL2PageTable000
 +
  PhyPage *pPageSysroot;                //<! PhyPage object describing the pages backing SceSysroot
 +
  PhyPage *pPageTTBR0;                  //<! PhyPage object describing the pages backing SceKernelTTBR0
 +
  PhyPage *pPageTTBR1;                  //<! PhyPage object describing the pages backing SceKernelTTBR1
 +
  PhyPage *pPageL2Vector;              //<! PhyPage object describing the pages backing SceKernelL2Vector
 +
  PhyPage *pPagePhypage;                //<! PhyPage object describing the pages backing SceKernelPhyPageTable
 +
  PhyPage *pPagePhypageHigh;            //<! PhyPage object describing the pages backing SceKernelPhyPageTableHigh
 +
  PhyPage *pPageBootKernelImage;        //<! PhyPage object describing the pages backing SceBootKernelImage????
 +
  PhyPage *pPageFixedHeap32B;          //<! PhyPage object describing the pages backing SceKernelFixedHeap32B
 +
  PhyPage *pPageFixedHeap48B;          //<! PhyPage object describing the pages backing SceKernelFixedHeap48B
 +
  PhyPage *pPageFixedHeap64B;          //<! PhyPage object describing the pages backing SceKernelFixedHeap64B
 +
  PhyPage *pPageFixedHeapForL2Object;  //<! PhyPage object describing the pages backing SceKernelFixedHeapForL2Object
 +
  SceUIDFixedHeapObject *pFixedHeap32B;
 +
  SceUIDFixedHeapObject *pFixedHeap48B;
 +
  SceUIDFixedHeapObject *pFixedHeap64B;
 +
  SceUIDFixedHeapObject *pFixedHeapForL2Object;
 +
  PhyPage *pPageUIDHeap;                //<! PhyPage object describing the pages backing SceKernelFixedUIDHeap??
 +
  SceUIDEntryHeapObject *pUIDHeap;      //<! Pointer to SceKernelFixedUIDHeap object
 +
  L2PageTableObject *pL2PT000Object;    //<! L2PageTableObject for SceKernelL2PageTable000
 +
  L2PageTableObject *pPhyPageTblL2PTO;  //<! L2PageTableObject for table used to map the PhyPageTable (located @ SceKernelL2PageTable000.pbase + 0x400)
 +
  SceUIDPartitionObject *pPartitionKernel; //<! Object of "SceKernelRoot" partition
 +
  SceUID uidPartitionKernel;              //<! UID of object above (0x10009)
 +
  SceUInt32 unk2F8[2];
 +
  void *data_0x300;
 +
  void *pPutcharHandler;
 +
  SceUInt32 minimum_log_level;
 +
  SceUInt32 magic;                          //<! 0x7F407C30
 +
} SceKernelBootParam;
 +
 +
typedef struct SceNskblModuleInfo { // size is 0xC on FWs 0.940-0.990
 +
    char* filename;    // Raw SKPRX file name (e.g. "sysmem.skprx"). Modules are loaded either from os0:kd/ or host0:module/.
 +
    SceUID moduleId;    // SCE_UID_INVALID_UID. It gets filled when loading.
 +
    SceUInt32 loadFlags; // Passed as flags to sceKernelLoadModule.
 +
} __attribute__((packed)) SceNskblModuleInfo;
 +
 +
typedef struct SceNskblModuleInfo2 { // size is 4 on FW 3.60
 +
    const char* filename;
 +
} __attribute__((packed)) SceNskblModuleInfo2;
 +
 +
typedef struct SceHardwareFlags { // size is 0x10 on FW 3.60
 +
    uint32_t data[4];
 +
} __attribute__((packed)) SceHardwareFlags;
  
 
/* Many pointers are NSKBL heap relationships */
 
/* Many pointers are NSKBL heap relationships */
Line 64: Line 238:
 
int unk_0xB4;
 
int unk_0xB4;
 
int unk_0xB8; // ex: 0x80
 
int unk_0xB8; // ex: 0x80
sysroot360_t *pSysroot;
+
sysroot_t *pSysroot;
 
void *unk_0xC0;
 
void *unk_0xC0;
 
void *unk_0xC4;
 
void *unk_0xC4;
Line 81: Line 255:
 
! Version !! Name !! World !! Visibility !! NID
 
! Version !! Name !! World !! Visibility !! NID
 
|-
 
|-
| 3.60-3.65 || [[NSKBL#SceKblForKernel|SceKblForKernel]] || Non-secure || Kernel || 0xD0FC2991
+
| 0.940-3.65 || [[NSKBL#SceKblForKernel|SceKblForKernel]] || Non-secure || Kernel || 0xD0FC2991
 
|}
 
|}
  
 
== SceKblForKernel ==
 
== SceKblForKernel ==
 +
 +
NOTE: this library is linked directly to <code>psp2bootconfig</code> instead of being registered, and can thus only be imported by this module.
 +
 +
=== sceSDrfpStartForKernel ===
 +
{| class="wikitable"
 +
|-
 +
! Version !! NID
 +
|-
 +
| 0.940-0.990 || 0x230456F3
 +
|-
 +
| 3.60 || not present
 +
|}
 +
 +
=== sceSDbgSdioStartForKernel ===
 +
{| class="wikitable"
 +
|-
 +
! Version !! NID
 +
|-
 +
| 0.940-0.990 || 0x29A8524D
 +
|-
 +
| 3.60 || not present
 +
|}
 +
 +
Requires DIPSW 193.
 +
 +
<source lang="C">SceInt32 sceSDbgSdioStartForKernel(void);</source>
 +
 +
=== sceSDfMgrStartForKernel ===
 +
{| class="wikitable"
 +
|-
 +
! Version !! NID
 +
|-
 +
| 0.940-0.990 || 0xAA8005E4
 +
|-
 +
| 3.60 || not present
 +
|}
  
 
=== sceKblPutcharForKernel ===
 
=== sceKblPutcharForKernel ===
Line 91: Line 301:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x08E9FAEB
+
| 0.940-3.60 || 0x08E9FAEB
 
|}
 
|}
  
In 3.60 this function is at 0x510172BD
+
This is a guessed name.
 +
 
 +
This function is at 0x510172BD in FW 3.60 and at 0x51003BE0 in FW 0.940.040.
  
 
<source lang="C">int sceKblPutcharForKernel(void *args, char c);</source>
 
<source lang="C">int sceKblPutcharForKernel(void *args, char c);</source>
Line 103: Line 315:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x13A5ABEF
+
| 0.940-3.60 || 0x13A5ABEF
 
|}
 
|}
  
In 3.60 this function is at 0x510137A9
+
In FW 3.60 this function is at 0x510137A9.
  
 
<source lang="C">int sceKernelPrintfForKernel(const char *fmt, ...);</source>
 
<source lang="C">int sceKernelPrintfForKernel(const char *fmt, ...);</source>
Line 115: Line 327:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x752E7EEC
+
| 0.940 || Not present
 +
|-
 +
| 0.990-3.60 || 0x752E7EEC
 
|}
 
|}
  
In 3.60 this function is at 0x51013841.
+
In FW 3.60 this function is at 0x51013841.
  
 
<source lang="C">int sceKernelPrintfLevelForKernel(int level, const char *fmt, ...);</source>
 
<source lang="C">int sceKernelPrintfLevelForKernel(int level, const char *fmt, ...);</source>
  
=== sceKblGetMinimumLogLevelForKernel ===
+
=== sceKernelGetDebugLevelForKernel ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xC011935A
+
| 0.940-3.60 || 0xC011935A
 
|}
 
|}
  
In 3.60 this function is at 0x51013921.
+
Temp name was sceKblGetMinimumLogLevelForKernel.
  
<source lang="C">int sceKblGetMinimumLogLevelForKernel(void);</source>
+
In FW 3.60 this function is at 0x51013921.
  
=== sceKblGetPutcharHandlerForKernel ===
+
<source lang="C">int sceKernelGetDebugLevelForKernel(void);</source>
 +
 
 +
=== sceKernelGetDebugPutcharForKernel ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x9B868276
+
| 0.940-3.60 || 0x9B868276
 
|}
 
|}
  
In 3.60 this function is at 0x51013765.
+
In FW 3.60 this function is at 0x51013765.
  
<source lang="C">void *sceKblGetPutcharHandlerForKernel(void);</source>
+
<source lang="C">void *sceKernelGetDebugPutcharForKernel(void);</source>
  
 
=== sceKernelSysrootProcessmgrStart2ForKernel ===
 
=== sceKernelSysrootProcessmgrStart2ForKernel ===
Line 151: Line 367:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x161D6FCC
+
| 0.940-3.60 || 0x161D6FCC
 
|}
 
|}
  
In 3.60 this function is at 0x510123DD.
+
In FW 3.60 this function is at 0x510123DD.
  
 
<source lang="C">int sceKernelSysrootProcessmgrStart2ForKernel(void);</source>
 
<source lang="C">int sceKernelSysrootProcessmgrStart2ForKernel(void);</source>
Line 163: Line 379:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x1DB28F02
+
| 0.940-3.60 || 0x1DB28F02
 
|}
 
|}
  
In 3.60 this function is at 0x510123A1.
+
In FW 3.60 this function is at 0x510123A1.
  
 
<source lang="C">int sceKernelSysrootThreadMgrStartAfterProcessForKernel(void);</source>
 
<source lang="C">int sceKernelSysrootThreadMgrStartAfterProcessForKernel(void);</source>
Line 175: Line 391:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xC7B77991
+
| 0.940-3.60 || 0xC7B77991
 
|}
 
|}
  
In 3.60 this function is at 0x5101297D.
+
In FW 3.60 this function is at 0x5101297D.
  
 
<source lang="C">int sceKernelSysrootIofilemgrStartForKernel(void);</source>
 
<source lang="C">int sceKernelSysrootIofilemgrStartForKernel(void);</source>
  
=== sceKblSysrootCpuCoreSyncAllForKernel ===
+
=== sceKernelSysrootCorelockUnlockForKernel ===
 +
{| class="wikitable"
 +
|-
 +
! Version !! NID
 +
|-
 +
| 0.940-3.60 || 0x314AA770
 +
|}
 +
 
 +
In FW 3.60 this function is at 0x510124FD.
 +
 
 +
<source lang="C">void sceKernelSysrootCorelockUnlockForKernel(void);</source>
 +
 
 +
=== sceKernelSysrootCorelockLockForKernel ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x314AA770
+
| 0.940-3.60 || 0x807B4437
 
|}
 
|}
  
In 3.60 this function is at 0x510124FD.
+
In FW 3.60 this function is at 0x510124E5.
  
<source lang="C">void sceKblSysrootCpuCoreSyncAllForKernel(void);</source>
+
<source lang="C">void sceKernelSysrootCorelockLockForKernel(SceUInt32 core);</source>
  
=== sceKblSysrootCpuCoreSyncWaitForKernel ===
+
=== sceKblCpuSuspendIntrForKernel_old ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x807B4437
+
| 0.940-0.990 || 0x99B2F981
 +
|-
 +
| 3.60 || not present
 
|}
 
|}
  
same to SceSysrootForKernel_8E4B61F1
+
This is a guessed name.
 +
 
 +
On FW 0.940, it calls a routine that simply executes <code>cpsid i</code> then returns 0.
  
In 3.60 this function is at 0x510124E5.
+
CPSID i ; Disable all interrupts except NMI (set PRIMASK)
  
<source lang="C">void sceKblSysrootCpuCoreSyncWaitForKernel(int core);</source>
+
Disables IRQ interrupts by setting the I-bit in the CPSR.
  
=== sceKblCpuDisableIrqInterruptsForKernel ===
+
=== sceKblCpuSuspendIntrForKernel_new ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.940-0.990 || Not present
 
|-
 
|-
 
| 3.60 || 0xDDB3A1A8
 
| 3.60 || 0xDDB3A1A8
 
|}
 
|}
  
In 3.60 this function is at 0x51003554.
+
This is a guessed name. Temp name was sceKblCpuSwitchInterruptsForKernel, sceKblCpuDisableIrqInterruptsForKernel.
  
Old wrong name is sceKblCpuSwitchInterruptsForKernel.
+
In FW 3.60 this function is at 0x51003554.
  
<source lang="C">void sceKblCpuDisableIrqInterruptsForKernel(void);</source>
+
<source lang="C">void sceKblCpuSuspendIntrForKernel_new(void);</source>
  
 
=== sceSblAimgrIsCEXForKernel ===
 
=== sceSblAimgrIsCEXForKernel ===
Line 227: Line 461:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x8A416887
+
| 0.940-3.60 || 0x8A416887
 
|}
 
|}
  
In 3.60 this function is at 0x510171B5.
+
In FW 3.60 this function is at 0x510171B5.
  
 
<source lang="C">int sceSblAimgrIsCEXForKernel(void);</source>
 
<source lang="C">int sceSblAimgrIsCEXForKernel(void);</source>
Line 239: Line 473:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xC3DDDE15
+
| 0.940-3.60 || 0xC3DDDE15
 
|}
 
|}
  
In 3.60 this function is at 0x51017175.
+
In FW 3.60 this function is at 0x51017175.
  
 
<source lang="C">int sceSblAimgrIsDiagForKernel(void);</source>
 
<source lang="C">int sceSblAimgrIsDiagForKernel(void);</source>
Line 250: Line 484:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.940-0.990 || Not present
 
|-
 
|-
 
| 3.60 || 0x5945F065
 
| 3.60 || 0x5945F065
 
|}
 
|}
  
In 3.60 this function is at 0x51017159.
+
In FW 3.60 this function is at 0x51017159.
  
 
<source lang="C">int sceSblAimgrIsDEXForKernel(void);</source>
 
<source lang="C">int sceSblAimgrIsDEXForKernel(void);</source>
Line 262: Line 498:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.990 || not present
 
|-
 
|-
 
| 3.60 || 0xB6C9ACF1
 
| 3.60 || 0xB6C9ACF1
 
|}
 
|}
  
In 3.60 this function is at 0x51017139.
+
In FW 3.60 this function is at 0x51017139.
  
 
<source lang="C">int sceSblAimgrIsToolForKernel(void);</source>
 
<source lang="C">int sceSblAimgrIsToolForKernel(void);</source>
Line 274: Line 512:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.990 || not present
 
|-
 
|-
 
| 3.60 || 0x943E7537
 
| 3.60 || 0x943E7537
 
|}
 
|}
  
In 3.60 this function is at 0x5101711D.
+
In FW 3.60 this function is at 0x5101711D.
  
 
<source lang="C">int sceSblAimgrIsTestForKernel(void);</source>
 
<source lang="C">int sceSblAimgrIsTestForKernel(void);</source>
Line 286: Line 526:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.990 || not present
 
|-
 
|-
 
| 3.60 || 0x838466E9
 
| 3.60 || 0x838466E9
 
|}
 
|}
  
In 3.60 this function is at 0x51017299.
+
In FW 3.60 this function is at 0x51017299.
  
 
<source lang="C">int sceSblAimgrIsVITAForKernel(void);</source>
 
<source lang="C">int sceSblAimgrIsVITAForKernel(void);</source>
Line 298: Line 540:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.990 || not present
 
|-
 
|-
 
| 3.60 || 0xA7BD4417
 
| 3.60 || 0xA7BD4417
 
|}
 
|}
  
In 3.60 this function is at 0x510172A1.
+
In FW 3.60 this function is at 0x510172A1.
  
 
<source lang="C">int sceSblAimgrIsDolceForKernel(void);</source>
 
<source lang="C">int sceSblAimgrIsDolceForKernel(void);</source>
Line 310: Line 554:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.990 || not present
 
|-
 
|-
 
| 3.60 || 0xB6D00D6D
 
| 3.60 || 0xB6D00D6D
 
|}
 
|}
  
In 3.60 this function is at 0x510171E5.
+
In FW 3.60 this function is at 0x510171E5.
  
 
<source lang="C">int sceSblAimgrIsGenuineDolceForKernel(void);</source>
 
<source lang="C">int sceSblAimgrIsGenuineDolceForKernel(void);</source>
  
=== sceKblLoadModuleForKernel ===
+
=== LoadModulesForKernel ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.940-0.990 || 0xFAE33FDD
 +
|-
 +
| 3.60 || not present
 +
|}
 +
 +
Load all modules from the provided list. The list end is marked by an entry with <code>moduleName = NULL</code>.
 +
 +
Module GUIDs are populated into the list, so it must be writeable.
 +
 +
<source lang="C">SceInt32 LoadModules(SceNskblModuleInfo* module_list);</source>
 +
 +
=== sceKernelBootLoadModulesForKernel ===
 +
{| class="wikitable"
 +
|-
 +
! Version !! NID
 +
|-
 +
| 0.990 || not present
 
|-
 
|-
 
| 3.60 || 0x6D7A1F18
 
| 3.60 || 0x6D7A1F18
 
|}
 
|}
  
In 3.60 this function is at 0x51001551.
+
Temp name was sceKblLoadModulesForKernel.
 +
 
 +
In FW 3.60 this function is at 0x51001551.
 +
 
 +
<source lang="C">int sceKernelBootLoadModulesForKernel(const SceNskblModuleInfo2 *pList, SceUID *pUidList, SceUInt32 count, SceBool use_tool_extended_memory);</source>
 +
 
 +
=== BootModulesForKernel ===
 +
{| class="wikitable"
 +
|-
 +
! Version !! NID
 +
|-
 +
| 0.940-0.990 || 0xA7D60F71
 +
|-
 +
| 3.60 || not present
 +
|}
 +
 
 +
Runs the entrypoint of all modules in provided list. The list end is marked by an entry with <code>moduleId = SCE_UID_INVALID_UID</code>.
  
 
<source lang="C">
 
<source lang="C">
typedef struct SceModuleLoadList {
+
// If run_boot_entry is SCE_TRUE, module_start is executed on core 0 then
  const char *filename;
+
// module_bootstart is executed on all cores. Otherwise, module_start is executed on all cores and
} __attribute__((packed)) SceModuleLoadList;
+
// module_bootstart is not executed.
 
+
SceInt32 BootModules(SceNskblModuleInfo* module_list, SceSize args, const void* argp, SceBool run_boot_entry);
int sceKblLoadModuleForKernel(const SceModuleLoadList *list, SceUID *uid, int count, int some_flag);
 
 
</source>
 
</source>
  
=== sceKblStartModuleForKernel ===
+
=== sceKernelBootBootModulesForKernel ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.990 || not present
 
|-
 
|-
 
| 3.60 || 0x9A92436E
 
| 3.60 || 0x9A92436E
 
|}
 
|}
  
In 3.60 this function is at 0x51001571
+
Temp name was sceKblBootModulesForKernel.
 +
 
 +
In FW 3.60 this function is at 0x51001571.
  
<source lang="C">int sceKblStartModuleForKernel(SceUID *uid_list, int count, SceSize args, void *argp);</source>
+
<source lang="C">int sceKernelBootBootModulesForKernel(SceUID *pUidList, SceUInt32 count, SceSize args, void *argp);</source>
  
=== sceKblAuthMgrCloseForKernel ===
+
=== sceAuthMgrExitForKernel ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.990 || not present
 
|-
 
|-
 
| 3.60 || 0x79241ACF
 
| 3.60 || 0x79241ACF
 
|}
 
|}
  
In 3.60 this function is at 0x51001345.
+
Temp name was sceKblAuthMgrCloseForKernel.
  
<source lang="C">int sceKblAuthMgrCloseForKernel(void);</source>
+
In FW 3.60 this function is at 0x51001345.
 +
 
 +
<source lang="C">int sceAuthMgrExitForKernel(void);</source>
  
 
=== sceKblSetNonSyncModuleStartForKernel ===
 
=== sceKblSetNonSyncModuleStartForKernel ===
Line 364: Line 651:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.990 || not present
 
|-
 
|-
 
| 3.60 || 0x9F4F3F98
 
| 3.60 || 0x9F4F3F98
 
|}
 
|}
  
In 3.60 this function is at 0x51001561.
+
This is a guessed name.
 +
 
 +
In FW 3.60 this function is at 0x51001561.
  
 
<source lang="C">int sceKblSetNonSyncModuleStartForKernel(void);</source>
 
<source lang="C">int sceKblSetNonSyncModuleStartForKernel(void);</source>
Line 377: Line 668:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xB506A10E
+
| 0.940-3.60 || 0xB506A10E
 
|}
 
|}
  
In 3.60 this function is at 0x510147C9.
+
In FW 3.60 this function is at 0x510147C9.
  
 
<source lang="C">int sceKernelCpuIdForKernel(void);</source>
 
<source lang="C">int sceKernelCpuIdForKernel(void);</source>
Line 389: Line 680:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xC8F4DE71
+
| 0.990-3.60 || 0xC8F4DE71
 
|}
 
|}
  
In 3.60 this function is at 0x51015851.
+
In FW 3.60 this function is at 0x51015851.
  
 
<source lang="C">int sceKernelCheckDipswForKernel(int bit);</source>
 
<source lang="C">int sceKernelCheckDipswForKernel(int bit);</source>
Line 401: Line 692:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xCE94F329
+
| 0.940-3.60 || 0xCE94F329
 
|}
 
|}
  
In 3.60 this function is at 0x51016FD1
+
In FW 3.60 this function is at 0x51016FD1.
  
 
<source lang="C">int sceSblQafManagerIsAllowKernelDebugForKernel(void);</source>
 
<source lang="C">int sceSblQafManagerIsAllowKernelDebugForKernel(void);</source>
Line 412: Line 703:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.990 || not present
 
|-
 
|-
 
| 3.60 || 0xD3A516D5
 
| 3.60 || 0xD3A516D5
 
|}
 
|}
  
get some device flags function
+
This is a guessed name.
  
In 3.60 this function is at 0x510128AD
+
In FW 3.60 this function is at 0x510128AD.
  
<source lang="C">
+
These hardware flags are maybe simply the [[KBL_Param#Hardware_Info_2]] like in [[SceSyscon#sceSysconGetHardwareInfo2ForDriver]].
typedef struct SceSysrootHardwareFlags {
 
uint32_t data[4];
 
} __attribute__((packed)) SceSysrootHardwareFlags;
 
  
int sceKblGetHardwareFlagsForKernel(SceSysrootHardwareFlags *data);
+
<source lang="C">int sceKblGetHardwareFlagsForKernel(SceHardwareFlags *pFlags);</source>
</source>
 
  
=== sceKblInitDeviceForKernel ===
+
=== sceSdStandaloneInitForKernel ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xF7AF8690
+
| 0.940-3.60 || 0xF7AF8690
 
|}
 
|}
  
some device init function
+
Temp name was sceKblInitDeviceForKernel.
 +
 
 +
Some device init function. On FW 0.940 it initializes and mounts <code>os0:</code> (eMMC) and <code>sd0:</code> (GCSD).
  
In 3.60 this function is at 0x5100124D.
+
In FW 3.60 this function is at 0x5100124D.
  
<source lang="C">int sceKblInitDeviceForKernel(void);</source>
+
<source lang="C">int sceSdStandaloneInitForKernel(void);</source>
  
=== sceKblFreeFileSystemCtxForKernel ===
+
=== sceSdStandaloneExitForKernel ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x261F2747
+
| 0.940-3.60 || 0x261F2747
 
|}
 
|}
  
In 3.60 this function is at 0x51001321.
+
Temp name was sceKblFreeFileSystemCtxForKernel.
 +
 
 +
Cleanup state created by [[NSKBL#sceSdStandaloneInitForKernel|sceSdStandaloneInitForKernel]].
 +
 
 +
In FW 3.60 this function is at 0x51001321.
  
<source lang="C">int sceKblFreeFileSystemCtxForKernel(void);</source>
+
<source lang="C">int sceSdStandaloneExitForKernel(void);</source>
  
[[Category:Modules]]
+
[[Category:ARM]]
 
[[Category:Kernel]]
 
[[Category:Kernel]]
 +
[[Category:Library]]

Latest revision as of 17:42, 30 March 2024

The Non-Secure Kernel Boot Loader (NSKBL) is the first program that runs on ARM cores in Non-Secure state. As its name indicate, it has the role of initializing the Non-Secure state environment and loading the kernel from storage.

Module

NSKBL is made of stripped down versions of some Non-Secure kernel modules along with code using all these functions to prepare the non-secure environment and load the next stage.

Reduced versions of the following modules are embedded in NSKBL:

It is very likely that the embedded modules in NSKBL are built from the same source tree as the Non-Secure kernel modules. This can be inferred from debugging information contained in some modules (line numbers in NSKBL and module equivalent match).

Notes

How to debug NSKBL

NSKBL supports sd0: for debugging. pKblParam->boot_type_indicator_1 = 0x40000 is required.

sceIoOpen(?) error code 0x803FF007

This error can occur if the file is fragmented.

NSKBL walk through

This section aims to provide an overview of the tasks performed by NSKBL. This description is based on System Software version 3.50 and later. Older versions may behave differently. See also NSKBL Subroutines.

Reset

The NSKBL reset vector, located at 0x51000000, is the first instruction executed in Non-Secure state, with the MMU turned off. It jumps to a small ASM function that disables interrupts (cpsid if), clears exclusive access requests (clrex), invalidates all caches, sets up stacks for all processors modes, and calls boot.

boot

This function is responsible for turning on the MMU. It partially initializes the SceKernelBootParam, copies the KBL Param from 0x40200100 (where it was placed by SKBL) and prints the Starting PSP2 Kernel Boot Loader (Non-secure) message.

The SceKernelBootParam initialization includes allocating physical and virtual pages for things like page tables, TTBR, fixed heaps, Sysroot, PhyPageTable, etc. The virtual address for the smaller mappings is randomized in the first 1 MiB of the address space (255 page-sized slots - first slot is reserved for NULL page), while larger allocations are randomized in the first 16 MiB (15 section-sized slots - slot 0 is reserved for the small ASLR mappings). A few mappings are exempted from randomization, like the identity mapping of 0x51000000-0x51FFFFFF where NSKBL resides. This memory range is mapped as RWX and seems to be the only RWX mapping in the Non-Secure kernel.

After all these mappings are complete, the MMU is turned on along with caches, branch predictor, and a few other things via the SCTLR. At this point, boot is done and sceKblMain is called.

sceKblMain

This function runs with the MMU enabled and receives a partially filled-in SceKernelBootParam from boot().

This function begins with a call to sceKernelSysrootStart which initializes the Sysroot structure. The slack space after the structure in the SceSysroot mapping (which is 16KiB-sized) is turned into a "heap" as part of this process. Memory allocation needs are serviced from this space using sceKernelSysrootAlloc. At this point, there are no other kernel heaps available. Sysroot status is set to 1 by this function.

After the Sysroot is initialized, sceKernelSysmemStart is called, which initializes the embedded SceSysmem module. It is at this stage that all the Sysmem object classes are created. Sysroot status is set to 2 then 3 by this function. Kernel heaps are available after the Sysroot status is set to 3 i.e. when this function returns.

Now that Sysmem is initialized, 16-KiB-sized SceKernelBootStackCoreX memory blocks are allocated, and execution is transfered to main2 after switching the stack pointer to these memblocks. Up until now, the stack it used was located in NSKBL .bss section.

main2

The main2 function receives a filled-up SceKernelBootParam from sceKblMain().

After setting the Sysroot status to 4, the remaining embedded modules are started (in order: sceKernelModulemgrStart(), SceExcpmgr start, sceKernelIntrMgrStart, sceSblAuthMgrStart() and SceSblSmschedProxy start). Once the embedded modules are started, Sysroot status is set to 0x10 and the final NSKBL function is called.

Final function

The final function receives the same SceKernelBootParam as main2.

It first calls sceSdStandaloneInit then loads and caches the gcauthmgr, rmauth and encdec_w_portability security modules.

After this, it loads os0:kd/psp2bootconfig.skprx, links the SceKblForKernel library to the module, and starts it with SceKernelBootParam address as argp.

NSKBL has now handed over control and simply remains resident until it is unmapped by SceSysStateMgr. See also SceKernelModulemgr#sceKernelFinalizeKblForKernel.

Types

typedef struct KBPMemoryRegion {
    SceUIntPtr pbase;
    SceSize psize;
} KBPMemoryRegion;

typedef struct KBPMappingInfo {
    char *name;         //<! Name of the mapping
    SceUIntPtr pbase;     //<! Base physical address of the mapping
    SceUIntPtr vbase;     //<! Base virtual address of the mapping
    SceSize psize;     //<! Size of the physical range of the mapping??
    SceSize vsize;     //<! Size of the virtual range of the mapping?? - Usually equal to psize, but may be bigger.
    SceUInt32 extraHigh; //<! Sometimes used as extraHigh for some memblock allocations? Exact meaning unknown.
    // psize + extraHigh must always be equal to vsize
} KBPMappingInfo;

typedef struct KBPBootStackInfo {
    unsigned unk0[2];
    SceUIntPtr ttbcr;
    SceUInt32 dacr;
    SceUInt32 asid;
    SceSize size;
    SceUID blkId;      //<! UID of the stack's memblock
    void *stackBottom; //<! = memblock.vbase + size 
} KBPBootStackInfo;

// This structure is passed as argp of modules like sysmem.skprx, etc
// 0x51030100 on NSKBL
typedef struct SceKernelBootParam { // Size is 0x310-bytes in 3.60-3.65 and 4.00. Layout appears to be identical.
   SSceSize size;                 //<! Size of this structure
   SceBool secure;               //<! Is secure state? Always 0 in NSKBL
   SceUInt32 num_memory;           //<! Number of filled elements in the next field
   KBPMemoryRegion memory[4];     //<! Physical memory ranges usable by NSKBL and kernel
   SceKblParam *pKblParam;        //<! Pointer to KBL Param
   unsigned unk30[5];
   SceUInt32 SoCInfo;              //<! = *(u32*)PERVASIVE_MISC
   SceUInt32 pmisc_unk4;           //<! = *(u32*)(PERVASIVE_MISC + 4)
   SceUInt32 KermitRevision;       //<! = SoCInfo & 0x1FFFF
   SceUInt32 hwDependent[2];       //<! Depends on pKBLParam->hardwareInfo
   KBPMappingInfo ttbr0;          //<! "SceKernelTTBR0", ASLR vbase, psize 0x4000
   unsigned ttbr0_maxAddress;     //<! Maximal address covered by TTBR0
   unsigned sizeTTBR0Address;     //<! Size of the address space covered by TTBR0
   KBPMappingInfo ttbr1;          //<! "SceKernelTTBR1", ASLR vbase, psize 0x4000
   unsigned sizeTTBR1Address;     //<! Size of the address space covered by TTBR1
   void *L2PT000_mapbase;         //<! First vaddr mapped by "SceKernelL2PageTable000"
   KPBMappingInfo reset;          //<! "SceKernelReset", vbase 0, psize 0x1000, extraHigh 0x3000
   KBPMappingInfo excpEntry;      //<! "SceKernelExceptionEntry", ASLR vbase, psize 0x1000, extraHigh 0x1000
   KBPMappingInfo l2pt000;        //<! "SceKernelL2PageTable000", ASLR vbase, psize 0x1000, extraHigh 0x1000
   KBPMappingInfo l2vector;       //<! "SceKernelL2Vector", ASLR vbase, psize 0x4000, extraHigh 0x4000
   KBPMappingInfo sysroot;        //<! "SceSysroot", ASLR vbase, psize 0x4000
   KBPMappingInfo fh32b;          //<! "SceKernelFixedHeap32B", ASLR vbase, psize 0x10000
   KBPMappingInfo fh48b;          //<! "SceKernelFixedHeap48B", ASLR vbase, psize 0x10000
   KBPMappingInfo fh64b;          //<! "SceKernelFixedHeap64B", ASLR vbase, psize 0x10000
   KBPMappingInfo fhUIDEntry;     //<! "SceKernelFixedHeapUIDEntry", ASLR vbase, psize 0x10000
   KBPMappingInfo fhL2Object;     //<! "SceKernelFixedHeapForL2Object", ASLR vbase, psize 0x1000, extraHigh 0x1000
   KBPMappingInfo unk188;         //<! Unused? NOTE: ASLR vbase = randomize in 255 slots, MegaASLR vbase = randomize in 15 slots
   KBPMappingInfo phypage;        //<! "SceKernelPhyPageTable", MegaASLR vbase, psize 0x80000
   KBPMappingInfo phypageHigh;    //<! "SceKernelPhyPageTableHigh", MegaASLR vbase, psize 0x80000, pbase 0x77F00000
   KBPMappingInfo bootkernimg;    //<! "SceBootKernelImage", vbase=pbase=0x51000000, psize 0x1000000, extraHigh 0x1000000
   KBPMappingInfo hwreg;          //<! Unnamed. vbase=pbase=0xE0000000, psize 0x8000000
   SceCorelockContext *pCorelock;
   KBPBootStackInfo bootCpu[4];   //<! bootCpu[X] corresponds to CPUX's info. Stack is pivoted to this when calling main2.
   SceSysroot *pSysroot;                 //<! Pointer to Sysroot structure
   unsigned unk288;                      //<! Related to L2PageTable000? Always 0.
   void *pL2PageTable000;                //<! Base address of the L2PageTable000
   void *resetVector;                    //<! Goes into VBAR. = excpEntry.vbase + 0x100
   SceKernelPhyMemPart *phyMemPartKD;    //<! "SceKernelPhyMemPartKD"
   SceKernelPhyMemPart *phyMemPartTool;  //<! "SceKernelPhyMemPartTool". May be NULL
   PhyPage *pPageKernelReset;            //<! PhyPage object describing the pages backing SceKernelReset
   PhyPage *pPageL2PageTable000;         //<! PhyPage object describing the pages backing SceKernelL2PageTable000
   PhyPage *pPageSysroot;                //<! PhyPage object describing the pages backing SceSysroot
   PhyPage *pPageTTBR0;                  //<! PhyPage object describing the pages backing SceKernelTTBR0
   PhyPage *pPageTTBR1;                  //<! PhyPage object describing the pages backing SceKernelTTBR1
   PhyPage *pPageL2Vector;               //<! PhyPage object describing the pages backing SceKernelL2Vector
   PhyPage *pPagePhypage;                //<! PhyPage object describing the pages backing SceKernelPhyPageTable
   PhyPage *pPagePhypageHigh;            //<! PhyPage object describing the pages backing SceKernelPhyPageTableHigh
   PhyPage *pPageBootKernelImage;        //<! PhyPage object describing the pages backing SceBootKernelImage????
   PhyPage *pPageFixedHeap32B;           //<! PhyPage object describing the pages backing SceKernelFixedHeap32B
   PhyPage *pPageFixedHeap48B;           //<! PhyPage object describing the pages backing SceKernelFixedHeap48B
   PhyPage *pPageFixedHeap64B;           //<! PhyPage object describing the pages backing SceKernelFixedHeap64B
   PhyPage *pPageFixedHeapForL2Object;   //<! PhyPage object describing the pages backing SceKernelFixedHeapForL2Object
   SceUIDFixedHeapObject *pFixedHeap32B;
   SceUIDFixedHeapObject *pFixedHeap48B;
   SceUIDFixedHeapObject *pFixedHeap64B;
   SceUIDFixedHeapObject *pFixedHeapForL2Object;
   PhyPage *pPageUIDHeap;                //<! PhyPage object describing the pages backing SceKernelFixedUIDHeap??
   SceUIDEntryHeapObject *pUIDHeap;      //<! Pointer to SceKernelFixedUIDHeap object 
   L2PageTableObject *pL2PT000Object;    //<! L2PageTableObject for SceKernelL2PageTable000
   L2PageTableObject *pPhyPageTblL2PTO;  //<! L2PageTableObject for table used to map the PhyPageTable (located @ SceKernelL2PageTable000.pbase + 0x400)
   SceUIDPartitionObject *pPartitionKernel; //<! Object of "SceKernelRoot" partition
   SceUID uidPartitionKernel;               //<! UID of object above (0x10009)
   SceUInt32 unk2F8[2];
   void *data_0x300;
   void *pPutcharHandler;
   SceUInt32 minimum_log_level;
   SceUInt32 magic;                          //<! 0x7F407C30
} SceKernelBootParam;

typedef struct SceNskblModuleInfo { // size is 0xC on FWs 0.940-0.990
    char* filename;    // Raw SKPRX file name (e.g. "sysmem.skprx"). Modules are loaded either from os0:kd/ or host0:module/.
    SceUID moduleId;     // SCE_UID_INVALID_UID. It gets filled when loading.
    SceUInt32 loadFlags; // Passed as flags to sceKernelLoadModule.
} __attribute__((packed)) SceNskblModuleInfo;

typedef struct SceNskblModuleInfo2 { // size is 4 on FW 3.60
    const char* filename;
} __attribute__((packed)) SceNskblModuleInfo2;

typedef struct SceHardwareFlags { // size is 0x10 on FW 3.60
    uint32_t data[4];
} __attribute__((packed)) SceHardwareFlags;

/* Many pointers are NSKBL heap relationships */
typedef struct SceNskblSysrootInfo { // size is at least 0xC8 on FW 3.60
	SceUID unk_0x00; // maybe some PID. ex: 0x10089
	int unk_0x04;
	void *unk_0x08;
	void *unk_0x0C;
	void *unk_0x10;
	void *unk_0x14;
	void *unk_0x18;
	void *unk_0x1C;
	void *unk_0x20;
	void *unk_0x24;
	void *unk_0x28;
	void *unk_0x2C;
	SceUID unk_0x30; // maybe some PID. ex: 0x1000B
	const void *unk_0x34; // mapped paddr in vaddr
	const void *unk_0x38; // mapped paddr in vaddr
	void *unk_0x3C;
	int unk_0x40; // ex: 0x80000000
	int unk_0x44; // ex: 0x20000000
	void *unk_0x48;
	void *unk_0x4C;
	void *unk_0x50;
	void *unk_0x54;
	void *unk_0x58;
	void *unk_0x5C;
	void *unk_0x60;
	void *unk_0x64;
	void *unk_0x68;
	void *unk_0x6C;
	void *unk_0x70;
	void *unk_0x74;
	void *unk_0x78;
	void *unk_0x7C;
	void *unk_0x80;
	void *unk_0x84;
	void *unk_0x88;
	void *unk_0x8C;
	void *unk_0x90;
	void *unk_0x94;
	void *unk_0x98;
	SceUInt32 magic; // 0x 19442EA8
	int unk_0xA0; // ex: 0x1000
	int unk_0xA4; // ex: 0x1000
	int unk_0xA8; // ex: 0x40000
	int unk_0xAC; // ex: 0x200000
	int unk_0xB0; // ex: 7
	int unk_0xB4;
	int unk_0xB8; // ex: 0x80
	sysroot_t *pSysroot;
	void *unk_0xC0;
	void *unk_0xC4;
	// more...?
} SceNskblSysrootInfo; // 3.60

SceNskblSysrootInfo *nskbl_sysroot_info = (SceNskblSysrootInfo *)(0x51000000 + 0x138980); // 3.60

Libraries

Known NIDs

Version Name World Visibility NID
0.940-3.65 SceKblForKernel Non-secure Kernel 0xD0FC2991

SceKblForKernel

NOTE: this library is linked directly to psp2bootconfig instead of being registered, and can thus only be imported by this module.

sceSDrfpStartForKernel

Version NID
0.940-0.990 0x230456F3
3.60 not present

sceSDbgSdioStartForKernel

Version NID
0.940-0.990 0x29A8524D
3.60 not present

Requires DIPSW 193.

SceInt32 sceSDbgSdioStartForKernel(void);

sceSDfMgrStartForKernel

Version NID
0.940-0.990 0xAA8005E4
3.60 not present

sceKblPutcharForKernel

Version NID
0.940-3.60 0x08E9FAEB

This is a guessed name.

This function is at 0x510172BD in FW 3.60 and at 0x51003BE0 in FW 0.940.040.

int sceKblPutcharForKernel(void *args, char c);

sceKernelPrintfForKernel

Version NID
0.940-3.60 0x13A5ABEF

In FW 3.60 this function is at 0x510137A9.

int sceKernelPrintfForKernel(const char *fmt, ...);

sceKernelPrintfLevelForKernel

Version NID
0.940 Not present
0.990-3.60 0x752E7EEC

In FW 3.60 this function is at 0x51013841.

int sceKernelPrintfLevelForKernel(int level, const char *fmt, ...);

sceKernelGetDebugLevelForKernel

Version NID
0.940-3.60 0xC011935A

Temp name was sceKblGetMinimumLogLevelForKernel.

In FW 3.60 this function is at 0x51013921.

int sceKernelGetDebugLevelForKernel(void);

sceKernelGetDebugPutcharForKernel

Version NID
0.940-3.60 0x9B868276

In FW 3.60 this function is at 0x51013765.

void *sceKernelGetDebugPutcharForKernel(void);

sceKernelSysrootProcessmgrStart2ForKernel

Version NID
0.940-3.60 0x161D6FCC

In FW 3.60 this function is at 0x510123DD.

int sceKernelSysrootProcessmgrStart2ForKernel(void);

sceKernelSysrootThreadMgrStartAfterProcessForKernel

Version NID
0.940-3.60 0x1DB28F02

In FW 3.60 this function is at 0x510123A1.

int sceKernelSysrootThreadMgrStartAfterProcessForKernel(void);

sceKernelSysrootIofilemgrStartForKernel

Version NID
0.940-3.60 0xC7B77991

In FW 3.60 this function is at 0x5101297D.

int sceKernelSysrootIofilemgrStartForKernel(void);

sceKernelSysrootCorelockUnlockForKernel

Version NID
0.940-3.60 0x314AA770

In FW 3.60 this function is at 0x510124FD.

void sceKernelSysrootCorelockUnlockForKernel(void);

sceKernelSysrootCorelockLockForKernel

Version NID
0.940-3.60 0x807B4437

In FW 3.60 this function is at 0x510124E5.

void sceKernelSysrootCorelockLockForKernel(SceUInt32 core);

sceKblCpuSuspendIntrForKernel_old

Version NID
0.940-0.990 0x99B2F981
3.60 not present

This is a guessed name.

On FW 0.940, it calls a routine that simply executes cpsid i then returns 0.

CPSID i ; Disable all interrupts except NMI (set PRIMASK)

Disables IRQ interrupts by setting the I-bit in the CPSR.

sceKblCpuSuspendIntrForKernel_new

Version NID
0.940-0.990 Not present
3.60 0xDDB3A1A8

This is a guessed name. Temp name was sceKblCpuSwitchInterruptsForKernel, sceKblCpuDisableIrqInterruptsForKernel.

In FW 3.60 this function is at 0x51003554.

void sceKblCpuSuspendIntrForKernel_new(void);

sceSblAimgrIsCEXForKernel

Version NID
0.940-3.60 0x8A416887

In FW 3.60 this function is at 0x510171B5.

int sceSblAimgrIsCEXForKernel(void);

sceSblAimgrIsDiagForKernel

Version NID
0.940-3.60 0xC3DDDE15

In FW 3.60 this function is at 0x51017175.

int sceSblAimgrIsDiagForKernel(void);

sceSblAimgrIsDEXForKernel

Version NID
0.940-0.990 Not present
3.60 0x5945F065

In FW 3.60 this function is at 0x51017159.

int sceSblAimgrIsDEXForKernel(void);

sceSblAimgrIsToolForKernel

Version NID
0.990 not present
3.60 0xB6C9ACF1

In FW 3.60 this function is at 0x51017139.

int sceSblAimgrIsToolForKernel(void);

sceSblAimgrIsTestForKernel

Version NID
0.990 not present
3.60 0x943E7537

In FW 3.60 this function is at 0x5101711D.

int sceSblAimgrIsTestForKernel(void);

sceSblAimgrIsVITAForKernel

Version NID
0.990 not present
3.60 0x838466E9

In FW 3.60 this function is at 0x51017299.

int sceSblAimgrIsVITAForKernel(void);

sceSblAimgrIsDolceForKernel

Version NID
0.990 not present
3.60 0xA7BD4417

In FW 3.60 this function is at 0x510172A1.

int sceSblAimgrIsDolceForKernel(void);

sceSblAimgrIsGenuineDolceForKernel

Version NID
0.990 not present
3.60 0xB6D00D6D

In FW 3.60 this function is at 0x510171E5.

int sceSblAimgrIsGenuineDolceForKernel(void);

LoadModulesForKernel

Version NID
0.940-0.990 0xFAE33FDD
3.60 not present

Load all modules from the provided list. The list end is marked by an entry with moduleName = NULL.

Module GUIDs are populated into the list, so it must be writeable.

SceInt32 LoadModules(SceNskblModuleInfo* module_list);

sceKernelBootLoadModulesForKernel

Version NID
0.990 not present
3.60 0x6D7A1F18

Temp name was sceKblLoadModulesForKernel.

In FW 3.60 this function is at 0x51001551.

int sceKernelBootLoadModulesForKernel(const SceNskblModuleInfo2 *pList, SceUID *pUidList, SceUInt32 count, SceBool use_tool_extended_memory);

BootModulesForKernel

Version NID
0.940-0.990 0xA7D60F71
3.60 not present

Runs the entrypoint of all modules in provided list. The list end is marked by an entry with moduleId = SCE_UID_INVALID_UID.

// If run_boot_entry is SCE_TRUE, module_start is executed on core 0 then
// module_bootstart is executed on all cores. Otherwise, module_start is executed on all cores and
// module_bootstart is not executed.
SceInt32 BootModules(SceNskblModuleInfo* module_list, SceSize args, const void* argp, SceBool run_boot_entry);

sceKernelBootBootModulesForKernel

Version NID
0.990 not present
3.60 0x9A92436E

Temp name was sceKblBootModulesForKernel.

In FW 3.60 this function is at 0x51001571.

int sceKernelBootBootModulesForKernel(SceUID *pUidList, SceUInt32 count, SceSize args, void *argp);

sceAuthMgrExitForKernel

Version NID
0.990 not present
3.60 0x79241ACF

Temp name was sceKblAuthMgrCloseForKernel.

In FW 3.60 this function is at 0x51001345.

int sceAuthMgrExitForKernel(void);

sceKblSetNonSyncModuleStartForKernel

Version NID
0.990 not present
3.60 0x9F4F3F98

This is a guessed name.

In FW 3.60 this function is at 0x51001561.

int sceKblSetNonSyncModuleStartForKernel(void);

sceKernelCpuIdForKernel

Version NID
0.940-3.60 0xB506A10E

In FW 3.60 this function is at 0x510147C9.

int sceKernelCpuIdForKernel(void);

sceKernelCheckDipswForKernel

Version NID
0.990-3.60 0xC8F4DE71

In FW 3.60 this function is at 0x51015851.

int sceKernelCheckDipswForKernel(int bit);

sceSblQafManagerIsAllowKernelDebugForKernel

Version NID
0.940-3.60 0xCE94F329

In FW 3.60 this function is at 0x51016FD1.

int sceSblQafManagerIsAllowKernelDebugForKernel(void);

sceKblGetHardwareFlagsForKernel

Version NID
0.990 not present
3.60 0xD3A516D5

This is a guessed name.

In FW 3.60 this function is at 0x510128AD.

These hardware flags are maybe simply the KBL_Param#Hardware_Info_2 like in SceSyscon#sceSysconGetHardwareInfo2ForDriver.

int sceKblGetHardwareFlagsForKernel(SceHardwareFlags *pFlags);

sceSdStandaloneInitForKernel

Version NID
0.940-3.60 0xF7AF8690

Temp name was sceKblInitDeviceForKernel.

Some device init function. On FW 0.940 it initializes and mounts os0: (eMMC) and sd0: (GCSD).

In FW 3.60 this function is at 0x5100124D.

int sceSdStandaloneInitForKernel(void);

sceSdStandaloneExitForKernel

Version NID
0.940-3.60 0x261F2747

Temp name was sceKblFreeFileSystemCtxForKernel.

Cleanup state created by sceSdStandaloneInitForKernel.

In FW 3.60 this function is at 0x51001321.

int sceSdStandaloneExitForKernel(void);