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