Skip to content

The input output processor (IOP)

frno7 edited this page Dec 31, 2021 · 14 revisions

The input/output processor (IOP) is a MIPS R3000A, or in later PlayStation 2 models a PowerPC 405GP emulating a MIPS R3000A. It provides a number of services, particularly for peripheral devices, such as USB devices, controllers, and so on. Device drivers for these are implemented as IOP modules that the Linux kernel loads as firmware.

Examining loaded IOP modules

Loaded IOP modules are accessible via the iop-module-sysfs.ko sysfs kernel module. It gives information on IOP module file names, sizes, and addresses, and so on. The modules are numbered in directories, from 1:

# ls /sys/firmware/iop
1	4	7	10	13	16	19	22	25
2	5	8	11	14	17	20	23	26
3	6	9	12	15	18	21	24	27

Directories have module properties:

# ls /sys/firmware/iop/1
bss_size    entry       gp          name        text_size   version
data_size   flags       id          newflags    text_start

List of all module names:

# cat /sys/firmware/iop/*/name | sort -f | column
cdvd_driver		IOP_SIF_rpc_interface	ROM_file_driver
cdvd_ee_driver		irq			secrman_for_cex
dmacman			irqrelay		ssbus_service
Exception_Manager	LoadModuleByEE		Stdio
FILEIO_service		Module_Manager		SyncEE
Heap_lib		Moldule_File_loader	System_C_lib
Interrupt_Manager	Multi_Thread_Manager	System_Memory_Manager
IO/File_Manager		printk			Timer_Manager
IOP_SIF_manager		RebootByEE		Vblank_service

The memory of loaded modules can be examined using /dev/mem. First, one needs to obtain the IOP RAM base address:

# grep IOP /proc/iomem 
1c000000-1c1fffff : IOP RAM

Now let’s look at the text segment of the first module, which happens to be System_Memory_Manager:

# cd /sys/firmware/iop/1
# cat name
System_Memory_Manager
# dd if=/dev/mem bs=$(cat text_size) iflag=skip_bytes \
    skip=$(( 0x1c000000 + $(cat text_start) )) count=1 status=none | xxd | head
00000000: 0000 0000 400d 0400 0101 0000 7379 736d  ....@.......sysm
00000010: 656d 0000 9008 0000 0809 0000 8808 0000  em..............
00000020: 900c 0000 1c0b 0000 6c0b 0000 340a 0000  ........l...4...
00000030: 600a 0000 c40a 0000 d40b 0000 3c0c 0000  `...........<...
00000040: 8808 0000 8808 0000 8808 0000 c013 0000  ................
00000050: 0c14 0000 0000 0000 0800 e003 0000 0000  ................
00000060: e8ff bd27 7f00 023c 00ff 4234 2a10 4400  ...'...<..B4*.D.
00000070: 0300 4010 1000 bfaf 7f00 043c 00ff 8434  ..@........<...4
00000080: 0000 023c c315 4224 00ff 0324 2410 4300  ...<..B$...$$.C.
00000090: 0000 053c b414 a524 2418 8300 0000 a2ac  ...<...$$.......

The IOP module kernel linker

IOP modules are IRX objects based on the executable and linkable format (ELF), having the suffix .irx. All valid IOP modules have a special .iopmod section containing the module name, version, etc. IOP module link requests are only permitted if the major versions match and the module version is at least of the same minor as the requested version.

When the IOP is reset, a set of modules are automatically linked from read-only memory (ROM). Non-ROM modules are handled as firmware by the IOP module linker.

IOP modules may import and export any number of library functions, including non at all. Imported libraries must be resolved and prelinked before the given module is allowed to link itself. Other modules can link with its exported libraries.

IOP modules begin to execute their entry function immediately after linking. The modules can either stay resident in the IOP, and provide services, or unlink themselves when exiting the entry function. Many modules provide remote procedure call (RPC) services via the sub-system interface (SIF).

As a simplification the IOP module linker assumes that modules with exported libraries are resident. The primary effect is that it refuses to link modules exporting libraries with the same names more than once, even if the they may have been unlinked in the IOP. This is because the IOP module linker maintains its own list of exported libraries, rather than asking the IOP about them, which remains to be implemented.

The IOP module linker also assumes that if a module exports a library it has the same name as the module. The simplifies resolving dependencies. In general, and with most ROM modules, the module name is not the same as the exported library names. A single module may export multiple libraries, but that is currently not not fully supported with IOP modules for Linux, due to dependency resolving limitations.

The IOP module info tool

The iopmod-info tool from the iopmod repo can be used to examine IRX objects, particularly properties that other tools such as objdump doesn’t recognise:

# iopmod-info SIFMAN.irx
iopmod id addr		0xf70
iopmod id name		IOP_SIF_manager
iopmod id version	0x0101
iopmod entry addr	0x0
iopmod unknown addr	0x8f70
iopmod text size	3792
iopmod data size	176
iopmod bss size		1072
iopmod version		0x0101
iopmod name		IOP_SIF_manager
import library	0x0101	loadcore
import  0	 6
import library	0x0102	intrman
import  0	 4	intrman_request_irq
import  1	 5	intrman_release_irq
import  2	 6	intrman_enable_irq
import  3	 7	intrman_disable_irq
import  4	 9	intrman_cpu_enable_irqs
import  5	17	intrman_cpu_suspend_irq
import  6	18	intrman_cpu_resume_irq
export library	0x0101	sifman
export  0	0x0000	_init_module
export  1	0x0e48	
export  2	0x0268	
export  3	0x0e48	
export  4	0x00f4	sifman_dma2_init
export  5	0x0148	sifman_init
export  6	0x02e8	sifman_set_dchain
export  7	0x0598	sifman_set_dma
export  8	0x0740	sifman_dma_stat
export  9	0x0798	sifman_set_one_dma
export 10	0x0894	
export 11	0x08d4	
export 12	0x08ec	sifman_dma0_transfer
export 13	0x09a8	sifman_dma0_sync
export 14	0x09e8	sifman_dma0_sending
export 15	0x0a00	sifman_dma1_transfer
export 16	0x0ad8	sifman_dma1_sync
export 17	0x0b18	sifman_dma1_sending
export 18	0x0b30	sifman_dma2_transfer
export 19	0x0c34	sifman_dma2_sync
export 20	0x0c74	sifman_dma2_sending
export 21	0x0c8c	sifman_get_ms_flag
export 22	0x0cac	sifman_set_ms_flag
export 23	0x0cd8	sifman_get_sm_flag
export 24	0x0cf8	sifman_set_sm_flag
export 25	0x0d24	sifman_get_main_addr
export 26	0x0d34	sifman_get_sub_addr
export 27	0x0d48	sifman_set_sub_addr
export 28	0x0d60	sifman_intr_main
export 29	0x02d8	sifman_check_init
export 30	0x033c	sifman_set_dma_intr_handler
export 31	0x0350	sifman_reset_dma_intr_handler
export 32	0x0e48	sifman_set_dma_intr
export 33	0x0e48	
export 34	0x0e48	
export 35	0x0e48	

Issues

See #11.