Editing Hypervisor Reverse Engineering

Jump to navigation Jump to search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
<span style="background:red; color:#ffffff;">Warning, this page is way too long and is voted to be split into seperate sections</span>
== 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</b>&nbsp;&#33;&#33;&#33;
= Difference between Debug Firmware HV and Retail HV =
There is a HSPRG0 array at 0x8(-0x69A0(HSPRG0)) + 0x20.
 
== LPAR  
There is no difference between debug firmware lv1.self and retail firmware lv1.self
LPAR = Logical Partition
The differences reside on the repository nodes loaded because of policies/flags.
lpar1 starts at 0x&lt;unknown&gt;, and its belived to be the memory space wherre 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.  
[http://www.mirrorcreator.com/files/1DKLUPMC/160_192_341_355_--CEX_DECR_-_LV1.rar_links DECR/Tool + CEX/Retail LV1.self 1.60 1.92 3.41 3.55]
 
= HSPRG  =
 
*The hypervisor stores a pointer to some structures per LPAR in HSPRG0 register.  
*'''There are actually 2 HSPRG0 values: one for each thread of Cell CPU'''&nbsp;!!!
*There is a HSPRG0 array at 0x8(-0x69A0(HSPRG0)) + 0x20.
 
= LPAR =
 
LPAR = Logical Partition  
 
lpar1 starts at 0x&lt;unknown&gt;, and it's believed to be the memory space where lv1 stores its variables, flags and other data.  
 
lpar2 starts at 0x80000000000 and it's believed to be the memory space where lv2 stores its variables, flags and other data.  
 
<br>
 
The pointer to active LPAR is stored at -0x67E8(HSPRG0).  
The pointer to active LPAR is stored at -0x67E8(HSPRG0).  
 
=== vtable ===
== vtable ==
 
0x0033CA40 (3.15)  
0x0033CA40 (3.15)  
 
=== Member variables ===
== Member variables ==
*offset 0x38 - some pointer  
 
*offset 0x50 - LPAR id (8 bytes)  
offset 0x38 - some pointer  
*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 0x50 - LPAR id (8 bytes)  
*offset 0x7C - number of 64-bit words in VAS id bitmap(4 bytes)  
 
== Interrupt handling ==
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).  
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)  
0x00001930 (3.15 and 2.60)  


== Interrupt vector tables ==
=== Interrupt vector tables ===
 
There are 2 interrupt vector tables. One for each thread. The pointer to these tables is at -0x6950(HSPRG0).  
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 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)
offset 0x10 - thread register offset (8 bytes)  
 
</p><h3><span class="mw-headline" id="Interrupt_vector_table_entry"> Interrupt vector table entry  </span></h3><p>offset 0x0 - pointer to interrupt handler  
offset 0x18 - start of interrupt vector table (19 entries, each entry 32 bytes)  
</p><p>offset 0x8 - TOC  
 
</p><p>offset 0x10 - 0  
=== Interrupt vector table entry  ===
</p><p>offset 0x18 - parameter to interrupt handler  
 
</p><h3><span class="mw-headline" id="Interrupt_handlers"> Interrupt handlers  </span></h3><h4><span class="mw-headline" id="Spurious_interrupt_handler"> Spurious interrupt handler  </span></h4><p>0x002BC174 (3.15)  
offset 0x0 - pointer to interrupt handler  
</p><h4><span class="mw-headline" id="RSX"> RSX  </span></h4><p>0x00219A44 (3.15)  
 
</p><p>0x002176FC (2.60)  
offset 0x8 - TOC  
</p><h4><span class="mw-headline" id="SB_bus"> SB bus  </span></h4><p>0x002B9CC4 (3.15)  
 
</p><h4><span class="mw-headline" id="I.2FO_address_translation"> I/O address translation  </span></h4><p>0x002CD7D8 (3.15)  
offset 0x10 - 0  
</p><p>0x002C9214 (2.60)  
 
</p><h4><span class="mw-headline" id="Performance_monitor"> Performance monitor  </span></h4><p>0x002F0584 (3.15)  
offset 0x18 - parameter to interrupt handler  
</p><p>0x002EB1B0 (2.60)  
 
</p><h4><span class="mw-headline" id="Token_manager"> Token manager  </span></h4><p>0x002BBA9C (3.15)  
=== Interrupt handlers  ===
</p><p>0x002B754C (2.60)  
 
</p><h1><span class="mw-headline" id="HV_call"> HV call  </span></h1><ul><li>The address of HV table is stored at -0x6FC8(HSPRG0).  
==== Spurious interrupt handler  ====
</li><li>The address of HV table size is stored at -0x6FD0(HSPRG0).
 
</li></ul><h2><span class="mw-headline" id="HV_call_2"> HV call  </span></h2>
0x002BC174 (3.15)  
{|  class="wikitable FCK&#95;_ShowTableBorders"
 
!  Id
==== RSX  ====
!  Name
 
!  Description
0x00219A44 (3.15)  
|-
 
|  62
0x002176FC (2.60)  
|  lv1_undocumented_function_62
 
|  SPE (isolation, it updates a SLB entry, writes to SLB_Index, SLB_VSID, SLB_ESID and SLB_Invalidate_Entry registers)
==== SB bus  ====
|-
 
|  89
0x002B9CC4 (3.15)  
|  lv1_undocumented_function_89
 
|  SPE (writes to MFC_TLB_Invalidate_Entry register)
==== I/O address translation  ====
|-
 
|  99
0x002CD7D8 (3.15)  
|  lv1_authenticate_program_segment
 
|  SPE (isolation, syscall 0x10043, syscall 0x10042, syscall 0x1004A)
0x002C9214 (2.60)  
|-
 
|  102
==== Performance monitor  ====
|  lv1_undocumented_function_102
 
|  Returns current TB ticks
0x002F0584 (3.15)  
|-
 
|  137
0x002EB1B0 (2.60)  
|  lv1_undocumented_function_137
 
| SPE
==== Token manager  ====
|-
 
|  138
0x002BBA9C (3.15)  
|  lv1_undocumented_function_138
 
|  SPE
0x002B754C (2.60)  
|-
 
|  167
= HV call  =
| lv1_undocumented_function_167
 
|  SPE (isolation, reads from SPU_Out_Intr_Mbox and MFC_CNTL registers)
*The address of HV table is stored at -0x6FC8(HSPRG0).  
|-
*The address of HV table size is stored at -0x6FD0(HSPRG0).
|  168
 
|  lv1_undocumented_function_168
== HV call  ==
|  SPE (isolation, writes to MFC_CNTL register)
''editorial note: The table listed here was moved/merged to a seperate page : [[HV Syscalls]]''
|-
 
|  195
=== Initializing HV Call Table ===
|  lv1_undocumented_function_195
 
|  WLAN Gelic device
==== set_lv1_hvcall_table ====
|-
 
|  196
0x002C02B4 (3.41)
| lv1_undocumented_function_196
 
|  WLAN Gelic device
0x002C1F04 (3.15)
|-  
 
|  200
0x002C2B4C (3.55)
|  lv1_undocumented_function_200
 
|  SPE (isolation)
This function sets pointer to HV Call Table and the size of HV Call Table in HSPRG context of a LPAR.
|-
 
|  201
==== set_lv1_hvcall_table_entry_invalid ====
|  lv1_undocumented_function_201
 
|  SPE (isolation)
0x002C1F28 (3.15)
|-
 
|  209
0x002C02D8 (3.41)
|  lv1_undocumented_function_209
 
|  SPE (isolation)
0x002C2B70 (3.55)
|-  
 
|  250
This function initializes an entry in HV Call Table to the Invalid HV Call function.
|  lv1_undocumented_function_250
 
|  Storage device
== Memory HV call ==
|-  
 
|  251
*All memory HV calls branch to '''lv1_mm_call'''
|  lv1_undocumented_function_251
*'''lv1_mm_call''' has it's own function table
| Storage device
*Memory HV call number = HV call number
|-
 
|  252
=== Memory HV call table ===
|  lv1_undocumented_function_252
 
| Storage device
*Each entry is a pointer to a function TOC entry.
|-
*table size = 256
|  253
 
|  lv1_undocumented_function_253
0x00364208 (3.15)
|  Storage device
 
|}<h3><span class="mw-headline" id="Initializing_HV_Call_Table"> Initializing HV Call Table </span></h3><h4><span class="mw-headline" id="set_lv1_hvcall_table"> set_lv1_hvcall_table </span></h4><p>0x002C02B4 (3.41)
0x00362308 (3.41)
</p><p>0x002C1F04 (3.15)
 
</p><p>0x002C2B4C (3.55)
0x00366088 (3.55)
</p><p>This function sets pointer to HV Call Table and the size of HV Call Table in HSPRG context of a LPAR.
 
</p><h4><span class="mw-headline" id="set_lv1_hvcall_table_entry_invalid"> set_lv1_hvcall_table_entry_invalid </span></h4><p>0x002C1F28 (3.15)
=== Memory HV calls ===
</p><p>0x002C02D8 (3.41)
 
</p><p>0x002C2B70 (3.55)
lv1_map_htab - 0x002D595C (3.15)
</p><p>This function initializes an entry in HV Call Table to the Invalid HV Call function.
 
</p><h2><span class="mw-headline" id="Memory_HV_call"> Memory HV call  </span></h2><ul><li>All memory HV calls branch to <b>lv1_mm_call</b></li><li><b>lv1_mm_call</b> has it's own function table
lv1_unmap_htab - 0x002D56B8 (3.15)  
</li><li>Memory HV call number = HV call number
 
</li></ul><h3><span class="mw-headline" id="Memory_HV_call_table"> Memory HV call table  </span></h3><ul><li>Each entry is a pointer to a function TOC entry.
lv1_allocate_memory - 0x002D72F0 (3.15)
</li><li>table size = 256
 
</li></ul><p>0x00364208 (3.15)
lv1_release_memory - 0x002D66A4 (3.15)  
</p><p>0x00362308 (3.41)
 
</p><p>0x00366088 (3.55)
lv1_query_logical_partition_address_region_info - 0x002C9B24 (3.15)
</p><h3><span class="mw-headline" id="Memory_HV_calls"> Memory HV calls  </span></h3><p>lv1_map_htab - 0x002D595C (3.15)  
 
</p><p>lv1_unmap_htab - 0x002D56B8 (3.15)  
lv1_create_repository_node - 0x002DD014 (3.15)  
</p><p>lv1_allocate_memory - 0x002D72F0 (3.15)  
 
</p><p>lv1_release_memory - 0x002D66A4 (3.15)  
lv1_get_repository_node_value - 0x002DD260 (3.15)
</p><p>lv1_query_logical_partition_address_region_info - 0x002C9B24 (3.15)  
 
</p><p>lv1_create_repository_node - 0x002DD014 (3.15)  
lv1_undocumented_function_231 - 0x0030B560 (3.15)
</p><p>lv1_get_repository_node_value - 0x002DD260 (3.15)  
 
</p><p>lv1_undocumented_function_231 - 0x0030B560 (3.15)  
= System call =
</p><h1><span class="mw-headline" id="System_call"> System call  </span></h1><p>HV Processes do not use HV calls. They use syscalls only.
 
</p><h2><span class="mw-headline" id="System_call_handler"> System call handler  </span></h2><p>0x002974D8 (3.15)  
HV Processes do not use HV calls. They use syscalls only.
</p><p>0x00292F6C (2.60)  
 
</p><p>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 handler ==
</p><h2><span class="mw-headline" id="System_call_table_0_-_36"> System call table 0 - 36  </span></h2><p>0x0035FAE8 (3.15)  
 
</p><p>0x00358ED0 (2.60)
0x002974D8 (3.15)
</p><h3><span class="mw-headline" id="System_call_numbers"> System call numbers  </span></h3><p>0x1 - getpid(void)  
 
</p><p>0x2 - getppid(void)  
0x00292F6C (2.60)
</p><p>0x3 - fork(void)
 
</p><p>0x4 - exit
There are 2 system call tables in HV. The first one stores system calls 0 - 36. The second one stores system calls 0x10000 - 0x100FF.
</p><p>0x5 - exec(filename)  
 
</p><p>0x6 - wait(status)  
== UX System call table 0 - 36  ==
</p><p>0x7 - open(filename)
 
</p><p>0x8 - close(fd)  
0x0035FAE8 (3.15)  
</p><p>0x9 - read
 
</p><p>0xA - write
0x00358ED0 (2.60)  
</p><p>0xB - seek
 
</p><p>0xC - unlink(filename)  
=== System call numbers  ===
</p><p>0xD - signal
0x0 - void eosh(void) //end_of_signal_handling(void)  
</p><p>0xE - kill(pid, signal type)  
 
</p><p>0xF - brk
0x1 - pid_t getpid(void)
</p><p>0x10 - socket(af, type, protocol) (supports only address family 0x1F, type 0x0 and protocol 0x0)  
 
</p><p>0x11 - bind
0x2 - pid_t getppid(void)
</p><p>0x12 - listen(fd, backlog)
 
</p><p>0x13 - accept
0x3 - pid_t fork(void)  
</p><p>0x14 - connect
 
</p><p>0x15 -&nbsp;?
0x4 - void exit(int status)  
</p><p>0x16 - pause(void)  
 
</p><p>0x17 - sleep(seconds)
0x5 - void execv(const char *path, char *const argv[])
</p><p>0x18 - mmap(addr, size, prot, flags, fd, offset)  
 
</p><p>0x19 - munmap
0x6 - void wait(int *status)
</p><p>0x1A - some fs func for directories, perhaps readdir
 
</p><p>0x1B -&nbsp;?
0x7 - int open(const char *path, int flags)
</p><p>0x1C - map_pages (used for alloc)  
 
</p><p>0x1D - unmap_pages (used for free)
0x8 - void close(int fd)
</p><p>0x1E - select
 
</p><p>0x1F - getcwd
0x9 - ssize_t read(int fd, void *buf, unsigned int nbyte)
</p><p>0x20 -&nbsp;?
 
</p><p>0x21 - alarm
0xA - ssize_t write(int fd, const void *buf, unsigned int nbyte)
</p><p>0x22 - ioctl
 
</p><p>0x23 - _map_pages
0xB - void lseek(int fd, long offset, int whence)
</p><p>0x24 - _unmap_pages
 
</p><h2><span class="mw-headline" id="System_call_table_0x10000_-_0x100FF"> System call table 0x10000 - 0x100FF  </span></h2><p>0x0035DE78 (3.15)  
0xC - unlink(const char *path)  
</p><p>0x00357260 (2.60)
 
</p><h3><span class="mw-headline" id="System_call_numbers_2"> System call numbers  </span></h3><p>0x10000 - allocate_memory_region(LPAR id, size, log2 of page size,&nbsp;?,&nbsp;?)
0xD - void signal(int sig, void *func(int sig))
</p><p>0x10001 - lpar_query_address_region_info
 
</p><p>0x10002 - lpar_memory_addr_to_phys_addr(LPAR id, LPAR address, physical addr)
0xE - int kill(int pid, int signal_type)  
</p><p>0x10005 - construct_logical_pu
 
</p><p>0x10007 - activate_logical_pu(LPAR id, PPE id)
0xF - int brk(void *addr)  
</p><p>0x10009 - construct_logical_partition(0, LPAR id, outlet)
 
</p><p>0x1000E - release_memory_region(LPAR id, memory region address)
0x10 - int socket(int af, int type, int protocol) (supports only address family 0x1F, type 0x0 and protocol 0x0)
</p><p>0x1001A - construct_event_receive_port
 
</p><p>0x10024 - shutdown_logical_partition(LPAR id, shutdown command)
0x11 - int bind(int sockfd , const sockaddr *addr, unsigned int addrlen)  
</p><p>0x10025 - destruct_logical_partition(LPAR id)
 
</p><p>0x10026 - get_logical_partition_info
0x12 - int listen(int sockfd, int backlog)  
</p><p>0x1002C - construct_scheduling_table
 
</p><p>0x1002D - set_scheduling_slot
0x13 - int accept(int sockfd, sockaddr *addr, unsigned int *addrlen)  
</p><p>0x10032 - accesses system console
 
</p><p>0x10036 - accesses system console
0x14 - int connect(int sockfd, const sockaddr *serv_addr, unsigned int addrlen)  
</p><p>0x10040 - construct_spe_type_1(SPE id, shaddow_addr)  
 
</p><p>0x10041 - destruct_spe(SPE id)  
0x15 - void putchar(int c)  
</p><p>0x10042 - decrypt_lv2_self(spe id, LPAR auth id, SELF file image ptr, LPAR memory address)  
 
</p><p>0x10043 - load_spe_module(spe id, SCE module ptr, arg1, arg2, arg3, arg4)  
0x16 - int pause(void)
</p><p>0x10044 - disable_spe_execution  
 
</p><p>0x10045 - set_spe_interrupt_mask
0x17 - int sleep(unsigned int seconds)  
</p><p>0x10046 - read_spe_problem_state_register(spe id, register offset, value)  
 
</p><p>0x10047 - write_spe_problem_state_register(spe id, register offset, value)  
0x18 - int mmap(void *addr, unsigned long size, int prot, int flags, int fd, long offset, void *mapped_addr)
</p><p>0x1004B - disable_spe_loading  
 
</p><p>0x10053 - pmi_set_guest_os_mode
0x19 - int munmap (void *addr, unsigned long size)
</p><p>0x10081 - accesses system console
 
</p><p>0x10084 - construct_virtual_uart(LPAR id, VUART id, VUART data buffer size)
0x1A - int chdir(const char *path)
</p><p>0x10085 - destruct_virtual_uart(LPAR id, VUART id)
 
</p><p>0x10088 - RSX_syscall_10088(LPAR id)
0x1B - void getchar(char *c)
</p><p>0x10089 - RSX_syscall_10089
 
</p><p>0x1008A - RSX_syscall_1008A
0x1C - map_pages(...) (used for alloc)
</p><p>0x100BE - lv1_ioctl
 
</p><p>0x100C0 - create_repository_node(LPAR id)  
0x1D - unmap_pages(...) (used for free)
</p><p>0x100C1 - get_repository_node_value(LPAR id)  
 
</p><p>0x100C2 - modify_repository_node_value(LPAR id)  
0x1E - int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
</p><p>0x100C3 - remove_repository_node_value(LPAR id)  
 
</p><h1><span class="mw-headline" id="Process"> Process  </span></h1><h2><span class="mw-headline" id="Process_table"> Process table  </span></h2><p>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).  
0x1F - getcwd(...)
</p><p>The process table is an array of 32 process table entries.  
 
</p><p>0x0035E850 (3.15)  
0x20 - Not used
</p><p>0x00357C38 (2.60)  
 
</p><h3><span class="mw-headline" id="Process_table_entry"> Process table entry  </span></h3><p>offset 0x0 - process status&nbsp;? (8 bytes)  
0x21 - unsigned int alarm(unsigned int seconds)
</p><p>offset 0x8 - pointer to Process object  
 
</p><h2><span class="mw-headline" id="create_new_proc"> create_new_proc  </span></h2><p>This function creates a new Process object.  
0x22 - int ioctl(int fd, unsigned __int64 request, ...)
</p><p>0x00298E2C (3.15)  
 
</p><p>0x002948BC (2.60)  
0x23 - pme_memalign(...)
</p><h3><span class="mw-headline" id="Parameters"> Parameters  </span></h3><p>r3 - pointer to parent Process object  
 
</p><p>r4 -&nbsp;?  
0x24 - ?
</p><h2><span class="mw-headline" id="copy_user_data"> copy_user_data  </span></h2><p>This function copies data to/from user space.  
 
</p><p>0x00299688 (3.15)  
== PMI System call table 0x10000 - 0x100FF  ==
</p><p>0x00295118 (2.60)  
 
</p><h3><span class="mw-headline" id="Parameters_2"> Parameters  </span></h3><p>r3 - pointer to Process object  
0x0035DE78 (3.15)  
</p><p>r4 - some address in address space of Process  
 
</p><p>r5 - pointer to buffer in HV space  
0x00357260 (2.60)  
</p><p>r6 - size to copy  
 
</p><p>r7 -&nbsp;?  
=== System call numbers  ===
</p><p>r8 - direction of copy (0 - copy from user space,&nbsp;&#33;= 0 - copy to user space)  
 
</p><p>r9 -&nbsp;?  
0x10000 - allocate_memory(LPAR id, size, log2 of page size,&nbsp;?,&nbsp;?) / construct_memory_segment
</p><h2><span class="mw-headline" id="vtable_2"> vtable  </span></h2><p>Processes have no vtables. That means they have no virtual functions.  
 
</p><h2><span class="mw-headline" id="Member_variables_2"> Member variables  </span></h2><p>offset 0x0 - PID (4 bytes)  
0x10001 - query_logical_partition_address_region_info
</p><p>offset 0x8 - pointer to parent Process object  
 
</p><p>offset 0x10 - pointer to AddressSpace object  
0x10002 - translate_logical_partition_to_physical_address(LPAR id, LPAR address, physical addr)  
</p><p>offset 0x30 - pointer to first PThread object of process  
 
</p><p>offset 0x38 - array of signal handlers (192 * 8 bytes)  
0x10003 - map_physical_address_region
</p><p>offset 0x638 - pointer to pointer to ELF image  
 
</p><p>offset 0x640 - start of file table (20 * 24 bytes)  
0x10004 - unmap_physical_address_region
</p><p>offset 0x820 - exit status (4 bytes)  
 
</p><p>offset 0x898 - pointer to Inode object of current directory  
0x10005 - construct_logical_pu
</p><p>offset 0x8A8 - some pointer  
 
</p><h3><span class="mw-headline" id="Signals"> Signals  </span></h3><p>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.  
0x10006 - destruct_logical_pu
</p><p>A process does not have a signal mask. Every thread of a process has it's own signal mask.  
 
</p><h4><span class="mw-headline" id="Signal_constants"> Signal constants  </span></h4><p>0x9 - SIGKILL  
0x10007 - activate_logical_pu(LPAR id, PPE id)  
</p><p>0xE - SIGALRM  
 
</p><p>0x20 - SIGSPUMB  
0x10009 - construct_logical_partition(0, LPAR id, outlet)  
</p><p>0x21 - SIGSPUMB_SL  
 
</p><p>0x22 - SIGSPUSTOP  
0x1000A - get_logical_console_info
</p><p>0x23 - SIGSPUSTOP_SL  
 
</p><p>0x24 - SIGSPUDMA  
0x1000B - get_remote_file_size
</p><p>0x26 - SIGSPUTIMEOUT  
 
</p><p>0x27 - SIGSPUERR  
0x1000C - read_remote_file
</p><p>0x41 - SIGSHUTDOWN  
 
</p><h3><span class="mw-headline" id="File_table"> File table  </span></h3><p>The file table has 20 entries. So, a process can have at most 20 files opened simultaneously. Each entry is 24 bytes large.  
0x1000D - write_remote_file
</p><p>offset 0x0 - entry valid or invalid (1 byte), 0 - invalid, 1 - valid  
 
</p><p>offset 0x8 - pointer to object with File interface  
0x1000E - release_memory_region(LPAR id, memory region address)  
</p><p>offset 0x10 - current file position (8 bytes)  
 
</p><h2><span class="mw-headline" id="Process_EA_to_RA"> Process_EA_to_RA  </span></h2><p>This function translates an effective process address to real address.  
0x1001A - construct_event_receive_port
</p><p>0x00297E08 (3.15)  
 
</p><h2><span class="mw-headline" id="Objects"> Objects  </span></h2><p>Here are the addresses of Process objects i could identify in HV dump 3.15:  
0x1001B - destruct_event_receive_port
</p><ul><li>0x006BB0D0 (PID 0)  
 
</li><li>0x0012C010 (PID 3) - ss_server3.fself  
0x1001C - request_to_connect_event_ports
</li><li>0x000915D0 (PID 5) - ss_server2.fself  
 
</li><li>0x000E4D70 (PID 6) - ss_server1.fself  
0x1001D - connect_event_ports
</li><li>0x0012C8D0 (PID 9) - sysmgr_ss.fself
 
</li></ul><p>Here are the addresses of Process objects i could identify in HV dump 2.60:  
0x1001E - destruct_event_send_port
</p><ul><li>0x006B7580 (PID 0)  
 
</li><li>0x00135F90 (PID 3)  
0x1001F - send_event_externally
</li><li>0x000862D0 (PID 5)  
 
</li><li>0x000A9870 (PID 6)  
0x10020 - get_status_of_event_send_port
</li><li>0x00084B80 (PID 9)
 
</li></ul><h1><span class="mw-headline" id="PThread"> PThread  </span></h1><p>All PThread objects of the same Process object are linked together in a list.  
0x10021 - get_event_port_connection_request
</p><h2><span class="mw-headline" id="vtable_3"> vtable  </span></h2><p>0x003556D8 (3.15)  
 
</p><p>0x0034ECC0 (2.60)  
0x10022 - end_of_control_signal_processing
</p><p>offset 0x60 - pointer to TOC entry of system call handler  
 
</p><h2><span class="mw-headline" id="Member_variables_3"> Member variables  </span></h2><p>offset 0x10 - pointer to next PThread object of Process  
0x10024 - shutdown_logical_partition(LPAR id, shutdown command)
</p><p>offset 0x18 - Thread object  
 
</p><p>offset 0x2B8 -&nbsp;? (4 bytes)  
0x10025 - destruct_logical_partition(LPAR id)  
</p><p>offset 0x2C0 - pointer to TOC of some function  
 
</p><p>offset 0x2C8 - pointer to TOC of some function  
0x10026 - get_logical_partition_info
</p><p>offset 0x348 - some conter (4 bytes)  
 
</p><p>offset 0x3C0 - pointer to Process object that owns PThread object  
0x10027 - read_privilege_set
</p><p>offset 0x3F8 - signal pending mask (3 * 8 bytes = 192 signals)  
 
</p><p>offset 0x440 - ConditionVariable object  
0x10028 - modify_privilege_set
</p><h2><span class="mw-headline" id="Signals_2"> Signals  </span></h2><p>A PThread has it's own signal mask, independant of all other PThreads in the same process.  
 
</p><h2><span class="mw-headline" id="Methods"> Methods  </span></h2><p>wait_for_my_turn(Pthread ptr,&nbsp;?, sleep interruptible flag) = wakeup status - 0x00296FB0 (3.15)  
0x10029 - get_remote_file_size_long_name
</p><h1><span class="mw-headline" id="Thread"> Thread  </span></h1><h2><span class="mw-headline" id="get_current_thread"> get_current_thread  </span></h2><p>This function returns the pointer to current running thread.  
 
</p><p>0x0028B994 (3.15)  
0x1002A - read_remote_file_long_name
</p><p>0x0028744C (2.60)  
 
</p><h2><span class="mw-headline" id="vtable_4"> vtable  </span></h2><p>0x00355750 (3.15)  
0x1002B - write_remote_file_long_name
</p><h2><span class="mw-headline" id="Member_variables_4"> Member variables  </span></h2><p>offset 0x288 - some pointer  
 
</p><p>offset 0x290 - some pointer  
0x1002C - construct_scheduling_table
</p><h1><span class="mw-headline" id="AddressSpace"> AddressSpace  </span></h1><h2><span class="mw-headline" id="vtable_5"> vtable  </span></h2><p>0x003549A0 (3.15)  
 
</p><p>0x0034DF88 (2.60)  
0x1002D - set_scheduling_slot
</p><h2><span class="mw-headline" id="Member_variables_5"> Member variables  </span></h2><p>offset 0x8 - Mutex object  
 
</p><p>offset 0x40 - AddressProtectionDomain object  
0x1002E - load_scheduling_table
</p><p>offset 0x50 - some pointer  
 
</p><p>offset 0xC0 - some counter (4 bytes)  
0x10032 - poweroff
</p><h2><span class="mw-headline" id="AddressSpace_EA_to_RA"> AddressSpace_EA_to_RA  </span></h2><p>0x002874D0 (3.15)  
 
</p><h1><span class="mw-headline" id="AddressProtectionDomain"> AddressProtectionDomain  </span></h1><h2><span class="mw-headline" id="vtable_6"> vtable  </span></h2><p>0x00354980 (3.15)  
0x10033 - get_remote_file_name
</p><h2><span class="mw-headline" id="Member_variables_6"> Member variables  </span></h2><p>offset 0x8 - pointer to previous AddressProtectionDomain object  
 
</p><p>offset 0x10 - pointer to next AddressProtectionDomain object  
0x10034 - allocate_cp_channel
</p><p>offset 0x18 - poiinter to pointer to SLB entries  
 
</p><p>offset 0x20 - pointer to AddressSpace object that owns this object  
0x10035 - release_cp_channel
</p><p>offset 0x34 - pointer to previous ProtectionPage  
 
</p><p>offset 0x3C - pointer to next ProtectionPage  
0x10036 - power_down
</p><p>offset 0x48 - Mutex object  
 
</p><h1><span class="mw-headline" id="ProtectionPage"> ProtectionPage  </span></h1><h2><span class="mw-headline" id="vtable_7"> vtable  </span></h2><p>none  
0x10037 - ?
</p><h2><span class="mw-headline" id="Member_variables_7"> Member variables  </span></h2><p>offset 0x0 - RA (8 bytes)  
 
</p><p>offset 0x8 - EA (4 bytes)  
0x10038 - ?
</p><p>offset 0x10 - pointer to previous ProtectionPage (4 bytes)  
 
</p><p>offset 0x14 - pointer to next ProtectionPage (4 bytes)  
0x10039 - ?
</p><h1><span class="mw-headline" id="Mutex"> Mutex  </span></h1><h2><span class="mw-headline" id="vtable_8"> vtable  </span></h2><p>0x00354D08 (3.15)  
 
</p><p>0x0034E2F0 (2.60)  
0x10040 - construct_spe_type_1(SPE id, shaddow_addr) / construct_logical_spu
</p><h2><span class="mw-headline" id="Member_variables_8"> Member variables  </span></h2><p>offset 0x18 -&nbsp;? (4 bytes)  
 
</p><p>offset 0x1C -&nbsp;? (4 bytes)  
0x10041 - destruct_spe(SPE id) / destruct_logical_spu
</p><h1><span class="mw-headline" id="ConditionVariable"> ConditionVariable </span></h1><h2><span class="mw-headline" id="vtable_9"> vtable  </span></h2><p>0x003549C0 (3.15)  
 
</p><p>offset 0x20 - wait  
0x10042 - decrypt_lv2_self(spe id, LPAR auth id, SELF file image ptr, LPAR memory address)  
</p><h2><span class="mw-headline" id="Member_variables_9"> Member variables  </span></h2><p>offset 0x20 - pointer to Mutex object  
 
</p><h1><span class="mw-headline" id="File_interface"> File interface  </span></h1><h2><span class="mw-headline" id="vtable_10"> vtable  </span></h2><p>offset 0x8 -&nbsp;?  
0x10043 - load_spe_module(spe id, SCE module ptr, arg1, arg2, arg3, arg4)  
</p><p>offset 0x28 - open  
 
</p><p>offset 0x30 - close  
0x10044 - disable_spe_execution  
</p><p>offset 0x38 - read  
 
</p><p>offset 0x40 - write  
0x10045 - read_spu_puint_mb(unsigned long spu_id, unsigned long msg)
</p><p>offset 0x50 - mmap  
 
</p><p>offset 0x58 - ioctl  
0x10046 - read_spe_problem_state_register(spe id, register offset, value) / read_spu_problem_state_area_register
</p><h1><span class="mw-headline" id="StorageRegionFile"> StorageRegionFile </span></h1><p>Flash device file class.  
 
</p><h2><span class="mw-headline" id="vtable_11"> vtable  </span></h2><p>0x003569F8 (3.15)  
0x10047 - write_spe_problem_state_register(spe id, register offset, value) / write_spu_problem_state_area_register
</p><h1><span class="mw-headline" id="VUARTFile"> VUARTFile  </span></h1><p>VUART device file class.  
 
</p><h2><span class="mw-headline" id="vtable_12"> vtable  </span></h2><p>0x00356458 (3.15)  
0x1004A - install_revoke_list
</p><h1><span class="mw-headline" id="STDLCFile"> STDLCFile  </span></h1><p>Console device file class.  
 
</p><h2><span class="mw-headline" id="vtable_13"> vtable  </span></h2><p>0x003561F8 (3.15)  
0x1004B - disable_spe_loading  
</p><h2><span class="mw-headline" id="Member_variables_10"> Member variables  </span></h2><p>offset 0x20 - reference counter (8 bytes)  
 
</p><p>offset 0x28 - free buffer space&nbsp;? (8 bytes)  
0x1004C - install_access_control_table?
</p><h1><span class="mw-headline" id="SocketFile"> SocketFile  </span></h1><h2><span class="mw-headline" id="vtable_14"> vtable  </span></h2><p>0x00355DB0 (3.15)  
 
</p><p>offset 0xB0 - bind  
0x1004D - get_storage_status?
</p><h1><span class="mw-headline" id="RegionManager"> RegionManager  </span></h1><h2><span class="mw-headline" id="vtable_15"> vtable  </span></h2><p>0x00355F80 (3.15)  
 
</p><h1><span class="mw-headline" id="Inode"> Inode  </span></h1><h2><span class="mw-headline" id="DirectoryInode"> DirectoryInode  </span></h2><h3><span class="mw-headline" id="vtable_16"> vtable  </span></h3><p>0x00355788 (3.15)  
0x1004E - get_region_table_bits?
</p><p>offset 0x20 - link  
 
</p><p>offset 0x28 - unlink  
0x1004F - commit_region_update?
</p><h2><span class="mw-headline" id="get_root_inode"> get_root_inode  </span></h2><p>This function returns the pointer to the Inode object of the root directory.  
 
</p><p>0x0029C124 (3.15)  
0x10050 - abort_region_update?
</p><p>0x00297BB4 (2.60)  
 
</p><h2><span class="mw-headline" id="vtable_17"> vtable  </span></h2><p>0x00334E50 (3.15)  
0x10051 - set_storage_tampered?
</p><p>offset 0x30 - lookup  
 
</p><h1><span class="mw-headline" id="File_system"> File system  </span></h1><h2><span class="mw-headline" id="Console_device_file_objects"> Console device file objects  </span></h2><p>Here is the list of console device file objects i found in HV dump 3.15:  
0x10053 - pmi_set_guest_os_mode
</p><ul><li>console
 
</li></ul><h3><span class="mw-headline" id="vtable_18"> vtable  </span></h3><p>0x003561F8 (3.15)  
0x1007F - pause
</p><h2><span class="mw-headline" id="Flash_device_file_objects"> Flash device file objects  </span></h2><p>Here is the list of flash device file objects i found in HV dump 3.15:  
 
</p><ul><li>/dev/eflash0  
0x10080 - get_total_execution_time
</li><li>/dev/eflash1  
 
</li><li>/dev/rflash0  
0x10081 - reset
</li><li>/dev/rflash1  
 
</li><li>/dev/rflash_1x  
0x10083 - construct_logical_rsx
</li><li>/dev/rflash_1xp
 
</li></ul><h3><span class="mw-headline" id="vtable_19"> vtable  </span></h3><p>0x003569F8 (3.15)  
0x10084 - construct_virtual_uart(LPAR id, VUART id, VUART data buffer size)  
</p><h2><span class="mw-headline" id="IOIF_device_file_objects"> IOIF device file objects  </span></h2><p>Here is the list of IOIF device file objects i found in HV dump 3.15:  
 
</p><ul><li>/dev/ioif0
0x10085 - destruct_virtual_uart(LPAR id, VUART id)  
</li></ul><h3><span class="mw-headline" id="vtable_20"> vtable  </span></h3><p>0x00356688 (3.15)  
 
</p><h3><span class="mw-headline" id="Member_variables_11"> Member variables  </span></h3><p>0x360 = MMIO base address  
0x10086 - establish_virtual_uart_channel
</p><h2><span class="mw-headline" id="SD_detector_device_file_objects"> SD detector device file objects  </span></h2><p>Here is the list of SD detector device file objects i found in HV dump 3.15:  
 
</p><ul><li>/dev/sd_detector
0x10088 - RSX_syscall_10088(LPAR id)  
</li></ul><h3><span class="mw-headline" id="vtable_21"> vtable  </span></h3><p>0x00356B48 (3.15)  
 
</p><h2><span class="mw-headline" id="NET_device_file_objects"> NET device file objects  </span></h2><p>Here is the list of NET device file objects i found in HV dump 3.15:  
0x10089 - RSX_syscall_10089
</p><ul><li>/dev/net0
 
</li></ul><h3><span class="mw-headline" id="vtable_22"> vtable  </span></h3><p>0x00356DE8 (3.15)  
0x1008A - RSX_syscall_1008A
</p><h2><span class="mw-headline" id="INODES"> INODES  </span></h2><p><b>INODE OBJECT</b></p><p>+0x04: previos inode  
 
</p><p>+0x08: next inodes  
0x100BE - lv1_ioctl
</p><p>+ 0x38:&nbsp; path  
 
</p><p>+ 0x358: childer_inode  
0x100C0 - create_repository_node(LPAR id)  
</p><p><br /></p><p><b>MFS_ROOT_INODE</b></p><p>(2.60) 0x3580B0  
 
</p><p>+ 0x60 = ROOT_INODE  
0x100C1 - get_repository_node_value(LPAR id)
</p><p><br /></p><p><b>SOME ADDRESSES IN 2.60</b></p><p>0x60C010: "/dev" inode  
 
</p><p>0x6AA580: "/proc" inode  
0x100C2 - modify_repository_node_value(LPAR id)
</p><p>using linked list you can follow all inodes  
 
</p><h1><span class="mw-headline" id="Repository"> Repository  </span></h1><ul><li>Each LPAR has it's own node repository  
0x100C3 - remove_repository_node(LPAR id)
</li><li>Repository nodes are stored in a hash table which can have several sub-hash tables.
 
</li></ul><h2><span class="mw-headline" id="RepositoryNode"> RepositoryNode  </span></h2><h3><span class="mw-headline" id="vtable_23"> vtable  </span></h3><p>0x00357F58 (3.15)  
= Process  =
</p><h3><span class="mw-headline" id="Member_variables_12"> Member variables  </span></h3><p>offset 0x30 - pointer to next RepositoryNode obj  
 
</p><p>offset 0x38 - 2nd hash value of name (4 bytes)  
== Process table  ==
</p><p>offset 0x40 - 1st field name (8 bytes)  
 
</p><p>offset 0x48 - 2nd field name (8 bytes)  
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).  
</p><p>offset 0x50 - 3rd field name (8 bytes)  
 
</p><p>offset 0x58 - 4th field name (8 bytes)  
The process table is an array of 32 process table entries.
</p><p>offset 0x60 -&nbsp;? (4 bytes)  
 
</p><p>offset 0x68 - 1st field value (8 bytes)  
0x0036C930 (4.30)
</p><p>offset 0x70 - 2nd field value (8 bytes)  
 
</p><h3><span class="mw-headline" id="Hash_Function"> Hash Function  </span></h3><ul><li>The name of a repository node is hashed and 2 hash values (2 32bit values) are produced.  
0x0036C8B0 (4.21)
</li><li>The 1st hash value is used to select a sub-hash table.  
 
</li><li>The 2nd hash value is used to find a sub-hash table bucket.  
0x00365458 (4.11)
</li><li>Repository nodes in a hash bucket are ordered by the 2nd hash value.
 
</li></ul><pre>void hash(unsigned long long n1,
0x0035F8D0 (3.55)
unsigned long long n2,
 
unsigned long long n3,
0x0035C550 (3.41)
unsigned long long n4,
 
unsigned long *h1,
0x0035E850 (3.15)
unsigned long *h2)
 
0x00357C38 (2.60)
 
=== Process table entry  ===
 
offset 0x0 - process status&nbsp;? (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 -&nbsp;?  
 
== 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 -&nbsp;?  
 
r8 - direction of copy (0 - copy from user space,&nbsp;!= 0 - copy to user space)  
 
r9 -&nbsp;?  
 
== 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)
 
In JIG 2.43:
*(PID3) <- ss_server3
*(PID4) <- ss_sc_init_pu
*(PID5) <- ss_server2
*(PID6) <- ss_server1
*(PID7) <- factory_data_mngr_server
*(PID8) <- updater_frontend
 
(see [http://pastie.org/pastes/9407461/text?key=f6bk5lof0g4bgeu6xrn5ua this])
 
= 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 -&nbsp;? (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,&nbsp;?, 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 0x0 - pointer to previous AddressProtectionDomain object  
 
offset 0x8 - pointer to next AddressProtectionDomain object  
 
offset 0x10 - poiinter to pointer to SLB entries  
 
offset 0x18 - pointer to AddressSpace object that owns this object  
 
offset 0x2A - pointer to previous ProtectionPage  
 
offset 0x34 - pointer to next ProtectionPage  
 
offset 0x40 - 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 -&nbsp;? (4 bytes)  
 
offset 0x1C -&nbsp;? (4 bytes)  
 
= ConditionVariable =
 
== vtable  ==
 
0x003549C0 (3.15)  
 
offset 0x20 - wait  
 
== Member variables  ==
 
offset 0x20 - pointer to Mutex object  
 
= File interface  =
 
== vtable  ==
 
offset 0x8 -&nbsp;?  
 
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&nbsp;? (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:&nbsp; path  
 
+ 0x358: childer_inode  
 
<br>
 
'''MFS_ROOT_INODE'''
 
(2.60) 0x3580B0  
 
+ 0x60 = ROOT_INODE  
 
<br>
 
'''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 -&nbsp;? (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.
<pre>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 long h;
    unsigned long hl;
unsigned long hl;
 
h = ((((n1 ^ n4) &gt;&gt; 32) ^ (n2 ^ n3)) ^ (((n2 ^ n3) &gt;&gt; 32) ^ (n1 ^ n4))) &amp; ~0xC0000000ULL;
    h = ((((n1 ^ n4) &gt;&gt; 32) ^ (n2 ^ n3)) ^ (((n2 ^ n3) &gt;&gt; 32) ^ (n1 ^ n4))) &amp; ~0xC0000000ULL;
*h1 = h &amp; 0xFFFFFFFFULL;
 
h = ((h &amp; 0x55555555ULL) &lt;&lt; 1) &#124; ((h &amp; 0xAAAAAAAAULL) &gt;&gt; 1);
    *h1 = h &amp; 0xFFFFFFFFULL;
h = ((h &amp; 0x33333333ULL) &lt;&lt; 2) &#124; ((h &amp; 0xCCCCCCCCULL) &gt;&gt; 2);
 
h = ((h &amp; 0xF0F0F0FULL) &lt;&lt; 4) &#124; ((h &amp; 0xF0F0F0F0ULL) &gt;&gt; 4);
    h = ((h &amp; 0x55555555ULL) &lt;&lt; 1) | ((h &amp; 0xAAAAAAAAULL) &gt;&gt; 1);
hl = (h &lt;&lt; 8) &#124; ((h &amp; 0xFF000000ULL) &gt;&gt; 24);
 
hl = (hl &amp; ~0xFF000000UL) &#124; ((h &amp; 0xFFULL) &lt;&lt; 24);
    h = ((h &amp; 0x33333333ULL) &lt;&lt; 2) | ((h &amp; 0xCCCCCCCCULL) &gt;&gt; 2);
hl = (hl &amp; ~0x0000FF00UL) &#124; (((h &lt;&lt; 24) &#124; (h &gt;&gt; 8)) &amp; 0x0000FF00ULL);
 
hl &#124;= 0x1;  
    h = ((h &amp; 0xF0F0F0FULL) &lt;&lt; 4) | ((h &amp; 0xF0F0F0F0ULL) &gt;&gt; 4);
*h2 = hl;
 
    hl = (h &lt;&lt; 8) | ((h &amp; 0xFF000000ULL) &gt;&gt; 24);
 
    hl = (hl &amp; ~0xFF000000UL) | ((h &amp; 0xFFULL) &lt;&lt; 24);
 
    hl = (hl &amp; ~0x0000FF00UL) | (((h &lt;&lt; 24) | (h &gt;&gt; 8)) &amp; 0x0000FF00ULL);
 
    hl |= 0x1;  
 
    *h2 = hl;
}
}
</pre>
</pre><h2><span class="mw-headline" id="Repository_nodes_from_HV_3.15"> Repository nodes from HV 3.15  </span></h2><p><a href="/index.php/Dump_of_all_repository_nodes_from_HV_3.15" title="Dump of all repository nodes from HV 3.15">Dump of all repository nodes from HV 3.15</a></p><h2><span class="mw-headline" id="Repository_nodes_from_HV_3.41_dump_made_from_GameOS"> Repository nodes from HV 3.41 dump made from GameOS  </span></h2><p><a href="/index.php/Dump_of_all_repository_nodes_from_HV_3.41_dump_made_from_GameOS" title="Dump of all repository nodes from HV 3.41 dump made from GameOS">Dump of all repository nodes from HV 3.41 dump made from GameOS</a></p><h1><span class="mw-headline" id="Buses"> Buses  </span></h1><h2><span class="mw-headline" id="SB_bus_2"> SB bus  </span></h2><p>type - 4  
== Repository nodes from HV 3.15  ==
</p><p>index - 1  
 
</p><p>num_devices - 4 (repository node says this but there are more devices&nbsp;&#33;&#33;&#33;)  
[http://www.ps3devwiki.com/index.php?title=Repository_Nodes#3.15_Linux Dump of all repository nodes from HV 3.15]
</p><h2><span class="mw-headline" id="Storage_bus"> Storage bus  </span></h2><p>type - 5  
 
</p><p>index - 4  
== Repository nodes from HV 3.41 dump made from GameOS  ==
</p><p>num_devices - 4  
 
</p><h1><span class="mw-headline" id="SB_bus_subsystem"> SB bus subsystem  </span></h1><h2><span class="mw-headline" id="vtable_24"> vtable  </span></h2><p>0x00352600 (3.15)  
[http://www.ps3devwiki.com/index.php?title=Repository_Nodes#3.41_GameOS Dump of all repository nodes from HV 3.41 dump made from GameOS]
</p><h2><span class="mw-headline" id="Member_variables_13"> Member variables  </span></h2><p>offset 0x10 - MMIO memory base address  
 
</p><p>offset 0x20 - array of 16 pointers to SB devices (0 - Gelic device, 1 - USB device)  
= Buses  =
</p><h2><span class="mw-headline" id="Objects_2"> Objects  </span></h2><p>0x00349528 - pointer to pointer to SB bus subsystem object  
 
</p><h2><span class="mw-headline" id="Memory_base_address"> Memory base address  </span></h2><p>0x24000000000  
== SB bus  ==
</p><p>All SB bus device MMIO addresses are relative to this memory address.  
 
</p><h2><span class="mw-headline" id="SB_device_MMIO.2FDMA_memory_region"> SB device MMIO/DMA memory region  </span></h2><h3><span class="mw-headline" id="vtable_25"> vtable  </span></h3><p>0x000x352308 (3.15)  
type - 4  
</p><h3><span class="mw-headline" id="Member_variables_14"> Member variables  </span></h3><p>offset 0x18 - pointer to previous bus memory region object  
 
</p><p>offset 0x20 - pointer to next bus memory region object  
index - 1  
</p><p>offset 0x30 - relative bus memory start address  
 
</p><p>offset 0x38 - size of bus memory region  
num_devices - 4 (repository node says this but there are more devices&nbsp;!!!)  
</p><h2><span class="mw-headline" id="SB_bus_device"> SB bus device  </span></h2><h3><span class="mw-headline" id="vtable_26"> vtable  </span></h3><p>0x00352620 (3.15)  
 
</p><h3><span class="mw-headline" id="Member_variables_15"> Member variables  </span></h3><p>offset 0x18 - array of pointers to MMIO memory region objects owned by device (8 * 8 bytes)  
== Storage bus  ==
</p><p>offset 0x60 - pointer to first DMA region object  
 
</p><p>offset 0x6C - device opened flag (1 byte, 0 - not opened, 1 - already opened)  
type - 5  
</p><p>offset 0x70 - id of LPAR that opened this device  
 
</p><p>offset 0x90 - pointer to an object that contains the address of interrupt handler for this device and SB bus interrupt index  
index - 4  
</p><h2><span class="mw-headline" id="Gelic_device_.28Network_Interface.29"> Gelic device (Network Interface)  </span></h2><p>device id = 0  
 
</p><p>interrupt index = 8  
num_devices - 4  
</p><h3><span class="mw-headline" id="MMIO_regions"> MMIO regions  </span></h3>
 
{|  class="wikitable FCK&#95;_ShowTableBorders"
= SB bus subsystem  =
!  Index
 
! Relative Bus Start Address
== vtable  ==
! Absolute Bus Start Address
 
! Size
0x00352600 (3.15)  
|-  
 
| 0
== Member variables  ==
| 0x2800
 
|  0x24000002800
offset 0x10 - MMIO memory base address  
|  0x200
 
|-  
offset 0x20 - array of 16 pointers to SB devices (0 - Gelic device, 1 - USB device)  
| 1
 
| 0x3004000
== Objects  ==
| 0x24003004000
 
|  0x1000
0x00349528 - pointer to pointer to SB bus subsystem object  
|-  
 
| 2
== Memory base address  ==
| -
 
| -
0x24000000000  
| -
 
|-
All SB bus device MMIO addresses are relative to this memory address.  
| 3
 
| -
== SB device MMIO/DMA memory region  ==
| -
 
| -
=== vtable  ===
|-
 
| 4
0x352308 (3.15)
| -
 
-
=== Member variables  ===
| -
 
|-  
offset 0x18 - pointer to previous bus memory region object  
|  5
 
| -
offset 0x20 - pointer to next bus memory region object  
| -
 
| -
offset 0x30 - relative bus memory start address  
|-  
 
| 6
offset 0x38 - size of bus memory region  
| -
 
| -
== SB bus device  ==
| -
 
|-  
=== vtable  ===
| 7
 
| -
0x00352620 (3.15)  
| -
 
| -
=== Member variables  ===
|}<h3><span class="mw-headline" id="DMA_regions"> DMA regions  </span></h3>
 
{| class="wikitable FCK&#95;_ShowTableBorders"
offset 0x18 - array of pointers to MMIO memory region objects owned by device (8 * 8 bytes)  
!  Relative Bus Start Address
 
!  Absolute Bus Start Address
offset 0x60 - pointer to first DMA region object  
!  Size
 
|-  
offset 0x6C - device opened flag (1 byte, 0 - not opened, 1 - already opened)  
| 0xA0000000
 
| -
offset 0x70 - id of LPAR that opened this device  
| 0x8000
 
|-  
offset 0x90 - pointer to an object that contains the address of interrupt handler for this device and SB bus interrupt index  
| 0xC0000000
 
| -
== Gelic device (Network Interface)  ==
| 0x10000000
 
|}<h2><span class="mw-headline" id="SATA_Controller_1_device"> SATA Controller 1 device  </span></h2><p>device id = 1
device id = 0  
</p><p>interrupt index = 49
 
</p><h3><span class="mw-headline" id="MMIO_regions_2"> MMIO regions  </span></h3>
interrupt index = 8  
{|  class="wikitable FCK&#95;_ShowTableBorders"
 
!  Index
The Gelic device is similar to the spider_net device from Toshiba. There are some differences with mmio initialization values within LV1 in comparison to the spider_net.c linux driver.
!  Relative Bus Start Address
 
Absolute Bus Start Address
Gelic defines:
! Size
{| class="wikitable sortable"
|-  
|-
| 0
! DEFINE !! Value
|  0x2000
|-
| 0x24000002000
| GELIC_CKRCTRL_REGISTER || 0xFF0
| 0x200
|-
|-  
| GELIC_CKRCTRL_STOP_VALUE || 0x00000105
| 1
|-
| 0x3000000
| GELIC_CKRCTRL_RUN_VALUE || 0x1D7F0105
| 0x24003000000
|-
| 0x1000
| GELIC_MACADDR_HIGH_REG || 0x500
|-
|-
| 2
| GELIC_MACADDR_LOW_REG || 0x504
|  0x3800000
|-
|  0x24003800000
|}
|  0x1000
 
|-
=== MMIO regions ===
|  3
 
| 0x3802000
{| class="wikitable FCK__ShowTableBorders"
| 0x24003802000
|-
| 0x1000
! Index
|-  
! Relative Bus Start Address
| 4
! Absolute Bus Start Address
| -
! Size
| -
|-
| -
| 0
|-  
| 0x2800
| 5
| 0x24000002800
| -
| 0x200
| -
|-
| -
| 1
|-  
| 0x3004000
| 6
| 0x24003004000
| -
| 0x1000
| -
|-
| -
| 2
|-  
| -  
| 7
| -  
| -
| -
| -
|-
| -
| 3
|}<h3><span class="mw-headline" id="DMA_regions_2"> DMA regions  </span></h3>
| -  
{| class="wikitable FCK&#95;_ShowTableBorders"
| -  
!  Relative Bus Start Address
| -
!  Absolute Bus Start Address
|-
!  Size
| 4
|-  
| -
| 0xA0000000
| -
| -
| -
|  0x1000
|-
|-  
| 5
| 0xA0001000
| -  
| -
| -
| 0x1000
| -
|-  
|-
| 0xA0002000
| 6
| -
| -  
0x1000
| -
|}<h2><span class="mw-headline" id="SATA_Controller_2_device"> SATA Controller 2 device  </span></h2><p>device id = 2
| -
</p><p>interrupt index = 13
|-
</p><h3><span class="mw-headline" id="MMIO_regions_3"> MMIO regions  </span></h3>
| 7
{| class="wikitable FCK&#95;_ShowTableBorders"
| -
!  Index
| -
!  Relative Bus Start Address
| -
!  Absolute Bus Start Address
|}
!  Size
 
|-  
=== DMA regions  ===
| 0
 
| 0x2200
{| class="wikitable FCK__ShowTableBorders"
| 0x24000002200
|-
| 0x200
! Relative Bus Start Address
|-
! Absolute Bus Start Address  
| 1
! Size
| 0x3001000
|-
| 0x24003001000
| 0xA0000000
| 0x1000
| -
|-
| 0x8000
2
|-
|  0x3801000
| 0xC0000000
|  0x24003801000
| -
|  0x1000
| 0x10000000
|-
|}
| 3
 
|  0x3803000
== SATA Controller 1 device ==
| 0x24003803000
 
| 0x1000
device id = 1
|-  
 
| 4
interrupt index = 49
| -
 
| -
=== MMIO regions ===
| -
 
|-  
{| class="wikitable FCK__ShowTableBorders"
| 5
|-
| -
! Index
| -
! Relative Bus Start Address
| -
! Absolute Bus Start Address
|-  
! Size
| 6
|-
| -
| 0
| -
| 0x2000
| -
| 0x24000002000
|-  
| 0x200
| 7
|-
| -
| 1
| -
| 0x3000000
| -
| 0x24003000000
|}<h3><span class="mw-headline" id="DMA_regions_3"> DMA regions  </span></h3>
| 0x1000
{| class="wikitable FCK&#95;_ShowTableBorders"
|-
!  Relative Bus Start Address
| 2
!  Absolute Bus Start Address
| 0x3800000
!  Size
| 0x24003800000
|-  
| 0x1000
| 0xA0000000
|-
| -
| 3
| 0x1000
| 0x3802000
|-  
| 0x24003802000
| 0xA0001000
| 0x1000
| -
|-
| 0x1000
| 4
|-  
| -  
| 0xA0002000
| -  
| -
| -
| 0x1000
|-
|}<h2><span class="mw-headline" id="USB_Controller_1_device"> USB Controller 1 device </span></h2><p>device id = 3
| 5
</p><h3><span class="mw-headline" id="MMIO_regions_4"> MMIO regions  </span></h3>
| -
{| class="wikitable FCK&#95;_ShowTableBorders"  
| -
!  Index
| -
! Relative Bus Start Address
|-
! Absolute Bus Start Address
| 6
! Size
| -  
|-  
| -  
| 0
| -
| 0x2400
|-
| 0x24000002400
| 7
| 0x200
| -  
|-
| -
| 1
| -
| 0x3010000
|}
| 0x24003010000
 
| 0x10000
=== DMA regions ===
|-  
 
| 2
{| class="wikitable FCK__ShowTableBorders"
| 0x3810000
|-
|  0x24003810000
! Relative Bus Start Address
| 0x10000
! Absolute Bus Start Address
|-
! Size
3
|-
| -
| 0xA0000000
|  -
| -
| -
| 0x1000
|-  
|-
|  4
| 0xA0001000
| -
| -
| -
| 0x1000
| -
|-
|-
| 0xA0002000
| 5
| -
| -
| 0x1000
| -
|}
| -
 
|-  
== SATA Controller 2 device ==
| 6
 
| -
device id = 2  
| -
 
| -
interrupt index = 13
|-  
 
| 7
=== MMIO regions ===
| -
 
| -
{| class="wikitable FCK__ShowTableBorders"
| -
|-
|}<h3><span class="mw-headline" id="DMA_regions_4"> DMA regions  </span></h3>
! Index
{| class="wikitable FCK&#95;_ShowTableBorders"
! Relative Bus Start Address
!  Relative Bus Start Address
! Absolute Bus Start Address
!  Absolute Bus Start Address
! Size
!  Size
|-
|-  
| 0
| 0xC0000000
| 0x2200
| -
| 0x24000002200
| 0x10000000
| 0x200
|-  
|-
| 0xD0000000
| 1
| -
| 0x3001000
| 0x10000000
| 0x24003001000
|}<h2><span class="mw-headline" id="USB_Controller_2_device"> USB Controller 2 device  </span></h2><p>device id = 4
| 0x1000
</p><h3><span class="mw-headline" id="MMIO_regions_5"> MMIO regions  </span></h3>
|-
{| class="wikitable FCK&#95;_ShowTableBorders"
| 2
!  Index
| 0x3801000
! Relative Bus Start Address
| 0x24003801000
! Absolute Bus Start Address
| 0x1000
! Size
|-
|-  
| 3
| 0
| 0x3803000
|  0x2600
| 0x24003803000
| 0x24000002600
| 0x1000
| 0x200
|-
|-  
| 4
| 1
| -
| 0x3020000
| -
| 0x24003020000
| -
| 0x10000
|-
|-
| 5
2
| -  
| 0x3820000
| -
|  0x24003820000
| -
|  0x10000
|-
|-
| 6
| 3
| -  
|  -
| -
| -
| -
| -
|-
|-
| 7
|  4
| -  
|  -
| -
| -
| -
| -
|}
|-
 
| 5
=== DMA regions ===
| -
 
| -
{| class="wikitable FCK__ShowTableBorders"
| -
|-
|-
! Relative Bus Start Address  
| 6
! Absolute Bus Start Address  
| -
! Size
| -
|-
| -
| 0xA0000000
|-
| -
| 7
| 0x1000
| -
|-
| -
| 0xA0001000
| -
| -
|}<h3><span class="mw-headline" id="DMA_regions_5"> DMA regions  </span></h3>
| 0x1000
{| class="wikitable FCK&#95;_ShowTableBorders"
|-
!  Relative Bus Start Address
| 0xA0002000
!  Absolute Bus Start Address
| -  
!  Size
| 0x1000
|-  
|}
| 0xC0000000
 
| -
== USB Controller 1 device ==
| 0x10000000
 
|-  
device id = 3  
| 0xD0000000
 
| -
=== MMIO regions ===
| 0x10000000
 
|}<h2><span class="mw-headline" id="ENCDEC_device"> ENCDEC device  </span></h2><p>device id = 7
{| class="wikitable FCK__ShowTableBorders"
</p><p>interrupt index = 5
|-
</p><h3><span class="mw-headline" id="MMIO_regions_6"> MMIO regions  </span></h3>
! Index
{| class="wikitable FCK&#95;_ShowTableBorders"
! Relative Bus Start Address
!  Index
! Absolute Bus Start Address
!  Relative Bus Start Address
! Size
!  Absolute Bus Start Address
|-
!  Size
| 0
|-  
| 0x2400
| 0
| 0x24000002400
| 0x2C00
| 0x200
| 0x24000002C00
|-
| 0x200
| 1
|-
| 0x3010000
| 1
| 0x24003010000
| 0x3005000
| 0x10000
|  0x24003005000
|-
|  0x1000
| 2
|-
| 0x3810000
| 2
| 0x24003810000
| 0x3006000
| 0x10000
| 0x24003006000
|-
| 0x1000
| 3
|-  
| -  
| 3
| -  
| -
| -
| -
|-
| -
| 4
|-
| -  
|  4
| -  
| -
| -
|  -
|-
|  -
| 5
|-
| -
5
| -
|  -
| -
| -
|-
|  -
| 6
|-
| -  
| 6
| -
| -
| -
| -
|-
| -
| 7
|-
| -  
| 7
| -
| -
| -
| -
|}
| -
 
|}<h3><span class="mw-headline" id="DMA_regions_6"> DMA regions  </span></h3>
=== DMA regions  ===
{| class="wikitable FCK&#95;_ShowTableBorders"
 
!  Relative Bus Start Address
{| class="wikitable FCK__ShowTableBorders"
!  Absolute Bus Start Address
|-
!  Size
! Relative Bus Start Address  
|-  
! Absolute Bus Start Address  
| 0x80010000
! Size
| -
|-
| 0x10000
| 0xC0000000
|-
| -
| 0x80004000
| 0x10000000
| -
|-
| 0x4000
| 0xD0000000
|-  
| -
| 0x80001000
| 0x10000000
| -
|}
| 0x1000
 
|-  
== USB Controller 2 device ==
| 0x80003000
 
| -
device id = 4
| 0x1000
 
|-
=== MMIO regions ===
| 0x80008000
 
| -
{| class="wikitable FCK__ShowTableBorders"
| 0x1000
|-
|-  
! Index
| 0x80009000
! Relative Bus Start Address
| -
! Absolute Bus Start Address
|  0x1000
! Size
|-  
|-
| 0x80040000
| 0
| -
| 0x2600
| 0x10000
| 0x24000002600
|-  
| 0x200
| 0x8000A000
|-
| -
| 1
| 0x1000
| 0x3020000
|-
| 0x24003020000
| 0x90020000
| 0x10000
|  -
|-
| 0x20000
| 2
|-  
| 0x3820000
|  0xC0000000
| 0x24003820000
| -
| 0x10000
| 0x10000
|-
|-  
| 3
| 0xC0040000
| -  
| -
| -
| 0x40000
| -
|}<h2><span class="mw-headline" id="FLASH_Controller_device_.28StarShip_-_SS.29"> FLASH Controller device (StarShip - SS)  </span></h2><p>device id = 9
|-
</p><p>interrupt index = 41
| 4
</p><h3><span class="mw-headline" id="MMIO_regions_7"> MMIO regions  </span></h3><p>FLASH controller doesn't have MMIO regions.
| -  
</p><h3><span class="mw-headline" id="DMA_regions_7"> DMA regions  </span></h3>
| -
{| class="wikitable FCK&#95;_ShowTableBorders"
| -
!  Relative Bus Start Address
|-
!  Absolute Bus Start Address
| 5
!  Size
| -  
|-
| -
| 0x80000000
| -
| -
|-
| 0x1000
| 6
|-  
| -  
| 0x80020000
| -
| -
| -
| 0x20000
|-
|-  
| 7
| 0x80002000
| -  
| -
| -
| 0x1000
| -
|-  
|}
| 0x90000000
 
| -
=== DMA regions ===
| 0x20000
 
|}<h2><span class="mw-headline" id="SB_Bus_Interrupt_Handling"> SB Bus Interrupt Handling  </span></h2><ul><li>There is a table of interrupt handlers for SB devices
{| class="wikitable FCK__ShowTableBorders"
</li><li>The size of table is 64
|-
</li><li>The main SB bus interrupt handler is at 0x002B9CC4 (3.15)  
! Relative Bus Start Address
</li><li>The main interrupt handler reads interrupt index and dispatches interrupts
! Absolute Bus Start Address
</li></ul><h3><span class="mw-headline" id="Interrupt_Index"> Interrupt Index </span></h3><ul><li>The main SB bus interrupt handler reads 2 32-bit values from addresses 0x24000008100 and 0x0x24000008104
! Size
</li><li>The interrupt index is calculated from these values
|-
</li></ul><h3><span class="mw-headline" id="Interrupt_Handler_Table"> Interrupt Handler Table </span></h3>
| 0xC0000000
{| class="wikitable FCK&#95;_ShowTableBorders"  
| -
!  Interrupt
| 0x10000000
! Description
|-
! Address in HV
| 0xD0000000
|-  
| -  
| 5
| 0x10000000
| ENCDEC device
|}
| 0x00275C60 (3.15)
 
|-  
== ENCDEC device ==
| 6
 
| EH EPCIC internal
device id = 7
|  0x0023B6B0 (3.15)
 
|-  
interrupt index = 5  
| 8
 
| Gelic device
=== MMIO regions ===
| 0x00245330 (3.15)
 
|-  
{| class="wikitable FCK__ShowTableBorders"
| 12
|-
| ATA interrupt handler
! Index
| 0x0026B984 (3.15)
! Relative Bus Start Address
|-
! Absolute Bus Start Address
|  13
! Size
|  ATA interrupt handler
|-
|  0x0026B984 (3.15)
| 0
|-
| 0x2C00
|  14
| 0x24000002C00
| Spider SC
| 0x200
|  0x0020A68C (3.15)
|-
|-  
| 1
|  29
| 0x3005000
| SBERR
| 0x24003005000
| 0x0023AA50 (3.15)
| 0x1000
|-  
|-
| 30
| 2
| SBERR
| 0x3006000
| 0x0023AA50 (3.15)
| 0x24003006000
|-  
| 0x1000
| 41
|-
| EBUS (Flash StartShip)
| 3
| 0x002814EC (3.15)
| -
|-  
| -  
| 49
| -
| ATA media interrupt handler
|-
| 0x00268A8C (3.15)
| 4
|-  
| -  
| 50
| -
| Flash&nbsp;?
| -
| 0x00280B24 (3.15)
|-
|-  
| 5
| 55
| -
| EH EPCIC SERR
| -  
| 0x0023B67C (3.15)
| -
|}<h1><span class="mw-headline" id="Storage_bus_subsystem"> Storage bus subsystem  </span></h1><h2><span class="mw-headline" id="vtable_27"> vtable  </span></h2><p>0x00353AC8 (3.15)  
|-
</p><h2><span class="mw-headline" id="Member_variables_16"> Member variables  </span></h2><p>offset 0xEE8 - table of pointers to storage device objects (7 * 8 bytes, max 7 devices)  
| 6
</p><h2><span class="mw-headline" id="Storage_device_class"> Storage device class  </span></h2><h3><span class="mw-headline" id="Member_variables_17"> Member variables  </span></h3><p>offset 0x8 - device id (8 bytes)  
| -  
</p><p>offset 0xD50 - device id (8 bytes)
| -  
</p><p>offset 0xD60 - pointer to ENCDEC SB bus device object
| -
</p><h3><span class="mw-headline" id="Region_Manager"> Region Manager </span></h3><ul><li> Each storage device has a Region Manager (i call it like that)
|-
</li><li> Region Manager stores information about each Region of the storage device
| 7
</li><li> All Regions of a Region Manager are linked together
| -  
</li><li> Free Regions of a Region Manager are linked together also
| -
</li><li> A Region Manager can have at most 8 Regions
| -
</li></ul><h4><span class="mw-headline" id="Region"> Region </span></h4><ul><li>Each storage device can have at most 8 regions (0-7)  
|}
</li><li>Each region has ACL table
 
</li><li>HV checks region ACLs before allowing access to the region
=== DMA regions ===
</li><li>Each region has a start sector that is an offset from the physical first sector of the storage device and a number of sectors
 
</li></ul><ul><li>The start sector passed to lv1 storage hvcalls is <b>relative</b> to the start sector of the region passed to the lv1 storage hvcall
{| class="wikitable FCK__ShowTableBorders"
</li></ul><h5><span class="mw-headline" id="Region_ACL"> Region ACL </span></h5><p>offset 0x0 - LPAR AUTH ID (8 bytes)
|-
</p><p>offset 0x8 - access rigths (8 bytes)
! Relative Bus Start Address
</p><p>offset 0x10 - entry valid flag: 0 - invalid, 1 - valid (1 byte)
! Absolute Bus Start Address
</p><h5><span class="mw-headline" id="Region_Access_Protection"> Region Access Protection </span></h5><ul><li>Before a storage region is accessed, HV checks access rights of the caller.
! Size
</li><li>Repository node <b>ss.laid</b> (LPAR authentication id) is evaluated for this purpose.
|-
</li><li>If LPAR has a repository node <b>ios.ata.region0.access</b> (value doesn't matter) then the access rights check never fails.
| 0x80010000
</li><li><b>ALL storage accesses from LPAR 1 are allowed</b></li><li><b>If (flags &amp; 0x100000002)&nbsp;&#33;= 0 then access rights check is skipped&nbsp;&#33;&#33;&#33;</b>.
| -  
</li></ul><pre> I tested on HV 3.41 with flags 0x2 and got access to regions which were denied by policy (LV1_DENIED_BY_POLICY result).
| 0x10000
</pre><h4><span class="mw-headline" id="Storage_Device_Partition_Table"> Storage Device Partition Table </span></h4><ul><li> Each storage device has a Partition Table
|-
</li><li> Partition Table contains information about each region on the storage device
| 0x80004000
</li></ul><h4><span class="mw-headline" id="Methods_2"> Methods </span></h4><p>lv1_storage_create_region (lv1_undocumented_function_250) - 0x00301328 (3.15)
| -  
</p><p>lv1_storage_delete_region (lv1_undocumented_function_251) - 0x003011E8 (3.15)
| 0x4000
</p><p>lv1_storage_set_region_acl (lv1_undocumented_function_252) - 0x00300F3C (3.15)
|-
</p><p>lv1_storage_get_region_acl (lv1_undocumented_function_253) - 0x00301090 (3.15)
| 0x80001000
</p><p>storage_device_create_region - 0x00253988 (3.15)
| -  
</p><p>storage_device_delete_region - 0x00253BE8 (3.15)
| 0x1000
</p><p>storage_device_region_set_acl - 0x00252C80 (3.15)
|-
</p><p>storage_device_region_get_acl - 0x00252710 (3.15)
| 0x80003000
</p><p>storage_region_mgr_create_region - 0x0025A530 (3.15)
| -  
</p><p>storage_region_mgr_delete_region - 0x0025BA64 (3.15)
| 0x1000
</p><p>storage_region_mgr_set_acl - 0x0025A140 (3.15)
|-
</p><p>storage_region_mgr_get_acl - 0x0025A298 (3.15)
| 0x80008000
</p><p>storage_region_mgr_update_partition_table - 0x00259924 (3.15)
| -  
</p><p>storage_region_acl_entry_reset - 0x0025C1A8 (3.15)
| 0x1000
</p><p>storage_region_acl_entry_check_laid - 0x0025C1FC (3.15)
|-
</p><p>storage_region_overlap - 0x0025C094 (3.15)
| 0x80009000
</p><p>storage_region_check_access - 0x00259EC8 (3.15)
| -  
</p><h2><span class="mw-headline" id="Storage_subsystem_device"> Storage subsystem device  </span></h2><p>device id = -1
| 0x1000
</p><ul><li>The storage subsystem is a storage device itself.
|-
</li><li>It's a psuedo device used to notify a LPAR when storage devices become e.g. ready.  
| 0x80040000
</li><li>Linux implements a loop and reads from this device and process notifications (adds new devices dynamically).
| -  
</li></ul><h3><span class="mw-headline" id="Notification_Events"> Notification Events  </span></h3><p>List of supported notification events:
| 0x10000
</p><ul><li>Notify Device Ready (0x1)
|-
</li><li>Notify Region Probe (0x2)  
| 0x8000A000
</li><li>Notify Region Update (0x4)
| -  
</li></ul><h2><span class="mw-headline" id="RBD_device"> RBD device  </span></h2><ul><li>On Linux, ENCDEC and RBD devices are mapped to the storage device with device id 0.
| 0x1000
</li><li>On GameOS, ENCDEC device has device id 0 and RBD device has device id 2.
|-
</li></ul><p>device id = 0
| 0x90020000
</p><p>block size = 2048
| -  
</p><p>/dev/rbd0
| 0x20000
</p><ul><li>The RBD storage device uses ENCDEC device.
|-
</li></ul><h3><span class="mw-headline" id="vtable_28"> vtable  </span></h3><p>0x00354288 (3.15)
| 0xC0000000
</p><h3><span class="mw-headline" id="Member_variables_18"> Member variables </span></h3><p>offset 0x1808 - request table (0x58 * 32 bytes)
| -
</p><h3><span class="mw-headline" id="Regions"> Regions  </span></h3>
| 0x10000
{|  class="wikitable FCK&#95;_ShowTableBorders"
|-
!  Index
| 0xC0040000
!  Start sector
| -
!  Number of sectors
| 0x40000
|-  
|}
|  0
 
|  0x0
== FLASH Controller device (StarShip - SS) ==
|  0x7FFFFFFF
 
|-  
device id = 9
|  1
 
|  -
interrupt index = 41
-
 
|-  
=== MMIO regions ===
|  2
 
-
FLASH controller doesn't have MMIO regions.
|  -
 
|-  
=== DMA regions ===
3
 
|  -
{| class="wikitable FCK__ShowTableBorders"
-
|-
|-  
! Relative Bus Start Address
|  4
! Absolute Bus Start Address  
-
! Size
|  -
|-
|-  
| 0x80000000
|  5
| -
|  -
| 0x1000
|  -
|-
|-  
| 0x80020000
|  6
| -
| -
| 0x20000
|  -
|-
|-  
| 0x80002000
|  7
| -
|  -
| 0x1000
|  -
|-
|}<h3><span class="mw-headline" id="Supported_Device_Commands"> Supported Device Commands  </span></h3><p>Here is the list of commands supported by RBD storage device.  
| 0x90000000
</p><ul><li>The commands can be used with HV call <b>lv1_storage_send_device_command</b>.  
| -
</li><li>However, before a command is executed HV does bit manipulation with it and checks it against the value of repository node <b>ss.laid</b> or also called <b>LPAR authentication ID</b>. If this test fails then the command is NOT executed.
| 0x20000
</li></ul>
|}
{| class="wikitable FCK&#95;_ShowTableBorders"
 
!  Command
== SB Bus Interrupt Handling  ==
!  Description
 
|-
*There is a table of interrupt handlers for SB devices
0x1
*The size of table is 64
|  LV1_STORAGE_SEND_ATAPI_COMMAND
*The main SB bus interrupt handler is at 0x002B9CC4 (3.15)  
|-
*The main interrupt handler reads interrupt index and dispatches interrupts
|  0x10
 
| ATAPI Read Capacity
=== Interrupt Index ===
|-
 
|  0x11
*The main SB bus interrupt handler reads 2 32-bit values from addresses 0x24000008100 and 0x0x24000008104
|  ATAPI Get Configuration
*The interrupt index is calculated from these values
|-
 
|  0x13
=== Interrupt Handler Table ===
|  ATAPI Read TOC
 
|-
{| class="wikitable FCK__ShowTableBorders"
|  0x1A
|-
|  ATAPI Get Event
! Interrupt
|}<h3><span class="mw-headline" id=".2Fdev.2Frbd0"> /dev/rbd0 </span></h3><ul><li>This LPAR 1 device accesses RBD storage device.  
! Description
</li><li>A write to this device sends a device command to RBD storage device.
! Address in HV
</li></ul><h2><span class="mw-headline" id="ENCDEC_Device_2"> ENCDEC Device </span></h2><p>bus id = 4
|-
</p><p>device id = 0
| 5
</p><ul><li><b>ENCDEC device</b> has a request table of size <b>32</b>.
| ENCDEC device
</li></ul><h3><span class="mw-headline" id="Member_variables_19"> Member variables </span></h3><p>offset 0xDC0 - request table (0x58 * 32 bytes)
| 0x00275C60 (3.15)
</p><h3><span class="mw-headline" id="Methods_3"> Methods </span></h3><p>encdec_device_initialize - 0x00273524 (3.15)
|-
</p><p>InitializeENCDEC - 0x00277310 (3.15)
| 6
</p><p>ENCDEC_ConnectBusDriver - 0x00275A98 (3.15)
| EH EPCIC internal
</p><p>encdec_interrupt_handler - 0x00275C60 (3.15)
| 0x0023B6B0 (3.15)
</p><p>encdec_process_interrupt - 0x0027526C (3.15)
|-
</p><p>encdec_device_enqueue_decsec_request - 0x00273738 (3.15)
| 8
</p><p>encdec_device_do_request - 0x00273EA8 (3.15)
| Gelic device
</p><p>encdec_device_do_SS_request - 0x00274940 (3.15)
| 0x00245330 (3.15)
</p><p>Encdec_KickDMA - 0x00277118 (3.15)
|-
</p><p>encdec_device_is_in_testmode - 0x002756E0 (3.15)
| 12
</p><p>is_encdec_in_testmode - 0x002732D0 (3.15)
| ATA interrupt handler
</p><h3><span class="mw-headline" id="ENCDEC_Device_Commands"> ENCDEC Device Commands  </span></h3><ul><li><b>EdecKgen1</b> command is used e.g. by <b>Storage Manager Service 0x5003</b> to generate random numbers. Storage Manager performs this command through LPAR 1 device <b>/dev/encdec0</b>.
| 0x0026B984 (3.15)
</li></ul>
|-
{| class="wikitable FCK&#95;_ShowTableBorders"
| 13
!  Command
| ATA interrupt handler
!  Description
| 0x0026B984 (3.15)
|-  
|-
|  0x81
| 14
|  EdecKgen1
| Spider SC
|-  
| 0x0020A68C (3.15)
| 0x82
|-
| EdecKgen2
| 29
|-  
| SBERR
| 0x83
| 0x0023AA50 (3.15)
| EdecKset/EdecKset NG
|-
|-
| 30
| 0x84
| SBERR
|  EdecKgenFlash
| 0x0023AA50 (3.15)
|-
|-
|  0x85
| 41
|  Encrypts/decrypts sectors (This command cannot be executed through ioctl interface&nbsp;&#33;&#33;&#33;)
| EBUS (Flash StarShip)  
|-
| 0x002814EC (3.15)
|  0x86
|-
|  Encdec decsec (This command cannot be executed through ioctl interface&nbsp;&#33;&#33;&#33;)
| 49
|-
| ATA media interrupt handler
| 0x87
| 0x00268A8C (3.15)
|  EdecSBClear
|-
|}<h4><span class="mw-headline" id="EdecKgen1_Command_.280x81.29"> EdecKgen1 Command (0x81) </span></h4><ul><li>First, ENCDEC device key generator is flashed by executing the operation which is also performed during <b>EdecKgenFlash</b> command.
| 50
</li><li>0x30 bytes of data are written to MMIO registers of ENCDEC device.
| Flash&nbsp;?
</li><li>0x40 bytes of data are read from MMIO registers of ENCDEC device.
| 0x00280B24 (3.15)
</li><li>The base address of MMIO registers used in this command is <b>0x24003006000</b>.
|-
</li><li>I tested this command by directly communicating with ENCDEC device from GameOS by using HV call <b>lv1_storage_send_device_command</b> and it returns random data.
| 55
</li></ul><p>Here is the data i sent to ENCDEC device:
| EH EPCIC SERR
</p><pre>
| 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''' ([[Authority ID|LPAR Authority 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 &amp; 0x100000002)&nbsp;!= 0 then access rights check is skipped&nbsp;!!!'''.
 
  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 pseudo 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  ===
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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 '''[[Authority ID|LPAR Authority ID]]'''. If this test fails then the command is NOT executed.
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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'''.
* ENCDEC device supports upto 16 keys simultaneously.
 
=== 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'''.
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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:
 
<pre>
Offset      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
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É
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éÉ
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
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  ‚.Ö............
00000030  82 1D 8F D6 00 00 00 00  00 00 00 00 00 00 00 00  ‚. Ö............
</pre>
</pre><p>Here is the data i received back from ENCDEC device:
 
</p><pre>
Here is the data i received back from ENCDEC device:
 
<pre>
Offset      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
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.(
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  QNùïvâÇ.ïA.úl–¨
00000010  51 8D 4E F9 EF 76 E2 C7  17 EF 41 14 FA 6C 96 A8  Q NùïvâÇ.ïA.úl–¨
00000020  7E 41 43 96 15 9A 0D 71  A9 B6 A6 B0 F1 96 15 C5  ~AC–.š.q©¶¦°ñ–.Å
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á…’
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Ûì............
00000040  99 66 DB EC 00 00 00 00  00 00 00 00 00 00 00 00  ™fÛì............
</pre>
</pre><p>Here is another data i received back from ENCDEC device by using the same command and data:
 
</p><pre>
Here is another data i received back from ENCDEC device by using the same command and data:
 
<pre>
Offset      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
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.(
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  QNùïvâÇ.ïA.úl–¨
00000010  51 8D 4E F9 EF 76 E2 C7  17 EF 41 14 FA 6C 96 A8  Q NùïvâÇ.ïA.úl–¨
00000020  7E 41 43 96 17 08 75 F6  66 2F 32 5A 9E 3E E7 FD  ~AC–..uöf/2Zž>çý
00000020  7E 41 43 96 17 08 75 F6  66 2F 32 5A 9E 3E E7 FD  ~AC–..uöf/2Zž&gt;çý
00000030  16 3E 18 CA B2 5E 90 84  29 7F 98 BC 73 36 0E 7B  .>.ʲ^„)˜¼s6.{
00000030  16 3E 18 CA B2 5E 90 84  29 7F 98 BC 73 36 0E 7B  .&gt;.ʲ^ ) ˜¼s6.{
00000040  7D EC B6 37 00 00 00 00  00 00 00 00 00 00 00 00  }ì¶7............
00000040  7D EC B6 37 00 00 00 00  00 00 00 00 00 00 00 00  }ì¶7............
</pre>
</pre><h4><span class="mw-headline" id="EdecKgen2_Command_.280x82.29"> EdecKgen2 Command (0x82) </span></h4><ul><li>The base address of MMIO registers used in this command is <b>0x24003006000</b>.
 
</li></ul><h4><span class="mw-headline" id="EdecKset_Command_.280x83.29"> EdecKset Command (0x83) </span></h4><h4><span class="mw-headline" id="EdecKgenFlash_Command_.280x84.29"> EdecKgenFlash Command (0x84) </span></h4><ul><li>The base address of MMIO registers used in this command is <b>0x24003006000</b>.
==== EdecKgen2 Command (0x82) ====
</li><li>The command reads 4 bytes from address <b>0x240030060A0</b>, sets bit 1 to 1 (old value &#124; 0x2) and writes the new value to the same address.
 
</li></ul><h4><span class="mw-headline" id="Encdec_decsec_Command_.280x86.29"> Encdec decsec Command (0x86) </span></h4><ul><li>This command is used to decrypt/encrypt sectors.
*The base address of MMIO registers used in this command is '''0x24003006000'''.
</li><li>FLASH, HDD and RBD storage devices use this command to decrypt/encrypt sectors.
 
</li><li>This command cannot be executed through lv1_storage_send_device_command HV call, it's used by HV only internally.
==== EdecKset Command (0x83) ====
</li></ul><h4><span class="mw-headline" id="EdecSBClear_Command_.280x87.29"> EdecSBClear Command (0x87) </span></h4><ul><li>The command expects arg2 to be 4 or else it returns with an error.
 
</li><li>This command is used e.g. by <b>Storage Manager service 0x5002</b> when ATA keys are deleted.
==== EdecKgenFlash Command (0x84) ====
</li></ul><h3><span class="mw-headline" id="Test_Mode"> Test Mode </span></h3><ul><li> ENCDEC device has <b>Test Mode</b></li><li> Some HV functions test it by reading a 4 byte value from address <b>0x24003005200</b>. If this value is 0 then ENCDEC device is NOT in <b>Test Mode</b>.
 
</li></ul><h3><span class="mw-headline" id="ENCDEC_Request"> ENCDEC Request </span></h3><p>offset 0x34 - start sector (4 bytes)
*The base address of MMIO registers used in this command is '''0x24003006000'''.
</p><p>offset 0x38 - sector count (4 bytes)
*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.
</p><p>offset 0x3C - sector size (4 bytes)
 
</p><p>offset 0x40 - key (4 bytes)
==== Encdec decsec Command (0x86) ====
</p><p>offset 0x44 - 0 = decrypt, 1 = encrypt (4 bytes)
 
</p><h3><span class="mw-headline" id="Encrypting_and_Decrypting_Sectors"> Encrypting and Decrypting Sectors </span></h3><ul><li>HV passes to ENCDEC device addresses of 2 buffers: <b>ENCDEC User Buffer</b> and <b>ENCDEC Descriptor Buffer</b>.
*This command is used to decrypt/encrypt sectors.
</li><li><b>ENCDEC User Buffer</b> contains the following information: <b>Start Sector</b>, <b>Sector Count</b>, <b>Sector Size</b> and <b>Key</b></li></ul><h4><span class="mw-headline" id="ENCDEC_User_Buffer"> ENCDEC User Buffer </span></h4><p>offset 0x0 - start sector (4 bytes)
*FLASH, HDD and RBD storage devices use this command to decrypt/encrypt sectors.
</p><p>offset 0x4 - sector count (4 bytes)
*This command cannot be executed through lv1_storage_send_device_command HV call, it's used by HV only internally.
</p><p>offset 0x8 - sector size (4 bytes)
 
</p><p>offset 0xC - key (4 bytes)
==== EdecSBClear Command (0x87) ====
</p><h2><span class="mw-headline" id="FLASH_device"> FLASH device  </span></h2><p>device id = 1  
 
</p><ul><li>The FLASH device uses ENCDEC device.
*The command expects arg2 to be 4 or else it returns with an error.
</li></ul><h3><span class="mw-headline" id="vtable_29"> vtable  </span></h3><p>0x00354450 (3.15)  
*This command is used e.g. by '''Storage Manager service 0x5002''' when ATA keys are deleted.
</p><h3><span class="mw-headline" id="Member_variables_20"> Member variables </span></h3><p>offset 0x18F0 - request table (0x58 * 16 bytes)
 
</p><h3><span class="mw-headline" id="Regions_2"> Regions  </span></h3>
=== Test Mode ===
{| class="wikitable FCK&#95;_ShowTableBorders"  
 
! Index
* ENCDEC device has '''Test Mode'''
! Start sector
* 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'''.
! Number of sectors
 
|-  
=== ENCDEC Request ===
| 0
 
| 0x0
offset 0x34 - start sector (4 bytes)
| 0x8000
 
|-  
offset 0x38 - sector count (4 bytes)
| 1
 
| 0x8
offset 0x3C - sector size (4 bytes)
| 0x77F8
 
|-  
offset 0x40 - key (4 bytes)
| 2
 
| 0x7900
offset 0x44 - 0 = decrypt, 1 = encrypt (4 bytes)
| 0x100
 
|-  
=== Encrypting and Decrypting Sectors ===
| 3
 
| 0x7A00
*HV passes to ENCDEC device addresses of 2 buffers: '''ENCDEC User Buffer''' and '''ENCDEC Descriptor Buffer'''.
| 0x400
*'''ENCDEC User Buffer''' contains the following information: '''Start Sector''', '''Sector Count''', '''Sector Size''' and '''Key'''
|-  
 
| 4
==== ENCDEC User Buffer ====
| -
 
| -
offset 0x0 - start sector (4 bytes)
|-  
 
| 5
offset 0x4 - sector count (4 bytes)
| -
 
| -
offset 0x8 - sector size (4 bytes)
|-  
 
| 6
offset 0xC - key (4 bytes)
| -
 
| -
== FLASH device  ==
|-  
 
| 7
device id = 1  
| -
 
| -
*The FLASH device uses ENCDEC device.
|}<h3><span class="mw-headline" id="Supported_Device_Commands_2"> Supported Device Commands  </span></h3><p>Here is the list of commands supported by FLASH StarShip 2 storage device.  
 
</p><ul><li>The commands can be used with HV call <b>lv1_storage_send_device_command</b>.  
=== vtable  ===
</li><li>However, before a command is executed HV does bit manipulation with it and checks it against the value of repository node <b>ss.laid</b> or also called <b>LPAR authentication ID</b>. If this test fails then the command is NOT executed.
 
</li></ul>
0x00354450 (3.15)  
{| class="wikitable FCK&#95;_ShowTableBorders"  
 
Command
=== Member variables ===
! Description
 
|-  
offset 0x18F0 - request table (0x58 * 16 bytes)
| 0x31
 
| Dummy (This command does nothing, returns success immediately)
=== Regions  ===
|-  
 
| 0xA2
{| class="wikitable FCK__ShowTableBorders"
| -
|-
|-  
! Index  
| 0xA3
! Start sector  
| -
! Number of sectors
|-  
|-
| 0xA4
| 0  
| -
| 0x0  
|-  
| 0x8000
| 0xA6
|-
| SS2 HW Reset
| 1  
|-  
| 0x8  
| 0xAC
| 0x77F8
| -
|-
|-  
| 2  
| 0xAD
| 0x7900  
| TEST
| 0x100
|}<h3><span class="mw-headline" id=".2Fdev.2Feflash1_and_.2Fdev.2Frflash1"> /dev/eflash1 and /dev/rflash1  </span></h3><ul><li>These LPAR 1 devices access region 0 of FLASH storage device.  
|-
</li><li>/dev/rflash1 is 16MB large  
| 3  
</li><li>There is no file system on /dev/rflash1  
| 0x7A00  
</li><li>There is some sort of TOC (Table Of Contents) stored in it. It contains file names, offsets and sizes.  
| 0x400
</li><li>On /dev/rflash1 you will find <b>lv0</b>, <b>lv1ldr</b>, <b>lv2_lernel.self</b> and all the other important SELFs.  
|-
</li><li>The files are encryted of course.
| 4  
</li></ul><h4><span class="mw-headline" id="Content_of_.2Fdev.2Frflash1_.28FLASH_storage_device_region_0.2C_size_16_MB.29"> Content of /dev/rflash1 (FLASH storage device region 0, size 16 MB)  </span></h4><ul><li>There is a main TOC which describes different regions on <b>/dev/rflash1</b></li><li>It seems that TOC 0xC0000 and TOC 0x7C0000 contain the same files but from different SDK versions.  
| -  
</li><li>TOC 0xC0000 is SDK version 3.41 and TOC 0x7C0000 is SDK version 3.30 (look at the content of files <b>sdk_version</b>).  
| -
</li><li>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.  
|-
</li><li>TOC on <b>/dev/rflash1</b> is used by HV Processes to locate files and load them into memory, e.g. SPU modules. E.g. Process 6 loads <b>spu_utoken_processor.self</b> to decrypt and verify user tokens or SPL which runs in Process 5 loads <b>spp_verifier.self</b> from there in order to decrypt and verify profile files. And Update Manager stores e.g. there files.
| 5  
</li></ul><h5><span class="mw-headline" id="TOC_Entry"> TOC Entry  </span></h5><p>A TOC entry is 0x30 bytes large.  
| -  
</p><p>offset 0x0 - relative offset from this TOC to entry data  
| -
</p><p>offset 0x8 - entry data size  
|-
</p><p>offset 0x10 - entry name (max 32 characters)  
| 6  
</p><h5><span class="mw-headline" id="Main_TOC"> Main TOC  </span></h5><p>Here is a list of regions/files stored on <b>/dev/rflash1</b> i found in <b>HV 3.41</b> and dumped with PSGroove:  
| -  
</p>
| -
{| class="wikitable FCK&#95;_ShowTableBorders"  
|-
! Entry Name
| 7  
! TOC Offset
| -  
! Entry TOC Index
| -
! Entry Relative Offset
|}
! Entry Absolute Offset
 
! Entry Size
=== Supported Device Commands  ===
|-  
 
| asecure_loader
Here is the list of commands supported by FLASH StarShip 2 storage device.  
| 0x400
 
| 0
*The commands can be used with HV call '''lv1_storage_send_device_command'''.  
| 0x400
*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 '''[[Authority ID|LPAR Authority ID]]'''. If this test fails then the command is NOT executed.
| 0x810
 
| 0x2E800
{| class="wikitable FCK__ShowTableBorders"
|-  
|-
| eEID
! Command  
| 0x400
! Description
| 1
|-
| 0x2EC00
| 0x31  
| 0x2F010
| Dummy (This command does nothing, returns success immediately)
| 0x10000
|-
|-  
| 0xA2  
| cISD
| -
| 0x400
|-
| 2
| 0xA3  
| 0x3EC00
| -
| 0x3F010
|-
| 0x800
| 0xA4  
|-  
| -
| cCSD
|-
| 0x400
| 0xA6  
| 3
| SS2 HW Reset
| 0x3F400
|-
| 0x3F810
| 0xAC  
| 0x800
| -
|-  
|-
| trvk_prg0
| 0xAD  
| 0x400
| TEST
| 4
|}
| 0x3FC00
 
| 0x40010
=== /dev/eflash1 and /dev/rflash1  ===
| 0x20000
 
|-  
*These LPAR 1 devices access region 0 of FLASH storage device.  
| trvk_prg1
*/dev/rflash1 is 16MB large  
| 0x400
*There is no file system on /dev/rflash1  
| 5
*There is some sort of TOC (Table Of Contents) stored in it. It contains file names, offsets and sizes.  
| 0x5FC00
*On /dev/rflash1 you will find '''lv0''', '''lv1ldr''', '''lv2_lernel.self''' and all the other important SELFs.  
| 0x60010
*The files are encryted of course.
| 0x20000
 
|-  
==== Content of /dev/rflash1 (FLASH storage device region 0, size 16 MB)  ====
| trvk_pkg0
 
| 0x400
*There is a main TOC which describes different regions on '''/dev/rflash1'''
| 6
*It seems that TOC 0xC0000 and TOC 0x7C0000 contain the same files but from different SDK versions.  
| 0x7FC00
*TOC 0xC0000 is SDK version 3.41 and TOC 0x7C0000 is SDK version 3.30 (look at the content of files '''sdk_version''').  
| 0x80010
*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.  
| 0x20000
*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.
|-  
 
| trvk_pkg1
===== TOC Entry  =====
| 0x400
 
| 7
A TOC entry is 0x30 bytes large.  
| 0x9FC00
 
| 0xA0010
offset 0x0 - relative offset from this TOC to entry data  
| 0x20000
 
|-  
offset 0x8 - entry data size  
| ros0
 
| 0x400
offset 0x10 - entry name (max 32 characters)  
| 8
 
| 0xBFC00
===== Main TOC  =====
| 0xC0010
 
| 0x700000
Here is a list of regions/files stored on '''/dev/rflash1''' i found in '''HV 3.41''' and dumped with PSGroove:  
|-  
 
| ros1
{| class="wikitable FCK__ShowTableBorders"
| 0x400
|-
| 9
! Entry Name  
| 0x7BFC00
! TOC Offset  
| 0x7C0010
! Entry TOC Index  
| 0x700000
! Entry Relative Offset  
|-  
! Entry Absolute Offset  
| cvtrm
! Entry Size
| 0x400
|-
| 10
| asecure_loader  
| 0xEBFC00
| 0x400  
| 0xEC0010
| 0  
| 0x40000
| 0x400  
|}<h5><span class="mw-headline" id="asecure_loader_Region_TOC"> asecure_loader Region TOC  </span></h5><p>Here is a list of files stored on <b>/dev/rflash1</b> i found in <b>HV 3.41</b> and dumped with PSGroove:  
| 0x810  
</p>
| 0x2E800
{| class="wikitable FCK&#95;_ShowTableBorders"  
|-
! Entry Name
| eEID  
! TOC Offset
| 0x400  
! Entry TOC Index
| 1  
! Entry Relative Offset
| 0x2EC00  
! Entry Absolute Offset
| 0x2F010  
! Entry Size
| 0x10000
|-  
|-
| metldr
| cISD  
| 0x800
| 0x400  
| 0
| 2  
| 0x40
| 0x3EC00  
| 0x840
| 0x3F010  
| 0xE920
| 0x800
|}<h5><span class="mw-headline" id="ros1_Region_TOC"> ros1 Region TOC  </span></h5><p>Here is a list of files stored on <b>/dev/rflash1</b> i found in <b>HV 3.41</b> and dumped with PSGroove:  
|-
</p>
| cCSD  
{| class="wikitable FCK&#95;_ShowTableBorders"  
| 0x400  
! Entry Name
| 3  
! TOC Offset
| 0x3F400  
! Entry TOC Index
| 0x3F810  
! Entry Relative Offset
| 0x800
! Entry Absolute Offset
|-
! Entry Size
| trvk_prg0  
|-  
| 0x400  
| creserved_0
| 4  
| 0xC0000
| 0x3FC00  
| 0
| 0x40010  
| 0x460
| 0x20000
| 0xC0470
|-
| 0x40000
| trvk_prg1  
|-  
| 0x400  
| sdk_version
| 5  
| 0xC0000
| 0x5FC00  
| 1
| 0x60010  
| 0x40460
| 0x20000
| 0x100470
|-
| 0x8
| trvk_pkg0  
|-  
| 0x400  
| lv1ldr
| 6  
| 0xC0000
| 0x7FC00  
| 2
| 0x80010  
| 0x40480
| 0x20000
| 0x100490
|-
| 0x1E948
| trvk_pkg1  
|-  
| 0x400  
| lv2ldr
| 7  
| 0xC0000
| 0x9FC00  
| 3
| 0xA0010  
| 0x5EE00
| 0x20000
| 0x11EE10
|-
| 0x16FF0
| ros0  
|-  
| 0x400  
| isoldr
| 8  
| 0xC0000
| 0xBFC00  
| 4
| 0xC0010  
| 0x75E00
| 0x700000
| 0x135E10
|-
| 0x13074
| ros1  
|-  
| 0x400  
| appldr
| 9  
| 0xC0000
| 0x7BFC00  
| 5
| 0x7C0010  
| 0x88E80
| 0x700000
| 0x148E90
|-
| 0x1E254
| cvtrm  
|-  
| 0x400  
| spu_pkg_rvk_verifier.self
| 10  
| 0xC0000
| 0xEBFC00  
| 6
| 0xEC0010  
| 0xA70D4
| 0x40000
| 0x1670E4
|}
| 0xFACC
 
|-  
===== asecure_loader Region TOC  =====
| spu_token_processor.self
 
| 0xC0000
Here is a list of files stored on '''/dev/rflash1''' i found in '''HV 3.41''' and dumped with PSGroove:  
| 7
 
| 0xB6BA0
{| class="wikitable FCK__ShowTableBorders"
| 0x176BB0
|-
| 0x5C94
! Entry Name  
|-  
! TOC Offset  
| spu_utoken_processor.self
! Entry TOC Index  
| 0xC0000
! Entry Relative Offset  
| 8
! Entry Absolute Offset  
| 0xBC834
! Entry Size
| 0x17C844
|-
| 0x65D0
| metldr  
|-  
| 0x800  
| sc_iso.self
| 0  
| 0xC0000
| 0x40  
| 9
| 0x840  
| 0xC2E04
| 0xE920
| 0x182E14
|}
| 0x1532C
 
|-  
===== ros1 Region TOC  =====
| aim_spu_module.self
 
| 0xC0000
Here is a list of files stored on '''/dev/rflash1''' i found in '''HV 3.41''' and dumped with PSGroove:  
| 10
 
| 0xD8130
{| class="wikitable FCK__ShowTableBorders"
| 0x198140
|-
| 0x4498
! Entry Name  
|-  
! TOC Offset  
| spp_verifier.self
! Entry TOC Index  
| 0xC0000
! Entry Relative Offset  
| 11
! Entry Absolute Offset  
| 0xDC5C8
! Entry Size
| 0x19C5D8
|-
| 0xD7F0
| creserved_0  
|-  
| 0xC0000  
| mc_iso_spu_module.self
| 0  
| 0xC0000
| 0x460  
| 12
| 0xC0470  
| 0xE9DB8
| 0x40000
| 0x1A9DC8
|-
| 0x808C
| sdk_version  
|-  
| 0xC0000  
| me_iso_spu_module.self
| 1  
| 0xC0000
| 0x40460  
| 13
| 0x100470  
| 0xF1E44
| 0x8
| 0x1B1E54
|-
| 0x88B8
| lv1ldr  
|-  
| 0xC0000  
| sv_iso_spu_module.self
| 2  
| 0xC0000
| 0x40480  
| 14
| 0x100490  
| 0xFA6FC
| 0x1E948
| 0x1BA70C
|-
| 0xC078
| lv2ldr  
|-  
| 0xC0000  
| sb_iso_spu_module.self
| 3  
| 0xC0000
| 0x5EE00  
| 15
| 0x11EE10  
| 0x106774
| 0x16FF0
| 0x1C6784
|-
| 0x5DB0
| isoldr  
|-  
| 0xC0000  
| default.spp
| 4  
| 0xC0000
| 0x75E00  
| 16
| 0x135E10  
| 0x10C524
| 0x13074
| 0x1CC534
|-
| 0x22A0
| appldr  
|-  
| 0xC0000  
| lv1.self
| 5  
| 0xC0000
| 0x88E80  
| 17
| 0x148E90  
| 0x10E800
| 0x1E254
| 0x1CE810
|-
| 0x127DF0
| spu_pkg_rvk_verifier.self  
|-  
| 0xC0000  
| lv0
| 6  
| 0xC0000
| 0xA70D4  
| 18
| 0x1670E4  
| 0x236600
| 0xFACC
| 0x2F6610
|-
| 0x3E678
| spu_token_processor.self  
|-  
| 0xC0000  
| lv2_kernel.self
| 7  
| 0xC0000
| 0xB6BA0  
| 19
| 0x176BB0  
| 0x274C78
| 0x5C94
| 0x334C88
|-
| 0x171B88
| spu_utoken_processor.self  
|-  
| 0xC0000  
| eurus_fw.bin
| 8  
| 0xC0000
| 0xBC834  
| 20
| 0x17C844  
| 0x3E6800
| 0x65D0
| 0x4A6810
|-
| 0x70F94
| sc_iso.self  
|-  
| 0xC0000  
| emer_init.self
| 9  
| 0xC0000
| 0xC2E04  
| 21
| 0x182E14  
| 0x457794
| 0x1532C
| 0x5177A4
|-
| 0x7CDB8
| aim_spu_module.self  
|-  
| 0xC0000  
| hdd_copy.self
| 10  
| 0xC0000
| 0xD8130  
| 22
| 0x198140  
| 0x4D454C
| 0x4498
| 0x59455C
|-
| 0x60D68
| spp_verifier.self  
|}<h5><span class="mw-headline" id="ros2_Region_TOC"> ros2 Region TOC  </span></h5><p>Here is a list of files stored on <b>/dev/rflash1</b> i found in <b>HV 3.41</b> and dumped with PSGroove:  
| 0xC0000  
</p>
| 11  
{| class="wikitable FCK&#95;_ShowTableBorders"  
| 0xDC5C8  
! Entry Name
| 0x19C5D8  
! TOC Offset
| 0xD7F0
! Entry TOC Index
|-
! Entry Relative Offset
| mc_iso_spu_module.self  
! Entry Absolute Offset
| 0xC0000  
! Entry Size
| 12  
|-  
| 0xE9DB8  
| creserved_0
| 0x1A9DC8  
| 0x7C0000
| 0x808C
| 0
|-
| 0x460
| me_iso_spu_module.self  
| 0x7C0470
| 0xC0000  
| 0x40000
| 13  
|-  
| 0xF1E44  
| sdk_version
| 0x1B1E54  
| 0x7C0000
| 0x88B8
| 1
|-
| 0x40460
| sv_iso_spu_module.self  
| 0x800470
| 0xC0000  
| 0x8
| 14  
|-  
| 0xFA6FC  
| lv1ldr
| 0x1BA70C  
| 0x7C0000
| 0xC078
| 2
|-
| 0x40480
| sb_iso_spu_module.self  
| 0x800490
| 0xC0000  
| 0x1E64C
| 15  
|-  
| 0x106774  
| lv2ldr
| 0x1C6784  
| 0x7C0000
| 0x5DB0
| 3
|-
| 0x5EB00
| default.spp  
| 0x81EB10
| 0xC0000  
| 0x16E30
| 16  
|-  
| 0x10C524  
| isoldr
| 0x1CC534  
| 0x7C0000
| 0x22A0
| 4
|-
| 0x75980
| lv1.self  
| 0x835990
| 0xC0000  
| 0x12EC4
| 17  
|-  
| 0x10E800  
| appldr
| 0x1CE810  
| 0x7C0000
| 0x127DF0
| 5
|-
| 0x88880
| lv0  
| 0x848890
| 0xC0000  
| 0x1DB64
| 18  
|-  
| 0x236600  
| spu_pkg_rvk_verifier.self
| 0x2F6610  
| 0x7C0000
| 0x3E678
| 6
|-
| 0xA63E4
| lv2_kernel.self  
| 0x8663F4
| 0xC0000  
| 0xFACC
| 19  
|-  
| 0x274C78  
| spu_token_processor.self
| 0x334C88  
| 0x7C0000
| 0x171B88
| 7
|-
| 0xB5EB0
| eurus_fw.bin  
| 0x875EC0
| 0xC0000  
| 0x5C94
| 20  
|-  
| 0x3E6800  
| spu_utoken_processor.self
| 0x4A6810  
| 0x7C0000
| 0x70F94
| 8
|-
| 0xBBB44
| emer_init.self  
| 0x87BB54
| 0xC0000  
| 0x65D0
| 21  
|-  
| 0x457794  
| sc_iso.self
| 0x5177A4  
| 0x7C0000
| 0x7CDB8
| 9
|-
| 0xC2114
| hdd_copy.self  
| 0x882124
| 0xC0000  
| 0x1532C
| 22  
|-  
| 0x4D454C  
| aim_spu_module.self
| 0x59455C  
| 0x7C0000
| 0x60D68
| 10
|}
| 0xD7440
 
| 0x897450
===== ros2 Region TOC  =====
| 0x4498
 
|-  
Here is a list of files stored on '''/dev/rflash1''' i found in '''HV 3.41''' and dumped with PSGroove:  
| spp_verifier.self
 
| 0x7C0000
{| class="wikitable FCK__ShowTableBorders"
| 11
|-
| 0xDB8D8
! Entry Name  
| 0x89B8E8
! TOC Offset  
| 0xD7F0
! Entry TOC Index  
|-  
! Entry Relative Offset  
| mc_iso_spu_module.self
! Entry Absolute Offset  
| 0x7C0000
! Entry Size
| 12
|-
| 0xE90C8
| creserved_0  
| 0x8A90D8
| 0x7C0000  
| 0x808C
| 0  
|-  
| 0x460  
| me_iso_spu_module.self
| 0x7C0470  
| 0x7C0000
| 0x40000
| 13
|-
| 0xF1154
| sdk_version  
| 0x8B1164
| 0x7C0000  
| 0x88B8
| 1  
|-  
| 0x40460  
| sv_iso_spu_module.self
| 0x800470  
| 0x7C0000
| 0x8
| 14
|-
| 0xF9A0C
| lv1ldr  
| 0x8B9A1C
| 0x7C0000  
| 0xC078
| 2  
|-  
| 0x40480  
| sb_iso_spu_module.self
| 0x800490  
| 0x7C0000
| 0x1E64C
| 15
|-
| 0x105A84
| lv2ldr  
| 0x8C5A94
| 0x7C0000  
| 0x5DB0
| 3  
|-  
| 0x5EB00  
| default.spp
| 0x81EB10  
| 0x7C0000
| 0x16E30
| 16
|-
| 0x10B834
| isoldr  
| 0x8CB844
| 0x7C0000  
| 0x22A0
| 4  
|-  
| 0x75980  
| lv1.self
| 0x835990  
| 0x7C0000
| 0x12EC4
| 17
|-
| 0x10DB00
| appldr  
| 0x8CDB10
| 0x7C0000  
| 0x129040
| 5  
|-  
| 0x88880  
| lv0
| 0x848890  
| 0x7C0000
| 0x1DB64
| 18
|-
| 0x236B80
| spu_pkg_rvk_verifier.self  
| 0x9F6B90
| 0x7C0000  
| 0x3E570
| 6  
|-  
| 0xA63E4  
| lv2_kernel.self
| 0x8663F4  
| 0x7C0000
| 0xFACC
| 19
|-
| 0x2750F0
| spu_token_processor.self  
| 0xA35100
| 0x7C0000  
| 0x1712D0
| 7  
|-  
| 0xB5EB0  
| eurus_fw.bin
| 0x875EC0  
| 0x7C0000
| 0x5C94
| 20
|-
| 0x3E63C0
| spu_utoken_processor.self  
| 0xBA63D0
| 0x7C0000  
| 0x70F94
| 8  
|-  
| 0xBBB44  
| emer_init.self
| 0x87BB54  
| 0x7C0000
| 0x65D0
| 21
|-
| 0x457354
| sc_iso.self  
| 0xC17364
| 0x7C0000  
| 0x7FBB8
| 9  
|-  
| 0xC2114  
| hdd_copy.self
| 0x882124  
| 0x7C0000
| 0x1532C
| 22
|-
| 0x4D6F0C
| aim_spu_module.self  
| 0xC96F1C
| 0x7C0000  
| 0x61518
| 10  
|}<h3><span class="mw-headline" id="Methods_4"> Methods </span></h3><p>initialize_starship - 0x0028298C (3.15)
| 0xD7440  
</p><p>SSOperation - 0x0027BFB0 (3.15)
| 0x897450  
</p><p>SSTransfer - 0x0027BE68 (3.15)
| 0x4498
</p><p>FLASH_Memory_SS2_on_complete - 0x00278E48 (3.15)
|-
</p><p>_FLASH_read_data - 0x0022D89C (3.15)
| spp_verifier.self  
</p><p>_FLASH_write_data - 0x0022D8C8 (3.15)
| 0x7C0000  
</p><p>FLASH_SS2_HW_Reset - 0x0027BD1C (3.15)
| 11  
</p><h2><span class="mw-headline" id="HDD_device"> HDD device  </span></h2><p>device id = 2  
| 0xDB8D8  
</p><p>block size = 512  
| 0x89B8E8  
</p><ul><li>The HDD device uses ENCDEC device.
| 0xD7F0
</li></ul><h3><span class="mw-headline" id="vtable_30"> vtable  </span></h3><p>0x00353F48 (3.15)  
|-
</p><h3><span class="mw-headline" id="Member_variables_21"> Member variables  </span></h3><p>offset 0x1590 - LBA48 capability flag (4 bytes)
| mc_iso_spu_module.self  
</p><p>offset 0x17E8 - request table (0x58 * 16 bytes)
| 0x7C0000  
</p><p>offset 0x1DB8 - request timer active flag (1 byte)
| 12  
</p><h3><span class="mw-headline" id="Regions_3"> Regions  </span></h3>
| 0xE90C8  
{| class="wikitable FCK&#95;_ShowTableBorders"  
| 0x8A90D8  
! Index
| 0x808C
! Start sector
|-
! Number of sectors
| me_iso_spu_module.self  
|-  
| 0x7C0000  
| 0
| 13  
| 0x0
| 0xF1154  
| 0x950F8B0
| 0x8B1164  
|-  
| 0x88B8
| 1
|-
| 0x8
| sv_iso_spu_module.self  
| 0x80000
| 0x7C0000  
|-  
| 14  
| 2
| 0xF9A0C  
| 0x80018
| 0x8B9A1C  
| 0x7C8F898
| 0xC078
|-  
|-
| 3
| sb_iso_spu_module.self  
| 0x7D0F8B8
| 0x7C0000  
| 0x3FFFF8
| 15  
|-  
| 0x105A84  
| 4
| 0x8C5A94  
| 0x810F8B8
| 0x5DB0
| 0x13FFFF8
|-
|-  
| default.spp  
| 5
| 0x7C0000  
| -
| 16  
| -
| 0x10B834  
|-  
| 0x8CB844  
| 6
| 0x22A0
| -
|-
| -
| lv1.self  
|-  
| 0x7C0000  
| 7
| 17  
| -
| 0x10DB00  
| -
| 0x8CDB10  
|}<h3><span class="mw-headline" id="Supported_Device_Commands_3"> Supported Device Commands  </span></h3><p>Here is the list of commands supported by HDD storage device.  
| 0x129040
</p><ul><li>The commands can be used with HV call <b>lv1_storage_send_device_command</b>.  
|-
</li><li>However, before a command is executed HV does bit manipulation with it and checks it against the value of repository node <b>ss.laid</b> or also called <b>LPAR authentication ID</b>. If this test fails then the command is NOT executed.
| lv0  
</li></ul>
| 0x7C0000  
{| class="wikitable FCK&#95;_ShowTableBorders"  
| 18  
! Command
| 0x236B80  
! Description
| 0x9F6B90  
|-  
| 0x3E570
| 0x2
|-
| LV1_STORAGE_SEND_ATA_COMMAND
| lv2_kernel.self  
|-  
| 0x7C0000  
| 0x10
| 19  
| -
| 0x2750F0  
|-  
| 0xA35100  
| 0x1B
| 0x1712D0
| ATA Set UltraDMA Mode
|-
|-  
| eurus_fw.bin  
| 0x1C
| 0x7C0000  
| ATA Set Features PIO Flow Control Transfer Mode
| 20  
|-  
| 0x3E63C0  
| 0x21
| 0xBA63D0  
| -
| 0x70F94
|-  
|-
| 0x22
| emer_init.self  
| ATA Identify Device
| 0x7C0000  
|-  
| 21  
| 0x23
| 0x457354  
| LV1_STORAGE_ATA_HDDOUT (ATA Flush Cache Ext)
| 0xC17364  
|-  
| 0x7FBB8
| 0x26
|-
| ATA Read Alternative Status
| hdd_copy.self  
|-  
| 0x7C0000  
| 0x27
| 22  
| ATA Read Error
| 0x4D6F0C  
|-  
| 0xC96F1C  
| 0x28
| 0x61518
| -
|}
|-  
 
| 0x31
=== Methods ===
| ATA Flush Cache/ATA Flush Cache Ext
 
|-  
initialize_starship - 0x0028298C (3.15)
| 0x32
 
| ATA Stanby Immediate
SSOperation - 0x0027BFB0 (3.15)
|-  
 
| 0x33
SSTransfer - 0x0027BE68 (3.15)
| -
 
|}<h2><span class="mw-headline" id="Virtual_FLASH_device_.28VFLASH.29"> Virtual FLASH device (VFLASH) </span></h2><p>device id = 3 (on Linux)/ 4 (on GameOS)  
FLASH_Memory_SS2_on_complete - 0x00278E48 (3.15)
</p><p>block size = 512  
 
</p><ul><li>It's a psuedo device.  
_FLASH_read_data - 0x0022D89C (3.15)
</li><li><b>This storage device redirects all requests to the region 1 of HDD storage device&nbsp;&#33;&#33;&#33;</b></li></ul><h3><span class="mw-headline" id="vtable_31"> vtable  </span></h3><p>0x00353D88 (3.15)  
 
</p><h3><span class="mw-headline" id="Member_variables_22"> Member variables  </span></h3><p>offset 0xD60 - pointer to a storage device that all requests are redirected to  
_FLASH_write_data - 0x0022D8C8 (3.15)
</p><p>offset 0xD68 - region ID of the storage device that all requests are redirected to  
 
</p><h3><span class="mw-headline" id="Regions_4"> Regions  </span></h3>
FLASH_SS2_HW_Reset - 0x0027BD1C (3.15)
{| class="wikitable FCK&#95;_ShowTableBorders"  
 
! Index
== HDD device  ==
! Start sector
 
! Number of sectors
device id = 2  
|-  
 
| 0
block size = 512  
| 0x0
 
| 0x80000
*The HDD device uses ENCDEC device.
|-  
 
| 1
=== vtable  ===
| 0x8
 
| 0x75F8
0x00353F48 (3.15)  
|-  
 
| 2
=== Member variables  ===
| 0x7800
 
| 0x63E00
offset 0x1590 - LBA48 capability flag (4 bytes)
|-  
 
| 3
offset 0x17E8 - request table (0x58 * 16 bytes)
| 0x6B600
 
| 0x8000
offset 0x1DB8 - request timer active flag (1 byte)
|-  
 
| 4
=== Regions  ===
| 0x73600
 
| 0x400
{| class="wikitable FCK__ShowTableBorders"
|-  
|-
| 5
! Index  
| 0x73A00
! Start sector  
| 0x2000
! Number of sectors
|-  
|-
| 6
| 0  
| 0x77C00
| 0x0  
| 0x200
| 0x950F8B0
|-  
|-
| 7
| 1  
| -
| 0x8  
| -
| 0x80000
|}<h3><span class="mw-headline" id=".2Fdev.2Frflash1_1x_and_.2Fdev.2Frflash_1xp"> /dev/rflash1_1x and /dev/rflash_1xp </span></h3><ul><li>These LPAR 1 devices access region 5 of UNKNOWN storage device.  
|-
</li><li>In region 5 of UNKNOWN storage device is e.g. LINUX image stored.
| 2  
</li></ul><h3><span class="mw-headline" id="GameOS.27s_dev_flash"> GameOS's dev_flash </span></h3><ul><li>dev_flash has <b>FAT16</b> file system.
| 0x80018  
</li><li>Accesses to GameOS's dev_flash are routed to <b>UNKNOWN storage device region 2</b></li><li>To decrypt sectors read from this region use as <b>flags 0x4</b>&nbsp;&#33;&#33;&#33; Without using <b>flags 0x4</b> the sectors will be encrypted.
| 0x7C8F898
</li><li>The sectors are decrypted not by GameOS but by ENCDEC device.
|-
</li></ul><p>Here is a snippet from raw <b>dev_flash</b> dump made with HV call <b>lv1_storage_read (flags 0x4)</b> from GameOS:
| 3  
</p><pre>
| 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 '''[[Authority ID|LPAR Authority ID]]'''. If this test fails then the command is NOT executed.
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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 Standby Immediate
|-
| 0x33  
| -
|}
 
== Virtual FLASH device (VFLASH) ==
 
device id = 3 (on Linux)/ 4 (on GameOS)  
 
block size = 512  
 
*It's a pseudo device.  
*'''This storage device redirects all requests to the region 1 of HDD storage device&nbsp;!!!'''
 
=== 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  ===
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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  
| -  
| -
|}
 
=== Supported Device Commands ===
 
Here is the list of commands supported by VFLASH storage device.  
 
{| class="wikitable FCK__ShowTableBorders"
|-
! Index
! Start sector
! Number of sectors
|-
| 0x31
| ATA Flush Cache/ATA Flush Cache Ext
| -
|}
 
=== /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:
 
<pre>
Offset      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
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  é..        .....
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.........
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
00000020  00 3E 06 00 00 00 29 00  00 00 00 4E 4F 20 4E 41  .&gt;....)....NO NA
00000030  4D 45 20 20 20 20 46 41  54 31 36 20 20 20 00 00  ME    FAT16  ..
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  ................
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
Line 2,860: Line 1,846:
000001E0  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ª
000001F0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 AA  ..............Uª
</pre>
</pre><p><br /></p><h3><span class="mw-headline" id="Methods_5"> Methods </span></h3><p>initialize_virtual_flash - 0x00282954 (3.15)
 
</p><h2><span class="mw-headline" id="Enqueueing_and_Scheduling_of_Storage_Requests"> Enqueueing and Scheduling of Storage Requests </span></h2><ul><li>HV uses a simple <b>FIFO</b> scheduling algorithm for Storage Requests and a request timeout.
 
</li><li>Each storage device has a table of size <b>16</b> to store incomming and pending Storage Requests
=== Methods ===
</li><li>ENCDEC storage device has a table of size <b>32</b> to store incomming and pending Storage Requests
 
</li><li>When a new Storage Request is submitted e.g. by HV call <b>lv1_storage_read</b> or <b>lv1_storage_write</b>, the table is scanned for a free slot, if there are no pending Storage Requests then the Storage Request is executed immediately
initialize_virtual_flash - 0x00282954 (3.15)
</li><li>When a Storage Request is completed, the finished Storage Reuqest is passed to function <b>storage_device_async_request_complete</b> and the table of Storage Requests is scanned again for the next pending Storage Request which will be executed
 
</li><li> There are 2 types of Storage Requests: <b>Read/Write (1)</b> and <b>Device Command (2)</b>.
== Enqueueing and Scheduling of Storage Requests ==
</li><li> 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 <b>flags</b> parameter passed e.g. in <b>lv1_storage_read</b> or <b>lv1_storage_write</b> is <b>ored</b> with <b>0x8</b>. That is how HV differentiates between Read and Write Storage Requests.
 
</li></ul><h3><span class="mw-headline" id="Storage_Device_Request_Table"> Storage Device Request Table </span></h3><ul><li>Each request slot is of size <b>0x58</b></li></ul><h4><span class="mw-headline" id="Request_Slot"> Request Slot </span></h4><p>offset 0x0 - state: 1 - free, 2 -&nbsp;? (4 bytes)
*HV uses a simple '''FIFO''' scheduling algorithm for Storage Requests and a request timeout.
</p><p>offset 0x4 - type: 1 - Read/Write, 2 - Command, 0x86 - ENCDEC command (4 bytes)
*Each storage device has a table of size '''16''' to store incomming and pending Storage Requests
</p><p>offset 0x10 - request tag (8 bytes)
*ENCDEC storage device has a table of size '''32''' to store incomming and pending Storage Requests
</p><p>offset 0x20 - start sector (8 bytes)
*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
</p><p>offset 0x28 - sector count (4 bytes)
*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
</p><h4><span class="mw-headline" id="ENCDEC_Storage_Device"> ENCDEC Storage Device </span></h4><ul><li>Request Table begins at <b>offset 0xDC0</b> of ENCDEC storage device.
* There are 2 types of Storage Requests: '''Read/Write (1)''' and '''Device Command (2)'''.
</li></ul><h4><span class="mw-headline" id="RBD_Storage_Device"> RBD Storage Device </span></h4><ul><li>Request Table begins at <b>offset 0x1808</b> of RBD storage device.
* 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.
</li></ul><h4><span class="mw-headline" id="FLASH_Storage_Device"> FLASH Storage Device </span></h4><ul><li>Request Table begins at <b>offset 0x18F0</b> of FLASH storage device.
 
</li></ul><h4><span class="mw-headline" id="HDD_Storage_Device"> HDD Storage Device </span></h4><ul><li>Request Table begins at <b>offset 0x17E8</b> of HDD storage device.
=== Storage Device Request Table ===
</li></ul><h3><span class="mw-headline" id="Methods_6"> Methods </span></h3><p>storage_device_HDD_enqueue_request - 0x0026E21C (3.15)
 
</p><p>storage_device_HDD_do_device_command - 0x0026CED0 (3.15)
*Each request slot is of size '''0x58'''
</p><p>storage_device_HDD_do_request - 0x0026DED8 (3.15)
 
</p><p>storage_device_HDD_request_complete - 0x0026E57C (3.15)
==== Request Slot ====
</p><p>storage_device_FLASH_enqueue_request - 0x0027A518 (3.15)
 
</p><p>storage_device_FLASH_do_request - 0x00278D1C (3.15)
offset 0x0 - state: 1 - free, 2 - ? (4 bytes)
</p><p>storage_device_FLASH_do_device_command - 0x00279250 (3.15)
 
</p><p>FLASH_Memory_SS2_on_complete - 0x00278E48 (3.15)
offset 0x4 - type: 1 - Read/Write, 2 - Command, 0x86 - ENCDEC command (4 bytes)
</p><p>storage_device_async_request_complete - 0x00255184 (3.15)
 
</p><p>storage_device_TransLparAddrToPhysAddr - 0x002533B4 (3.15)
offset 0x10 - request tag (8 bytes)
</p><p>storage_device_add_async_request_locked - 0x002527B8 (3.15)
 
</p><p>storage_device_RBD_enqueue_request - 0x002723F0 (3.15)
offset 0x20 - start sector (8 bytes)
</p><p>storage_device_RBD_do_request - 0x0025EF70 (3.15)
 
</p><p>storage_device_RBD_do_next_request - 0x00270994 (3.15)
offset 0x28 - sector count (4 bytes)
</p><p>storage_device_RBD_request_complete - 0x00271FD4 (3.15)
 
</p><p>storage_device_rbd_do_request - 0x0025EE94 (3.41)
==== ENCDEC Storage Device ====
</p><p>storage_device_rbd_do_device_command - 0x0027061C (3.41)
 
</p><h2><span class="mw-headline" id="Encryption_and_Decryption_of_Storage_Devices"> Encryption and Decryption of Storage Devices </span></h2><h3><span class="mw-headline" id="HDD"> HDD </span></h3><ul><li><b>ENCDEC peripheral device</b> is used for HDD encryption/decryption
*Request Table begins at '''offset 0xDC0''' of ENCDEC storage device.
</li><li>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 <b>ATA WriteDMAExt</b> command to HDD.
 
</li><li>When a storage device request is processed by HV, Storage Subsystem checks if cryptography is enabled for the storage device.
==== RBD Storage Device ====
</li><li>HV checks 1 byte of data owned by the storage device and when the value of this flag is <b>not 0</b> then it uses encryption/decryption.
 
</li><li><b>By setting this flag to 0 at runtime, encryption/decryption of storage devices can be disabled at runtime</b>.
*Request Table begins at '''offset 0x1808''' of RBD storage device.
</li><li><b>We could patch lv1.self so that encryption/decryption of storage devices is disabled permanently</b>.
 
</li><li>HDD sectors can be both decrypted and encrypted with HV calls
==== FLASH Storage Device ====
</li></ul><h4><span class="mw-headline" id="UFS2"> UFS2 </span></h4><ul><li><b>Superblock</b> starts at <b>sector 0x80</b>.
 
</li><li>At the end of the superblock structure you will find <b>UFS2 signature 0x19540119</b>.
*Request Table begins at '''offset 0x18F0''' of FLASH storage device.
</li></ul><p>Here is the decrypted <b>superblock</b> of UFS2 filesystem:
 
</p><pre>
==== 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:
 
<pre>
Offset      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
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
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...¸........
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....\
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  ..@.............
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  ........ÿÿÀ.ÿÿø.
00010040  00 00 00 00 00 00 00 00  FF FF C0 00 FF FF F8 00  ........ÿÿÀ.ÿÿø.
Line 2,978: Line 1,903:
00010090  00 00 00 00 F5 35 BD 07  00 00 00 00 00 00 18 00  ....õ5½.........
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  ..@.............
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
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  ................
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
000100D0  00 00 00 80 2F 63 65 6C  6C 5F 6D 77 5F 63 66 73  ...€/cell_mw_cfs
Line 3,012: Line 1,937:
000102B0  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  ................
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  .......|........
000102D0  00 00 00 00 00 00 00 7C  00 00 00 00 00 00 00 00  .......&#124;........
000102E0  00 00 00 00 00 00 00 00  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  ................
000102F0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
Line 3,030: Line 1,955:
000103D0  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  ................
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  .......<.....;Ó#
000103F0  00 00 00 00 00 00 00 3C  00 00 00 00 00 3B D3 23  .......&lt;.....;Ó#
00010400  00 00 00 00 00 7D 0F 82  00 00 00 00 00 00 00 9F  .....}.‚.......Ÿ
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  ................
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  ................
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°^;.....ò>&
00010430  00 00 00 00 49 B0 5E 3B  00 00 00 00 01 F2 3E 26  ....I°^;.....ò&gt;&amp;
00010440  00 00 00 00 01 E2 86 3B  00 00 00 00 00 00 0B B8  .....â†;.......¸
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  ................
00010450  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
Line 3,053: Line 1,978:
00010540  00 00 00 00 00 00 07 FF  00 00 00 00 00 00 00 00  .......ÿ........
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..
00010550  00 00 00 00 00 00 00 00  00 00 00 00 19 54 01 19  .............T..
</pre>
</pre><h3><span class="mw-headline" id="FLASH"> FLASH </span></h3><h3><span class="mw-headline" id="RBD"> RBD </span></h3><h2><span class="mw-headline" id="SATA.2FATA.2FATAPI"> SATA/ATA/ATAPI </span></h2><h3><span class="mw-headline" id="ATA_Interrupt_Handler"> ATA Interrupt Handler  </span></h3><p>0x0026B984 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_SetDMA"> ATA_SetDMA  </span></h3><p>0x00268ADC (3.15)  
Other examples:<br />
</p><h3><span class="mw-headline" id="ATA_make_PRD_table"> ATA_make_PRD_table  </span></h3><p>0x00267DB4 (3.15)  
http://pastebin.com/3L241qu3
</p><p>This function initializes a PRD (Physical Region Descriptor) table.  
http://pastebin.com/WJv40nUQ
</p><h3><span class="mw-headline" id="ClearPATACInterrupt"> ClearPATACInterrupt  </span></h3><p>0x00267CAC (3.15)  
http://pastie.org/1529241
</p><h3><span class="mw-headline" id="EnablePATACInterrupt"> EnablePATACInterrupt  </span></h3><p>0x00267D44 (3.15)  
http://pastie.org/1588747
</p><h3><span class="mw-headline" id="DisablePATACInterrupt"> DisablePATACInterrupt  </span></h3><p>0x00267AF0 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_read_AltStatus_reg"> ATA_read_AltStatus_reg  </span></h3><p>0x00267C40 (3.15)  
=== FLASH ===
</p><p>This function reads the ATA Alternate Status Register and returns it's value.  
 
</p><h3><span class="mw-headline" id="ATA_write_DATA_reg"> ATA_write_DATA_reg  </span></h3><p>0x00268A10 (3.15)  
=== RBD ===
</p><p>This function writes a 16-bit value to the ATA Data Register.  
 
</p><h3><span class="mw-headline" id="ATA_read_DATA_reg"> ATA_read_DATA_reg  </span></h3><p>0x0026887C (3.15)  
== SATA/ATA/ATAPI ==
</p><h3><span class="mw-headline" id="ATA_write_DATA"> ATA_write_DATA  </span></h3><p>0x0026635C (3.15)  
 
</p><p>This function writes several 16-bit values to the ATA Data register.  
=== ATA Interrupt Handler  ===
</p><h3><span class="mw-headline" id="ATA_write_CMD_reg"> ATA_write_CMD_reg  </span></h3><p>0x002688A0 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_read_Error_reg"> ATA_read_Error_reg  </span></h3><p>0x00267BD4 (3.15)  
0x0026B984 (3.15)  
</p><h3><span class="mw-headline" id="ATA_write_Features_reg"> ATA_write_Features_reg  </span></h3><p>0x002689F0 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_write_DevCtrl_reg"> ATA_write_DevCtrl_reg  </span></h3><p>0x00267BB4 (3.15)  
=== ATA_SetDMA  ===
</p><h3><span class="mw-headline" id="ATA_write_TaskFile_regs"> ATA_write_TaskFile_regs  </span></h3><p>0x00266BC8 (3.15) 0x002665A0 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_send_ATAPI_cmd"> ATA_send_ATAPI_cmd  </span></h3><p>0x002655F4 (3.15)  
0x00268ADC (3.15)  
</p><h3><span class="mw-headline" id="ATA_send_cmd"> ATA_send_cmd  </span></h3><p>0x0026580C (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_send_ReadSectors_cmd"> ATA_send_ReadSectors_cmd  </span></h3><p>This function uses LBA28.  
=== ATA_make_PRD_table  ===
</p><p>0x0025D2B4 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_send_WriteSectors_cmd"> ATA_send_WriteSectors_cmd  </span></h3><p>This function uses LBA28.  
0x00267DB4 (3.15)  
</p><p>0x0025CEF4 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_send_ReadDMA_cmd"> ATA_send_ReadDMA_cmd  </span></h3><p>This function uses LBA28.  
This function initializes a PRD (Physical Region Descriptor) table.  
</p><p>0x0025D380 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_send_WriteDMA_cmd"> ATA_send_WriteDMA_cmd  </span></h3><p>This function uses LBA28.  
=== ClearPATACInterrupt  ===
</p><p>0x0025CFB8 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_send_ReadDMAExt_cmd"> ATA_send_ReadDMAExt_cmd  </span></h3><p>This function uses LBA48.  
0x00267CAC (3.15)  
</p><p>0x0025D74C (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_send_WriteDMAExt_cmd"> ATA_send_WriteDMAExt_cmd  </span></h3><p>This function uses LBA48.  
=== EnablePATACInterrupt  ===
</p><p>0x0025D664 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_send_IdentifyDevice_cmd"> ATA_send_IdentifyDevice_cmd  </span></h3><p>0x0025D4D8 (3.15)  
0x00267D44 (3.15)  
</p><h3><span class="mw-headline" id="ATA_send_IdentifyPacketDevice_cmd"> ATA_send_IdentifyPacketDevice_cmd  </span></h3><p>0x0025D448 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_send_FlushCache_cmd"> ATA_send_FlushCache_cmd  </span></h3><p>0x0025D5E8 (3.15)  
=== DisablePATACInterrupt  ===
</p><h3><span class="mw-headline" id="ATA_send_FlushCacheExt_cmd"> ATA_send_FlushCacheExt_cmd  </span></h3><p>0x0025D568 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_send_StandbyImmediate_cmd"> ATA_send_StandbyImmediate_cmd  </span></h3><p>0x0025D07C (3.15)  
0x00267AF0 (3.15)  
</p><h3><span class="mw-headline" id="ATA_send_SetFeatures_cmd"> ATA_send_SetFeatures_cmd  </span></h3><p>0x0025D208 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_send_SMARTEnable_cmd"> ATA_send_SMARTEnable_cmd  </span></h3><p>0x0025D0F8 (3.15)  
=== ATA_read_AltStatus_reg  ===
</p><h3><span class="mw-headline" id="ATA_send_SMARTSaveAttributeValue_cmd"> ATA_send_SMARTSaveAttributeValue_cmd  </span></h3><p>0x0025D180 (3.15)  
 
</p><h3><span class="mw-headline" id="ATA_SetUDMAMode"> ATA_SetUDMAMode  </span></h3><p>0x00260EE8 (3.15)  
0x00267C40 (3.15)  
</p><h4><span class="mw-headline" id="Parameters_3"> Parameters  </span></h4><p>r5 - UltraDMA mode (0-5)
 
</p><h2><span class="mw-headline" id="Booting_a_Bootloader_from_VFLASH"> Booting a Bootloader from VFLASH </span></h2><p>Coming soon&nbsp;&#33;&#33;&#33;
This function reads the ATA Alternate Status Register and returns it's value.  
</p><h1><span class="mw-headline" id="High_precision_timers"> High precision timers  </span></h1><p>These timers are used e.g. in SATA/ATA/ATAPI driver.  
 
</p><h2><span class="mw-headline" id="timer_add"> timer_add  </span></h2><p>0x002C3F2C (3.15)  
=== ATA_write_DATA_reg  ===
</p><h2><span class="mw-headline" id="timer_del"> timer_del  </span></h2><p>0x002C41AC (3.15)  
 
</p><h2><span class="mw-headline" id="timer_run_expired"> timer_run_expired  </span></h2><p>This function is called from HDEC interrupt handler.  
0x00268A10 (3.15)  
</p><p>0x002C4020 (3.15)  
 
</p><h2><span class="mw-headline" id="timer_set_HDEC"> timer_set_HDEC  </span></h2><p>0x002BCF80 (3.15)  
This function writes a 16-bit value to the ATA Data Register.  
</p><h1><span class="mw-headline" id="SPE"> SPE  </span></h1><p>There are 3 SPE classes.  
 
</p><p>The HV call <b>lv1_construct_logical_spe</b> can create LogicalSPE, SPEType1 and SPEType2 objects.  
=== ATA_read_DATA_reg  ===
</p><p>The <b>syscall 0x10040</b> creates only SPEType1 objects.  
 
</p><p>The SPEType1 and SPEType2 objects cannot be created when isolation mode is disabled. The right most bit of repository node <b>sys.lv1.iso_enbl</b> 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 <b>sys.lv1.iso_enbl</b> is checked.  
0x0026887C (3.15)  
</p><h2><span class="mw-headline" id="LogicalSPE"> LogicalSPE  </span></h2><p>SPE type = 0  
 
</p><p>Objects of this class are used e.g. on Linux.  
=== ATA_write_DATA  ===
</p><h3><span class="mw-headline" id="vtable_32"> vtable  </span></h3><p>0x00358360 (3.15)  
 
</p><p>offset 0x20 - pointer to TOC entry of interrupt handler for SPE  
0x0026635C (3.15)  
</p><h3><span class="mw-headline" id="Member_variables_23"> Member variables  </span></h3><p>offset 0x38 - pointer to LPAR obj that owns this SPE obj  
 
</p><p>offset 0x78 - table of pointers to Outlet objects (3 * 8 bytes, one for each Class 0-2)  
This function writes several 16-bit values to the ATA Data register.  
</p><p>offset 0xB0 - pointer to VAS object  
 
</p><p>offset 0xC8 - pointer to Logical PPE object  
=== ATA_write_CMD_reg  ===
</p><p>offset 0xE0 - SPE id  
 
</p><p>offset 0x1A0 - pointer to MMIO Memory Region object  
0x002688A0 (3.15)  
</p><p>offset 0x1A8 - pointer to Shadow Registers Memory Region object  
 
</p><h3><span class="mw-headline" id="Objects_3"> Objects  </span></h3><p>Here is the list of logical SPE objects i found in HV 3.15:  
=== ATA_read_Error_reg  ===
</p><ul><li>0x003A82E0 - SPE id 0  
 
</li><li>0x003A8660 - SPE id 1  
0x00267BD4 (3.15)  
</li><li>0x003ABA00 - SPE id 2  
 
</li><li>0x003B4010 - SPE id 3  
=== ATA_write_Features_reg  ===
</li><li>0x003B4D60 - SPE id 4  
 
</li><li>0x003B5970 - SPE id 5
0x002689F0 (3.15)  
</li></ul><h2><span class="mw-headline" id="SPEType1"> SPEType1  </span></h2><p>SPE type = 1  
 
</p><h3><span class="mw-headline" id="vtable_33"> vtable  </span></h3><p>0x00359750  
=== ATA_write_DevCtrl_reg  ===
</p><h3><span class="mw-headline" id="Member_Variables_24"> Member Variables  </span></h3><p>offset 0x198 - pointer to MMIO Memory Region object  
 
</p><p>offset 0x1A0 - pointer to Shadow Registers Memory Region object  
0x00267BB4 (3.15)  
</p><h2><span class="mw-headline" id="SPEType2"> SPEType2  </span></h2><p>SPE type = 2  
 
</p><h3><span class="mw-headline" id="vtable_34"> vtable  </span></h3><p>0x00359790  
=== ATA_write_TaskFile_regs  ===
</p><h2><span class="mw-headline" id="SPE_Register_Shadow_Area"> SPE Register Shadow Area  </span></h2><ul><li>HV createas a SPE Register Shadow Area for each contstructed SPE.  
 
</li><li>The area is 1 4Kb page of physical memory.  
0x00266BC8 (3.15) 0x002665A0 (3.15)  
</li><li>When SPE state changes then HV updates data in this area.  
 
</li><li>The value of <b>shadow_addr</b> that is returned by <b>lv1_construct_logical_spe</b> is a LPAR start address of this area and it cannot be accessed until it's mapped in the HTAB.  
=== ATA_send_ATAPI_cmd  ===
</li><li>The SPE Register Shadow Area may be mapped only with read-only page protection or else HV call <b>lv1_insert_htab_entry</b> fails. I tested it with PSGroove and could map the whole memory range and read it after i constructed SPE of type 1 with <b>lv1_construct_logical_spe</b>.  
 
</li><li>The shadow_addr is also returned by <b>syscall_10040</b> (that creates SPE of type 1) but it returns already mapped Process address so HV Processes do not have to map it in HTAB.  
0x002655F4 (3.15)  
</li><li>When an isoated SPU is done, HV Processes checks the value at offset 0x30 to determine if the SPU execution was successfull or not.  
 
</li><li>GameOS checks also the value at offset 0x30 in the SPE Shadow Area.  
=== ATA_send_cmd  ===
</li><li>When GameOS creates SPE of type 1 then it maps only SPE Register Shadow Area into it's address space.
 
</li></ul><h3><span class="mw-headline" id="SPE_Register_Shadow_Area_Offsets"> SPE Register Shadow Area Offsets  </span></h3><p>0x30 - SPU_Status register value (4 bytes)  
0x0026580C (3.15)  
</p><p>0xF10 -&nbsp;?  
 
</p><p>0xF18 -&nbsp;?  
=== ATA_send_ReadSectors_cmd  ===
</p><h4><span class="mw-headline" id="Stop_Code"> Stop Code  </span></h4><ul><li>The high-order 16 bit of SPU_Status register value is a Stop Code.
 
</li></ul><p>Here is the list of Stop Codes i extracted from HV Processes which read the value at offset 0x30 when SPU is done:  
This function uses LBA28.  
</p>
 
{| class="wikitable FCK&#95;_ShowTableBorders"  
0x0025D2B4 (3.15)  
! Value
 
! Description
=== ATA_send_WriteSectors_cmd  ===
|-  
 
| 0xA
This function uses LBA28.  
| Success
 
|-  
0x0025CEF4 (3.15)  
| 0xC
 
| Access Violation (LPAR auth id error)
=== ATA_send_ReadDMA_cmd  ===
|-  
 
| 0xE
This function uses LBA28.  
| &nbsp;?
 
|-  
0x0025D380 (3.15)  
| 0xF
 
| Revoked
=== ATA_send_WriteDMA_cmd  ===
|-  
 
| 0x12
This function uses LBA28.  
| Invalid Parameter
 
|-  
0x0025CFB8 (3.15)  
| 0x13
 
| &nbsp;?
=== ATA_send_ReadDMAExt_cmd  ===
|-  
 
| 0x17
This function uses LBA48.  
| Invalid Parameter
 
|-  
0x0025D74C (3.15)  
| 0x25
 
| &nbsp;?
=== ATA_send_WriteDMAExt_cmd  ===
|}<h2><span class="mw-headline" id="SPU_send_MFC_cmd"> SPU_send_MFC_cmd  </span></h2><p>0x002B09B0 (3.15)
 
</p><p>This function programs a MFC.
This function uses LBA48.  
</p><h2><span class="mw-headline" id="SPU_write_MFC_cmd_status_reg"> SPU_write_MFC_cmd_status_reg  </span></h2><p>0x002AEE70 (3.15)
 
</p><h2><span class="mw-headline" id="SPU_write_Sig_Notify1_reg"> SPU_write_Sig_Notify1_reg  </span></h2><p>0x002AEF4C (3.15)
0x0025D664 (3.15)  
</p><h2><span class="mw-headline" id="SPU_write_Sig_Notify2_reg"> SPU_write_Sig_Notify2_reg  </span></h2><p>0x002AEF30 (3.15)
 
</p><h2><span class="mw-headline" id="SPU_write_Sig_Notify1_and_Notify2"> SPU_write_Sig_Notify1_and_Notify2  </span></h2><p>0x002B0A78 (3.15)
=== ATA_send_IdentifyDevice_cmd  ===
</p><h2><span class="mw-headline" id="SPU_enable_iso_load_request"> SPU_enable_iso_load_request  </span></h2><p>0x002AEDE0 (3.15)
 
</p><h2><span class="mw-headline" id="SPU_iso_load_request"> SPU_iso_load_request  </span></h2><p>0x002AEED0 (3.15)
0x0025D4D8 (3.15)  
</p><h2><span class="mw-headline" id="SPU_enable_runcntl"> SPU_enable_runcntl  </span></h2><p>0x002AEB24 (3.15)
 
</p><h2><span class="mw-headline" id="SPU_stop_request"> SPU_stop_request  </span></h2><p>0x002AEEF0 (3.15)
=== ATA_send_IdentifyPacketDevice_cmd  ===
</p><h2><span class="mw-headline" id="SPU_run_request"> SPU_run_request  </span></h2><p>0x002AEF10 (3.15)
 
</p><h2><span class="mw-headline" id="SPU_read_status_reg"> SPU_read_status_reg  </span></h2><p>0x002AE978 (3.15)
0x0025D448 (3.15)  
</p><h2><span class="mw-headline" id="SPU_read_Mbox_Stat_reg"> SPU_read_Mbox_Stat_reg  </span></h2><p>0x002AE998 (3.15)
 
</p><h2><span class="mw-headline" id="lv1_undocumented_function_62"> lv1_undocumented_function_62  </span></h2><p>Updates SLB entry.
=== ATA_send_FlushCache_cmd  ===
</p><h3><span class="mw-headline" id="Parameters_4"> Parameters  </span></h3><p>%r3 - SPE id
 
</p><p>%r4 -&nbsp;? (valid values: 0 - 3)
0x0025D5E8 (3.15)  
</p><p>%r5 - SLB entry index (valid values: 0 - 7)
 
</p><p>%r6 - ESID
=== ATA_send_FlushCacheExt_cmd  ===
</p><p>%r7 - VSID
 
</p><h2><span class="mw-headline" id="spe_type1_interrupt_handler"> spe_type1_interrupt_handler  </span></h2><p>0x0030E238 (3.15)
0x0025D568 (3.15)  
</p><h2><span class="mw-headline" id="spe_type2_interrupt_handler"> spe_type2_interrupt_handler  </span></h2><p>0x003103F8 (3.15)
 
</p><h2><span class="mw-headline" id="spe_type3_interrupt_handler"> spe_type3_interrupt_handler  </span></h2><p>0x002F36F4 (3.15)
=== ATA_send_StandbyImmediate_cmd  ===
</p><h2><span class="mw-headline" id="Isolation"> Isolation  </span></h2><h3><span class="mw-headline" id="Loaders_Table"> Loaders Table  </span></h3><ul><li><b>All the binary files needed for isolation and decryption are already stored in HV memory&nbsp;&#33;&#33;&#33;</b></li><li>They are probably loaded during HV initialization from FLASH.
 
</li><li>The table has 9 entries.
0x0025D07C (3.15)  
</li><li>Each entry is 16 bytes large.
 
</li></ul><p>0x00010100 (3.15)
=== ATA_send_SetFeatures_cmd  ===
</p><h5><span class="mw-headline" id="Loaders_Table_Entry"> Loaders Table Entry  </span></h5><p>offset 0x0 - pointer to data in memory
 
</p><p>offset 0x8 - size of data
0x0025D208 (3.15)  
</p><p>Here are the contents of the Loaders Table from HV 3.15:
 
</p>
=== ATA_send_SMARTEnable_cmd  ===
{|  class="wikitable FCK&#95;_ShowTableBorders"
 
!  Index
0x0025D0F8 (3.15)  
!  Name
 
!  Address of Data in HV Dump
=== ATA_send_SMARTSaveAttributeValue_cmd  ===
!  Size of Data
 
|-
0x0025D180 (3.15)  
|  0
 
|  -
=== ATA_SetUDMAMode  ===
|  0x0C150000
 
|  0x1E5CC
0x00260EE8 (3.15)  
|-
 
|  1
==== Parameters  ====
|  metldr
 
|  0x00011000
r5 - UltraDMA mode (0-5)
|  0xE8D0
 
|-
== Booting a Bootloader from VFLASH ==
|  2
 
|  lv2ldr
Coming soon !!!
|  0x00020000
 
|  0x16DA0
= High precision timers  =
|-
 
|  3
These timers are used e.g. in SATA/ATA/ATAPI driver.  
|  isoldr
 
|  0x00055000
== timer_add  ==
|  0x12E44
 
|-
0x002C3F2C (3.15)  
|  4
 
|  appldr
== timer_del  ==
|  0x00037000
 
|  0x1DAE4
0x002C41AC (3.15)  
|-
 
|  5
== timer_run_expired  ==
|  EID0
 
|  0x00068000
This function is called from HDEC interrupt handler.  
|  0x860
 
|-
0x002C4020 (3.15)  
|  6
 
|  -
== timer_set_HDEC  ==
|  0x00069010
 
|  0x8
0x002BCF80 (3.15)  
|-
 
|  7
= SPE  =
|  -
 
|  0x00069020
There are 3 SPE classes.  
|  0x50
 
|-
The HV call '''lv1_construct_logical_spe''' can create LogicalSPE, SPEType1 and SPEType2 objects.  
|  8
 
|  -
The '''syscall 0x10040''' creates only SPEType1 objects.  
|  0x00069070
 
|  0x8
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.  
|}<h4><span class="mw-headline" id="Methods_7"> Methods  </span></h4><p>get_iso_loaders_tab - 0x002B0B70 (3.15)
 
</p><p>iso_loaders_tab_get_entry - 0x002B0CB8 (3.15)
== LogicalSPE  ==
</p><h3><span class="mw-headline" id="metldr"> metldr  </span></h3><h4><span class="mw-headline" id="Loading_metldr"> Loading metldr  </span></h4><ul><li>Physical/Virtual memory address of an isolation module that should be loaded by metldr is written into SPU register <b>SPU_In_Mbox</b>. The SPU register <b>SPU_In_Mbox</b> is 32bit, so 64bit memory address is written in 2 steps.
 
</li><li>MFC relocation is turned off by clearing <b>R-bit</b> in SPU register <b>MFC_SR1</b>. By doing this, HV enables real address mode for MFC of SPU.
SPE type = 0  
</li><li>On GameOS, it also works with relocation on. You just have to initialize SLB of SPU and insert valid SLB entries.
 
</li><li>Physical/Virtual memory address of <b>metldr</b> is written to SPU registers <b>Sig_Notify1</b> and <b>Sig_Notify2</b></li><li>Isolation load request is enabled by writing SPU register <b>SPU_PrivCntl</b></li><li>Isolation load request is made by writing value <b>0x3</b> into SPU register <b>SPU_RunCntl</b></li></ul><h4><span class="mw-headline" id="Methods_8"> Methods  </span></h4><p>SPE_load_request_metldr - 0x002B00A4 (3.15)
Objects of this class are used e.g. on Linux.  
</p><h3><span class="mw-headline" id="lv2ldr"> lv2ldr  </span></h3><ul><li><b>lv2ldr</b> is used to decrypt <b>lv2_kernel.self</b></li><li>syscalls <b>0x10042</b> and <b>0x1004A</b> use <b>lv2ldr</b></li><li>syscall <b>0x10042</b> is used by HV Process 3 during LV2 LPAR construction
 
</li><li>syscall <b>0x1004A</b> uses different parameters as syscall <b>0x10042</b></li></ul><h4><span class="mw-headline" id="Methods_9"> Methods  </span></h4><p>SPE_load_request_lv2ldr_1 - 0x002AE82C (3.15)
=== vtable  ===
</p><p>SPE_load_request_lv2ldr_2 - 0x002AE8D8 (3.15)
 
</p><h4><span class="mw-headline" id="Loading_lv2ldr"> Loading lv2ldr  </span></h4><ul><li>64 bit memory address of <b>lv2ldr</b> is written into 32 bit SPU register <b>SPU_In_Mbox</b></li><li><b>metldr</b> is loaded
0x00358360 (3.15)  
</li></ul><h3><span class="mw-headline" id="isoldr"> isoldr  </span></h3><ul><li><b>isoldr</b> is used for executing isolated SPUs
 
</li><li>syscall <b>0x10043</b> and HV call <b>lv1_undocumented_function_209</b> use <b>isoldr</b> to execute isolated SPUs
offset 0x20 - pointer to TOC entry of interrupt handler for SPE  
</li><li><b>EID0 data</b> is transferred to <b>Local Storage Address 0x3E400</b> by MFC
 
</li><li><b>Revoke List For Program</b> is transferred to <b>Local Storage Address 0x3F000</b> by MFC
=== Member variables  ===
</li></ul><h4><span class="mw-headline" id="Revoke_List_For_Programs"> Revoke List For Programs  </span></h4><p>0x00361980 (3.15)
 
</p><h4><span class="mw-headline" id="Methods_10"> Methods  </span></h4><p>SPE_load_request_isoldr - 0x002B0394
offset 0x38 - pointer to LPAR obj that owns this SPE obj  
</p><h4><span class="mw-headline" id="Loading_isoldr"> Loading isoldr  </span></h4><ul><li>64 bit memory address of <b>isoldr</b> is written into 32 bit SPU register <b>SPU_In_Mbox</b></li><li><b>metldr</b> is loaded
 
</li></ul><h3><span class="mw-headline" id="appldr"> appldr  </span></h3><ul><li><b>appldr</b> is used for decryption of SELFs
offset 0x78 - table of pointers to Outlet objects (3 * 8 bytes, one for each Class 0-2)  
</li><li>HV call <b>lv1_authenticate_program_segment</b> loads <b>appldr</b></li></ul><h4><span class="mw-headline" id="Methods_11"> Methods  </span></h4><p>SPE_load_request_appldr - 0x002AE900
 
</p><h4><span class="mw-headline" id="Loading_appldr"> Loading appldr  </span></h4><ul><li>64 bit memory address of <b>isoldr</b> is written into 32 bit SPU register <b>SPU_In_Mbox</b></li><li><b>metldr</b> is loaded
offset 0xB0 - pointer to VAS object  
</li></ul><h4><span class="mw-headline" id="Decrypting_SELFs_with_appldr_and_lv1_authenticate_program_segment"> Decrypting SELFs with appldr and lv1_authenticate_program_segment  </span></h4><ul><li><b>lv1_authenticate_program_segment</b> loads and prepares <b>appldr</b> for SELF decryption.
 
</li><li>When <b>appldr</b> is ready to decrypt data, it sends a message via mailbox.
offset 0xC8 - pointer to Logical PPE object  
</li><li>The address and the size of the encrypted data is passed to <b>appldr</b> via a shared memory.
 
</li></ul><h1><span class="mw-headline" id="Socket"> Socket  </span></h1><p>The socket supports only one address family <b>0x1F</b>, one socket type <b>0</b> and one protocol <b>0</b>.
offset 0xE0 - SPE id  
</p><h2><span class="mw-headline" id="Socket_address"> Socket address  </span></h2><p>Socket address is called port ID. Valid port IDs are 0-63. Port ID 0 is reserved.
 
</p><h2><span class="mw-headline" id="Socket_state"> Socket state  </span></h2><p>2 - LISTEN
offset 0x1A0 - pointer to MMIO Memory Region object  
</p><h2><span class="mw-headline" id="Socket_table"> Socket table  </span></h2><p>The socket table contains 64 entries, one for each port ID. Each entry is 16 bytes large.
 
</p><p>The socket table is at 0x0035F6E8 (3.15).
offset 0x1A8 - pointer to Shadow Registers Memory Region object  
</p><p>Here is the list of opened sockets i found in HV 3.15:
 
</p><ul><li>0x00091FE0 (port ID 0x23, accepts connections)
=== Objects  ===
</li><li>0x00127850 (port ID 0x24, accepts connections)
 
</li><li>0x0012F810 (port ID 0x25, accepts connections)
Here is the list of logical SPE objects i found in HV 3.15:  
</li></ul><h3><span class="mw-headline" id="Socket_table_entry"> Socket table entry  </span></h3><p>offset 0x0 - pointer to Socket obj
 
</p><p>offset 0x8 - socket accepts connections or not (0 - does not accept, 1 - accepts, 1 byte)
*0x003A82E0 - SPE id 0  
</p><h2><span class="mw-headline" id="vtable_35"> vtable  </span></h2><p>0x00355DB0 (3.15)
*0x003A8660 - SPE id 1  
</p><p>offset 0xB0 - bind
*0x003ABA00 - SPE id 2  
</p><p>offset 0xB8 - listen
*0x003B4010 - SPE id 3  
</p><p>offset 0xC8 - connect
*0x003B4D60 - SPE id 4  
</p><h2><span class="mw-headline" id="Member_variables_25"> Member variables  </span></h2><p>offset 0x360 - socket state (4 bytes)
*0x003B5970 - SPE id 5
</p><p>offset 0x368 - port ID (8 bytes)
 
</p><p>offset 0x370 - max backlog queue size (8 bytes)
== SPEType1 ==
</p><h1><span class="mw-headline" id="Virtual_Address_Space"> Virtual Address Space  </span></h1><h2><span class="mw-headline" id="VAS"> VAS  </span></h2><h3><span class="mw-headline" id="vtable_36"> vtable  </span></h3><p>0x00357958 (3.15)
 
</p><h3><span class="mw-headline" id="Member_variables_26"> Member variables  </span></h3><p>offset 0x18 - pointer to LPAR that owns this VAS object
SPE type = 1  
</p><p>offset 0x48 - VAS id (8 bytes)
 
</p><p>offset 0x70 - number of page sizes (4 bytes)
=== vtable  ===
</p><p>offset 0x74 - log2 of HTAB size
 
</p><p>offset 0x78 - pointer to HTAB object
0x00359750  
</p><h3><span class="mw-headline" id="Objects_4"> Objects  </span></h3><p>Here is the list of the VAS objects i found in HV dump 3.15:
 
</p><ul><li>0x001C8050 (VAS id 2, LPAR 1)
=== Member Variables  ===
</li><li>0x003B4910 (VAS id 3, LPAR 2)
 
</li><li>0x003BDB50 (VAS id 48, LPAR 2)
offset 0x198 - pointer to MMIO Memory Region object  
</li></ul><h2><span class="mw-headline" id="HTAB"> HTAB  </span></h2><p>0x38(-0x69A8(HSPRG0)) - pointer to the currently active HTAB in LPAR
 
</p><h3><span class="mw-headline" id="vtable_37"> vtable  </span></h3><p>0x003575B0 (3.15)
offset 0x1A0 - pointer to Shadow Registers Memory Region object  
</p><h3><span class="mw-headline" id="Member_variables_27"> Member variables  </span></h3><p>offset 0x48 - pointer to first PTE
 
</p><p>offset 0x60 - LPID (4 bytes)
== SPEType2  ==
</p><p>offset 0x64 - log2 of HTAB size (4 bytes)
 
</p><h3><span class="mw-headline" id="Objects_5"> Objects  </span></h3><p>Here is the list of the HTAB objects i found in HV dump 3.15:
SPE type = 2  
</p><ul><li>0x001C8270 (VAS id 2, LPAR 1)
 
</li></ul><pre> * 0x00180000 - HTAB PTEs (HTAB size 256 kB)
=== vtable  ===
</pre><ul><li>0x003A8050 (VAS id 3, LPAR 2)
 
</li></ul><pre> * 0x00500000 - HTAB PTEs (HTAB size 1 MB)
0x00359790  
</pre><ul><li>0x003BC510 (VAS id 48, LPAR 2)
 
</li></ul><pre> * 0x00800000 - HTAB PTEs (HTAB size 1 MB)
== SPE Register Shadow Area  ==
</pre><h3><span class="mw-headline" id="LPAR_change_HTAB"> LPAR_change_HTAB  </span></h3><p>This function changes currently active HTAB. It writes to SDR1 register where HTAB address and size is stored.
 
</p><p>0x002BE5D4 (3.15)
*HV createas a SPE Register Shadow Area for each contstructed SPE.  
</p><h3><span class="mw-headline" id="Process_SLB"> Process SLB  </span></h3><p>Each HV process has 16 SLB entries.
*The area is 1 4Kb page of physical memory.  
</p><p>Each SLB entry is 16 bytes large and is in format expected by opcode <b>slbmte</b>.
*When SPE state changes then HV updates data in this area.  
</p><p>Most of the entries are zero (invalid).
*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.  
</p><p>Each process has 4 valid SLB entries: code, data, heap and stack.
*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'''.  
</p><h4><span class="mw-headline" id="Process_3"> Process 3  </span></h4><h5><span class="mw-headline" id="SLB_entries"> SLB entries  </span></h5><p>0x0012D1F0 (3.15)
*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.  
</p>
*When an isoated SPU is done, HV Processes checks the value at offset 0x30 to determine if the SPU execution was successfull or not.  
{|  class="wikitable FCK&#95;_ShowTableBorders"
*GameOS checks also the value at offset 0x30 in the SPE Shadow Area.  
!  Name
*When GameOS creates SPE of type 1 then it maps only SPE Register Shadow Area into it's address space.
!  ESID
 
!  VSID
=== SPE Register Shadow Area Offsets  ===
|-
 
|  code
0x30 - SPU_Status register value (4 bytes)  
|  0x8
 
|  0x38
0xF10 -&nbsp;?  
|-
 
|  data
0xF18 -&nbsp;?  
|  0xC
 
|  0x3C
==== Stop Code  ====
|-
 
|  heap
*The high-order 16 bit of SPU_Status register value is a Stop Code.
|  0xA
 
|  0x3A
Here is the list of Stop Codes i extracted from HV Processes which read the value at offset 0x30 when SPU is done:  
|-
 
|  stack
{| class="wikitable FCK__ShowTableBorders"
|  0xF
|-
|  0x3F
! Value  
|}<h4><span class="mw-headline" id="Process_5"> Process 5  </span></h4><h5><span class="mw-headline" id="SLB_entries_2"> SLB entries  </span></h5><p>0x00093120 (3.15)
! Description
</p>
|-
{|  class="wikitable FCK&#95;_ShowTableBorders"
| 0xA  
!  Name
| Success
!  ESID
|-
!  VSID
| 0xC  
|-
| Access Violation (LPAR auth id error)
|  code
|-
|  0x8
| 0xE  
|  0x48
| &nbsp;?
|-
|-
|  data
| 0xF  
|  0xC
| Revoked
|  0x4C
|-
|-
| 0x12  
|  heap
| Invalid Parameter
|  0xA
|-
|  0x4A
| 0x13  
|-
| &nbsp;?
|  stack
|-
|  0xF
| 0x17  
|  0x4F
| Invalid Parameter
|}<h4><span class="mw-headline" id="Process_6"> Process 6  </span></h4><h5><span class="mw-headline" id="SLB_entries_3"> SLB entries  </span></h5><p>0x000E6960 (3.15)
|-
</p>
| 0x25  
{|  class="wikitable FCK&#95;_ShowTableBorders"
| &nbsp;?
!  Name
!  ESID
!  VSID
|-
|  code
|  0x8
|  0x58
|-
|  data
|  0xC
|  0x5C
|-
|  heap
|  0xA
|  0x5A
|-
|  stack
|  0xF
|  0x5F
|}<h4><span class="mw-headline" id="Process_9"> Process 9  </span></h4><h5><span class="mw-headline" id="SLB_entries_4"> SLB entries  </span></h5><p>0x00763E20 (3.15)
</p>
{|  class="wikitable FCK&#95;_ShowTableBorders"
!  Name
!  ESID
!  VSID
|-
|  code
|  0x8
|  0x8
|-
|  data
|  0xC
|  0xC
|-
|  heap
|  0xA
|  0xA
|-
|  stack
|  0xF
|  0xF
|}<h1><span class="mw-headline" id="VUART"> VUART  </span></h1><p>VUART is a bi-directional communication link. A VUART object has a peer VUART object.
</p><p>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.
</p><h2><span class="mw-headline" id="VUART_table"> VUART table  </span></h2><p>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.
</p><p>0x00677218 (3.15) - address of VUART table of LPAR 1
</p><p>Here is the list of all VUART objects in LPAR 1 i found in HV 3.15:
</p><ul><li>0x006ABD90 - VUART 0
</li><li>0x006ABEB0 - VUART 1
</li><li>0x006A3CB0 - VUART 2
</li><li>0x006A3DD0 - VUART 3
</li><li>0x000A3410 - VUART 5
</li><li>0x000A3250 - VUART 6
</li></ul><p>VUART [0-3] are used by /dev/sc[0-3] respectively.
</p><p>VUART [0-3] are linked to VUART objects of different type i could not yet identify. These unknown VUART objects use <b>eieio</b> opcode a lot. So i think, they communicate with hardware peripheral.
</p><p>A write/read to/from /dev/sc[0-3] is a write/read to/from VUART.
</p><p><br /></p><p>0x00762AA8 (3.15) - address of VUART table of LPAR 2
</p><p>Here is the list of all VUART objects in LPAR 2 i found in HV 3.15:
</p><ul><li>0x00126660 - VUART 0
</li><li>0x000A3010 - VUART 2
</li></ul><p>VUART 0 and VUART 2 of LPAR 2 are created by Process 9 during LPAR construction.
</p><h2><span class="mw-headline" id="VUART_class"> VUART class  </span></h2><h3><span class="mw-headline" id="Member_variables_28"> Member variables  </span></h3><p>offset 0x48 - pointer to peer VUART object
</p><p>offset 0x58 - write pointer into data ring buffer
</p><p>offset 0x60 - read pointer into data ring buffer
</p><p>offset 0x68 - pointer to data ring buffer
</p><p>offset 0x70 - size of data ring buffer (8 bytes)
</p><p>offset 0x78 - size of data stored in data ring buffer currently (8 bytes)
</p><p>offset 0x88 - tx trigger (8 bytes)
</p><p>offset 0x90 - rx trigger (8 bytes)
</p><p>offset 0x98 - interrupt mask (8 bytes)
</p><p>offset 0xA8 - port number (4 bytes)
</p><h2><span class="mw-headline" id="Methods_12"> Methods  </span></h2><p>pmpi_read_virtual_uart(port, buf, size, nread) - 0x002EB30C (3.15)
</p><p>pmpi_write_virtual_uart(port, buf, size, nwritten) - 0x002EB0EC (3.15)
</p><p>VUART_read(pointer to VUART object, buf, size, nread) - 0x002E8654 (3.15)
</p><p>VUART_write(pointer to VUART object, buf, size, nwritten) - 0x002E8428 (3.15)
</p><h2><span class="mw-headline" id="Guest_OS_VUART_0_.28AV_Manager.29"> Guest OS VUART 0 (AV Manager)  </span></h2><p>All data sent to VUART 0 in LPAR 2 is written into the data buffer of VUART 5 of LPAR 1.
</p><p>VUART 5 of LPAR 1 is accessed by Process 9 in LPAR 1 through the file <b>/proc/partitions/2/vuart/0</b>.
</p><ul><li>Process 9 of LPAR 1 uses RSX syscalls to access RSX driver and memory mapped device access (/dev/ioif0).
</li></ul><h2><span class="mw-headline" id="Guest_OS_VUART_2_.28System_Manager.29"> Guest OS VUART 2 (System Manager)  </span></h2><p>All data sent to VUART 2 in LPAR 2 is written into the data buffer of VUART 6 of LPAR 1.
</p><p>VUART 6 of LPAR 1 is accessed by Process 9 in LPAR 1 through the file <b>/proc/partitions/2/vuart/2</b>.
</p><ul><li>System manager supports 62 (0-61) service ids.
</li><li>Process 9 has a SID table. SID table has 62 entries.
</li><li>Each entry is a pointer to a function responsible for processing SID packets.
</li></ul><h1><span class="mw-headline" id="A.2FV_Manager"> A/V Manager  </span></h1><ul><li>A/V Manager is running in Process 9 of HV.
</li><li>It communicates with Guest OS through <b>/proc/partitions/0/vuart/0 file</b>.
</li><li>GameOS accesses A/V Manager through <b>syscalls 367 - 370</b>.
</li><li>PS2 Soft EMU accesses A/V Manager also.
</li></ul><h1><span class="mw-headline" id="System_Manager_.28SM.29"> System Manager (SM)  </span></h1><ul><li>System Manager (SM) is running in Process 9 of HV.
</li><li>It communicates with Guest OS through <b>/proc/partitions/2/vuart/2 file</b>.
</li><li>GameOS accesses SM through <b>syscalls 372 - 415</b></li></ul><h2><span class="mw-headline" id="System_Manager_class"> System Manager class  </span></h2><h3><span class="mw-headline" id="Member_variables_29"> Member variables  </span></h3><p>offset 0x10 - LPAR state (8 bytes)
</p><p>offset 0x68 - LPAR auth id
</p><p>offset 0x70 - LPAR name
</p><p>offset 0x90 - LPAR image path
</p><p>offset 0x1C0 - LPAR ability (8 bytes)
</p><h3><span class="mw-headline" id="Types_of_System_Manager"> Types of System Manager  </span></h3><ul><li>There are 6 different SM types
</li><li>When Process 9 starts it reads profile file, by default <b>DEFAULT.SPP</b>, by sending requests to SPL (Secure Profile Loader) and constructs System Managers listed in this profile file.
</li><li><b>So, the profile file controls which System Manager types are available later.</b></li></ul>
{|  class="wikitable FCK&#95;_ShowTableBorders"
!  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
|}<h3><span class="mw-headline" id="Ability_Bitmask"> Ability Bitmask  </span></h3>
{|  class="wikitable FCK&#95;_ShowTableBorders"
!  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
|}
|}
 
{|  class="wikitable FCK&#95;_ShowTableBorders"
== SPU_send_MFC_cmd  ==
!  Bit Position (from right)
 
!  SID
0x002B09B0 (3.15)
!  Description
 
|-
This function programs a MFC.
|  1
 
|  5 (SET_NEXT_OP)
== SPU_write_MFC_cmd_status_reg  ==
|  Shutdown or Reboot LPAR
 
|-
0x002AEE70 (3.15)
|  2
 
|  5 (SET_NEXT_OP)
== SPU_write_Sig_Notify1_reg  ==
|  Boot PS3 LPAR
 
|-
0x002AEF4C (3.15)
|  3
 
|  5 (SET_NEXT_OP)
== SPU_write_Sig_Notify2_reg  ==
|  Boot PS2_SW LPAR
 
|-
0x002AEF30 (3.15)
|  4
 
|  5 (SET_NEXT_OP)
== SPU_write_Sig_Notify1_and_Notify2  ==
|  Boot LINUX LPAR
 
|-
0x002B0A78 (3.15)
|  5
 
|  12 (CONTROL_LED)
== SPU_enable_iso_load_request  ==
|  Control LED
 
|-
0x002AEDE0 (3.15)
|  6
 
|  21 (RING_BUZZER)
== SPU_iso_load_request  ==
|  Ring Buzzer
 
|-
0x002AEED0 (3.15)
|  7
 
|  19 (SET_CONFIG)
== SPU_enable_runcntl  ==
|  Set Config
 
|-
0x002AEB24 (3.15)
|  10
 
|  26 (REQUEST_ERROR_LOG)
== SPU_stop_request  ==
|  Request Error Log
 
|-
0x002AEEF0 (3.15)
|  10
 
|  28 (REQUEST_BE_COUNT)
== SPU_run_request  ==
|  Request BE Count
 
|-
0x002AEF10 (3.15)
|  10
 
|  32 (REQUEST_SYSTEM_EVENT_LOG)
== SPU_read_status_reg  ==
|  Request System Event Log
 
|-
0x002AE978 (3.15)
|  12
 
|  30 (REQUEST_SC_VERSION)
== SPU_read_Mbox_Stat_reg  ==
|  Request SC Version
 
|-
0x002AE998 (3.15)
|  14
 
|  39 (SET_SHOP_DEMO_MODE)
== lv1_undocumented_function_62  ==
|  Set Shop Demo Mode
 
|}<h2><span class="mw-headline" id="Service_ID_.28SID.29"> Service ID (SID)  </span></h2><p>SM supports 62 (0-61) SIDs.
Updates SLB entry.
</p><p>The value of SM member variable <b>ability</b> controls which SIDs may be used by LPAR.
 
</p>
=== Parameters  ===
{|  class="wikitable FCK&#95;_ShowTableBorders"
 
!  SID
%r3 - SPE id
!  Name
 
!  Description
%r4 -&nbsp;? (valid values: 0 - 3)
|-
 
|  0
%r5 - SLB entry index (valid values: 0 - 7)
|  -
 
|  -
%r6 - ESID
|-
 
|  1
%r7 - VSID
|  REQUEST
 
|  -
== spe_type1_interrupt_handler  ==
|-
 
|  2
0x0030E238 (3.15)
|  RESPONSE
 
|  -
== spe_type2_interrupt_handler  ==
|-
 
|  3
0x003103F8 (3.15)
|  COMMAND
 
|  -
== spe_type3_interrupt_handler  ==
|-
 
|  4
0x002F36F4 (3.15)
|  EXTERN_EVENT
 
|  -
== Isolation  ==
|-
 
|  5
=== Loaders Table  ===
|  SET_NEXT_OP
 
|  -
*'''All the binary files needed for isolation and decryption are already stored in HV memory&nbsp;!!!'''
|-
*They are probably loaded during HV initialization from FLASH.
|  6
*The table has 9 entries.
|  -
*Each entry is 16 bytes large.
|  -
 
|-
0x00010100 (3.15)
|  7
 
|  -
===== Loaders Table Entry  =====
|  -
 
|-
offset 0x0 - pointer to data in memory
|  8
 
|  SET_ATTR
offset 0x8 - size of data
|  -
 
|-
Here are the contents of the Loaders Table from HV 3.15:
|  9
 
|  GET_INTER_LPAR_PARAM
{| class="wikitable FCK__ShowTableBorders"
|  -
|-
|-
! Index
|  10
! Name
|  SET_INTER_LPAR_PARAM
! Address of Data in HV Dump
|  -
! Size of Data
|-
! Entry Id
|  11
|-
|  -
| 0
|  -
| lv1ldr
|-
| 0x0C150000
|  12
| 0x1E5CC
|  CONTROL_LED
| 0x01
|  -
|-
|-
| 1
|  13
| metldr
|  TEMPERATURE
| 0x00011000
|  -
| 0xE8D0
|-
| 0x00
|  14
|-
|  -
| 2
|  -
| lv2ldr
|-
| 0x00020000
|  15
| 0x16DA0
|  -
| 0x02
|  -
|-
|-
| 3
|  16
| isoldr
|  -
| 0x00055000
|  -
| 0x12E44
|-
| 0x04
|  17
|-
|  -
| 4
|  -
| appldr
|-
| 0x00037000
|  18
| 0x1DAE4
|  -
| 0x03
|  -
|-
|-
| 5
|  19
| EID0
|  SET_CONFIG
| 0x00068000
|  -
| 0x860
|-
| 0x0C
|  20
|-
|  -
| 6
|  -
| QA Flag
|-
| 0x00069010
|  21
| 0x8
|  RING_BUZZER
| 0x0F
|  -
|-
|-
| 7
|  22
| QA Flag Token
|  -
| 0x00069020
|  -
| 0x50
|-
| 0x10
|  23
|-
|  -
| 8
|  -
| Trace Level
|-
| 0x00069070
|  24
| 0x8
|  -
| 0x11
|  -
|}
|-
 
|  25
==== Methods  ====
|  FAN_POLICY
 
|  -
get_iso_loaders_tab - 0x002B0B70 (3.15)
|-
 
|  26
iso_loaders_tab_get_entry - 0x002B0CB8 (3.15)
|  REQUEST_ERROR_LOG
 
|  -
=== metldr  ===
|-
 
|  27
==== 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.
|  28
*On GameOS, it also works with relocation on. You just have to initialize SLB of SPU and insert valid SLB entries.
|  REQUEST_BE_COUNT
*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'''
|  29
 
|  -
==== Methods  ====
|  -
 
|-
SPE_load_request_metldr - 0x002B00A4 (3.15)
|  30
 
|  REQUEST_SC_VERSION
=== lv2ldr  ===
|  -
 
|-
*'''lv2ldr''' is used to decrypt '''lv2_kernel.self'''
|  31
*syscalls '''0x10042''' and '''0x1004A''' use '''lv2ldr'''
|  -
*syscall '
|  -
|-
|  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
|  -
|  -
|}<h3><span class="mw-headline" id="12_-_CONTROL_LED"> 12 - CONTROL_LED  </span></h3><ul><li>I have tested this service with PSGroove and GameOS is allowed to use it.
</li><li>GameOS <b>syscall 386</b> uses this service.
</li></ul><h4><span class="mw-headline" id="Packet_Body"> Packet Body  </span></h4><pre>struct sysmgr_ctrl_led
{
u8 field0;
u8 field1;
u8 field2;
u8 res1;
u8 field4;
u8 field5;
u8 res2[10];
};
</pre><h4><span class="mw-headline" id="Parameters_5"> Parameters  </span></h4><p>I have tested the following parameters with this service:
</p>
{|  class="wikitable FCK&#95;_ShowTableBorders"
!  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
|}<h3><span class="mw-headline" id="21_-_RING_BUZZER"> 21 - RING_BUZZER  </span></h3><ul><li>I have tested this service with PSGroove and GameOS is allowed to use it
</li></ul><h4><span class="mw-headline" id="Packet_Body_2"> Packet Body  </span></h4><pre>struct sysmgr_ring_buzzer
{
u8 res1;
u8 field1;
u8 field2;
u8 res2
{
{
    u8 field0;
u8 field0[8];
    u8 field1;
    u8 field2;
    u8 res1;
    u8 field4;
    u8 field5;
    u8 res2[10];
};
};
</pre>
</pre><h3><span class="mw-headline" id="0x19005_-_Get_Open_PS_ID"> 0x19005 - Get Open PS ID </span></h3><pre>
==== Parameters  ====
struct ss_aim_get_open_ps_id
 
I have tested the following parameters with this service:
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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  ====
<pre>struct sysmgr_ring_buzzer
{
{
    u8 res1;
u8 field0[16];
    u8 field1;
    u8 field2;
    u8 res2;
    u32 field4;
};
};
</pre>
</pre><h2><span class="mw-headline" id="0x24000_-_USB_Dongle_Authenticator"> 0x24000 - USB Dongle Authenticator </span></h2>
==== Parameters ====
{| class="wikitable FCK&#95;_ShowTableBorders"  
 
! Packet ID
I have tested the following parameters with this service:
! Description
 
|-  
{| class="wikitable FCK__ShowTableBorders"
| 0x24001
|-
| Generate Challenge
! field1
|-  
! field2
| 0x24002
! field4
| Verify Response
! Description
|}<h3><span class="mw-headline" id="0x24001_-_Generate_Challenge"> 0x24001 - Generate Challenge  </span></h3><ul><li>I have got access to this service through DM and tested it
|-
</li><li>The service expects no input parameters except those in SS packet header
| 0x29
</li><li>It uses 0x5003 service (Generate Random Number) to generate random numbers that are used in challenge body
| 0x4
</li><li>The length of a challnge body is always 23 bytes, first 3 bytes are always the same: <b>0x2E 0x02 0x01</b></li></ul><p>Here are hexdumps of some challenge bodies i let 0x24001 service generate:
| 0x6
</p><pre>2E 02 01 72 3A 0A 76 BB 81 CB 29 BC E7 B5 D6 62 7C 0E EE 23 18 A9 1D
| Makes a short single beep
</pre><pre>2E 02 01 F0 DA 78 D4 1D CB D7 C9 C7 F0 32 F4 2E 92 39 BD 3F 32 93 AA
|-
</pre><pre>2E 02 01 3B B2 9D FD A8 83 AF 9A C0 E9 13 BB AE D5 6C 8C 45 2E DE 13
| 0x29
</pre><h3><span class="mw-headline" id="0x24002_-_Verify_Response"> 0x24002 - Verify Response </span></h3><ul><li>I have got access to this service and tested it with PSGroove
| 0xA
</li><li>The response body is 25 bytes large
| 0x1B6
</li><li>The first 3 bytes have to be <b>0x2E 0x02 0x02</b> or else the check fails
| Makes a triple beep
</li><li>The 16 bit at offset 3 is a dongle ID
|-
</li><li>The dongle ID is checked if it's revoked or not
| 0x29
</li><li>When the verification succeedes then <b>product mode</b> is set to <b>1</b></li><li>The service calculates <b>USB Dongle Key</b> from <b>USB Dongle ID</b> and <b>USB Dongle Master Key</b> by using <b>HMAC SHA-1</b></li><li>The service uses <b>HMAC SHA-1</b> to calculate the correct response body from the challenge body and <b>USB Dongle Key</b></li><li>After that the service compares the calculated response body with the given one that was sent to the service
| 0x7
</li><li>It seems that <b>laid</b> and <b>paid</b> from SS packet header are used in decryption process
| 0x36
</li></ul><h4><span class="mw-headline" id="USB_Dongle_Master_Key"> USB Dongle Master Key </span></h4><ul><li>USB Dongle Master Key is stored encrypted in Process 6
| -
</li><li>The encrypted key is 64 bytes large
|-
</li><li>The decrypted key is 20 bytes large
| 0x29
</li><li>The USB Dongle Master Key is decrypted first time the service 0x24002 is used
| 0xA
</li><li>The USB Dongle Master Key is decrypted by using the service <b>0x200E (Decrypt Master)</b> of <b>Vitual TRM Manager</b></li><li>The decrypted USB Dongle Master Key is stored in Process 6 in clear text (after first usage of this service)
| 0xFFF
</li><li>When decryption of USB Dongle Master Key fails then a dummy key is used  
| Makes a continuous beep
</li><li>Unfortunately, in the HV dump 3.15 the USB Dongle Master Key was not decrypted at the moment of dumping
|}
</li><li>The first 12 bytes of decrypted USB Dongle Master Key is a magic value: <b>_USB_DONGLE_</b>. 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.
field 1 seems relative to beep tone, as 0x25 sounds different
</li></ul><p>Here is the encrypted USB Dongle Master Key from HV 3.15:
 
</p><pre>0x22 0xD5 0xD1 0x8C 0xFF 0xE2 0x4F 0xAC 0xEC 0x72 0xA2 0x42 0xA7 0x18 0x98 0x10
=== Active System Managers in HV dump 3.15  ===
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
There are 4 active SMs in HV dump.
0x20 0x3F 0x46 0x89 0x04 0x82 0xB7 0x30 0x84 0x89 0x4B 0xCC 0x9D 0xB1 0x24 0x7C
 
</pre><p>This is the <b>decrypted</b> dongle master key:
{| class="wikitable FCK__ShowTableBorders"
</p><pre>
|-
0x46 0xDC 0xEA 0xD3 0x17 0xFE 0x45 0xD8 0x09 0x23
! Index
0xEB 0x97 0xE4 0x95 0x64 0x10 0xD4 0xCD 0xB2 0xC2
! Name
</pre><p>This is the <b>decrypted</b> dongle key for dongle ID&nbsp;0xAAAA&nbsp;which works up to 3.55:
! LPAR auth id
</p><pre>
! LPAR image pathname
0x04 0x4E 0x61 0x1B 0xA6 0xA6 0xE3 0x9A 0x98 0xCF
! Ability Bitmask (Hex)
0x35 0x81 0x2C 0x80 0x68 0xC7 0xFC 0x5F 0x7A 0xE8
|-
</pre><p>Here is the USB Dongle Master Dummy Key from HV 3.15:
| 0
</p><pre>0xD1 0xFC 0x57 0x55 0xBF 0x20 0xFA 0xB2 0xD4 0xA5 0x4A 0x0A 0x0C 0x5D 0x52 0x8E
| SCE_CELLOS_PME
0xDF 0x66 0xCD 0x74
| 0x1070000001000001
</pre><h4><span class="mw-headline" id="USB_Dongle_ID_Revoke_List"> USB Dongle ID Revoke List </span></h4><ul><li>Process 6 contains a revoke list for USB Dongle IDs
| /flh/os/this_is_dummy
</li><li>The revoke list is 0x2000 bytes large. It's a bitmap.  
| 0x1
</li><li>Each bit represents a USB Dongle ID. If bit is 0 then USB Dongle ID is revoked.
|-
</li></ul><p>The following USB Dongle IDs are revoked in HV 3.15:
| 1
</p><pre>0, 2, 13, 32, 34, 176, 241
| SCE_CELLOS_SYSTEM_MGR
</pre><h2><span class="mw-headline" id="0x25000_-_User_Token_Manager"> 0x25000 - User Token Manager </span></h2>
| 0x1070000002000001
{| class="wikitable FCK&#95;_ShowTableBorders"  
| /flh/os/lv2_kernel.self
! Packet ID
| 0x3BF7EF
! Description
|-
|-  
| 2
| 0x25001
| SCE_CELLOS_SYSTEM_MGR_PS2_SW
| Encrypt User Token
| 0x1020000003000001
|-  
| /local_sys0/ps2emu/ps2_softemu.self
| 0x25002
| 0x1226D
| Decrypt User Token
|-
|}<h3><span class="mw-headline" id="User_Token"> User Token  </span></h3><ul><li>Before User Token Manager encrypts a received user token it checks it's format.
| 3  
</li><li>User Tokens are processed by <b>spu_utoken_processor.self</b></li><li>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.
| SCE_CELLOS_SYSTEM_MGR_LINUX
</li></ul><h4><span class="mw-headline" id="User_Token_Format"> User Token Format </span></h4><pre>stuct user_token_attr
| 0x1080000004000001
{
| /flh/lx/linux
uint32_t type;                                /* 0x00000001, value&nbsp;&#33;= 0x00000001 means attribute list ends here */
| 0x40012
uint32_t size;                                /* 8 + sizeof(data) */
|}
/* data follows here, size of data may be 0 */
 
}
*GameOS file image '''lv2_kernel.self''' is stored on '''/dev/rflash1'''
struct user_token
*Linux file image is stored on '''/dev/rflash_1x''' or '''/dev/rflash_1xp'''
{
 
uint32_t magic;                                /* 0x73757400 = &quot;sut�&quot; */
== Booting Linux LPAR through System Manager ==
uint32_t format_version;                      /* 0x00000001 */
 
uint64_t size;
To boot Linux LPAR from GameOS when Linux support was not removed (Ability Mask of PS3 System Manager needs patching&nbsp;!!!):
uint8_t idps[16];
 
uint64_t expire_date;
*Send SID packet '''SET_NEXT_OP''' with operation '''OP_LPAR_REBOOT''' and the index of Linux system manager to System Manager (VUART 2)
uint64_t capability;
*Send SID packet '''REQUEST''' with type '''SHUTDOWN''' to System Manager (VUART 2)
union
*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.  
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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&nbsp;!!! (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 ==
 
{| class="wikitable FCK__ShowTableBorders"
|-
! Port ID  
! Process ID
|-
| 0x23
| 6
|-
| 0x24
| 5
|-
| 0x25
| 3
|}
 
== Function ID - Port ID mapping  ==
 
{| class="wikitable FCK__ShowTableBorders"
|-
! Function ID
! Port ID
! Supported Packet IDs
! Function Description
|-
| 0x2000
| 0x23
| 0x2001 - 0x2017
| [[Virtual_TRM_Manager|Virtual TRM Manager]]
|-
| 0x3000
| 0x24
| 0x3001 - 0x3003
| [[Secure_RTC_Manager|Secure RTC]]
|-
| 0x5000
| 0x23
| 0x5001 - 0x500A
| [[Storage_Manager|Storage Manager]]
|-
| 0x6000
| 0x23
| 0x6001 - 0x6011
| [[Update_Manager|Update Manager]]
|-
| 0x8000
| 8
| 0x8001 - 0x8005
| [[Updater_Frontend|Updater Frontend]]
|-
| 0x9000
| 0x24
| 0x9001 - 0x9016
| [[SC_Manager|SC Manager]]
|-
| 0x10000
| 0x23
| 0x10001-0x10007
| [[SB_Manager|SBM (South Bridge Manager)]]
|-
| 0x11000
| 0x25
| 0x11001 - 0x11002
| [[Security_Policy_Manager|SPM (Security Policy Manager)]]
|-
| 0x14000
| 0x25
| 0x14004 - 0x14005
| [[Secure_LPAR_Loader|SLL (Secure LPAR Loader)]]
|-
| 0x15000
| 0x24
| 0x15001, 0x15003, 0x15009
| [[Secure_Profile_Loader|SPL (Secure Profile Loader)]]
|-
| 0x17000
| 0x24
| 0x17001 - 0x17017
| [[Indi_Info_Manager|Indi Info Manager]]
|-
| 0x18000
| 0x25
| 0x18001, 0x18002, 0x18004
| [[Dispatcher_Manager|Dispatcher Manager]]
|-
| 0x19000
| 0x24
| 0x19002 - 0x19005
| [[AIM_Manager|AIM]]
|-
| 0x22000
| 0x16
| 0x22001 - 0x22004
| [[Factory_Data_Manager|Factory Data Manager]]
|-
| 0x24000
| 0x23
| 0x24001 - 0x24002
| [[USB_Dongle_Authenticator|USB Dongle Authenticator]]
|-
| 0x25000
| 0x23
| 0x25001 - 0x25002
| [[User_Token_Manager|User Token Manager]]
|}
 
== SS Packet ==
 
*SS means '''Secure Service'''&nbsp;?
*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.
<pre>struct ss_header
{
{
    uint64_t packet_id;
stuct user_token_attr attrs[0];
    uint64_t function_id;
uint8_t dummy[3072];
    uint32_t retval;
} attrs;
    uint8_t res[4];
/* 0xC30 */
    uint64_t laid;             /* LPAR Authority ID */
uint8_t digest[20];
    uint64_t paid;             /* Program Authority ID */
}
}
</pre>
</pre><h1><span class="mw-headline" id="LPAR_Memory_Management"> LPAR Memory Management </span></h1><h2><span class="mw-headline" id="Memory_Region_class"> Memory Region class  </span></h2><p>This class is the base class for different memory region types.
==== SS Service Return Values ====
</p><h3><span class="mw-headline" id="vtable_38"> vtable  </span></h3><p>0x003578B0 (3.15)
 
</p><h3><span class="mw-headline" id="Member_variables_31"> Member variables </span></h3><p>offset 0x40 - pointer to LPAR object that owns this memory region
{| class="wikitable FCK__ShowTableBorders"
</p><p>offset 0x48 - type of memory region (8 bytes)
|-
</p><p>offset 0x50 - LPAR start address of memory region
! Error Code
</p><p>offset 0x58 - size of memory region (8 bytes)
! Description
</p><p>offset 0x60 - flags (8 bytes)
|-
</p><p>offset 0xA0 - log2 of page size
| 0x00000000
</p><h3><span class="mw-headline" id="Generating_New_LPAR_Memory_Region_Addresses"> Generating New LPAR Memory Region Addresses </span></h3><p>generate_new_lpar_mem_region_address(?, memory region size, log2(page size),&nbsp;?,&nbsp;?) - 002C82E8 (3.15)
| Success
</p><p>generate_new_lpar_mem_region_address - 002C6570 (3.41)
|-
</p><ul><li>The function returns a new LPAR memory region address.
| 0x00000005
</li><li>This method is used e.g. in all HV calls which create any kind of memory regions, e.g. <b>lv1_allocate_memory</b>, <b>lv1_map_htab</b>, <b>lv1_undocumented_function_114</b>, <b>lv1_construct_logical_spe</b>, <b>lv1_map_device_mmio_region</b> or <b>syscall 0x10040</b>.
| Access Violation
</li></ul><h4><span class="mw-headline" id="Encoding_LPAR_Memory_Region_Start_Addresses_and_Sizes"> Encoding LPAR Memory Region Start Addresses and Sizes </span></h4><ul><li>Size of LPAR memory region is encoded in the LPAR memory region start address.
|-
</li><li>That is why e.g. the LPAR Memory Region Start Addresses of LPAR Memory Region of size 4096 byte begin with <b>0x300000000000</b>, <b>0x300000000000 &gt;&gt; 42 = 0xC = log2(4096)</b>.
| 0x00000006
</li><li>Each LPAR has a counter (8 bytes) which is incremented by 1 every time a new LPAR Memory Region is created.
| No Entry&nbsp;?
</li><li>Before incrementing, the counter is shifted left by <b>log2(LPAR Memory Region Size)</b> and ored with <b>log2(LPAR Memory Region Size) &lt;&lt; 42</b>.
|-
</li></ul><pre>LPAR Memory Region Start Address &gt;&gt; 42 = log2(LPAR Memory Region Size)
| 0x00000009
</pre><pre>LPAR Memory Region Start Address = (log2(LPAR Memory Region Size) &lt;&lt; 42) &#124;
| Invalid Parameter
(counter &lt;&lt; log2(LPAR Memory Region Size))
|-
</pre><h5><span class="mw-headline" id="LPAR_Memory_Region_Address_Counter"> LPAR Memory Region Address Counter </span></h5><ul><li>LPAR Memory Region Address Counter is stored at address: <b>0x38(LPAR ptr) + 0x9E8</b></li><li>LPAR1's Memory Region Address Counter is at address <b>0x00677A48</b> in HV dump 3.15
| 0x0000000F
</li><li>LPAR2's Memory Region Address Counter is at address <b>0x007632D8</b> in HV dump 3.15
| Call Limit Exceeded&nbsp;?
</li><li>LPAR1's Memory Region Address Counter is at address <b>0x00677A48</b> in HV dump 3.41
|}
</li><li>LPAR2's Memory Region Address Counter is at address <b>0x00161E68</b> in HV dump 3.41
 
</li></ul><h2><span class="mw-headline" id="Physical_Memory_Region_class"> Physical Memory Region class  </span></h2><p>This type of memory region is created e.g. in <b>lv1_allocate_memory</b> HV call or in <b>syscall 0x10000</b>.  
=== Body ===
</p><h3><span class="mw-headline" id="vtable_39"> vtable  </span></h3><p>0x00357D08 (3.15)
 
</p><h3><span class="mw-headline" id="Member_variables_32"> Member variables  </span></h3><p>offset 0xB0 - pointer to object that stores a list of addresses of physical pages owned by this memory region
*The body of a SS Packet follows after the header.
</p><p>offset 0xB8 - pointer to LPAR object that owns this memory region  
*The size of the body depends on a used service.
</p><p>offset 0xC0 - reference counter (8 bytes)  
 
</p><h3><span class="mw-headline" id="Objects_6"> Objects </span></h3><p>Here is the list of physical memory region objects i found in HV 3.15.
= LPAR Memory Management  =
</p>
 
{|  class="wikitable FCK&#95;_ShowTableBorders"
== Memory Region class  ==
!  Address in HV dump
 
!  LPAR id
This class is the base class for different memory region types.
!  LPAR Start Address
 
! Size
=== vtable  ===
!  Flags
 
!  log2(Page Size)
0x003578B0 (3.15)  
!  Physical Page Addresses
 
|-
=== Member variables  ===
|  0x006B5510
 
| 1
offset 0x40 - pointer to LPAR object that owns this memory region
|  0x300000001000
 
|  0x1000
offset 0x48 - type of memory region (8 bytes)
|  0x0
 
|  0xC
offset 0x50 - LPAR start address of memory region
|  0x672000
 
|-  
offset 0x58 - size of memory region (8 bytes)
| 0x006B5E50
 
| 1
offset 0x60 - flags (8 bytes)
| 0x440000040000
 
| 0x20000
offset 0xA0 - log2 of page size
| 0x0
 
| 0x11
=== Generating New LPAR Memory Region Addresses ===
| 0x6C0000
 
|-  
generate_new_lpar_mem_region_address(?, memory region size, log2(page size), ?, ?) - 002C82E8 (3.15)
| 0x006B6980
 
| 1
generate_new_lpar_mem_region_address - 002C6570 (3.41)
| 0x440000060000
 
| 0x20000
*The function returns a new LPAR memory region address.
| 0x0
*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'''.
| 0x11
 
| 0x6E0000
==== Encoding LPAR Memory Region Start Addresses and Sizes ====
|-  
 
| 0x006B7F00
*Size of LPAR memory region is encoded in the LPAR memory region start address.
| 1
*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)'''.
| 0x400000040000
*Each LPAR has a counter (8 bytes) which is incremented by 1 every time a new LPAR Memory Region is created.
| 0x10000
*Before incrementing, the counter is shifted left by '''log2(LPAR Memory Region Size)''' and ored with '''log2(LPAR Memory Region Size) << 42'''.
| 0x0
 
| 0x10
LPAR Memory Region Start Address >> 42 = log2(LPAR Memory Region Size)
| 0x100000
 
|-  
LPAR Memory Region Start Address = (log2(LPAR Memory Region Size) << 42) |
| 0x003A80F0
    (counter << log2(LPAR Memory Region Size))
| 2
 
| 0x6C0058000000
===== LPAR Memory Region Address Counter =====
| 0x7000000
 
| 0x4
*LPAR Memory Region Address Counter is stored at address: '''0x38(LPAR ptr) + 0x9E8'''
| 0x18
*LPAR1's Memory Region Address Counter is at address '''0x00677A48''' in HV dump 3.15
| 0x1000000 - 0x7000000
*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
| 0x003BE800
*LPAR2's Memory Region Address Counter is at address '''0x00161E68''' in HV dump 3.41
| 2
 
| 0x300000047000
== Physical Memory Region class  ==
| 0x1000
 
| 0x0
This type of memory region is created e.g. in '''lv1_allocate_memory''' HV call or in '''syscall 0x10000'''.
| 0xC
 
| 0x1FA000
=== vtable  ===
|-  
 
| 0x006BDAA0
0x00357D08 (3.15)  
| 2
 
| 0x0
=== Member variables ===
| 0x8000000
 
| 0x8
offset 0xB0 - pointer to object that stores a list of addresses of physical pages owned by this memory region  
| 0x1B (single huge page)
 
| 0x8000000
offset 0xB8 - pointer to LPAR object that owns this memory region
|}<p>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.  
 
</p><h3><span class="mw-headline" id="GameOS_Physical_Memory_Regions"> GameOS Physical Memory Regions  </span></h3><ul><li>GameOS allocates nearly all physical memory of PS3 for itself&nbsp;&#33;&#33;&#33; That is why new HV calls <b>lv1_allocate_memory</b> with large memory region sizes will fail.  
offset 0xC0 - reference counter (8 bytes)
</li><li>So when someone wants a large piece of physical memory, he can borrow it from GameOS's LPAR memory region that starts at <b>0x700020000000</b>. It can be used for example to send update packages to Update Manager which are very large.
 
</li></ul><p>Here is the list of physical memory regions of GameOS i found in HV 3.41:  
=== Objects ===
</p>
 
{| class="wikitable FCK&#95;_ShowTableBorders"  
Here is the list of physical memory region objects i found in HV 3.15.
Start Address
 
! Size
{| class="wikitable FCK__ShowTableBorders"
! Access Right
|-
! Max Page Size
! Address in HV dump
! Flags
! LPAR id
! Real Addresses
! LPAR Start Address
|-  
! Size
| 0x0
! Flags
| 0x1000000
! log2(Page Size)
| 0x3
! Physical Page Addresses
| 0x18
|-
| 0x8
| 0x006B5510
| 0x1000000 - 0x1FFF000
| 1  
|-  
| 0x300000001000
| 0x500000300000
| 0x1000
| 0xA0000
| 0x0  
| 0x3
| 0xC
| 0x10
| 0x672000
| 0x8
|-
| 0x380000 - 0x38F000, 0x3B0000 - 0x3BF000, 0x1E0000 - 0x1FF000, 0x3C0000 - 0x3FF000, 0xFF00000 - 0xFF1F000
| 0x006B5E50
|-  
| 1  
| 0x700020000000
| 0x440000040000
| 0xE900000 (huge memory region)
| 0x20000  
| 0x3
| 0x0  
| 0x14
| 0x11  
| 0x0
| 0x6C0000
| 0x400000 - 0x5FF000, 0x800000 - 0xFFF000, 0x2000000 - 0xFEFF000
|-
|}<h2><span class="mw-headline" id="HTAB_Memory_Region_class"> HTAB Memory Region class  </span></h2><p>This memory region is created when a HTAB is mapped into LPAR's address space. It's created in <b>lv1_map_htab</b> HV call.  
| 0x006B6980
</p><h3><span class="mw-headline" id="vtable_40"> vtable  </span></h3><p>0x00357C98 (3.15)  
| 1  
</p><h3><span class="mw-headline" id="Member_variables_33"> Member variables  </span></h3><p>offset 0xB0 - pointer to VAS object that owns the HTAB  
| 0x440000060000
</p><h3><span class="mw-headline" id="Objects_7"> Objects  </span></h3><p>Here is the list of HTAB memory region objects i found in HV 3.15.  
| 0x20000
</p>
| 0x0  
{| class="wikitable FCK&#95;_ShowTableBorders"  
| 0x11
Address in HV dump
| 0x6E0000
! LPAR id
|-
! VAS id
| 0x006B7F00
! LPAR Start Address
| 1
! Size
| 0x400000040000
! Flags
| 0x10000
! log2(Page Size)
| 0x0
|-  
| 0x10
| 0x001FE0F0
| 0x100000
| 2
|-
| 3
| 0x003A80F0
| 0x500000C00000
| 2
| 0x100000
| 0x6C0058000000
| 0xC000000000000000
| 0x7000000
| 0x14
| 0x4
|-  
| 0x18  
| 0x003BD850
| 0x1000000 - 0x7000000
| 2
|-
| 3
| 0x003BE800  
| 0x500004300000
| 2  
| 0x100000
| 0x300000047000  
| 0xC000000000000000
| 0x1000  
| 0x14
| 0x0  
|-  
| 0xC  
| 0x003BDEA0
| 0x1FA000
| 2
|-
| 3
| 0x006BDAA0  
| 0x500004500000
| 2  
| 0x100000
| 0x0  
| 0xC000000000000000
| 0x8000000  
| 0x14
| 0x8  
|}<h3><span class="mw-headline" id="GameOS_HTAB"> GameOS HTAB  </span></h3><ul><li>HTAB of GameOS is already mapped into address space of GameOS so that is why HV call <b>lv1_map_htab</b> will fail until you unmap it with <b>lv1_unmap_htab</b></li><li>Effective address of GameOS HTAB is <b>0x800000000F000000</b></li><li>Virtual address of GameOS HTAB is <b>0xF000000</b></li><li>Size of GameOS HTAB is <b>0x40000</b></li><li>GameOS HTAB supports large pages of size <b>64K</b> and <b>1M</b></li><li>GameOS HTAB can be easily dumped by reading 0x40000 bytes at EA 0x800000000F000000
| 0x1B (single huge page)  
</li></ul><h3><span class="mw-headline" id="GameOS_SLB"> GameOS SLB  </span></h3><p>Here is the dump of SLB entries from GameOS 3.41:  
| 0x8000000
</p><pre>0x8000000008000000  0x0000000000000500
|}
 
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&nbsp;!!! 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:  
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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.  
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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:  
<pre>0x8000000008000000  0x0000000000000500
0x8000000208000000  0x0000000000020500
0x8000000208000000  0x0000000000020500
0x8000000300000000  0x0000000000030510
0x8000000300000000  0x0000000000030510
Line 5,079: Line 4,505:
0x0000000000000000  0x0000000000000000
0x0000000000000000  0x0000000000000000
0x80000000004D8088  0x80000000004D9000
0x80000000004D8088  0x80000000004D9000
</pre>
</pre><h2><span class="mw-headline" id="SPE_MMIO_Memory_Region_class"> SPE MMIO Memory Region class  </span></h2><p>This type of memory region represents MMIO memory region of a SPE. It's created e.g. in <b>lv1_construct_logical_spe</b> or in <b>syscall 0x10040</b>.
== SPE MMIO Memory Region class  ==
</p><h3><span class="mw-headline" id="vtable_41"> vtable  </span></h3><p>0x003583F8 (3.15)
 
</p><h3><span class="mw-headline" id="Member_variables_34"> Member variables  </span></h3><h3><span class="mw-headline" id="Objects_8"> Objects  </span></h3><p>Here is the list of SPE memory region objects i found in HV 3.15.
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'''.
</p>
 
{|  class="wikitable FCK&#95;_ShowTableBorders"
=== vtable  ===
!  Address in HV dump
 
!  LPAR id
0x003583F8 (3.15)
!  SPE
 
!  LPAR Start Address
=== Member variables  ===
!  Size
 
!  Physical Address
=== Objects  ===
!  Flags
 
!  log2(Page Size)
Here is the list of SPE memory region objects i found in HV 3.15.
|-
 
|  0x003ABC20
{| class="wikitable FCK__ShowTableBorders"
|  2
|-
|  1
! Address in HV dump
|  0x4C0000880000
! LPAR id
|  0x80000
! SPE
|  0x20000080000
! LPAR Start Address
|  0xA000000000000000
! Size
|  0xC
! Physical Address
|-
! Flags
|  0x003AAD70
! log2(Page Size)
|  2
|-
|  2
| 0x003ABC20
|  0x4C0000980000
| 2
|  0x80000
| 1
|  0x20000100000
| 0x4C0000880000
|  0xA000000000000000
| 0x80000
|  0xC
| 0x20000080000
|-
| 0xA000000000000000
|  0x003A8880
| 0xC
|  2
|-
|  3
| 0x003AAD70
|  0x4C0000780000
| 2
|  0x80000
| 2
|  0x20000180000
| 0x4C0000980000
|  0xA000000000000000
| 0x80000
|  0xC
| 0x20000100000
|-
| 0xA000000000000000
|  0x003B4F70
| 0xC
|  2
|-
|  4
| 0x003A8880
|  0x4C0000A80000
| 2
|  0x80000
| 3
|  0x20000200000
| 0x4C0000780000
|  0xA000000000000000
| 0x80000
|  0xC
| 0x20000180000
|-
| 0xA000000000000000
|  0x003AB700
| 0xC
|  2
|-
|  5
| 0x003B4F70
|  0x4C0000680000
| 2
|  0x80000
| 4
|  0x20000280000
| 0x4C0000A80000
|  0xA000000000000000
| 0x80000
|  0xC
| 0x20000200000
|-
| 0xA000000000000000
|  0x003B5BE0
| 0xC
|  2
|-
|  6
| 0x003AB700
|  0x4C0000B80000
| 2
|  0x80000
| 5
|  0x20000300000
| 0x4C0000680000
|  0xA000000000000000
| 0x80000
|  0xC
| 0x20000280000
|}<h2><span class="mw-headline" id="SPE_Shadow_Registers_Memory_Region_class"> SPE Shadow Registers Memory Region class  </span></h2><p>This type of memory region represents shadow registers memory region of a SPE. It's created e.g. in <b>lv1_construct_logical_spe</b> or in <b>syscall 0x10040<
| 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.
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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.
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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.
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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.
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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)
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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)
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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)
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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&nbsp;!!!
*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:
 
{| class="wikitable FCK__ShowTableBorders"
|-
! 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.
 
<pre>
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 */
};
</pre>
 
==== Calculating Packet Header Checksum ====
 
<pre>
/* 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);
</pre>
 
=== 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 <span style="background:#00FF00">0x01</span> 0x00 0x00 0x00 0x00 <span style="background:#FF0000">0x80 0x15</span> <span style="background:#FFFF00">0x00 0x00 0x00 0x00</span> <span style="background:#00FFFF">0x00 0x04</span> <span style="background:#00FFFF">0x00 0x04</span> 0x20 0x02 0x07 0x01
 
And here is the response to the above request:
0x14 <span style="background:#00FF00">0x01</span> 0x00 0x00 0x00 0x00 <span style="background:#FF0000">0x80 0x15</span> <span style="background:#FFFF00">0x00 0x00 0x00 0x03</span> <span style="background:#00FFFF">0x00 0x05</span> <span style="background:#00FFFF">0x00 0x05</span> 0x00 0x02 0x07
Please note that all contributions to PS3 Developer wiki are considered to be released under the GNU Free Documentation License 1.2 (see PS3 Developer wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To protect the wiki against automated edit spam, we kindly ask you to solve the following hCaptcha:

Cancel Editing help (opens in new window)