The iPhone Wiki is no longer updated. Visit this article on The Apple Wiki for current information. |
iBoot Flags
Contents
Notes
Initial
Initially, boot flags are set to 0x2C0000, or:
bit0: No
bit 1: No
bit 2: No
bit 3: No
bit 4: No
bit 5: No
bit 6: No
bit 7: No
bit 8: No
bit 9: No
bit 10: No
bit 11: No
bit 12: No
bit 13: No
bit 14: No
bit 15: No
bit 16: No
bit 17: No
bit 18: Yes
bit 19: Yes
bit 20: No
bit 21: Yes
bit 22: No
bit 23: No
bit 24: No
bit 25: No
bit 26: No
bit 27: No
bit 28: No
bit 29: No
bit 30: No
bit 31: No
Commands
||***Command***||***Bits***|| ||powernvram||Check if bit 8 is set to even allow the command to be used without a Permission Denied error, and check if bit is set 17 to allow usage of the 'set' subcommand|| ||diags||Check if bit 4 is set to allow usage of ***diags [address]*** to execute code.|| ||charge||Check if bits 8 ***and*** 17 are set to allow usage of this command.|| ||bdev||Check if bit 8 is set to allow usage of this command.|| ||pki||Check if bit 8 is set to allow usage of this command.|| ||image||Check if bit 8 is set to allow usage of this command.|| ||iic||Check of bit 17 is set to allow usage of this command.|| ||chunk||Check if bit 8 is set to allow usage of this command.||
Undocumented Routine
This stuff is from an interesting (and long) routine that I am not quite sure what it does, it has something to do with the 'bootx' command though, I think.
||***Thing***||***Bits***|| ||System-Trusted||Check if bit 29 is set.|| ||Secure-Boot||Check if bit 28 is set.|| ||uid-aes-key||Check if bit 19 is set.|| ||gid-aes-key||Check if bit 18 is set.|| ||production-cert||Check if bit 21 is set.|| ||development-cert||Check if bit 20 is set.|| ||debug-enabled||Check if bit 5 is set.||
Range Check
If bit 16 is set, range check is bypassed.
Reversing
Reversings of various routines that relate to the iBoot flags in an effort to find out what does what.
Setup Range
ROM:0FF0BD38 ; =============== S U B R O U T I N E ======================================= ROM:0FF0BD38 ROM:0FF0BD38 ; logic: ROM:0FF0BD38 ; if running on a special engineering / debug device, return. ROM:0FF0BD38 ; if 'option' is not set to 0, then set mimimum address to -1 and maximum address to 0. then return. wtf? ROM:0FF0BD38 ; if new_min is higher or equal to the current minimum address, don't set it. ROM:0FF0BD38 ; if new_max is lower or equal to the current maximum address, don't set it. ROM:0FF0BD38 ROM:0FF0BD38 ; void __cdecl Set_Up_Allowed_Range(__int32 new_min, __int32 new_max, int option) ROM:0FF0BD38 Set_Up_Allowed_Range ; CODE XREF: sub_FF07682+B9E�p ROM:0FF0BD38 ; sub_FF0BD7C+6E�p ROM:0FF0BD38 new_min = R0 ; new minimum allowed address to be set ROM:0FF0BD38 new_max = R1 ; this one is weird. it should be new maximum address minus the new minimum ROM:0FF0BD38 000 10 B5 PUSH {R4,LR} ; Push registers ROM:0FF0BD3A 008 0D 4B LDR R3, =iBoot_flags ; Load from Memory ROM:0FF0BD3C 008 41 18 ADDS new_max, new_min, new_max ; new_max + new_min = real new maximum (wtf?) ROM:0FF0BD3E 008 1B 68 LDR R3, [R3] ; Load from Memory ROM:0FF0BD40 008 DC 03 LSLS R4, R3, #0xF ; Logical Shift Left ROM:0FF0BD42 008 13 D4 BMI return ; if bit 16 is set, return. ROM:0FF0BD42 ; ROM:0FF0BD42 ; by the looks of it, bit 16 is set when the device is a special ROM:0FF0BD42 ; engineering / debug device ROM:0FF0BD44 008 00 2A CMP R2, #0 ; Set cond. codes on Op1 - Op2 ROM:0FF0BD46 008 07 D0 BEQ set_minimum ; if the "option" arg is 0, jump here. ROM:0FF0BD48 ROM:0FF0BD48 bad ; Load from Memory ROM:0FF0BD48 008 0A 4A LDR R2, =Minimum_Allowed_Addr ROM:0FF0BD4A 008 01 23 MOVS R3, #1 ; Rd = Op2 ROM:0FF0BD4C 008 5B 42 NEGS R3, R3 ; Negate ROM:0FF0BD4E 008 13 60 STR R3, [R2] ; set minimum address to -1 ROM:0FF0BD50 008 09 4B LDR R3, =Maximum_Allowed_Addr ; Load from Memory ROM:0FF0BD52 008 00 22 MOVS R2, #0 ; Rd = Op2 ROM:0FF0BD54 008 1A 60 STR R2, [R3] ; set maximum address to 0 ROM:0FF0BD56 008 09 E0 B return ; Branch ROM:0FF0BD58 ; --------------------------------------------------------------------------- ROM:0FF0BD58 ROM:0FF0BD58 set_minimum ; CODE XREF: Set_Up_Allowed_Range+E�j ROM:0FF0BD58 008 06 4A LDR R2, =Minimum_Allowed_Addr ; Load from Memory ROM:0FF0BD5A 008 13 68 LDR R3, [R2] ; Load from Memory ROM:0FF0BD5C 008 98 42 CMP new_min, R3 ; Set cond. codes on Op1 - Op2 ROM:0FF0BD5E 008 00 D2 BCS set_maximum ; if new_min is higher or the same as the current ROM:0FF0BD5E ; minimum address, don't change anything. ROM:0FF0BD60 008 10 60 STR new_min, [R2] ; set the minimum address to new_min ROM:0FF0BD62 ROM:0FF0BD62 set_maximum ; CODE XREF: Set_Up_Allowed_Range+26�j ROM:0FF0BD62 008 05 4A LDR R2, =Maximum_Allowed_Addr ; Load from Memory ROM:0FF0BD64 008 13 68 LDR R3, [R2] ; Load from Memory ROM:0FF0BD66 008 99 42 CMP new_max, R3 ; Set cond. codes on Op1 - Op2 ROM:0FF0BD68 008 00 D9 BLS return ; if new_max is less than or the same as the current ROM:0FF0BD68 ; maximum address, don't change anything. ROM:0FF0BD6A 008 11 60 STR new_max, [R2] ; set maximum address to new_max ROM:0FF0BD6C ROM:0FF0BD6C return ; CODE XREF: Set_Up_Allowed_Range+A�j ROM:0FF0BD6C ; Set_Up_Allowed_Range+1E�j ROM:0FF0BD6C ; Set_Up_Allowed_Range+30�j ROM:0FF0BD6C 008 10 BD POP {R4,PC} ; Pop registers ROM:0FF0BD6C ; End of function Set_Up_Allowed_Range ROM:0FF0BD6C ROM:0FF0BD6C ; --------------------------------------------------------------------------- ROM:0FF0BD6E 00 00 DCW 0 ROM:0FF0BD70 C0 86 F1 0F off_FF0BD70 DCD iBoot_flags ; DATA XREF: Set_Up_Allowed_Range+2�r ROM:0FF0BD74 C4 86 F1 0F off_FF0BD74 DCD Minimum_Allowed_Addr ROM:0FF0BD74 ; DATA XREF: Set_Up_Allowed_Range:bad�r ROM:0FF0BD74 ; Set_Up_Allowed_Range:set_minimum�r ROM:0FF0BD78 C8 86 F1 0F off_FF0BD78 DCD Maximum_Allowed_Addr ROM:0FF0BD78 ; DATA XREF: Set_Up_Allowed_Range+18�r ROM:0FF0BD78 ; Set_Up_Allowed_Range:set_maximum�r
Range Check
ROM:0FF0BD04 ; =============== S U B R O U T I N E ======================================= ROM:0FF0BD04 ROM:0FF0BD04 ; iboot range check ROM:0FF0BD04 ; ROM:0FF0BD04 ; logic: ROM:0FF0BD04 ; if running on a special dev board, we are good to go. bypasses the range check. ROM:0FF0BD04 ; if unkown addr is negative for some reason, then fail. ROM:0FF0BD04 ; if addr to check is less than the minimum addr defined at 0x0ff186c4, then fail. ROM:0FF0BD04 ; if addr to check is greater than the maximum addr defined in 0xff186c8, then fail. ROM:0FF0BD04 ; ROM:0FF0BD04 ; psuedocode: ROM:0FF0BD04 ; int permissions_check(long addr_to_check, long unk_addr) { ROM:0FF0BD04 ; if(flags at 0x0ff186c0 << 0xF < 0) { // is bit 16 set? ROM:0FF0BD04 ; return(1); // aka, success. ROM:0FF0BD04 ; } ROM:0FF0BD04 ; if(addr to check >= unk addr + addr to check) { ROM:0FF0BD04 ; return(0); // aka, fail. ROM:0FF0BD04 ; } ROM:0FF0BD04 ; if(addr to check < min allowed addr) { ROM:0FF0BD04 ; return(0); // aka, fail. ROM:0FF0BD04 ; } ROM:0FF0BD04 ; if(addr to check > max allowed addr) { ROM:0FF0BD04 ; return(0); // aka, fail. ROM:0FF0BD04 ; } ROM:0FF0BD04 ; ROM:0FF0BD04 ; return(1); // aka, success, since the other checks above passed ROM:0FF0BD04 ; } ROM:0FF0BD04 ROM:0FF0BD04 ; int __cdecl range_check(__int32 addr_to_check, __int32 unk_addr) ROM:0FF0BD04 range_check ; CODE XREF: cmd_bootx+30�p ROM:0FF0BD04 ; cmd_diags+1C�p ROM:0FF0BD04 ; sub_FF00BE8+64�p ROM:0FF0BD04 ; sub_FF00CA8+56�p ... ROM:0FF0BD04 000 09 4B LDR R3, =0xFF186C0 ; iboot flags ROM:0FF0BD06 000 42 18 ADDS R2, R0, R1 ; r2 = addr to check + unknown addr ROM:0FF0BD08 000 1B 68 LDR R3, [R3] ; flags located at 0x0ff186c0 ROM:0FF0BD0A 000 D9 03 LSLS R1, R3, #0xF ; Logical Shift Left ROM:0FF0BD0C 000 09 D4 BMI return_success ; return(1); // good ROM:0FF0BD0E 000 90 42 CMP R0, R2 ; Set cond. codes on Op1 - Op2 ROM:0FF0BD10 000 09 D2 BCS return_fail ; return(0); // bad ROM:0FF0BD12 000 07 4B LDR R3, =0xFF186C4 ; min addr ROM:0FF0BD14 000 1B 68 LDR R3, [R3] ; Load from Memory ROM:0FF0BD16 000 98 42 CMP R0, R3 ; Set cond. codes on Op1 - Op2 ROM:0FF0BD18 000 05 D3 BCC return_fail ; return(0); // bad ROM:0FF0BD1A 000 06 4B LDR R3, =0xFF186C8 ; max addr ROM:0FF0BD1C 000 1B 68 LDR R3, [R3] ; Load from Memory ROM:0FF0BD1E 000 9A 42 CMP R2, R3 ; Set cond. codes on Op1 - Op2 ROM:0FF0BD20 000 01 D8 BHI return_fail ; return(0); // bad ROM:0FF0BD22 ROM:0FF0BD22 return_success ; CODE XREF: range_check+8�j ROM:0FF0BD22 000 01 20 MOVS R0, #1 ; return(1); // good ROM:0FF0BD24 000 00 E0 B return ; Branch ROM:0FF0BD26 ; --------------------------------------------------------------------------- ROM:0FF0BD26 ROM:0FF0BD26 return_fail ; CODE XREF: range_check+C�j ROM:0FF0BD26 ; range_check+14�j ROM:0FF0BD26 ; range_check+1C�j ROM:0FF0BD26 000 00 20 MOVS R0, #0 ; return(0); // bad ROM:0FF0BD28 ROM:0FF0BD28 return ; CODE XREF: range_check+20�j ROM:0FF0BD28 000 70 47 BX LR ; Branch to/from Thumb mode ROM:0FF0BD28 ; End of function range_check ROM:0FF0BD28 ROM:0FF0BD28 ; --------------------------------------------------------------------------- ROM:0FF0BD2A 00 00 DCW 0 ROM:0FF0BD2C C0 86 F1 0F dword_FF0BD2C DCD 0xFF186C0 ; DATA XREF: range_check�r ROM:0FF0BD30 C4 86 F1 0F dword_FF0BD30 DCD 0xFF186C4 ; DATA XREF: range_check+E�r ROM:0FF0BD34 C8 86 F1 0F dword_FF0BD34 DCD 0xFF186C8 ; DATA XREF: range_check+16�r
Permissions / Generic Flag Check
ROM:0FF0BCAC ; will check the given flag in the iboot flags ROM:0FF0BCAC ; ROM:0FF0BCAC ; logic: ROM:0FF0BCAC ; if the iboot_flags do not contain the flag supplied to the routine, return 0 // bad ROM:0FF0BCAC ; if the flags supplied to this routine does has bit 4 set, then set bit 5 in the iboot flags as well. return 1. // good ROM:0FF0BCAC ROM:0FF0BCAC ; int __cdecl flag_check(int flag) ROM:0FF0BCAC flag_check ; CODE XREF: cmd_diags+26�p ROM:0FF0BCAC ; cmd_powernvram+E�p ROM:0FF0BCAC ; cmd_powernvram+7E�p ROM:0FF0BCAC ; cmd_charge+C�p ... ROM:0FF0BCAC 000 10 B5 PUSH {R4,LR} ; Push registers ROM:0FF0BCAE 008 08 49 LDR R1, =iBoot_flags ; Load from Memory ROM:0FF0BCB0 008 00 24 MOVS R4, #0 ; Rd = Op2 ROM:0FF0BCB2 008 0A 68 LDR R2, [R1] ; Load from Memory ROM:0FF0BCB4 008 13 1C ADDS R3, R2, #0 ; Rd = Op1 + Op2 ROM:0FF0BCB6 008 03 40 ANDS R3, R0 ; Rd = Op1 & Op2 ROM:0FF0BCB8 008 98 42 CMP R0, R3 ; check iboot flags against the supplied flags ROM:0FF0BCBA 008 07 D1 BNE return ; return(0); ROM:0FF0BCBC 008 01 24 MOVS R4, #1 ; Rd = Op2 ROM:0FF0BCBE 008 C3 06 LSLS R3, R0, #0x1B ; check if the supplied flags has bit 4 set ROM:0FF0BCC0 008 04 D5 BPL return ; return(1); ROM:0FF0BCC2 008 04 4B LDR R3, =0xDFF3FFFF ; Load from Memory ROM:0FF0BCC4 008 13 40 ANDS R3, R2 ; Rd = Op1 & Op2 ROM:0FF0BCC6 008 20 22 MOVS R2, #0x20 ; Rd = Op2 ROM:0FF0BCC8 008 13 43 ORRS R3, R2 ; Rd = Op1 | Op2 ROM:0FF0BCCA 008 0B 60 STR R3, [R1] ; set bit 5 of the iboot flags ROM:0FF0BCCC ROM:0FF0BCCC return ; CODE XREF: flag_check+E�j ROM:0FF0BCCC ; flag_check+14�j ROM:0FF0BCCC 008 20 1C ADDS R0, R4, #0 ; Rd = Op1 + Op2 ROM:0FF0BCCE 008 10 BD POP {R4,PC} ; Pop registers ROM:0FF0BCCE ; End of function flag_check
Thanks
MUCH thanks to CPICH for teaching me about all of this bitwise stuff that was really confusing to me at first