Porting Openiboot
From iDroid Project
This page should act as temporary place holder for any technical information found regarding porting Openiboot to newer devices.
Contents |
3GS
Reboot
There is not a specific WDT device in 3GS device tree. The reboot sequence instead accesses several registers in PMGR.
From 3.1.2 iBoot:
LDR R1, =0xBF10021C LDR R3, =0xBF100214 MOVS R0, #0 MOVS R2, #1 STR R0, [R1] STR R2, [R3] LDR R2, =0xBF100210 MOV.W R3, #0x80000000 STR R3, [R2] MOVS R3, #4 STR R3, [R1] STR R0, [R2]
This also appears to be the same code for an iPod Touch 3G.
MIU
The MIU setup is found in the miu_init() in the LLB image instead. The register that contains MIU setting is 0xBF100000 (PMGR base address). The bit mask is now 3 instead of 7 for most other devices before this. Assume setting for map to 0x0 is 1, otherwise 2.
From 3.1.2 iLLB:
ROM:84006F44 CBZ R0, loc_84006F4C ROM:84006F46 CMP R0, #1 ROM:84006F48 BNE loc_84006F68 ROM:84006F4A B loc_84006F5A ROM:84006F4C loc_84006F4C ROM:84006F4C LDR R2, =0xBF100000 ROM:84006F4E LDR R3, [R2] ROM:84006F50 BIC.W R3, R3, #3 ROM:84006F54 ORR.W R3, R3, #1 ROM:84006F58 B loc_84006F66 ROM:84006F5A loc_84006F5A ROM:84006F5A LDR R2, =0xBF100000 ROM:84006F5C LDR R3, [R2] ROM:84006F5E BIC.W R3, R3, #3 ROM:84006F62 ORR.W R3, R3, #2 ROM:84006F66 ROM:84006F66 loc_84006F66 ROM:84006F66 STR R3, [R2] ROM:84006F68 ROM:84006F68 loc_84006F68 ROM:84006F68 LDR R3, =0xBF100000 ROM:84006F6A LDR R3, [R3] ROM:84006F6C BX LR
Vectored Interrupt Controller (VIC)
3GS is using the same PL192 VIC hardware as iPhone 2G therefore the register offsets and definitions remained the same. However the base address for 3GS has now become 0xBF200000. Also, there are now 3 "VIC cells" where each cell can fit up to 0x20 interrupts. The base address of the cells are separated by 0x10000.For example, VIC cell #0, #1 and #2 has base address at 0xBF200000, 0xBF210000 and 0xBF220000 respectively. VIC cell #0 defines interrupt from 0x0-0x1F, cell #1 from 0x20-3F and finally cell #2 from 0x40 - 5F making the maximum number of interrupts 0x60 (iphone 2g has 0x40). Below is the assembly in which this conclusion is based upon.
From 3.1.2 iBoot:
ROM:4FF102CC hw_vic_init ROM:4FF102CC ROM:4FF102CC oldR7 = -8 ROM:4FF102CC oldLR = -4 ROM:4FF102CC ROM:4FF102CC PUSH {R7,LR} ROM:4FF102CE ADD R7, SP, #0 ROM:4FF102D0 LDR.W R12, =0xBF200014 ROM:4FF102D4 MOVS R0, #0 ROM:4FF102D6 ROM:4FF102D6 loc_4FF102D6 ROM:4FF102D6 ADD.W R1, R12, #0xF0 ROM:4FF102DA MOVS R2, #1 ROM:4FF102DC MOV.W R3, #0xFFFFFFFF ROM:4FF102E0 STR.W R3, [R12] ROM:4FF102E4 ADDS R3, #1 ROM:4FF102E6 STR.W R3, [R12,#-8] ROM:4FF102EA MOVW R3, #0xFFFF ROM:4FF102EE STR.W R3, [R12,#0x10] ROM:4FF102F2 STR.W R0, [R12,#0xEC] ROM:4FF102F6 ROM:4FF102F6 loc_4FF102F6 ROM:4FF102F6 ADD.W R3, R2, R0 ROM:4FF102FA ADDS R2, #1 ROM:4FF102FC CMP R2, #0x20 ROM:4FF102FE STR.W R3, [R1],#4 ROM:4FF10302 BNE loc_4FF102F6 ROM:4FF10304 LDR R3, =0xBF230014 ROM:4FF10306 ADD.W R12, R12, #0x10000 ROM:4FF1030A ADDS R0, #0x20 ROM:4FF1030C CMP R12, R3 ROM:4FF1030E BNE loc_4FF102D6 ROM:4FF10310 BL os_exit_critical_section ROM:4FF10314 MOVS R0, #0 ROM:4FF10316 POP {R7,PC} ROM:4FF10316 ; End of function hw_vic_init
Timer
Identified 2 timer related registers.
0xBF100200 -> tickslow 0xBF100204 -> tickshigh
From 3.1.2 iBoot:
ROM:4FF04860 hw_get_timer ROM:4FF04860 LDR R1, =0xBF100204 ROM:4FF04862 LDR R3, =0xBF100200 ROM:4FF04864 LDR R2, [R1] ROM:4FF04866 LDR.W R12, [R3] ROM:4FF0486A LDR R3, [R1] ROM:4FF0486C CMP R3, R2 ROM:4FF0486E BNE hw_get_timer ROM:4FF04870 MOV R2, R3 ROM:4FF04872 MOV.W R3, #0 ROM:4FF04876 MOVS R0, #0 ROM:4FF04878 MOV R1, R2 ROM:4FF0487A MOV R2, R12 ROM:4FF0487C MOV.W R3, #0 ROM:4FF04880 ORRS R0, R2 ROM:4FF04882 ORRS R1, R3 ROM:4FF04884 BX LR ROM:4FF04884 ; End of function hw_get_timer
Scheduler related timer registers (?):
0xBF100208 0xBF100220
Clock
Frequency Setting And Derivation
Reversing clock stuffs is a tedious process at least to me therefore I am not surprised if the findings are prone to mistakes.
The base frequency seems to be 24MHz. There are 2 blocks of clock registers that together are used to derive a set of frequencies, in this case, 25 of them. These registers are initialized in iLLB and later set to default or cleared.
The first block, I called it the reference frequency derivation registers. It consists of 3 registers
0xBF100004 0xBF100008 0xBF10000C
These registers contains information to derive its own reference frequency based on a formula. My best guess on the bit definition of these registers are as follow:
(a)bit0 - status (?) (b)bit1-3 - second stage divisor factor (h)bit5 - accepted bit (this is set when the hardware has accepted the contents of the register) (c)bit8-15 - base frequency multiplier (d)bit16 - unknown (e)bit17 - ready (?) (f)bit18-19 - unknown (g)bit20-25 - first stage divisor
For example, iLLB initializes 0xBF100004 as 0x40609601
The formula for calculating the reference frequency is:
(c * 24MHz) / (g * (1 << b))
so for a value of 0x40609601, the derived reference frequency according to the above formula is 600MHz.
So according to iLLB:
*(0xBF100004) = 0x40609601 -> 600MHz *(0xBF100008) = 0x40605103 -> 162MHz *(0xBF10000C) = 0x40606403 -> 200MHz
An additional reference frequency with the same value as the base frequency (or input frequency) of 24MHz is also defined thus:
reference_frequency[] = {600000000, 162000000, 200000000, 24000000}
The second block of clock register related to frequency derivation, I like to call it the device frequency configuration registers. It consists of 25 registers ranging from 0xBF100010 to 0xBF100070. Registers at 0xBF100038 and 0xBF10004C correspond to device frequency number 11 and 16 are being treated differently for reasons unknown to me. These registers are used to derive the device frequency from the main frequencies shown above in conjunction with a configuration table.
Assumed bit definitions (device frequency from 1 - 10, 12 - 15 and 17 - 25)
(a)bit0-7 - divisor (b)bit8-9 - reference frequency selector (c)bit10 - divisor factor (normally 1) (d)bit16-23 - divisor
for device frequency 16, bit16-17 is the reference frequency selector instead.
The actual formula that is used to derive the device frequencies is quite hard to explain. I will just paste the result based on iLLB's calculation routine and also the assembly for you to reverse instead.
cfg_table[0] = 0x00000004, freq_config_register[0] = 0x00000404, device_freq[0] = 150MHz cfg_table[1] = 0x00000202, freq_config_register[1] = 0x00000602, device_freq[1] = 100MHz cfg_table[2] = 0x00000202, freq_config_register[2] = 0x00000602, device_freq[2] = 100MHz cfg_table[3] = 0x00000102, freq_config_register[3] = 0x00000502, device_freq[3] = 81MHz cfg_table[4] = 0x00000202, freq_config_register[4] = 0x00000602, device_freq[4] = 100MHz cfg_table[5] = 0x00000202, freq_config_register[5] = 0x00000602, device_freq[5] = 100MHz cfg_table[6] = 0x00000103, freq_config_register[6] = 0x00000503, device_freq[6] = 54MHz cfg_table[7] = 0x00000201, freq_config_register[7] = 0x00000601, device_freq[7] = 200MHz cfg_table[8] = 0x00000001, freq_config_register[8] = 0x00000401, device_freq[8] = 150MHz cfg_table[9] = 0x00000202, freq_config_register[9] = 0x00000602, device_freq[9] = 100MHz cfg_table[10] = 0x000A0330, freq_config_register[10] = 0x000A0F30, device_freq[10] = 50KHz cfg_table[11] = 0x00000300, freq_config_register[11] = 0x00000B00, device_freq[11] = Undefined cfg_table[12] = 0x00000001, freq_config_register[12] = 0x00000401, device_freq[12] = 150MHz cfg_table[13] = 0x00000300, freq_config_register[13] = 0x00000B00, device_freq[13] = Undefined cfg_table[14] = 0x00000104, freq_config_register[14] = 0x00000504, device_freq[14] = 40.5MHz cfg_table[15] = 0x00000301, freq_config_register[15] = 0x000C0304, device_freq[15] = 600MHz cfg_table[16] = 0x00000318, freq_config_register[16] = 0x00000718, device_freq[16] = 1MHz cfg_table[17] = 0x00000318, freq_config_register[17] = 0x00000718, device_freq[17] = 1MHz cfg_table[18] = 0x00000318, freq_config_register[18] = 0x00000718, device_freq[18] = 1MHz cfg_table[19] = 0x00000301, freq_config_register[19] = 0x00000701, device_freq[19] = 24MHz cfg_table[20] = 0x00000104, freq_config_register[20] = 0x00000504, device_freq[20] = 40.5MHz cfg_table[21] = 0x00000300, freq_config_register[21] = 0x00000B00, device_freq[21] = Undefined cfg_table[22] = 0x0000010F, freq_config_register[22] = 0x0000050F, device_freq[22] = 10.8MHz cfg_table[23] = 0x00000103, freq_config_register[23] = 0x00000503, device_freq[23] = 54MHz cfg_table[24] = 0x00000101, freq_config_register[24] = 0x00000501, device_freq[24] = 162MHz cfg_table[25] = NA , freq_config_register[25] = NA , device_freq[25] = 200MHz cfg_table[26] = NA , freq_config_register[26] = NA , device_freq[26] = 24MHz cfg_table[27] = NA , freq_config_register[27] = NA , device_freq[27] = 24MHz
Note: freq_config_register[0] correspond to register 0xBF100010, freq_config_register[1] correspond to register 0xBF100014 and so on.
To obtain the frequency from the registers (except register[10] and [15]), simply follow the following formula:
output_frequency = reference_frequency[b] / (c * a)
For example, register number 23 of value 0x50F will have b=1, c=1 and a=15 producing an output_frequency of 162/(1*15)MHz or 10.8MHz
From 3.1.2 iLLB:
ROM:840071E0 sub_840071E0 ROM:840071E0 ROM:840071E0 oldR4 = -0x14 ROM:840071E0 oldR5 = -0x10 ROM:840071E0 oldR6 = -0xC ROM:840071E0 oldR7 = -8 ROM:840071E0 oldLR = -4 ROM:840071E0 ROM:840071E0 PUSH {R4-R7,LR} ROM:840071E2 ADD R7, SP, #0xC ROM:840071E4 PUSH.W {R8,R10,R11} ROM:840071E8 BL set_clock_config ROM:840071EC MOVS R0, #0 ROM:840071EE MOVS R1, #6 ROM:840071F0 MOV R3, R0 ROM:840071F2 MOVS R2, #0x96 ROM:840071F4 BL set_main_frequency ROM:840071F8 LDR.W R8, =unk_8400FD40 ROM:840071FC LDR R3, =600000000 ROM:840071FE MOVS R0, #1 ROM:84007200 MOVS R1, #6 ROM:84007202 STR.W R3, [R8] ROM:84007206 MOVS R2, #0x51 ROM:84007208 MOV R3, R0 ROM:8400720A BL set_main_frequency ROM:8400720E LDR R3, =162000000 ROM:84007210 MOVS R2, #0x64 ROM:84007212 MOVS R0, #2 ROM:84007214 STR.W R3, [R8,#4] ROM:84007218 MOVS R1, #6 ROM:8400721A MOVS R3, #1 ROM:8400721C BL set_main_frequency ROM:84007220 LDR R3, =200000000 ROM:84007222 MOVS R2, #2 ROM:84007224 LDR R6, =0xBF100010 ROM:84007226 STR.W R3, [R8,#8] ROM:8400722A LDR R3, =24000000 ROM:8400722C LDR.W R11, =frequency_config_setup_table ROM:84007230 LDR.W R10, =derived_device_frequency ROM:84007234 STR.W R3, [R8,#0xC] ROM:84007238 LDR R3, =unk_8400FDC0 ROM:8400723A MOVS R5, #0 ROM:8400723C STR R2, [R3] ROM:8400723E LDR R3, =unk_8400FDC4 ROM:84007240 ADDS R2, R2, R2 ROM:84007242 STR R2, [R3] ROM:84007244 loc_84007244 ROM:84007244 LDR R2, =0x40EFFFF0 ROM:84007246 ADD.W R3, R6, R11 ROM:8400724A CMP R5, #0xA ROM:8400724C LDR R3, [R3,R2] ; frequency_config + offset ROM:8400724E BNE loc_84007278 ROM:84007250 LSRS R2, R3, #8 ROM:84007252 AND.W R4, R2, #3 ROM:84007256 LSRS R2, R3, #0x10 ROM:84007258 AND.W R2, R2, #0xFF ROM:8400725C AND.W R1, R3, #0xFF ROM:84007260 MUL.W R1, R1, R2 ROM:84007264 CBZ R1, loc_8400726A ROM:84007266 ORR.W R3, R3, #0x400 ROM:8400726A loc_8400726A ROM:8400726A LDR R2, =0xBF100038 ROM:8400726C ORR.W R3, R3, #0x800 ROM:84007270 STR R3, [R2] ROM:84007272 LDR.W R0, [R8,R4,LSL#2] ROM:84007276 B loc_840072B8 ROM:84007278 loc_84007278 ROM:84007278 CMP R5, #0xF ROM:8400727A BNE loc_8400729C ROM:8400727C LDR R0, =0xBF10004C ROM:8400727E AND.W R1, R3, #0xFF ROM:84007282 BIC.W R2, R3, #0xFF ROM:84007286 ORR.W R2, R2, #0xC0000 ROM:8400728A LSRS R3, R3, #0x10 ROM:8400728C ORR.W R2, R2, R1,LSL#2 ROM:84007290 STR R2, [R0] ROM:84007292 AND.W R0, R3, #3 ROM:84007296 LDR.W R0, [R8,R0,LSL#2] ROM:8400729A B loc_840072BE ROM:8400729C loc_8400729C ROM:8400729C LSRS R2, R3, #8 ROM:8400729E AND.W R4, R2, #3 ROM:840072A2 ANDS.W R1, R3, #0xFF ROM:840072A6 IT NE ROM:840072A8 ORRNE.W R3, R3, #0x400 ROM:840072AC ORR.W R3, R3, #0x800 ROM:840072B0 STR R3, [R6] ROM:840072B2 LDR.W R0, [R8,R4,LSL#2] ROM:840072B6 CBZ R5, loc_840072BE ROM:840072B8 ROM:840072B8 loc_840072B8 ROM:840072B8 CBNZ R4, loc_840072BE ROM:840072BA LDR.W R0, [R10] ROM:840072BE ROM:840072BE loc_840072BE ROM:840072BE CBZ R1, loc_840072CC ROM:840072C0 BLX udiv ROM:840072C4 LDR R3, =0x40EFFFF0 ROM:840072C6 ADD.W R4, R6, R10 ROM:840072CA STR R0, [R4,R3] ; derived_device_frequency + offset ROM:840072CC ROM:840072CC loc_840072CC ROM:840072CC ADDS R5, #1 ROM:840072CE ADDS R6, #4 ROM:840072D0 CMP R5, #0x19 ROM:840072D2 BNE loc_84007244 ROM:840072D4 LDR.W R2, [R10,#0x3C] ROM:840072D8 LDR R3, =0xAAAAAAAB ROM:840072DA MOVS R0, #0 ROM:840072DC UMULL.W R1, R3, R2, R3 ROM:840072E0 LSRS R3, R3, #1 ROM:840072E2 STR.W R3, [R10,#0x64] ROM:840072E6 LDR R3, =24000000 ROM:840072E8 STR.W R3, [R10,#0x68] ROM:840072EC STR.W R3, [R10,#0x6C] ROM:840072F0 POP.W {R8,R10,R11} ROM:840072F4 POP {R4-R7,PC} ROM:840072F4 ; End of function sub_840071E0
Clock Gates
I actually have some doubts regarding this, what I thought was clock-gate registers. The registers are from 0xBF100078 to 0xBF100144 based on the following assembly:
From 3.1.2 iBoot:
ROM:4FF18E3C set_clear_clock_gate ROM:4FF18E3C LDR.W R12, =0xBF100078 ROM:4FF18E40 LSLS R2, R0, #2 ROM:4FF18E42 ADD.W R3, R2, R12 ROM:4FF18E46 LDR R2, =0xBF100144 ROM:4FF18E48 CMP R3, R2 ROM:4FF18E4A BHI locret_4FF18E60 ROM:4FF18E4C CBZ R1, loc_4FF18E56 ROM:4FF18E4E LDR R3, [R3] ROM:4FF18E50 ORR.W R3, R3, #0b1111 ROM:4FF18E54 B loc_4FF18E5C : : : : :
It would imply that the register range allows 51 clock-gates but I am actually seeing clock-gate value higher than 51 from the ioreg output. Someone needs to make sense out of this.
GPIO
There are a maximum of 0x2E GPIO ports implied by the 3GS iBoot with a group of 8 pins forms a GPIO port.
GPIO base address = 0x83000000
There seems to be a dedicated GPIO control register for each pin.
For example, the iPhone menu button has a value of 0x1606 assigned to the GPIO pin and:
0x1606 >> 8 & 0xFF => GPIO_Port_Number 0x1606 & 0xFF => GPIO_Pin_Number
Therefore, the menu button's GPIO control register is 0x830002D8 since:
GPIO Register = 0x83000000 + (8* GPIO_Port_Number + GPIO_Pin_Number) * sizeof(Register)
So far, I have seen up to 11 lower bits of a control register being used to control a GPIO pin. There are 3 bitmasks being used to set different bits of these registers in the main GPIO control routine:
0x27E=> sets bit 1-6 and 9 0x27F=> sets bit 0-6 and 9 0x3FF=> sets bit 0-10
The available values are:
1) Bitmask 0x27E -> 0x210, 0x212, 0x230, 0x250, 0x270 2) Bitmask 0x27F -> 0x212, 0x213 3) Bitmask 0x3FF -> 0x01E, 0x09E, 0xD1E, 0x11E, 0x210, 0x212, 0x213, 0x230, 0x250, 0x290, 0x310, 0x330, 0x41E, 0x610, 0x632, 0x6B2
There are evidence that bitmask 0x27F is used to set the GPIO pin state and bitmask 0x3FF is used to reset the GPIO registers.
Here is the assembly for the GPIO control routine:
From iBoot 3.1.2:
ROM:4FF01C34 gpio_ctl ROM:4FF01C34 PUSH {R7,LR} ROM:4FF01C36 ADD R7, SP, #0 ROM:4FF01C38 LSRS R3, R0, #8 ROM:4FF01C3A AND.W R3, R3, #0xFF ROM:4FF01C3E CMP R3, #0x2E ROM:4FF01C40 AND.W R2, R0, #7 ROM:4FF01C44 BNE loc_4FF01C4E ROM:4FF01C46 MOV R0, R2 ROM:4FF01C48 BL spi_setup ROM:4FF01C4C B locret_4FF01CBA ; default ROM:4FF01C4E ; --------------------------------------------------------------------------- ROM:4FF01C4E ROM:4FF01C4E loc_4FF01C4E ROM:4FF01C4E LSLS R0, R3, #3 ROM:4FF01C50 ADDS R0, R0, R2 ROM:4FF01C52 CMP R1, #7 ; switch 8 cases ROM:4FF01C54 BHI locret_4FF01CBA ; default ROM:4FF01C56 TBB.W [PC,R1] ; switch jump ROM:4FF01C56 ; --------------------------------------------------------------------------- ROM:4FF01C5A jpt_4FF01C56 DCB 0xB ; jump table for switch statement ROM:4FF01C5B DCB 0x18 ROM:4FF01C5C DCB 0x10 ROM:4FF01C5D DCB 0x13 ROM:4FF01C5E DCB 0x1E ROM:4FF01C5F DCB 0x1B ROM:4FF01C60 DCB 5 ROM:4FF01C61 DCB 8 ROM:4FF01C62 DCB 0x30 ; 0 ROM:4FF01C63 DCB 0 ROM:4FF01C64 ; --------------------------------------------------------------------------- ROM:4FF01C64 ROM:4FF01C64 loc_4FF01C64 ROM:4FF01C64 MOV.W R1, #0x250 ; jumptable 4FF01C56 case 6 ROM:4FF01C68 B loc_4FF01C74 ROM:4FF01C6A ; --------------------------------------------------------------------------- ROM:4FF01C6A ROM:4FF01C6A loc_4FF01C6A ROM:4FF01C6A MOV.W R1, #0x270 ; jumptable 4FF01C56 case 7 ROM:4FF01C6E B loc_4FF01C74 ROM:4FF01C70 ; --------------------------------------------------------------------------- ROM:4FF01C70 ROM:4FF01C70 loc_4FF01C70 ROM:4FF01C70 MOV.W R1, #0x210 ; jumptable 4FF01C56 case 0 ROM:4FF01C70 ; enable ROM:4FF01C74 ROM:4FF01C74 loc_4FF01C74 ROM:4FF01C74 MOVW R12, #0b1001111110 ; mask out bits 1-6,9 ROM:4FF01C78 B loc_4FF01CA0 ROM:4FF01C7A ; --------------------------------------------------------------------------- ROM:4FF01C7A ROM:4FF01C7A loc_4FF01C7A ROM:4FF01C7A MOVW R1, #0x212 ; jumptable 4FF01C56 case 2 ROM:4FF01C7E B loc_4FF01C84 ; clear state? ROM:4FF01C80 ; --------------------------------------------------------------------------- ROM:4FF01C80 ROM:4FF01C80 loc_4FF01C80 ROM:4FF01C80 MOVW R1, #0x213 ; jumptable 4FF01C56 case 3 ROM:4FF01C80 ; set state? ROM:4FF01C84 ROM:4FF01C84 loc_4FF01C84 ROM:4FF01C84 MOVW R12, #0x27F ; mask out bits 0-6, 9 ROM:4FF01C88 B loc_4FF01CA0 ROM:4FF01C8A ; --------------------------------------------------------------------------- ROM:4FF01C8A ROM:4FF01C8A loc_4FF01C8A ROM:4FF01C8A MOVW R1, #0x212 ; jumptable 4FF01C56 case 1 ROM:4FF01C8E B loc_4FF01C74 ROM:4FF01C90 ; --------------------------------------------------------------------------- ROM:4FF01C90 ROM:4FF01C90 loc_4FF01C90 ROM:4FF01C90 MOV.W R1, #0x230 ; jumptable 4FF01C56 case 5 ROM:4FF01C94 B loc_4FF01C74 ; sets bit4,5,9 ROM:4FF01C94 ROM:4FF01C96 ; --------------------------------------------------------------------------- ROM:4FF01C96 ROM:4FF01C96 LDR R3, =word_4FF26F24 ; jumptable 4FF01C56 case 4 ROM:4FF01C98 MOVW R12, #0x3FF ROM:4FF01C9C LDRH.W R1, [R3,R0,LSL#1] ROM:4FF01CA0 LSLS R0, R0, #2 ROM:4FF01CA2 ADD.W R0, R0, #0x83000000 ROM:4FF01CA6 MVN.W R3, R12 ROM:4FF01CAA LDR R2, [R0] ROM:4FF01CAC AND.W R2, R3, R2 ROM:4FF01CB0 AND.W R3, R12, R1 ROM:4FF01CB4 ORR.W R3, R2, R3 ROM:4FF01CB8 STR R3, [R0] ROM:4FF01CBA ROM:4FF01CBA locret_4FF01CBA ROM:4FF01CBA POP {R7,PC} ; default ROM:4FF01CBA ; End of function gpio_ctl
Bits 7 and 8 are set in a separate routine:
From 3.1.2 iBoot:
ROM:4FF01C00 CMP R1, #0 ROM:4FF01C02 IT LT ROM:4FF01C04 MOVLT.W R1, #0x100 ; sets bit 8 ROM:4FF01C08 BLT loc_4FF01C0E ROM:4FF01C0A IT NE ROM:4FF01C0C MOVNE R1, #0x80 ; sets bit 7 ROM:4FF01C0E ROM:4FF01C0E loc_4FF01C0E ROM:4FF01C0E LSRS R3, R0, #5 ROM:4FF01C10 AND.W R3, R3, #0x7F8 ROM:4FF01C14 AND.W R0, R0, #7 ROM:4FF01C18 ADD R0, R3 ROM:4FF01C1A AND.W R2, R1, #0b110000000 ; mask out bits 7, 8 ROM:4FF01C1E LSLS R0, R0, #2 ROM:4FF01C20 ADD.W R0, R0, #0x83000000 ROM:4FF01C24 LDR R3, [R0] ROM:4FF01C26 BIC.W R1, R3, #0b110000000 ROM:4FF01C2A ORR.W R1, R2, R1 ROM:4FF01C2E STR R1, [R0] ROM:4FF01C30 BX LR
Next task is to try to identify what these control bits control. Typical GPIO control settings are Enable/Disable, Input/Output/Functional, Pull Up/Down, Interrupt Trigger (rising/falling edge), State Setting/Reading, Mode setting (Sleep/Stop/Wake).
Based on the things I am seeing so far, I can roughly make the following assumptions:
bit0 - GPIO pin state bit1-3 - Direction/Function? (input/output/functional) bit4 - Always set (enable?) bit5-6 - Pull Up/Down? (Disable/Pull Down/Pull Up) bit7-8 - Sleep Mode Pull Up/Down? (Disable/Pull Down/Pull Up) bit9-10 - Sleep Mode Control? (input/outputs/previous state)
The above should be subjected to heavy scrutiny by someone who posses deadlier reversing kungfu than myself. Hopefully further reversing on how different GPIO pins are setup for different hardware could provide some more hints for this objective.
For example bit 0 is likely the peripheral state bit when the pin is configured as input based on this baseband detection routine.
From 3.1.2 iBoot:
ROM:4FF0EB74 PUSH {R4,R5,R7,LR} ROM:4FF0EB76 ADD R7, SP, #8 ROM:4FF0EB78 MOVW R4, #0x803 ; radio hardware ROM:4FF0EB7C MOV R0, R4 ROM:4FF0EB7E MOVS R1, #0 ROM:4FF0EB80 BL gpio_ctl ROM:4FF0EB84 MOVS R1, #0 ROM:4FF0EB86 MOVS R0, #0x64 ROM:4FF0EB88 BL delay ROM:4FF0EB8C MOV R0, R4 ROM:4FF0EB8E BL gpio_get ROM:4FF0EB92 MOVS R1, #4 ROM:4FF0EB94 MOV R5, R0 ROM:4FF0EB96 MOV R0, R4 ROM:4FF0EB98 BL gpio_ctl ROM:4FF0EB9C MOVS R0, #0x64 ROM:4FF0EB9E MOVS R1, #0 ROM:4FF0EBA0 BL delay ROM:4FF0EBA4 MOV R0, R5 ROM:4FF0EBA6 POP {R4,R5,R7,PC} ROM:4FF0EBA6 ; End of function probe_radio
gpio_get routine:
ROM:4FF01D0C PUSH {R7,LR} ROM:4FF01D0E ADD R7, SP, #0 ROM:4FF01D10 LSRS R3, R0, #8 ROM:4FF01D12 AND.W R3, R3, #0xFF ROM:4FF01D16 CMP R3, #0x2E ROM:4FF01D18 AND.W R2, R0, #7 ROM:4FF01D1C BNE loc_4FF01D26 ROM:4FF01D1E MOV R0, R2 ROM:4FF01D20 BL sub_4FF11894 ROM:4FF01D24 B locret_4FF01D36 ROM:4FF01D26 ; --------------------------------------------------------------------------- ROM:4FF01D26 ROM:4FF01D26 loc_4FF01D26 ROM:4FF01D26 LSLS R0, R3, #3 ROM:4FF01D28 ADDS R0, R0, R2 ROM:4FF01D2A LSLS R0, R0, #2 ROM:4FF01D2C ADD.W R0, R0, #0x83000000 ROM:4FF01D30 LDR R0, [R0] ROM:4FF01D32 AND.W R0, R0, #1 ROM:4FF01D36 ROM:4FF01D36 locret_4FF01D36 ROM:4FF01D36 POP {R7,PC}
Also, possible values for bit 7 and 8 (as shown previously) is 00, 01, 10 so a pull up/down control should make sense.
Bit 5 and 6 as pull up/down control also is viable since register value of 0x270 is never used in any of the iBoots I have seen. This register value is corresponding to "case 7" in the gpio_ctl function in iBoot where both bit 5 and 6 are set.