1 /*-------------------------------------------------------------
3 wiilaunch.c -- Wii NAND title launching and argument passing
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
27 -------------------------------------------------------------*/
38 #include "processor.h"
42 #include "wiilaunch.h"
44 static char __nandbootinfo
[] ATTRIBUTE_ALIGN(32) = "/shared2/sys/NANDBOOTINFO";
45 static char __stateflags
[] ATTRIBUTE_ALIGN(32) = "/title/00000001/00000002/data/state.dat";
47 static int __initialized
= 0;
72 #define TYPE_NANDBOOT 4
73 #define TYPE_SHUTDOWNSYSTEM 5
74 #define RETURN_TO_MENU 0
75 #define RETURN_TO_SETTINGS 1
76 #define RETURN_TO_ARGS 2
79 static NANDBootInfo nandboot
ATTRIBUTE_ALIGN(32);
81 static StateFlags stateflags
ATTRIBUTE_ALIGN(32);
83 static u32
__CalcChecksum(u32
*buf
, int len
)
95 static void __SetChecksum(void *buf
, int len
)
98 p
[0] = __CalcChecksum(p
, len
);
101 static int __ValidChecksum(void *buf
, int len
)
104 return p
[0] == __CalcChecksum(p
, len
);
107 static s32
__WII_ReadStateFlags(void)
112 fd
= IOS_Open(__stateflags
,IPC_OPEN_READ
);
114 memset(&stateflags
,0,sizeof(stateflags
));
115 return WII_EINTERNAL
;
118 ret
= IOS_Read(fd
, &stateflags
, sizeof(stateflags
));
120 if(ret
!= sizeof(stateflags
)) {
121 memset(&stateflags
,0,sizeof(stateflags
));
122 return WII_EINTERNAL
;
124 if(!__ValidChecksum(&stateflags
, sizeof(stateflags
))) {
125 memset(&stateflags
,0,sizeof(stateflags
));
126 return WII_ECHECKSUM
;
131 static s32
__WII_ReadNANDBootInfo(void)
136 fd
= IOS_Open(__nandbootinfo
,IPC_OPEN_READ
);
138 memset(&nandboot
,0,sizeof(nandboot
));
139 return WII_EINTERNAL
;
142 ret
= IOS_Read(fd
, &nandboot
, sizeof(nandboot
));
144 if(ret
!= sizeof(nandboot
)) {
145 memset(&nandboot
,0,sizeof(nandboot
));
146 return WII_EINTERNAL
;
148 if(!__ValidChecksum(&nandboot
, sizeof(nandboot
))) {
149 memset(&nandboot
,0,sizeof(nandboot
));
150 return WII_ECHECKSUM
;
155 static s32
__WII_WriteStateFlags(void)
160 __SetChecksum(&stateflags
, sizeof(stateflags
));
162 fd
= IOS_Open(__stateflags
,IPC_OPEN_READ
|IPC_OPEN_WRITE
);
164 return WII_EINTERNAL
;
167 ret
= IOS_Write(fd
, &stateflags
, sizeof(stateflags
));
169 if(ret
!= sizeof(stateflags
)) {
170 return WII_EINTERNAL
;
175 static s32
__WII_WriteNANDBootInfo(void)
180 __SetChecksum(&nandboot
, sizeof(nandboot
));
182 fd
= IOS_Open(__nandbootinfo
,IPC_OPEN_READ
|IPC_OPEN_WRITE
);
184 return WII_EINTERNAL
;
187 ret
= IOS_Write(fd
, &nandboot
, sizeof(nandboot
));
189 if(ret
!= sizeof(nandboot
)) {
190 return WII_EINTERNAL
;
195 s32
WII_Initialize(void)
197 __WII_ReadStateFlags();
198 __WII_ReadNANDBootInfo();
203 s32
__WII_SetArgs(const char **argv
)
214 for(i
=0; argv
[i
] != NULL
; i
++) {
215 argslen
+= strlen(argv
[i
]) + 1;
218 buflen
= (argslen
+ 3) & ~3;
225 argp
= 0x1000 - argslen
;
226 argvp
= 0x1000 - buflen
;
228 memset(&nandboot
.argbuf
, 0, sizeof(nandboot
.argbuf
));
230 nandboot
.argsoff
= 0x1000 + argvp
;
231 *((u32
*)&nandboot
.argbuf
[argvp
]) = argc
;
234 for(i
=0; i
<argc
; i
++) {
235 strcpy((char*)&nandboot
.argbuf
[argp
], argv
[i
]);
236 *((u32
*)&nandboot
.argbuf
[argvp
]) = argp
+ 0x1000;
238 argp
+= strlen(argv
[i
]) + 1;
240 *((u32
*)&nandboot
.argbuf
[argvp
]) = 0;
245 s32
WII_LaunchTitle(u64 titleID
)
249 STACK_ALIGN(tikview
,views
,4,32);
254 res
= ES_GetNumTicketViews(titleID
, &numviews
);
259 return WII_EINTERNAL
;
261 res
= ES_GetTicketViews(titleID
, views
, numviews
);
270 res
= ES_LaunchTitle(titleID
, &views
[0]);
273 return WII_EINTERNAL
;
276 s32
WII_LaunchTitleWithArgs(u64 titleID
, int launchcode
, ...)
279 const char *argv
[256];
286 sprintf(argv0
, "%016llx", titleID
);
290 va_start(args
, launchcode
);
293 argv
[argc
++] = va_arg(args
, const char *);
294 } while(argv
[argc
- 1] != NULL
);
298 if(ES_GetTitleID(&nandboot
.launcher
) < 0)
299 nandboot
.launcher
= 0x100000002LL
;
301 if(titleID
== 0x100000002LL
)
302 nandboot
.titletype
= 4;
304 nandboot
.titletype
= 2;
305 nandboot
.apptype
= 0x80;
306 nandboot
.launchcode
= launchcode
;
308 stateflags
.type
= TYPE_RETURN
;
309 stateflags
.returnto
= RETURN_TO_ARGS
;
313 __WII_WriteStateFlags();
314 __WII_WriteNANDBootInfo();
316 return WII_LaunchTitle(titleID
);
319 s32
WII_ReturnToMenu(void)
323 stateflags
.type
= TYPE_RETURN
;
324 stateflags
.returnto
= RETURN_TO_MENU
;
325 __WII_WriteStateFlags();
326 return WII_LaunchTitle(0x100000002LL
);
329 s32
WII_ReturnToSettings(void)
333 stateflags
.type
= TYPE_RETURN
;
334 stateflags
.returnto
= RETURN_TO_SETTINGS
;
335 __WII_WriteStateFlags();
336 return WII_LaunchTitle(0x100000002LL
);
339 s32
WII_ReturnToSettingsPage(const char *page
)
344 return WII_LaunchTitleWithArgs(0x100000002LL
, 1, page
, NULL
);
347 s32
WII_OpenURL(const char *url
)
359 ret
= ES_GetNumTitles(&titlecount
);
361 return WII_EINTERNAL
;
363 list
= memalign(32, titlecount
* sizeof(u64
) + 32);
365 ret
= ES_GetTitles(list
, titlecount
);
368 return WII_EINTERNAL
;
371 for(i
=0; i
<titlecount
; i
++) {
372 if((list
[i
] & ~0xFF) == 0x1000148414400LL
) {
382 if(ES_GetStoredTMDSize(tid
, &tmdsize
) < 0)
385 return WII_LaunchTitleWithArgs(tid
, 0, url
, NULL
);