smb improvements (rodries)
[libogc.git] / libogc / ios.c
blobfa674d257bc9aa7fb4b8c4ade1f48210f72a05cd
1 /*-------------------------------------------------------------
3 ios.c -- IOS control
5 Copyright (C) 2008
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
8 Hector Martin (marcan)
10 This software is provided 'as-is', without any express or implied
11 warranty. In no event will the authors be held liable for any
12 damages arising from the use of this software.
14 Permission is granted to anyone to use this software for any
15 purpose, including commercial applications, and to alter it and
16 redistribute it freely, subject to the following restrictions:
18 1. The origin of this software must not be misrepresented; you
19 must not claim that you wrote the original software. If you use
20 this software in a product, an acknowledgment in the product
21 documentation would be appreciated but is not required.
23 2. Altered source versions must be plainly marked as such, and
24 must not be misrepresented as being the original software.
26 3. This notice may not be removed or altered from any source
27 distribution.
29 -------------------------------------------------------------*/
31 #if defined(HW_RVL)
33 #include <stdio.h>
34 #include <malloc.h>
35 #include "asm.h"
36 #include "processor.h"
37 #include "cache.h"
38 #include "ipc.h"
39 #include "stm.h"
40 #include "es.h"
41 #include "ios.h"
42 #include "irq.h"
44 #define IOS_HEAP_SIZE 0x1000
45 #define MAX_IPC_RETRIES 400
47 //#define DEBUG_IOS
49 #define IOS_MAX_VERSION 61
50 #define IOS_MIN_VERSION 28
52 static s32 __ios_hid = -1;
53 extern void udelay(int us);
55 s32 __IOS_InitHeap(void)
57 if(__ios_hid <0 ) {
58 __ios_hid = iosCreateHeap(IOS_HEAP_SIZE);
59 if(__ios_hid < 0) return __ios_hid;
61 return 0;
64 // These two functions deal with the "internal" IOS subsystems that are used by default by libogc
65 // Other stuff should be inited by the user and deinited by the exit callbacks. The user is also responsible
66 // for deiniting other stuff before an IOS reload and reiniting them after.
67 s32 __IOS_InitializeSubsystems(void)
69 s32 res;
70 s32 ret = 0;
71 #ifdef DEBUG_IOS
72 printf("IOS Subsystem Init\n");
73 #endif
74 res = __ES_Init();
75 if(res < 0) {
76 ret = res;
77 #ifdef DEBUG_IOS
78 printf("ES Init failed: %d\n",ret);
79 #endif
81 res = __STM_Init();
82 if(res < 0) {
83 ret = res;
84 #ifdef DEBUG_IOS
85 printf("STM Init failed: %d\n",ret);
86 #endif
88 #ifdef DEBUG_IOS
89 printf("IOS Subsystem Init Done: %d\n",ret);
90 #endif
91 return ret;
94 s32 __IOS_ShutdownSubsystems(void)
96 s32 res;
97 s32 ret = 0;
98 #ifdef DEBUG_IOS
99 printf("IOS Subsystem Close\n");
100 #endif
101 res = __STM_Close();
102 if(res < 0) ret = res;
103 res = __ES_Close();
104 if(res < 0) ret = res;
105 #ifdef DEBUG_IOS
106 printf("IOS Subsystem Close Done: %d\n",ret);
107 #endif
108 return ret;
111 s32 IOS_GetPreferredVersion()
113 int ver = IOS_EBADVERSION;
114 s32 res;
115 u32 count;
116 u64 *titles;
117 u32 tmd_size;
118 u32 i;
119 u32 a,b;
121 res = __IOS_InitHeap();
122 if(res<0) return res;
124 res = ES_GetNumTitles(&count);
125 if(res < 0) {
126 #ifdef DEBUG_IOS
127 printf(" GetNumTitles failed: %d\n",res);
128 #endif
129 return res;
131 #ifdef DEBUG_IOS
132 printf(" %d titles on card:\n",count);
133 #endif
134 titles = iosAlloc(__ios_hid, sizeof(u64)*count);
135 if(!titles) {
136 printf(" iosAlloc titles failed\n");
137 return -1;
139 res = ES_GetTitles(titles, count);
140 if(res < 0) {
141 #ifdef DEBUG_IOS
142 printf(" GetTitles failed: %d\n",res);
143 #endif
144 iosFree(__ios_hid, titles);
145 return res;
148 u32 *tmdbuffer = memalign(32, MAX_SIGNED_TMD_SIZE);
150 if(!tmdbuffer)
152 iosFree(__ios_hid, titles);
153 return -1;
156 for(i=0; i<count; i++) {
157 a = titles[i]>>32;
158 b = titles[i]&0xFFFFFFFF;
159 if(a != 1) continue;
160 if(b < IOS_MIN_VERSION) continue;
161 if(b > IOS_MAX_VERSION) continue;
163 if (ES_GetStoredTMDSize(titles[i], &tmd_size) < 0)
164 continue;
166 if (tmd_size < 0 || tmd_size > 4096)
167 continue;
169 if(ES_GetStoredTMD(titles[i], (signed_blob *)tmdbuffer, tmd_size) < 0)
170 continue;
172 if (!tmdbuffer[1] && !tmdbuffer[2])
173 continue;
175 if((((s32)b) > ((s32)ver) && ver != 58) || b == 58) ver = b;
177 #ifdef DEBUG_IOS
178 printf(" Preferred verson: %d\n",ver);
179 #endif
180 iosFree(__ios_hid, titles);
181 free(tmdbuffer);
182 return ver;
185 s32 IOS_GetVersion()
187 u32 vercode;
188 u16 version;
189 DCInvalidateRange((void*)0x80003140,8);
190 vercode = *((u32*)0x80003140);
191 version = vercode >> 16;
192 if(version == 0) return IOS_EBADVERSION;
193 if(version > 0xff) return IOS_EBADVERSION;
194 return version;
197 s32 IOS_GetRevision()
199 u32 vercode;
200 u16 rev;
201 DCInvalidateRange((void*)0x80003140,8);
202 vercode = *((u32*)0x80003140);
203 rev = vercode & 0xFFFF;
204 if(vercode == 0 || rev == 0) return IOS_EBADVERSION;
205 return rev;
208 s32 IOS_GetRevisionMajor()
210 s32 rev;
211 rev = IOS_GetRevision();
212 if(rev < 0) return rev;
213 return (rev>>8)&0xFF;
216 s32 IOS_GetRevisionMinor()
218 s32 rev;
219 rev = IOS_GetRevision();
220 if(rev < 0) return rev;
221 return rev&0xFF;
224 s32 __IOS_LaunchNewIOS(int version)
226 u32 numviews;
227 s32 res;
228 u64 titleID = 0x100000000LL;
229 raw_irq_handler_t irq_handler;
230 u32 counter;
232 STACK_ALIGN(tikview,views,4,32);
233 #ifdef DEBUG_IOS
234 s32 oldversion;
235 #endif
236 s32 newversion;
238 if(version < 3 || version > 0xFF) {
239 return IOS_EBADVERSION;
242 #ifdef DEBUG_IOS
243 oldversion = IOS_GetVersion();
244 if(oldversion>0) printf("Current IOS Version: IOS%d\n",oldversion);
245 #endif
247 titleID |= version;
248 #ifdef DEBUG_IOS
249 printf("Launching IOS TitleID: %016llx\n",titleID);
250 #endif
252 res = ES_GetNumTicketViews(titleID, &numviews);
253 if(res < 0) {
254 #ifdef DEBUG_IOS
255 printf(" GetNumTicketViews failed: %d\n",res);
256 #endif
257 return res;
259 if(numviews > 4) {
260 printf(" GetNumTicketViews too many views: %u\n",numviews);
261 return IOS_ETOOMANYVIEWS;
263 res = ES_GetTicketViews(titleID, views, numviews);
264 if(res < 0) {
265 #ifdef DEBUG_IOS
266 printf(" GetTicketViews failed: %d\n",res);
267 #endif
268 return res;
271 write32(0x80003140, 0);
273 res = ES_LaunchTitleBackground(titleID, &views[0]);
274 if(res < 0) {
275 #ifdef DEBUG_IOS
276 printf(" LaunchTitleBackground failed: %d\n",res);
277 #endif
278 return res;
281 __ES_Reset();
283 // Mask IPC IRQ while we're busy reloading
284 __MaskIrq(IRQ_PI_ACR);
285 irq_handler = IRQ_Free(IRQ_PI_ACR);
287 #ifdef DEBUG_IOS
288 printf("Waiting for IOS ...\n");
289 #endif
290 while ((read32(0x80003140) >> 16) == 0)
291 udelay(1000);
293 #ifdef DEBUG_IOS
294 u32 v = read32(0x80003140);
295 printf("IOS loaded: IOS%d v%d.%d\n", v >> 16, (v >> 8) & 0xff, v & 0xff);
296 #endif
298 #ifdef DEBUG_IOS
299 printf("Waiting for IPC ...\n");
300 #endif
301 for (counter = 0; !(read32(0x0d000004) & 2); counter++) {
302 udelay(1000);
304 if (counter >= MAX_IPC_RETRIES)
305 break;
308 #ifdef DEBUG_IOS
309 printf("IPC started (%u)\n", counter);
310 #endif
312 IRQ_Request(IRQ_PI_ACR, irq_handler, NULL);
313 __UnmaskIrq(IRQ_PI_ACR);
315 __IPC_Reinitialize();
317 newversion = IOS_GetVersion();
319 if(newversion != version) {
320 #ifdef DEBUG_IOS
321 printf(" Version mismatch!\n");
322 #endif
323 return IOS_EMISMATCH;
326 return version;
329 s32 __attribute__((weak)) __IOS_LoadStartupIOS()
331 #if 0
332 int version;
333 int res;
335 res = __ES_Init();
336 if(res < 0) return res;
337 version = IOS_GetPreferredVersion();
338 if(version < 0) {
339 #ifdef DEBUG_IOS
340 printf("GetPreferredVersion failed: %d\n",version);
341 #endif
342 __ES_Close();
343 return version;
345 #ifdef DEBUG_IOS
346 printf("Loading startup IOS: %d\n",version);
347 #endif
348 res = __IOS_LaunchNewIOS(version);
349 if(res < 0) return res;
350 #endif
352 return 0;
355 s32 IOS_ReloadIOS(int version)
357 int ret = 0;
358 int res;
360 #ifdef DEBUG_IOS
361 printf("Reloading to IOS%d\n",version);
362 #endif
364 res = __IOS_ShutdownSubsystems();
365 if(res < 0) {
366 #ifdef DEBUG_IOS
367 printf("__IOS_ShutdownSubsystems failed: %d\n", res);
368 #endif
369 ret = res;
372 res = __ES_Init();
373 if(res < 0) {
374 #ifdef DEBUG_IOS
375 printf("__ES_Init failed: %d\n", res);
376 #endif
377 ret = res;
378 } else {
379 res = __IOS_LaunchNewIOS(version);
380 if(res < 0) {
381 #ifdef DEBUG_IOS
382 printf("__IOS_LaunchNewIOS failed: %d\n", res);
383 #endif
384 ret = res;
385 __ES_Close();
389 res = __IOS_InitializeSubsystems();
390 if(res < 0) {
391 #ifdef DEBUG_IOS
392 printf("__IOS_InitializeSubsystems failed: %d\n", res);
393 #endif
394 ret = res;
397 return ret;
400 #endif /* defined(HW_RVL) */