From WiiBrew
Jump to navigation Jump to search

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:

ELF header:

The second-to-last program header is the syscall table. For example:

$ arm-eabi-readelf -l ~/wii/system_updates/boot2.elf  | tail -2
 LOAD           0x0230d5 0xffff7f60 0xffff7f60 0x00a88 0x00a88 RW  0x10
 LOAD           0x023b5d 0xffff8a00 0xffff8a00 0x00000 0x071e8 RW  0x20


elf_header:134C01A0 elf32_phdr < 1, 0x230D5, syscall_base, syscall_base, 0xA88, 0xA88,  6, 0x10>
elf_header:134C01C0 elf32_phdr < 1, 0x23B5D, current_thread_context, current_thread_context, 0, 0x71E8,  6, 0x20>

Syscall Handler: The second vector is the invalid instruction handler, which is used to implement syscalls:

kernel:FFFF0000               LDR     PC, =_reset
kernel:FFFF0004               LDR     PC, =starlet_syscall_handler

kernel:FFFF1894             starlet_syscall_handler                 ; CODE XREF: start�j
kernel:FFFF1894 E9 CD 7F FF                 STMFA   SP, {R0-LR}^
kernel:FFFF1898 E1 4F 80 00                 MRS     R8, SPSR
kernel:FFFF189C E5 8D 80 00                 STR     R8, [SP,#arg_0]
kernel:FFFF18A0 E5 8D E0 40                 STR     LR, [SP,#arg_40]
kernel:FFFF18A4 E5 1E A0 04                 LDR     R10, [LR,#-4]
kernel:FFFF18A8 E3 CA 9D 7F                 BIC     R9, R10, #0x1FC0
kernel:FFFF18AC E5 9F 84 9C                 LDR     R8, =0xE6000010
kernel:FFFF18B0 E3 C9 90 20                 BIC     R9, R9, #0x20
kernel:FFFF18B4 E1 59 00 08                 CMP     R9, R8
kernel:FFFF18B8 1A 00 00 1F                 BNE     loc_FFFF193C
kernel:FFFF18BC E1 A0 A2 CA                 MOV     R10, R10,ASR#5
kernel:FFFF18C0 E2 0A A0 FF                 AND     R10, R10, #0xFF
kernel:FFFF18C4 E3 5A 00 75                 CMP     R10, #0x75 ; 'u'
kernel:FFFF18C8 CA 00 00 11                 BGT     loc_FFFF1914
kernel:FFFF18CC E1 A0 80 0D                 MOV     R8, SP
kernel:FFFF18D0 E3 A0 B0 1F                 MOV     R11, #0x1F
kernel:FFFF18D4 E1 21 F0 0B                 MSR     CPSR_c, R11
kernel:FFFF18D8 E5 98 80 44                 LDR     R8, [R8,#arg_44]
kernel:FFFF18DC E5 9F B4 70                 LDR     R11, =syscall_flags_maybe
kernel:FFFF18E0 E7 9B B1 0A                 LDR     R11, [R11,R10,LSL#2]
kernel:FFFF18E4 E0 8D D1 0B                 ADD     SP, SP, R11,LSL#2
kernel:FFFF18E8             loc_FFFF18E8                            ; CODE XREF: starlet_syscall_handler+68�j
kernel:FFFF18E8 E3 5B 00 00                 CMP     R11, #0
kernel:FFFF18EC 0A 00 00 03                 BEQ     loc_FFFF1900
kernel:FFFF18F0 E5 3D 90 04                 LDR     R9, [SP,#var_4]!
kernel:FFFF18F4 E5 28 90 04                 STR     R9, [R8,#-4]!
kernel:FFFF18F8 E2 4B B0 01                 SUB     R11, R11, #1
kernel:FFFF18FC EA FF FF F9                 B       loc_FFFF18E8
kernel:FFFF1900             loc_FFFF1900                            ; CODE XREF: starlet_syscall_handler+58�j
kernel:FFFF1900 E1 A0 D0 08                 MOV     SP, R8
kernel:FFFF1904 E5 9F B4 4C                 LDR     R11, =syscall_base
kernel:FFFF1908 E7 9B B1 0A                 LDR     R11, [R11,R10,LSL#2]
kernel:FFFF190C E1 A0 E0 0F                 MOV     LR, PC
kernel:FFFF1910 E1 2F FF 1B                 BX      R11
kernel:FFFF1914             loc_FFFF1914                            ; CODE XREF: starlet_syscall_handler+34�j
kernel:FFFF1914 E3 A0 B0 DB                 MOV     R11, #0xDB ; '¦'
kernel:FFFF1918 E1 21 F0 0B                 MSR     CPSR_c, R11
kernel:FFFF191C E5 9D B0 00                 LDR     R11, [SP,#arg_0]
kernel:FFFF1920 E1 6F F0 0B                 MSR     SPSR_cxsf, R11
kernel:FFFF1924 E1 A0 E0 00                 MOV     LR, R0
kernel:FFFF1928 E9 DD 7F FF                 LDMED   SP, {R0-LR}^
kernel:FFFF192C E1 A0 00 00                 NOP
kernel:FFFF1930 E1 A0 00 0E                 MOV     R0, LR
kernel:FFFF1934 E5 9D E0 40                 LDR     LR, [SP,#arg_40]
kernel:FFFF1938 E1 B0 F0 0E                 MOVS    PC, LR
kernel:FFFF193C             loc_FFFF193C                            ; CODE XREF: starlet_syscall_handler+24�j
kernel:FFFF193C E5 9F D4 18                 LDR     SP, =current_thread_context
kernel:FFFF1940 E5 9D D0 00                 LDR     SP, [SP,#arg_0]
kernel:FFFF1944 E5 8D E0 40                 STR     LR, [SP,#arg_40]
kernel:FFFF1948 E3 A0 E0 06                 MOV     LR, #6
kernel:FFFF194C E5 8D E0 50                 STR     LR, [SP,#arg_50]
kernel:FFFF1950 E2 8D D0 04                 ADD     SP, SP, #4
kernel:FFFF1954 E9 4D 7F FF                 STMFD   SP, {R0-LR}^
kernel:FFFF1958 E1 4F B0 00                 MRS     R11, SPSR
kernel:FFFF195C E5 0D B0 04                 STR     R11, [SP,#-4+arg_0]
kernel:FFFF1960 EA 00 00 C9                 B       schedule
kernel:FFFF1960             ; End of function starlet_syscall_handler

Syscalls are invoked by way of the invalid instruction handler; syscalls take the form 0xE6000010 | (syscall_num << 5). (E.g. E6000010 is syscall 0, E60006D0 is syscall 0x36, etc.)

tmbinc has written an IDAPython script which can take a database that has "syscall_base" defined, and transform the references to it into more meaningful things -- it is available here: IOS/Syscall_IDAPython

(please feel free to contribute your own findings!)

ID # Internal name Description Return value
0 u32 thread_create( u32 (*proc)(void* arg), u8 priority, u32* stack, u32 stacksize, void* arg, BOOL autostart) Creates a thread Returns threadid
1 thread_join
2 thread_cancel
3 get_tid
4 get_pid
5 thread_continue
6 thread_stop
7 thread_yield
8 thread_get_priority
9 thread_set_priority
a message_queue_create
b message_queue_destroy
c message_queue_send
d message_queue_send_now
e message_queue_receive
f RegisterEventHandler
10 UnregisterEventHandler
11 timer_create
12 timer_restart
13 timer_stop
14 timer_destroy
15 timer_now
16 heap_create
17 heap_destroy
18 heap_alloc
19 heap_alloc_aligned
1a heap_free
1b BOOL device_register(char* device, u32 messagequeue) Registers device to the device tree, so it can be opened (from Starlet and PPC) Returns 0 on success, else error
1c u32 device_open(char* device, int mode) Similar to IOS_Open on PPC, except now internal to the IOS system Returns an fd
1d device_close
1e device_read
1f device_write
20 device_seek
21 device_ioctl
22 device_ioctlv
23 device_open_async
24 device_close_async
25 device_read_async
26 device_write_async
27 device_seek_async
28 device_ioctl_async
29 device_ioctlv_async
2a syscall_2a seems to set the return value of a received message
2b SetUID
2c get_hmac_queue_for_pid
2d SetGID
2e lookup_GID_maybe
2f cc_ahbMemFlush
30 syscall_ahbMemFlush_wrapper
31 software_IRQ_31 seems to enable hardware interrupts for device nr 31
32 software_irq_18 seems to enable hardware interrupts for device nr 18
33 software_IRQ_7_or_8(id) seems to enable hardware interrupts for device nr 7 if id==0, else device nr 8
34 software_IRQ(id) seems to enable hardware interrupts for device nr. id
35 _return_0
36 syscall_36
37 syscall_37
38 iobuf_log_header_info
39 iobuf_log_buffer_info
3a syscall_3a
3b syscall_3b
3c syscall_3c
3d syscall_3d
3e syscall_3e
3f void sync_before_read(u32 address, u32 size) Invalidates dcache, and something (probably related to flushing memory)
40 sync_after_write
41 ppc_boot
42 ios_boot
43 syscall_43
44 int syscall_assert_di_reset Clears bit 10 of 0xD800194 Returns 0 on success, -1 on error
45 int syscall_deassert_di_reset Enables bit 10 of 0xD800194 Returns 0 on success, -1 on error
46 BOOL syscall_check_di_reset Checks bit 10 of 0xD800194 Returns 1 on reset asserted, 0 on (deasserted or error)
47 zero_r0_r1
48 set_r0_1_r1_0
49 get_boot_vector
4a syscall_4a
4b kernel_debug_print
4c kernel_set_version
4d kernel_get_version
4e poke_E0_1
4f virt_to_phys
50 syscall_50
51 syscall_51
52 syscall_52
53 syscall_53
54 syscall_54
55 get_bc_flag
56 poke_gpios
57 syscall_57
58 call_poke_debug_port
59 create_key
5a destroy_key
5b es_syscall_5b
5c es_syscall_5c
5d set_public_key
5e es_syscall_5e
5f es_syscall_5f
60 es_syscall_60
61 get_keyid
62 es_syscall_62
63 es_syscall_63
64 sha_async
65 sha
66 aes_async
67 aes
68 es_syscall_68
69 es_syscall_69
6a es_syscall_6a
6b hmac
6c hmac_async
6d es_syscall_6d
6e get_ng_cert
6f key_set_permission_mask
70 es_syscall_70
71 es_syscall_71
72 es_syscall_72
73 es_syscall_73
74 es_syscall_74
75 ??
76 ??