Line 6: |
Line 6: |
| | | |
| == Syscalls (via undefined instructions) == | | == Syscalls (via undefined instructions) == |
− | Internally, IOS uses a syscall table that is stored toward the end of the binary. The exact address varies with version of IOS, but there are two methods to locate it: | + | Internally, IOS uses a syscall table that is stored toward the end of the main kernel binary. The exact address varies with version of IOS, but there are two methods to locate it: |
| | | |
| ELF header: | | ELF header: |
Line 12: |
Line 12: |
| The second-to-last program header is the syscall table. For example: | | The second-to-last program header is the syscall table. For example: |
| $ arm-eabi-readelf -l ~/wii/system_updates/boot2.elf | tail -2 | | $ arm-eabi-readelf -l ~/wii/system_updates/boot2.elf | tail -2 |
− | LOAD 0x0230d5 0xffff7f60 0xffff7f60 0x00a88 0x00a88 RW 0x10 | + | LOAD 0x0230d5 0xffff7f60 0xffff7f60 0x00a88 0x00a88 RW 0x10 # syscall table |
− | LOAD 0x023b5d 0xffff8a00 0xffff8a00 0x00000 0x071e8 RW 0x20 | + | LOAD 0x023b5d 0xffff8a00 0xffff8a00 0x00000 0x071e8 RW 0x20 # kernel BSS |
| | | |
| or | | or |
Line 33: |
Line 33: |
| kernel:FFFF1F38 E3 CA 9D 7F BIC R9, R10, #NOT 0xFFFFE03F | | kernel:FFFF1F38 E3 CA 9D 7F BIC R9, R10, #NOT 0xFFFFE03F |
| kernel:FFFF1F3C E5 9F 84 CC LDR R8, =0xE6000010 ; syscall base | | kernel:FFFF1F3C E5 9F 84 CC LDR R8, =0xE6000010 ; syscall base |
− | kernel:FFFF1F40 E3 C9 90 20 BIC R9, R9, #NOT 0xFFFFFFDF | + | kernel:FFFF1F40 E3 C9 90 20 BIC R9, R9, #NOT 0xFFFFFFDF ; R9 = R10 & FFFFE01F |
− | kernel:FFFF1F44 E1 59 00 08 CMP R9, R8 ; ??? | + | kernel:FFFF1F44 E1 59 00 08 CMP R9, R8 ; Were any bits set other than the syscall number |
− | kernel:FFFF1F48 1A 00 00 1F BNE loc_FFFF1FCC | + | kernel:FFFF1F48 1A 00 00 1F BNE invalid_syscall |
| kernel:FFFF1F4C E1 A0 A2 CA MOV R10, R10,ASR#5 ; R10 = R10 >> 5 | | kernel:FFFF1F4C E1 A0 A2 CA MOV R10, R10,ASR#5 ; R10 = R10 >> 5 |
| kernel:FFFF1F50 E2 0A A0 FF AND R10, R10, #0xFF ; R10 = R10 & 0xFF | | kernel:FFFF1F50 E2 0A A0 FF AND R10, R10, #0xFF ; R10 = R10 & 0xFF |
− | kernel:FFFF1F54 E3 5A 00 7A CMP R10, #0x7A ; max index of syscall ? | + | kernel:FFFF1F54 E3 5A 00 7A CMP R10, #0x7A ; max index of syscall |
| kernel:FFFF1F58 CA 00 00 11 BGT return_to_caller | | kernel:FFFF1F58 CA 00 00 11 BGT return_to_caller |
| kernel:FFFF1F5C E1 A0 80 0D MOV R8, SP | | kernel:FFFF1F5C E1 A0 80 0D MOV R8, SP |
Line 46: |
Line 46: |
| kernel:FFFF1F6C E5 9F B4 A0 LDR R11, =literal_2 | | kernel:FFFF1F6C E5 9F B4 A0 LDR R11, =literal_2 |
| kernel:FFFF1F70 E7 9B B1 0A LDR R11, [R11,R10,LSL#2] | | kernel:FFFF1F70 E7 9B B1 0A LDR R11, [R11,R10,LSL#2] |
− | kernel:FFFF1F74 E0 8D D1 0B ADD SP, SP, R11,LSL#2 | + | kernel:FFFF1F74 E0 8D D1 0B ADD SP, SP, R11,LSL#2 ; SP += R11[R10 << 2] |
| kernel:FFFF1F78 unknown_loop ; CODE XREF: start+1F8C�j | | kernel:FFFF1F78 unknown_loop ; CODE XREF: start+1F8C�j |
| kernel:FFFF1F78 E3 5B 00 00 CMP R11, #0 | | kernel:FFFF1F78 E3 5B 00 00 CMP R11, #0 |
Line 76: |
Line 76: |
| kernel:FFFF1FC8 E1 B0 F0 0E MOVS PC, LR ; return to caller | | kernel:FFFF1FC8 E1 B0 F0 0E MOVS PC, LR ; return to caller |
| kernel:FFFF1FCC | | kernel:FFFF1FCC |
− | kernel:FFFF1FCC loc_FFFF1FCC ; CODE XREF: start+1F48�j | + | kernel:FFFF1FCC invalid_syscall ; CODE XREF: start+1F48�j |
| kernel:FFFF1FCC E5 9F D4 48 LDR SP, =current_thread_context_addr | | kernel:FFFF1FCC E5 9F D4 48 LDR SP, =current_thread_context_addr |
| kernel:FFFF1FD0 E5 9D D0 00 LDR SP, [SP,#spsr_register_save] | | kernel:FFFF1FD0 E5 9D D0 00 LDR SP, [SP,#spsr_register_save] |
Line 86: |
Line 86: |
| kernel:FFFF1FE8 E1 4F B0 00 MRS R11, SPSR | | kernel:FFFF1FE8 E1 4F B0 00 MRS R11, SPSR |
| kernel:FFFF1FEC E5 0D B0 04 STR R11, [SP,#-4+spsr_register_save] | | kernel:FFFF1FEC E5 0D B0 04 STR R11, [SP,#-4+spsr_register_save] |
− | kernel:FFFF1FF0 EA 00 00 D2 B schedule | + | kernel:FFFF1FF0 EA 00 00 D2 B schedule_yield |
| kernel:FFFF1FF0 ; End of function starlet_syscall_handler | | kernel:FFFF1FF0 ; End of function starlet_syscall_handler |
| | | |
Line 361: |
Line 361: |
| |- | | |- |
| | 76 || crypto_syscall_76 | | | 76 || crypto_syscall_76 |
| + | |- |
| + | | 77 || ? |
| + | |- |
| + | | 78 || ? |
| + | |- |
| + | | 79 || ? |
| + | |- |
| + | | 7A || ? |
| |} | | |} |
| | | |
| == Syscalls (via ARM syscall instruction) == | | == Syscalls (via ARM syscall instruction) == |
− | These types of syscalls are created with the ARM syscall instruction. The exception handler is empty and just do nothing and returns. These syscalls are [http://www.keil.com/support/man/docs/armcc/armcc_babdjeec.htm RealView semihosting operations] that allow communication with a debugger. Currently only the following syscalls are still used in distributed IOS versions: | + | These types of syscalls are created with the ARM syscall instruction. The exception handler is empty and just do nothing and returns. These syscalls are [http://www.keil.com/support/man/docs/armcc/armcc_babdjeec.htm RealView semihosting operations] that allow communication with a debugger. Currently only the following syscall is still used in production versions of IOS: |
| | | |
| <source lang="c"> | | <source lang="c"> |
Line 378: |
Line 386: |
| ! ID # !! Internal name !! Description !! Return value | | ! ID # !! Internal name !! Description !! Return value |
| |- | | |- |
− | | 4 || write(const char *string) || Prints a null-terminated debug message. || unknown. | + | | 4 || write(const char *string) || Prints a null-terminated debug message. || none. |
| |} | | |} |