SceSysStateMgr
This module initializes part of the kernel, then loads and parses System Configuration script which is responsible for loading the rest of the kernel and spawning the Shell.
See also Boot Sequence (SceSysStateMgr)
Module
This module only exists in Non-Secure world.
The SELF can be found at os0:kd/sysstatemgr.skprx
.
Version | World | Privilege |
---|---|---|
0.931-3.60 | Non-secure | Kernel |
Libraries
This module doesn't export any library.
System Configuration script
The bulk of SceSysStateMgr consists of loading, parsing, and executing so-called System Configuration scripts.
Scripts can exist in two forms: encrypted modules that get loaded and expose a callback to get the plaintext (once decrypted) script, or a plain UTF-8 text file. Every line of the script contains one command or a comment. Each command performs an action (load module, ...) or changes the parser's state (change directory, load bootfs, ...). Scripts are parsed in their entirety before being executed.
The maximum blob size is 0x8000 bytes, and each command consumes a ~16 bytes fixed overhead + 1 byte per argument byte. This gives a rough estimation of a maximum of around 1000 commands per script.
Script locations
SceSysStateMgr will attempt to parse configuration scripts from different locations, depending on the firmware and the console's QA flags.
Unlike what could be expected, the script file's extension is not taken into account to determine whether or not the configuration is loaded as a module or a plaintext file. Script is loaded as a module if the file's first four bytes are SCE\0
(SELF magic), and plaintext otherwise, if QA flags allow it (SceQafMgrForDriver_883E9465() returns true).
The following tables provides all locations a script is attempted to be loaded from in the order of the attempts.
Path | Condition |
---|---|
host0:psp2config.skprx |
SceQafMgrForDriver_082A4FC2() returns true
|
sd0:psp2config.skprx |
MANUFACTURING_MODE predicate is true
|
ux0:psp2config.skprx |
MANUFACTURING_MODE predicate is true
|
os0:psp2config_vita.skprx |
sceSblAIMgrIsDolce returns false
|
os0:psp2config_dolce.skprx |
sceSblAIMgrIsDolce returns true
|
Path | Condition |
---|---|
host0:psp2config.skprx |
SceQafMgrForDriver_082A4FC2() returns true
|
sd0:psp2config.skprx |
MANUFACTURING_MODE predicate is true
|
ux0:psp2config.skprx |
MANUFACTURING_MODE predicate is true
|
os0:psp2config.skprx |
Always |
Path | Condition |
---|---|
The following applies if SceSysStateMgr is started with args=1. | |
sd0:psp2-config.txt |
DIP switch 224 is ON |
host0:psp2config.skprx |
DIP switch 224 is OFF |
host0:psp2-config.txt |
Always |
The following applies if SceSysStateMgr is started with args=0. (always?) | |
host0:psp2config.skprx |
SceQafMgrForDriver_082A4FC2() returns true
|
host0:psp2-config.skarx |
SceQafMgrForDriver_082A4FC2() returns true
|
sd0:psp2config.skprx |
MANUFACTURING_MODE predicate is true
|
sd0:psp2-config.skarx |
MANUFACTURING_MODE predicate is true
|
ux0:psp2config.skprx |
MANUFACTURING_MODE predicate is true
|
os0:psp2config.skprx |
Always |
os0:psp2-config.skarx |
Always |
Path | Condition |
---|---|
The following applies if SceSysStateMgr is started with args=1. | |
sd0:psp2-config.txt |
DIP switch 224 is ON |
host0:psp2config.skprx |
DIP switch 224 is OFF |
host0:psp2-config.txt |
Always |
The following applies if SceSysStateMgr is started with args=0. (always?) | |
host0:psp2config.skprx |
SceQafMgrForDriver_082A4FC2() returns non-0
|
host0:psp2-config.skarx |
SceQafMgrForDriver_082A4FC2() returns non-0
|
sd0:psp2config.skprx |
MANUFACTURING_MODE predicate is true
|
sd0:psp2-config.skarx |
MANUFACTURING_MODE predicate is true
|
os0:psp2config.skprx |
Always |
os0:psp2-config.skarx |
Always |
Processing flow
Scripts are processed in two steps:
- Parsing: Every line of the script is read and split by whitespace. Each line is transformed into a corresponding instruction for the execution engine and saved into a data blob. Invalid scripts cause an early abort here and never reach the next pass.
- Execution: The data blob created in step 1 is handed over to a sort of virtual machine that reads it and executes the code corresponding to the instructions specified in it.
Syntax
\r
(0xD
) is ignored\xFF
, if present, marks the end of the file\n
ends a line\t
/\f
/0x9
,0xC
and0x20
) are considered as whitespace
Syntax of a line (Convention: {x}
is ignored, [x]
is optional, <x>
is mandatory):
{whitespace}[prefix]{whitespace}<command / keyword>{whitespace}[argumentBlock]<newline> [argumentBlock]: <argument>{whitespace}[argumentBlock]
Up to 7 arguments can be passed to a command if the prefix is not whitespace-separated from it, 6 otherwise. Additional arguments are ignored.
Example commands:
# Example # with more spaces -load os0:kd/codec.skprx & echo ohayo
Prefixes
The first non-ignored character of a command is checked to be among one of those, and affects the behaviour of the command.
#
Comment. Rest of the line is ignored and can contain anything.
-
Ignore error. If an error happens while executing the command on the line, continue executing the script.
If this prefix isn't present, when an error happens, execution of the script is aborted, no other script is attempted to be executed ?and kernel panics?.
&
Not supported.
Commands
The set of commands available and their behaviour can slightly vary between firmware.
All path parameters can refer to either an absolute or relative path. Relative pathes are canonicalized by appending the provided path to the current directory (see cd), while absolute pathes are used raw.
A path is treated as absolutes if it begins with one of the following strings: /
,\
, sd0:
, host0:
, os0:
, vs0:
, ur0:
, ud0:
and ux0:
(ux0:
is not considered as a drive before firmware 0.995).
sd0:
and ux0:
are only allowed if external storage access is allowed.
If DIP switch 252 is enabled and SceQafMgrForDriver_082A4FC2()
returns true, all pathes except those starting with host0:
are attempted from host0:module/
first. For example, load os0:kd/test.skprx
would try to load host0:module/test.skprx
then, if it failed, try to load os0:kd/test.skprx
.
For module related commands, the provided path is "canonicalized" before being used. The same canonical path used when loading must be used for all commands. Since canonicalization for relative pathes involves the current directory, the following script is invalid:
cd sd0:kd/ # Module canonical path is "sd0:kd/test.skprx" loadonly test.skprx
cd os0:kd/ # Module canonical path is "os0:kd/test.skprx" - has not been loaded, so this fails! start test.skprx
load
Load and start module.
The module path ends at the first whitespace. Same logic applies to other load-like commands.
Syntax:
load <module_path> [arguments]
Example:
load sd0:module.skprx this args param1 # -> loads sd0:module.skprx and pass "sd0:module.skprx this args param1" to argp.
# Whitespace hazard demonstration load sd0:kernel modules/test module.skprx # -> loads "sd0:kernel", not "sd0:kernel modules/test module.skprx"!
tload
Same as load, but module is loaded in TOOL memory instead. Requires DIP switch 210.
sload
Performs like load if the console is in Show Mode i.e. Hardware_Info & 0x40
.
Added between firmwares 1.50 and 1.691.
unload
Stop and unload a module (sceKernelStopUnloadModule()
).
Syntax:
unload <module path> [?arguments?]
Example:
unload sd0:module.skprx
loadonly
Load a module without starting it (sceKernelLoadModule()
).
Syntax:
loadonly <module path>
Example:
loadonly sd0:module.skprx
start
Start a loaded module (sceKernelStartModule()
).
Syntax:
start <module path> [?arguments?]
Example:
start sd0:module.skprx
stop
Stop a module (sceKernelStopModule()
).
Syntax:
stop <module path> [?arguments?]
Example:
stop sd0:module.skprx
unloadonly
Unload a module (sceKernelUnloadModule
).
Syntax:
unloadonly <module path>
Example:
unloadonly sd0:module.skprx
spawn
Create and start a new process, using specified module as its main module. This command is subject to rpath redirection.
Syntax:
spawn <module path> [?arguments?]
Example:
if SAFE_MODE spawn os0:ue/safemode.self end endif
wait
Wait until a spawn
'ed process finished.
Syntax:
wait <module path>
Example:
spawn sd0:example.self wait sd0:example.self
spawnwait
Combined spawn
+wait
not subject to rpath redirection.
Syntax:
spawnwait <module path> [?arguments?]
Example:
if MANUFACTURING_MODE - spawnwait sd0:psp2diag.self - spawnwait ux0:psp2diag.self endif
appspawn
Spawn an application process using sceKernelSysrootAppMgrSpawnProcess()
. This command is subject to rpath and Shell path redirection.
Syntax:
appspawn <executable path> [budget ID]
Budget ID must be one of the following:
ID string | Budget ID | Notes |
---|---|---|
GAME_BUDGET_ID |
0x1000000 | 0x1010001 in 0.931 |
SHELL_BUDGET_ID |
0x4000000 | 0x4020102 in 0.931 |
If none is specified, GAME_BUDGET_ID
is used.
Examples:
- appspawn vs0:vsh/shell/shell.self SHELL_BUDGET_ID - appspawn sd0:game.self GAME_BUDGET_ID # Same effect as above - appspawn sd0:game.self
kill
Kill a process. This command is dummy and doesn't have any effect.
sleep
Sleep for a certain duration. This command is dummy and doesn't have any effect.
echo
Write to stdout (using sceKernelPrintf
).
Syntax:
echo [data]
Example:
# Write "Hello world!" to stdout. echo Hello world!
loadconfig
Load and parse another configuration file. The configuration file must be either a module or a plaintext file (latter is only allowed depending on the system's QA flags). The configuration file is fully executed before this command returns.
This command can be executed by the loaded configuration files, but the maximum number of nested calls is 4 (or 5?) - further nested calls are ignored. For example, assuming file cfgX.txt
loads file cfg(X+1).txt
, only files 0-4 are executed, and cfg5.txt
is skipped. Nested call overflow is not considered an error; the files are simply skipped but the command succeeds.
Note that the configuration is loaded under its own independent context; for example, it cannot unload
a module that the configuration executing the loadconfig
has load
'ed.
Syntax:
loadconfig <configuration path>
Example:
- loadconfig sd0:boot_config_second.txt
include
Alias of loadconfig.
cd
Change directory. Sets the current directory.
Syntax:
cd <directory>
Example:
cd sd0:kd/ load module.skprx # loads sd0:kd/module.skprx
The default working directory is the same as where the bootconfig is located.
setenv
Sets an environement variable. Seems unused.
Syntax:
setenv <name> <value>
Example:
setenv OHAYO_PATH sd0:ohayo
setmodfile
Alias of setenv.
umount_bootfs
Unmount bootfs. os0:kd/bootimage.skprx
is mounted as bootfs before scripts execute since firmware 0.996 (except if External Boot mode (SceSysrootForKernel_89D19090()
) is active on firmwares >= 3.00).
Added in firmware 1.80.
Syntax:
umount_bootfs
Special commands
Those commands affect the script's execution flow instead of invoking callbacks with side effects.
Special commands cannot fail and do not support prefixing. For example, -if MANUFACTURING_MODE
is a syntax error.
ifmodel
Conditional code block start. Execute code in block if predicate is true.
Syntax:
ifmodel <predicate name>
Example:
ifmodel MANUFACTURING_MODE # Code executes only if MANUFACTURING_MODE evaluates to true echo Running in manufacturing mode! endif
Nested ifmodel
/ifnmodel
blocks are supported, maximum depth is 32.
Every ifmodel
block must end with a corresponding endif
.
predicate name
is a string provided to the function ConfReaderUtilsEvalCond
which finds a callback function whose return value is considered as the value of the predicate (i.e. false if the function returns 0, true if the function returns 1). Specifying the name of a non-existent predicate is a syntax error.
The following table contains the name of all supported predicates along with the code of the associated callback function:
Firmware | Name | Predicate code | Notes |
---|---|---|---|
0.931-3.60 | 0 |
return 0; |
Always false. |
0.931-3.60 | 1 |
return 1; |
Always true. |
0.931-3.60 | MANUFACTURING_MODE |
return sceKernelSysrootIsManufacturingModeForKernel(); |
|
0.940-3.60 | EXTERNAL_BOOT_MODE |
return sceKernelSysrootIsExternalBootModeForKernel(); |
|
0.931-0.945 | UPDATE_MODE |
return (sceKernelSysrootGetKblParam()->bootFlags[0] != 0xFF); |
|
0.990-3.60 | UPDATE_MODE |
return sceKernelSysrootIsUpdateModeForKernel(); |
Identical to 0.931 but moved to a Sysroot function |
0.990-0.995 | USB_ENUM_WAKEUP |
return ((sceKernelSysrootGetErnieWakeupFactor() & 0x7F) == 0xF); |
|
0.996-3.60 | USB_ENUM_WAKEUP |
return sceKernelSysrootIsUsbEnumWakeupForKernel(); |
Identical to 0.990 but code was moved to a Sysroot function |
0.940-3.60 | DEVELOPMENT_MODE |
return sceSblACMgrIsDevelopmentMode(); |
|
0.931-0.945 | SAFE_MODE |
SceKblParam* pKbl = sceKernelSysrootGetKblParam(); return ((pKbl->wakeupFactor & 0x7F) == 0xB) && ((pKbl->bootControlsInfo >> 8 & 0xFF) == 0xA9); //R+SELECT+X+O |
|
0.990-3.60 | SAFE_MODE |
return sceKernelSysrootIsSafeModeForKernel(); |
Routine is similar to 0.931 check |
0.931-3.60 | UD0_EXIST |
SceIoStat stat; return (sceIoGetstat("ud0:", &stat) == SCE_OK); |
|
0.931-3.01 | DEMO_MODE |
SceIoStat stat; if (!SceQafMgrForDriver_CAD47130() || sceIoGetstat("vs0:vsh/shell/shell_mini.self", &stat) >= 0) return false; return (sceIoGetstat("vs0:vsh/shell/shell_gamebudget.self", &stat) == SCE_OK); |
|
0.931-1.69 | KERMIT_REV_ES1_X |
return (sceKernelSysrootGetKermitRevision() & 0xF0) == 0x10); |
|
0.931-1.69 | KERMIT_REV_ES2_X |
return (sceKernelSysrootGetKermitRevision() & 0xF0) == 0x20); |
|
0.940-1.69 | KERMIT_REV_ES3_X |
return (sceKernelSysrootGetKermitRevision() & 0xF0) == 0x30); |
|
0.990-1.69 | KERMIT_REV_ES4_X |
return (sceKernelSysrootGetKermitRevision() & 0xF0) == 0x40); |
|
1.80-3.01 | KERMIT_REV_ES4_X |
Same as KERMIT10_REV_ES4_X |
|
1.80-3.01 | KERMIT10_REV_ES4_X |
return (sceKernelSysrootGetKermitRevision() & 0x1FFF0) == 0x40); |
Change due to new Kermit revision encoding |
1.80-3.01 | KERMIT15_REV_ES1_X |
return (sceKernelSysrootGetKermitRevision() & 0x1FFF0) == 0x110); |
|
3.10-3.60 | AU_CODEC_IC_CONEXANT |
uint32_t hwFlag[4]; SceSysrootForDriver_46E72428(&hwFlag); // sceKernelSysrootGetHardwareFlagsForDriver return ((hwFlag[0] & 0x40) != 0); |
Related to SceCodec IC. Probably superseded KERMITxx_REV_ESx_X variables
|
2.10-3.60 | BSOD_REBOOT |
return sceKernelSysrootIsBsodRebootForKernel(); |
if
Alias of ifmodel.
ifnmodel
Conditional code block start. Execute code in block if predicate is false. See ifmodel.
Syntax:
ifnmodel <predicate>
Example:
ifnmodel USB_ENUM_WAKEUP # Code executes only if USB_ENUM_WAKEUP evaluates to false echo Not wakeup due to USB enum! endif
Every ifnmodel
block must end with a corresponding endif
.
else
Mark the beginning of a failed predicate conditional block. Must reside between a if[n]model
and the corresponding endif
.
Syntax:
else
Example:
if USB_ENUM_WAKEUP load os0:kd/enum_wakeup.skprx else echo No USB enum wakeup! endif
endif
Marks the end of a conditional block.
Syntax:
endif
Example:
if USB_ENUM_WAKEUP load os0:kd/enum_wakeup.skprx endif
repeat
Start of a repetition block. Commands in a repetition block are repeated multiple times.
Syntax:
repeat <count>
count
is the number of times the code block will be executed, and must be a decimal number.
Example:
repeat 3 echo Something endrepeat # prints the following: # # Something # Something # Something
endrepeat
End of a repetition block. Must appear after a repeat
command.
Syntax:
endrepeat
end
Stop the script execution and return success.
Syntax:
end
if SAFE_MODE spawn os0:ue/safemode.self end endif
echo Not in Safe Mode!
Remote Path file
SceSysStateMgr attempts to read a Remote Path file at host0:psp2config.rpath
. This is only done if either SceQafMgrForDriver_B99770A13()
or SceQafMgrForDriver_082A4FC2()
return true. The rpath
file applies to all configuration scripts.
The file's syntax is similar to System Configuration scripts.
This file can be used for two purposes: override the Shell file, and override application spawn path.
If a line starts with set_shell_filename [path]
, path
is used when appspawn
'ing any application with executable name shell.self
. See appspawn. If path
is empty, Shell loading override is disabled (i.e. the requested file is loaded).
This only affects the appspawn command.
Otherwise, if a line doesn't start with a #
(i.e. not a comment), it is stored as a remote path for application spawning. Up to 4 such pathes can be specified, all those past the 4th one are ignored.
This only affects the spawn and appspawn commands.
When attempting to load file os0:path/to/module.skprx
, the following files are attempted to be loaded in order:
- "Remote path" (
host0:module/
prefix i.e.host0:module/module.skprx
) if allowed by QA flags and DIP switches - "Remote Rpath" (e.g.
os0:tk/module.skprx
if rpath wasos0:tk/
) if a rpath file is present and allowed - "Canonical path" (absolute path if specified, otherwise built from current directory)
Example psp2config.rpath
file:
# Load development Shell from PC set_shell_filename host0:dev_shell.self # Allow test app spawn from PC host0:test_app/
With this file, the following behaviour is observed:
appspawn vs0:vsh/shell/shell.self
:
- Attempt to load
host0:dev_shell.self
- Attempt to load
host0:test_app/dev_shell.self
Note how the original Shell path is completly ignored.
spawn os0:kd/test_exec.self
- Attempt to load
host0:module/test_exec.self
if allowed by QAF - Attempt to load
host0:test_app/test_exec.self
- Attempt to load
os0:kd/test_exec.self