Second Loader: Difference between revisions

From Vita Development Wiki
Jump to navigation Jump to search
Line 118: Line 118:
   }
   }
   set_status(69LL);
   set_status(69LL);
</pre>
=== TODO ===
<pre>
   is_resume = (boot_type >> 7) & 1;
   is_resume = (boot_type >> 7) & 1;
   v17 = something_with_dram_808662(1LL, is_resume);
   v17 = something_with_dram_808662(1LL, is_resume);

Revision as of 19:17, 22 June 2018

Boot process (3.60)

TODO

int __usercall boot_800432@<W4>()
{
  v51 = v0;
  setup_gpio_0_1_leds_809422();
  gpio_something_809582(0LL, 7LL, 0LL);
  gpio_something2_80950A(0LL, 7LL);
  memset_FF_16_bytes_802302();
  sub_80193E();
  clear_line_0x516_80255C();

EMMC and syscon init

  set_emmc_hook_80712A(0x80374ELL);             // syscon_setup_80374E
  ret = try_init_emmc_801070();
  v50 = ret;
  if ( ret )
    goto LABEL_97;
  get_syscon_setup_cached_retval_807132((__int64)&v50);
  ret = v50;
  if ( v50 )
    goto LABEL_97;

emmc device (sdif0) is initialized. It sets keys for emmc crypto to be 0x20E/0x20F pair and protects them (dword_E0030024 = 0x1FEF020F; dword_E0030024 = 0x1FEF020E; unk_E0070008 = 0x20E020F; unk_E0070000 = 0; unk_E0070000 = 1;)

The command sequence sent to emmc is GO_IDLE_STATE, SEND_OP_COND, SEND_CID, SET_RELATIVE_ADDR, SEND_CSD, SELECT_CARD, SEND_EXT_CSD, SET_BLOCKLEN, SWITCH, SWITCH.

During SEND_OP_COND the function pointer from set_emmc_hook is called, it performs syscon init. It enables syscon device using gpio and sends syscon commands 1 (get syscon ver), 5 (get vita model info), 2 (get syscon date string), optionally 0x80.

Model/devkit checks

  model_info = get_cached_model_info_8038F2();
  model_info_1 = model_info;
  set_global_model_info_808C24(model_info);
  model_upper = model_info_1 & 0xFF0000;
  if ( model_upper == 0x600000 )
    goto its_devkit;
  if ( model_upper > 0x600000 )
    goto LABEL_8;
  if ( model_upper == 0x310000 )
    goto its_devkit;
  v5 = 0x100000;
  if ( model_upper > 0x310000 )
  {
    if ( model_upper == 0x410000 )
      goto its_devkit;
LABEL_8:
    if ( model_upper == 0x800000 || model_upper <= 0x800000 && model_upper == 0x700000 || model_upper == 0x820000 )
      goto its_devkit;
    v5 = 0x900000;
    goto LABEL_13;
  }
  do
  {
LABEL_13:
    if ( model_upper == v5 )
    {
its_devkit:
      sub_802044();
      enable_leds_808B7A();
    }
    set_status(65LL);
    v6 = get_syscon_ver_8038EC();
    v5 = 0x802FF;
    syscon_ver = v6;
  }
  while ( v6 <= 0x802FF );
  keyring_writeX_80250C(0x508LL, (__int64)&syscon_ver, 4LL);
  model_info_2 = get_cached_model_info_8038F2();
  keyring_writeX_80250C(0x51BLL, (__int64)&model_info_2, 4LL);
  if ( (model_info_2 & 0xFF0000u) > 0x7FFFFF )
    v7 = 0x1030;
  else
    v7 = 0x10;
  dword_E3100180 = v7;
  set_status(67LL);

Model info is retrieved from a global set by syscon command 5. Some checks are performed to determine if the vita is a devkit, if it is then a flag to enable debug LEDs is set. Syscon hw version from command 1 is written to keyslot 0x508 and vita model info is written to keyslot 0x51B.

TODO

  boot_type = 0;
  v8 = syscon_cmd_0x10_get_boot_type_80452A((__int64)&boot_type);
  v50 = v8;
  if ( (_DWORD)v8 )
  {
    v9 = 67LL;
LABEL_21:
    v10 = 0LL;
LABEL_22:
    report_error_808CAA(2LL, v9, v8, v10);
LABEL_23:
    ret = v50;
    goto LABEL_97;
  }
  set_status(68LL);
  ret_from_E002_1 = dword_E0020004;
  ret_from_E002 = ret_from_E002_1;
  ret_from_brom_1 = dword_E0010004;
  ret_from_brom = ret_from_brom_1;
  v15 = dword_E0062020;
  v8 = check_0x501_protection_and_compare_800DBC(ret_from_E002, ret_from_brom);
  v50 = v8;
  if ( (_DWORD)v8 )
  {
    v9 = 68LL;
    goto LABEL_21;
  }
  set_status(69LL);

TODO

  is_resume = (boot_type >> 7) & 1;
  v17 = something_with_dram_808662(1LL, is_resume);
  v50 = v17;
  if ( (_DWORD)v17 )
  {
    v18 = (unsigned __int8)sub_80877E();
    v19 = sub_808784();
    v9 = 69LL;
    v8 = v17;
    v10 = (v18 << 8) | (unsigned int)v19;
    goto LABEL_22;
  }
  if ( !(_DWORD)is_resume )
    goto LABEL_32;
  if ( !check_tz_magic_800A82() )
  {
    is_resume = 0LL;
LABEL_32:
    v20 = 0;
    clear_sysroot_801C0C();
    goto LBL_123;
  }
  if ( copy_sysroot_to_0x4001FD00_801C1E() )
  {
    is_resume = 1LL;
    goto LABEL_32;
  }
  is_resume = 1LL;
  v20 = 1;
LBL_123:
  emmc_key_reg = dword_E0070004;
  if ( emmc_key_reg & 1 )
  {
    set_status(82LL);
    report_error_808CAA(2LL, 82LL, 0x800F0029LL, 0LL);
    ret = 0x800F0029;
    goto LABEL_97;
  }
  sub_806B58(0x40000500LL, 0x1000LL);
  set_status(84LL);

Factory firmware check

  a3 = 0;
  v8 = get_factory_fw_801BAC((__int64)&a3);
  v50 = v8;
  if ( (_DWORD)v8 )
  {
    v9 = 84LL;
    goto LABEL_21;
  }
  v10 = a3;
  if ( a3 >= 0x3600001 )
  {
    v8 = 0x800F0030LL;
    v50 = 0x800F0030;
    v9 = 84LL;
    goto LABEL_22;
  }
  keyring_writeX_80250C(0x50FLL, (__int64)&a3, 4LL);
  set_status(85LL);

Factory firmware version is retrieved from idstorage and written to keyring slot 0x50F. The factory firmware must be not higher than this second_loader version, otherwise the boot is aborted to prevent downgrading below factory firmware version.

IDPS and OpenPSID

  ret = idps_and_openpsid_800B06();
  v50 = ret;
  if ( !ret )
  {
    set_status(95LL);

IDPS and OpenPSID are retrieved from idstorage and written to keyslots 0x509 and 0x50D.

TODO

    v22 = calls_syscon_0x88E_8089F0(6LL);
    v50 = v22;
    if ( (_DWORD)v22 )
      report_error_808CAA(1LL, 95LL, v22, 0LL);
    some_set_clock_808960(6LL);
    some_set_clock2_808982();
    v23 = 0x800F0026;
    if ( !(_DWORD)is_resume )
    {
      dmac_init_804BEC(&ctx);
      v23 = dmac_memset_int_804F04(0x40000000LL, 0x200000LL, 0LL, &ctx);
    }
    set_status(86LL);
    v24 = syscon_read_cmd_0x1082_ptr_0x480_into_gbuf_80232A();
    v50 = v24;
    if ( (_DWORD)v24 )
      report_error_808CAA(1LL, 86LL, v24, 0LL);
    if ( !v20 )
      syscon_read_cmd_0x1082_ptr_0x4a0_into_sysroot_802346();
    if ( !(_DWORD)is_resume && !v23 )
      dmac_wait_804C16(&ctx);
    set_status(77LL);
    if ( (_DWORD)is_resume )
      v25 = syscon_ver > 0x1000101;
    else
      v25 = 0LL;
    v50 = derive_slots_and_set_0x50B_8023A2(v25);
    if ( v50 )
    {
      syscon_unk_808C2A();
      v9 = 77LL;
LABEL_77:
      v8 = (unsigned int)v50;
      goto LABEL_21;
    }
    set_status(81LL);
    v50 = pervasive_and_syscon_cmd_0x888_optional_801038(v26);
    if ( v50 )
    {
      syscon_unk_808C2A();
      v9 = 81LL;
      goto LABEL_77;
    }
    memset((__int64)line_0x510, 0LL, 0x20LL);
    if ( sub_802050() )
    {
      set_status(87LL);
      v27 = read_syscon_cmd_0x90_off_0xE0_802056((__int64)line_0x510);
      v50 = v27;
      if ( (_DWORD)v27 )
        report_error_808CAA(1LL, 87LL, v27, 0LL);
      if ( !is_bit_set_802088((__int64)line_0x510, 0x9FLL) && !is_bit_set_802088((__int64)line_0x510, 0x81LL) )
        sub_808B66(1LL);
    }
    write_sysroot_fields_from_syscon_801FC0();
    keyring_writeX_80250C(0x510LL, (__int64)line_0x510, 0x20LL);
    memset((__int64)line_0x50A, 0LL, 0x10LL);
    set_keys_0x506_0x507_8020EA();
    if ( !is_bit_set_802088((__int64)line_0x510, 0xF0LL) )
    {
      set_status(88LL);
      v28 = some_syscon_derivation_802112((__int64)line_0x50A);
      v50 = v28;
      if ( (_DWORD)v28 != 0x800F0002 && (_DWORD)v28 != 0x800F0025 )
      {
        if ( (_DWORD)v28 )
        {
          report_error_808CAA(1LL, 88LL, v28, 0LL);
        }
        else if ( is_bit_set_802088((__int64)line_0x510, 241LL) )
        {
          unset_bit_8022F4((__int64)line_0x50A, 13LL, 1LL);
          unset_bit_8022F4((__int64)line_0x50A, 14LL, 1LL);
        }
      }
    }
    keyring_writeX_80250C(0x50ALL, (__int64)line_0x50A, 0x10LL);
    set_status(70LL);
    ret = zero_801B0E();
    v50 = ret;
    if ( !ret )
    {
      set_status(71LL);
      v50 = zero_801B24();
      if ( v50 )
      {
        syscon_unk_808C2A();
        report_error_808CAA(2LL, 71LL, (unsigned int)v50, 0LL);
        set_status(79LL);
        goto LABEL_23;
      }
      set_status(73LL);
      kbl_fw_version = 0;
      if ( (_DWORD)is_resume && (boot_type & 0x7F) != 0x17 )
      {
        copy_arm_tz_reset_vectors_800A9A();
      }
      else
      {
        v50 = decrypt_kernel_boot_loader_self_801162((__int64)&kbl_fw_version);
        if ( v50 )
        {
          syscon_unk_808C2A();
          v9 = 73LL;
          goto LABEL_77;
        }
      }
      set_status(89LL);
      syscon_unk_808C2A();
      print_info_log_800A5E();
      seven = ret_7_801B2C();
      six = ret_6_801B30();
      *(_DWORD *)(unsigned int)&dword_80C698 = zero_801B34();
      sub_804764((unsigned int)&unk_801888);
      set_status(78LL);
      v8 = set_and_check_current_fw_version_800E74(kbl_fw_version, is_resume);
      v50 = v8;
      if ( (_DWORD)v8 )
      {
        v9 = 78LL;
        goto LABEL_21;
      }
      sub_804786((__int64)&v50);
      v8 = (unsigned int)v50;
      if ( v50 )
      {
        v9 = 74LL;
        goto LABEL_21;
      }
      set_status(94LL);
      if ( (_DWORD)is_resume || kbl_fw_version >= a3 )
      {
        set_status(90LL);
        write_sysroot_801C36((__int64)line_0x510, (__int64)line_0x50A, boot_type, is_resume, a3);
        set_status(96LL);
        v29 = reads_pervasivevid_calls_syscon_0x88E_80899C(seven);
        v50 = v29;
        if ( (_DWORD)v29 )
          report_error_808CAA(1LL, 0x4CLL, v29, 0LL);
        set_status(0x4CLL);
        v8 = prepare_to_start_arm_80878A(seven, *(unsigned int *)(unsigned int)&dword_80C698, 0LL);
        v50 = v8;
        if ( (_DWORD)v8 )
        {
          v9 = 0x4CLL;
          goto LABEL_21;
        }
        v30 = some_line;
        set_status(80LL);
        read_line32_8003E8(0x602LL, (__int64)some_line);
        v31 = 0xE0020100LL;
        v32 = some_line;
        v33 = 8;
        do
        {
          v34 = *(_DWORD *)v32;
          v32 = (char *)(unsigned int)((_DWORD)v32 + 4);
          *(_DWORD *)v31 = v34;
          v31 = (unsigned int)(v31 + 4);
          --v33;
        }
        while ( v33 );
        read_line32_8003E8(0x601LL, (__int64)some_line);
        v35 = 8;
        do
        {
          v36 = *(_DWORD *)v30;
          v30 = (char *)(unsigned int)((_DWORD)v30 + 4);
          *(_DWORD *)v31 = v36;
          v31 = (unsigned int)(v31 + 4);
          --v35;
        }
        while ( v35 );
        nullsub_2();
        if ( six < 7 )
        {
          if ( six != 6 )
          {
            some_set_clock_808960(six);
            calls_syscon_0x88E_8089F0(six);
          }
        }
        else
        {
          calls_syscon_0x88E_8089F0(six);
          some_set_clock_808960(six);
        }
      }
      else
      {
        report_error_808CAA(2LL, 94LL, a3, kbl_fw_version);
        ret = 0x800F0030;
      }
    }
  }
LABEL_97:
  protect_lines_and_set_E002_8010CE();
  if ( ret )
  {
    send_status_to_arm_8010E2(0LL);
    print_info_log_800A5E();
    set_number_base_808D40((unsigned int)&g_unused, 0x10LL);
    printnum_808D46(2LL);
    printf((unsigned int)aB1B004fa16);          // boot failed
    randnum = dword_E005003C;
    sleep_8051D0((unsigned __int16)randnum);
    if ( !sub_808B82() && sub_803744() )
      syscon_cmd_0xC0_804606(0LL, 0LL);
  }
  else
  {
    send_status_to_arm_8010E2(1LL);
    syncm_8003E0();
    set_status(64LL);
  }
  return ret;
}

eeprom protection

On 0.995 and 3.60 the following lines are protected after starting arm: 0x0-0x7F, 0x140-0x17F, 0x200-0x203, 0x206-0x20D, 0x344-0x353, 0x400-0x47F, 0x502-0x57F, 0x700-0x77F

The protection it sets is 0x1C1F (so f00d read disabled).

Bypassing version checks

memeprom line 0x50B offset 0x4 bit 1 set = ignore version mismatch errors. This line itself is set from SNVS 0xD2 block 0. Alternatively set version to 0xDEADBEEF to skip.

Session key/coredump encryption

0x20 random bytes are generated and written to keyslot 0x51A. Then, the buffer is encrypted with aes128-cbc using coredump_key and coredump_iv. The result is copied to sysroot buffer +0x100 (0x1F000200)