Hypervisor Reverse Engineering: Difference between revisions
Graf chokolo (talk | contribs) |
Graf chokolo (talk | contribs) |
||
Line 4,819: | Line 4,819: | ||
* The service returns the ENCDEC key index used for the key | * The service returns the ENCDEC key index used for the key | ||
* '''ENCDEC supports upto 16 keys !!!''' | * '''ENCDEC supports upto 16 keys !!!''' | ||
* Storage Manager in HV process 6 has a bit mask of size 2 bytes which indicates which keys are used currently. | |||
Per default, keys with index 0x0 - 0xB are not free. But we could patch it also. | |||
=== 0x5002 - Set/Delete ATA (Encdec) Key === | === 0x5002 - Set/Delete ATA (Encdec) Key === |
Revision as of 19:53, 22 March 2011
This is a copy of the page from 22nd of February 2011, right before ps3wiki.lan.st went down.
EDIT: Not anymore, because i added more stuff now :-) And i continue to update it (graf_chokolo)
HSPRG
- The hypervisor stores a pointer to some structure per LPAR in HSPRG0 register.
- There are actually 2 HSPRG0 values: one for each thread of Cell CPU !!!
- There is a HSPRG0 array at 0x8(-0x69A0(HSPRG0)) + 0x20.
LPAR
LPAR = Logical Partition
lpar1 starts at 0x<unknown>, and its belived to be the memory space where lv1 stores its variables, flags and other data.
lpar2 starts at 0x80000000000 and it's belived to be the memory space where lv2 stores its variables, flags and other data.
The pointer to active LPAR is stored at -0x67E8(HSPRG0).
vtable
0x0033CA40 (3.15)
Member variables
offset 0x38 - some pointer
offset 0x50 - LPAR id (8 bytes)
offset 0x70 - pointer to VAS id bitmap
offset 0x78 - power of 2 of word size from VAS id bitmap (4 bytes), equal to 6
offset 0x7C - number of 64-bit words in VAS id bitmap(4 bytes)
Interrupt handling
The pointer to the interrupt handler that is called e.g. when an external interrupt occurs is at -0x69F0(HSPRG0).
0x00001930 (3.15 and 2.60)
Interrupt vector tables
There are 2 interrupt vector tables. One for each thread. The pointer to these tables is at -0x6950(HSPRG0).
offset 0x8 - IIC memory base address (8 bytes)
offset 0x10 - thread register offset (8 bytes)
offset 0x18 - start of interrupt vector table (19 entries, each entry 32 bytes)
Interrupt vector table entry
offset 0x0 - pointer to interrupt handler
offset 0x8 - TOC
offset 0x10 - 0
offset 0x18 - parameter to interrupt handler
Interrupt handlers
Spurious interrupt handler
0x002BC174 (3.15)
RSX
0x00219A44 (3.15)
0x002176FC (2.60)
SB bus
0x002B9CC4 (3.15)
I/O address translation
0x002CD7D8 (3.15)
0x002C9214 (2.60)
Performance monitor
0x002F0584 (3.15)
0x002EB1B0 (2.60)
Token manager
0x002BBA9C (3.15)
0x002B754C (2.60)
HV call
- The address of HV table is stored at -0x6FC8(HSPRG0).
- The address of HV table size is stored at -0x6FD0(HSPRG0).
HV call
Id | Name | Description |
---|---|---|
62 | lv1_undocumented_function_62 | SPE (isolation, it updates a SLB entry, writes to SLB_Index, SLB_VSID, SLB_ESID and SLB_Invalidate_Entry registers) |
89 | lv1_undocumented_function_89 | SPE (writes to MFC_TLB_Invalidate_Entry register) |
99 | lv1_authenticate_program_segment | SPE (isolation, syscall 0x10043, syscall 0x10042, syscall 0x1004A) |
102 | lv1_undocumented_function_102 | Returns current TB ticks |
137 | lv1_undocumented_function_137 | SPE |
138 | lv1_undocumented_function_138 | SPE |
167 | lv1_undocumented_function_167 | SPE (isolation, reads from SPU_Out_Intr_Mbox and MFC_CNTL registers) |
168 | lv1_undocumented_function_168 | SPE (isolation, writes to MFC_CNTL register) |
195 | lv1_undocumented_function_195 | WLAN Gelic device |
196 | lv1_undocumented_function_196 | WLAN Gelic device |
200 | lv1_undocumented_function_200 | SPE (isolation) |
201 | lv1_undocumented_function_201 | SPE (isolation) |
209 | lv1_undocumented_function_209 | SPE (isolation) |
250 | lv1_undocumented_function_250 | Storage device |
251 | lv1_undocumented_function_251 | Storage device |
252 | lv1_undocumented_function_252 | Storage device |
253 | lv1_undocumented_function_253 | Storage device |
Initializing HV Call Table
set_lv1_hvcall_table
0x002C02B4 (3.41)
0x002C1F04 (3.15)
0x002C2B4C (3.55)
This function sets pointer to HV Call Table and the size of HV Call Table in HSPRG context of a LPAR.
set_lv1_hvcall_table_entry_invalid
0x002C1F28 (3.15)
0x002C02D8 (3.41)
0x002C2B70 (3.55)
This function initializes an entry in HV Call Table to the Invalid HV Call function.
Memory HV call
- All memory HV calls branch to lv1_mm_call
- lv1_mm_call has it's own function table
- Memory HV call number = HV call number
Memory HV call table
- Each entry is a pointer to a function TOC entry.
- table size = 256
0x00364208 (3.15)
0x00362308 (3.41)
0x00366088 (3.55)
Memory HV calls
lv1_map_htab - 0x002D595C (3.15)
lv1_unmap_htab - 0x002D56B8 (3.15)
lv1_allocate_memory - 0x002D72F0 (3.15)
lv1_release_memory - 0x002D66A4 (3.15)
lv1_query_logical_partition_address_region_info - 0x002C9B24 (3.15)
lv1_create_repository_node - 0x002DD014 (3.15)
lv1_get_repository_node_value - 0x002DD260 (3.15)
lv1_undocumented_function_231 - 0x0030B560 (3.15)
System call
HV Processes do not use HV calls. They use syscalls only.
System call handler
0x002974D8 (3.15)
0x00292F6C (2.60)
There are 2 system call tables in HV. The first one stores system calls 0 - 36. The second one stores system calls 0x10000 - 0x100FF.
System call table 0 - 36
0x0035FAE8 (3.15)
0x00358ED0 (2.60)
System call numbers
0x1 - getpid(void)
0x2 - getppid(void)
0x3 - fork(void)
0x4 - exit
0x5 - exec(filename)
0x6 - wait(status)
0x7 - open(filename)
0x8 - close(fd)
0x9 - read
0xA - write
0xB - seek
0xC - unlink(filename)
0xD - signal
0xE - kill(pid, signal type)
0xF - brk
0x10 - socket(af, type, protocol) (supports only address family 0x1F, type 0x0 and protocol 0x0)
0x11 - bind
0x12 - listen(fd, backlog)
0x13 - accept
0x14 - connect
0x15 - ?
0x16 - pause(void)
0x17 - sleep(seconds)
0x18 - mmap(addr, size, prot, flags, fd, offset)
0x19 - munmap
0x1A - some fs func for directories, perhaps readdir
0x1B - ?
0x1C - map_pages (used for alloc)
0x1D - unmap_pages (used for free)
0x1E - select
0x1F - getcwd
0x20 - ?
0x21 - alarm
0x22 - ioctl
0x23 - _map_pages
0x24 - _unmap_pages
System call table 0x10000 - 0x100FF
0x0035DE78 (3.15)
0x00357260 (2.60)
System call numbers
0x10000 - allocate_memory_region(LPAR id, size, log2 of page size, ?, ?)
0x10001 - lpar_query_address_region_info
0x10002 - lpar_memory_addr_to_phys_addr(LPAR id, LPAR address, physical addr)
0x10005 - construct_logical_pu
0x10007 - activate_logical_pu(LPAR id, PPE id)
0x10009 - construct_logical_partition(0, LPAR id, outlet)
0x1000E - release_memory_region(LPAR id, memory region address)
0x1001A - construct_event_receive_port
0x10024 - shutdown_logical_partition(LPAR id, shutdown command)
0x10025 - destruct_logical_partition(LPAR id)
0x10026 - get_logical_partition_info
0x1002C - construct_scheduling_table
0x1002D - set_scheduling_slot
0x10032 - accesses system console
0x10036 - accesses system console
0x10040 - construct_spe_type_1(SPE id, shaddow_addr)
0x10041 - destruct_spe(SPE id)
0x10042 - decrypt_lv2_self(spe id, LPAR auth id, SELF file image ptr, LPAR memory address)
0x10043 - load_spe_module(spe id, SCE module ptr, arg1, arg2, arg3, arg4)
0x10044 - disable_spe_execution
0x10045 - set_spe_interrupt_mask
0x10046 - read_spe_problem_state_register(spe id, register offset, value)
0x10047 - write_spe_problem_state_register(spe id, register offset, value)
0x1004B - disable_spe_loading
0x10053 - pmi_set_guest_os_mode
0x10081 - accesses system console
0x10084 - construct_virtual_uart(LPAR id, VUART id, VUART data buffer size)
0x10085 - destruct_virtual_uart(LPAR id, VUART id)
0x10088 - RSX_syscall_10088(LPAR id)
0x10089 - RSX_syscall_10089
0x1008A - RSX_syscall_1008A
0x100BE - lv1_ioctl
0x100C0 - create_repository_node(LPAR id)
0x100C1 - get_repository_node_value(LPAR id)
0x100C2 - modify_repository_node_value(LPAR id)
0x100C3 - remove_repository_node_value(LPAR id)
Process
Process table
HV supports only 32 processes simultaneously. The number of processes currently running in HV is stored at address 0x0035EA54 (3.15) and 0x00357E3C (2.60).
The process table is an array of 32 process table entries.
0x0035E850 (3.15)
0x00357C38 (2.60)
Process table entry
offset 0x0 - process status ? (8 bytes)
offset 0x8 - pointer to Process object
create_new_proc
This function creates a new Process object.
0x00298E2C (3.15)
0x002948BC (2.60)
Parameters
r3 - pointer to parent Process object
r4 - ?
copy_user_data
This function copies data to/from user space.
0x00299688 (3.15)
0x00295118 (2.60)
Parameters
r3 - pointer to Process object
r4 - some address in address space of Process
r5 - pointer to buffer in HV space
r6 - size to copy
r7 - ?
r8 - direction of copy (0 - copy from user space, != 0 - copy to user space)
r9 - ?
vtable
Processes have no vtables. That means they have no virtual functions.
Member variables
offset 0x0 - PID (4 bytes)
offset 0x8 - pointer to parent Process object
offset 0x10 - pointer to AddressSpace object
offset 0x30 - pointer to first PThread object of process
offset 0x38 - array of signal handlers (192 * 8 bytes)
offset 0x638 - pointer to pointer to ELF image
offset 0x640 - start of file table (20 * 24 bytes)
offset 0x820 - exit status (4 bytes)
offset 0x898 - pointer to Inode object of current directory
offset 0x8A8 - some pointer
Signals
A process can have upto 192 signal handlers. For example, signal 9 is SIGKILL. A signal handler for SIGKILL cannot be installed and it cannot be ignored.
A process does not have a signal mask. Every thread of a process has it's own signal mask.
Signal constants
0x9 - SIGKILL
0xE - SIGALRM
0x20 - SIGSPUMB
0x21 - SIGSPUMB_SL
0x22 - SIGSPUSTOP
0x23 - SIGSPUSTOP_SL
0x24 - SIGSPUDMA
0x26 - SIGSPUTIMEOUT
0x27 - SIGSPUERR
0x41 - SIGSHUTDOWN
File table
The file table has 20 entries. So, a process can have at most 20 files opened simultaneously. Each entry is 24 bytes large.
offset 0x0 - entry valid or invalid (1 byte), 0 - invalid, 1 - valid
offset 0x8 - pointer to object with File interface
offset 0x10 - current file position (8 bytes)
Process_EA_to_RA
This function translates an effective process address to real address.
0x00297E08 (3.15)
Objects
Here are the addresses of Process objects i could identify in HV dump 3.15:
- 0x006BB0D0 (PID 0)
- 0x0012C010 (PID 3) - ss_server3.fself
- 0x000915D0 (PID 5) - ss_server2.fself
- 0x000E4D70 (PID 6) - ss_server1.fself
- 0x0012C8D0 (PID 9) - sysmgr_ss.fself
Here are the addresses of Process objects i could identify in HV dump 2.60:
- 0x006B7580 (PID 0)
- 0x00135F90 (PID 3)
- 0x000862D0 (PID 5)
- 0x000A9870 (PID 6)
- 0x00084B80 (PID 9)
PThread
All PThread objects of the same Process object are linked together in a list.
vtable
0x003556D8 (3.15)
0x0034ECC0 (2.60)
offset 0x60 - pointer to TOC entry of system call handler
Member variables
offset 0x10 - pointer to next PThread object of Process
offset 0x18 - Thread object
offset 0x2B8 - ? (4 bytes)
offset 0x2C0 - pointer to TOC of some function
offset 0x2C8 - pointer to TOC of some function
offset 0x348 - some conter (4 bytes)
offset 0x3C0 - pointer to Process object that owns PThread object
offset 0x3F8 - signal pending mask (3 * 8 bytes = 192 signals)
offset 0x440 - ConditionVariable object
Signals
A PThread has it's own signal mask, independant of all other PThreads in the same process.
Methods
wait_for_my_turn(Pthread ptr, ?, sleep interruptible flag) = wakeup status - 0x00296FB0 (3.15)
Thread
get_current_thread
This function returns the pointer to current running thread.
0x0028B994 (3.15)
0x0028744C (2.60)
vtable
0x00355750 (3.15)
Member variables
offset 0x288 - some pointer
offset 0x290 - some pointer
AddressSpace
vtable
0x003549A0 (3.15)
0x0034DF88 (2.60)
Member variables
offset 0x8 - Mutex object
offset 0x40 - AddressProtectionDomain object
offset 0x50 - some pointer
offset 0xC0 - some counter (4 bytes)
AddressSpace_EA_to_RA
0x002874D0 (3.15)
AddressProtectionDomain
vtable
0x00354980 (3.15)
Member variables
offset 0x8 - pointer to previous AddressProtectionDomain object
offset 0x10 - pointer to next AddressProtectionDomain object
offset 0x18 - poiinter to pointer to SLB entries
offset 0x20 - pointer to AddressSpace object that owns this object
offset 0x34 - pointer to previous ProtectionPage
offset 0x3C - pointer to next ProtectionPage
offset 0x48 - Mutex object
ProtectionPage
vtable
none
Member variables
offset 0x0 - RA (8 bytes)
offset 0x8 - EA (4 bytes)
offset 0x10 - pointer to previous ProtectionPage (4 bytes)
offset 0x14 - pointer to next ProtectionPage (4 bytes)
Mutex
vtable
0x00354D08 (3.15)
0x0034E2F0 (2.60)
Member variables
offset 0x18 - ? (4 bytes)
offset 0x1C - ? (4 bytes)
ConditionVariable
vtable
0x003549C0 (3.15)
offset 0x20 - wait
Member variables
offset 0x20 - pointer to Mutex object
File interface
vtable
offset 0x8 - ?
offset 0x28 - open
offset 0x30 - close
offset 0x38 - read
offset 0x40 - write
offset 0x50 - mmap
offset 0x58 - ioctl
StorageRegionFile
Flash device file class.
vtable
0x003569F8 (3.15)
VUARTFile
VUART device file class.
vtable
0x00356458 (3.15)
STDLCFile
Console device file class.
vtable
0x003561F8 (3.15)
Member variables
offset 0x20 - reference counter (8 bytes)
offset 0x28 - free buffer space ? (8 bytes)
SocketFile
vtable
0x00355DB0 (3.15)
offset 0xB0 - bind
RegionManager
vtable
0x00355F80 (3.15)
Inode
DirectoryInode
vtable
0x00355788 (3.15)
offset 0x20 - link
offset 0x28 - unlink
get_root_inode
This function returns the pointer to the Inode object of the root directory.
0x0029C124 (3.15)
0x00297BB4 (2.60)
vtable
0x00334E50 (3.15)
offset 0x30 - lookup
File system
Console device file objects
Here is the list of console device file objects i found in HV dump 3.15:
- console
vtable
0x003561F8 (3.15)
Flash device file objects
Here is the list of flash device file objects i found in HV dump 3.15:
- /dev/eflash0
- /dev/eflash1
- /dev/rflash0
- /dev/rflash1
- /dev/rflash_1x
- /dev/rflash_1xp
vtable
0x003569F8 (3.15)
IOIF device file objects
Here is the list of IOIF device file objects i found in HV dump 3.15:
- /dev/ioif0
vtable
0x00356688 (3.15)
Member variables
0x360 = MMIO base address
SD detector device file objects
Here is the list of SD detector device file objects i found in HV dump 3.15:
- /dev/sd_detector
vtable
0x00356B48 (3.15)
NET device file objects
Here is the list of NET device file objects i found in HV dump 3.15:
- /dev/net0
vtable
0x00356DE8 (3.15)
INODES
INODE OBJECT
+0x04: previos inode
+0x08: next inodes
+ 0x38: path
+ 0x358: childer_inode
MFS_ROOT_INODE
(2.60) 0x3580B0
+ 0x60 = ROOT_INODE
SOME ADDRESSES IN 2.60
0x60C010: "/dev" inode
0x6AA580: "/proc" inode
using linked list you can follow all inodes
Repository
- Each LPAR has it's own node repository
- Repository nodes are stored in a hash table which can have several sub-hash tables.
RepositoryNode
vtable
0x00357F58 (3.15)
Member variables
offset 0x30 - pointer to next RepositoryNode obj
offset 0x38 - 2nd hash value of name (4 bytes)
offset 0x40 - 1st field name (8 bytes)
offset 0x48 - 2nd field name (8 bytes)
offset 0x50 - 3rd field name (8 bytes)
offset 0x58 - 4th field name (8 bytes)
offset 0x60 - ? (4 bytes)
offset 0x68 - 1st field value (8 bytes)
offset 0x70 - 2nd field value (8 bytes)
Hash Function
- The name of a repository node is hashed and 2 hash values (2 32bit values) are produced.
- The 1st hash value is used to select a sub-hash table.
- The 2nd hash value is used to find a sub-hash table bucket.
- Repository nodes in a hash bucket are ordered by the 2nd hash value.
void hash(unsigned long long n1, unsigned long long n2, unsigned long long n3, unsigned long long n4, unsigned long *h1, unsigned long *h2) { unsigned long long h; unsigned long hl; h = ((((n1 ^ n4) >> 32) ^ (n2 ^ n3)) ^ (((n2 ^ n3) >> 32) ^ (n1 ^ n4))) & ~0xC0000000ULL; *h1 = h & 0xFFFFFFFFULL; h = ((h & 0x55555555ULL) << 1) | ((h & 0xAAAAAAAAULL) >> 1); h = ((h & 0x33333333ULL) << 2) | ((h & 0xCCCCCCCCULL) >> 2); h = ((h & 0xF0F0F0FULL) << 4) | ((h & 0xF0F0F0F0ULL) >> 4); hl = (h << 8) | ((h & 0xFF000000ULL) >> 24); hl = (hl & ~0xFF000000UL) | ((h & 0xFFULL) << 24); hl = (hl & ~0x0000FF00UL) | (((h << 24) | (h >> 8)) & 0x0000FF00ULL); hl |= 0x1; *h2 = hl; }
Repository nodes from HV 3.15
Dump of all repository nodes from HV 3.15
Repository nodes from HV 3.41 dump made from GameOS
Dump of all repository nodes from HV 3.41 dump made from GameOS
Buses
SB bus
type - 4
index - 1
num_devices - 4 (repository node says this but there are more devices !!!)
Storage bus
type - 5
index - 4
num_devices - 4
SB bus subsystem
vtable
0x00352600 (3.15)
Member variables
offset 0x10 - MMIO memory base address
offset 0x20 - array of 16 pointers to SB devices (0 - Gelic device, 1 - USB device)
Objects
0x00349528 - pointer to pointer to SB bus subsystem object
Memory base address
0x24000000000
All SB bus device MMIO addresses are relative to this memory address.
SB device MMIO/DMA memory region
vtable
0x000x352308 (3.15)
Member variables
offset 0x18 - pointer to previous bus memory region object
offset 0x20 - pointer to next bus memory region object
offset 0x30 - relative bus memory start address
offset 0x38 - size of bus memory region
SB bus device
vtable
0x00352620 (3.15)
Member variables
offset 0x18 - array of pointers to MMIO memory region objects owned by device (8 * 8 bytes)
offset 0x60 - pointer to first DMA region object
offset 0x6C - device opened flag (1 byte, 0 - not opened, 1 - already opened)
offset 0x70 - id of LPAR that opened this device
offset 0x90 - pointer to an object that contains the address of interrupt handler for this device and SB bus interrupt index
Gelic device (Network Interface)
device id = 0
interrupt index = 8
MMIO regions
Index | Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|---|
0 | 0x2800 | 0x24000002800 | 0x200 |
1 | 0x3004000 | 0x24003004000 | 0x1000 |
2 | - | - | - |
3 | - | - | - |
4 | - | - | - |
5 | - | - | - |
6 | - | - | - |
7 | - | - | - |
DMA regions
Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|
0xA0000000 | - | 0x8000 |
0xC0000000 | - | 0x10000000 |
SATA Controller 1 device
device id = 1
interrupt index = 49
MMIO regions
Index | Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|---|
0 | 0x2000 | 0x24000002000 | 0x200 |
1 | 0x3000000 | 0x24003000000 | 0x1000 |
2 | 0x3800000 | 0x24003800000 | 0x1000 |
3 | 0x3802000 | 0x24003802000 | 0x1000 |
4 | - | - | - |
5 | - | - | - |
6 | - | - | - |
7 | - | - | - |
DMA regions
Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|
0xA0000000 | - | 0x1000 |
0xA0001000 | - | 0x1000 |
0xA0002000 | - | 0x1000 |
SATA Controller 2 device
device id = 2
interrupt index = 13
MMIO regions
Index | Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|---|
0 | 0x2200 | 0x24000002200 | 0x200 |
1 | 0x3001000 | 0x24003001000 | 0x1000 |
2 | 0x3801000 | 0x24003801000 | 0x1000 |
3 | 0x3803000 | 0x24003803000 | 0x1000 |
4 | - | - | - |
5 | - | - | - |
6 | - | - | - |
7 | - | - | - |
DMA regions
Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|
0xA0000000 | - | 0x1000 |
0xA0001000 | - | 0x1000 |
0xA0002000 | - | 0x1000 |
USB Controller 1 device
device id = 3
MMIO regions
Index | Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|---|
0 | 0x2400 | 0x24000002400 | 0x200 |
1 | 0x3010000 | 0x24003010000 | 0x10000 |
2 | 0x3810000 | 0x24003810000 | 0x10000 |
3 | - | - | - |
4 | - | - | - |
5 | - | - | - |
6 | - | - | - |
7 | - | - | - |
DMA regions
Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|
0xC0000000 | - | 0x10000000 |
0xD0000000 | - | 0x10000000 |
USB Controller 2 device
device id = 4
MMIO regions
Index | Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|---|
0 | 0x2600 | 0x24000002600 | 0x200 |
1 | 0x3020000 | 0x24003020000 | 0x10000 |
2 | 0x3820000 | 0x24003820000 | 0x10000 |
3 | - | - | - |
4 | - | - | - |
5 | - | - | - |
6 | - | - | - |
7 | - | - | - |
DMA regions
Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|
0xC0000000 | - | 0x10000000 |
0xD0000000 | - | 0x10000000 |
ENCDEC device
device id = 7
interrupt index = 5
MMIO regions
Index | Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|---|
0 | 0x2C00 | 0x24000002C00 | 0x200 |
1 | 0x3005000 | 0x24003005000 | 0x1000 |
2 | 0x3006000 | 0x24003006000 | 0x1000 |
3 | - | - | - |
4 | - | - | - |
5 | - | - | - |
6 | - | - | - |
7 | - | - | - |
DMA regions
Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|
0x80010000 | - | 0x10000 |
0x80004000 | - | 0x4000 |
0x80001000 | - | 0x1000 |
0x80003000 | - | 0x1000 |
0x80008000 | - | 0x1000 |
0x80009000 | - | 0x1000 |
0x80040000 | - | 0x10000 |
0x8000A000 | - | 0x1000 |
0x90020000 | - | 0x20000 |
0xC0000000 | - | 0x10000 |
0xC0040000 | - | 0x40000 |
FLASH Controller device (StarShip - SS)
device id = 9
interrupt index = 41
MMIO regions
FLASH controller doesn't have MMIO regions.
DMA regions
Relative Bus Start Address | Absolute Bus Start Address | Size |
---|---|---|
0x80000000 | - | 0x1000 |
0x80020000 | - | 0x20000 |
0x80002000 | - | 0x1000 |
0x90000000 | - | 0x20000 |
SB Bus Interrupt Handling
- There is a table of interrupt handlers for SB devices
- The size of table is 64
- The main SB bus interrupt handler is at 0x002B9CC4 (3.15)
- The main interrupt handler reads interrupt index and dispatches interrupts
Interrupt Index
- The main SB bus interrupt handler reads 2 32-bit values from addresses 0x24000008100 and 0x0x24000008104
- The interrupt index is calculated from these values
Interrupt Handler Table
Interrupt | Description | Address in HV |
---|---|---|
5 | ENCDEC device | 0x00275C60 (3.15) |
6 | EH EPCIC internal | 0x0023B6B0 (3.15) |
8 | Gelic device | 0x00245330 (3.15) |
12 | ATA interrupt handler | 0x0026B984 (3.15) |
13 | ATA interrupt handler | 0x0026B984 (3.15) |
14 | Spider SC | 0x0020A68C (3.15) |
29 | SBERR | 0x0023AA50 (3.15) |
30 | SBERR | 0x0023AA50 (3.15) |
41 | EBUS (Flash StartShip) | 0x002814EC (3.15) |
49 | ATA media interrupt handler | 0x00268A8C (3.15) |
50 | Flash ? | 0x00280B24 (3.15) |
55 | EH EPCIC SERR | 0x0023B67C (3.15) |
Storage bus subsystem
vtable
0x00353AC8 (3.15)
Member variables
offset 0xEE8 - table of pointers to storage device objects (7 * 8 bytes, max 7 devices)
Storage device class
Member variables
offset 0x8 - device id (8 bytes)
offset 0xD50 - device id (8 bytes)
offset 0xD60 - pointer to ENCDEC SB bus device object
Region Manager
- Each storage device has a Region Manager (i call it like that)
- Region Manager stores information about each Region of the storage device
- All Regions of a Region Manager are linked together
- Free Regions of a Region Manager are linked together also
- A Region Manager can have at most 8 Regions
Region
- Each storage device can have at most 8 regions (0-7)
- Each region has ACL table
- HV checks region ACLs before allowing access to the region
- Each region has a start sector that is an offset from the physical first sector of the storage device and a number of sectors
- The start sector passed to lv1 storage hvcalls is relative to the start sector of the region passed to the lv1 storage hvcall
Region ACL
offset 0x0 - LPAR AUTH ID (8 bytes)
offset 0x8 - access rigths (8 bytes)
offset 0x10 - entry valid flag: 0 - invalid, 1 - valid (1 byte)
Region Access Protection
- Before a storage region is accessed, HV checks access rights of the caller.
- Repository node ss.laid (LPAR authentication id) is evaluated for this purpose.
- If LPAR has a repository node ios.ata.region0.access (value doesn't matter) then the access rights check never fails. After System Manager sets ATA keys it removes this repository node from LPAR 1. If we add this repository node again or patch System Manager so it's not removed then we will be able to access all storage regions of all storage devices.
- ALL storage accesses from LPAR 1 are allowed
- If (flags & 0x100000002) != 0 then access rights check is skipped !!!.
I tested on HV 3.41 with flags 0x2 and got access to regions which were denied by policy (LV1_DENIED_BY_POLICY result).
Storage Device Partition Table
- Each storage device has a Partition Table
- Partition Table contains information about each region on the storage device
Methods
lv1_storage_create_region (lv1_undocumented_function_250) - 0x00301328 (3.15)
lv1_storage_delete_region (lv1_undocumented_function_251) - 0x003011E8 (3.15)
lv1_storage_set_region_acl (lv1_undocumented_function_252) - 0x00300F3C (3.15)
lv1_storage_get_region_acl (lv1_undocumented_function_253) - 0x00301090 (3.15)
storage_device_create_region - 0x00253988 (3.15)
storage_device_delete_region - 0x00253BE8 (3.15)
storage_device_region_set_acl - 0x00252C80 (3.15)
storage_device_region_get_acl - 0x00252710 (3.15)
storage_region_mgr_create_region - 0x0025A530 (3.15)
storage_region_mgr_delete_region - 0x0025BA64 (3.15)
storage_region_mgr_set_acl - 0x0025A140 (3.15)
storage_region_mgr_get_acl - 0x0025A298 (3.15)
storage_region_mgr_update_partition_table - 0x00259924 (3.15)
storage_region_acl_entry_reset - 0x0025C1A8 (3.15)
storage_region_acl_entry_check_laid - 0x0025C1FC (3.15)
storage_region_overlap - 0x0025C094 (3.15)
storage_region_check_access - 0x00259EC8 (3.15)
Storage subsystem device
device id = -1
- The storage subsystem is a storage device itself.
- It's a psuedo device used to notify a LPAR when storage devices become e.g. ready.
- Linux implements a loop and reads from this device and process notifications (adds new devices dynamically).
Notification Events
List of supported notification events:
- Notify Device Ready (0x1)
- Notify Region Probe (0x2)
- Notify Region Update (0x4)
RBD device
- On Linux, ENCDEC and RBD devices are mapped to the storage device with device id 0.
- On GameOS, ENCDEC device has device id 0 and RBD device has device id 2.
device id = 0
block size = 2048
/dev/rbd0
- The RBD storage device uses ENCDEC device.
vtable
0x00354288 (3.15)
Member variables
offset 0x1808 - request table (0x58 * 32 bytes)
Regions
Index | Start sector | Number of sectors |
---|---|---|
0 | 0x0 | 0x7FFFFFFF |
1 | - | - |
2 | - | - |
3 | - | - |
4 | - | - |
5 | - | - |
6 | - | - |
7 | - | - |
Supported Device Commands
Here is the list of commands supported by RBD storage device.
- The commands can be used with HV call lv1_storage_send_device_command.
- However, before a command is executed HV does bit manipulation with it and checks it against the value of repository node ss.laid or also called LPAR authentication ID. If this test fails then the command is NOT executed.
Command | Description |
---|---|
0x1 | LV1_STORAGE_SEND_ATAPI_COMMAND |
0x10 | ATAPI Read Capacity |
0x11 | ATAPI Get Configuration |
0x13 | ATAPI Read TOC |
0x1A | ATAPI Get Event |
/dev/rbd0
- This LPAR 1 device accesses RBD storage device.
- A write to this device sends a device command to RBD storage device.
ENCDEC Device
bus id = 4
device id = 0
- ENCDEC device has a request table of size 32.
Member variables
offset 0xDC0 - request table (0x58 * 32 bytes)
Methods
encdec_device_initialize - 0x00273524 (3.15)
InitializeENCDEC - 0x00277310 (3.15)
ENCDEC_ConnectBusDriver - 0x00275A98 (3.15)
encdec_interrupt_handler - 0x00275C60 (3.15)
encdec_process_interrupt - 0x0027526C (3.15)
encdec_device_enqueue_decsec_request - 0x00273738 (3.15)
encdec_device_do_request - 0x00273EA8 (3.15)
encdec_device_do_SS_request - 0x00274940 (3.15)
Encdec_KickDMA - 0x00277118 (3.15)
encdec_device_is_in_testmode - 0x002756E0 (3.15)
is_encdec_in_testmode - 0x002732D0 (3.15)
ENCDEC Device Commands
- EdecKgen1 command is used e.g. by Storage Manager Service 0x5003 to generate random numbers. Storage Manager performs this command through LPAR 1 device /dev/encdec0.
Command | Description |
---|---|
0x81 | EdecKgen1 |
0x82 | EdecKgen2 |
0x83 | EdecKset/EdecKset NG |
0x84 | EdecKgenFlash |
0x85 | Encrypts/decrypts sectors (This command cannot be executed through ioctl interface !!!) |
0x86 | Encdec decsec (This command cannot be executed through ioctl interface !!!) |
0x87 | EdecSBClear |
EdecKgen1 Command (0x81)
- First, ENCDEC device key generator is flashed by executing the operation which is also performed during EdecKgenFlash command.
- 0x30 bytes of data are written to MMIO registers of ENCDEC device.
- 0x40 bytes of data are read from MMIO registers of ENCDEC device.
- The base address of MMIO registers used in this command is 0x24003006000.
- I tested this command by directly communicating with ENCDEC device from GameOS by using HV call lv1_storage_send_device_command and it returns random data.
Here is the data i sent to ENCDEC device:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 00 01 00 30 72 A7 88 EC FC A4 06 71 4C B1 50 C9 ...0r§ˆìü¤.qL±PÉ 00000010 FB E0 06 C2 74 B5 84 C4 E6 BD 1E 55 4E 36 E9 C9 ûà.Âtµ„Äæ½.UN6éÉ 00000020 D6 09 BC B4 79 A6 BC DE 60 A5 B2 41 C7 15 68 68 Ö.¼´y¦¼Þ`¥²AÇ.hh 00000030 82 1D 8F D6 00 00 00 00 00 00 00 00 00 00 00 00 ‚.Ö............
Here is the data i received back from ENCDEC device:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 00 02 00 00 57 CF 06 AF 53 85 1B B8 49 37 06 28 ....WÏ.¯S….¸I7.( 00000010 51 8D 4E F9 EF 76 E2 C7 17 EF 41 14 FA 6C 96 A8 QNùïvâÇ.ïA.úl–¨ 00000020 7E 41 43 96 15 9A 0D 71 A9 B6 A6 B0 F1 96 15 C5 ~AC–.š.q©¶¦°ñ–.Å 00000030 30 25 C3 8E 6F AC FB 7F E7 2A FB E2 36 E1 85 92 0%ÃŽo¬û?ç*ûâ6á…’ 00000040 99 66 DB EC 00 00 00 00 00 00 00 00 00 00 00 00 ™fÛì............
Here is another data i received back from ENCDEC device by using the same command and data:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 00 02 00 00 57 CF 06 AF 53 85 1B B8 49 37 06 28 ....WÏ.¯S….¸I7.( 00000010 51 8D 4E F9 EF 76 E2 C7 17 EF 41 14 FA 6C 96 A8 QNùïvâÇ.ïA.úl–¨ 00000020 7E 41 43 96 17 08 75 F6 66 2F 32 5A 9E 3E E7 FD ~AC–..uöf/2Zž>çý 00000030 16 3E 18 CA B2 5E 90 84 29 7F 98 BC 73 36 0E 7B .>.ʲ^„)?˜¼s6.{ 00000040 7D EC B6 37 00 00 00 00 00 00 00 00 00 00 00 00 }ì¶7............
EdecKgen2 Command (0x82)
- The base address of MMIO registers used in this command is 0x24003006000.
EdecKset Command (0x83)
EdecKgenFlash Command (0x84)
- The base address of MMIO registers used in this command is 0x24003006000.
- The command reads 4 bytes from address 0x240030060A0, sets bit 1 to 1 (old value | 0x2) and writes the new value to the same address.
Encdec decsec Command (0x86)
- This command is used to decrypt/encrypt sectors.
- FLASH, HDD and RBD storage devices use this command to decrypt/encrypt sectors.
- This command cannot be executed through lv1_storage_send_device_command HV call, it's used by HV only internally.
EdecSBClear Command (0x87)
- The command expects arg2 to be 4 or else it returns with an error.
- This command is used e.g. by Storage Manager service 0x5002 when ATA keys are deleted.
Test Mode
- ENCDEC device has Test Mode
- Some HV functions test it by reading a 4 byte value from address 0x24003005200. If this value is 0 then ENCDEC device is NOT in Test Mode.
ENCDEC Request
offset 0x34 - start sector (4 bytes)
offset 0x38 - sector count (4 bytes)
offset 0x3C - sector size (4 bytes)
offset 0x40 - key (4 bytes)
offset 0x44 - 0 = decrypt, 1 = encrypt (4 bytes)
Encrypting and Decrypting Sectors
- HV passes to ENCDEC device addresses of 2 buffers: ENCDEC User Buffer and ENCDEC Descriptor Buffer.
- ENCDEC User Buffer contains the following information: Start Sector, Sector Count, Sector Size and Key
ENCDEC User Buffer
offset 0x0 - start sector (4 bytes)
offset 0x4 - sector count (4 bytes)
offset 0x8 - sector size (4 bytes)
offset 0xC - key (4 bytes)
FLASH device
device id = 1
- The FLASH device uses ENCDEC device.
vtable
0x00354450 (3.15)
Member variables
offset 0x18F0 - request table (0x58 * 16 bytes)
Regions
Index | Start sector | Number of sectors |
---|---|---|
0 | 0x0 | 0x8000 |
1 | 0x8 | 0x77F8 |
2 | 0x7900 | 0x100 |
3 | 0x7A00 | 0x400 |
4 | - | - |
5 | - | - |
6 | - | - |
7 | - | - |
Supported Device Commands
Here is the list of commands supported by FLASH StarShip 2 storage device.
- The commands can be used with HV call lv1_storage_send_device_command.
- However, before a command is executed HV does bit manipulation with it and checks it against the value of repository node ss.laid or also called LPAR authentication ID. If this test fails then the command is NOT executed.
Command | Description |
---|---|
0x31 | Dummy (This command does nothing, returns success immediately) |
0xA2 | - |
0xA3 | - |
0xA4 | - |
0xA6 | SS2 HW Reset |
0xAC | - |
0xAD | TEST |
/dev/eflash1 and /dev/rflash1
- These LPAR 1 devices access region 0 of FLASH storage device.
- /dev/rflash1 is 16MB large
- There is no file system on /dev/rflash1
- There is some sort of TOC (Table Of Contents) stored in it. It contains file names, offsets and sizes.
- On /dev/rflash1 you will find lv0, lv1ldr, lv2_lernel.self and all the other important SELFs.
- The files are encryted of course.
Content of /dev/rflash1 (FLASH storage device region 0, size 16 MB)
- There is a main TOC which describes different regions on /dev/rflash1
- It seems that TOC 0xC0000 and TOC 0x7C0000 contain the same files but from different SDK versions.
- TOC 0xC0000 is SDK version 3.41 and TOC 0x7C0000 is SDK version 3.30 (look at the content of files sdk_version).
- I guess it's because when i bought my PS 3 Slim it had Firmware 3.30 and i updated it to 3.41 for PSGroove.
- TOC on /dev/rflash1 is used by HV Processes to locate files and load them into memory, e.g. SPU modules. E.g. Process 6 loads spu_utoken_processor.self to decrypt and verify user tokens or SPL which runs in Process 5 loads spp_verifier.self from there in order to decrypt and verify profile files. And Update Manager stores e.g. there files.
TOC Entry
A TOC entry is 0x30 bytes large.
offset 0x0 - relative offset from this TOC to entry data
offset 0x8 - entry data size
offset 0x10 - entry name (max 32 characters)
Main TOC
Here is a list of regions/files stored on /dev/rflash1 i found in HV 3.41 and dumped with PSGroove:
Entry Name | TOC Offset | Entry TOC Index | Entry Relative Offset | Entry Absolute Offset | Entry Size |
---|---|---|---|---|---|
asecure_loader | 0x400 | 0 | 0x400 | 0x810 | 0x2E800 |
eEID | 0x400 | 1 | 0x2EC00 | 0x2F010 | 0x10000 |
cISD | 0x400 | 2 | 0x3EC00 | 0x3F010 | 0x800 |
cCSD | 0x400 | 3 | 0x3F400 | 0x3F810 | 0x800 |
trvk_prg0 | 0x400 | 4 | 0x3FC00 | 0x40010 | 0x20000 |
trvk_prg1 | 0x400 | 5 | 0x5FC00 | 0x60010 | 0x20000 |
trvk_pkg0 | 0x400 | 6 | 0x7FC00 | 0x80010 | 0x20000 |
trvk_pkg1 | 0x400 | 7 | 0x9FC00 | 0xA0010 | 0x20000 |
ros0 | 0x400 | 8 | 0xBFC00 | 0xC0010 | 0x700000 |
ros1 | 0x400 | 9 | 0x7BFC00 | 0x7C0010 | 0x700000 |
cvtrm | 0x400 | 10 | 0xEBFC00 | 0xEC0010 | 0x40000 |
asecure_loader Region TOC
Here is a list of files stored on /dev/rflash1 i found in HV 3.41 and dumped with PSGroove:
Entry Name | TOC Offset | Entry TOC Index | Entry Relative Offset | Entry Absolute Offset | Entry Size |
---|---|---|---|---|---|
metldr | 0x800 | 0 | 0x40 | 0x840 | 0xE920 |
ros1 Region TOC
Here is a list of files stored on /dev/rflash1 i found in HV 3.41 and dumped with PSGroove:
Entry Name | TOC Offset | Entry TOC Index | Entry Relative Offset | Entry Absolute Offset | Entry Size |
---|---|---|---|---|---|
creserved_0 | 0xC0000 | 0 | 0x460 | 0xC0470 | 0x40000 |
sdk_version | 0xC0000 | 1 | 0x40460 | 0x100470 | 0x8 |
lv1ldr | 0xC0000 | 2 | 0x40480 | 0x100490 | 0x1E948 |
lv2ldr | 0xC0000 | 3 | 0x5EE00 | 0x11EE10 | 0x16FF0 |
isoldr | 0xC0000 | 4 | 0x75E00 | 0x135E10 | 0x13074 |
appldr | 0xC0000 | 5 | 0x88E80 | 0x148E90 | 0x1E254 |
spu_pkg_rvk_verifier.self | 0xC0000 | 6 | 0xA70D4 | 0x1670E4 | 0xFACC |
spu_token_processor.self | 0xC0000 | 7 | 0xB6BA0 | 0x176BB0 | 0x5C94 |
spu_utoken_processor.self | 0xC0000 | 8 | 0xBC834 | 0x17C844 | 0x65D0 |
sc_iso.self | 0xC0000 | 9 | 0xC2E04 | 0x182E14 | 0x1532C |
aim_spu_module.self | 0xC0000 | 10 | 0xD8130 | 0x198140 | 0x4498 |
spp_verifier.self | 0xC0000 | 11 | 0xDC5C8 | 0x19C5D8 | 0xD7F0 |
mc_iso_spu_module.self | 0xC0000 | 12 | 0xE9DB8 | 0x1A9DC8 | 0x808C |
me_iso_spu_module.self | 0xC0000 | 13 | 0xF1E44 | 0x1B1E54 | 0x88B8 |
sv_iso_spu_module.self | 0xC0000 | 14 | 0xFA6FC | 0x1BA70C | 0xC078 |
sb_iso_spu_module.self | 0xC0000 | 15 | 0x106774 | 0x1C6784 | 0x5DB0 |
default.spp | 0xC0000 | 16 | 0x10C524 | 0x1CC534 | 0x22A0 |
lv1.self | 0xC0000 | 17 | 0x10E800 | 0x1CE810 | 0x127DF0 |
lv0 | 0xC0000 | 18 | 0x236600 | 0x2F6610 | 0x3E678 |
lv2_kernel.self | 0xC0000 | 19 | 0x274C78 | 0x334C88 | 0x171B88 |
eurus_fw.bin | 0xC0000 | 20 | 0x3E6800 | 0x4A6810 | 0x70F94 |
emer_init.self | 0xC0000 | 21 | 0x457794 | 0x5177A4 | 0x7CDB8 |
hdd_copy.self | 0xC0000 | 22 | 0x4D454C | 0x59455C | 0x60D68 |
ros2 Region TOC
Here is a list of files stored on /dev/rflash1 i found in HV 3.41 and dumped with PSGroove:
Entry Name | TOC Offset | Entry TOC Index | Entry Relative Offset | Entry Absolute Offset | Entry Size |
---|---|---|---|---|---|
creserved_0 | 0x7C0000 | 0 | 0x460 | 0x7C0470 | 0x40000 |
sdk_version | 0x7C0000 | 1 | 0x40460 | 0x800470 | 0x8 |
lv1ldr | 0x7C0000 | 2 | 0x40480 | 0x800490 | 0x1E64C |
lv2ldr | 0x7C0000 | 3 | 0x5EB00 | 0x81EB10 | 0x16E30 |
isoldr | 0x7C0000 | 4 | 0x75980 | 0x835990 | 0x12EC4 |
appldr | 0x7C0000 | 5 | 0x88880 | 0x848890 | 0x1DB64 |
spu_pkg_rvk_verifier.self | 0x7C0000 | 6 | 0xA63E4 | 0x8663F4 | 0xFACC |
spu_token_processor.self | 0x7C0000 | 7 | 0xB5EB0 | 0x875EC0 | 0x5C94 |
spu_utoken_processor.self | 0x7C0000 | 8 | 0xBBB44 | 0x87BB54 | 0x65D0 |
sc_iso.self | 0x7C0000 | 9 | 0xC2114 | 0x882124 | 0x1532C |
aim_spu_module.self | 0x7C0000 | 10 | 0xD7440 | 0x897450 | 0x4498 |
spp_verifier.self | 0x7C0000 | 11 | 0xDB8D8 | 0x89B8E8 | 0xD7F0 |
mc_iso_spu_module.self | 0x7C0000 | 12 | 0xE90C8 | 0x8A90D8 | 0x808C |
me_iso_spu_module.self | 0x7C0000 | 13 | 0xF1154 | 0x8B1164 | 0x88B8 |
sv_iso_spu_module.self | 0x7C0000 | 14 | 0xF9A0C | 0x8B9A1C | 0xC078 |
sb_iso_spu_module.self | 0x7C0000 | 15 | 0x105A84 | 0x8C5A94 | 0x5DB0 |
default.spp | 0x7C0000 | 16 | 0x10B834 | 0x8CB844 | 0x22A0 |
lv1.self | 0x7C0000 | 17 | 0x10DB00 | 0x8CDB10 | 0x129040 |
lv0 | 0x7C0000 | 18 | 0x236B80 | 0x9F6B90 | 0x3E570 |
lv2_kernel.self | 0x7C0000 | 19 | 0x2750F0 | 0xA35100 | 0x1712D0 |
eurus_fw.bin | 0x7C0000 | 20 | 0x3E63C0 | 0xBA63D0 | 0x70F94 |
emer_init.self | 0x7C0000 | 21 | 0x457354 | 0xC17364 | 0x7FBB8 |
hdd_copy.self | 0x7C0000 | 22 | 0x4D6F0C | 0xC96F1C | 0x61518 |
Methods
initialize_starship - 0x0028298C (3.15)
SSOperation - 0x0027BFB0 (3.15)
SSTransfer - 0x0027BE68 (3.15)
FLASH_Memory_SS2_on_complete - 0x00278E48 (3.15)
_FLASH_read_data - 0x0022D89C (3.15)
_FLASH_write_data - 0x0022D8C8 (3.15)
FLASH_SS2_HW_Reset - 0x0027BD1C (3.15)
HDD device
device id = 2
block size = 512
- The HDD device uses ENCDEC device.
vtable
0x00353F48 (3.15)
Member variables
offset 0x1590 - LBA48 capability flag (4 bytes)
offset 0x17E8 - request table (0x58 * 16 bytes)
offset 0x1DB8 - request timer active flag (1 byte)
Regions
Index | Start sector | Number of sectors |
---|---|---|
0 | 0x0 | 0x950F8B0 |
1 | 0x8 | 0x80000 |
2 | 0x80018 | 0x7C8F898 |
3 | 0x7D0F8B8 | 0x3FFFF8 |
4 | 0x810F8B8 | 0x13FFFF8 |
5 | - | - |
6 | - | - |
7 | - | - |
Supported Device Commands
Here is the list of commands supported by HDD storage device.
- The commands can be used with HV call lv1_storage_send_device_command.
- However, before a command is executed HV does bit manipulation with it and checks it against the value of repository node ss.laid or also called LPAR authentication ID. If this test fails then the command is NOT executed.
Command | Description |
---|---|
0x2 | LV1_STORAGE_SEND_ATA_COMMAND |
0x10 | - |
0x1B | ATA Set UltraDMA Mode |
0x1C | ATA Set Features PIO Flow Control Transfer Mode |
0x21 | - |
0x22 | ATA Identify Device |
0x23 | LV1_STORAGE_ATA_HDDOUT (ATA Flush Cache Ext) |
0x26 | ATA Read Alternative Status |
0x27 | ATA Read Error |
0x28 | - |
0x31 | ATA Flush Cache/ATA Flush Cache Ext |
0x32 | ATA Stanby Immediate |
0x33 | - |
Virtual FLASH device (VFLASH)
device id = 3 (on Linux)/ 4 (on GameOS)
block size = 512
- It's a psuedo device.
- This storage device redirects all requests to the region 1 of HDD storage device !!!
vtable
0x00353D88 (3.15)
Member variables
offset 0xD60 - pointer to a storage device that all requests are redirected to
offset 0xD68 - region ID of the storage device that all requests are redirected to
Regions
Index | Start sector | Number of sectors |
---|---|---|
0 | 0x0 | 0x80000 |
1 | 0x8 | 0x75F8 |
2 | 0x7800 | 0x63E00 |
3 | 0x6B600 | 0x8000 |
4 | 0x73600 | 0x400 |
5 | 0x73A00 | 0x2000 |
6 | 0x77C00 | 0x200 |
7 | - | - |
/dev/rflash1_1x and /dev/rflash_1xp
- These LPAR 1 devices access region 5 of UNKNOWN storage device.
- In region 5 of UNKNOWN storage device is e.g. LINUX image stored.
GameOS's dev_flash
- dev_flash has FAT16 file system.
- Accesses to GameOS's dev_flash are routed to UNKNOWN storage device region 2
- To decrypt sectors read from this region use as flags 0x4 !!! Without using flags 0x4 the sectors will be encrypted.
- The sectors are decrypted not by GameOS but by ENCDEC device.
Here is a snippet from raw dev_flash dump made with HV call lv1_storage_read (flags 0x4) from GameOS:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 E9 00 00 20 20 20 20 20 20 20 20 00 02 10 10 00 é.. ..... 00000010 02 00 02 00 00 F8 70 00 00 00 00 00 00 00 00 00 .....øp......... 00000020 00 3E 06 00 00 00 29 00 00 00 00 4E 4F 20 4E 41 .>....)....NO NA 00000030 4D 45 20 20 20 20 46 41 54 31 36 20 20 20 00 00 ME FAT16 .. 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............Uª
Methods
initialize_virtual_flash - 0x00282954 (3.15)
Enqueueing and Scheduling of Storage Requests
- HV uses a simple FIFO scheduling algorithm for Storage Requests and a request timeout.
- Each storage device has a table of size 16 to store incomming and pending Storage Requests
- ENCDEC storage device has a table of size 32 to store incomming and pending Storage Requests
- When a new Storage Request is submitted e.g. by HV call lv1_storage_read or lv1_storage_write, the table is scanned for a free slot, if there are no pending Storage Requests then the Storage Request is executed immediately
- When a Storage Request is completed, the finished Storage Reuqest is passed to function storage_device_async_request_complete and the table of Storage Requests is scanned again for the next pending Storage Request which will be executed
- There are 2 types of Storage Requests: Read/Write (1) and Device Command (2).
- Read and Write Storage Requests use the same HV function of a Storage Device to enqueue the request. Before Write Storage Request is inserted into the Request Table of a Storage Device, the flags parameter passed e.g. in lv1_storage_read or lv1_storage_write is ored with 0x8. That is how HV differentiates between Read and Write Storage Requests.
Storage Device Request Table
- Each request slot is of size 0x58
Request Slot
offset 0x0 - state: 1 - free, 2 - ? (4 bytes)
offset 0x4 - type: 1 - Read/Write, 2 - Command, 0x86 - ENCDEC command (4 bytes)
offset 0x10 - request tag (8 bytes)
offset 0x20 - start sector (8 bytes)
offset 0x28 - sector count (4 bytes)
ENCDEC Storage Device
- Request Table begins at offset 0xDC0 of ENCDEC storage device.
RBD Storage Device
- Request Table begins at offset 0x1808 of RBD storage device.
FLASH Storage Device
- Request Table begins at offset 0x18F0 of FLASH storage device.
HDD Storage Device
- Request Table begins at offset 0x17E8 of HDD storage device.
Methods
storage_device_HDD_enqueue_request - 0x0026E21C (3.15)
storage_device_HDD_do_device_command - 0x0026CED0 (3.15)
storage_device_HDD_do_request - 0x0026DED8 (3.15)
storage_device_HDD_request_complete - 0x0026E57C (3.15)
storage_device_FLASH_enqueue_request - 0x0027A518 (3.15)
storage_device_FLASH_do_request - 0x00278D1C (3.15)
storage_device_FLASH_do_device_command - 0x00279250 (3.15)
FLASH_Memory_SS2_on_complete - 0x00278E48 (3.15)
storage_device_async_request_complete - 0x00255184 (3.15)
storage_device_TransLparAddrToPhysAddr - 0x002533B4 (3.15)
storage_device_add_async_request_locked - 0x002527B8 (3.15)
storage_device_RBD_enqueue_request - 0x002723F0 (3.15)
storage_device_RBD_do_request - 0x0025EF70 (3.15)
storage_device_RBD_do_next_request - 0x00270994 (3.15)
storage_device_RBD_request_complete - 0x00271FD4 (3.15)
storage_device_rbd_do_request - 0x0025EE94 (3.41)
storage_device_rbd_do_device_command - 0x0027061C (3.41)
Encryption and Decryption of Storage Devices
HDD
- ENCDEC peripheral device is used for HDD encryption/decryption
- Write request is first passed to ENCDEC device for encryption. When ENCDEC device is done, it calls a callback and passes the encrypted data to the callback. The callback writes the encrypted data with ATA WriteDMAExt command to HDD.
- When a storage device request is processed by HV, Storage Subsystem checks if cryptography is enabled for the storage device.
- HV checks 1 byte of data owned by the storage device and when the value of this flag is not 0 then it uses encryption/decryption.
- By setting this flag to 0 at runtime, encryption/decryption of storage devices can be disabled at runtime.
- We could patch lv1.self so that encryption/decryption of storage devices is disabled permanently.
- HDD sectors can be both decrypted and encrypted with HV calls
UFS2
- Superblock starts at sector 0x80.
- At the end of the superblock structure you will find UFS2 signature 0x19540119.
Here is the decrypted superblock of UFS2 filesystem:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00010000 00 00 00 00 00 00 00 00 00 00 00 28 00 00 00 30 ...........(...0 00010010 00 00 00 38 00 00 0B B8 00 00 00 00 00 00 00 00 ...8...¸........ 00010020 00 00 00 00 00 00 00 00 00 00 78 10 00 00 01 5C ..........x....\ 00010030 00 00 40 00 00 00 08 00 00 00 00 08 00 00 00 08 ..@............. 00010040 00 00 00 00 00 00 00 00 FF FF C0 00 FF FF F8 00 ........ÿÿÀ.ÿÿø. 00010050 00 00 00 0E 00 00 00 0B 00 00 00 08 00 00 08 00 ................ 00010060 00 00 00 03 00 00 00 02 00 00 08 00 00 00 00 00 ................ 00010070 00 00 00 00 00 00 08 00 00 00 00 40 00 00 00 00 ...........@.... 00010080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010090 00 00 00 00 F5 35 BD 07 00 00 00 00 00 00 18 00 ....õ5½......... 000100A0 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 ..@............. 000100B0 00 00 00 00 00 00 00 00 00 00 5C 00 00 01 6F 70 ..........\...op 000100C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000100D0 00 00 00 80 2F 63 65 6C 6C 5F 6D 77 5F 63 66 73 ...€/cell_mw_cfs 000100E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000100F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000101A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000101B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000101C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000101D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000101E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000101F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000102A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000102B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000102C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000102D0 00 00 00 00 00 00 00 7C 00 00 00 00 00 00 00 00 .......|........ 000102E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000102F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010330 00 00 00 00 00 00 00 00 80 00 00 00 00 55 FD 70 ........€....Uýp 00010340 80 00 00 00 00 55 E0 00 80 00 00 00 00 55 F8 00 €....Uà.€....Uø. 00010350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 ..............@. 00010360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010390 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000103A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000103B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000103C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000103D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000103E0 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 ................ 000103F0 00 00 00 00 00 00 00 3C 00 00 00 00 00 3B D3 23 .......<.....;Ó# 00010400 00 00 00 00 00 7D 0F 82 00 00 00 00 00 00 00 9F .....}.‚.......Ÿ 00010410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010430 00 00 00 00 49 B0 5E 3B 00 00 00 00 01 F2 3E 26 ....I°^;.....ò>& 00010440 00 00 00 00 01 E2 86 3B 00 00 00 00 00 00 0B B8 .....â†;.......¸ 00010450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000104A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 ..............@. 000104B0 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............ 000104C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000104D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000104E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000104F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00010520 00 00 00 03 00 00 00 08 00 00 00 78 00 00 00 00 ...........x.... 00010530 00 00 80 10 02 02 FF FF 00 00 00 00 00 00 3F FF ..€...ÿÿ......?ÿ 00010540 00 00 00 00 00 00 07 FF 00 00 00 00 00 00 00 00 .......ÿ........ 00010550 00 00 00 00 00 00 00 00 00 00 00 00 19 54 01 19 .............T..
FLASH
RBD
SATA/ATA/ATAPI
ATA Interrupt Handler
0x0026B984 (3.15)
ATA_SetDMA
0x00268ADC (3.15)
ATA_make_PRD_table
0x00267DB4 (3.15)
This function initializes a PRD (Physical Region Descriptor) table.
ClearPATACInterrupt
0x00267CAC (3.15)
EnablePATACInterrupt
0x00267D44 (3.15)
DisablePATACInterrupt
0x00267AF0 (3.15)
ATA_read_AltStatus_reg
0x00267C40 (3.15)
This function reads the ATA Alternate Status Register and returns it's value.
ATA_write_DATA_reg
0x00268A10 (3.15)
This function writes a 16-bit value to the ATA Data Register.
ATA_read_DATA_reg
0x0026887C (3.15)
ATA_write_DATA
0x0026635C (3.15)
This function writes several 16-bit values to the ATA Data register.
ATA_write_CMD_reg
0x002688A0 (3.15)
ATA_read_Error_reg
0x00267BD4 (3.15)
ATA_write_Features_reg
0x002689F0 (3.15)
ATA_write_DevCtrl_reg
0x00267BB4 (3.15)
ATA_write_TaskFile_regs
0x00266BC8 (3.15) 0x002665A0 (3.15)
ATA_send_ATAPI_cmd
0x002655F4 (3.15)
ATA_send_cmd
0x0026580C (3.15)
ATA_send_ReadSectors_cmd
This function uses LBA28.
0x0025D2B4 (3.15)
ATA_send_WriteSectors_cmd
This function uses LBA28.
0x0025CEF4 (3.15)
ATA_send_ReadDMA_cmd
This function uses LBA28.
0x0025D380 (3.15)
ATA_send_WriteDMA_cmd
This function uses LBA28.
0x0025CFB8 (3.15)
ATA_send_ReadDMAExt_cmd
This function uses LBA48.
0x0025D74C (3.15)
ATA_send_WriteDMAExt_cmd
This function uses LBA48.
0x0025D664 (3.15)
ATA_send_IdentifyDevice_cmd
0x0025D4D8 (3.15)
ATA_send_IdentifyPacketDevice_cmd
0x0025D448 (3.15)
ATA_send_FlushCache_cmd
0x0025D5E8 (3.15)
ATA_send_FlushCacheExt_cmd
0x0025D568 (3.15)
ATA_send_StandbyImmediate_cmd
0x0025D07C (3.15)
ATA_send_SetFeatures_cmd
0x0025D208 (3.15)
ATA_send_SMARTEnable_cmd
0x0025D0F8 (3.15)
ATA_send_SMARTSaveAttributeValue_cmd
0x0025D180 (3.15)
ATA_SetUDMAMode
0x00260EE8 (3.15)
Parameters
r5 - UltraDMA mode (0-5)
Booting a Bootloader from VFLASH
Coming soon !!!
High precision timers
These timers are used e.g. in SATA/ATA/ATAPI driver.
timer_add
0x002C3F2C (3.15)
timer_del
0x002C41AC (3.15)
timer_run_expired
This function is called from HDEC interrupt handler.
0x002C4020 (3.15)
timer_set_HDEC
0x002BCF80 (3.15)
SPE
There are 3 SPE classes.
The HV call lv1_construct_logical_spe can create LogicalSPE, SPEType1 and SPEType2 objects.
The syscall 0x10040 creates only SPEType1 objects.
The SPEType1 and SPEType2 objects cannot be created when isolation mode is disabled. The right most bit of repository node sys.lv1.iso_enbl is checked and when it's not 1 then the SPEType1 and SPEType2 objects cannot be created. In LPAR 1, this check succeedes always. Only in LPARs different from 1, the repository node sys.lv1.iso_enbl is checked.
LogicalSPE
SPE type = 0
Objects of this class are used e.g. on Linux.
vtable
0x00358360 (3.15)
offset 0x20 - pointer to TOC entry of interrupt handler for SPE
Member variables
offset 0x38 - pointer to LPAR obj that owns this SPE obj
offset 0x78 - table of pointers to Outlet objects (3 * 8 bytes, one for each Class 0-2)
offset 0xB0 - pointer to VAS object
offset 0xC8 - pointer to Logical PPE object
offset 0xE0 - SPE id
offset 0x1A0 - pointer to MMIO Memory Region object
offset 0x1A8 - pointer to Shadow Registers Memory Region object
Objects
Here is the list of logical SPE objects i found in HV 3.15:
- 0x003A82E0 - SPE id 0
- 0x003A8660 - SPE id 1
- 0x003ABA00 - SPE id 2
- 0x003B4010 - SPE id 3
- 0x003B4D60 - SPE id 4
- 0x003B5970 - SPE id 5
SPEType1
SPE type = 1
vtable
0x00359750
Member Variables
offset 0x198 - pointer to MMIO Memory Region object
offset 0x1A0 - pointer to Shadow Registers Memory Region object
SPEType2
SPE type = 2
vtable
0x00359790
SPE Register Shadow Area
- HV createas a SPE Register Shadow Area for each contstructed SPE.
- The area is 1 4Kb page of physical memory.
- When SPE state changes then HV updates data in this area.
- The value of shadow_addr that is returned by lv1_construct_logical_spe is a LPAR start address of this area and it cannot be accessed until it's mapped in the HTAB.
- The SPE Register Shadow Area may be mapped only with read-only page protection or else HV call lv1_insert_htab_entry fails. I tested it with PSGroove and could map the whole memory range and read it after i constructed SPE of type 1 with lv1_construct_logical_spe.
- The shadow_addr is also returned by syscall_10040 (that creates SPE of type 1) but it returns already mapped Process address so HV Processes do not have to map it in HTAB.
- When an isoated SPU is done, HV Processes checks the value at offset 0x30 to determine if the SPU execution was successfull or not.
- GameOS checks also the value at offset 0x30 in the SPE Shadow Area.
- When GameOS creates SPE of type 1 then it maps only SPE Register Shadow Area into it's address space.
SPE Register Shadow Area Offsets
0x30 - SPU_Status register value (4 bytes)
0xF10 - ?
0xF18 - ?
Stop Code
- The high-order 16 bit of SPU_Status register value is a Stop Code.
Here is the list of Stop Codes i extracted from HV Processes which read the value at offset 0x30 when SPU is done:
Value | Description |
---|---|
0xA | Success |
0xC | Access Violation (LPAR auth id error) |
0xE | ? |
0xF | Revoked |
0x12 | Invalid Parameter |
0x13 | ? |
0x17 | Invalid Parameter |
0x25 | ? |
SPU_send_MFC_cmd
0x002B09B0 (3.15)
This function programs a MFC.
SPU_write_MFC_cmd_status_reg
0x002AEE70 (3.15)
SPU_write_Sig_Notify1_reg
0x002AEF4C (3.15)
SPU_write_Sig_Notify2_reg
0x002AEF30 (3.15)
SPU_write_Sig_Notify1_and_Notify2
0x002B0A78 (3.15)
SPU_enable_iso_load_request
0x002AEDE0 (3.15)
SPU_iso_load_request
0x002AEED0 (3.15)
SPU_enable_runcntl
0x002AEB24 (3.15)
SPU_stop_request
0x002AEEF0 (3.15)
SPU_run_request
0x002AEF10 (3.15)
SPU_read_status_reg
0x002AE978 (3.15)
SPU_read_Mbox_Stat_reg
0x002AE998 (3.15)
lv1_undocumented_function_62
Updates SLB entry.
Parameters
%r3 - SPE id
%r4 - ? (valid values: 0 - 3)
%r5 - SLB entry index (valid values: 0 - 7)
%r6 - ESID
%r7 - VSID
spe_type1_interrupt_handler
0x0030E238 (3.15)
spe_type2_interrupt_handler
0x003103F8 (3.15)
spe_type3_interrupt_handler
0x002F36F4 (3.15)
Isolation
Loaders Table
- All the binary files needed for isolation and decryption are already stored in HV memory !!!
- They are probably loaded during HV initialization from FLASH.
- The table has 9 entries.
- Each entry is 16 bytes large.
0x00010100 (3.15)
Loaders Table Entry
offset 0x0 - pointer to data in memory
offset 0x8 - size of data
Here are the contents of the Loaders Table from HV 3.15:
Index | Name | Address of Data in HV Dump | Size of Data |
---|---|---|---|
0 | - | 0x0C150000 | 0x1E5CC |
1 | metldr | 0x00011000 | 0xE8D0 |
2 | lv2ldr | 0x00020000 | 0x16DA0 |
3 | isoldr | 0x00055000 | 0x12E44 |
4 | appldr | 0x00037000 | 0x1DAE4 |
5 | EID0 | 0x00068000 | 0x860 |
6 | - | 0x00069010 | 0x8 |
7 | - | 0x00069020 | 0x50 |
8 | - | 0x00069070 | 0x8 |
Methods
get_iso_loaders_tab - 0x002B0B70 (3.15)
iso_loaders_tab_get_entry - 0x002B0CB8 (3.15)
metldr
Loading metldr
- Physical/Virtual memory address of an isolation module that should be loaded by metldr is written into SPU register SPU_In_Mbox. The SPU register SPU_In_Mbox is 32bit, so 64bit memory address is written in 2 steps.
- MFC relocation is turned off by clearing R-bit in SPU register MFC_SR1. By doing this, HV enables real address mode for MFC of SPU.
- On GameOS, it also works with relocation on. You just have to initialize SLB of SPU and insert valid SLB entries.
- Physical/Virtual memory address of metldr is written to SPU registers Sig_Notify1 and Sig_Notify2
- Isolation load request is enabled by writing SPU register SPU_PrivCntl
- Isolation load request is made by writing value 0x3 into SPU register SPU_RunCntl
Methods
SPE_load_request_metldr - 0x002B00A4 (3.15)
lv2ldr
- lv2ldr is used to decrypt lv2_kernel.self
- syscalls 0x10042 and 0x1004A use lv2ldr
- syscall 0x10042 is used by HV Process 3 during LV2 LPAR construction
- syscall 0x1004A uses different parameters as syscall 0x10042
Methods
SPE_load_request_lv2ldr_1 - 0x002AE82C (3.15)
SPE_load_request_lv2ldr_2 - 0x002AE8D8 (3.15)
Loading lv2ldr
- 64 bit memory address of lv2ldr is written into 32 bit SPU register SPU_In_Mbox
- metldr is loaded
isoldr
- isoldr is used for executing isolated SPUs
- syscall 0x10043 and HV call lv1_undocumented_function_209 use isoldr to execute isolated SPUs
- EID0 data is transferred to Local Storage Address 0x3E400 by MFC
- Revoke List For Program is transferred to Local Storage Address 0x3F000 by MFC
Revoke List For Programs
0x00361980 (3.15)
Methods
SPE_load_request_isoldr - 0x002B0394
Loading isoldr
- 64 bit memory address of isoldr is written into 32 bit SPU register SPU_In_Mbox
- metldr is loaded
appldr
- appldr is used for decryption of SELFs
- HV call lv1_authenticate_program_segment loads appldr
Methods
SPE_load_request_appldr - 0x002AE900
Loading appldr
- 64 bit memory address of isoldr is written into 32 bit SPU register SPU_In_Mbox
- metldr is loaded
Decrypting SELFs with appldr and lv1_authenticate_program_segment
- lv1_authenticate_program_segment loads and prepares appldr for SELF decryption.
- When appldr is ready to decrypt data, it sends a message via mailbox.
- The address and the size of the encrypted data is passed to appldr via a shared memory.
Socket
The socket supports only one address family 0x1F, one socket type 0 and one protocol 0.
Socket address
Socket address is called port ID. Valid port IDs are 0-63. Port ID 0 is reserved.
Socket state
2 - LISTEN
Socket table
The socket table contains 64 entries, one for each port ID. Each entry is 16 bytes large.
The socket table is at 0x0035F6E8 (3.15).
Here is the list of opened sockets i found in HV 3.15:
- 0x00091FE0 (port ID 0x23, accepts connections)
- 0x00127850 (port ID 0x24, accepts connections)
- 0x0012F810 (port ID 0x25, accepts connections)
Socket table entry
offset 0x0 - pointer to Socket obj
offset 0x8 - socket accepts connections or not (0 - does not accept, 1 - accepts, 1 byte)
vtable
0x00355DB0 (3.15)
offset 0xB0 - bind
offset 0xB8 - listen
offset 0xC8 - connect
Member variables
offset 0x360 - socket state (4 bytes)
offset 0x368 - port ID (8 bytes)
offset 0x370 - max backlog queue size (8 bytes)
Virtual Address Space
VAS
vtable
0x00357958 (3.15)
Member variables
offset 0x18 - pointer to LPAR that owns this VAS object
offset 0x48 - VAS id (8 bytes)
offset 0x70 - number of page sizes (4 bytes)
offset 0x74 - log2 of HTAB size
offset 0x78 - pointer to HTAB object
Objects
Here is the list of the VAS objects i found in HV dump 3.15:
- 0x001C8050 (VAS id 2, LPAR 1)
- 0x003B4910 (VAS id 3, LPAR 2)
- 0x003BDB50 (VAS id 48, LPAR 2)
HTAB
0x38(-0x69A8(HSPRG0)) - pointer to the currently active HTAB in LPAR
vtable
0x003575B0 (3.15)
Member variables
offset 0x48 - pointer to first PTE
offset 0x60 - LPID (4 bytes)
offset 0x64 - log2 of HTAB size (4 bytes)
Objects
Here is the list of the HTAB objects i found in HV dump 3.15:
- 0x001C8270 (VAS id 2, LPAR 1)
* 0x00180000 - HTAB PTEs (HTAB size 256 kB)
- 0x003A8050 (VAS id 3, LPAR 2)
* 0x00500000 - HTAB PTEs (HTAB size 1 MB)
- 0x003BC510 (VAS id 48, LPAR 2)
* 0x00800000 - HTAB PTEs (HTAB size 1 MB)
LPAR_change_HTAB
This function changes currently active HTAB. It writes to SDR1 register where HTAB address and size is stored.
0x002BE5D4 (3.15)
Process SLB
Each HV process has 16 SLB entries.
Each SLB entry is 16 bytes large and is in format expected by opcode slbmte.
Most of the entries are zero (invalid).
Each process has 4 valid SLB entries: code, data, heap and stack.
Process 3
SLB entries
0x0012D1F0 (3.15)
Name | ESID | VSID |
---|---|---|
code | 0x8 | 0x38 |
data | 0xC | 0x3C |
heap | 0xA | 0x3A |
stack | 0xF | 0x3F |
Process 5
SLB entries
0x00093120 (3.15)
Name | ESID | VSID |
---|---|---|
code | 0x8 | 0x48 |
data | 0xC | 0x4C |
heap | 0xA | 0x4A |
stack | 0xF | 0x4F |
Process 6
SLB entries
0x000E6960 (3.15)
Name | ESID | VSID |
---|---|---|
code | 0x8 | 0x58 |
data | 0xC | 0x5C |
heap | 0xA | 0x5A |
stack | 0xF | 0x5F |
Process 9
SLB entries
0x00763E20 (3.15)
Name | ESID | VSID |
---|---|---|
code | 0x8 | 0x8 |
data | 0xC | 0xC |
heap | 0xA | 0xA |
stack | 0xF | 0xF |
VUART
VUART is a bi-directional communication link. A VUART object has a peer VUART object.
Data written to a VUART object is stored NOT in the data buffer of the VUART object but in the data buffer of the peer VUART object.
VUART table
Every LPAR has a VUART table. A VUART table has 256 entries. Each entry is a pointer to a VUART object that implements VUART interface.
0x00677218 (3.15) - address of VUART table of LPAR 1
Here is the list of all VUART objects in LPAR 1 i found in HV 3.15:
- 0x006ABD90 - VUART 0
- 0x006ABEB0 - VUART 1
- 0x006A3CB0 - VUART 2
- 0x006A3DD0 - VUART 3
- 0x000A3410 - VUART 5
- 0x000A3250 - VUART 6
VUART [0-3] are used by /dev/sc[0-3] respectively.
VUART [0-3] are linked to VUART objects of different type i could not yet identify. These unknown VUART objects use eieio opcode a lot. So i think, they communicate with hardware peripheral.
A write/read to/from /dev/sc[0-3] is a write/read to/from VUART.
0x00762AA8 (3.15) - address of VUART table of LPAR 2
Here is the list of all VUART objects in LPAR 2 i found in HV 3.15:
- 0x00126660 - VUART 0
- 0x000A3010 - VUART 2
VUART 0 and VUART 2 of LPAR 2 are created by Process 9 during LPAR construction.
VUART class
Member variables
offset 0x48 - pointer to peer VUART object
offset 0x58 - write pointer into data ring buffer
offset 0x60 - read pointer into data ring buffer
offset 0x68 - pointer to data ring buffer
offset 0x70 - size of data ring buffer (8 bytes)
offset 0x78 - size of data stored in data ring buffer currently (8 bytes)
offset 0x88 - tx trigger (8 bytes)
offset 0x90 - rx trigger (8 bytes)
offset 0x98 - interrupt mask (8 bytes)
offset 0xA8 - port number (4 bytes)
Methods
pmpi_read_virtual_uart(port, buf, size, nread) - 0x002EB30C (3.15)
pmpi_write_virtual_uart(port, buf, size, nwritten) - 0x002EB0EC (3.15)
VUART_read(pointer to VUART object, buf, size, nread) - 0x002E8654 (3.15)
VUART_write(pointer to VUART object, buf, size, nwritten) - 0x002E8428 (3.15)
Guest OS VUART 0 (AV Manager)
All data sent to VUART 0 in LPAR 2 is written into the data buffer of VUART 5 of LPAR 1.
VUART 5 of LPAR 1 is accessed by Process 9 in LPAR 1 through the file /proc/partitions/2/vuart/0.
- Process 9 of LPAR 1 uses RSX syscalls to access RSX driver and memory mapped device access (/dev/ioif0).
Guest OS VUART 2 (System Manager)
All data sent to VUART 2 in LPAR 2 is written into the data buffer of VUART 6 of LPAR 1.
VUART 6 of LPAR 1 is accessed by Process 9 in LPAR 1 through the file /proc/partitions/2/vuart/2.
- System manager supports 62 (0-61) service ids.
- Process 9 has a SID table. SID table has 62 entries.
- Each entry is a pointer to a function responsible for processing SID packets.
A/V Manager
- A/V Manager is running in Process 9 of HV.
- It communicates with Guest OS through /proc/partitions/0/vuart/0 file.
- GameOS accesses A/V Manager through syscalls 367 - 370.
- PS2 Soft EMU accesses A/V Manager also.
System Manager (SM)
- System Manager (SM) is running in Process 9 of HV.
- It communicates with Guest OS through /proc/partitions/2/vuart/2 file.
- GameOS accesses SM through syscalls 372 - 415
System Manager class
Member variables
offset 0x10 - LPAR state (8 bytes)
offset 0x68 - LPAR auth id
offset 0x70 - LPAR name
offset 0x90 - LPAR image path
offset 0x1C0 - LPAR ability (8 bytes)
Types of System Manager
- There are 6 different SM types
- When Process 9 starts it reads profile file, by default DEFAULT.SPP, by sending requests to SPL (Secure Profile Loader) and constructs System Managers listed in this profile file.
- So, the profile file controls which System Manager types are available later.
Name | LPAR name |
---|---|
SCE_CELLOS_PME | - |
SCE_CELLOS_SYSTEM_MGR | PS3_LPAR |
SCE_CELLOS_SYSTEM_MGR_PS2 | PS2_LPAR |
SCE_CELLOS_SYSTEM_MGR_PS2_SW | PS2_SW_LPAR |
SCE_CELLOS_SYSTEM_MGR_PS2_GX | PS2_GX_LPAR |
SCE_CELLOS_SYSTEM_MGR_LINUX | LINUX_LPAR |
Ability Bitmask
Index | Name | Ability Bitmask (Hex) | Ability Bitmask (Binary) |
---|---|---|---|
0 | SCE_CELLOS_PME | 0x1 | 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 |
1 | SCE_CELLOS_SYSTEM_MGR | 0x3BF7EF | 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0011 1011 1111 0111 1110 1111 |
2 | SCE_CELLOS_SYSTEM_MGR_PS2_SW | 0x1226D | 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0010 0010 0110 1101 |
3 | SCE_CELLOS_SYSTEM_MGR_LINUX | 0x40012 | 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 0000 0000 0001 0010 |
Bit Position (from right) | SID | Description |
---|---|---|
1 | 5 (SET_NEXT_OP) | Shutdown or Reboot LPAR |
2 | 5 (SET_NEXT_OP) | Boot PS3 LPAR |
3 | 5 (SET_NEXT_OP) | Boot PS2_SW LPAR |
4 | 5 (SET_NEXT_OP) | Boot LINUX LPAR |
5 | 12 (CONTROL_LED) | Control LED |
6 | 21 (RING_BUZZER) | Ring Buzzer |
7 | 19 (SET_CONFIG) | Set Config |
9 | 25 / 50 (FAN_POLICY) | Fan Policy |
10 | 26 (REQUEST_ERROR_LOG) | Request Error Log |
10 | 28 (REQUEST_BE_COUNT) | Request BE Count |
10 | 32 (REQUEST_SYSTEM_EVENT_LOG) | Request System Event Log |
12 | 30 (REQUEST_SC_VERSION) | Request SC Version |
14 | 39 (SET_SHOP_DEMO_MODE) | Set Shop Demo Mode |
Service ID (SID)
SM supports 62 (0-61) SIDs.
The value of SM member variable ability controls which SIDs may be used by LPAR.
SID | Name | Description |
---|---|---|
0 | - | - |
1 | REQUEST | - |
2 | RESPONSE | - |
3 | COMMAND | - |
4 | EXTERN_EVENT | - |
5 | SET_NEXT_OP | - |
6 | - | - |
7 | - | - |
8 | SET_ATTR | - |
9 | GET_INTER_LPAR_PARAM | - |
10 | SET_INTER_LPAR_PARAM | - |
11 | - | - |
12 | CONTROL_LED | - |
13 | TEMPERATURE | - |
14 | - | - |
15 | Shares data with 25 | - |
16 | - | - |
17 | - | - |
18 | - | - |
19 | SET_CONFIG | - |
20 | - | - |
21 | RING_BUZZER | - |
22 | - | - |
23 | - | - |
24 | - | - |
25 | FAN_POLICY | - |
26 | REQUEST_ERROR_LOG | - |
27 | - | - |
28 | REQUEST_BE_COUNT | - |
29 | - | - |
30 | REQUEST_SC_VERSION | - |
31 | - | - |
32 | REQUEST_SYSTEM_EVENT_LOG | - |
33 | - | - |
34 | RTC_ALARM | - |
35 | - | - |
36 | RTC_ALARM | - |
37 | - | - |
38 | RTC_ALARM | - |
39 | SET_SHOP_DEMO_MODE | - |
40 | BOOT_PARAMETER | - |
41 | - | - |
42 | BOOT_PARAMETER | - |
43 | - | - |
44 | FACTORY_PROCESS_COMP | - |
45 | - | - |
46 | FACTORY_PROCESS_COMP | - |
47 | - | - |
48 | FACTORY_PROCESS_COMP | - |
49 | - | - |
50 | FAN_POLICY | - |
51 | - | - |
52 | - | - |
53 | - | - |
54 | - | - |
55 | - | - |
56 | - | - |
57 | - | - |
58 | - | - |
59 | - | - |
60 | - | - |
61 | - | - |
12 - CONTROL_LED
- I have tested this service with PSGroove and GameOS is allowed to use it.
- GameOS syscall 386 uses this service.
Packet Body
struct sysmgr_ctrl_led { u8 field0; u8 field1; u8 field2; u8 res1; u8 field4; u8 field5; u8 res2[10]; };
Parameters
I have tested the following parameters with this service:
field0 | field1 | field2 | field4 | field5 | Description |
---|---|---|---|---|---|
0x1 | 0x0 | 0xFF | 0xFF | 0xFF | Turns off the power button LED |
0x1 | 0x1 | 0xFF | 0xFF | 0xFF | Turns on the power button LED |
21 - RING_BUZZER
- I have tested this service with PSGroove and GameOS is allowed to use it
Packet Body
struct sysmgr_ring_buzzer { u8 res1; u8 field1; u8 field2; u8 res2; u32 field4; };
Parameters
I have tested the following parameters with this service:
field1 | field2 | field4 | Description |
---|---|---|---|
0x29 | 0x4 | 0x6 | Makes a short single beep |
0x29 | 0xA | 0x1B6 | Makes a double beep |
0x29 | 0x7 | 0x36 | - |
0x29 | 0xA | 0xFFF | Makes a continuous beep |
Active System Managers in HV dump 3.15
There are 4 active SMs in HV dump.
Index | Name | LPAR auth id | LPAR image pathname | Ability Bitmask (Hex) |
---|---|---|---|---|
0 | SCE_CELLOS_PME | 0x1070000001000001 | /flh/os/this_is_dummy | 0x1 |
1 | SCE_CELLOS_SYSTEM_MGR | 0x1070000002000001 | /flh/os/lv2_kernel.self | 0x3BF7EF |
2 | SCE_CELLOS_SYSTEM_MGR_PS2_SW | 0x1020000003000001 | /local_sys0/ps2emu/ps2_softemu.self | 0x1226D |
3 | SCE_CELLOS_SYSTEM_MGR_LINUX | 0x1080000004000001 | /flh/lx/linux | 0x40012 |
- GameOS file image lv2_kernel.self is stored on /dev/rflash1
- Linux file image is stored on /dev/rflash_1x or /dev/rflash_1xp
Booting Linux LPAR through System Manager
To boot Linux LPAR from GameOS when Linux support was not removed (Ability Mask of PS3 System Manager needs patching !!!):
- Send SID packet SET_NEXT_OP with operation OP_LPAR_REBOOT and the index of Linux system manager to System Manager (VUART 2)
- Send SID packet REQUEST with type SHUTDOWN to System Manager (VUART 2)
- Execute lv1_panic HV call in GameOS
It should also work when Linux support was removed but Linux system manager was not removed from Process 9 and also assumed that a Linux kernel image is stored at the right place in /dev/rflash_1x.
It's just a theory, nothing else, that i gathered during HV reversing. It needs a practical proof. Unfortunately, i don't have access to Hypervisor.
Booting modified and reencrypted lv2_kernel.self
- The System Manager of GameOS sends the path to lv2_kernel.self to SLL (Secure LPAR Loader) and SLL loads it from FLASH device file /dev/rflash1
- I stored a new lv2_kernel.self on FLASH directly by writing FLASH from GameOS. It't risky but if you know what you are doing then it's safe. I warned you guys. You could brick your PS3.
- Then i added a new TOC entry to FLASH device which points to the new lv2_kernel.self
- I patched the path to lv2_kernel.self in the System Manager of GameOS so it points to my new GameOS kernel (You need HV rights to do it)
- Then i rebooted GameOS without rebooting HV, so the patched file path should not change
- This method has the advantage that when the new lv2_kernel.self won't work you can just reboot HV and it will load the original lv2_kernel.self again
- lv2_kernel.self can be also loaded from GameOS dev_flash. For that, you have to change the path to lv2_kernel.self in default.spp from /flh/os/lv2_kernel.self to /local_sys0/lv2_kernel.self and store lv2_kernel.self on dev_flash.
AV Manager
All data sent to VUART 0 in LPAR 2 is written into the data buffer of VUART 5 of LPAR 1.
VUART 5 of LPAR 1 is accessed by Process 9 in LPAR 1 through the file /proc/partitions/2/vuart/0.
- During initialization, AV Manager opens /dev/ioif0 device and maps different address ranges of the device into address space of Process 9
- /dev/ioif0 is NOT opened and mapped if the value of repository node lv1.rsx.enable is less than 1
- /dev/ioif0 is mapped with READ/WRITE protection
- File descriptor of /dev/ioif0 in Process 9 is 4
- AV Manager supports a lot more commands than used on Linux
- Every command is implemented by a class
Mapped Address Ranges From /dev/ioif0
The base address of /dev/ioif0 is 0x28000000000. The device supports only mmap system call, it cannot be read or written. It also doesn't support ioctl.
Index | Absolute Address Range | Size | Mapped Address in Process 9 Address Space |
---|---|---|---|
0 | 0x28000000000 - 0x28000002000 | 0x2000 | 0xA0019000 |
1 | 0x28001800000 - 0x28001801000 | 0x1000 | 0xA0004000 |
2 | 0x28000600000 - 0x28000604000 | 0x4000 | 0xA001A000 |
3 | 0x28000680000 - 0x28000684000 | 0x4000 | 0xA0006000 |
4 | 0x28000080000 - 0x28000088000 | 0x8000 | 0xA000A000 |
5 | 0x28000088000 - 0x28000089000 | 0x1000 | 0xA000E000 |
6 | 0x2800000C000 - 0x2800000D000 | 0x1000 | 0xA0016000 |
7 | 0x2800008A000 - 0x2800008B000 | 0x1000 | 0xA0017000 |
8 | 0x2800008C000 - 0x2800008D000 | 0x1000 | 0xA0018000 |
Process socket services
Function ID and Packet ID
- Processes 3, 5 and 6 provide services (functions) to other Processes through sockets (something like RPC).
- A service is identified by a function ID.
- Each process has a hash table which maps a function ID to socket port ID.
- Services (functions) can be further differentiated by a packet ID.
- To request a service, a Process sends a packet with specified function and packet ID to the Process that provides the service.
- A process that provides a service (function) has a table of objects which handle different packet IDs.
- Services are synchronous, a client sends a request and waits for a response.
- If a Process requests a service that is located in the same Process then the service is called directly and sockets are not used !!! (e.g. SLL requests from DM creating VUART port during GameOS loading, SLL and DM are in the same Process, so SLL calls DM directly)
Port ID - Process ID mapping
Port ID | Process ID |
---|---|
0x23 | 6 |
0x24 | 5 |
0x25 | 3 |
Function ID - Port ID mapping
Function ID | Port ID | Supported Packet IDs | Function Description |
---|---|---|---|
0x2000 | 0x23 | 0x2001 - 0x2017 | Virtual TRM Manager |
0x3000 | 0x24 | 0x3001 - 0x3003 | Secure RTC |
0x5000 | 0x23 | 0x5001 - 0x500A | Storage Manager |
0x6000 | 0x23 | 0x6001 - 0x6011 | Update Manager |
0x9000 | 0x24 | 0x9001 - 0x9016 | SC Manager |
0x10000 | 0x23 | - | - |
0x11000 | 0x25 | 0x11001 - 0x11002 | SPM (Security Policy Manager) |
0x14000 | 0x25 | 0x14004 - 0x14005 | SLL (Secure LPAR Loader) |
0x15000 | 0x24 | 0x15001, 0x15003, 0x15009 | SPL (Secure Profile Loader) |
0x17000 | 0x24 | 0x17001 - 0x17017 | Indi Info Manager |
0x18000 | 0x25 | 0x18001, 0x18002, 0x18004 | Dispatcher Manager |
0x19000 | 0x24 | 0x19002 - 0x19005 | AIM |
0x24000 | 0x23 | 0x24001 - 0x24002 | USB Dongle Authenticator |
0x25000 | 0x23 | 0x25001 - 0x25002 | User Token Manager |
SS Packet
- SS means Secure Service ?
- Processes send SS Packets to request a service or to reply to a service request.
Member variables
offset 0x8 - packet ID (8 bytes)
offset 0x10 - function ID (8 bytes)
offset 0x18 - return value (4 bytes)
offset 0x20 - subject ID (2 * 8 bytes)
Header
- All services use a common header.
- The header of a SS Packet is 0x28 bytes large.
struct ss_header { uint64_t packet_id; uint64_t function_id; uint32_t retval; uint8_t res[4]; uint64_t laid; /* LPAR authority id */ uint64_t paid; /* Program authority id */ }
SS Service Return Values
Error Code | Description |
---|---|
0x00000000 | Success |
0x00000005 | Access Violation |
0x00000006 | No Entry ? |
0x00000009 | Invalid Parameter |
0x0000000F | ? |
Body
- The body of a SS Packet follows after the header.
- The size of the body depends on a used service.
0x2000 - Virtual TRM Manager
Packet ID | Description |
---|---|
0x2001 | Init |
0x2002 | Status |
0x2003 | Store |
0x2004 | Store |
0x2005 | Retrieve |
0x2006 | Free |
0x200A | Encrypt |
0x200B | Decrypt |
0x200C | Encrypt With Portability |
0x200D | Decrypt With Portability |
0x200E | Decrypt Master |
0x2012 | Backup Flash |
0x2013 | Restore Flash |
0x2014 | Backup SRK SRH |
0x2015 | Restore SRK SRH |
0x2016 | Flash Address Size |
0x2017 | Force Restart |
0x200E - Decrypt Master
- This service is e.g. used in Process 6 by USB Dongle Authenticator to decrypt USB Dongle Master Key
- GameOS uses this service e.g. in syscall SYS_SS_AD_SIGN
- syscall 862 uses Virtual TRM Manager services.
0x3000 - Secure RTC
Packet ID | Description |
---|---|
0x3001 | Set RTC |
0x3002 | Get Time |
0x3003 | Set Time |
- Secure RTC reads LAIDs and PAIDs that are allowed to access Secure RTC service from DEFAULT.SPP segment SCE_CELLOS_SS_SECURE_RTC.
0x3001 - Set RTC
- This service uses SC Manager Set RTC (0x9008) service.
0x3002 - Get Time
- This service uses SC Manager Get Time (0x9009) service.
0x3003 - Set Time
- This service uses SC Manager Set Time (0x900A) service.
0x5000 - Storage Manager
Packet ID | Description |
---|---|
0x5001 | Set Encdec Key |
0x5002 | Set/Delete ATA (Encdec) Key |
0x5003 | Get Random Number |
0x5004 | Authenticate BD Drive |
0x5005 | Authenticate PS2 Disc |
0x5006 | Get Secure Firmware Version |
0x5007 | HW disc auth emu |
0x5008 | HW mc |
0x5009 | HW me auth header |
0x500A | HW me dec block |
- Storage Manager service is used e.g. by syscall 864 and syscall SYS_SS_MEDIA_ID
- GameOS's VSH uses syscall 864
- Storage Manager executes SPU module sb_iso_spu_module.self
- Storage Manager communicates with devices /dev/encdec0 and /dev/rbd0 from LPAR 1
- 2nd value from repository node bus1.id is used by Storage Manager
- Storage Manager communicates with sb_iso_spu_module.self through a shared DMA memory buffer and SPU MBox
- EID4 data is passed to sb_iso_spu_module.self module.
SB Isolation DMA Buffer Header
struct sb_iso_header { u32 seqno; u32 mbmsg; u32 cmd; u32 cmd_size; u8 cmd_data[0]; }
0x5001 - Set Encdec Key
- This service allows you to set ENCDEC keys with index 0xC - 0xF
- By patching HV process 6 it would be possible to set default ENCDEC key (used for HDD encryption) to a value different from the default one !!! It means we could encrypt our HDDs with a key we want !!!
- The service accepts 2 parameters: a key (max 24 bytes) and a key length (in bits)
- Valid key length values: 0x40, 0x80 and 0xC0
- The service returns the ENCDEC key index used for the key
- ENCDEC supports upto 16 keys !!!
- Storage Manager in HV process 6 has a bit mask of size 2 bytes which indicates which keys are used currently.
Per default, keys with index 0x0 - 0xB are not free. But we could patch it also.
0x5002 - Set/Delete ATA (Encdec) Key
- Sets/Deletes ATA (Encdec) Key
- The service has only one parameter of size 8 bytes: 0x100 - Set ATA Key and 0x110 - Delete ATA Key.
- This service is used e.g. by System Manager in HV Process 9 during LPAR booting.
- SPM doesn't allow GameOS to use this service.
- 3 possible key lengths: 0x40, 0x80 and 0xC0
- This service communicates with /dev/encdec0 device.
- The service uses ENCDEC device commands EdecKgen1 (0x81), EdecKgen2 (0x82), EdecKset (0x83) and EdecKgenFlash (0x84).
- This service communicates also with /dev/rbd0 device.
- I guess that the ATA key is stored encrypted in EID4 data.
- This service is used by LPAR Manager in HV Process 9 during LPAR 2 loading.
- I tested this service on Linux with ps3dm-utils and after deleting ATA key the sectors on VFLASH or HDD were NOT decrypted by HV
- After setting ATA key again, the sectors were encrypted/decrypted by HV again
Service Parameter Table
Service Parameter | Description |
---|---|
0xC - 0xF | Delete Encdec Key |
0x10* | Set ATA Key (index 1) |
0x11* | Delete ATA Key (index 1) |
0x5003 - Get Random Number
- I have got access to Get Random Number service through DM and tested it with PSGroove
- The service returns 192-bit random numbers
- It has no input parameters except those in SS packet header
- Storage Manager communicates with device /dev/encdec0.
- This service is used e.g. by USB Dongle Authenticator to generate the body of a challenge or by GameOS to generate hardware random numbers.
0x5004 - Authenticate BD Drive
- Used by LPAR Manager in HV Process 9 during LPAR 2 loading and unloading.
- Used by SLL Load GOS service (0x14004) in HV Process 3 during PS2EMU loading and by SLL Unload GOS service (0x14005) during PS2EMU unloading.
- The service expects one additional parameter.
- The service is used during loading of LPAR 2 to authenticate BD drive and during unloading LPAR 2 to reset BD drive.
- The service uses isolated SPU module sv_iso_spu_module.self for BD drive authentication.
- The service communicates with LPAR 1 device /dev/rbd0 through ATAPI interface.
Service Parameter Table
Service Parameter | Description |
---|---|
0x02 | Used by SLL service 0x14004 during PS2EMU loading |
0x1E | Used by SLL service 0x14005 during PS2EMU unloading |
0x29 | Reset BD Drive |
0x46 | Authenticate BD Drive |
0x5007 - Control BD Drive
- Used by GameOS to authenticate discs and for BD emulation.
Service Parameter Table
Service Parameter | Description |
---|---|
0x41 | - |
0x46 | - |
0x51 | - |
0x52 | - |
0x53 | - |
0xA3 | BD emu |
0xA5 | BD emu |
0xA7 | BD emu |
0xAA | BD emu |
0x6000 - Update Manager
Packet ID | Description |
---|---|
0x6001 | Update Package Tophalf |
0x6002 | Inspect Package Tophalf |
0x6003 | Get Package Info |
0x6004 | Get Fix Instruction |
0x6005 | Extract Package Tophalf |
0x6006 | Get Extract Package |
0x6009 | Get Token Seed |
0x600A | Set Token |
0x600B | Read EPROM |
0x600C | Write EPROM |
0x6010 | Check Integrity |
0x6011 | Get Applicable Version |
- Update Manager service is accessed by GameOS syscall 863
0x6001 - Update Package Tophalf
- The result of the request can be checked by reading the value of repository node ss.update.request.<Request ID> periodically
0x6002 - Inspect Package Tophalf
- I have got access to this service through DM and tested it with PSGroove
- This service can tell you if a package can be installed or not, the service just checks a package but does not install it
- Packages can be updated without GameOS !!! I'm using only HV calls and communicate directly with Dispatcher Manager and Update Manager
- I just sent a whole SCE package to GameOS through network, created a LPAR memory region and stored the file there
- It expects a SCE package that can be easily extracted from PUP file
- The data of SCE package can be passed either in SS packet itself or through LPAR memory of requester
- When the data of SCE package is too large for SS packet (SS packets are sent through DM, GameOS and DM communicate through VUART that has only 0x800 bytes buffer) then the data of SCE package has to be passed through GameOS LPAR memory. The requester sends a vector of LPAR memory addresses where the data of SCE package is stored and Update Manager maps it into the address space of Process 6
- E.g. Revoke List packages can be sent in SS packets because they are small (about 0x200 bytes). All other packages are too big to sent them in SS packets
- The service is actually split into 2 halfs: Top-Half and Bottom-Half
- The Top-Half is executed synchronously with service request and it sends a reply to the requester
- In the reply sent by Top-Half a Request ID (8 bytes) is returned to the requester
- Request ID is calculated by using SHA-1
- After the Top-Half is done, a reply is sent to the requester but the service just checked some input parameter upto now and the passed SCE package was not really checked yet
- The Bottom-Half is called asynchronously to the request, it does the real job, it checks the passed SCE package.
- The result of the request can be checked by reading the value of repository node ss.inspect.request.<Request ID> periodically
- I successfully tested this service with RL_FOR_PROGRAM.img from 3.50 PUP file and the service returned Success, so theoretically i could install this package on my PS3. But of course i want to downgrade and NOT to upgrade.
Inspect Package Tophalf Return Values
Error Code | Description |
---|---|
0x00000000 | Success |
0x00000013 | Same Version/Older Version |
0x00000014 | - |
0x6003 - Get Package Info
- I have got access to this service through DM and tested it with PSGroove
- The service expects one additional parameter: package type (valid values are 1-9)
- The service returns the version (8 bytes) of a package type installed
Here are the versions of packages installed on my PS3:
Package Type | Returned Version | Description | Package Name in PUP File |
---|---|---|---|
1 | 0x0003004100000000 | Core OS Package | CORE_OS_PACKAGE.pkg |
2 | 0x0003004100000000 | Revoke List Package for Program | RL_FOR_PROGRAM.img |
3 | 0x0002003000000000 | Revoke List Package for Package | RL_FOR_PACKAGE.img |
4 | 0xDEADBEAFFACEBABE | - | - |
5 | 0xDEADBEAFFACEBABE | - | - |
6 | 0x0003004000000000 | BD Firmware Package | BDIT_FIRMWARE_PACKAGE.pkg, BDPT_FIRMWARE_PACKAGE_*.pkg |
7 | Invalid Parameter | Bluetooth Firmware, dev_flash tarballs | BLUETOOTH_FIRMWARE.pkg, dev_flash, dev_flash3 |
8 | Invalid Parameter | - | - |
9 | Invalid Parameter | SC Firmware Package | SYS_CON_FIRMWARE_*.pkg |
Decrypting and Extracting Packages with spu_pkg_rvk_verifier.self
- I have managed to decrypt and extract Revoke List Packages 3.41 and 3.50 by using SPE HV calls and spu_pkg_rvk_verifier.self
- Important: Parameters to SPU module shuold be aligned, i used cache line alignment, don't know exactly alignment requerements. Or else some very strange things could happen. E.g SYSCON firmware was only partially decrypted when i used no cache line alignment.
- I have also managed to decrypt and extract Core OS Packages 1.10, 1.18 Debug, 2.40, 2.80, 3.15, 3.41 and 3.50 by using SPE HV calls and spu_pkg_rvk_verifier.self but it's compressed with zlib.Update Manager in Process 6 from 3.15 uses zlib 1.2.3 inflate to decompress it after it was decrypted and then it stores the data to flash memory.
- I decompressed the decrypted Core OS Packages with zlib.
- I am able now to decrypt and decompress all Core OS Packages
- The decrypted and decompressed package CORE_OS_PACKAGE.pkg looks exactly like it's stored on flash.
- I also decrypted BD Firmwares BDIT_FIRMWARE_PACKAGE.pkg and BDPT_FIRMWARE_PACKAGE.pkg successfully. The firmware is not compressed.
- I also decrypted Bluetooth Firmware BLUETOOTH_FIRMWARE.pkg successfully. The firmware is encrypted and compressed.
- I also managed to decrypt System Controller Firmware SYS_CON_FIRMWARE_01050101.pkg from 3.41.
- Core OS Package 3.50 contains a new isolated SPU module that is not contained in older versions. The SPU module is manu_info_spu_module.self.
- Here links to PS3 Firmwares: [1] and [2]
RL_FOR_PROGRAM.img 3.41
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000200 00 00 00 04 00 00 00 01 00 03 00 41 00 00 00 00 ...........A.... 00000210 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000220 00 00 00 03 00 00 00 01 00 03 00 41 00 00 00 00 ...........A.... 00000230 00 00 00 00 00 00 00 02 FF FF FF FF FF FF FF FF ........ÿÿÿÿÿÿÿÿ 00000240 00 00 00 04 00 00 00 01 00 03 00 41 00 00 00 00 ...........A.... 00000250 10 70 00 05 FF 00 00 01 FF FF FF FF FF FF FF FF .p..ÿ...ÿÿÿÿÿÿÿÿ 00000260 00 00 00 04 00 00 00 01 00 03 00 41 00 00 00 00 ...........A.... 00000270 10 70 00 05 FE 00 00 01 FF FF FF FF FF FF FF FF .p..þ...ÿÿÿÿÿÿÿÿ 00000280 00 00 00 04 00 00 00 01 00 03 00 41 00 00 00 00 ...........A.... 00000290 10 70 00 05 FD 00 00 01 FF FF FF FF FF FF FF FF .p..ý...ÿÿÿÿÿÿÿÿ 000002A0 00 00 00 04 00 00 00 01 00 03 00 41 00 00 00 00 ...........A.... 000002B0 10 70 00 05 FC 00 00 01 FF FF FF FF FF FF FF FF .p..ü...ÿÿÿÿÿÿÿÿ 000002C0 00 00 00 04 00 00 00 03 00 01 00 00 00 00 00 00 ................ 000002D0 10 70 00 04 00 00 00 01 FF FF FF FF FF FF FF FF .p......ÿÿÿÿÿÿÿÿ
RL_FOR_PROGRAM.img 3.50
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000200 00 00 00 04 00 00 00 01 00 03 00 50 00 00 00 00 ...........P.... 00000210 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000220 00 00 00 03 00 00 00 01 00 03 00 50 00 00 00 00 ...........P.... 00000230 00 00 00 00 00 00 00 02 FF FF FF FF FF FF FF FF ........ÿÿÿÿÿÿÿÿ 00000240 00 00 00 04 00 00 00 01 00 03 00 50 00 00 00 00 ...........P.... 00000250 10 70 00 05 FF 00 00 01 FF FF FF FF FF FF FF FF .p..ÿ...ÿÿÿÿÿÿÿÿ 00000260 00 00 00 04 00 00 00 01 00 03 00 50 00 00 00 00 ...........P.... 00000270 10 70 00 05 FE 00 00 01 FF FF FF FF FF FF FF FF .p..þ...ÿÿÿÿÿÿÿÿ 00000280 00 00 00 04 00 00 00 01 00 03 00 50 00 00 00 00 ...........P.... 00000290 10 70 00 05 FD 00 00 01 FF FF FF FF FF FF FF FF .p..ý...ÿÿÿÿÿÿÿÿ 000002A0 00 00 00 04 00 00 00 01 00 03 00 50 00 00 00 00 ...........P.... 000002B0 10 70 00 05 FC 00 00 01 FF FF FF FF FF FF FF FF .p..ü...ÿÿÿÿÿÿÿÿ 000002C0 00 00 00 04 00 00 00 03 00 01 00 00 00 00 00 00 ................ 000002D0 10 70 00 04 00 00 00 01 FF FF FF FF FF FF FF FF .p......ÿÿÿÿÿÿÿÿ
RL_FOR_PACKAGE.img 3.41
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000200 00 00 00 03 00 00 00 02 00 01 00 00 00 00 00 00 ................ 00000210 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000220 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 02 ................ 00000230 00 00 00 08 00 05 00 00 00 00 00 00 00 00 00 00 ................
RL_FOR_PACKAGE.img 3.50
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000200 00 00 00 03 00 00 00 02 00 01 00 00 00 00 00 00 ................ 00000210 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000220 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 02 ................ 00000230 00 00 00 08 00 05 00 00 00 00 00 00 00 00 00 00 ................
CORE_OS_PACKAGE.pkg 3.15
Here is a piece of data from decrypted and decompressed package.
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 00 00 00 01 00 00 00 17 00 00 00 00 00 6F FF E0 .............oÿà 00000010 00 00 00 00 00 00 04 60 00 00 00 00 00 04 00 00 .......`........ 00000020 63 72 65 73 65 72 76 65 64 5F 30 00 00 00 00 00 creserved_0..... 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000040 00 00 00 00 00 04 04 60 00 00 00 00 00 00 00 08 .......`........ 00000050 73 64 6B 5F 76 65 72 73 69 6F 6E 00 00 00 00 00 sdk_version..... 00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000070 00 00 00 00 00 04 04 80 00 00 00 00 00 01 E5 CC .......€......åÌ 00000080 6C 76 31 6C 64 72 00 00 00 00 00 00 00 00 00 00 lv1ldr.......... 00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000A0 00 00 00 00 00 05 EA 80 00 00 00 00 00 01 6D A0 ......ê€......m 000000B0 6C 76 32 6C 64 72 00 00 00 00 00 00 00 00 00 00 lv2ldr.......... 000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000D0 00 00 00 00 00 07 58 80 00 00 00 00 00 01 2E 44 ......X€.......D 000000E0 69 73 6F 6C 64 72 00 00 00 00 00 00 00 00 00 00 isoldr.......... 000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000100 00 00 00 00 00 08 87 00 00 00 00 00 00 01 DA E4 ......‡.......Úä 00000110 61 70 70 6C 64 72 00 00 00 00 00 00 00 00 00 00 appldr.......... 00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000130 00 00 00 00 00 0A 61 E4 00 00 00 00 00 00 FA CC ......aä......úÌ 00000140 73 70 75 5F 70 6B 67 5F 72 76 6B 5F 76 65 72 69 spu_pkg_rvk_veri 00000150 66 69 65 72 2E 73 65 6C 66 00 00 00 00 00 00 00 fier.self....... 00000160 00 00 00 00 00 0B 5C B0 00 00 00 00 00 00 5C 94 ......\°......\” 00000170 73 70 75 5F 74 6F 6B 65 6E 5F 70 72 6F 63 65 73 spu_token_proces 00000180 73 6F 72 2E 73 65 6C 66 00 00 00 00 00 00 00 00 sor.self........ 00000190 00 00 00 00 00 0B B9 44 00 00 00 00 00 00 65 D0 ......¹D......eÐ 000001A0 73 70 75 5F 75 74 6F 6B 65 6E 5F 70 72 6F 63 65 spu_utoken_proce 000001B0 73 73 6F 72 2E 73 65 6C 66 00 00 00 00 00 00 00 ssor.self....... 000001C0 00 00 00 00 00 0C 1F 14 00 00 00 00 00 01 53 2C ..............S, 000001D0 73 63 5F 69 73 6F 2E 73 65 6C 66 00 00 00 00 00 sc_iso.self..... 000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001F0 00 00 00 00 00 0D 72 40 00 00 00 00 00 00 44 98 [email protected]˜ 00000200 61 69 6D 5F 73 70 75 5F 6D 6F 64 75 6C 65 2E 73 aim_spu_module.s 00000210 65 6C 66 00 00 00 00 00 00 00 00 00 00 00 00 00 elf............. 00000220 00 00 00 00 00 0D B6 D8 00 00 00 00 00 00 D7 F0 ......¶Ø......×ð 00000230 73 70 70 5F 76 65 72 69 66 69 65 72 2E 73 65 6C spp_verifier.sel 00000240 66 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f............... 00000250 00 00 00 00 00 0E 8E C8 00 00 00 00 00 00 80 8C ......ŽÈ......€Œ 00000260 6D 63 5F 69 73 6F 5F 73 70 75 5F 6D 6F 64 75 6C mc_iso_spu_modul 00000270 65 2E 73 65 6C 66 00 00 00 00 00 00 00 00 00 00 e.self.......... 00000280 00 00 00 00 00 0F 0F 54 00 00 00 00 00 00 88 B8 .......T......ˆ¸ 00000290 6D 65 5F 69 73 6F 5F 73 70 75 5F 6D 6F 64 75 6C me_iso_spu_modul 000002A0 65 2E 73 65 6C 66 00 00 00 00 00 00 00 00 00 00 e.self.......... 000002B0 00 00 00 00 00 0F 98 0C 00 00 00 00 00 00 C0 78 ......˜.......Àx 000002C0 73 76 5F 69 73 6F 5F 73 70 75 5F 6D 6F 64 75 6C sv_iso_spu_modul 000002D0 65 2E 73 65 6C 66 00 00 00 00 00 00 00 00 00 00 e.self.......... 000002E0 00 00 00 00 00 10 58 84 00 00 00 00 00 00 5D B0 ......X„......]° 000002F0 73 62 5F 69 73 6F 5F 73 70 75 5F 6D 6F 64 75 6C sb_iso_spu_modul 00000300 65 2E 73 65 6C 66 00 00 00 00 00 00 00 00 00 00 e.self.......... 00000310 00 00 00 00 00 10 B6 34 00 00 00 00 00 00 22 A0 ......¶4......" 00000320 64 65 66 61 75 6C 74 2E 73 70 70 00 00 00 00 00 default.spp..... 00000330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000340 00 00 00 00 00 10 D9 00 00 00 00 00 00 12 B1 70 ......Ù.......±p 00000350 6C 76 31 2E 73 65 6C 66 00 00 00 00 00 00 00 00 lv1.self........ 00000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000370 00 00 00 00 00 23 8A 80 00 00 00 00 00 03 E8 28 .....#Š€......è( 00000380 6C 76 30 00 00 00 00 00 00 00 00 00 00 00 00 00 lv0............. 00000390 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000003A0 00 00 00 00 00 27 72 A8 00 00 00 00 00 16 EE B8 .....'r¨......î¸ 000003B0 6C 76 32 5F 6B 65 72 6E 65 6C 2E 73 65 6C 66 00 lv2_kernel.self. 000003C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000003D0 00 00 00 00 00 3E 61 60 00 00 00 00 00 07 0F 94 .....>a`.......” 000003E0 65 75 72 75 73 5F 66 77 2E 62 69 6E 00 00 00 00 eurus_fw.bin.... 000003F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000400 00 00 00 00 00 45 70 F4 00 00 00 00 00 07 FC 48 .....Epô......üH 00000410 65 6D 65 72 5F 69 6E 69 74 2E 73 65 6C 66 00 00 emer_init.self.. 00000420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000430 00 00 00 00 00 4D 6D 3C 00 00 00 00 00 06 16 00 .....Mm<........ 00000440 68 64 64 5F 63 6F 70 79 2E 73 65 6C 66 00 00 00 hdd_copy.self... 00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00040460 33 31 35 2E 30 30 30 0A 00 00 00 00 00 00 00 00 315.000......... 00040470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
BDIT_FIRMWARE_PACKAGE.pkg 3.50
Here is a piece of data from decrypted package.
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000300 43 6F 70 79 72 69 67 68 74 28 43 29 20 32 30 30 Copyright(C) 200 00000310 35 2D 32 30 30 36 2C 20 53 6F 6E 79 20 43 6F 6D 5-2006, Sony Com 00000320 70 75 74 65 72 20 45 6E 74 65 72 74 61 69 6E 6D puter Entertainm 00000330 65 6E 74 20 49 6E 63 2E 1A 00 00 00 00 00 00 00 ent Inc......... 00000340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000370 41 96 18 D3 2D 8F 0F 68 11 4D A7 09 E4 1F A7 6F A–.Ó-.h.M§.ä.§o 00000380 EF 29 48 A0 E9 F2 A8 F0 CC 4B F3 4D E0 4A B0 17 ï)H éò¨ðÌKóMàJ°. 00000390 C2 DA 07 5F 96 B3 C8 8D E1 06 2E 3A 1D A7 FD 20 ÂÚ._–³Èá..:.§ý
BDPT_FIRMWARE_PACKAGE_301R.pkg 3.50
Here is a piece of data from decrypted package.
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000300 43 6F 70 79 72 69 67 68 74 28 43 29 20 32 30 30 Copyright(C) 200 00000310 35 2D 32 30 30 39 2C 20 53 6F 6E 79 20 43 6F 6D 5-2009, Sony Com 00000320 70 75 74 65 72 20 45 6E 74 65 72 74 61 69 6E 6D puter Entertainm 00000330 65 6E 74 20 49 6E 63 2E 1A 00 00 00 00 00 00 00 ent Inc......... 00000340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000370 80 18 D2 E4 22 AA 2B D7 85 47 F4 40 53 9A 04 0C €.Òä"ª+×…Gô@Sš.. 00000380 D0 B8 A5 04 20 51 9E 90 09 4F 2E 78 BA 32 C0 EA и¥. Qž.O.xº2Àê 00000390 E9 61 96 ED D8 2A 70 C0 59 68 4E B2 47 25 9C 97 éa–íØ*pÀYhN²G%œ—
BLUETOOTH_FIRMWARE.pkg 3.41
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 52 43 32 39 5F 66 69 72 6D 77 61 72 65 5F 66 6F RC29_firmware_fo 00000010 6F 74 65 72 2E 64 66 75 00 00 00 00 00 00 00 00 oter.dfu........ 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000060 00 00 00 00 30 30 30 30 36 34 34 00 30 30 30 30 ....0000644.0000 00000070 30 30 30 00 30 30 30 30 30 30 30 00 30 30 30 30 000.0000000.0000 00000080 31 35 36 36 33 30 30 00 31 31 30 36 34 33 34 36 1566300.11064346 00000090 33 30 36 00 30 31 35 34 36 33 00 20 30 00 00 00 306.015463. 0... 000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000100 00 75 73 74 61 72 20 20 00 72 6F 6F 74 00 00 00 .ustar .root... 00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000120 00 00 00 00 00 00 00 00 00 72 6F 6F 74 00 00 00 .........root... 00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000140 00 00 00 00 00 00 00 00 00 30 30 30 30 30 30 30 .........0000000 00000150 00 30 30 30 30 30 30 30 00 00 00 00 00 00 00 00 .0000000........ 000A5950 84 1B 00 C0 94 04 00 00 74 06 00 00 45 75 72 75 „..À”...t...Euru 000A5960 73 5F 50 72 69 6D 61 72 79 5F 50 68 79 00 00 00 s_Primary_Phy... 000A5970 4D 61 72 76 65 6C 6C 5F 41 50 00 00 94 BB 01 C0 Marvell_AP..”».À 000B7CC0 00 00 00 00 01 10 60 23 4D 61 72 76 65 6C 6C 20 ......`#Marvell 000B7CD0 46 69 72 6D 77 61 72 65 20 53 44 4B 20 56 65 72 Firmware SDK Ver 000B7CE0 73 69 6F 6E 20 32 2E 33 2E 30 54 74 5D 04 02 2B sion 2.3.0Tt]..+ 000B7CF0 0F 14 E1 36 04 32 0A 1A FD 08 32 1A 1A C1 08 02 ..á6.2..ý.2..Á.. 000F42B0 44 6F 53 68 61 72 65 64 4B 65 79 53 65 71 31 3A DoSharedKeySeq1: 000F42C0 20 45 6E 74 65 72 65 64 20 2D 2D 2D 20 72 73 70 Entered --- rsp 000F42D0 4D 61 63 20 3D 20 25 30 32 78 3A 25 30 32 78 3A Mac = %02x:%02x: 000F42E0 25 30 32 78 3A 25 30 32 78 3A 25 30 32 78 3A 25 %02x:%02x:%02x:% 000F42F0 30 32 78 0A 00 00 00 00 6D 6C 6D 65 41 75 74 68 02x.....mlmeAuth 000F4300 44 6F 53 68 61 72 65 64 4B 65 79 53 65 71 31 3A DoSharedKeySeq1: 000F4310 20 56 61 6C 69 64 61 74 69 6F 6E 20 66 61 69 6C Validation fail 000F4320 65 64 20 2D 2D 2D 20 72 73 70 4D 61 63 20 3D 20 ed --- rspMac = 000F4330 25 30 32 78 3A 25 30 32 78 3A 25 30 32 78 0A 00 %02x:%02x:%02x.. 000F4340 6D 6C 6D 65 41 75 74 68 44 6F 53 68 61 72 65 64 mlmeAuthDoShared 000F4350 4B 65 79 53 65 71 33 3A 20 76 61 6C 69 64 61 74 KeySeq3: validat 000F4360 69 6F 6E 20 66 61 69 6C 65 64 21 20 2D 2D 2D 20 ion failed! --- 000F4370 72 73 70 4D 61 63 20 3D 20 25 30 32 78 3A 25 30 rspMac = %02x:%0 000F4380 32 78 3A 25 30 32 78 0A 00 65 65 70 72 6F 6D 00 2x:%02x..eeprom. 000F4390 62 74 5F 68 63 69 00 62 74 5F 75 61 72 74 00 75 bt_hci.bt_uart.u 000F43A0 73 62 30 00 75 73 62 31 00 4F 53 41 00 77 6C 61 sb0.usb1.OSA.wla 000F43B0 F3 B8 E9 70 01 00 00 00 1C 6B 03 00 00 02 00 00 ó¸ép.....k......
SYS_CON_FIRMWARE_01050101.pkg 3.41
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000300 1B 2D 70 0F AB 5E B3 99 68 20 FE 3D E1 80 6A 1D .-p.«^³™h þ=á€j. 00000310 B8 FD 37 CF CD 45 85 AB 51 F7 05 E3 EA 32 A5 EA ¸ý7ÏÍE…«Q÷.ãê2¥ê 00000320 67 45 F9 48 00 00 00 00 00 10 00 00 C0 0F 00 00 gEùH........À... 00000330 8B 04 07 F9 9B A2 90 3A 75 89 F1 42 12 59 DA 0D ‹..ù›¢:u‰ñB.YÚ. 00000340 21 7C A2 C3 5A E4 78 00 10 8D 4B F7 A2 73 9C 63 !|¢ÃZäx..K÷¢sœc 00000350 5D 8D 5D 49 16 C7 6F 2C AD 33 FE 1F D3 6C A1 CA ]]I.Ço,3þ.Ól¡Ê 00000360 BA AD 2B FE 8F 33 71 D7 C5 E6 5C FF BF 77 6C 80 º+þ3q×Åæ\ÿ¿wl€ 00000370 F2 BE 11 BB 3C 52 52 DC A9 68 E5 24 AD 4F F3 48 ò¾.»<RRÜ©hå$OóH
0x6005 - Extract Package Tophalf
- The result of the request can be checked by reading the value of repository node ss.extract.request.<Request ID> periodically
0x600B - Read EEPROM
- I have got read access to EEPROM of Update Manager through DM and tested it with PSGroove
- I read PRODUCT_MODE from it successfully, PRODUCT_MODE = 0x000000FF
- The service expects one additional parameter: offset (4 bytes)
- The service accepts only some predefined offsets
- The service returns the specified offset and the value at this offset
EEPROM Offset Table
Here is the table of EEPROM offsets that can be accessed through Update Manager (3.15):
Offset | Size | Description |
---|---|---|
0x48C06 | 1 | FSELF Control Flag |
0x48C07 | 1 | Product Mode (UM allows to read this offset, it can be also written but only when already in product mode) |
0x48C0A | 1 | QA Flag |
0x48C13 | 1 | Device Type |
0x48C42 | 1 | HDD Copy Mode |
0x48C50 | 0x10 | Debug Support Flag |
0x48C60 | 1 | Update Status |
0x48C61 | 1 | Recover Mode Flag |
0x48D3E | 0x50 | QA Token (UM doesn't allow access to this offset but SC Manager can read/write it) |
0x600C - Write EEPROM
- Writting to EEPROM of Update Manager is also possible through DM
- Tested this service successfully with QA flag
0x6010 - Check Integrity
- This service checks integrity of important files stored on /dev/rflash1, e.g. lv0 or lv1
- The service is used e.g. by System Manager
- When product mode is NOT 0xFF then check is skipped !!!
0x6011 - Get Applicable Version
- I have got access to this service through DM and PSGroove and tested it
- The service expects one additional unknown parameter of size 4 bytes, it has to be 0x00000001 or else the service fails
Here is the return value:
00 00 00 01 00 00 00 00 00 03 00 20 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
BD Firmware Update
- Update Manager in HV Process 6 updates BD firmware through ATAPI Interface of /dev/rbd0 device.
- BD firmware is sent to BD drive by using ATAPI Write Buffer (0x3B) command with Mode 0x07 (Download microcode with offsets and save) and Buffer ID 0x00.
- The current BD drive firmware version and hash is also stored by and retrieved from SYSCON by using SC Manager Get/Set Region Data (0x9006/0x9007) service. After successfull BD firmware update, Update Manager sends the new firmware version and hash to SYSCON.
- BD firmware package is decrypted, SCE header size + 0x80 bytes are skipped and data beginning with copyright message is sent to BD drive.
- BD firmware is sent packet wise, one packet is at most 0x8000 bytes.
- After each sent packet, Update Manager checks the result by using ATAPI Request Sense (0x3) command.
- Theoretically, BD firmware update can be done also from GameOS by using ATAPI interface of the BD drive.
Detecting BD Drive Type, Generation and Revision
- To detect BD drive type, Update Manager uses ATAPI Inquiry command.
- To detect BD drive generation, Update Manager uses ATAPI Mode Sense 10 command.
BD Drive Type Table
Here is the BD Drive Type Table extracted from HV Process 6 (3.15):
Index | Vendor Identification String | Drive Type |
---|---|---|
0 | "SONY EmerFlashROM" |
0x2100000000000001 |
1 | "SONY PS-EMBOOT 300R" |
0x2100000000000001 |
2 | "SONY BDRW AQUAM(BDIT)" |
0x1100000000000001 |
3 | "SONY PS-SYSTEM 300R" |
0x1100000000000001 |
4 | "SONY PS-SYSTEM V300" |
0x1100000000000001 |
5 | "SCEI EMER-FLASH-8" |
0x2200000000000002 |
6 | "SONY PS-EMBOOT 301R" |
0x2200000000000002 |
7 | "SONY PS-SYSTEM 301R" |
0x1200000000000002 |
8 | "SONY PS-EMBOOT 302R" |
0x2200000000000003 |
9 | "SONY PS-SYSTEM 302R" |
0x1200000000000003 |
10 | "SONY PS-EMBOOT 303R" |
0x2200000000000004 |
11 | "SONY PS-SYSTEM 303R" |
0x1200000000000004 |
12 | "SONY PS-EMBOOT 304R" |
0x2200000000000005 |
13 | "SONY PS-SYSTEM 304R" |
0x1200000000000005 |
14 | "SONY PS-EMBOOT 306R" |
0x2200000000000007 |
15 | "SONY PS-SYSTEM 306R" |
0x1200000000000007 |
Methods (HV Process 6)
update_manager_update_bd_firmware - 0x800064BC (3.15)
bd_updater_prepare_drive - 0x80011A88 (3.15)
bd_updater_send_firmware - 0x80011544 (3.15)
bd_updater_disable_reqsense - 0x80010410 (3.15)
bd_updater_enable_reqsense - 0x800104D8 (3.15)
send_atp_command - 0x80023B10 (3.15)
0x9000 - SC Manager
- SC Manager cannot be accessed directly by using DM unfortunately (DM discards all requests) but it's used by other services that are accessable through DM
- E.g. Update Manager services "Read EEPROM" and "Write EEPROM" send requests to SC Manager services "Read EEPROM" and "Write EEPROM"
- SC Manager runs sc_iso.self
- With full HV rights you could patch Dispatcher Manager and enable access to SC Manager from GameOS.
Packet ID | Description |
---|---|
0x9001 | Get SRH |
0x9002 | Set SRH |
0x9003 | Encrypt |
0x9004 | Decrypt |
0x9005 | Init For VTRM |
0x9006 | Get Region Data |
0x9007 | Set Region Data |
0x9008 | Set RTC |
0x9009 | Get Time |
0x900A | Set Time |
0x900B | Read EPROM |
0x900C | Write EPROM |
0x900D | Init For Updater |
0x900E | Get SC Status |
0x9011 | SC Binary Patch |
0x9012 | SC RTC Factory |
0x9013 | Correct RTC Factory |
0x9014 | Set SC Status |
0x9015 | Backup Root Info |
0x9016 | Restore Root Info |
0x9001 - SC Get SRH
struct ss_sc_mgr_get_srh { u8 field0[20]; u8 res1[4]; u8 field18[20]; u8 res2[4]; };
0x9003 - SC Encrypt
- There are 5 different types/kinds of encryption: 1 - 5.
struct ss_sc_mgr_encrypt { u32 type; /* 1 - 5 */ u8 res[4]; u8 field8[16]; u8 field18[16]; u64 field28; };
0x9004 - SC Decrypt
- There are 5 different types/kinds of decryption: 1 - 5.
- Virtual TRM Decrypt Master (0x200E) service uses e.g. decryption type 4.
0x9006 - SC Get Region Data
- This service expects an ID. The valid range of ID is 0 - 15.
- E.g. Update Manager uses this service to retrieve hash and version of some SELFs and firmwares, e.g. lv0 and lv1.
struct ss_sc_mgr_get_region_data { u64 id; u64 data_size; /* max 0x30 bytes */ u8 data[0]; };
Update Package Type - ID Mapping Table
Update Package Type | ID |
---|---|
1 | 0 |
2 | 2 |
3 | 4 |
4 | 6 |
5 | 7 |
6 | 8 |
0x9007 - SC Set Region Data
- This service expects an ID. The valid range of ID is 0 - 15.
- E.g. Update Manager uses this service to store hash and version of some SELFs and firmwares, e.g. lv0 and lv1.
struct ss_sc_mgr_set_region_data { u64 id; u64 data_size; /* max 0x30 bytes */ u8 data[0]; };
0x900B - SC Read EPROM
- There are 2 ways to access SC EPROM: NVS Service and Device Access Service.
- NVS Service uses Block ID and Block Offset.
- Not all EPROM offsets can be accessed through SC Manager.
struct ss_sc_mgr_read_eprom { u32 offset; u8 res1[4]; u32 nread; /* max 0x100 bytes */ u8 res2[4]; u64 buf_size; u8 buf[0]; /* here follows buf */ };
EPROM Offset - Block ID and Block Offset Mapping Table (NVS Service)
EPROM Offset | Block ID | Block Offset |
---|---|---|
0x48000 - 0x480FF | 0x00 | 0x48000 - 0x480FF |
0x48800 - 0x488FF | 0x01 | 0x48800 - 0x488FF |
0x48C00 - 0x48CFF | 0x02 | 0x48C00 - 0x48CFF |
0x48D00 - 0x48DFF | 0x03 | 0x48D00 - 0x48DFF |
0x2F00 - 0x2FFF | 0x10 | 0x2F00 - 0x2FFF |
0x3000 - 0x30FF | 0x20 | 0x3000 - 0x30FF |
All other offsets | Invalid | Invalid |
0x900C - SC Write EPROM
struct ss_sc_mgr_write_eprom { u32 offset; u8 res1[4]; u32 nwrite; u8 res2[4]; u64 buf_size; u8 buf[0]; /* here follows buf */ };
0x900E - SC Get Status
Here is what the service returned on my fat PS3:
0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0xC0 0x00 0x00 0xFF 0x00 0x00 0x00 0x00
So, version is 0x00000003 and mode is 0xC00000FF.
struct ss_sc_mgr_get_sc_status { u32 version; u8 res1[4]; u32 mode; u8 res2[4]; };
0x9011 - SC Binary Patch
- This service is used by Update Manager to send a new SC firmware version to SYSCON.
SC Isolation DMA Buffer Header
struct sc_iso_header { u32 seqno; u32 mbmsg; u32 cmd; u32 cmd_size; u8 cmd_data[0]; };
0x11000 - SPM (Security Policy Manager)
- Packet ID is mapped to SS id
- SS id value range is 0x0 - 0x84
Packet ID | Description |
---|---|
0x11001 | Request |
0x11002 | Load Additional Policy |
0x14000 - SLL (Secure LPAR Loader)
- SLL opens lv2_kernel.self, parses ELF header and determines the size of initial memory region for GameOS LPAR
- SLL creates a memory region for GameOS LPAR by using syscall 0x10000.
- SLL opens /proc/partitions/<LPAR id>/mem file and maps it with mmap syscall into it's address space.
- Then it authenticates, decrypts and copies the SELF file of GameOS to LPAR's memory region by using SPE syscalls 0x10040 and 0x10042.
- Linux is not loaded by SLL, it's loaded in Process 9 by Linux System Manager
- GameOS file image lv2_kernel.self is stored on /dev/rflash1
Packet ID | Description |
---|---|
0x14004 | Load GOS |
0x14005 | Unload GOS |
0x15000 - SPL (Secure Profile Loader)
- DEFAULT.SPP file is stored on /dev/rflash1
Packet ID | Description |
---|---|
0x15001 | Get LPAR Parameter Size/Get LPAR Parameter |
0x15003 | Get Contents Size/Get Contents |
0x15009 | Get Component |
SPP File
- The file is encrypted but can be read by using 0x15003 service of SPL
- SPL reads SPP file, parses SPP header and checks some fields
- SPP file is verified and decrypted by SPU module spp_verifier.self that cab be executed with HV SPE calls
- Even old default.spp from PS3 Firmware 1.10 can be decrypted with spp_verifier.self from PS3 Firmware 3.41
- Header format version should be 5 or else the header check fails
- If (SPP header size % 256 != 0) then header check fails
- Finally i was able to decrypt profile file from 3.41 but by using SPE HV calls only !!! And Linux Manager is still there !!!
- The decrypted file is a binary file
Here are the contents of DEFAULT.SPP from 3.41.
Here are the contents of DEFAULT.SPP 1.18 Debug from 1.18 Debug Firmware.
SPP Header
offset 0x2 - header format version (2 bytes)
offset 0x4 - header size (4 bytes)
offset 0x18 - number of segments (4 bytes)
Segments
- Segments follow after the header
- SPP file contains several segments.
Here is the list of profile segments from 3.41:
- SCE_CELLOS_PME
- PS3_LPAR
- PS2_LPAR
- PS2_GX_LPAR
- LINUX_LPAR
- SCE_CELLOS_SYSTEM_MGR
- SCE_CELLOS_SYSTEM_MGR_LINUX
- SCE_CELLOS_SYSTEM_MGR_PS2
- SCE_CELLOS_SYSTEM_MGR_PS2_SW
- SCE_CELLOS_SYSTEM_MGR_PS2_GX
- SCE_CELLOS_SS_SECURE_RTC
- SCE_CELLOS_SS_INDI_INFO_EID
- SCE_CELLOS_SS_INIT_LV1_ACL
0x15003 - Get Contents Size/Get Contents
- This service provides the contents of a segment specified by a service requester
- I have got access to this service through DM but couldn't get through access policy yet, the service returns error code 0x00000005 that means Access Violation
- But i still could test with this service which segment names are valid
- I need valid laid and paid to get through it
0x17000 - Indi Info Manager
Packet ID | Description |
---|---|
0x17001 | Read EID Data Size By Index/Read metldr Size |
0x17002 | Read EID Data By Index/Read metldr |
0x17004 | Read System Data |
0x17007 | Read System Data From EEPROM |
0x17013 | Read eEID Size |
0x17014 | Write eEID/Write metldr |
0x17015 | Read cISD Size |
0x17016 | Read cISD |
0x17017 | Write cISD |
- Indi Info Manager is accessed e.g. in syscall 868 on GameOS
0x17001 - Read EID Data Size By Index
- I have got access to this service through DM and tested it
- This service is used e.g. by Update Manager, User Token Manager or Storage Manager
- The service expects 2 additional parameters, each parameter is 8 bytes
- I tested it with values: 0x0, 0x4 and 0x1000 for the 1st parameter. I extracted this values from HV Processes which use this service
- The 2nd parameter is not used in a request but in a response. It contains EID size.
Index | Size Of Data | Description |
---|---|---|
0 | 0x860 | Used e.g. by Update Manager to decrypt update packages |
4 | 0x30 | Used e.g. by Storage Manager |
0x1000 | 0xe960 | metldr |
0x17002 - Read EID Data By Index
- I have got access to this service through DM and tested it
- This service is used e.g. by Update Manager, User Token Manager or Storage Manager
- The service expects 2 additional parameters, each parameter is 8 bytes
- The 1st parameter is same as the 1st parameter of service Read EID Data Size By Index
- The 2nd parameter is EID Data Size that is returned by the service Read EID Data Size By Index
- The returned data is some binary data.
- The data returned by the service with 1st parameter set to 0x0 or 0x4 is from file eEID stored on FLASH storage device region 0.
- The data returned by the service with 1st parameter set to 0x1000 contains string metldr.
- E.g. EID0 data is passed by Update Manager to SPU module spu_token_processor.self when Update Manager loads and executes it with syscall 0x10043.
- E.g. EID4 data is passed by Storage Manager to SPU module sb_iso_spu_module.self.
0x17004 - Read System Data
- Reads data from cISD or cCSD files stored on /dev/rflash1.
- E.g. Gelic MAC address is stored in file cISD.
0x17007 - Read System Data From EEPROM
- Reads data from SC EEPROM
- An index is passed to the service. The index is mapped to a specific SC EEPROM offset.
Here is the list of possible EEPROM offsets from HV 3.15:
Index | SC EEPROM Offset | Size Of Data |
---|---|---|
0 | 0x48D20 | 6 |
1 | 0x48D28 | 6 |
2 | 0x48D30 | 6 |
3 | 0x48D38 | 6 |
4 | 0x48D00 | 4 |
5 | 0x48D04 | 4 |
6 | 0x48D08 | 4 |
0x17014 - Write eEID/Write metldr
- Holy crap, it writes passed data to the region of FLASH memory where eEID or metldr data is stored !!!
- And GameOS is allowed to use this service !!!
- Do not experiment with this service if you don't know what it does or else your PS3 will not work anymore !!!
0x17015 - Read cISD Size
- Returns size of data cISD that is stored on FLASH storage device region 0
0x17016 - Read cISD
- Returns data cISD that is stored on FLASH storage device region 0
0x17017 - Write cISD
- Writes passed data to the region of FLASH memory where cISD data is stored !!!
0x18000 - DM (Dispatcher Manager)
- Dispatcher Manager runs in Process 3.
- When SLL (Secure LPAR Loader) creates GamesOS LPAR and loads it, it also creates a VUART with port number 10 owned by GameOS using a service provided by Dispatcher Manager (0x18001 - Construct Service Port).
- Dispatcher Manager communicates with GameOS through this VUART. It opens the file /proc/partitions/<LPAR id>/vuart/10. When the file /proc/partitions/<LPAR id>/vuart/10 is opened by Dispatcher Manager, the Hypervisor creates a peer VUART which is connected to the GameOS's VUART 10.
- After that Dispatcher Manager reads requests from this VUART sent by GameOS and dispatches these requests to services (functions) provided by Hypervisor Processes through sockets. Through VUART and Dispatcher Manager, the GameOS LPAR has access to all services provided by Hypervisor Processes.
- However, the services provided by Hypervisor Processes are protected by Security Policy Manager (SPM). Before Dispatcher Manager routes the requests from GameOS to these services, it consults SPM (by using 0x11001 service of SPM) and checks if the GameOS has access rights to the requested service. If not then the request is not routed.
- DM overwrites the LAID sent in SS packet header with the LAID of the LPAR that sent the request. So, no matter what LAID you send in SS packet header, it will be always overwritten with the correct one by DM. That is the reason why e.g. USB Dongle Master Key cannot be decrypted by GameOS without patching DM. But with HV access rights, DM can be easily patched and access to SYSCON can be gained.
- Linux LPAR doesn't have a VUART communication link to Dispatcher Manager.
- I tested VUART 10 on GameOS with PSGroove and it's there.
- On GamesOS, _ss_multiplexer accesses DM (VUART 10)
Packet ID | Description |
---|---|
0x18001 | Construct Service Port |
0x18002 | Destruct Service Port |
Dispatcher Manager Messages
Dispatcher Manager Header
- Payload follows after header
- Payload is a SS packet
struct dispmgr_header { uint32_t request_id; uint32_t function_id; uint32_t request_size; /* payload size of request */ uint32_t response_size; /* payload size of response */ }
Packet ID - SS ID Mapping
- Before DM routes a received request to a service provider (HV Process) it consults SPM
- DM sends a request to SPM
- Request contains SS ID and Subject ID (laid and paid)
- DM obtains SS ID by mapping Packet ID
Here is the mapping table i extracted from HV Process 3 where SPM and DM run:
Packet ID | SS ID |
---|---|
0x2001 | 0x34 |
0x2002 | 0x35 |
0x2003 | 0x36 |
0x2004 | 0x37 |
0x2005 | 0x38 |
0x2006 | 0x39 |
0x200A | 0x3D |
0x200B | 0x3E |
0x200C | 0x3F |
0x200D | 0x40 |
0x200E | 0x41 |
0x2012 | 0x7B |
0x2013 | 0x7C |
0x2014 | 0x7E |
0x2015 | 0x7F |
0x2016 | 0x7D |
0x2017 | 0x80 |
0x19000 - AIM
- Executes isolated SPU module aim_spu_module.self
- EID0 data is passed to aim_spu_module.self
Packet ID | Description |
---|---|
0x19002 | Get Device Type |
0x19003 | Get Device ID |
0x19004 | Get PS Code |
0x19005 | Get Open PS ID |
0x19002 - Get Device Type
On my fat PS3 with HV 3.41 it returns:
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x85
struct ss_aim_get_device_type { u8 field0[16]; };
0x19003 - Get Device ID
struct ss_aim_get_device_id { u8 field0[16]; };
0x19004 - Get PS Code
struct ss_aim_get_ps_code { u8 field0[8]; };
0x19005 - Get Open PS ID
struct ss_aim_get_open_ps_id { u8 field0[16]; };
0x24000 - USB Dongle Authenticator
Packet ID | Description |
---|---|
0x24001 | Generate Challenge |
0x24002 | Verify Response |
0x24001 - Generate Challenge
- I have got access to this service through DM and tested it
- The service expects no input parameters except those in SS packet header
- It uses 0x5003 service (Generate Random Number) to generate random numbers that are used in challenge body
- The length of a challnge body is always 23 bytes, first 3 bytes are always the same: 0x2E 0x02 0x01
Here are hexdumps of some challenge bodies i let 0x24001 service generate:
2E 02 01 72 3A 0A 76 BB 81 CB 29 BC E7 B5 D6 62 7C 0E EE 23 18 A9 1D
2E 02 01 F0 DA 78 D4 1D CB D7 C9 C7 F0 32 F4 2E 92 39 BD 3F 32 93 AA
2E 02 01 3B B2 9D FD A8 83 AF 9A C0 E9 13 BB AE D5 6C 8C 45 2E DE 13
0x24002 - Verify Response
- I have got access to this service and tested it with PSGroove
- The response body is 25 bytes large
- The first 3 bytes have to be 0x2E 0x02 0x02 or else the check fails
- The 16 bit at offset 3 is a dongle ID
- The dongle ID is checked if it's revoked or not
- When the verification succeedes then product mode is set to 1
- The service calculates USB Dongle Key from USB Dongle ID and USB Dongle Master Key by using HMAC SHA-1
- The service uses HMAC SHA-1 to calculate the correct response body from the challenge body and USB Dongle Key
- After that the service compares the calculated response body with the given one that was sent to the service
- It seems that laid and paid from SS packet header are used in decryption process
USB Dongle Master Key
- USB Dongle Master Key is stored encrypted in Process 6
- The encrypted key is 64 bytes large
- The decrypted key is 20 bytes large
- The USB Dongle Master Key is decrypted first time the service 0x24002 is used
- The USB Dongle Master Key is decrypted by using the service 0x200E (Decrypt Master) of Vitual TRM Manager
- The decrypted USB Dongle Master Key is stored in Process 6 in clear text (after first usage of this service)
- When decryption of USB Dongle Master Key fails then a dummy key is used
- Unfortunately, in the HV dump 3.15 the USB Dongle Master Key was not decrypted at the moment of dumping
- The first 12 bytes of decrypted USB Dongle Master Key is a magic value: _USB_DONGLE_. After these 12 bytes follows the real USB Dongle Master Key of size 20 bytes. So, if after decryption of USB Dongle Master Key, you see this magic value then the decryption was successfull.
Here is the encrypted USB Dongle Master Key from HV 3.15:
0x22 0xD5 0xD1 0x8C 0xFF 0xE2 0x4F 0xAC 0xEC 0x72 0xA2 0x42 0xA7 0x18 0x98 0x10 0x25 0x33 0xE0 0x96 0xF2 0xC1 0x91 0x0D 0x15 0x23 0xD3 0x07 0x74 0xE7 0x2B 0x72 0xDF 0xA6 0xDD 0xE9 0x68 0x8B 0x76 0x2A 0x6A 0x87 0x51 0x7F 0x85 0x39 0x0B 0xD4 0x20 0x3F 0x46 0x89 0x04 0x82 0xB7 0x30 0x84 0x89 0x4B 0xCC 0x9D 0xB1 0x24 0x7C
This is the decrypted dongle master key:
0x46 0xDC 0xEA 0xD3 0x17 0xFE 0x45 0xD8 0x09 0x23 0xEB 0x97 0xE4 0x95 0x64 0x10 0xD4 0xCD 0xB2 0xC2
This is the decrypted dongle key for dongle ID 0xAAAA which works up to 3.55:
0x04 0x4E 0x61 0x1B 0xA6 0xA6 0xE3 0x9A 0x98 0xCF 0x35 0x81 0x2C 0x80 0x68 0xC7 0xFC 0x5F 0x7A 0xE8
Here is the USB Dongle Master Dummy Key from HV 3.15:
0xD1 0xFC 0x57 0x55 0xBF 0x20 0xFA 0xB2 0xD4 0xA5 0x4A 0x0A 0x0C 0x5D 0x52 0x8E 0xDF 0x66 0xCD 0x74
USB Dongle ID Revoke List
- Process 6 contains a revoke list for USB Dongle IDs
- The revoke list is 0x2000 bytes large. It's a bitmap.
- Each bit represents a USB Dongle ID. If bit is 0 then USB Dongle ID is revoked.
The following USB Dongle IDs are revoked in HV 3.15:
0, 2, 13, 32, 34, 176, 241
0x25000 - User Token Manager
Packet ID | Description |
---|---|
0x25001 | Encrypt User Token |
0x25002 | Decrypt User Token |
User Token
- Before User Token Manager encrypts a received user token it checks it's format.
- User Tokens are processed by spu_utoken_processor.self
- Before User Token is processed, User Token Manager reads IDPS by sending SS requests to Indi Info Manager (packet ids 0x17001 and 0x17002). Indi Info Manager runs in HV Process 5.
User Token Format
stuct user_token_attr { uint32_t type; /* 0x00000001, value != 0x00000001 means attribute list ends here */ uint32_t size; /* 8 + sizeof(data) */ /* data follows here, size of data may be 0 */ } struct user_token { uint32_t magic; /* 0x73757400 = "sut\0" */ uint32_t format_version; /* 0x00000001 */ uint64_t size; uint8_t idps[16]; uint64_t expire_date; uint64_t capability; union { stuct user_token_attr attrs[0]; uint8_t dummy[3072]; } attrs; /* 0xC30 */ uint8_t digest[20]; }
LPAR Memory Management
Memory Region class
This class is the base class for different memory region types.
vtable
0x003578B0 (3.15)
Member variables
offset 0x40 - pointer to LPAR object that owns this memory region
offset 0x48 - type of memory region (8 bytes)
offset 0x50 - LPAR start address of memory region
offset 0x58 - size of memory region (8 bytes)
offset 0x60 - flags (8 bytes)
offset 0xA0 - log2 of page size
Generating New LPAR Memory Region Addresses
generate_new_lpar_mem_region_address(?, memory region size, log2(page size), ?, ?) - 002C82E8 (3.15)
generate_new_lpar_mem_region_address - 002C6570 (3.41)
- The function returns a new LPAR memory region address.
- This method is used e.g. in all HV calls which create any kind of memory regions, e.g. lv1_allocate_memory, lv1_map_htab, lv1_undocumented_function_114, lv1_construct_logical_spe, lv1_map_device_mmio_region or syscall 0x10040.
Encoding LPAR Memory Region Start Addresses and Sizes
- Size of LPAR memory region is encoded in the LPAR memory region start address.
- That is why e.g. the LPAR Memory Region Start Addresses of LPAR Memory Region of size 4096 byte begin with 0x300000000000, 0x300000000000 >> 42 = 0xC = log2(4096).
- Each LPAR has a counter (8 bytes) which is incremented by 1 every time a new LPAR Memory Region is created.
- Before incrementing, the counter is shifted left by log2(LPAR Memory Region Size) and ored with log2(LPAR Memory Region Size) << 42.
LPAR Memory Region Start Address >> 42 = log2(LPAR Memory Region Size)
LPAR Memory Region Start Address = (log2(LPAR Memory Region Size) << 42) | (counter << log2(LPAR Memory Region Size))
LPAR Memory Region Address Counter
- LPAR Memory Region Address Counter is stored at address: 0x38(LPAR ptr) + 0x9E8
- LPAR1's Memory Region Address Counter is at address 0x00677A48 in HV dump 3.15
- LPAR2's Memory Region Address Counter is at address 0x007632D8 in HV dump 3.15
- LPAR1's Memory Region Address Counter is at address 0x00677A48 in HV dump 3.41
- LPAR2's Memory Region Address Counter is at address 0x00161E68 in HV dump 3.41
Physical Memory Region class
This type of memory region is created e.g. in lv1_allocate_memory HV call or in syscall 0x10000.
vtable
0x00357D08 (3.15)
Member variables
offset 0xB0 - pointer to object that stores a list of addresses of physical pages owned by this memory region
offset 0xB8 - pointer to LPAR object that owns this memory region
offset 0xC0 - reference counter (8 bytes)
Objects
Here is the list of physical memory region objects i found in HV 3.15.
Address in HV dump | LPAR id | LPAR Start Address | Size | Flags | log2(Page Size) | Physical Page Addresses |
---|---|---|---|---|---|---|
0x006B5510 | 1 | 0x300000001000 | 0x1000 | 0x0 | 0xC | 0x672000 |
0x006B5E50 | 1 | 0x440000040000 | 0x20000 | 0x0 | 0x11 | 0x6C0000 |
0x006B6980 | 1 | 0x440000060000 | 0x20000 | 0x0 | 0x11 | 0x6E0000 |
0x006B7F00 | 1 | 0x400000040000 | 0x10000 | 0x0 | 0x10 | 0x100000 |
0x003A80F0 | 2 | 0x6C0058000000 | 0x7000000 | 0x4 | 0x18 | 0x1000000 - 0x7000000 |
0x003BE800 | 2 | 0x300000047000 | 0x1000 | 0x0 | 0xC | 0x1FA000 |
0x006BDAA0 | 2 | 0x0 | 0x8000000 | 0x8 | 0x1B (single huge page) | 0x8000000 |
So, Linux kernel should be located at physical address 0x8000000 and Linux syscall handler at 0x8000C00. Too bad that the HV dump is not large enough.
GameOS Physical Memory Regions
- GameOS allocates nearly all physical memory of PS3 for itself !!! That is why new HV calls lv1_allocate_memory with large memory region sizes will fail.
- So when someone wants a large piece of physical memory, he can borrow it from GameOS's LPAR memory region that starts at 0x700020000000. It can be used for example to send update packages to Update Manager which are very large.
Here is the list of physical memory regions of GameOS i found in HV 3.41:
Start Address | Size | Access Right | Max Page Size | Flags | Real Addresses |
---|---|---|---|---|---|
0x0 | 0x1000000 | 0x3 | 0x18 | 0x8 | 0x1000000 - 0x1FFF000 |
0x500000300000 | 0xA0000 | 0x3 | 0x10 | 0x8 | 0x380000 - 0x38F000, 0x3B0000 - 0x3BF000, 0x1E0000 - 0x1FF000, 0x3C0000 - 0x3FF000, 0xFF00000 - 0xFF1F000 |
0x700020000000 | 0xE900000 (huge memory region) | 0x3 | 0x14 | 0x0 | 0x400000 - 0x5FF000, 0x800000 - 0xFFF000, 0x2000000 - 0xFEFF000 |
HTAB Memory Region class
This memory region is created when a HTAB is mapped into LPAR's address space. It's created in lv1_map_htab HV call.
vtable
0x00357C98 (3.15)
Member variables
offset 0xB0 - pointer to VAS object that owns the HTAB
Objects
Here is the list of HTAB memory region objects i found in HV 3.15.
Address in HV dump | LPAR id | VAS id | LPAR Start Address | Size | Flags | log2(Page Size) |
---|---|---|---|---|---|---|
0x001FE0F0 | 2 | 3 | 0x500000C00000 | 0x100000 | 0xC000000000000000 | 0x14 |
0x003BD850 | 2 | 3 | 0x500004300000 | 0x100000 | 0xC000000000000000 | 0x14 |
0x003BDEA0 | 2 | 3 | 0x500004500000 | 0x100000 | 0xC000000000000000 | 0x14 |
GameOS HTAB
- HTAB of GameOS is already mapped into address space of GameOS so that is why HV call lv1_map_htab will fail until you unmap it with lv1_unmap_htab
- Effective address of GameOS HTAB is 0x800000000F000000
- Virtual address of GameOS HTAB is 0xF000000
- Size of GameOS HTAB is 0x40000
- GameOS HTAB supports large pages of size 64K and 1M
- GameOS HTAB can be easily dumped by reading 0x40000 bytes at EA 0x800000000F000000
GameOS SLB
Here is the dump of SLB entries from GameOS 3.41:
0x8000000008000000 0x0000000000000500 0x8000000208000000 0x0000000000020500 0x8000000300000000 0x0000000000030510 0x0000000000000000 0x0000000000000000 0x0000000080000000 0x0000000000038C00 0x00000000A0000000 0x000000000003AC00 0x00000000C0000000 0x000000000003CC00 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x8000000010057960 0x8000000000313E78 0x8000000010057940 0x0000000000000000 0x800000000001B698 0x0000000000000000 0x8000000010057930 0x8000000000490708 0x80000000002B6C68 0x80000000003DE928 0x8000000010057EC0 0x80000000003DE920 0x0000000000000000 0x8000000000309810 0x80000000004B3000 0x0000000000000000 0x8000000010057CC0 0x0000000000000000 0x80000000004AF000 0x80000000004E1F00 0x80000000100579C8 0x80000000100579C0 0x80000000100579E0 0x2400002200000000 0x80000000004CF5B0 0x8000000200012000 0x80000000100579F8 0x80000000100579F0 0x8000000010057A10 0x80000000004A3A00 0x80000000004CF5B0 0x80000000004C8D00 0x800000000001BF6C 0x80000000004CD400 0x800000000001B698 0x80000000004C8100 0x80000000100579D0 0x80000000004B48C0 0x0000000000001C08 0x0000000000000000 0x8000000010057A78 0x8000000010057A70 0x8000000010057A90 0x0000000000000000 0x80000000004CF90C 0x0000000000000000 0x0000000000000000 0x8000000010057A80 0x8000000010057A90 0x8000000000309810 0x80000000004CF62C 0x0000000000000000 0x8000000010057CC0 0x0000000000000000 0x80000000004AF000 0x80000000004B48C0 0x00004000001C0000 0x0000000000000001 0x00000000D0000000 0x0000A8E3EE7D10DA 0x0000000000000000 0x0000000000000000 0x80000000004D8088 0x80000000004D9000
SPE MMIO Memory Region class
This type of memory region represents MMIO memory region of a SPE. It's created e.g. in lv1_construct_logical_spe or in syscall 0x10040.
vtable
0x003583F8 (3.15)
Member variables
Objects
Here is the list of SPE memory region objects i found in HV 3.15.
Address in HV dump | LPAR id | SPE | LPAR Start Address | Size | Physical Address | Flags | log2(Page Size) |
---|---|---|---|---|---|---|---|
0x003ABC20 | 2 | 1 | 0x4C0000880000 | 0x80000 | 0x20000080000 | 0xA000000000000000 | 0xC |
0x003AAD70 | 2 | 2 | 0x4C0000980000 | 0x80000 | 0x20000100000 | 0xA000000000000000 | 0xC |
0x003A8880 | 2 | 3 | 0x4C0000780000 | 0x80000 | 0x20000180000 | 0xA000000000000000 | 0xC |
0x003B4F70 | 2 | 4 | 0x4C0000A80000 | 0x80000 | 0x20000200000 | 0xA000000000000000 | 0xC |
0x003AB700 | 2 | 5 | 0x4C0000680000 | 0x80000 | 0x20000280000 | 0xA000000000000000 | 0xC |
0x003B5BE0 | 2 | 6 | 0x4C0000B80000 | 0x80000 | 0x20000300000 | 0xA000000000000000 | 0xC |
SPE Shadow Registers Memory Region class
This type of memory region represents shadow registers memory region of a SPE. It's created e.g. in lv1_construct_logical_spe or in syscall 0x10040.
vtable
0x00358448 (3.15)
Objects
Here is the list of SPE Shadow Registers memory region objects i found in HV 3.15.
Address in HV dump | LPAR id | SPE | LPAR Start Address | Size | Physical Address | Flags | log2(Page Size) |
---|---|---|---|---|---|---|---|
0x003ABDA0 | 2 | 1 | 0x300000012000 | 0x1000 | - | 0xA000000000000000 | 0xC |
0x003B4290 | 2 | 2 | 0x300000014000 | 0x1000 | - | 0xA000000000000000 | 0xC |
0x003A8A00 | 2 | 3 | 0x300000010000 | 0x1000 | - | 0xA000000000000000 | 0xC |
0x003B50F0 | 2 | 4 | 0x300000016000 | 0x1000 | - | 0xA000000000000000 | 0xC |
0x001FFC90 | 2 | 5 | 0x30000000E000 | 0x1000 | - | 0xA000000000000000 | 0xC |
0x003AE5B0 | 2 | 6 | 0x300000018000 | 0x1000 | - | 0xA000000000000000 | 0xC |
Device MMIO Memory Region class
This type of memory region is created when a device MMIO region is mapped into LPAR address space, e.g. in lv1_map_device_mmio_region.
vtable
0x00352468 (3.15)
Member variables
offset 0xA8 - physical address where the device MMIO region is mapped to
Objects
Here is the list of Device MMIO memory region objects i found in HV 3.15.
Address in HV dump | LPAR id | LPAR Start Address | Size | Flags | log2(Page Size) | Physical Address | Device |
---|---|---|---|---|---|---|---|
0x001FDF00 | 2 | 0x4000001D0000 | 0x10000 | 0x8000000000000000 | 0xC | 0x24003010000 | USB controller |
0x003B3850 | 2 | 0x400000200000 | 0x10000 | 0x8000000000000000 | 0xC | 0x24003020000 | USB controller |
0x003B6E50 | 2 | 0x4000001E0000 | 0x10000 | 0x8000000000000000 | 0xC | 0x24003810000 | USB controller |
0x003B9950 | 2 | 0x4000001F0000 | 0x10000 | 0x8000000000000000 | 0xC | 0x24003820000 | USB controller |
GPU Device Memory Region class
This type of memory region is created e.g. in lv1_gpu_open, lv1_gpu_device_map and lv1_undocumented_function_114.
vtable
0x00357C48 (3.15)
Member variables
offset 0xA8 - physical address
Objects
Here is the list of Device GPU memory region objects i found in HV 3.15.
Address in HV dump | LPAR id | LPAR Start Address | Size | Flags | log2(Page Size) | Physical Address |
---|---|---|---|---|---|---|
0x003AF380 | 2 | 0x700190000000 | 0xFE00000 | 0x8000000000000000 | 0x14 | 0x28080000000 |
0x003AF500 | 2 | 0x4000001A0000 | 0xC000 | 0x8000000000000000 | 0xC | 0x3C0000 |
0x003AF680 | 2 | 0x4800006C0000 | 0x40000 | 0x8000000000000000 | 0xC | 0x2808FE00000 |
0x003AFC30 | 2 | 0x440000380000 | 0x20000 | 0x8000000000000000 | 0xC | 0x28000C00000 |
0x003BB420 | 2 | 0x3C0000108000 | 0x8000 | 0x8000000000000000 | 0xC | 0x28000080100 |
Direct Map Memory Region class
This type of memory region is created in HV call lv1_undocumented_function_114. lv1_undocumented_function_114 allows you to map any memory address into LPAR's memory address.
- The HV call lv1_undocumented_function_115 destroys a memory region of this type.
- HV allows GameOS to create objects of this type of size 0 only !!! But it can be exploited with a dangling HTAB entry.
vtable
0x00357C48 (3.15)
Member variables
offset 0xA8 - physical address
Exploiting HV with memory glitching and HV call lv1_undocumented_function_114
Here is a short description of the method i used to exploit HV from GameOS 3.15 and 3.41.
- First i used the Geohot's method to create a dangling HTAB entry.
- Making memory glitch work on GameOS was the largest of my obstacles but i solved it and i'm able to create a dangling HTAB entry from GameOS within 1-3 minutes.
- Then i created many Direct Map Memory Region objects of size 0 with HV call lv1_undocumented_function_114 and checked if they are within the page to which the dangling HTAB entry points to.
- When i found one such Direct Map Memory Region object i patched the size of this object to 0x1000. Then i pointed this memory region object to the code of HV call lv1_undocumented_function_114 and patched 4 bytes in this HV call which allows me to create any Direct Map Memory Region objects without any restrictions.
- Function LPAR_construct_direct_mapping_mem_region which is used by HV call lv1_undocumented_function_114 has a parameter (register %r9) and when this parameter is not 0 then HV will allow you to create any Direct Map Memory Region objects without restrictions, but unfortunately the HV call lv1_undocumented_function_114 passes 0 in this parameter, so i just patched it.
- Then i mapped whole HV memory range with the patched HV call lv1_undocumented_function_114 into the address space of GameOS.
- And now you have read/write access to the whole HV.
- $ONY could fix this exploit by disallowing creating of Direct Map Memory Region objects of size 0, but i know tons of other HV C++ classes which will allow me to exploit the HV in a similar way, so it wouldn't bring $ONY anything :-) And they have to change member variable offsets in those objects to make sure that i cannot patch them easily :-)
Methods
LPAR_get_memory_region_by_start_address - 0x002C7C40 (3.15)
LPAR_get_memory_region_by_address - 0x002C7DA8 (3.15)
LPAR_mem_addr_to_phys_addr(LPAR id, LPAR address, phys_addr) - 0x002FB8F0 (3.15)
LPAR_construct_direct_mapping_mem_region - 0x002D4D04 (3.15)
Network Devices
Ethernet Gelic Device
device id = 0
MAC Address: 00:1F:A7:C6:2A:C5
device memory base address = 0x24003004000 (size = 0x1000)
WLAN Gelic Device
device id = 0
MAC Address: 02:1F:A7:C6:2A:C5 (locally administered)
Net Manager
- Net Manager runs in Process 9
- It sends commands to /dev/sc1 to reset WLAN Gelic device
- It opens /dev/net0, sets MAC address and writes device firmware eurus_fw.bin to WLAN device by using ioctl syscall
/dev/net0
The device supports 3 ioctl commands:
- 0 - 0x002AC10C (3.15)
- 1 - 0x002AC250 (3.15)
- 2 - EURUS_STAT 0x002AC320 (3.15)
Methods
net_control_cmd_GELIC_LV1_POST_WLAN_CMD - 0x0024A55C (3.15)
net_control_wlan_cmd_GELIC_EURUS_CMD_ASSOC - 0x00246C78 (3.15)
net_control_wlan_cmd_GELIC_EURUS_CMD_START_SCAN - 0x00248A14 (3.15)
net_control_wlan_cmd_GELIC_EURUS_CMD_SET_WEP_CFG - 0x00249F24 (3.15)
net_control_wlan_cmd_GELIC_EURUS_CMD_SET_WPA_CFG - 0x002497B8 (3.15)
Event Notification
- Event Notfication is used e.g. to notify a LPAR about some event, e.g. device interrupt or notify a LPAR about destruction of another LPAR.
- For example Process 9 is notified through Event Notification when LPAR 2 is destructed.
- During LPAR construction, Process 9 creates an Outlet object with syscall 0x1001A and then passes the outlet ID to the syscall 0x10009 that constructs the LINUX LPAR. In this way Process 9 is notified when LINUX LPAR is destructed.
Outlet class
This is the base Outlet class. There are different types of Outlet and they derive from this base class.
vtable
0x00357DC0 (3.15)
Member variables
offset 0x30 - type (8 bytes)
offset 0x38 - pointer to LPAR that owns this Outlet object
offset 0x48 - outlet id (8 bytes)
offset 0x90 - VIRQ assigned to this Outlet object (4 bytes)
Event Receive Port class
- This type of Outlet is created e.g. in lv1_construct_event_receive_port and in syscall 0x1001A.
- HV calls lv1_connect_irq_plug and lv1_connect_irq_plug_ext assigns a VIRQ to Event Receive Port object.
vtable
0x00357E88
VUART Outlet
- HV supports only one VUART Outlet per LPAR
- lv1_configure_virtual_uart_irq constructs a VUART Outlet object and passes the address of LPAR's VUART IRQ Bitmap to HV
vtable
0x00357DC0
VUART IRQ Bitmap
- At address 0x38(LPAR ptr) + 0x158 is the VUART IRQ Bitmap owned by HV for LPAR (4 * 8 bytes = 256 bits)
- At address 0x38(LPAR ptr) + 0x150 is stored the physical address of LPAR's VUART IRQ Bitmap that was passed to lv1_configure_virtual_uart_irq
- When a VUART interrupt is generated by HV then first the VUART IRQ Bitmap owned by HV is updated and then this bitmap is copied to LPAR's VUART IRQ Bitmap, so VUART IRQ Bitmap is stored twice, once in HV and once in LPAR, just like IRQ State Bitmap.
- VUART IRQ Bitmap is not allowed to cross page boundary of LPAR memory region where it is stored. HV checks it and makes sure that it doesn't happen.
- GameOS 3.41 VUART IRQ bitmap is at address 0x80000000003556E8 and of size 32 bytes (256 bits, each bit corresponds to a VUART port).
- GameOS 3.15 VUART IRQ bitmap is at address 0x8000000000354768.
Logical PPE
- Logical PPE is used for interrupt management of LPAR.
- A Logical PPE object is created in syscall 0x10005. It' used e.g. in Process 9 during LPAR construction.
- syscall 0x10007 activates a Logical PPE object
- 0x67F0(HSPRG0) - pointer to currently active Logical PPE object (in HV dump it points to Linux PPE object naturally because the dump was made on Linux, so Linux LPAR was active at that time)
- E.g. lv1_get_logical_ppe_id, lv1_start_ppe_periodic_tracer and lv1_set_ppe_periodic_tracer_frequency grab the currently active Logical PPE object
vtable
0x00357DF0 (3.15)
Member variables
offset 0x90 - pointer to an object that contains VIRQ-Outlet mapping table for thread 0
offset 0x98 - pointer to an object that contains VIRQ-Outlet mapping table for thread 1
Objects
Here is the list of Logical PPE objects i found in HV 3.15.
Address in HV dump | LPAR id | PPE id |
---|---|---|
0x0069C7F0 | 1 | 1 |
0x007A8900 | 2 | 1 |
Virtual IRQ - Outlet Mapping
- HV maintains 2 tables per PPE that map a VIRQ to an Outlet object.
- The table has 256 entries and is indexed by VIRQ.
- Each entry is a pointer to Outlet object.
- Each Logical PPE object has 2 tables, one for each thread of Cell CPU.
LPAR 1 PPE 1 Thread 0
0x0069C990 (3.15) - address of VIRQ-Outlet table for LPAR 1 PPE 1 Thread 0 (not empty)
VIRQ | Address of Outlet object in HV dump | Description |
---|---|---|
58 | 0x00090D10 | - |
59 | 0x006BAC50 | - |
60 | 0x006B3ED0 | FLASH storage device / Storage device notification for LPAR 1 |
61 | 0x00697E70 | VUART interrupts |
62 | 0x001C8F20 | - |
LPAR 1 PPE 1 Thread 1
0x0069D9B0 (3.15) - address of VIRQ-Outlet table for LPAR 1 PPE 1 Thread 1 (empty)
LPAR 2 PPE 1 Thread 0
0x000A06B0 (3.15) - address of VIRQ-Outlet table for LPAR 2 PPE 1 Thread 0 (not empty)
VIRQ | Address of Outlet object in HV dump | Description |
---|---|---|
20 | 0x003AA210 | - |
21 | 0x003AFEC0 | - |
22 | 0x001FC010 | - |
23 | 0x003A8E50 | - |
24 | 0x001FFED0 | SPE 0 Class 0 Interrupt |
25 | 0x003AE160 | SPE 0 Class 1 Interrupt |
26 | 0x003AE350 | SPE 0 Class 2 Interrupt |
27 | 0x003AB100 | SPE 1 Class 0 Interrupt |
28 | 0x003AB2F0 | SPE 1 Class 1 Interrupt |
29 | 0x003AB4E0 | SPE 1 Class 2 Interrupt |
30 | 0x003AA6A0 | SPE 2 Class 0 Interrupt |
31 | 0x003AA890 | SPE 2 Class 1 Interrupt |
32 | 0x003AAA80 | SPE 2 Class 2 Interrupt |
33 | 0x003B44A0 | SPE 3 Class 0 Interrupt |
34 | 0x003B4690 | SPE 3 Class 1 Interrupt |
35 | 0x003B4AD0 | SPE 3 Class 2 Interrupt |
36 | 0x003B5300 | SPE 4 Class 0 Interrupt |
37 | 0x003B54F0 | SPE 4 Class 1 Interrupt |
38 | 0x003B56E0 | SPE 4 Class 2 Interrupt |
39 | 0x003AE7C0 | SPE 5 Class 0 Interrupt |
40 | 0x003AE9B0 | SPE 5 Class 1 Interrupt |
41 | 0x003AEBA0 | SPE 5 Class 2 Interrupt |
42 | 0x003B2040 | Storage device notification for LPAR 2 |
43 | 0x003AEE30 | VUART interrupts |
44 | 0x001FEAA0 | - |
45 | 0x001FEED0 | HDD storage device |
46 | 0x003B5E20 | - |
47 | 0x003B7040 | - |
48 | 0x003B9B40 | - |
49 | 0x003B3A40 | - |
50 | 0x003BACA0 | Gelic device |
51 | 0x003BAE10 | UNKNOWN storage device |
52 | 0x003B8350 | - |
LPAR 2 PPE 1 Thread 1
0x007A89E0 (3.15) - address of VIRQ-Outlet table for LPAR 2 PPE 1 Thread 1 (not empty)
VIRQ | Address of Outlet object in HV dump | Description |
---|---|---|
16 | 0x003B2480 | - |
17 | 0x003B2590 | - |
18 | 0x003B26A0 | - |
19 | 0x003B27B0 | - |
IRQ State Bitmap
- There is one IRQ State Bitmap (256 bits = 32 bytes) per thread of Logical PPE
- HSPRG0 value is per thread, so there are 2 HSPRG0 values in HV dump !!!
- The IRQ State Bitmap of a thread is stored at -0x68E0(HSPRG0)
- When an Event or Interrupt happens then the bitmap at 0x68E0(HSPRG0) is updated
- The physical address of LPAR's IRQ State Bitmap of thread is stored at offset -0x68C0(HSPRG0)
- The address of LPAR's IRQ State Bitmap is passed to Hypervisor through HV call lv1_configure_irq_state_bitmap
- lv1_detect_pending_interrupts returns value of current IRQ State Bitmap.
- The IRQ State Bitmap is updated if an Outlet object is assigned to VIRQ and when Outlet generates an event
- After IRQ State Bitmap update, it's copied to LPAR's IRQ State Bitmap and a hardware interrupt is generated so that LPAR can read it's IRQ State Bitmap and handle interrupts.
- So, IRQ State Bitmap is stored twice, once in HV and once in LPAR, just like VUART IRQ Bitmap.
- GameOS IRQ state bitmap is stored at address SPRG0 + 0x1C0 and of size 64 bytes (256 bits state + 256 bits mask) per thread of Cell CPU. So there are 2 IRQ state bitmaps.
0x8941FC0 - physical address of LPAR's IRQ State Bitmap for Thread 0 of LINUX LPAR
0x8948FC0 - physical address of LPAR's IRQ State Bitmap for Thread 1 of LINUX LPAR
System Controller (SC or SYSCON)
- Data received from SC is sent to a VUART
- lv1_get_rtc and syscall 0x10036 communicate with SC VUART 4.
VUART Table
- Address of SC VUART Table - 0x00610410 (3.15).
- There are 5 VUARTs for SC in HV 3.15
Here is the SC VUART table from HV 3.15:
Index | Address of VUART object in HV dump | Description |
---|---|---|
0 | 0x0060FD20 | This VUART is connected with the VUART 0 (/dev/sc0) of LPAR 1 |
1 | 0x0060FE20 | This VUART is connected with the VUART 1 (/dev/sc1) of LPAR 1 |
2 | 0x0060FF20 | This VUART is not connected to some peer VUART but i guess that it should be connected to VUART 2 (/dev/sc2) of LPAR1 |
3 | 0x006124E0 | This VUART is connected with the VUART 3 (/dev/sc3) of LPAR 1 |
4 | 0x00612DF0 | lv1_get_rtc and syscall 0x10036 communicate with this VUART. |
Interrupt Handling
spider_sc_interrupt_handler - 0x0020A68C (3.15)
Methods
sc_vuart_4_get_peer_vuart - 0x002ED384 (3.15)
sc_send - 0x0020A908 (3.15)
sc_receive - 0x0020A354 (3.15)
sc_vuart_rx_trigger_callback - 0x002ED470 (3.15)
lv1_get_rtc
- lv1_get_rtc communicates with SC VUART 4.
- 20 bytes are written to the peer VUART of SC VUART 4.
- After a request is sent to SC VUART 4, lv1_get_rtc busy waits until SC VUART 4 receive data buffer is not empty.
- When SC VUART 4 receive data buffer is not empty, lv1_get_rtc reads 24 bytes from the VUART.
SYSCON Protocol
- I was able to enable SYSCON Manager debug messages in HV Process 5
- Messages sent to SYSCON are at least 0x10 bytes of size. SC VUARTs check it before sending the messages to SYSCON.
- The header size of the SYSCON messages is 0x10 bytes.
Packet Header
- Packet header is of size 0x10 bytes.
- At offset 0x6 of SYSCON packet is the header checksum which is of size 2 bytes.
- The header checkum is just a sum of first 6 header bytes and 0x8000 constant
- The 2nd byte in every SYSCON message has to be 1 or else the function sc_send fails.
- The word at offset 0x8 is the SC VUART index.
- The half-words at offset 0xC and 0xE have to be equal or the function sc_send fails.
struct sc_hdr { uint8_t field0; uint8_t field1; /* always 1 */ uint8_t field2[4]; uint16_t cksum; /* header checksum */ uint32_t index; /* syscon index (0 - /dev/sc0, 1 - /dev/sc1, 2 - /dev/sc2, 3 - /dev/sc3) */ uint16_t size1; /* body size */ uint16_t size2; /* body size */ };
Calculating Packet Header Checksum
/* calculating SC packet header checksum */ /* * sc_hdr_cksum */ uint16_t sc_hdr_cksum(struct sc_hdr *sc_hdr) { uint8_t *ptr; uint32_t sum; ptr = (uint8_t *) sc_hdr; sum = 0; for (i = 0; i < 6; i++) sum += *ptr++; sum += 0x8000; return sum & 0xffff; } struct sc_hdr sc_hdr; memset(&sc_hdr, 0, sizeof(sc_hdr)); sc_hdr.cksum = sc_hdr_cksum(sc_hdr); /* fill sc header here */ sc_hdr.cksum = sc_hdr_cksum(sc_hdr);
Packet Body
- Packet body follows packet header
- Packet body size is stored at offset 0xC and 0xE in packet header and is of size 2 bytes
Reading SYSCON EPROM (NVS Service)
Here is a command which is sent to SYSCON to read 1 byte of EPROM at offset 0x48C07 (Product Mode):
0x14 0x01 0x00 0x00 0x00 0x00 0x80 0x15 0x00 0x00 0x00 0x00 0x00 0x04 0x00 0x04 0x20 0x02 0x07 0x01
And here is the response to the above request:
0x14 0x01 0x00 0x00 0x00 0x00 0x80 0x15 0x00 0x00 0x00 0x03 0x00 0x05 0x00 0x05 0x00 0x02 0x07 0x01 0xff
PCI Bus Power
- Used by PS2EMU System Manager in HV process 9 when PS2 EMU is booted
PCI Bus Power On
Request to SC1:
0x10 0x01 0x00 0x00 0x00 0x00 0x80 0x11 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x02 0x31 0x01
PCI Bus Power Off
Request to SC1:
0x10 0x01 0x00 0x00 0x00 0x00 0x80 0x11 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x02 0x31 0x00
Ring Buzzer
Request:
0x16 0x01 0x00 0x00 0x00 0x00 0x80 0x17 0x00 0x00 0x00 0x00 0x00 0x08 0x00 0x08 0x20 0x00 0x00 0x00 0x00 0x00 0x00 0x00