KBL Param
The KBL Param buffer (temporary name was sysroot buffer) is a 0x100 or 0x200
bytes sized buffer passed to the Secure Kernel BootLoader in the scratch space and contains all sorts of flags and system parameters. This buffer is created in Second Loader copied to Secure Kernel, passed to the Secure and Non-Secure Kernel BootLoaders, and finally to the non-secure kernel. It is used by many functions to check for features that are enabled for the system. The strategy in this buffer is to compute once for all the information that is often used, to share it between all security layers not to have to implement generator code many times, and to implement the generation code in the most secure layer: second_loader (excluding first_loader but that's because first_loader is not updatable and has minimum code).
Structure
Offset | Size | Description |
---|---|---|
0x0 | 0x2 | Version (usually 1) |
0x2 | 0x2 | Size. Size of this structure. 0x100 or 0x200 |
0x4 | 0x4 | Current Firmware Version |
0x8 | 0x4 | Minimum Firmware Version. Comes from SMI IdStorage leaf. |
0xC | 0x4 | Unknown |
0x10 | 0x4 | Used for Kit Activation. If lower than 0x20, the Kit is fake activated (License Status = 0, Issue No = 0, Expire Date = 0xffffffff). |
0x14 | 0xC | maybe unused |
0x20 | 0x10 | QA flags |
0x30 | 0x10 | Boot flags |
0x40 | 0x20 | DIP Switches |
0x60 | 0x4 | DRAM base paddr (0x40000000) |
0x64 | 0x4 | DRAM size (0x20000000 on retail and testkit, 0x40000000 on DevKit in DevKit Memory Size mode) |
0x68 | 0x4 | unk |
0x6C | 0x4 | Boot type indicator 1 |
0x70 | 0x10 | OpenPsId |
0x80 | 0x4 | secure_kernel.enp raw data paddr (optional)
|
0x84 | 0x4 | secure_kernel.enp size (optional)
|
0x88 | 0x4 | context_auth_sm.self raw data paddr
|
0x8C | 0x4 | context_auth_sm.self size
|
0x90 | 0x4 | kprx_auth_sm.self raw data paddr
|
0x94 | 0x4 | kprx_auth_sm.self size
|
0x98 | 0x4 | prog_rvk.srvk raw data paddr
|
0x9C | 0x4 | prog_rvk.srvk size
|
0xA0 | 0x8 | PsCode |
0xA8 | 0x8 | unk |
0xB0 | 0x10 | Session ID |
0xC0 | 0x4 | Used by sceSysrootIsUsbEnumWakeup, comes from syscon cmd 3 (ex: 0x10) |
0xC4 | 0x4 | Wakeup Factor |
0xC8 | 0x4 | Unknown, comes from syscon cmd 0x800 (?Device model dependant?) (ex: 0x40, 0x60, 0x64, 0x3D2, 0xC001C0) |
0xCC | 0x4 | Unknown, comes from syscon cmd 0x100 (0x74FFFFFF on coldboot, 0x74FFBFFF on warmboot, 0x36AFFFXX triggers SetProductMode on 0.940, 0x00FF0000 triggers SetProductMode on 0.995) |
0xD0 | 0x4 | Saved context paddr, comes from syscon cmd 0x90 offset 0xC |
0xD4 | 0x4 | Hardware Info |
0xD8 | 0x4 | Boot type indicator 2 |
0xDC | 0xC | unk |
0xE8 | 0x10 | Hardware flags, comes from syscon cmd 6 |
0xF8 | 0x4 | BootLoader Revision |
0xFC | 0x4 | Sysroot Magic value (0xCBAC03AA) |
0x100 | 0x20 | Coredump Encrypted Session Key (FW 2.12+) |
QA flags
In the following table bytes are counted from left to right and bits from left to right too (little-endian). However the OS uses bit masking for QA flags (unlike bit shifting for DIP Switches).
Byte (0-0xF) - mask = 1 << (bit_no & 7) | Description | Used in |
---|---|---|
Byte 0x6 - mask 2 | Allow ScreenShot Always, Np Full Test, Limited Debug Menu Display | Shell, Settings |
Byte 0x9 - mask 0x1 | Used on 0.931 by SceSblACMgrForKernel_F7524073 | |
Byte 0xB - mask 0x4 | kprx_auth_sm | |
Byte 0xB - mask 0x10 | Bypass platform (TEST/TOOL/special CEX) requirement for fSELF with attribute 128 loading | secure_kernel |
Byte 0xC - mask 2 | Allow All Debug Menu Display | Settings |
Byte 0xC - mask 4 | Skip version checks in system updates, Allow DevKit PspEmu | Updater, compat_sm |
Byte 0xD - mask 1 | Allow Kernel Debug (NSKBL logging level set to 0 instead of 1/2, 1 instead of 2), CMeP Debug, USB Enum Wake Up Debug Menu | secure_kernel, most NS and S kernel modules |
Byte 0xD - mask 2 | Allow Remote Sysmodule Load (host0:), Dictates if you can pass arguments to sceAppMgrLaunchAppByPathForDriver | secure_kernel, SceAppMgr |
Byte 0xE - mask 1 | Allow Remote SM and Kernel module Load (host0:), Allow ASLR Disable | second_loader, secure_kernel |
Byte 0xF - mask 1 | Allow NonQA Pup, Minimum Debug Menu Display | secure_kernel, update_service_sm, Updater, Settings |
Byte 0xF - mask 2 | unknown | update_service_sm |
To check: Byte 0xF bit 7, byte 0xE bit 7, byte 0xE bit 6, byte 0xB bit 3: Revocation related.
The data below contains QA Flags captured (at 0x20 in sysroot buffer) from a System Debugger unit (SD DEM):
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000020 33 00 00 00 00 00 07 05 73 01 00 01 06 03 03 01 3.......s.......
Boot flags
These Boot flags come from Ernie NVS and Ernie SNVS.
On FW 3.60, second_loader generates the boot flags as following:
- byte 0 = NVS 0x4A0 byte 0
- byte 1 = SNVS 0x480 byte 1
- byte 2 = 0
- byte 3 = SNVS 0x480 byte 3
- byte 4 = SNVS 0x480 byte 7
- byte 5 = SNVS 0x480 byte 6
- byte 6-0xF = 0
Example: FF FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00
Bit | Description |
---|---|
47 | use internal storage |
- byte 0: 0xFF - not update mode
- byte 1: 0xFF - extra UART not enabled
- byte 3: 0xFF - not safe mode
- byte 4: 0xFF - unknown, maybe not used on FWs <= 0.995
- byte 5: 0xFF on FAT - no internal storage or on PSTV or SLIM - internal storage enabled, 0xFE on PSTV or SLIM - internal storage disabled, maybe not used on FWs <= 0.995
DIP Switches
DIP switches area embeds two parts: Communication Processor information as 32-bit integers, followed by DIP switches stored as bit flags.
Offset | Size | Description |
---|---|---|
0x40 | 0x4 | CP Timestamp 1 (ex: 0x4AD86AB3 -> 16/10/2009 14:44:35) |
0x44 | 0x2 | CP Version (ex:0x1301 => 1301 on PDEL-100x) |
0x46 | 0x2 | CP Board ID (3 on DEM-300xH, 4 on PDEL-100x) |
0x48 | 0x4 | CP Timestamp 2 (identical as CP Timestamp 1) |
0x4C | 0x4 | ASLR Seed (?USER flags?) (also set on Retail and TestKit) (ex: 0x00000000 on a DEM-300xH) |
0x50 | 0x4 | SDK (SCE) flags (ex: 0x80000000, 0x80000001, 0x80000003, 0x81000000, 0x81000001, 0, 2) |
0x54 | 0x4 | Shell flags (ex: 0x00000000 on a DEM-300xH) |
0x58 | 0x4 | Debug control flags (ex: 0x000413E7 on a DEM-300xH, 0x001453E7 dev mode, 0x00080002 release mode) |
0x5C | 0x4 | System control flags (ex: 0x2000001C on a DEM-300xH, 0x20000010 dev mode, 0x20000000 release mode) |
DIP Switches bit flags resolving
Warning: DIP Switches bit flags actually start at offset 0x10 (before that is CP information), which implies the first bit flag number is 128 (bit_num = offset / 8).
DIP Switches bit flags follow little-endian logic, which makes it hard to visualize in commonly used big-endian hexadecimal:
- ((uint32_t *)kbl_param->dipsw[0x10])[0] = 0x00000001 (big-endian in hex) = 01 00 00 00 (little-endian in hex) = 10000000 00000000 00000000 00000000 (little-endian in base 2) <- the 1 corresponds to bit flag number 128
- ((uint32_t *)kbl_param->dipsw[0x10])[0] = 0x00000002 (big-endian in hex) = 02 00 00 00 (little-endian in hex) = 01000000 00000000 00000000 00000000 (little-endian in base 2) <- the 1 corresponds to bit flag number 129
- ((uint32_t *)kbl_param->dipsw[0x10])[0] = 0x00000100 (big-endian in hex) = 00 01 00 00 (little-endian in hex) = 00000000 10000000 00000000 00000000 (little-endian in base 2) <- the 1 corresponds to bit flag number 136
- ((uint32_t *)kbl_param->dipsw[0x10])[0] = 0x80000000 (big-endian in hex) = 00 00 00 80 (little-endian in hex) = 00000000 00000000 00000000 00000001 (little-endian in base 2) <- the 1 corresponds to bit flag number 159
As you can see this way is not convenient to know in memory on which byte corresponds which bit flag, so instead we can use a formula to convert bit number to offset and bit: offset = (bit_num / 32) * 4
, bit = bit_num & 31
. This is used for example in the following code:
SceBool sceKernelCheckDipswForDriver(SceUInt32 no) { return (*(SceUInt32 *)(kbl_param->dipsw + (no >> 5) * 4) >> (no & 31)) & 1; }
CP Information
Bits 0-31
is a 32-bit integer of the current time on the CP clock. This is duplicated in bits 64-95
.
Bits 32-47
is a 16-bit integer of the CP version and bits 48-63
is a 16-bit integer of the CP board ID. All integers are little-endian. On units that do not have a CP, these fields are zeroes.
Bits 96-127
is 32-bit integer ASLR seed that is randomized on each boot in second loader. It can be disabled by setting a specific DIP switch or QA flag byte 0xE mask 1.
Bits 0-63
are also manipulable as general purpose DIP Switches exposed with sceKernelSetDipsw
, sceKernelClearDipsw
, and sceKernelCheckDipsw
but these functions do not change anything in hardware (only cached values are overwritten in SceSysmem).
According to SDK only DIP Switches 0-63 are accessible from usermode, however:
- On FW 0.990 (but not on FW 0.931 nor 3.60), DIP Switch number 237 is the only one out of range 0-63 that can be set from usermode.
- Usermode SELFs can use DIP Switches number > 63 if they have a special attribute or capability in SELF Auth Info.
SDK (SCE) flags
Bits 128-159
are used for DevKit Boot Parameters.
Bit | Name | Description |
---|---|---|
128 | memory_size_switch | Memory Size. (Extended game memory) On: 1 - Off: 0 |
129 | release_check_mode_console | Release Mode Console. On: 1 - Off: 0 |
152 | platform_emulation_dolce | PS TV Emulation. On: 1 - Off: 0 |
159 | development_mode | Release Check Mode. Development Mode: 1 - Release Mode: 0 |
Shell flags
Bits 160-191
are used for SceShell flags.
Bit | Name | Description |
---|---|---|
168 | Memory Size: Console Size: 1 - Development Tool Size: 0 | |
184 | enable_extra_tty | Enable extra TTY: On: 1 - Off: 0. (tty7:) |
185 | Enable System Boot Time Notifications: On: 1 - Off: 0 | |
187 | Allow processes to run on all cores (CPU affinity): On: 1 - Off: 0 |
Debug control flags
Bits 192-223
are for various debug options.
Bit | Description |
---|---|
192 | ? |
193 | Enable SDbgSdio |
194 | Enable CP (if disabled it disables Cpup, DbgSdio and UsbDbg) |
195 | Disable USB Debug. nouse_dbgusb (if enabled, SceUsbDbg doesn't init) |
196 | Enable kernel UART console logging (if enabled, UART is initialized and SceDebug handlers are set to UART functions). |
197 | Enable kernel console logging: On: 1 - Off: 0 |
199 | Enable TTY stdio ("tty0:"): On: 1 - Off: 0 |
200 | Stop when an assertion fails: On: 1 - Off: 0 |
201 | Set minimum assertion level to 1?: On: 1 - Off: 0 |
202 | Set minimum assertion level to 2?: On: 1 - Off: 0 |
204 | Set minimum assertion level to 1: On: 1 - Off: 0. Used in NSKBL. |
205 | Set minimum assertion level to 2: On: 1 - Off: 0. Used in NSKBL. |
210 | Allow Kernel Budget (related to memblock types) |
211 | Enable usermode UART console logging? |
212 | ? Used in NSKBL. Works with dipsw 213. |
213 | ? Used in NSKBL. Works with dipsw 212. |
214 | Disable ASLR |
216 | Wipe SceKernelBootStackCore0 in NSKBL: On: 1 - Off: 0. Used on FW 0.990 by functions SceThreadmgrForKernel_CA84C603 and SceThreadmgrForKernel_05F5306C and on FW 3.60 by NSKBL. |
System control flags
Bits 224-255
are used for various system options.
Bit | Description |
---|---|
224 | Allows loading sd0:psp2-config.txt |
225 | Used in NSKBL when doing something with exception stacks |
228 | Allows getting and setting Process and Thread HBP and HWP. sceKernelGetPHWPForKernel, sceKernelSetPHWPForKernel, sceKernelGetPHBPForKernel, sceKernelSetPHBPForKernel, sceKernelGetTHBPForDriver, sceKernelSetTHBPForDriver. |
229 | HDCP related? |
232 | ? Used in second_loader. DIP Switches 232, 240 and 241 are related. |
236 | GPU overclock. When enabled, GPU and GPU Xbar are overclocked from 111MHz to 166MHz. |
237 | On FW 0.990 (but not on FW 0.931 nor 3.60), this is the only DIP switch out of range 0-63 that can be set from usermode. |
238 | Underclock. When enabled, something is underclocked from 222MHz to 111MHz. |
239 | Underclock/overclock related. |
240 | ? Used in second_loader. DIP Switches 232, 240 and 241 are related. |
241 | ? Used in second_loader. DIP Switches 232, 240 and 241 are related. |
250 | Enable "tty0:" |
251 | Enable "dummytty0:" |
252 | ? Used in SceSblFwLoader. |
253 | Enable some console logging: On: 1 - Off: 0. Used in NSKBL. |
if ((System control flags & 1) != 0) { // not allow load QA flag } else { // allow load QA flag }
if ((System control flags & 2) != 0) { // clear qa flags // (SceQafMgrForDriver_382C71E8, SceQafMgrForDriver_52B4E164, sceSblQafMgrIsAllowHost0Access and sceSblQafMgrIsAllowDecryptedBootConfigLoad functions will return false) }
Boot type indicator 1
We ignore the official name so we name it Boot type indicator 1.
- 0x1: external boot mode. It is used in internal FWs to boot in external mode. It cannot be set in external (release) second_loader.
- 0x2: seems to be never set in external (release) second_loader
- 0x4: product mode. manufacturing mode (Mgmt bit 0)
- 0x8: seems to be never set in external (release) second_loader
- 0x40: use special media type. Never set in external (release) second_loader. Used in NSKBL when loading modules from sd0:.
- 0x10000: seems to be never set in external (release) second_loader, allows to bypass current fw check for module loading
- 0x20000: on resume, no boot logo
- 0x40000: manufacturing mode (Mgmt bit 0) and GCSD initialized (for mounting sd0:) by second_loader using Ernie command 0x888
- 0x80000: ?sd mode? - (Mgmt bit 1)
Wakeup Factor
- 14 FF 00 00
- 04 FF 00 00 after normal reboot
- 04 00 00 00
- 00 FF 00 00
- 0F 00 00 00 ?some debug mode?, -> sceSysrootIsUsbEnumWakeupForKernel : 1
- 80 xx xx xx after suspend
Hardware Info
Data returned by Ernie.
The following list is ordered by Ernie version, that should approximately match the hardware revision order.
- 03 10 10 00: supports FW 0.931
- 03 20 10 00: supports FW 0.931
- 00 40 31 00: supports FW 0.931
- 03 24 10 00: supports FW 0.931-1.691, seems to be DEM-3000L (IRT-002) (to confirm)
- 00 50 31 00: supports FW 0.931-1.691
- 03 26 10 00: supports FW 0.940-3.68
- 00 52 31 00: certainly DEM-3000H (IRT-001), supports FW 0.940-1.691
- 00 10 41 00: supports FW 0.990-1.691
- 00 40 41 00: supports FW 0.990-1.691
- 00 50 41 00: supports FW 0.996-1.691
- 00 52 41 00: supports FW 0.996-3.68
- 00 60 41 00: PDEL-10XX (IRT-002), supports FW 1.000-3.68
- 00 40 40 00: unknown DEX model, CEM-3000, supports FW 0.990-1.692
- 00 41 40 00: unknown DEX model, CEM-3000, supports FW 0.990-1.692
- 00 44 40 00: unknown DEX model, CEM-3000, supports FW 0.990-1.692
- 00 46 40 00: unknown DEX model, CEM-3000, supports FW 0.990-1.692
- 00 48 40 00: unknown DEX model, supports FW 1.66-1.692
- 00 50 40 00: unknown DEX model, supports FW 1.66-3.68
- 00 52 40 00: unknown DEX model, supports FW 1.66-3.68
- 00 60 40 00: PCH-10XX / PTEL-10XX (IRS-002 without 3G PCIe), supports FW 1.04-3.73
- 02 60 40 00: PCH-11XX (IRS-002 with 3G PCIe), supports FW 1.04-3.73
- XX XX 51 00: Prototype PSTV.
- 00 10 60 00: hybrid TOOL/DEX/CEX model (IRS-1001), supports FW 1.80-3.73
- 00 20 60 00: unknown DEX/CEX model (IRS-1001), supports FW 1.80-3.73
- 00 30 60 00: unknown DEX/CEX model (IRS-1001), supports FW 1.80-3.73
- 00 32 60 00: PCH-10XX / PCH-11XX (IRS-1001), supports FW 1.80-3.73
- 30 30 70 00: VTE-10XX (DOL-1001), supports FW 2.50-3.73
- 38 50 80 00: PCH-20XX / PTEL-20XX (USS-1001), supports FW 2.50-3.73
- 30 30 72 00: VTE-10XX (DOL-1002), supports FW 3.30-3.73
- 38 22 82 00: PCH-20XX (USS-1002), supports FW 3.50-3.73
- XX XX 90 00: Unknown prototype.
Bytes meaning
Little-endian as usual.
First byte
This byte indicates the presence of some components:
- 00 -> FAT WIFI
- 02 -> 3G. This is what SceBbmc checks to know if 3G is supported.
- 03 -> probably SD card reader
- 30 -> PSTV (USB, ethernet)
- 38 -> SLIM (micro USB)
Second byte
This byte indicates the motherboard minor version. It is relative to the motherboard main version which is indicated by third byte.
Third byte
This byte indicates the motherboard main version:
- 10 -> unknown prototype motherboard, has Syscon, maybe IRS-001, seems to be IRT-002 (to confirm)
- 31 -> IRT-001
- 40 -> IRS-002
- 41 -> IRT-002
- 51 -> unknown prototype, maybe IRT-003
- 60 -> IRS-1001
- 70 -> DOL-1001
- 72 -> DOL-1002
- 80 -> USS-1001
- 82 -> USS-1002
- 90 -> unknown prototype, maybe PSP3
Fourth byte
This byte is reserved in case 3 bytes becomes not enough to handle all Hardware Info:
- 00 -> default, unused
Boot type indicator 2
Experimental point of view
- No AC connected + No POWER Button pressed: 0x0
ex: rebooting by software PSVita when AC is not connected
- No AC connected + POWER Button pressed: 0x4
ex: booting PSVita by pressing POWER button when AC is not connected
- AC connected + No POWER Button pressed: 0x8
ex: rebooting by software PSVita when AC is connected
ex: autobooting PSTV/IDU PSVita by pluging AC
- AC connected + POWER Button pressed: 0xC
ex: powering off by software PSTV then booting it by pressing POWER button
ex: booting PSVita by pressing POWER button when AC is connected
Bit flags point of view
Bit | Description |
---|---|
0 | AC: connected: 1 - disconnected: 0 (note that PSTV always has AC connected) |
1 | POWER button: pressed: 1 - not pressed: 0 |
Hardware flags
Bit | Description |
---|---|
1 | IC Conexant: 1 - yes, 2 - no |
5 | unk |
6 | unk |
7 | unk |
14 | unk |
- all zeroes on most cases
- seen values: 47 02, 07 00 on a Slim PSVita
Types
typedef struct SceDIPSW { uint32_t cp_timestamp_1; uint16_t cp_version; uint16_t cp_build_id; uint32_t cp_timestamp_2; uint32_t aslr_seed; uint32_t sce_sdk_flags; uint32_t shell_flags; uint32_t debug_control_flags; uint32_t system_control_flags; } SceDIPSW; typedef struct SceKblParam { uint16_t version; uint16_t size; uint32_t current_fw_version; uint32_t min_fw_version; uint32_t unk_C; uint32_t unk_10; uint8_t unk_14[0xC]; uint8_t qa_flags[0x10]; uint8_t boot_flags[0x10]; SceDIPSW dipsw; uint32_t dram_base; uint32_t dram_size; uint32_t unk_68; uint32_t boot_type_indicator_1; uint8_t openpsid[0x10]; uint32_t secure_kernel_enp_addr; uint32_t secure_kernel_enp_size; uint32_t context_auth_sm_self_addr; uint32_t context_auth_sm_self_size; uint32_t kprx_auth_sm_self_addr; uint32_t kprx_auth_sm_self_size; uint32_t prog_rvk_srvk_addr; uint32_t prog_rvk_srvk_size; uint8_t pscode[8]; uint8_t unk_A8[8]; uint8_t session_id[0x10]; uint32_t unk_C0; uint32_t wakeup_factor; uint32_t unk_C8; uint32_t unk_CC; uint32_t resume_context_addr; uint32_t hardware_info; uint32_t boot_type_indicator_2; uint8_t unk_DC[0xC]; uint8_t hardware_flags[0x10]; uint32_t bootldr_revision; uint32_t magic; uint8_t coredump_session_key[0x20]; uint8_t unused[0xE0]; } __attribute__((packed)) SceKblParam;