update DI disc code
[libogc.git] / libogc / ios.c
blob38c2854376ad78e6991bea7bbca91ee570b16190
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 "asm.h"
35 #include "processor.h"
36 #include "cache.h"
37 #include "ipc.h"
38 #include "stm.h"
39 #include "es.h"
40 #include "ios.h"
41 #include "irq.h"
43 #define IOS_HEAP_SIZE 0x1000
44 #define MAX_IOS_RETRIES 2000
45 #define MAX_IPC_RETRIES 2000
47 //#define DEBUG_IOS
49 #define IOS_MAX_VERSION 61
50 #define IOS_MIN_VERSION 3
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 i;
118 u32 a,b;
120 res = __IOS_InitHeap();
121 if(res<0) return res;
123 res = ES_GetNumTitles(&count);
124 if(res < 0) {
125 #ifdef DEBUG_IOS
126 printf(" GetNumTitles failed: %d\n",res);
127 #endif
128 return res;
130 #ifdef DEBUG_IOS
131 printf(" %d titles on card:\n",count);
132 #endif
133 titles = iosAlloc(__ios_hid, sizeof(u64)*count);
134 if(!titles) {
135 printf(" iosAlloc titles failed\n");
136 return -1;
138 res = ES_GetTitles(titles, count);
139 if(res < 0) {
140 #ifdef DEBUG_IOS
141 printf(" GetTitles failed: %d\n",res);
142 #endif
143 iosFree(__ios_hid, titles);
144 return res;
147 for(i=0; i<count; i++) {
148 a = titles[i]>>32;
149 b = titles[i]&0xFFFFFFFF;
150 if(a != 1) continue;
151 if(b < IOS_MIN_VERSION) continue;
152 if(b > IOS_MAX_VERSION) continue;
153 if(((s32)b) > ((s32)ver)) ver = b;
155 #ifdef DEBUG_IOS
156 printf(" Preferred verson: %d\n",ver);
157 #endif
158 iosFree(__ios_hid, titles);
159 return ver;
162 s32 IOS_GetVersion()
164 u32 vercode;
165 u16 version;
166 DCInvalidateRange((void*)0x80003140,8);
167 vercode = *((u32*)0x80003140);
168 version = vercode >> 16;
169 if(version == 0) return IOS_EBADVERSION;
170 if(version > 0xff) return IOS_EBADVERSION;
171 return version;
174 s32 IOS_GetRevision()
176 u32 vercode;
177 u16 rev;
178 DCInvalidateRange((void*)0x80003140,8);
179 vercode = *((u32*)0x80003140);
180 rev = vercode & 0xFFFF;
181 if(vercode == 0 || rev == 0) return IOS_EBADVERSION;
182 return rev;
185 s32 IOS_GetRevisionMajor()
187 s32 rev;
188 rev = IOS_GetRevision();
189 if(rev < 0) return rev;
190 return (rev>>8)&0xFF;
193 s32 IOS_GetRevisionMinor()
195 s32 rev;
196 rev = IOS_GetRevision();
197 if(rev < 0) return rev;
198 return rev&0xFF;
201 s32 __IOS_LaunchNewIOS(int version)
203 u32 numviews;
204 s32 res, retries;
205 u64 titleID = 0x100000000LL;
206 raw_irq_handler_t irq_handler;
208 STACK_ALIGN(tikview,views,4,32);
209 #ifdef DEBUG_IOS
210 s32 oldversion;
211 #endif
212 s32 newversion;
214 if(version < 3 || version > 0xFF) {
215 return IOS_EBADVERSION;
218 #ifdef DEBUG_IOS
219 oldversion = IOS_GetVersion();
220 if(oldversion>0) printf("Current IOS Version: IOS%d\n",oldversion);
221 #endif
223 titleID |= version;
224 #ifdef DEBUG_IOS
225 printf("Launching IOS TitleID: %016llx\n",titleID);
226 #endif
228 res = ES_GetNumTicketViews(titleID, &numviews);
229 if(res < 0) {
230 #ifdef DEBUG_IOS
231 printf(" GetNumTicketViews failed: %d\n",res);
232 #endif
233 return res;
235 if(numviews > 4) {
236 printf(" GetNumTicketViews too many views: %u\n",numviews);
237 return IOS_ETOOMANYVIEWS;
239 res = ES_GetTicketViews(titleID, views, numviews);
240 if(res < 0) {
241 #ifdef DEBUG_IOS
242 printf(" GetTicketViews failed: %d\n",res);
243 #endif
244 return res;
247 res = ES_LaunchTitleBackground(titleID, &views[0]);
248 if(res < 0) {
249 #ifdef DEBUG_IOS
250 printf(" LaunchTitleBackground failed: %d\n",res);
251 #endif
252 return res;
254 __ES_Reset();
256 // Mask IPC IRQ while we're busy reloading
257 __MaskIrq(IRQ_PI_ACR);
258 irq_handler = IRQ_Free(IRQ_PI_ACR);
260 // Wait for old IOS to change version number before reloading
261 for (retries = 0; retries < MAX_IOS_RETRIES; retries++)
263 newversion = IOS_GetVersion();
264 #ifdef DEBUG_IOS
265 printf(" IOS Version: IOS%d %d.%d\n",newversion,IOS_GetRevisionMajor(),IOS_GetRevisionMinor());
266 #endif
267 if (newversion != version) udelay(1000);
270 if(newversion != version)
272 #ifdef DEBUG_IOS
273 printf(" Version mismatch!\n");
274 #endif
275 return IOS_EMISMATCH;
278 // Wait for new IOS to signal IPC is ready
279 for (retries = 0; retries < MAX_IPC_RETRIES; retries++)
281 if(IPC_ReadReg(1) & 2) break;
282 udelay(1000);
285 IRQ_Request(IRQ_PI_ACR, irq_handler, NULL);
286 __UnmaskIrq(IRQ_PI_ACR);
288 __IPC_Reinitialize();
290 return version;
293 s32 __attribute__((weak)) __IOS_LoadStartupIOS()
295 #if 0
296 int version;
297 int res;
299 res = __ES_Init();
300 if(res < 0) return res;
301 version = IOS_GetPreferredVersion();
302 if(version < 0) {
303 #ifdef DEBUG_IOS
304 printf("GetPreferredVersion failed: %d\n",version);
305 #endif
306 __ES_Close();
307 return version;
309 #ifdef DEBUG_IOS
310 printf("Loading startup IOS: %d\n",version);
311 #endif
312 res = __IOS_LaunchNewIOS(version);
313 if(res < 0) return res;
314 #endif
315 return 0;
318 s32 IOS_ReloadIOS(int version)
320 int ret = 0;
321 int res;
322 #ifdef DEBUG_IOS
323 printf("Reloading to IOS%d\n",version);
324 #endif
325 res = __IOS_ShutdownSubsystems();
326 if(res < 0) ret = res;
327 res = __ES_Init();
328 if(res < 0) ret = res;
329 else {
330 res = __IOS_LaunchNewIOS(version);
331 if(res < 0) {
332 ret = res;
333 __ES_Close();
336 res = __IOS_InitializeSubsystems();
337 if(res < 0) ret = res;
338 return ret;
341 #endif /* defined(HW_RVL) */