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"
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;
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
)
94 static void __SetChecksum(void *buf
, int len
)
97 p
[0] = __CalcChecksum(p
, len
);
100 static int __ValidChecksum(void *buf
, int len
)
103 return p
[0] == __CalcChecksum(p
, len
);
106 static s32
__WII_ReadStateFlags(void)
111 fd
= IOS_Open(__stateflags
,IPC_OPEN_READ
);
113 memset(&stateflags
,0,sizeof(stateflags
));
114 return WII_EINTERNAL
;
117 ret
= IOS_Read(fd
, &stateflags
, sizeof(stateflags
));
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
;
130 static s32
__WII_ReadNANDBootInfo(void)
135 fd
= IOS_Open(__nandbootinfo
,IPC_OPEN_READ
);
137 memset(&nandboot
,0,sizeof(nandboot
));
138 return WII_EINTERNAL
;
141 ret
= IOS_Read(fd
, &nandboot
, sizeof(nandboot
));
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
;
154 static s32
__WII_WriteStateFlags(void)
159 __SetChecksum(&stateflags
, sizeof(stateflags
));
161 fd
= IOS_Open(__stateflags
,IPC_OPEN_READ
|IPC_OPEN_WRITE
);
163 return WII_EINTERNAL
;
166 ret
= IOS_Write(fd
, &stateflags
, sizeof(stateflags
));
168 if(ret
!= sizeof(stateflags
)) {
169 return WII_EINTERNAL
;
174 static s32
__WII_WriteNANDBootInfo(void)
179 __SetChecksum(&nandboot
, sizeof(nandboot
));
181 fd
= IOS_Open(__nandbootinfo
,IPC_OPEN_READ
|IPC_OPEN_WRITE
);
183 return WII_EINTERNAL
;
186 ret
= IOS_Write(fd
, &nandboot
, sizeof(nandboot
));
188 if(ret
!= sizeof(nandboot
)) {
189 return WII_EINTERNAL
;
194 s32
WII_Initialize(void)
196 __WII_ReadStateFlags();
197 __WII_ReadNANDBootInfo();
202 s32
__WII_SetArgs(const char **argv
)
213 for(i
=0; argv
[i
] != NULL
; i
++) {
214 argslen
+= strlen(argv
[i
]) + 1;
217 buflen
= (argslen
+ 3) & ~3;
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
;
233 for(i
=0; i
<argc
; i
++) {
234 strcpy((char*)&nandboot
.argbuf
[argp
], argv
[i
]);
235 *((u32
*)&nandboot
.argbuf
[argvp
]) = argp
+ 0x1000;
237 argp
+= strlen(argv
[i
]) + 1;
239 *((u32
*)&nandboot
.argbuf
[argvp
]) = 0;
244 s32
WII_LaunchTitle(u64 titleID
)
248 STACK_ALIGN(tikview
,views
,4,32);
253 res
= ES_GetNumTicketViews(titleID
, &numviews
);
258 return WII_EINTERNAL
;
260 res
= ES_GetTicketViews(titleID
, views
, numviews
);
267 res
= ES_LaunchTitle(titleID
, &views
[0]);
270 return WII_EINTERNAL
;
273 s32
WII_LaunchTitleWithArgs(u64 titleID
, int launchcode
, ...)
276 const char *argv
[256];
283 sprintf(argv0
, "%016llx", titleID
);
287 va_start(args
, launchcode
);
290 argv
[argc
++] = va_arg(args
, const char *);
291 } while(argv
[argc
- 1] != NULL
);
295 if(ES_GetTitleID(&nandboot
.launcher
) < 0)
296 nandboot
.launcher
= 0x100000002LL
;
298 if(titleID
== 0x100000002LL
)
299 nandboot
.titletype
= 4;
301 nandboot
.titletype
= 2;
302 nandboot
.apptype
= 0x80;
303 nandboot
.launchcode
= launchcode
;
305 stateflags
.type
= TYPE_RETURN
;
306 stateflags
.returnto
= RETURN_TO_ARGS
;
310 __WII_WriteStateFlags();
311 __WII_WriteNANDBootInfo();
313 return WII_LaunchTitle(titleID
);
316 s32
WII_ReturnToMenu(void)
320 stateflags
.type
= TYPE_RETURN
;
321 stateflags
.returnto
= RETURN_TO_MENU
;
322 __WII_WriteStateFlags();
323 return WII_LaunchTitle(0x100000002LL
);
326 s32
WII_ReturnToSettings(void)
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
)
341 return WII_LaunchTitleWithArgs(0x100000002LL
, 1, page
, NULL
);
344 s32
WII_OpenURL(const char *url
)
356 ret
= ES_GetNumTitles(&titlecount
);
358 return WII_EINTERNAL
;
360 list
= memalign(32, titlecount
* sizeof(u64
) + 32);
362 ret
= ES_GetTitles(list
, titlecount
);
365 return WII_EINTERNAL
;
368 for(i
=0; i
<titlecount
; i
++) {
369 if((list
[i
] & ~0xFF) == 0x1000148414400LL
) {
379 if(ES_GetStoredTMDSize(tid
, &tmdsize
) < 0)
382 return WII_LaunchTitleWithArgs(tid
, 0, url
, NULL
);