iBoot Flags

From The Apple Wiki

Notes[edit]

Initial[edit]

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[edit]

||***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[edit]

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[edit]

If bit 16 is set, range check is bypassed.

Reversing[edit]

Reversings of various routines that relate to the iBoot flags in an effort to find out what does what.

Setup Range[edit]

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[edit]

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[edit]

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[edit]

MUCH thanks to CPICH for teaching me about all of this bitwise stuff that was really confusing to me at first

References[edit]

chronicdev Google Code