1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - OS
3 File: os_application_jump.c
4
5 Copyright 2007-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-12-08#$
14 $Rev: 9571 $
15 $Author: okajima_manabu $
16 *---------------------------------------------------------------------------*/
17
18 #include <twl/os.h>
19 #include <application_jump_private.h>
20 #include <twl/spi.h>
21 #include <twl/code32.h>
22 #include <twl/mcu.h>
23 #include <twl/hw/common/mmap_shared.h>
24 #include <twl/hw/common/mmap_parameter.h>
25
26 // Define data-------------------------------------------------------
27 #define OSi_LAUNCHER_PARAM_MAGIC_CODE "TLNC"
28 #define OSi_LAUNCHER_PARAM_MAGIC_CODE_LEN 4
29 #define OSi_TITLE_ID_MEDIA_FLAG_MASK ( 0x0001ULL << 34 )
30 #define OSi_TITLE_ID_DATA_ONLY_FLAG_MASK ( 0x0001ULL << 35 )
31 #define OSi_TMP_APP_SIZE_MAX ( 16 * 1024 * 1024 )
32
33 #define OSi_TMP_APP_PATH_RAW "nand:/tmp/jump.app"
34 #define OSi_TMP_APP_PATH_RAW_LENGTH 18
35
36 typedef struct NandFirmResetParameter {
37 u8 isHotStart :1;
38 u8 isResetSW :1;
39 u8 rsv :5;
40 u8 isValid :1;
41 }NandFirmResetParameter;
42
43 // NAND firmware parameter address
44 #define OSi_GetNandFirmResetParam() ( (NandFirmResetParameter *)HW_NAND_FIRM_HOTSTART_FLAG )
45
46 // Launcher parameter address
47 #define OSi_GetLauncherParam() ( (LauncherParam *)HW_PARAM_LAUNCH_PARAM )
48
49
50 // Extern data-------------------------------------------------------
51
52 // Function's prototype----------------------------------------------
53 static void OSi_DoHardwareReset( void );
54
55 // Global variables--------------------------------------------------
56
57 // Static variables--------------------------------------------------
58 #include <twl/ltdmain_begin.h>
59 static OSTitleId s_prevTitleId = 0;
60 #include <twl/ltdmain_end.h>
61 // Const data--------------------------------------------------------
62
63 #ifdef SDK_ARM9
64
OSi_InitPrevTitleId(void)65 void OSi_InitPrevTitleId( void )
66 {
67 OSDeliverArgInfo deliverArgInfo;
68 OS_InitDeliverArgInfo( &deliverArgInfo, 0 );
69 if ( OS_DELIVER_ARG_SUCCESS == OS_DecodeDeliverArg() )
70 {
71 s_prevTitleId = OS_GetTitleIdFromDeliverArg();
72 }
73 OS_SetDeliverArgStateInvalid();
74 }
75
76 // For safety purposes, locate this function in itcm
77 #include <twl/itcm_begin.h>
OSi_DoHardwareReset(void)78 static void OSi_DoHardwareReset( void )
79 {
80 // [TODO:] Lastly, change to HW reset via a microcomputer
81 // Issue reset command
82 PM_ForceToResetHardware();
83 OS_Terminate();
84 }
85
86 #include <twl/itcm_end.h>
87
88 /* The following code is located in the TWL extended memory region */
89 #ifdef SDK_TWL
90 #include <twl/ltdmain_begin.h>
91 #endif
92 // Hardware reset by specifying LauncherParam
OS_SetLauncherParamAndResetHardware(OSTitleId id,LauncherBootFlags * flag)93 void OS_SetLauncherParamAndResetHardware( OSTitleId id, LauncherBootFlags *flag )
94 {
95 // Copy the manufacturer and game codes
96 u32 *maker_code_dest_addr = (u32 *)((u32)(OSi_GetLauncherParam()) + HW_PARAM_DELIVER_ARG_MAKERCODE_OFS);
97 u32 *game_code_dest_addr = (u32 *)((u32)(OSi_GetLauncherParam()) + HW_PARAM_DELIVER_ARG_GAMECODE_OFS);
98 u16 *maker_code_src_addr = (u16 *)(HW_TWL_ROM_HEADER_BUF + 0x10);
99 u32 *game_code_src_addr = (u32 *)(HW_TWL_ROM_HEADER_BUF + 0xc);
100 *maker_code_dest_addr = (u32)*maker_code_src_addr;
101 *game_code_dest_addr = *game_code_src_addr;
102
103 // Set the launcher parameter
104 OSi_GetLauncherParam()->body.v1.prevTitleID = *(OSTitleId *)(HW_TWL_ROM_HEADER_BUF + 0x230);
105 OSi_GetLauncherParam()->body.v1.bootTitleID = id;
106 OSi_GetLauncherParam()->body.v1.flags = *flag;
107 MI_CpuCopyFast( OSi_LAUNCHER_PARAM_MAGIC_CODE, (char *)&OSi_GetLauncherParam()->header.magicCode, OSi_LAUNCHER_PARAM_MAGIC_CODE_LEN);
108 OSi_GetLauncherParam()->header.bodyLength = sizeof(LauncherParamBody);
109 OSi_GetLauncherParam()->header.crc16 = SVC_GetCRC16( 65535, &OSi_GetLauncherParam()->body, OSi_GetLauncherParam()->header.bodyLength );
110 OSi_GetLauncherParam()->header.version = 1;
111
112 if( id == 0 || OS_IsDeliverArgEncoded() != TRUE || OS_GetTitleIdLastEncoded() != OSi_GetLauncherParam()->body.v1.prevTitleID )
113 {
114 // If the DeliverArg is not encoded with the current application, force initialization of DeliverArg and encode
115 OSDeliverArgInfo deliverArgInfo;
116 OS_InitDeliverArgInfo( &deliverArgInfo, 0 );
117 (void)OS_EncodeDeliverArg();
118 }
119
120 DC_FlushRange((const void *)HW_PARAM_DELIVER_ARG, HW_PARAM_DELIVER_ARG_SIZE + HW_PARAM_LAUNCH_PARAM_SIZE );
121 DC_WaitWriteBufferEmpty();
122
123 OSi_DoHardwareReset();
124 }
125
126 // Function that returns from the application after the application jump to the original application
127 // If there is no original application, FALSE
OS_ReturnToPrevApplication(void)128 BOOL OS_ReturnToPrevApplication( void )
129 {
130 if( s_prevTitleId != 0)
131 {
132 return OS_DoApplicationJump( s_prevTitleId, OS_APP_JUMP_NORMAL ); //Never return
133 }
134 return FALSE;
135 }
136
IsSameTitleID(OSTitleId titleID,OSTitleId listedTitleID)137 static inline BOOL IsSameTitleID( OSTitleId titleID, OSTitleId listedTitleID )
138 {
139 if ((char)titleID == 'A')
140 {
141 // Corresponding to language code A option
142 return (listedTitleID >> 8) == (titleID >> 8);
143 }
144 else
145 {
146 return listedTitleID == titleID;
147 }
148 }
149
150 // Get the ID that can actually be started for the given title ID
151 // If a startable ID exists, set that ID to the *bootableTitleID and return TRUE
152 // If a startable ID does not exist, return FALSE
OS_GetBootableTitleID(OSTitleId titleID,OSTitleId * bootableTitleID)153 static BOOL OS_GetBootableTitleID( OSTitleId titleID, OSTitleId *bootableTitleID )
154 {
155 const OSTitleIDList *list = (const OSTitleIDList *)HW_OS_TITLE_ID_LIST;
156 const int OS_TITLE_ID_LIST_MAX = sizeof(list->TitleID) / sizeof(*list->TitleID);
157 const int num = MATH_MIN(list->num, OS_TITLE_ID_LIST_MAX);
158 int i;
159 for (i = 0; i < num; ++i)
160 {
161 if (IsSameTitleID(titleID, list->TitleID[i]) && (list->appJumpFlag[i / 8] & (u8)(0x1 << (i % 8))))
162 {
163 *bootableTitleID = list->TitleID[i];
164 return TRUE;
165 }
166 }
167 return FALSE;
168 }
169
170 // Whether an application has been installed that corresponds to that TitleID
OSi_CanApplicationJumpTo(OSTitleId titleID)171 BOOL OSi_CanApplicationJumpTo( OSTitleId titleID )
172 {
173 return OS_GetBootableTitleID(titleID, &titleID);
174 }
175
176 // Wrapper for OS_SetLauncherParamAndResetHardware
OS_DoApplicationJump(OSTitleId id,OSAppJumpType jumpType)177 BOOL OS_DoApplicationJump( OSTitleId id, OSAppJumpType jumpType )
178 {
179 FSFile file[1];
180 LauncherBootFlags flag;
181 u8 platform_code;
182 u8 bit_field;
183
184 switch( jumpType )
185 {
186 case OS_APP_JUMP_NORMAL:
187 if( id & OSi_TITLE_ID_DATA_ONLY_FLAG_MASK )
188 {
189 // Set so that it is not possible to jump to DataOnly items
190 return FALSE;
191 }
192 if( id != 0 )
193 {
194 if (!OS_GetBootableTitleID(id, &id))
195 {
196 return FALSE;
197 }
198 }
199 // Set the bootType and jump
200 if( id & OSi_TITLE_ID_MEDIA_FLAG_MASK )
201 {
202 flag.bootType = LAUNCHER_BOOTTYPE_NAND;
203 }else
204 {
205 flag.bootType = LAUNCHER_BOOTTYPE_ROM;
206 }
207 break;
208 case OS_APP_JUMP_TMP:
209 // When you yourself are a TMP application, TMP jump is not possible
210 if( OS_IsTemporaryApplication() )
211 {
212 OS_TPrintf("OS_DoApplicationJump error : tmp app can't jump to tmp app!\n");
213 return FALSE;
214 }
215 // Get the TitleID from the file of OS_TMP_APP_PATH and check the allowed TMP jump bits
216 FS_InitFile( file );
217 if( !FS_OpenFileEx(file, OS_TMP_APP_PATH, FS_FILEMODE_R) )
218 {
219 OS_TPrintf("OS_DoApplicationJump error : tmp app open error!\n");
220 return FALSE;
221 }
222 // File size check
223 if( FS_GetFileLength( file ) > OSi_TMP_APP_SIZE_MAX )
224 {
225 OS_TPrintf("OS_DoApplicationJump error : too large tmp app size!\n");
226 return FALSE;
227 }
228
229 if( !FS_SeekFile( file, 0x12, FS_SEEK_SET ) ||
230 ( sizeof(platform_code) != FS_ReadFile( file, &platform_code, sizeof(platform_code) ) ) ||
231 !FS_SeekFile( file, 0x1d, FS_SEEK_SET ) ||
232 ( sizeof(bit_field) != FS_ReadFile( file, &bit_field, sizeof(bit_field) ) )
233 )
234 {
235 OS_TPrintf("OS_DoApplicationJump error : tmp app read error!\n");
236 (void)FS_CloseFile(file);
237 return FALSE;
238 }
239
240 if( !( bit_field & 0x2 ) )
241 {
242 OS_TPrintf("OS_DoApplicationJump error : tmp jump bit is not enabled!\n");
243 (void)FS_CloseFile(file);
244 return FALSE;
245 }
246 flag.bootType = LAUNCHER_BOOTTYPE_TEMP;
247 // The TWL application gets the title ID from the header and enters it. For NTR applications, for the time being enter TitleIDs other than 0
248 if( platform_code & 0x2 )
249 {
250 if( !FS_SeekFile( file, 0x0230, FS_SEEK_SET ) ||
251 ( sizeof(id) != FS_ReadFile( file, &id, sizeof(id) ) )
252 )
253 {
254 OS_TPrintf("OS_DoApplicationJump error : tmp app read error!\n");
255 (void)FS_CloseFile(file);
256 return FALSE;
257 }
258 }else
259 {
260 id = 0x1;
261 }
262 (void)FS_CloseFile(file);
263 break;
264 default:
265 return FALSE;
266 }
267
268 if ( PMi_TryLockForReset() == FALSE )
269 {
270 return FALSE;
271 }
272
273 // Shared configurations
274 flag.isValid = TRUE;
275 flag.isLogoSkip = TRUE;
276 flag.isInitialShortcutSkip = FALSE;
277 flag.isAppLoadCompleted = FALSE;
278 flag.isAppRelocate = FALSE;
279 flag.rsv = 0;
280
281 OS_SetLauncherParamAndResetHardware( id, &flag ); // never return.
282 return TRUE;
283 }
284
285 /* The code above is located in the TWL extended memory region */
286 #ifdef SDK_TWL
287 #include <twl/ltdmain_end.h>
288 #endif
289
290 /*---------------------------------------------------------------------------*
291 Name: OS_JumpToSystemMenu
292
293 Description: Run a hardware reset and jump to the system menu
294
295 Arguments: None.
296
297 Returns: FALSE ... Application jump failed for some reason
298 * If the process was successful, a reset process occurred during this function so TRUE is not returned
299
300 *---------------------------------------------------------------------------*/
OS_JumpToSystemMenu(void)301 BOOL OS_JumpToSystemMenu( void )
302 {
303 BOOL result = FALSE;
304 #ifdef SDK_TWL
305 if( OS_IsRunOnTwl() )
306 {
307 // ---- Application Jump with id==0
308 // means to jump to system menu.
309 result = OS_DoApplicationJump( 0, OS_APP_JUMP_NORMAL );
310 }
311 else
312 #endif
313 {
314 OS_Warning("This Hardware don't support this funciton");
315 }
316 return result;
317 }
318
319 /*---------------------------------------------------------------------------*
320 Name: OS_RebootSystem
321
322 Description: Runs a hardware reset and restarts itself.
323
324 Arguments: None.
325
326 Returns: FALSE Run on NITRO, or failure in restarting
327 * If the process was successful, a reset occurred during this function so TRUE is not returned
328
329 *---------------------------------------------------------------------------*/
OS_RebootSystem(void)330 BOOL OS_RebootSystem( void )
331 {
332 #ifdef SDK_TWL
333 if( OS_IsRunOnTwl() )
334 {
335 if( OS_IsTemporaryApplication() )
336 {
337 OS_TPrintf("OS_RebootSystem error : tmp app can't execute this function\n");
338 return FALSE;
339 }
340 // Application jump to self
341 return OS_DoApplicationJump( OS_GetTitleId(), OS_APP_JUMP_NORMAL );
342 }
343 else
344 #endif
345 {
346 OS_Warning("This Hardware don't support this funciton");
347 return FALSE;
348 }
349 }
350
351 /*---------------------------------------------------------------------------*
352 Name: OS_IsRebooted
353
354 Description: Checks whether a restart was applied using OS_RebootSystem
355
356 Arguments: None.
357
358 Returns: TRUE Restart was applied more than one time
359 FALSE First startup
360 *---------------------------------------------------------------------------*/
OS_IsRebooted(void)361 BOOL OS_IsRebooted( void )
362 {
363 BOOL result = FALSE;
364 #ifdef SDK_TWL
365 if( OS_IsRunOnTwl() )
366 {
367 if( OS_GetTitleId() == s_prevTitleId )
368 {
369 result = TRUE;
370 }
371 }
372 #endif
373 return result;
374 }
375
376 /*---------------------------------------------------------------------------*
377 Name: OS_IsTemporaryApplication
378
379 Description: Checks whether self is a TMP application.
380
381 Arguments: None.
382
383 Returns: TRUE TMP application
384 FALSE Other than TMP applications
385 *---------------------------------------------------------------------------*/
OS_IsTemporaryApplication(void)386 BOOL OS_IsTemporaryApplication(void)
387 {
388 #ifdef SDK_TWL
389 static BOOL isChecked = FALSE, isTmpApp = FALSE;
390 if( OS_IsRunOnTwl() )
391 {
392 if( isChecked == FALSE ) /* If already checked, flow previous results */
393 {
394 if( 0 == STD_CompareNString( OS_GetBootSRLPath(), OSi_TMP_APP_PATH_RAW, OSi_TMP_APP_PATH_RAW_LENGTH ) )
395 {
396 isTmpApp = TRUE;
397 }
398 else
399 {
400 isTmpApp = FALSE;
401 }
402 isChecked = TRUE;
403 }
404 return isTmpApp;
405 }
406 #endif
407 return FALSE;
408 }
409
410 #else // SDK_ARM9
411 //----------------------------------------------------------------
412 // For ARM7
413
OSi_IsValidLauncherParam(void)414 static BOOL OSi_IsValidLauncherParam( void )
415 {
416 return ( STD_StrNCmp( (const char *)&OSi_GetLauncherParam()->header.magicCode,
417 OSi_LAUNCHER_PARAM_MAGIC_CODE,
418 OSi_LAUNCHER_PARAM_MAGIC_CODE_LEN ) == 0 ) &&
419 ( OSi_GetLauncherParam()->header.bodyLength > 0 ) &&
420 ( OSi_GetLauncherParam()->header.crc16 == SVC_GetCRC16( 65535, &OSi_GetLauncherParam()->body, OSi_GetLauncherParam()->header.bodyLength ) );
421 }
422
OSi_IsEnableJTAG(void)423 static BOOL OSi_IsEnableJTAG( void )
424 {
425 // If SCFG register is invalid, the SCFG register value becomes "0". Check the value retracted to WRAM.
426 u8 value = (u8)(( reg_SCFG_EXT & REG_SCFG_EXT_CFG_MASK ) ?
427 ( reg_SCFG_JTAG & REG_SCFG_JTAG_CPUJE_MASK ) :
428 ( *(u8 *)HWi_WSYS09_ADDR & HWi_WSYS09_JTAG_CPUJE_MASK ));
429 return value ? TRUE : FALSE;
430 }
431
432 // Launcher parameter lead and determine hot/cold boot
433 // Return TRUE if launcher parameter is valid; FALSE if invalid
434 // If the launcher parameter in LauncherParam is valid, that launcher parameter is stored
435 // TRUE if hot boot in isHotstart; False is stored if a cold boot.
OS_ReadLauncherParameter(LauncherParam * buf,BOOL * isHotstart)436 BOOL OS_ReadLauncherParameter( LauncherParam *buf, BOOL *isHotstart )
437 {
438 if( !OSi_GetNandFirmResetParam()->isValid ) {
439 *(u8 *)OSi_GetNandFirmResetParam() = (u8)MCU_GetFreeRegister( OS_MCU_RESET_VALUE_OFS );
440 OSi_GetNandFirmResetParam()->isValid = 1;
441 }
442
443 // Hot/cold boot determination
444 // If "HOTBT flag of a microcomputer free register = 0," cold boot
445 if( !OSi_GetNandFirmResetParam()->isHotStart ) {
446 *isHotstart = FALSE;
447 }else {
448 *isHotstart = TRUE;
449 // Determine launcher parameter validity
450 if( OSi_IsValidLauncherParam() &&
451 !OSi_GetNandFirmResetParam()->isResetSW
452 ) {
453 // If launcher parameter is valid, copy to buf
454 MI_CpuCopy32 ( OSi_GetLauncherParam(), buf, sizeof(LauncherParam) );
455 return TRUE;
456 }else {
457 // Else, clear the transfer destination buffer
458 MI_CpuClear32 ( buf, sizeof(LauncherParam) );
459 }
460 }
461 return FALSE;
462 }
463
464 #endif // SDK_ARM9
465