IBoot Flags

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