Advertisement
xerpi

3DS CPU bootup

Jul 19th, 2016
309
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.95 KB | None | 0 0
  1. /*
  2.  * RE by xerpi
  3.  * thanks Dazzozo for initial help :)
  4.  *
  5.  * CPU2/CPU3 bootup code at: sub_FFF2EC68
  6.  * CPU1 entrypoint: 0x1FFAE064
  7.  * CPU2/CPU3 entrypoint at: 0x1FFAE490 (0xFFF2E490)
  8.  */
  9.  
  10. // CPU2/3 startup routine
  11. void sub_FFF2E490()
  12. {
  13.     int cpu_id;
  14.     u32 val;
  15.  
  16.     __asm__ volatile {
  17.         "cpsid aif\nt"
  18.     };
  19.  
  20.     __mrc(0xF, &val, 0xF, 0xC, 0); // Read Performance Monitor Control Register
  21.     val |= 0xFFFF00D;
  22.     __mcr(0xF, val, 0xF, 0xC, 0);
  23.  
  24.     0x17E00100 = 1; // Enable interrupts
  25.  
  26.     cpu_id = __mrc(0xF, 0, 0, 0, 5) & 3;
  27.  
  28.     /* Tell the CPU0 we are here */
  29.     if (cpu_id == 3)
  30.         0x10141313 = 1;
  31.     else
  32.         0x10141312 = 1;
  33.  
  34.     do {
  35.         __wfi();
  36.         0x17E00110 = 0x17E0010C; // ack interrupt
  37.     } while (0x17E0010C != cpu_id);
  38.  
  39.     JUMPOUT(0x1FFAE064);
  40. }
  41.  
  42. // a1: enable_SMP?
  43. int sub_FFF2EC68(int a1)
  44. {
  45.     int v1;         // r8@1
  46.     signed int v2;      // r10@4
  47.     signed int v3;      // r0@16
  48.     int v4;         // r0@24
  49.     signed int v5;      // r3@25
  50.     signed int v6;      // r9@27
  51.     unsigned int v7;    // r1@42
  52.     int result;     // r0@44
  53.     signed int v9;      // r0@47
  54.     signed int v10;     // r2@47
  55.     signed int v11;     // r1@47
  56.     int v12;        // t1@48
  57.  
  58.     v1 = a1;
  59.     if (!a1) {
  60.         if ((0x10140FFC & 0b10) >> 1) { // If we have more than 2 CPUs..
  61.             if ((0x10140FFC & 0b100) >> 2)  // If 4 CPUs
  62.                 v2 = 0b101;
  63.             else                // If 3 CPUs
  64.                 v2 = 0b011;
  65.  
  66.             if ((0x10141300 & 0b111) != v2) {
  67.                 0x10141304 |= 1; // Power on 3rd ARM11 MPCore
  68.                 if ((0x10140FFC & 0b100) >> 2) // If 4 CPUs
  69.                     0x10141304 |= 0x100; // Power on 4rd ARM11 MPCore
  70.  
  71.                 sub_FFF2E454(0x193);    // delay
  72.  
  73.                 0x17E00100 = 1; // enable interrupts
  74.                 0x17E01288 = 0x1000000; // Interrupt Pending clear Registers
  75.  
  76.                 0x10141300 = v2 & 0b111 | 0x8000; // enable clk mult, clk=2x, busy=1
  77.  
  78.                 0x17E01458 = 0; // Interrupt Priority Registers
  79.                 0x17E01858 |= 1;    // Interrupt CPU targets Registers
  80.                 0x17E01108 = 0x1000000; // Interrupt Enable set Registers ID0-ID31
  81.  
  82.                 do {
  83.                     __wfi();
  84.                 } while (!(0x10141300 & 0x8000)); // While PDN_MPCORE_CLKCNT busy
  85.  
  86.                 0x17E01188 = 0x1000000; //Interrupt Enable set Registers ID32 and upwards
  87.  
  88.                 0x10140400 = 3; // CLK_UNK1
  89.             }
  90.             0x10140410 = 0x3FFFF; // CLK_UNK2
  91.         }
  92.  
  93.         /* Start shit */
  94.         0x1FFFFFF0 = 1;
  95.         while (0x1FFFFFF0 != 2) ;
  96.         0x1FFFFFF0 = 3;
  97.         0x1FFAF405 = 0x1FFFFFF1;
  98.         0x1FFAF406 = 0x1FFFFFF2;
  99.         if (0x1FFFFFF1 == 3) {
  100.             v3 = 0;
  101.             do
  102.                 ++v3;
  103.             while (v3 < 0x800000);
  104.             0x1FFFFFF0 = 1;
  105.             while (0x1FFFFFF0 != 2) ;
  106.             0x1FFFFFF0 = 3;
  107.         }
  108.         /* End shit */
  109.  
  110.         if ((0x10140FFC & 2) >> 1 && (0x17E00004 & 3) == 3) {   // If we have 4 CPUs
  111.             0x17E00008 &= 0xFFFFFF0F;   // SCU power on CPU2 and CPU3
  112.  
  113.             v4 = 0x10141300 & 0b111;
  114.             if ((0x10140FFC & 0b100) >> 2) // If 4 CPUs
  115.                 v5 = 1;
  116.             else
  117.                 v5 = 2;
  118.  
  119.             v6 = 1 << v1;
  120.             if (v4 != v5) {
  121.                 0x17E00100 = 1; // enable interrupts
  122.                 0x17E01288 = 0x1000000;
  123.                 0x10141300 = v5 & 0b111 | 0x8000; // enable clk mult, clk=1x, busy=1
  124.                 0x17E01458 = 0;
  125.                 0x17E01858 |= v6;
  126.                 0x17E01108 = 0x1000000;
  127.                 do {
  128.                     __wfi();
  129.                 } while (!(0x10141300 & 0x8000)); // While PDN_MPCORE_CLKCNT busy
  130.                 0x17E01188 = 0x1000000;
  131.             }
  132.  
  133.             0x10140420 |= 1;        // Enable bootrom overlay
  134.             0x10140424 = 0x1FFAE490;    // Set CPU2/3 entrypoint (overlay value)
  135.  
  136.             if (!(0x10141312 & 0x10)) { // If CPU2 has not booted
  137.                 0x10141312 |= 2; // Enable CPU2 bootrom data overlay?
  138.                 0x10141312 |= 1; // Enable CPU2 bootrom instruction overlay
  139.             }
  140.             if (!(0x10141313 & 0x10)) { // If CPU3 has not booted
  141.                 0x10141313 |= 2; // Enable CPU3 bootrom data overlay?
  142.                 0x10141313 |= 1; // Enable CPU3 bootrom instruction overlay
  143.             }
  144.  
  145.             /* Wait until CPU2 is online */
  146.             while ((0x10141312 & 0x12) != 0x10)
  147.                 ;
  148.  
  149.             /* Wait until CPU3 is online */
  150.             while ((0x10141313 & 0x12) != 0x10)
  151.                 ;
  152.  
  153.             0x10140420 &= 0xFE; // Disable bootrom overlay
  154.  
  155.             if (v4 != v5) {
  156.                 0x17E00100 = 1;
  157.                 0x17E01288 = 0x1000000;
  158.                 0x10141300 = v4 & 0b111 | 0x8000; // enable clk mult, clk=orignal state, busy=1
  159.                 0x17E01458 = 0;
  160.                 0x17E01858 |= v6;
  161.                 0x17E01108 = 0x1000000;
  162.                 do {
  163.                     __wfi();
  164.                 } while (!(0x10141300 & 0x8000));
  165.                 0x17E01188 = 0x1000000;
  166.             }
  167.         }
  168.         0x1FFFFFDC = 0x1FFAE064; // CPU1 entrypoint
  169.     }
  170.     v7 = *(_DWORD *) (4 * v1 + 0x1FFAF3C4);
  171.     __mcr(15, 0, 0, 8, 7, 0);
  172.     __mcr(15, 0, (v7 >> 9 << 9) | 0x12, 2, 0, 0);
  173.     __mcr(15, 0, (v7 >> 14 << 14) | 0x12, 2, 0, 1);
  174.     __mcr(15, 0, 2u, 2, 0, 2);
  175.     __mcr(15, 0, 0, 13, 0, 1);
  176.     __mcr(15, 0, 1u, 3, 0, 0);
  177.     sub_FFF2E594();
  178.  
  179.     if (!v1)
  180.         0x17E00000 |= 1; // Enable SCU
  181.  
  182.     // Rest is 3DS shit...
  183.  
  184.     __mcr(15, 0, __mrc(15, 0, 1, 0, 1) | 0x2F, 1, 0, 1);
  185.     result = __mrc(15, 0, 1, 0, 0) | 0xC03805;
  186.     __mcr(15, 0, result, 1, 0, 0);
  187.     __mcr(15, 0, 0, 7, 5, 4);
  188.     __mcr(15, 0, 0, 7, 5, 0);
  189.     __mcr(15, 0, 0, 7, 6, 0);
  190.     __mcr(15, 0, 0, 8, 7, 0);
  191.     __mcr(15, 0, 0, 7, 10, 5);
  192.     __mcr(15, 0, 0, 7, 5, 4);
  193.     if (!v1) {
  194.         *0x1FFAF40C = *0x1FFAF40C & 0xFC6FEBFF | 0x2800000;
  195.         *0x1FFAF420 = *0x1FFAF420 & 0xF65FFFE1 | 0x70000001;
  196.         *0x1FFAF424 &= 0xFFFFFFFC;
  197.         *0x1FFAF410 |= 0x1FFu;
  198.         *0x1FFAF418 = 0xFFFF;
  199.         while (*0x1FFAF414 & 1) ;
  200.         *0x1FFAF414 = 0;
  201.         *0x1FFAF408 |= 1u;
  202.         v9 = 536821756;
  203.         v10 = 536530940;
  204.         v11 = 512;
  205.         do {
  206.             --v11;
  207.             *(_DWORD *) (v9 + 4) = *(_DWORD *) (v10 + 4);
  208.             v12 = *(_DWORD *) (v10 + 8);
  209.             v10 += 8;
  210.             *(_DWORD *) (v9 + 8) = v12;
  211.             v9 += 8;
  212.         }
  213.         while (v11);
  214.         if (0x1FFED000u << 20)
  215.             __breakpoint(89);
  216.         if (0x1FFEC000u << 20)
  217.             __breakpoint(90);
  218.         ((void (*)(void))sub_FFF2F2CC) ();
  219.         sub_FFF2F2CC(0x1FFEC000u, 536547328, 0x1000u);
  220.         sub_FFF2F2CC(0x1FFEC000 - (unsigned __int16)&sub_FFF2D000,
  221.                  0x1FFAD000u >> 16 << 16,
  222.                  (unsigned __int16)&sub_FFF2D000);
  223.         __mcr(15, 0, 0, 7, 10, 0);
  224.         __mcr(15, 0, 0, 7, 10, 4);
  225.         *0x1FFAF41C = 0xFFFF;
  226.         result = 0x1FFAF414;
  227.         while (*0x1FFAF414 & 1) ;
  228.         *0x1FFAF414 = 0;
  229.     }
  230.     __mcr(15, 0, 0, 7, 14, 0);
  231.     __mcr(15, 0, 0, 7, 10, 5);
  232.     __mcr(15, 0, 0, 7, 5, 0);
  233.     __mcr(15, 0, 0, 7, 5, 6);
  234.     __mcr(15, 0, 0, 7, 10, 4);
  235.     __mcr(15, 0, 0, 7, 5, 4);
  236.     return result;
  237. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement