bump up min IOS version
[libogc.git] / libogc / wiilaunch.c
blob02c80eecec1c5a4df56f19e11598a025ab95b8e0
1 /*-------------------------------------------------------------
3 wiilaunch.c -- Wii NAND title launching and argument passing
5 Copyright (C) 2008
6 Hector Martin (marcan)
8 This software is provided 'as-is', without any express or implied
9 warranty. In no event will the authors be held liable for any
10 damages arising from the use of this software.
12 Permission is granted to anyone to use this software for any
13 purpose, including commercial applications, and to alter it and
14 redistribute it freely, subject to the following restrictions:
16 1. The origin of this software must not be misrepresented; you
17 must not claim that you wrote the original software. If you use
18 this software in a product, an acknowledgment in the product
19 documentation would be appreciated but is not required.
21 2. Altered source versions must be plainly marked as such, and
22 must not be misrepresented as being the original software.
24 3. This notice may not be removed or altered from any source
25 distribution.
27 -------------------------------------------------------------*/
29 #if defined(HW_RVL)
31 #include <string.h>
32 #include <malloc.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include "ipc.h"
37 #include "asm.h"
38 #include "processor.h"
39 #include "es.h"
40 #include "video.h"
41 #include "wiilaunch.h"
43 static char __nandbootinfo[] ATTRIBUTE_ALIGN(32) = "/shared2/sys/NANDBOOTINFO";
44 static char __stateflags[] ATTRIBUTE_ALIGN(32) = "/title/00000001/00000002/data/state.dat";
46 static int __initialized = 0;
48 typedef struct {
49 u32 checksum;
50 u32 argsoff;
51 u8 unk1;
52 u8 unk2;
53 u8 apptype;
54 u8 titletype;
55 u32 launchcode;
56 u32 unknown[2];
57 u64 launcher;
58 u8 argbuf[0x1000];
59 } NANDBootInfo;
61 typedef struct {
62 u32 checksum;
63 u8 flags;
64 u8 type;
65 u8 discstate;
66 u8 returnto;
67 u32 unknown[6];
68 } StateFlags;
70 #define TYPE_RETURN 3
71 #define TYPE_NANDBOOT 4
72 #define TYPE_SHUTDOWNSYSTEM 5
73 #define RETURN_TO_MENU 0
74 #define RETURN_TO_SETTINGS 1
75 #define RETURN_TO_ARGS 2
78 static NANDBootInfo nandboot ATTRIBUTE_ALIGN(32);
80 static StateFlags stateflags ATTRIBUTE_ALIGN(32);
82 static u32 __CalcChecksum(u32 *buf, int len)
84 u32 sum = 0;
85 int i;
86 len = (len/4);
88 for(i=1; i<len; i++)
89 sum += buf[i];
91 return sum;
94 static void __SetChecksum(void *buf, int len)
96 u32 *p = (u32*)buf;
97 p[0] = __CalcChecksum(p, len);
100 static int __ValidChecksum(void *buf, int len)
102 u32 *p = (u32*)buf;
103 return p[0] == __CalcChecksum(p, len);
106 static s32 __WII_ReadStateFlags(void)
108 int fd;
109 int ret;
111 fd = IOS_Open(__stateflags,IPC_OPEN_READ);
112 if(fd < 0) {
113 memset(&stateflags,0,sizeof(stateflags));
114 return WII_EINTERNAL;
117 ret = IOS_Read(fd, &stateflags, sizeof(stateflags));
118 IOS_Close(fd);
119 if(ret != sizeof(stateflags)) {
120 memset(&stateflags,0,sizeof(stateflags));
121 return WII_EINTERNAL;
123 if(!__ValidChecksum(&stateflags, sizeof(stateflags))) {
124 memset(&stateflags,0,sizeof(stateflags));
125 return WII_ECHECKSUM;
127 return 0;
130 static s32 __WII_ReadNANDBootInfo(void)
132 int fd;
133 int ret;
135 fd = IOS_Open(__nandbootinfo,IPC_OPEN_READ);
136 if(fd < 0) {
137 memset(&nandboot,0,sizeof(nandboot));
138 return WII_EINTERNAL;
141 ret = IOS_Read(fd, &nandboot, sizeof(nandboot));
142 IOS_Close(fd);
143 if(ret != sizeof(nandboot)) {
144 memset(&nandboot,0,sizeof(nandboot));
145 return WII_EINTERNAL;
147 if(!__ValidChecksum(&nandboot, sizeof(nandboot))) {
148 memset(&nandboot,0,sizeof(nandboot));
149 return WII_ECHECKSUM;
151 return 0;
154 static s32 __WII_WriteStateFlags(void)
156 int fd;
157 int ret;
159 __SetChecksum(&stateflags, sizeof(stateflags));
161 fd = IOS_Open(__stateflags,IPC_OPEN_READ|IPC_OPEN_WRITE);
162 if(fd < 0) {
163 return WII_EINTERNAL;
166 ret = IOS_Write(fd, &stateflags, sizeof(stateflags));
167 IOS_Close(fd);
168 if(ret != sizeof(stateflags)) {
169 return WII_EINTERNAL;
171 return 0;
174 static s32 __WII_WriteNANDBootInfo(void)
176 int fd;
177 int ret;
179 __SetChecksum(&nandboot, sizeof(nandboot));
181 fd = IOS_Open(__nandbootinfo,IPC_OPEN_READ|IPC_OPEN_WRITE);
182 if(fd < 0) {
183 return WII_EINTERNAL;
186 ret = IOS_Write(fd, &nandboot, sizeof(nandboot));
187 IOS_Close(fd);
188 if(ret != sizeof(nandboot)) {
189 return WII_EINTERNAL;
191 return 0;
194 s32 WII_Initialize(void)
196 __WII_ReadStateFlags();
197 __WII_ReadNANDBootInfo();
198 __initialized = 1;
199 return 0;
202 s32 __WII_SetArgs(const char **argv)
204 int argslen = 0;
205 int buflen = 0;
206 int argvp, argp;
207 int argc = 0;
208 int i;
210 if(!__initialized)
211 return WII_ENOTINIT;
213 for(i=0; argv[i] != NULL; i++) {
214 argslen += strlen(argv[i]) + 1;
215 argc++;
217 buflen = (argslen + 3) & ~3;
218 buflen += 4 * argc;
219 buflen += 8;
221 if(buflen > 0x1000)
222 return WII_E2BIG;
224 argp = 0x1000 - argslen;
225 argvp = 0x1000 - buflen;
227 memset(&nandboot.argbuf, 0, sizeof(nandboot.argbuf));
229 nandboot.argsoff = 0x1000 + argvp;
230 *((u32*)&nandboot.argbuf[argvp]) = argc;
231 argvp += 4;
233 for(i=0; i<argc; i++) {
234 strcpy((char*)&nandboot.argbuf[argp], argv[i]);
235 *((u32*)&nandboot.argbuf[argvp]) = argp + 0x1000;
236 argvp += 4;
237 argp += strlen(argv[i]) + 1;
239 *((u32*)&nandboot.argbuf[argvp]) = 0;
241 return 0;
244 s32 WII_LaunchTitle(u64 titleID)
246 s32 res;
247 u32 numviews;
248 STACK_ALIGN(tikview,views,4,32);
250 if(!__initialized)
251 return WII_ENOTINIT;
253 res = ES_GetNumTicketViews(titleID, &numviews);
254 if(res < 0) {
255 return res;
257 if(numviews > 4) {
258 return WII_EINTERNAL;
260 res = ES_GetTicketViews(titleID, views, numviews);
261 if(res < 0)
262 return res;
264 VIDEO_SetBlack(1);
265 VIDEO_Flush();
267 res = ES_LaunchTitle(titleID, &views[0]);
268 if(res < 0)
269 return res;
270 return WII_EINTERNAL;
273 s32 WII_LaunchTitleWithArgs(u64 titleID, int launchcode, ...)
275 char argv0[20];
276 const char *argv[256];
277 int argc = 1;
278 va_list args;
280 if(!__initialized)
281 return WII_ENOTINIT;
283 sprintf(argv0, "%016llx", titleID);
285 argv[0] = argv0;
287 va_start(args, launchcode);
289 do {
290 argv[argc++] = va_arg(args, const char *);
291 } while(argv[argc - 1] != NULL);
293 va_end(args);
295 if(ES_GetTitleID(&nandboot.launcher) < 0)
296 nandboot.launcher = 0x100000002LL;
298 if(titleID == 0x100000002LL)
299 nandboot.titletype = 4;
300 else
301 nandboot.titletype = 2;
302 nandboot.apptype = 0x80;
303 nandboot.launchcode = launchcode;
305 stateflags.type = TYPE_RETURN;
306 stateflags.returnto = RETURN_TO_ARGS;
308 __WII_SetArgs(argv);
310 __WII_WriteStateFlags();
311 __WII_WriteNANDBootInfo();
313 return WII_LaunchTitle(titleID);
316 s32 WII_ReturnToMenu(void)
318 if(!__initialized)
319 return WII_ENOTINIT;
320 stateflags.type = TYPE_RETURN;
321 stateflags.returnto = RETURN_TO_MENU;
322 __WII_WriteStateFlags();
323 return WII_LaunchTitle(0x100000002LL);
326 s32 WII_ReturnToSettings(void)
328 if(!__initialized)
329 return WII_ENOTINIT;
330 stateflags.type = TYPE_RETURN;
331 stateflags.returnto = RETURN_TO_SETTINGS;
332 __WII_WriteStateFlags();
333 return WII_LaunchTitle(0x100000002LL);
336 s32 WII_ReturnToSettingsPage(const char *page)
338 if(!__initialized)
339 return WII_ENOTINIT;
341 return WII_LaunchTitleWithArgs(0x100000002LL, 1, page, NULL);
344 s32 WII_OpenURL(const char *url)
346 u32 tmdsize;
347 u64 tid = 0;
348 u64 *list;
349 u32 titlecount;
350 s32 ret;
351 u32 i;
353 if(!__initialized)
354 return WII_ENOTINIT;
356 ret = ES_GetNumTitles(&titlecount);
357 if(ret < 0)
358 return WII_EINTERNAL;
360 list = memalign(32, titlecount * sizeof(u64) + 32);
362 ret = ES_GetTitles(list, titlecount);
363 if(ret < 0) {
364 free(list);
365 return WII_EINTERNAL;
368 for(i=0; i<titlecount; i++) {
369 if((list[i] & ~0xFF) == 0x1000148414400LL) {
370 tid = list[i];
371 break;
374 free(list);
376 if(!tid)
377 return WII_EINSTALL;
379 if(ES_GetStoredTMDSize(tid, &tmdsize) < 0)
380 return WII_EINSTALL;
382 return WII_LaunchTitleWithArgs(tid, 0, url, NULL);
385 #endif