SceSysStateMgr: Difference between revisions

From Vita Development Wiki
Jump to navigation Jump to search
No edit summary
 
(10 intermediate revisions by 3 users not shown)
Line 1: Line 1:
This module initializes part of the kernel, loads the scripted config and loads the rest of the modules needed for boot.
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.


also see : [[Boot Sequence#SceSysStateMgr|Boot Sequence(SceSysStateMgr)]]
See also [[Boot Sequence#SceSysStateMgr|Boot Sequence (SceSysStateMgr)]]


== boot configs ==
= Module =


The lower the priority, the higher.
This module only exists in Non-Secure world.


<code>.rpath</code> is Remote Path
The SELF can be found at <code>os0:kd/sysstatemgr.skprx</code>.


{| class="wikitable"
{| class="wikitable"
|-
|-
! Priority
! Version !! World !! Privilege
! Path
! Type
|-
|-
| 0
| 0.931-3.60 || Non-secure || Kernel
| host0:psp2config.skprx
|}
| Module
 
= 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 <code>SCE\0</code> ([[SELF]] magic), and plaintext otherwise, if QA flags allow it ([[SceSysmem#SceQafMgrForDriver_883E9465|SceQafMgrForDriver_883E9465()]] returns true).
 
The following tables provides all locations a script is attempted to be loaded from in the order of the attempts.
 
{| class="wikitable"
|+ Script locations for firmware 2.10-3.60
|-
! Path !! Condition
|-
| <code>host0:psp2config.skprx</code> || [[SceSysmem#SceQafMgrForDriver_082A4FC2|<code>SceQafMgrForDriver_082A4FC2()</code>]] returns true
|-
| <code>sd0:psp2config.skprx</code> || [[SceSysStateMgr#ifmodel|<code>MANUFACTURING_MODE</code>]] predicate is true
|-
| <code>ux0:psp2config.skprx</code> || [[SceSysStateMgr#ifmodel|<code>MANUFACTURING_MODE</code>]] predicate is true
|-
| <code>os0:psp2config_vita.skprx</code> || [[SceSysmem#sceSblAIMgrIsDolceForDriver|<code>sceSblAIMgrIsDolce</code>]] returns false
|-
| <code>os0:psp2config_dolce.skprx</code> || [[SceSysmem#sceSblAIMgrIsDolceForDriver|<code>sceSblAIMgrIsDolce</code>]] returns true
|}
 
{| class="wikitable"
|+ Script locations for firmware 1.00-2.06
|-
! Path !! Condition
|-
| <code>host0:psp2config.skprx</code> || [[SceSysmem#SceQafMgrForDriver_082A4FC2|<code>SceQafMgrForDriver_082A4FC2()</code>]] returns true
|-
| <code>sd0:psp2config.skprx</code> || [[SceSysStateMgr#ifmodel|<code>MANUFACTURING_MODE</code>]] predicate is true
|-
| <code>ux0:psp2config.skprx</code> || [[SceSysStateMgr#ifmodel|<code>MANUFACTURING_MODE</code>]] predicate is true
|-
| <code>os0:psp2config.skprx</code> || Always
|}
 
{| class="wikitable"
|+ Script locations for firmware 0.995-0.996
|-
! Path !! Condition
|-
! colspan="2" | '''The following applies if SceSysStateMgr is started with args=1.'''
|-
| <code>sd0:psp2-config.txt</code> || DIP switch 224 is ON
|-
| <code>host0:psp2config.skprx</code> || DIP switch 224 is OFF
|-
| <code>host0:psp2-config.txt</code> || Always
|-
! colspan="2" | '''The following applies if SceSysStateMgr is started with args=0.''' (always?)
|-
| <code>host0:psp2config.skprx</code> || [[SceSysmem#SceQafMgrForDriver_082A4FC2|<code>SceQafMgrForDriver_082A4FC2()</code>]] returns true
|-
| <code>host0:psp2-config.skarx</code> || [[SceSysmem#SceQafMgrForDriver_082A4FC2|<code>SceQafMgrForDriver_082A4FC2()</code>]] returns true
|-
| <code>sd0:psp2config.skprx</code> || [[SceSysStateMgr#ifmodel|<code>MANUFACTURING_MODE</code>]] predicate is true
|-
| <code>sd0:psp2-config.skarx</code> || [[SceSysStateMgr#ifmodel|<code>MANUFACTURING_MODE</code>]] predicate is true
|-
| <code>ux0:psp2config.skprx</code> || [[SceSysStateMgr#ifmodel|<code>MANUFACTURING_MODE</code>]] predicate is true
|-
| <code>os0:psp2config.skprx</code> || Always
|-
| <code>os0:psp2-config.skarx</code> || Always
|}
 
{| class="wikitable"
|+ Script locations for firmware 0.931-0.990
|-
|-
| 1
! Path !! Condition
| sd0:psp2config.skprx
| Module
|-
|-
| 2
! colspan="2" | '''The following applies if SceSysStateMgr is started with args=1.'''
| ux0:psp2config.skprx
| Module
|-
|-
| 3
| <code>sd0:psp2-config.txt</code> || DIP switch 224 is ON
| os0:psp2config_dolce.skprx
| Module
|-
|-
| 3
| <code>host0:psp2config.skprx</code> || DIP switch 224 is OFF
| os0:psp2config_vita.skprx
| Module
|-
|-
| ?
| <code>host0:psp2-config.txt</code> || Always
| host0:psp2config.rpath
|-
| Plaintext
! colspan="2" | '''The following applies if SceSysStateMgr is started with args=0.''' (always?)
|-
| <code>host0:psp2config.skprx</code> || [[SceSysmem#SceQafMgrForDriver_082A4FC2|<code>SceQafMgrForDriver_082A4FC2()</code>]] returns non-0
|-
| <code>host0:psp2-config.skarx</code> || [[SceSysmem#SceQafMgrForDriver_082A4FC2|<code>SceQafMgrForDriver_082A4FC2()</code>]] returns non-0
|-
| <code>sd0:psp2config.skprx</code> || [[SceSysStateMgr#ifmodel|<code>MANUFACTURING_MODE</code>]] predicate is true
|-
| <code>sd0:psp2-config.skarx</code> || [[SceSysStateMgr#ifmodel|<code>MANUFACTURING_MODE</code>]] predicate is true
|-
| <code>os0:psp2config.skprx</code> || Always
|-
| <code>os0:psp2-config.skarx</code> || Always
|}
|}


== command prefixs ==
== 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 ==
 
* <code>\r</code>(<code>0xD</code>) is ignored
* <code>\xFF</code>, if present, marks the end of the file
* <code>\n</code> ends a line
* <code>\t</code>/<code>\f</code>/<code> </code>(respectively <code>0x9</code>, <code>0xC</code> and <code>0x20</code>) are considered as whitespace
 
Syntax of a line (Convention: <code>{x}</code> is ignored, <code>[x]</code> is optional, <code><x></code> 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.


to comment.
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?.


=== - ===
==== & ====


to ignore error.
Not supported.


=== & ===
=== Commands ===


unknown.
The set of commands available and their behaviour can slightly vary between firmware.


== module load path processing ==
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 [[SceSysStateMgr#cd|cd]]), while absolute pathes are used raw.


Space cannot be included in path, and the written after the space is ignored by module load.
A path is treated as absolutes if it begins with one of the following strings: <code>/</code>,<code>\</code>, <code>sd0:</code>, <code>host0:</code>, <code>os0:</code>, <code>vs0:</code>, <code>ur0:</code>, <code>ud0:</code> and <code>ux0:</code> (<code>ux0:</code> is not considered as a drive before firmware 0.995).


<source>
<code>sd0:</code> and <code>ux0:</code> are only allowed if external storage access is allowed.
load sd0:module.skprx this args param1
# -> load sd0:module.skprx and pass "sd0:module.skprx this args param1" to argp.
</source>


If DIP switch 252 is enabled and <code>SceQafMgrForDriver_082A4FC2()</code> returns true, all pathes except those starting with <code>host0:</code> are attempted from <code>host0:module/</code> first. For example, <code>load os0:kd/test.skprx</code> would try to load <code>host0:module/test.skprx</code> then, if it failed, try to load <code>os0:kd/test.skprx</code>.


== bootconfig commands ==
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:


=== load ===
  cd sd0:kd/
  # Module canonical path is "sd0:kd/test.skprx"
  loadonly test.skprx


<source>
  cd os0:kd/
load sd0:module.skprx
  # Module canonical path is "os0:kd/test.skprx" - has not been loaded, so this fails!
</source>
  start test.skprx


=== unload ===
<hr>


<source>
==== load ====
unload sd0:module.skprx
</source>


=== loadonly ===
Load and start module.


<source>
The module path ends at the first whitespace. Same logic applies to other load-like commands.
loadonly sd0:module.skprx
</source>


=== start ===
Syntax:
  load <module_path> [arguments]


<source>
Example:
start sd0:module.skprx
  load sd0:module.skprx this args param1
</source>
  # -> loads sd0:module.skprx and pass "sd0:module.skprx this args param1" to argp.


=== stop ===
  # Whitespace hazard demonstration
  load sd0:kernel modules/test module.skprx
  # -> loads "sd0:kernel", not "sd0:kernel modules/test module.skprx"!


<source>
==== tload ====
stop sd0:module.skprx
</source>


=== unloadonly ===
Same as [[SceSysStateMgr#load|load]], but module is loaded in TOOL memory instead. Requires DIP switch 210.


<source>
==== sload ====
unloadonly sd0:module.skprx
</source>


=== spawn ===
Performs like [[SceSysStateMgr#load|load]] if the console is in Show Mode i.e. <code>[[KBL_Param#Hardware_Info|Hardware_Info]] & 0x40</code>.


Create a new process.
Added between firmwares 1.50 and 1.691.


<source>
==== unload ====
if SAFE_MODE
spawn os0:ue/safemode.self
end
endif
</source>


=== spawnwait ===
Stop and unload a module (<code>sceKernelStopUnloadModule()</code>).


Create a new process and wait until it finishes.
Syntax:
  unload <module path> [?arguments?]


<source>
Example:
if MANUFACTURING_MODE
  unload sd0:module.skprx
- spawnwait sd0:psp2diag.self
- spawnwait ux0:psp2diag.self
endif
</source>


=== wait ===
==== loadonly ====


Probably wait for the process to finish.
Load a module without starting it (<code>sceKernelLoadModule()</code>).


=== kill ===
Syntax:
  loadonly <module path>


unknown
Example:
  loadonly sd0:module.skprx


=== end ===
==== start ====


defines the end of config.
Start a loaded module (<code>sceKernelStartModule()</code>).


<source>
Syntax:
if SAFE_MODE
  start <module path> [?arguments?]
spawn os0:ue/safemode.self
end
endif
</source>


=== sleep ===
Example:
  start sd0:module.skprx


unknown
==== stop ====


=== echo ===
Stop a module (<code>sceKernelStopModule()</code>).


unknown
Syntax:
  stop <module path> [?arguments?]


=== loadconfig ===
Example:
  stop sd0:module.skprx


same to include
==== unloadonly ====


<source>
Unload a module (<code>sceKernelUnloadModule</code>).
- loadconfig sd0:boot_config_second.txt
</source>


=== if ===
Syntax:
  unloadonly <module path>


defines if statement.
Example:
  unloadonly sd0:module.skprx


<source>
==== spawn ====
if USB_ENUM_WAKEUP
load os0:kd/enum_wakeup.skprx
endif
</source>


MANUFACTURING_MODE
Create and start a new process, using specified module as its main module. This command is subject to [[SceSysStateMgr#Remote path file|rpath redirection]].


EXTERNAL_BOOT_MODE
Syntax:
  spawn <module path> [?arguments?]


UPDATE_MODE
Example:
  if SAFE_MODE
  spawn os0:ue/safemode.self
  end
  endif


USB_ENUM_WAKEUP
==== wait ====


BSOD_REBOOT
Wait until a <code>spawn</code>'ed process finished.


UD0_EXIST
Syntax:
  wait <module path>


SAFE_MODE
Example:
  spawn sd0:example.self
  wait sd0:example.self


DEVELOPMENT_MODE
==== spawnwait ====


AU_CODEC_IC_CONEXANT
Combined <code>spawn</code>+<code>wait</code> [[SceSysStateMgr#Remote path file|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 <code>sceKernelSysrootAppMgrSpawnProcess()</code>. This command is subject to [[SceSysStateMgr#Remote path file|rpath and Shell path redirection]].
 
Syntax:
  appspawn <executable path> [budget ID]
 
Budget ID must be one of the following:
{| class="wikitable"
|-
! ID string !! Budget ID !! Notes
|-
| <code>GAME_BUDGET_ID</code>  || 0x1000000 || 0x1010001 in 0.931
|-
| <code>SHELL_BUDGET_ID</code> || 0x4000000 || 0x4020102 in 0.931
|}
If none is specified, <code>GAME_BUDGET_ID</code> 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 <code>sceKernelPrintf</code>).
 
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 <code>cfgX.txt</code> loads file <code>cfg(X+1).txt</code>, only files 0-4 are executed, and <code>cfg5.txt</code> 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 [[SceSysStateMgr#unload|<code>unload</code>]] a module that the configuration executing the <code>loadconfig</code> has [[SceSysStateMgr#load|<code>load</code>]]'ed.
 
Syntax:
  loadconfig <configuration path>
 
Example:
  - loadconfig sd0:boot_config_second.txt
 
==== include ====
 
Alias of [[SceSysStateMgr#loadconfig|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 [[SceSysStateMgr#setenv|setenv]].
 
==== umount_bootfs ====
 
Unmount bootfs. <code>os0:kd/bootimage.skprx</code> is mounted as bootfs before scripts execute since firmware 0.996 (except if External Boot mode (<code>SceSysrootForKernel_89D19090()</code>) 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, <code>-if MANUFACTURING_MODE</code> 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 <code>ifmodel</code>/<code>ifnmodel</code> blocks are supported, maximum depth is 32.
 
Every <code>ifmodel</code> block must end with a corresponding [[SceSysStateMgr#endif|<code>endif</code>]].
 
<code>predicate name</code> is a string provided to the function <code>ConfReaderUtilsEvalCond</code> 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:
{| class="wikitable"
|+ Available predicates list
|-
! Firmware !! Name !! Predicate code !! Notes
|-
| 0.931-3.60 || <code>0</code> || <code>return 0;</code> || Always false.
|-
| 0.931-3.60 || <code>1</code> || <code>return 1;</code> || Always true.
|-
| 0.931-3.60 || <code>MANUFACTURING_MODE</code> || [[SceSysmem#sceKernelSysrootIsManufacturingModeForKernel|<code>return sceKernelSysrootIsManufacturingModeForKernel();]] ||
|-
| 0.940-3.60 || <code>EXTERNAL_BOOT_MODE</code> || [[SceSysmem#sceKernelSysrootIsExternalBootModeForKernel|<code>return sceKernelSysrootIsExternalBootModeForKernel();]] ||
|-
| 0.931-0.945 || <code>UPDATE_MODE</code> || <source lang="C">
return (sceKernelSysrootGetKblParam()->bootFlags[0] != 0xFF);
</source> ||
|-
| 0.990-3.60 || <code>UPDATE_MODE</code> || [[SceSysmem#sceKernelSysrootIsUpdateModeForKernel|<code>return sceKernelSysrootIsUpdateModeForKernel();]] || Identical to 0.931 but moved to a Sysroot function
|-
| 0.990-0.995 || <code>USB_ENUM_WAKEUP</code> || [[SceSysmem#sceKernelSysrootGetErnieWakeupFactorForKernel|<code>return ((sceKernelSysrootGetErnieWakeupFactor() & 0x7F) == 0xF);]] ||
|-
| 0.996-3.60 || <code>USB_ENUM_WAKEUP</code> || [[SceSysmem#sceKernelSysrootIsUsbEnumWakeupForKernel|<code>return sceKernelSysrootIsUsbEnumWakeupForKernel();</code>]] || Identical to 0.990 but code was moved to a Sysroot function
|-
| 0.940-3.60 || <code>DEVELOPMENT_MODE</code> || [[SceSblACMgr#sceSblACMgrIsDevelopmentMode|<code>return sceSblACMgrIsDevelopmentMode();</code>]] ||
|-
| 0.931-0.945 || <code>SAFE_MODE</code> || <source lang="C">
SceKblParam* pKbl = sceKernelSysrootGetKblParam();
return ((pKbl->wakeupFactor & 0x7F) == 0xB) && ((pKbl->bootControlsInfo >> 8 & 0xFF) == 0xA9); //R+SELECT+X+O
</source> ||
|-
| 0.990-3.60 || <code>SAFE_MODE</code> || [[SceSysmem#sceKernelSysrootIsSafeModeForKernel|<code>return sceKernelSysrootIsSafeModeForKernel();</code>]] ||  Routine is similar to 0.931 check
|-
| 0.931-3.60 || <code>UD0_EXIST</code> || <source lang="C">
SceIoStat stat;
return (sceIoGetstat("ud0:", &stat) == SCE_OK);
</source> ||
|-
| 0.931-3.01 || <code>DEMO_MODE</code> || <source lang="C">
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);
</source> ||
|-
| 0.931-1.69 || <code>KERMIT_REV_ES1_X</code> || <code>return (sceKernelSysrootGetKermitRevision() & 0xF0) == 0x10);</code> ||
|-
| 0.931-1.69 || <code>KERMIT_REV_ES2_X</code> || <code>return (sceKernelSysrootGetKermitRevision() & 0xF0) == 0x20);</code> ||
|-
| 0.940-1.69 || <code>KERMIT_REV_ES3_X</code> || <code>return (sceKernelSysrootGetKermitRevision() & 0xF0) == 0x30);</code> ||
|-
| 0.990-1.69 || <code>KERMIT_REV_ES4_X</code> || <code>return (sceKernelSysrootGetKermitRevision() & 0xF0) == 0x40);</code> ||
|-
| 1.80-3.01 || <code>KERMIT_REV_ES4_X</code> || Same as <code>KERMIT10_REV_ES4_X</code> ||
|-
| 1.80-3.01 || <code>KERMIT10_REV_ES4_X</code> || <code>return (sceKernelSysrootGetKermitRevision() & 0x1FFF0) == 0x40);</code> || Change due to new Kermit revision encoding
|-
| 1.80-3.01 || <code>KERMIT15_REV_ES1_X</code> || <code>return (sceKernelSysrootGetKermitRevision() & 0x1FFF0) == 0x110);</code> ||
|-
| 3.10-3.60 || <code>AU_CODEC_IC_CONEXANT</code> || <source lang="C">
uint32_t hwFlag[4];
SceSysrootForDriver_46E72428(&hwFlag); // sceKernelSysrootGetHardwareFlagsForDriver
return ((hwFlag[0] & 0x40) != 0);
</source> || Related to [[SceCodec]] IC. Probably superseded <code>KERMITxx_REV_ESx_X</code> variables
|-
| 2.10-3.60 || <code>BSOD_REBOOT</code> || [[SceSysmem#sceKernelSysrootIsBsodRebootForKernel|<code>return sceKernelSysrootIsBsodRebootForKernel();</code>]] ||
|}


=== ifmodel ===
==== if ====


maybe same to if
Alias of [[SceSysStateMgr#ifmodel|ifmodel]].


=== ifnmodel ===
==== ifnmodel ====


<source>
Conditional code block start. Execute code in block if predicate is false. See [[SceSysStateMgr#if|ifmodel]].
ifnmodel USB_ENUM_WAKEUP
# if USB_ENUM_WAKEUP is 0, load module.skprx.
load sd0:module.skprx
endif
</source>


=== else ===
Syntax:
  ifnmodel <predicate>


Define when branching with if statement.
Example:
  ifnmodel USB_ENUM_WAKEUP
      # Code executes only if USB_ENUM_WAKEUP evaluates to false
      echo Not wakeup due to USB enum!
    endif


<source>
Every <code>ifnmodel</code> block must end with a corresponding [[SceSysStateMgr#endif|<code>endif</code>]].
if USB_ENUM_WAKEUP
load os0:kd/enum_wakeup.skprx
else
load sd0:module.skprx
endif
</source>


=== endif ===
==== else ====


Define at the end of if statement.
Mark the beginning of a failed predicate conditional block. Must reside between a <code>if[n]model</code> and the corresponding <code>endif</code>.


<source>
Syntax:
if USB_ENUM_WAKEUP
  else
load os0:kd/enum_wakeup.skprx
endif
</source>


=== include ===
Example:
  if USB_ENUM_WAKEUP
  load os0:kd/enum_wakeup.skprx
  else
  echo No USB enum wakeup!
  endif


include add config.
==== endif ====


<source>
Marks the end of a conditional block.
- include sd0:boot_config_second.txt
</source>


=== cd ===
Syntax:
  endif


Setting working dir
Example:
  if USB_ENUM_WAKEUP
  load os0:kd/enum_wakeup.skprx
  endif


<source>
==== repeat ====
cd sd0:kd/
load module.skprx
# -> load "sd0:kd/module.skprx"
</source>


=== setenv ===
Start of a repetition block. Commands in a repetition block are repeated multiple times.


same to setmodfile.
Syntax:
  repeat <count>


Looks similar to setenv on Linux.
<code>count</code> is the number of times the code block will be executed, and must be a decimal number.


=== setmodfile ===
Example:
  repeat 3
  echo Something
  endrepeat
  # prints the following:
  #
  # Something
  # Something
  # Something


unknown
==== endrepeat ====


=== repeat ===
End of a repetition block. Must appear after a [[SceSysStateMgr#repeat|<code>repeat</code>]] command.


Probably not implemented in 3.60
Syntax:
  endrepeat


=== endrepeat ===
==== end ====


Probably not implemented in 3.60
Stop the script execution and return success.


=== appspawn ===
Syntax:
  end


<source>
  if SAFE_MODE
- appspawn vs0:vsh/shell/shell.self SHELL_BUDGET_ID
  spawn os0:ue/safemode.self
  end
  endif


or
  echo Not in Safe Mode!


- appspawn sd0:game.self GAME_BUDGET_ID
== Remote Path file ==
</source>


=== tload ===
SceSysStateMgr attempts to read a Remote Path file at <code>host0:psp2config.rpath</code>. This is only done if either <code>SceQafMgrForDriver_B99770A13()</code> or <code>SceQafMgrForDriver_082A4FC2()</code> return true. The <code>rpath</code> file applies to all configuration scripts.


Tool memory load.
The file's syntax is similar to System Configuration scripts.


LoadStart the module to the devkit dedicated memory. Requires DIPSW 210.
This file can be used for two purposes: override the Shell file, and override application spawn path.


<source>tload sd0:module.skprx</source>
If a line starts with <code>set_shell_filename [path]</code>, <code>path</code> is used when <code>appspawn</code>'ing any application with executable name <code>shell.self</code>. See [[SceSysStateMgr#appspawn|appspawn]]. If <code>path</code> is empty, Shell loading override is disabled (i.e. the requested file is loaded).


=== umount_bootfs ===
'''This only affects the [[SceSysStateMgr#appspawn|appspawn]] command.'''


unmount bootfs
Otherwise, if a line doesn't start with a <code>#</code> (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.


<source>
'''This only affects the [[SceSysStateMgr#spawn|spawn]] and [[SceSysStateMgr#appspawn|appspawn]] commands.'''
umount_bootfs
</source>


=== sload ===
When attempting to load file <code>os0:path/to/module.skprx</code>, the following files are attempted to be loaded in order:
# "Remote path" (<code>host0:module/</code> prefix i.e. <code>host0:module/module.skprx</code>) if allowed by QA flags and DIP switches
# "Remote Rpath" (e.g. <code>os0:tk/module.skprx</code> if rpath was <code>os0:tk/</code>) if a rpath file is present and allowed
# "Canonical path" (absolute path if specified, otherwise built from current directory)


LoadStart in Show mode.
Example <code>psp2config.rpath</code> file:
  # Load development Shell from PC
  set_shell_filename host0:dev_shell.self
 
  # Allow test app spawn from PC
  host0:test_app/


LoadStart only on hardware that matches "HardwareInfo & 0x40 != 0" (Show mode).
With this file, the following behaviour is observed:


<source>sload sd0:module.skprx</source>
<code>appspawn vs0:vsh/shell/shell.self</code>:
# Attempt to load <code>host0:dev_shell.self</code>
# Attempt to load <code>host0:test_app/dev_shell.self</code>
Note how the original Shell path is completly ignored.


<code>spawn os0:kd/test_exec.self</code>
# Attempt to load <code>host0:module/test_exec.self</code> if allowed by QAF
# Attempt to load <code>host0:test_app/test_exec.self</code>
# Attempt to load <code>os0:kd/test_exec.self</code>


[[Category:Libraries]]
[[Category:ARM]]
[[Category:Kernel]]
[[Category:Kernel]]
[[Category:Modules]]

Latest revision as of 21:33, 1 May 2023

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.

Script locations for firmware 2.10-3.60
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
Script locations for firmware 1.00-2.06
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
Script locations for firmware 0.995-0.996
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
Script locations for firmware 0.931-0.990
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:

  1. 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.
  2. 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/ (respectively 0x9, 0xC and 0x20) 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:

Available predicates list
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:

  1. "Remote path" (host0:module/ prefix i.e. host0:module/module.skprx) if allowed by QA flags and DIP switches
  2. "Remote Rpath" (e.g. os0:tk/module.skprx if rpath was os0:tk/) if a rpath file is present and allowed
  3. "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:

  1. Attempt to load host0:dev_shell.self
  2. Attempt to load host0:test_app/dev_shell.self

Note how the original Shell path is completly ignored.

spawn os0:kd/test_exec.self

  1. Attempt to load host0:module/test_exec.self if allowed by QAF
  2. Attempt to load host0:test_app/test_exec.self
  3. Attempt to load os0:kd/test_exec.self