1 /*---------------------------------------------------------------------------*
2 
3   Copyright 2010-2012 Nintendo.  All rights reserved.
4 
5   These coded instructions, statements, and computer programs contain
6   proprietary information of Nintendo of America Inc. and/or Nintendo
7   Company Ltd., and are protected by Federal copyright law.  They may
8   not be disclosed to third parties or copied or duplicated in any form,
9   in whole or in part, without the prior written consent of Nintendo.
10 
11  *---------------------------------------------------------------------------*/
12 using System;
13 using System.Text;
14 using System.Collections;
15 using System.Collections.Generic;
16 using System.Diagnostics;
17 using System.IO;
18 using System.Threading;
19 using System.Runtime.InteropServices;
20 using System.Text.RegularExpressions;
21 using System.Reflection;
22 using System.ComponentModel;
23 
24 
25 namespace CafeX
26 {
27     partial class Program
28     {
29         #region environment variables
30 
31         internal static EnvVar CAFE_ROOT = new EnvVar("CAFE_ROOT");
32         internal static EnvVar SDIO_BRIDGE_TOOLS = new EnvVar("SDIO_BRIDGE_TOOLS");
33         internal static EnvVar MION_BRIDGE_TOOLS = new EnvVar("MION_BRIDGE_TOOLS");
34         internal static EnvVar BRIDGE_CURRENT_NAME = new EnvVar("BRIDGE_CURRENT_NAME");
35         internal static EnvVar BRIDGE_CURRENT_IP_ADDRESS = new EnvVar("BRIDGE_CURRENT_IP_ADDRESS");
36 
37         internal static EnvVar PLATFORM = new EnvVar("PLATFORM");
38         internal static EnvVar CAFESTOP_STATUS = new EnvVar("CAFESTOP_STATUS");
39         internal static EnvVar CAFERUN_OPTION_SOFT_LAUNCH = new EnvVar("CAFERUN_OPTION_SOFT_LAUNCH");
40         internal static EnvVar CAFERUN_OPTION_FAST_RELAUNCH = new EnvVar("CAFERUN_OPTION_FAST_RELAUNCH");
41         internal static EnvVar HOSTSTOP_RVAL = new EnvVar("HOSTSTOP_RVAL");
42         internal static EnvVar HOSTSTOP_RETRIES = new EnvVar("HOSTSTOP_RETRIES");
43         internal static EnvVar HOSTSTOP_RESET_OPTION = new EnvVar("HOSTSTOP_RESET_OPTION");
44         internal static EnvVar CAFE_HARDWARE = new EnvVar("CAFE_HARDWARE");
45         internal static EnvVar MION_PWR_SEQ = new EnvVar("MION_PWR_SEQ");
46         internal static EnvVar BRIDGE_TYPE = new EnvVar("BRIDGE_TYPE");
47         internal static EnvVar TMP = new EnvVar("TMP");
48 
49         internal static EnvVar SESSION_MANAGER = new EnvVar("SESSION_MANAGER");
50         internal static EnvVar SESSION_NAME = new EnvVar("SESSION_NAME");
51         internal static EnvVar SESSION_DEBUG_OUT_PORT = new EnvVar("SESSION_DEBUG_OUT_PORT");
52         internal static EnvVar SESSION_DEBUG_CONTROL_PORT = new EnvVar("SESSION_DEBUG_CONTROL_PORT");
53         internal static EnvVar SESSION_HIO_OUT_PORT = new EnvVar("SESSION_HIO_OUT_PORT");
54         internal static EnvVar SESSION_LAUNCH_CTRL_PORT = new EnvVar("SESSION_LAUNCH_CTRL_PORT");
55         internal static EnvVar SESSION_NET_MANAGE_PORT = new EnvVar("SESSION_NET_MANAGE_PORT");
56         internal static EnvVar SESSION_PCFS_SATA_PORT = new EnvVar("SESSION_PCFS_SATA_PORT");
57         internal static EnvVar SESSION_PATH_PREFIX = new EnvVar("SESSION_PATH_PREFIX");
58 
59         internal static EnvVar CAFE_DATA_DIR = new EnvVar("CAFE_DATA_DIR");
60         internal static EnvVar CAFE_CONTENT_DIR = new EnvVar("CAFE_CONTENT_DIR");
61         internal static EnvVar CAFE_META_DIR = new EnvVar("CAFE_META_DIR");
62         internal static EnvVar CAFE_SAVE_DIR = new EnvVar("CAFE_SAVE_DIR");
63         internal static EnvVar CAFE_SLC_DIR = new EnvVar("CAFE_SLC_DIR");
64         internal static EnvVar CAFE_MLC_DIR = new EnvVar("CAFE_MLC_DIR");
65         internal static EnvVar CAFE_DATA_TMP = new EnvVar("CAFE_DATA_TMP");
66 
67         internal static EnvVar LANG = new EnvVar("LANG");
68         internal static EnvVar QUIET = new EnvVar("QUIET");
69         internal static EnvVar NO_CONSOLE = new EnvVar("NO_CONSOLE");
70         internal static EnvVar CAFESTOP_ONLY_IF_FSEMUL = new EnvVar("CAFESTOP_ONLY_IF_FSEMUL");
71         internal static EnvVar PPC_OS_FLAGS = new EnvVar("PPC_OS_FLAGS");
72         internal static EnvVar PPC_APP_FLAGS = new EnvVar("PPC_APP_FLAGS");
73         internal static EnvVar PCFS_SYNC_DATE = new EnvVar("PCFS_SYNC_DATE");
74         internal static EnvVar MCP_LAUNCH_HINT = new EnvVar("MCP_LAUNCH_HINT");
75         internal static EnvVar MCP_INFO_OPTION = new EnvVar("MCP_INFO_OPTION");
76         internal static EnvVar IGNORE_VERSION = new EnvVar("IGNORE_VERSION");
77         internal static EnvVar DEBUGGER = new EnvVar("DEBUGGER");
78         internal static EnvVar CAFE_CONSOLE = new EnvVar("CAFE_CONSOLE");
79         internal static EnvVar CONSOLE = new EnvVar("CONSOLE");
80         internal static EnvVar CAFE_DEBUG_PORT = new EnvVar("CAFE_DEBUG_PORT");
81         internal static EnvVar DEBUG_ELF_FILE = new EnvVar("DEBUG_ELF_FILE");
82         internal static EnvVar CAFERUN_OPTION_SOFT_RESTART = new EnvVar("CAFERUN_OPTION_SOFT_RESTART");
83         internal static EnvVar CAFE_TEST_SELF_REFRESH = new EnvVar("CAFE_TEST_SELF_REFRESH");
84         internal static EnvVar CAFERUN_OPTION_MLC_EMU_LAUNCH = new EnvVar("CAFERUN_OPTION_MLC_EMU_LAUNCH");
85         internal static EnvVar CAFERUN_OPTION_MLC_EMU_TITLEID = new EnvVar("CAFERUN_OPTION_MLC_EMU_TITLEID");
86         internal static EnvVar CAFERUN_OS_MAJOR_VERSION_LO = new EnvVar("CAFERUN_OS_MAJOR_VERSION_LO");
87         internal static EnvVar CAFERUN_OS_MAJOR_VERSION = new EnvVar("CAFERUN_OS_MAJOR_VERSION");
88         internal static EnvVar CAFERUN_COLDBOOT_OS_VERSION = new EnvVar("CAFERUN_COLDBOOT_OS_VERSION");
89         internal static EnvVar HEARTBEAT_DISABLE = new EnvVar("HEARTBEAT_DISABLE");
90         internal static EnvVar PCFS_DIR_MAPPING = new EnvVar("PCFS_DIR_MAPPING");
91         internal static EnvVar MAPDIR_MLC = new EnvVar("MAPDIR_MLC");
92         internal static EnvVar MAPDIR_SLC = new EnvVar("MAPDIR_SLC");
93         internal static EnvVar MAPDIR_CODE = new EnvVar("MAPDIR_CODE");
94         internal static EnvVar MAPDIR_META = new EnvVar("MAPDIR_META");
95         internal static EnvVar MAPDIR_CONTENT = new EnvVar("MAPDIR_CONTENT");
96         internal static EnvVar MAPDIR_SAVE = new EnvVar("MAPDIR_SAVE");
97         internal static EnvVar PCFS_LOG_TIMESTAMP = new EnvVar("PCFS_LOG_TIMESTAMP");
98         internal static EnvVar PCFS_SRV_LOG_OUTPUT = new EnvVar("PCFS_SRV_LOG_OUTPUT");
99         internal static EnvVar RUN_FROM_HDD_BANK = new EnvVar("RUN_FROM_HDD_BANK");
100         internal static EnvVar EJECT_STATE = new EnvVar("EJECT_STATE");
101         internal static EnvVar BRIDGE_PARAMETERS = new EnvVar("BRIDGE_PARAMETERS");
102         internal static EnvVar BRIDGE_PARAMETERS_WITH_E = new EnvVar("BRIDGE_PARAMETERS_WITH_E");
103         internal static EnvVar PCFSSERVER_PARAMETERS = new EnvVar("PCFSSERVER_PARAMETERS");
104         internal static EnvVar PCFS_OVER_SATA_PORT = new EnvVar("PCFS_OVER_SATA_PORT");
105         internal static EnvVar PREPHDD_STAT = new EnvVar("PREPHDD_STAT");
106         internal static EnvVar DISC_EMU_TID = new EnvVar("DISC_EMU_TID");
107         internal static EnvVar SYSTEM_MODE = new EnvVar("SYSTEM_MODE");
108         internal static EnvVar RPL_DIRS = new EnvVar("RPL_DIRS");
109         internal static EnvVar RPL_FILES = new EnvVar("RPL_FILES");
110         internal static EnvVar CAFERUN_OPTION_NO_DATA_SYNC = new EnvVar("CAFERUN_OPTION_NO_DATA_SYNC");
111         internal static EnvVar CAFE_BOOT_MODE = new EnvVar("CAFE_BOOT_MODE");
112         internal static EnvVar CAFERUN_HOSTBRIDGE_VERSION = new EnvVar("CAFERUN_HOSTBRIDGE_VERSION");
113         internal static EnvVar CAFERUN_FW_VERSION = new EnvVar("CAFERUN_FW_VERSION");
114         internal static EnvVar CAFE_DEBUG_INIT = new EnvVar("CAFE_DEBUG_INIT");
115         internal static EnvVar CAFE_DEBUG_PREINIT = new EnvVar("CAFE_DEBUG_PREINIT");
116         internal static EnvVar CAFE_DEBUG_DONTSTOP = new EnvVar("CAFE_DEBUG_DONTSTOP");
117         internal static EnvVar CAFE_LAUNCH_DEBUG = new EnvVar("CAFE_LAUNCH_DEBUG");
118         internal static EnvVar CAFE_SYSLOG_LEVEL = new EnvVar("CAFE_SYSLOG_LEVEL");
119         internal static EnvVar CAFE_RUN_FORCERESTART = new EnvVar("CAFE_RUN_FORCERESTART");
120         internal static EnvVar DEBUG_PROC_ID = new EnvVar("DEBUG_PROC_ID");
121         internal static EnvVar DEBUG_FLAGS = new EnvVar("DEBUG_FLAGS");
122         internal static EnvVar CATOUTPUT = new EnvVar("CATOUTPUT");
123         internal static EnvVar CMDOUTPUT = new EnvVar("CMDOUTPUT");
124         internal static EnvVar CAFE_AUTOTEST = new EnvVar("CAFE_AUTOTEST");
125         internal static EnvVar YOSHIS_COOKIE = new EnvVar("YOSHIS_COOKIE");
126         internal static EnvVar CAFERUN_APP_TYPE = new EnvVar("CAFERUN_APP_TYPE");
127 
128         internal static EnvVar DASH_A_ARGS = new EnvVar("DASH_A_ARGS");
129         internal static EnvVar ARGS_WITH_BARS = new EnvVar("ARGS_WITH_BARS");
130         internal static EnvVar DISC_EMU_TYPE = new EnvVar("DISC_EMU_TYPE");
131         internal static EnvVar APP_XML_FILE = new EnvVar("APP_XML_FILE");
132 
133         internal static EnvVar USE_PCFS_OVER_SATA = new EnvVar("USE_PCFS_OVER_SATA");
134         internal static EnvVar CAFERUN_OPTION_CALLED_FROM_CAFEDISCRUN = new EnvVar("CAFERUN_OPTION_CALLED_FROM_CAFEDISCRUN");
135         internal static EnvVar SYSTEM_XML = new EnvVar("SYSTEM_XML");
136         //internal static EnvVar TEMP = new EnvVar("TEMP");
137         internal static EnvVar CAFE_TEMP = new EnvVar("CAFE_TEMP");
138         internal static EnvVar CAFERUN_WORK_DIR = new EnvVar("CAFERUN_WORK_DIR");
139 
140         internal static EnvVar SYNCTOOL_SRC = new EnvVar("SYNCTOOL_SRC");
141         internal static EnvVar SYNCTOOL_DEST = new EnvVar("SYNCTOOL_DEST");
142         internal static EnvVar SYNCTOOL_CFG = new EnvVar("SYNCTOOL_CFG");
143         internal static EnvVar SYNCTOOL_LOG = new EnvVar("SYNCTOOL_LOG");
144 
145         internal static EnvVar CAFE_ELF = new EnvVar("CAFE_ELF");
146         internal static EnvVar CAFE_ELF_SRC_DIR = new EnvVar("CAFE_ELF_SRC_DIR");
147         internal static EnvVar CAFE_ELF_DIR = new EnvVar("CAFE_ELF_DIR");
148         internal static EnvVar CAFE_CODE_DIR = new EnvVar("CAFE_CODE_DIR");
149         internal static EnvVar COS_XML_FILE = new EnvVar("COS_XML_FILE");
150         internal static EnvVar META_XML_FILE = new EnvVar("META_XML_FILE");
151 
152         internal static EnvVar PREV_CAFE_ARGSTR = new EnvVar("PREV_CAFE_ARGSTR");
153         internal static EnvVar CAFERUN_OS_VERSION_PARTIAL_UNIQUE_ID = new EnvVar("CAFERUN_OS_VERSION_PARTIAL_UNIQUE_ID");
154         internal static EnvVar PCFS_SRV_LOG_DIR = new EnvVar("PCFS_SRV_LOG_DIR");
155         internal static EnvVar CMD_RESULT = new EnvVar("CMD_RESULT");
156 
157         internal static EnvVar CAFERUN_COLDBOOT_OS_VERSION_HI = new EnvVar("CAFERUN_COLDBOOT_OS_VERSION_HI");
158         internal static EnvVar CAFERUN_COLDBOOT_OS_VERSION_LO = new EnvVar("CAFERUN_COLDBOOT_OS_VERSION_LO");
159         internal static EnvVar BOOTRUN_WORK_DIR = new EnvVar("BOOTRUN_WORK_DIR");
160         internal static EnvVar BOOTRUN_USE_RECOVERY_IMAGE = new EnvVar("BOOTRUN_USE_RECOVERY_IMAGE");
161         internal static EnvVar WUMAD_WORK_DIR = new EnvVar("WUMAD_WORK_DIR");
162         internal static EnvVar FIRMWARE_FILE = new EnvVar("FIRMWARE_FILE");
163         internal static EnvVar TOOLCHAIN = new EnvVar("TOOLCHAIN");
164         internal static EnvVar CAFE_SECURITY = new EnvVar("CAFE_SECURITY");
165         internal static EnvVar BOOT_DLF_FILE = new EnvVar("BOOT_DLF_FILE");
166         internal static EnvVar CAFE_WUMAD = new EnvVar("CAFE_WUMAD");
167 
168         internal static EnvVar CAFEMAKEDLF = new EnvVar("CAFEMAKEDLF");
169         internal static EnvVar APP_TITLE_ID = new EnvVar("APP_TITLE_ID");
170         internal static EnvVar APP_GROUP_ID = new EnvVar("APP_GROUP_ID");
171         internal static EnvVar APP_TITLE_VERSION = new EnvVar("APP_TITLE_VERSION");
172         internal static EnvVar CAFEDEVRUN_FILE = new EnvVar("CAFEDEVRUN_FILE");
173         internal static EnvVar CAFEDEVRUN_EXT = new EnvVar("CAFEDEVRUN_EXT");
174         internal static EnvVar CAFEDEVRUN_NAME = new EnvVar("CAFEDEVRUN_NAME");
175         internal static EnvVar CAFEDEVRUN_FILENAME = new EnvVar("CAFEDEVRUN_FILENAME");
176         internal static EnvVar CAFEDEVRUN_DIR = new EnvVar("CAFEDEVRUN_DIR");
177         internal static EnvVar CAFEDEVRUN_WORK_DIR = new EnvVar("CAFEDEVRUN_WORK_DIR");
178         internal static EnvVar INCLUDE_SYSTEM_DIR = new EnvVar("INCLUDE_SYSTEM_DIR");
179         internal static EnvVar CAFE_BASEFILE_PATH = new EnvVar("CAFE_BASEFILE_PATH");
180         internal static EnvVar DEFAULT_DDF = new EnvVar("DEFAULT_DDF");
181         internal static EnvVar COMMON_DDF_FILE = new EnvVar("COMMON_DDF_FILE");
182         internal static EnvVar INDIVIDUAL_DDF_FILE = new EnvVar("INDIVIDUAL_DDF_FILE");
183 
184         internal static EnvVar FSEMUL_PARAMS = new EnvVar("FSEMUL_PARAMS");
185         internal static EnvVar BRIDGE_INSTALL_PATH = new EnvVar("BRIDGE_INSTALL_PATH");
186         internal static EnvVar CAFE_DETACH_FSEMUL = new EnvVar("CAFE_DETACH_FSEMUL");
187 
188         internal static EnvVar MULTIELF = new EnvVar("MULTIELF");
189         internal static EnvVar CATTOUCAN_STATUS = new EnvVar("CATTOUCAN_STATUS");
190         internal static EnvVar MULTI_CONNECT = new EnvVar("MULTI_CONNECT");
191         internal static EnvVar CAFE_MULTI_INIT = new EnvVar("CAFE_MULTI_INIT");
192         internal static EnvVar GHS_ROOT = new EnvVar("GHS_ROOT");
193 
194         internal static EnvVar CAFEON_DISABLE_BGD = new EnvVar("CAFEON_DISABLE_BGD");
195         internal static EnvVar CAFEON_NOBGD_META = new EnvVar("CAFEON_NOBGD_META");
196         internal static EnvVar CAFEON_OPTION_NO_DATA_SYNC = new EnvVar("CAFEON_OPTION_NO_DATA_SYNC");
197         internal static EnvVar AUTOTEST_RUNNING = new EnvVar("AUTOTEST_RUNNING");
198         internal static EnvVar CAFE_RUN_RUNNING = new EnvVar("CAFE_RUN_RUNNING");
199         internal static EnvVar CAFERUN_INS = new EnvVar("CAFERUN_INS");
200         internal static EnvVar CATTOUCAN_TERM = new EnvVar("CATTOUCAN_TERM");
201         internal static EnvVar OS_VERSION_LO = new EnvVar("OS_VERSION_LO");
202 
203         internal static EnvVar SDK_VER = new EnvVar("SDK_VER");
204         internal static EnvVar SDK_MAJ_VER = new EnvVar("SDK_MAJ_VER");
205         internal static EnvVar SDK_MIN_VER = new EnvVar("SDK_MIN_VER");
206         internal static EnvVar SDK_MIC_VER = new EnvVar("SDK_MIC_VER");
207 
208         internal static EnvVar CAFEUPDATE_USE_SYSTEM_UPDATER = new EnvVar("CAFEUPDATE_USE_SYSTEM_UPDATER");
209         internal static EnvVar CAFEUPDATE_TITLE = new EnvVar("CAFEUPDATE_TITLE");
210         internal static EnvVar CAFEUPDATE_PACKAGE = new EnvVar("CAFEUPDATE_PACKAGE");
211         internal static EnvVar CAFEUPDATE_PACKAGE_DEFAULT = new EnvVar("CAFEUPDATE_PACKAGE_DEFAULT");
212 
213         internal static EnvVar SCRIPT_EXE_TIMESTAMP = new EnvVar("SCRIPT_EXE_TIMESTAMP");
214         internal static EnvVar LOGDIR = new EnvVar("LOGDIR");
215         internal static EnvVar _CCRSYSCFG1 = new EnvVar("_CCRSYSCFG1");
216         internal static EnvVar MONITOR_DEFAULT_TIMEOUT = new EnvVar("MONITOR_DEFAULT_TIMEOUT");
217         internal static EnvVar COMPORTS_SUPPORT = new EnvVar("COMPORTS_SUPPORT");
218         internal static EnvVar INITIALIZED_COMPORTS = new EnvVar("INITIALIZED_COMPORTS");
219         internal static EnvVar MONITOR_FOR_OUTPUT_CALLS = new EnvVar("MONITOR_FOR_OUTPUT_CALLS");
220 
221         internal static EnvVar MON_RESULT_PASS = new EnvVar("MON_RESULT_PASS");
222         internal static EnvVar MON_RESULT_TIMEOUT = new EnvVar("MON_RESULT_TIMEOUT");
223         internal static EnvVar MON_RESULT_UNDEF = new EnvVar("MON_RESULT_UNDEF");
224         internal static EnvVar MON_RESULT_MANUAL = new EnvVar("MON_RESULT_MANUAL");
225         internal static EnvVar MON_RESULT_NOLOG = new EnvVar("MON_RESULT_NOLOG");
226         internal static EnvVar MON_RESULT_FAIL = new EnvVar("MON_RESULT_FAIL");
227         internal static EnvVar MON_RESULT_EXPECTED_TERM = new EnvVar("MON_RESULT_EXPECTED_TERM");
228         internal static EnvVar MON_RESULT_EXEC_WIN_APP = new EnvVar("MON_RESULT_EXEC_WIN_APP");
229         internal static EnvVar MON_RESULT_NOPPC = new EnvVar("MON_RESULT_NOPPC");
230         internal static EnvVar MON_RESULT_BOOT1 = new EnvVar("MON_RESULT_BOOT1");
231         internal static EnvVar MON_RESULT_RESTART = new EnvVar("MON_RESULT_RESTART");
232         internal static EnvVar MON_RESULT_TEST_AS_RPL = new EnvVar("MON_RESULT_TEST_AS_RPL");
233         internal static EnvVar MON_RESULT_END_OF_RPL_LOADER = new EnvVar("MON_RESULT_END_OF_RPL_LOADER");
234         internal static EnvVar MON_RESULT_BRIDGE_COLLISION = new EnvVar("MON_RESULT_BRIDGE_COLLISION");
235         internal static EnvVar MON_RESULT_TEST_DBG_OUT = new EnvVar("MON_RESULT_TEST_DBG_OUT");
236         internal static EnvVar MON_RESULT_BRIDGE_OFF = new EnvVar("MON_RESULT_BRIDGE_OFF");
237         internal static EnvVar MON_RESULT_ERROR = new EnvVar("MON_RESULT_ERROR");
238         internal static EnvVar MON_RESULT_SKIP = new EnvVar("MON_RESULT_SKIP");
239         internal static EnvVar MON_RESULT_FATAL_ERROR = new EnvVar("MON_RESULT_FATA_ERROR");
240         internal static EnvVar MON_RESULT_MISSING = new EnvVar("MON_RESULT_MISSING");
241         internal static EnvVar MON_RESULT_ABORTED = new EnvVar("MON_RESULT_ABORTED");
242         internal static EnvVar MON_RESULT_KILL_AUTOTEST = new EnvVar("MON_RESULT_KILL_AUTOTEST");
243         internal static EnvVar SYNCTOOL_RVAL = new EnvVar("SYNCTOOL_RVAL");
244 
245         internal static EnvVar PATH = new EnvVar("PATH");
246 
247         internal static EnvVar PCFS_HEADLESS_EMUL = new EnvVar("PCFS_HEADLESS_EMUL");
248         internal static EnvVar TMP_SUB_DIR = new EnvVar("TMP_SUB_DIR");
249         internal static EnvVar PCFSSERVERSYNC_RVAL = new EnvVar("PCFSSERVERSYNC_RVAL");
250 
251         internal static EnvVar CAFE_RUN_DEBUG = new EnvVar("CAFE_RUN_DEBUG");
252 
253         internal static EnvVar CYGWIN_PATH = new EnvVar("CYGWIN_PATH");
254 
255         internal static EnvVar CAFEX_STDIN_ENCODING = new EnvVar("CAFEX_STDIN_ENCODING");
256         internal static EnvVar CAFEX_STDOUT_ENCODING = new EnvVar("CAFEX_STDOUT_ENCODING");
257         internal static EnvVar CAFE_OUTPUT_ENCODING = new EnvVar("CAFE_OUTPUT_ENCODING");
258 
259         //disrun in NAND mode
260         internal static EnvVar ALLOW_DISCRUN_IN_SOFTLAUNCH = new EnvVar("ALLOW_DISCRUN_IN_SOFTLAUNCH");
261         internal static EnvVar BOOTRUN_ELF_OPT = new EnvVar("BOOTRUN_ELF_OPT");
262         internal static EnvVar BOOTRUN_ELF_VALUE = new EnvVar("BOOTRUN_ELF_VALUE");
263         internal static EnvVar ELF_NEST_OPT = new EnvVar("ELF_NEST_OPT");
264         internal static EnvVar ELF_NEST_VALUE = new EnvVar("ELF_NEST_VALUE");
265         internal static EnvVar SOFT_LAUNCH_CAFE_ELF = new EnvVar("SOFT_LAUNCH_CAFE_ELF");
266         internal static EnvVar CAFERUN_WUMAD_TITLE_ID = new EnvVar("CAFERUN_WUMAD_TITLE_ID");
267 
268         // Discrun OS mismatch checking
269         internal static EnvVar SKIP_OS_CHECK = new EnvVar("SKIP_OS_CHECK");
270 
271         // EXI debug
272         internal static EnvVar USE_EXI_AS_DEBUG_CHANNEL = new EnvVar("USE_EXI_AS_DEBUG_CHANNEL");
273 
274         // Fast launch
275         internal static EnvVar CAFERUN_OPTION_FASTLAUNCH_RETRIES = new EnvVar("CAFERUN_OPTION_FASTLAUNCH_RETRIES");
276         internal static EnvVar CAFERUN_OPTION_FASTLAUNCH_TIMEOUT = new EnvVar("CAFERUN_OPTION_FASTLAUNCH_TIMEOUT");
277         internal static EnvVar CAFERUN_OPTION_FASTLAUNCH_DELAY   = new EnvVar("CAFERUN_OPTION_FASTLAUNCH_DELAY");
278 
279         // KILL RESTART
280         internal static EnvVar CAFERUN_DISABLE_KILL_RESTART = new EnvVar("CAFERUN_DISABLE_KILL_RESTART");
281         internal static EnvVar CAFERUN_OPTION_KILL_RESTART = new EnvVar("CAFERUN_OPTION_KILL_RESTART");
282         internal static int g_gArgValue = 0;
283         internal static bool g_KOptionSet = false;
284 
285         //Cafe profiler
286         internal static EnvVar CAFE_PROFILE = new EnvVar("CAFE_PROFILE");
287         internal static EnvVar USE_SINGLE_CGI = new EnvVar("USE_SINGLE_CGI");
288 
289         // Mion version checking
290         internal static string MIN_MION_FW_VER = "0.0.14.74";
291         internal static string MIN_MION_SW_VER = "3.2.6.1";
292 
293         //For launch command
294         internal static string LAUNCH_DLF_FILE = string.Empty;
295         internal static bool execLaunchCmd = false;
296 
297         //For ECO mode debugging
298         internal static EnvVar ECO_MODE = new EnvVar("ECO_MODE");
299 
300 		//For update/recover testing
301         internal static EnvVar CAFEX_RECOVER_TEST = new EnvVar("CAFEX_RECOVER_TEST");
302         internal static UInt64 recover_flags = 0x230;
303 
304         //For default caferun / cafediscrun options
305         internal static EnvVar CAFERUN_DEFAULT_OPTIONS = new EnvVar("CAFERUN_DEFAULT_OPTIONS");
306 
307         //For MIONPS arguments
308         internal const int MIONPS_BOOT_BYTE = 2;
309         internal const int MIONPS_SDK_MAJ_BYTE = 3;
310         internal const int MIONPS_SDK_MIN_BYTE = 4;
311         internal const int MIONPS_SDK_MIC_BYTE = 5;
312 
313         internal const int MIONPS_BOOT_NAND = 1;
314         internal const int MIONPS_BOOT_PCFS = 2;
315         internal const int MIONPS_IMGUPLOAD_BASE_BYTE = 100;
316 
317         #endregion
318 
319         #region GLOBAL INTIALIZATION
320         internal static bool IsBooting = false;
321 
322         internal const int CAFERUN_RETRY_COUNT = 5;
323         internal const int CAFERUN_LAST_RETRY = (CAFERUN_RETRY_COUNT - 1);
324 
325         internal static char DEFAULT_DELIMITER = '\t';
326         internal static string SYSCONFIGTOOL_TITLE_ID = "000500101f700500";
327 
328         internal static bool fAppTypeDefined = false;
329         const int CAFE_ARGSTR_MAX_LENGTH = 4096;
330 
331         const string IOS_CRASHDUMP_TOKEN = "IOS_CRASH_START_PROCESS:";
332 
InitialEnvVarSetup()333         internal static CAFEX_ERROR InitialEnvVarSetup()
334         {
335             #if DEBUG
336                 Log.WriteLine("InitialEnvVarSetup started.");
337             #endif
338 
339             #region encoding setup
340 
341             //check to see if we are in a cygwin window.
342 //            if (CAFE_ROOT.value.Contains("cygdrive") || !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("CYGWIN")))
343 //                CALLED_FROM_CYGWIN = true;
344 
345             //determine the encoding that Cafe is outputting
346             if (!String.IsNullOrEmpty(LANG.value))
347             {
348                 //cygwin uses the format (language)_(territory).(charset)[@modifier]
349                 //and we're only interested in the charset
350                 int langLoc = LANG.value.IndexOf(".", 0);
351                 string lang = null;
352 
353                 if (langLoc > -1)
354                 {
355                     //handle case where LANG may have @ in it (legal in cygwin)
356                     int atSignLoc = LANG.value.IndexOf("@", 0);
357 
358                     if (langLoc > atSignLoc)
359                         lang = LANG.value.Substring(langLoc + 1);
360                     else
361                         lang = LANG.value.Substring(langLoc + 1, atSignLoc - langLoc);
362 
363                     switch (lang)
364                     {
365                         case "UTF-8":
366                         case "utf8":
367                             lang = "utf-8";
368                             break;
369                         case "SJIS":
370                         case "CP932":
371                             lang = "shift_jis";
372                             break;
373                         case "ASCII":
374                             lang = "us-ascii";
375                             break;
376                         case "CP1252":
377                             lang = "windows-1252";
378                             break;
379                         case "CP437":
380                             lang = "IBM437";
381                             break;
382                         case "CP720":
383                             lang = "DOS-270";
384                             break;
385                         case "CP737":
386                             lang = "ibm737";
387                             break;
388                         case "CP775":
389                             lang = "ibm775";
390                             break;
391                         case "CP850":
392                             lang = "ibm850";
393                             break;
394                         case "CP852":
395                             lang = "ibm852";
396                             break;
397                         case "CP855":
398                             lang = "IBM855";
399                             break;
400                         case "CP857":
401                             lang = "ibm857";
402                             break;
403                         case "CP858":
404                             lang = "IBM00858";
405                             break;
406                         case "CP860":
407                             lang = "IBM860";
408                             break;
409                         case "CP861":
410                             lang = "ibm861";
411                             break;
412                         case "CP862":
413                             lang = "DOS-862";
414                             break;
415                         case "CP863":
416                             lang = "IBM863";
417                             break;
418                         case "CP864":
419                             lang = "IBM864";
420                             break;
421                         case "CP865":
422                             lang = "IBM865";
423                             break;
424                         case "CP866":
425                             lang = "cp866";
426                             break;
427                         case "CP869":
428                             lang = "ibm869";
429                             break;
430                         case "CP870":
431                             lang = "IBM870";
432                             break;
433                         case "CP874":
434                         case "TIS-620":
435                         case "TIS620":
436                             lang = "windows-874";
437                             break;
438                         case "CP1250":
439                             lang = "windows-1250";
440                             break;
441                         case "CP1251":
442                             lang = "windows-1251";
443                             break;
444                         case "CP1253":
445                             lang = "windows-1253";
446                             break;
447                         case "CP1254":
448                             lang = "windows-1254";
449                             break;
450                         case "CP1255":
451                             lang = "windows-1255";
452                             break;
453                         case "CP1256":
454                             lang = "windows-1256";
455                             break;
456                         case "CP1257":
457                             lang = "windows-1257";
458                             break;
459                         case "CP1258":
460                             lang = "windows-1258";
461                             break;
462                         case "ISO-8859-1":
463                             lang = "iso-8859-1";
464                             break;
465                         case "ISO-8859-2":
466                             lang = "iso-8859-2";
467                             break;
468                         case "ISO-8859-3":
469                             lang = "iso-8859-3";
470                             break;
471                         case "ISO-8859-4":
472                             lang = "iso-8859-4";
473                             break;
474                         case "ISO-8859-5":
475                             lang = "iso-8859-5";
476                             break;
477                         case "ISO-8859-6":
478                             lang = "iso-8859-6";
479                             break;
480                         case "ISO-8859-7":
481                             lang = "iso-8859-7";
482                             break;
483                         case "ISO-8859-8":
484                             lang = "iso-8859-8";
485                             break;
486                         case "ISO-8859-9":
487                             lang = "iso-8859-9";
488                             break;
489                         case "ISO-8859-10":
490                             lang = "iso-8859-10";
491                             break;
492                         case "ISO-8859-11":
493                             lang = "iso-8859-11";
494                             break;
495                         case "ISO-8859-13":
496                             lang = "iso-8859-13";
497                             break;
498                         case "ISO-8859-14":
499                             lang = "iso-8859-14";
500                             break;
501                         case "ISO-8859-15":
502                             lang = "iso-8859-15";
503                             break;
504                         case "ISO-8859-16":
505                             lang = "iso-8859-16";
506                             break;
507                         case "Big5":
508                             lang = "big5";
509                             break;
510                         case "EUCCN":
511                         case "euc-CN":
512                         case "GB2312":
513                         case "GBK":
514                             lang = "gb2312";
515                             break;
516                         case "EUCJP":
517                         case "euc-JP":
518                             lang = "EUC-JP";
519                             break;
520                         case "EUCKR":
521                         case "euc-KR":
522                             lang = "ks_c_5601-1987";
523                             break;
524                         case "KOI8-R":
525                             lang = "koi8-r";
526                             break;
527                         case "KOI8-U":
528                             lang = "koi8-u";
529                             break;
530                         default:
531                             Console.WriteLine("cafex: Unknown LANG specified; using UTF-8 encoding for incoming Cafe messages");
532                             lang = null;
533                             break;
534                     }
535                 }
536                 else
537                 {
538                     Console.WriteLine("cafex: Invalid LANG specified; using UTF-8 encoding for incoming Cafe messages");
539                 }
540                 CAFE_OUTPUT_ENCODING.value = lang;
541             }
542 
543 
544             #endregion
545 
546             // THESE NEED TO BE SET IN CAFEX_ENV.BAT, BUT FOR NOW ARE HERE
547             CAFE_ROOT.value = PathConverter.Windowsify(CAFE_ROOT.value);
548             if (string.IsNullOrEmpty(CAFE_TEMP.value))
549             {
550                 CAFE_TEMP.value = Path.Combine (CAFE_ROOT.value, "temp");
551             }
552             CAFE_TEMP.value = PathConverter.Windowsify(CAFE_TEMP.value);
553             GHS_ROOT.value = PathConverter.Windowsify(GHS_ROOT.value);
554             if (string.IsNullOrEmpty(CAFE_HARDWARE.value))
555             {
556                 CAFE_HARDWARE.value = "catdevmp";
557             }
558             else if (!CAFE_HARDWARE.value.Equals("catdevmp"))
559             {
560                 Console.WriteLine("User has already defined CAFE_HARDWARE to '{0}'!", CAFE_HARDWARE.value);
561                 Console.WriteLine("Please be aware that anything but 'catdevmp' is not guaranteed to work.");
562             }
563             //CAFE_BOOT_MODE.value = "PCFS";
564             //CAFE_CONTENT_DIR.value = CAFE_ROOT.value + "\\data\\disc\\content";
565             //CAFE_SAVE_DIR.value = CAFE_ROOT.value + "\\data\\save";
566             //CAFE_SLC_DIR.value = CAFE_ROOT.value + "\\data\\slc";
567             //CAFE_MLC_DIR.value = CAFE_ROOT.value + "\\data\\mlc";
568             //CAFE_META_DIR.value = CAFE_ROOT.value + "\\data\\disc\\meta";
569             CAFE_CONTENT_DIR.value = PathConverter.Windowsify(CAFE_CONTENT_DIR.value);
570             CAFE_SAVE_DIR.value = PathConverter.Windowsify(CAFE_SAVE_DIR.value);
571             CAFE_SLC_DIR.value = PathConverter.Windowsify(CAFE_SLC_DIR.value);
572             CAFE_MLC_DIR.value = PathConverter.Windowsify(CAFE_MLC_DIR.value);
573             CAFE_META_DIR.value = PathConverter.Windowsify(CAFE_META_DIR.value);
574             TOOLCHAIN.value = "ghs";
575             MONITOR_DEFAULT_TIMEOUT.value = "60";
576             // carlosk - don't override this setting from environment
577             //CAFE_CONSOLE.value = "cattoucan";
578             if (string.IsNullOrEmpty(CAFE_CONSOLE.value))
579             {
580                 CAFE_CONSOLE.value = "cattoucan";
581             }
582             // carlosk - need to remove this or it will always do pcfs over sata
583             //USE_PCFS_OVER_SATA.value = "1";
584 
585             if (string.IsNullOrEmpty(CAFE_TEST_SELF_REFRESH.value))
586             {
587                 CAFE_TEST_SELF_REFRESH.value = "0";
588             }
589 
590             MON_RESULT_UNDEF.value = "-1";
591             MON_RESULT_TIMEOUT.value = "0";
592             MON_RESULT_PASS.value = "1";
593             MON_RESULT_MANUAL.value = "2";
594             MON_RESULT_NOLOG.value = "3";
595             MON_RESULT_FAIL.value = "4";
596             MON_RESULT_EXPECTED_TERM.value = "5";
597             MON_RESULT_EXEC_WIN_APP.value = "6";
598             MON_RESULT_NOPPC.value = "7";
599             MON_RESULT_BOOT1.value = "8";
600             MON_RESULT_RESTART.value = "9";
601             MON_RESULT_TEST_AS_RPL.value = "10";
602             MON_RESULT_END_OF_RPL_LOADER.value = "11";
603             MON_RESULT_BRIDGE_COLLISION.value = "12";
604             MON_RESULT_TEST_DBG_OUT.value = "13";
605             MON_RESULT_BRIDGE_OFF.value = "14";
606             MON_RESULT_KILL_AUTOTEST.value = "15";
607             MON_RESULT_ERROR.value = "128";
608             MON_RESULT_SKIP.value = "129";
609             MON_RESULT_FATAL_ERROR.value = "255";
610             MON_RESULT_MISSING.value = "131";
611             MON_RESULT_ABORTED.value = "132";
612 
613             ALLOW_DISCRUN_IN_SOFTLAUNCH.value = "0";
614             SKIP_OS_CHECK.value = "0";
615 
616             PATH.AddToVar("C:\\cygwin\\bin\\;", ';');
617 
618             CAFEX_ERROR ret = readSDKFromCafeRoot(null);
619             if (ret != CAFEX_ERROR.OK)
620             {
621                 return ret;
622             }
623 
624             #region session setup
625 
626             if (SESSION_MANAGER.value == "1")
627             {
628                 if (!File.Exists(MION_BRIDGE_TOOLS.value + "\\SessionManager.dll"))
629                 {
630                     Console.WriteLine("ERROR: SessionManager.dll not found and multi-CATDEV is enabled!");
631                     Console.WriteLine("       Please install HostBridge version 3.2.2.3+ or disable multi-CATDEV feature.");
632                     return CAFEX_ERROR.NO_SESSIONMANAGER_DLL;
633                 }
634 
635                 string output = string.Empty;
636                 SessionManagerUtil.GetSessionInfo(out output);
637 
638                 string[] output_array = output.Split(' ');
639 
640                 SESSION_NAME.value = output_array[0];
641                 SESSION_DEBUG_OUT_PORT.value = output_array[1];
642                 SESSION_DEBUG_CONTROL_PORT.value = output_array[2];
643                 SESSION_HIO_OUT_PORT.value = output_array[3];
644                 SESSION_LAUNCH_CTRL_PORT.value = output_array[4];
645                 SESSION_NET_MANAGE_PORT.value = output_array[5];
646                 SESSION_PCFS_SATA_PORT.value = output_array[6];
647 
648                 SESSION_PATH_PREFIX.value = SESSION_NAME.value + "_";
649 
650                 CAFE_DATA_DIR.value = CAFE_ROOT.value + "\\" + SESSION_PATH_PREFIX.value + "data";
651 
652                 // If the content or meta location has been changed from the default, we should not touch and use it.
653                 // Otherwise, should modify by appending the CAFE_DATA_DIR.
654                 string defaultContentDir = Path.Combine(CAFE_ROOT.value,"data\\disc\\content");
655                 string defaultMetaDir = Path.Combine(CAFE_ROOT.value,"data\\disc\\meta");
656                 string defaultSaveDir = Path.Combine(CAFE_DATA_DIR.value, "save");
657                 string defaultSlcDir = Path.Combine(CAFE_DATA_DIR.value, "slc");
658                 string defaultMlcDir = Path.Combine(CAFE_DATA_DIR.value, "mlc");
659 
660                 // typical directories for users to change to something custom
661                 if (string.Equals(CAFE_CONTENT_DIR.value,defaultContentDir))
662                 {
663                     CAFE_CONTENT_DIR.value = Path.Combine(CAFE_DATA_DIR.value, "disc\\content");
664                 }
665                 if (string.Equals(CAFE_META_DIR.value, defaultMetaDir))
666                 {
667                     CAFE_META_DIR.value = Path.Combine(CAFE_DATA_DIR.value, "disc\\meta");
668                 }
669                 if (string.Equals(CAFE_SAVE_DIR.value, defaultSaveDir))
670                 {
671                     CAFE_SAVE_DIR.value = Path.Combine(CAFE_DATA_DIR.value, "save");
672                 }
673 
674                 // No idea why users would ever change these next two paths, but we need to support it
675                 if (string.Equals(CAFE_SLC_DIR.value, defaultSlcDir))
676                 {
677                     CAFE_SLC_DIR.value = Path.Combine(CAFE_DATA_DIR.value, "slc");
678                 }
679                 else
680                 {
681                     Console.WriteLine("WARNING: CAFE_SLC_DIR is set to a non-default path! Cafe may encounter errors!");
682                     Console.WriteLine("default:{0}", defaultSlcDir);
683                     Console.WriteLine(" actual:{0}", CAFE_SLC_DIR.value);
684                 }
685                 if (string.Equals(CAFE_MLC_DIR.value, defaultMlcDir))
686                 {
687                     CAFE_MLC_DIR.value = Path.Combine(CAFE_DATA_DIR.value, "mlc");
688                 }
689                 else
690                 {
691                     Console.WriteLine("WARNING: CAFE_MLC_DIR is set to a non-default path! Cafe may encounter errors!");
692                     Console.WriteLine("default:{0}", defaultMlcDir);
693                     Console.WriteLine(" actual:{0}", CAFE_MLC_DIR.value);
694                 }
695 
696                 CAFE_DATA_TMP.value = CAFE_DATA_DIR.value + "\\tmp";
697             }
698             else
699             {
700                 SESSION_NAME.value = "";
701                 SESSION_DEBUG_OUT_PORT.value = "6001";
702                 SESSION_DEBUG_CONTROL_PORT.value = "6002";
703                 SESSION_HIO_OUT_PORT.value = "6003";
704                 SESSION_LAUNCH_CTRL_PORT.value = "6006";
705                 SESSION_NET_MANAGE_PORT.value = "6008";
706                 SESSION_PCFS_SATA_PORT.value = "7500";
707 
708                 SESSION_PATH_PREFIX.value = "";
709                 CAFE_DATA_DIR.value = CAFE_ROOT.value + "\\data";
710             }
711 
712             #if DEBUG
713                 Log.WriteLine("SESSION_NAME               = " + SESSION_NAME.value);
714                 Log.WriteLine("SESSION_DEBUG_OUT_PORT     = " + SESSION_DEBUG_OUT_PORT.value);
715                 Log.WriteLine("SESSION_DEBUG_CONTROL_PORT = " + SESSION_DEBUG_CONTROL_PORT.value);
716                 Log.WriteLine("SESSION_HIO_OUT_PORT       = " + SESSION_HIO_OUT_PORT.value);
717                 Log.WriteLine("SESSION_LAUNCH_CTRL_PORT   = " + SESSION_LAUNCH_CTRL_PORT.value);
718                 Log.WriteLine("SESSION_NET_MANAGE_PORT    = " + SESSION_NET_MANAGE_PORT.value);
719                 Log.WriteLine("SESSION_PCFS_SATA_PORT     = " + SESSION_PCFS_SATA_PORT.value);
720                 Log.WriteLine("SESSION_PATH_PREFIX        = " + SESSION_PATH_PREFIX.value);
721                 Log.WriteLine("CAFE_DATA_DIR              = " + CAFE_DATA_DIR.value);
722                 Log.WriteLine("CAFE_CONTENT_DIR           = " + CAFE_CONTENT_DIR.value);
723                 Log.WriteLine("CAFEON_OPTION_NO_DATA_SYNC = " + CAFEON_OPTION_NO_DATA_SYNC.value);
724                 Log.WriteLine("CAFERUN_OPTION_NO_DATA_SYNC= " + CAFERUN_OPTION_NO_DATA_SYNC.value);
725             #endif
726 
727             #endregion
728 
729             return CAFEX_ERROR.OK;
730         }
731 
732         #endregion
733 
MCP_MAKE_APP_TYPE(Int64 flags, Int64 id)734         internal static Int64 MCP_MAKE_APP_TYPE(Int64 flags, Int64 id)
735         {
736             return ((flags) | ((id) & ((1<<24) - 1)));
737         }
738 
739         #region SCRIPT FUNCTIONS
740 
741         // Helper function: FindAppType()
FindAppType( Int64 iTitleID )742         static string FindAppType( Int64 iTitleID )
743         {
744             string app_type;
745 
746             // Determine the correct app_type based on the title_id
747             if ((iTitleID == 0x0005001010001000) || (iTitleID == 0x0005001010001100) ||
748                 (iTitleID == 0x0005001010001200) || (iTitleID == 0x0005001010001300) ||
749                 (iTitleID == 0x0005001010001400) || (iTitleID == 0x0005001010001500) ||
750                 (iTitleID == 0x0005001010001600) || (iTitleID == 0x0005001010001700) ||
751                 (iTitleID == 0x0005001010001800) || (iTitleID == 0x0005001010001900) ||
752                 (iTitleID == 0x0005001010001A00) || (iTitleID == 0x0005001010001B00) ||
753                 (iTitleID == 0x0005001010001C00) || (iTitleID == 0x0005001010047000) ||
754                 (iTitleID == 0x0005001010047100) || (iTitleID == 0x0005001010047200)) // MCP_APP_TYPE_SYSTEM
755             {
756                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE(((1 << 31) | (1 << 28)), 32), 16);
757             }
758             else if ((iTitleID == 0x0005001010004005) || (iTitleID == 0x0005001010004006) ||
759                 (iTitleID == 0x0005001010004007) || (iTitleID == 0x0005001010004008) ||
760                 (iTitleID == 0x00050010100040FF) || (iTitleID == 0x0005001010008005) ||
761                 (iTitleID == 0x0005001010008006) || (iTitleID == 0x0005001010008007) ||
762                 (iTitleID == 0x0005001010008008) || (iTitleID == 0x000500101000C005) ||
763                 (iTitleID == 0x000500101000C006) || (iTitleID == 0x000500101000C007) ||
764                 (iTitleID == 0x000500101000C008) || (iTitleID == 0x000500101000C009)) // MCP_APP_TYPE_OS
765             {
766                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE((1 << 28), 10), 16);
767             }
768             else if ((iTitleID == 0x0005001010000100)) // MCP_APP_TYPE_BOOT1
769             {
770                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE((1 << 28), 9), 16);
771             }
772             else if ((iTitleID == 0x0005001010000200) || (iTitleID == 0x0005001010000300)) // MCP_APP_TYPE_DRH
773             {
774                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE((1 << 28), 20), 16);
775             }
776             else if ((iTitleID == 0x0005001010000400)) // MCP_APP_TYPE_BT
777             {
778                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE((1 << 28), 18), 16);
779             }
780             else if ((iTitleID == 0x0005001010004000)) // MCP_APP_TYPE_COMPAT_SYSTEM
781             {
782                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE((1 << 28), 17), 16);
783             }
784             else if ((iTitleID == 0x0005003010010000) || (iTitleID == 0x0005003010010100) ||
785                 (iTitleID == 0x0005003010010200) || (iTitleID == 0x0005003010020000) ||
786                 (iTitleID == 0x0005003010020100) || (iTitleID == 0x0005003010020200)) // MCP_APP_TYPE_HOMEBUTTON
787             {
788                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE(((1 << 31) | (1 << 28) | (1 << 30)), 4), 16);
789             }
790             else if ((iTitleID == 0x0005003010011000) || (iTitleID == 0x0005003010011100) ||
791                 (iTitleID == 0x0005003010011200) || (iTitleID == 0x0005003010021000) ||
792                 (iTitleID == 0x0005003010021100) || (iTitleID == 0x0005003010021200)) // MCP_APP_TYPE_ERRORDISPLAY
793             {
794                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE(((1 << 31) | (1 << 28) | (1 << 30)), 5), 16);
795             }
796             else if ((iTitleID == 0x0005003010019000) || (iTitleID == 0x0005003010019100) ||
797                 (iTitleID == 0x0005003010019200) || (iTitleID == 0x0005003010029000) ||
798                 (iTitleID == 0x0005003010029100) || (iTitleID == 0x0005003010029200)) // MCP_APP_TYPE_MINIMIIVERSE
799             {
800                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE(((1 << 31) | (1 << 28) | (1 << 30)), 13), 16);
801             }
802             else if ((iTitleID == 0x0005001010040000) || (iTitleID == 0x0005001010040100) ||
803                 (iTitleID == 0x0005001010040200) || (iTitleID == 0x000500101f700500)) // MCP_APP_TYPE_CAFEMENU
804             {
805                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE(((1 << 31) | (1 << 28)), 1), 16);
806             }
807             else if ((iTitleID == 0x0005001010041000) || (iTitleID == 0x0005001010041100) ||
808                 (iTitleID == 0x0005001010041200)) // MCP_APP_TYPE_SYSTEM_VERSION
809             {
810                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE((1 << 28), 21), 16);
811             }
812             else if ((iTitleID == 0x0005001010043000) || (iTitleID == 0x0005001010043100) ||
813                 (iTitleID == 0x0005001010043200)) // MCP_APP_TYPE_DRC
814             {
815                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE((1 << 28), 19), 16);
816             }
817             else if ((iTitleID == 0x0005001010044000) || (iTitleID == 0x0005001010044100) ||
818                 (iTitleID == 0x0005001010044200)) // MCP_APP_TYPE_DRC_LANG
819             {
820                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE((1 << 28), 26), 16);
821             }
822             else if ((iTitleID == 0x0005001010045000) || (iTitleID == 0x0005001010045100) ||
823                 (iTitleID == 0x0005001010045200)) // MCP_APP_TYPE_UPDATER
824             {
825                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE(((1 << 31) | (1 << 28)), 11), 16);
826             }
827             else if ((iTitleID == 0x0005001010046000) || (iTitleID == 0x0005001010046100) ||
828                 (iTitleID == 0x0005001010046200)) // MCP_APP_TYPE_UPDATE_SYSTEM
829             {
830                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE(((1 << 29) | (1 << 28)), 8), 16);
831             }
832             else if ((iTitleID == 0x000500101004B000) || (iTitleID == 0x000500101004B100) ||
833                 (iTitleID == 0x000500101004B200)) // MCP_APP_TYPE_NETSERV
834             {
835                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE(((1 << 31) | (1 << 28) | (1 << 30)), 22), 16);
836             }
837             else if ((iTitleID == 0x0005001B10059000) || (iTitleID == 0x0005001B10059100) ||
838                 (iTitleID == 0x0005001B10059200)) // MCP_APP_TYPE_EMANUAL
839             {
840                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE(((1 << 31) | (1 << 28) | (1 << 30)), 3), 16);
841             }
842             else if ((iTitleID == 0x0005001B1005F000)) // MCP_APP_TYPE_DATA_PATCH_MAP
843             {
844                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE(((1 << 27) | (1 << 28)), 35), 16);
845             }
846             else if ((iTitleID == 0x0005001010062000) || (iTitleID == 0x0005001010062100) ||
847                 (iTitleID == 0x0005001010062200) || (iTitleID == 0x0005001B10063000)) // MCP_APP_TYPE_DATA_WAGONU
848             {
849                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE(((1 << 27) | (1 << 28)), 41), 16);
850             }
851             else // If the title ID isn't internal or we don't know the app_type of the title then it gets set as MCP_APP_TYPE_GAME
852             {
853                 app_type = Convert.ToString(MCP_MAKE_APP_TYPE((1 << 31), 0), 16);
854             };
855 
856             app_type = app_type.TrimStart('f');
857 
858             return app_type;
859         }
860 
861         // Helper function: StartProcessOnCrashdump()
StartProcessOnCrashdump(string input)862         static bool StartProcessOnCrashdump(string input)
863         {
864             if (input == null)
865             {
866                 throw new ArgumentNullException("input");
867             }
868             int pos = input.IndexOf(IOS_CRASHDUMP_TOKEN);
869             if (pos >= 0)
870             {
871 #if DEBUG
872                 Log.WriteLine(String.Format("Found crash token in '{0}'!", input));
873 #endif
874                 string line = input.Substring(pos + IOS_CRASHDUMP_TOKEN.Length).Trim();
875                 //line = Environment.ExpandEnvironmentVariables(line);
876 
877                 string shell;
878 
879                 if (FileUtil.RunningFromCygwin)
880                 {
881                     shell = "cmd.exe";
882                     line = string.Format("/c start bash -c \"{0}\"", Regex.Replace(line, "%([A-Za-z_]\\w+)%", "${$1}"));
883                 }
884                 else
885                 {
886                     shell = "cmd.exe";
887                     line = "/c start " + Regex.Replace(line, "\\${?([A-Za-z_]\\w+)}?", "%$1%");
888                 }
889 #if DEBUG
890                 Log.WriteLine(String.Format("Starting '{0} {1}'...", shell, line));
891 #endif
892                 ProcessExecutor.DoProcess_DontWait(shell, line);
893             }
894 
895             return true;    // don't exit CafeX
896         }
897 
898         //Script function: cafestop
stop(string[] args, bool checkMionVersion)899         static void stop(string[] args, bool checkMionVersion)
900         {
901             #if DEBUG
902                 Log.WriteLine("stop started.");
903                 string argString = null;
904                 if (args != null)
905                 {
906                     foreach (string arg in args)
907                     {
908                         argString += arg + " ";
909                     }
910                 }
911                 Log.WriteLine("Arguments=" + argString);
912 
913             #endif
914 
915             bool HARD_STOP = false;
916 
917             if (args != null && args.Length > 0)
918             {
919                 // Check for -h and display help
920                 if (args[0].ToLowerInvariant() == "-h")
921                 {
922                     // Display help and return;
923                     stop_usage();
924                     return;
925                 }
926                 // Check for -hostonly setting on first argument
927                 if (args[0].ToLowerInvariant() == "-hostonly")
928                 {
929                     // CafeX doesn't let you execute any function if bridge vars are not set, so there is no
930                     // reason to check them here again like in BASH.
931                     // -----------------------------------------------------------------------------------------
932                     // We want to kill any running processes, but don't want to talk to a (non-existent?) device
933                     ToucanReset.Stop();
934                     PCFSServer.Shutdown();
935                     return;
936                 }
937                 if (args[0].ToLowerInvariant() == "-hard")
938                 {
939                     // Force hard stop
940                     HARD_STOP = true;
941                 }
942             }
943 
944             PLATFORM.value = "cafe";
945 
946             if ((CAFERUN_OPTION_SOFT_LAUNCH.value == "1" || CAFERUN_OPTION_KILL_RESTART.value == "1") && !HARD_STOP)
947             {
948 #if DEBUG
949                 Log.WriteLine("(CAFERUN_OPTION_SOFT_LAUNCH.value == 1 || CAFERUN_OPTION_KILL_RESTART.value == 1) && !HARD_STOP -> Doing nothing");
950 #endif
951             	// In autotest or in caferun with CAFERUN_OPTION_SOFTLAUNCH set, cafestop is a no-op
952                 CAFESTOP_STATUS.value = "0";
953 
954                 if (USE_SINGLE_CGI.value != "1")
955                 {
956                     // Explicitly clear the hint if not set to 1
957                     USE_SINGLE_CGI.value = null;
958                 }
959                 else
960                 {
961                     Console.WriteLine("cafex {0}: Enabling single pass CGI", command);
962                 }
963             }
964             else
965             {
966 #if DEBUG
967                 Log.WriteLine("CAFERUN_OPTION_SOFT_LAUNCH.value != 1 -> calling hoststop()");
968 #endif
969 #if TIMER
970                 Log.WriteLine("Hoststop start");
971                 CafeXSetupTime.Report();
972 #endif
973                 hoststop(args, checkMionVersion);
974 #if TIMER
975                 Log.WriteLine("Hoststop end");
976                 CafeXSetupTime.Report();
977 #endif
978                 int ret = PCFSServer.Shutdown();
979                 CAFESTOP_STATUS.value = ret.ToString();
980             }
981 
982             if (CAFESTOP_STATUS.value != "0")
983             {
984                 Console.WriteLine("cafex stop error: CAFESTOP_STATUS=" + CAFESTOP_STATUS.value);
985             }
986         }
987 
stop(string[] args)988         static void stop(string[] args)
989         {
990             stop(args, false);
991         }
992 
readSDKFromCafeRoot(string sdk_root)993         static CAFEX_ERROR readSDKFromCafeRoot(string sdk_root)
994         {
995             if (string.IsNullOrEmpty(sdk_root))
996             {
997                 sdk_root = CAFE_ROOT.value;
998             }
999 
1000             string sdk_ver_file = Path.Combine(sdk_root, "system\\include\\sdk_ver.h");
1001             if (!File.Exists(sdk_ver_file))
1002             {
1003                 Console.WriteLine("cafex: Unable to find {0}, using OS header file.", sdk_ver_file);
1004                 sdk_ver_file = Path.Combine(CAFE_ROOT.value, "system\\src\\build\\make\\os_version.mk");
1005                 if (!File.Exists(sdk_ver_file))
1006                 {
1007                     Console.WriteLine("cafex: Unable to find OS header file {0}!", sdk_ver_file);
1008                     return CAFEX_ERROR.RUN_COULDNT_PARSE_SDK_VERSION_HEADER;
1009                 }
1010                 else
1011                 {
1012 #if DEBUG
1013                     Console.WriteLine("cafex: SDK version from {0}.", sdk_ver_file);
1014 #endif
1015                     FileStream fs = new FileStream(sdk_ver_file, FileMode.Open, FileAccess.Read);
1016                     StreamReader sr = new StreamReader(fs);
1017                     bool found_line = false;
1018                     while (!sr.EndOfStream)
1019                     {
1020                         string line = sr.ReadLine();
1021                         if (line.Contains("SM                    := "))
1022                             SDK_VER.value = line.Substring(25, 1);
1023                         if (line.Contains("Sm                    := "))
1024                             SDK_VER.value = SDK_VER.value + "." + line.Substring(25, 2);
1025                         if (line.Contains("Sc                    := "))
1026                         {
1027                             SDK_VER.value = SDK_VER.value + "." + line.Substring(25, 2);
1028                             found_line = true;
1029                             break;
1030                         }
1031                     }
1032                     sr.Close();
1033                     if (!found_line)
1034                     {
1035                         Console.WriteLine("cafex Error: couldn't determine SDK version!");
1036                         return CAFEX_ERROR.RUN_COULDNT_PARSE_SDK_VERSION_HEADER;
1037                     }
1038                 }
1039             }
1040             else
1041             {
1042 #if DEBUG
1043                 Console.WriteLine("cafex: SDK version from {0}.", sdk_ver_file);
1044 #endif
1045                 FileStream fs = new FileStream(sdk_ver_file, FileMode.Open, FileAccess.Read);
1046                 StreamReader sr = new StreamReader(fs);
1047                 bool found_line = false;
1048                 while (!sr.EndOfStream)
1049                 {
1050                     string line = sr.ReadLine();
1051                     if (line.Contains("#define CAFE_OS_SDK_VERSION") && !line.Contains("CAFE_OS_SDK_VERSION_STRING"))
1052                     {
1053                         UInt32 maj, min, mic, version;
1054                         string[] subs = line.Split((string[])null, StringSplitOptions.RemoveEmptyEntries);
1055 
1056                         if (subs.Length < 3)
1057                         {
1058                             Console.WriteLine("cafex Error: CAFE_OS_SDK_VERSION not defined in {0}!", sdk_ver_file);
1059                             break;
1060                         }
1061 
1062                         if (!UInt32.TryParse(subs[2], out version))
1063                         {
1064                             Console.WriteLine("cafex Error: TryParse on CAFE_OS_SDK_VERSION '{0}' failed!", subs[2]);
1065                             break;
1066                         }
1067 
1068                         maj = version / 10000;
1069                         min = (version % 10000) / 100;
1070                         mic = version % 100;
1071 
1072                         SDK_VER.value = String.Format("{0}.{1:D2}.{2:D2}", maj, min, mic);
1073 
1074                         found_line = true;
1075                         break;
1076                     }
1077                 }
1078                 sr.Close();
1079                 if (!found_line)
1080                 {
1081                     Console.WriteLine("cafex Error: couldn't determine SDK version!");
1082                     return CAFEX_ERROR.RUN_COULDNT_PARSE_SDK_VERSION_HEADER;
1083                 }
1084             }
1085 
1086             return CAFEX_ERROR.OK;
1087         }
1088 
readSDKFromMion()1089 		static void readSDKFromMion()
1090 		{
1091             string retVal = mionps.Run(BRIDGE_CURRENT_IP_ADDRESS.value + " 3 4 5").Trim();
1092             char[] delims = {' '};
1093             string[] splitString = retVal.Split(delims);
1094             SDK_MAJ_VER.value = splitString[0];
1095             SDK_MIN_VER.value = String.Format("{0:D2}",Convert.ToInt32(splitString[1]));
1096             SDK_MIC_VER.value = String.Format("{0:D2}",Convert.ToInt32(splitString[2]));
1097 		}
1098 
setMionSDKVersion()1099         static void setMionSDKVersion()
1100         {
1101             char[] delims = { '.', ' ' };
1102             string[] splitString = SDK_VER.value.Split(delims);
1103 
1104             int sdkmaj = Convert.ToInt32(splitString[0]);
1105             int sdkmin = Convert.ToInt32(splitString[1]);
1106             int sdkmic = Convert.ToInt32(splitString[2]);
1107 
1108             string parameters = string.Format("{0} 3 -s {1} 4 -s {2} 5 -s {3}", BRIDGE_CURRENT_IP_ADDRESS.value,
1109                                                                                 sdkmaj,
1110                                                                                 sdkmin,
1111                                                                                 sdkmic);
1112 
1113             string retVal = mionps.Run(parameters).Trim();
1114             string[] result = retVal.Split(delims);
1115             try
1116             {
1117                 int newcatmaj = Convert.ToInt32(result[0]);
1118                 int newcatmin = Convert.ToInt32(result[1]);
1119                 int newcatmic = Convert.ToInt32(result[2]);
1120 
1121                 if (sdkmaj != newcatmaj)
1122                     Console.WriteLine("cafex unable to set the SDK Major version. Mionps returned " + result[0]);
1123                 if (sdkmin != newcatmin)
1124                     Console.WriteLine("cafex unable to set the SDK Minor version. Mionps returned " + result[1]);
1125                 if (sdkmic != newcatmic)
1126                     Console.WriteLine("cafex unable to set the SDK Micro version. Mionps returned " + result[2]);
1127             }
1128             catch (Exception)
1129             {
1130                 Console.WriteLine("An error occurred when trying to set the SDK version on the catdev.");
1131                 Console.WriteLine("Mionps returned: " + retVal);
1132             }
1133         }
1134 
checkNameFail()1135         static CAFEX_ERROR checkNameFail()
1136         {
1137             HOSTSTOP_RVAL.value = "1";
1138             return CAFEX_ERROR.CHECKNAME_FAILED;
1139         }
1140 
parseVersions(string output, bool checkMionVersion, bool checkSdk)1141         static CAFEX_ERROR parseVersions(string output, bool checkMionVersion, bool checkSdk)
1142         {
1143             int res;
1144             int end;
1145             string sw_ver_str = null;
1146             string fw_ver_str = null;
1147 
1148             // Parse the software version (if not already checked)
1149             if (checkMionVersion || sw_ver_flat == 0)
1150             {
1151                 res = output.IndexOf("software:");
1152                 if (res < 0)
1153                 {
1154                     return checkNameFail();
1155                 }
1156                 end = output.IndexOf('\n', res += 9);
1157                 if (end < 0)
1158                 {
1159                     return checkNameFail();
1160                 }
1161                 sw_ver_str = output.Substring(res, end - res);
1162                 if (sw_ver_flat == 0)
1163                 {
1164                     sw_ver_flat = compute_flat_version(sw_ver_str);
1165                 }
1166             }
1167 
1168             // Parse the firmware version (if not already checked)
1169             if (checkMionVersion || fw_ver_flat == 0)
1170             {
1171                 res = output.IndexOf("firmware:");
1172                 if (res < 0)
1173                 {
1174                     return checkNameFail();
1175                 }
1176                 end = output.IndexOf('\n', res += 9);
1177                 if (end < 0)
1178                 {
1179                     return checkNameFail();
1180                 }
1181                 fw_ver_str = output.Substring(res, end - res);
1182                 if (fw_ver_flat == 0)
1183                 {
1184                     fw_ver_flat = compute_flat_version(fw_ver_str);
1185                 }
1186             }
1187 
1188             // Check versions
1189             if (checkMionVersion)
1190             {
1191                 int min_fw_ver = compute_flat_version(MIN_MION_FW_VER);
1192                 int min_sw_ver = compute_flat_version(MIN_MION_SW_VER);
1193 
1194                 if (sw_ver_flat < min_sw_ver || fw_ver_flat < min_fw_ver)
1195                 {
1196                     Console.WriteLine("cafex failed: Please install at least HostBridgeSetup_{0}.exe and restart cafex_env.bat", MIN_MION_SW_VER);
1197                     Console.WriteLine("              Current software version is {0} (need {1})", sw_ver_str, MIN_MION_SW_VER);
1198                     Console.WriteLine("              Current firmware version is {0} (need {1})", fw_ver_str, MIN_MION_FW_VER);
1199                     return checkNameFail();
1200                 }
1201             }
1202 
1203             // Set SDK versions (if not set)
1204             if (checkSdk &&
1205                 (string.IsNullOrEmpty(SDK_MAJ_VER.value) ||
1206                 string.IsNullOrEmpty(SDK_MIN_VER.value) ||
1207                 string.IsNullOrEmpty(SDK_MIC_VER.value)))
1208             {
1209                 res = output.IndexOf("sdk:");
1210                 if (res < 0)
1211                 {
1212                     return checkNameFail();
1213                 }
1214                 end = output.IndexOf('\n', res += 4);
1215                 if (end < 0)
1216                 {
1217                     return checkNameFail();
1218                 }
1219                 char[] delims = { '.' };
1220                 string[] sdk = output.Substring(res, end - res).Split(delims);
1221                 SDK_MAJ_VER.value = sdk[0];
1222                 SDK_MIN_VER.value = sdk[1];
1223                 SDK_MIC_VER.value = sdk[2];
1224             }
1225             return CAFEX_ERROR.OK;
1226         }
1227 
1228         //Script function: hoststop
hoststop(string[] args, bool checkMionVersion)1229         static CAFEX_ERROR hoststop(string[] args, bool checkMionVersion)
1230         {
1231 			bool bAttemptedSoftwareShutdown = false;
1232             bool HARD_STOP = false;
1233 
1234             if (args != null && args.Length > 0)
1235             {
1236                 if (args[0].ToLowerInvariant() == "-hard")
1237                 {
1238                     // Force hard stop
1239                     HARD_STOP = true;
1240                 }
1241             }
1242 
1243             #if DEBUG
1244                 Log.WriteLine("hoststop started.");
1245                 string argString = null;
1246                 if (args != null)
1247                 {
1248                     foreach (string arg in args)
1249                     {
1250                         argString += arg + " ";
1251                     }
1252                 }
1253                 Log.WriteLine("Arguments=" + argString);
1254 
1255             #endif
1256 
1257             if (SDIO_BRIDGE_TOOLS.value == null)
1258             {
1259                 if (MION_BRIDGE_TOOLS.value == null)
1260                 {
1261                     Console.WriteLine("cafex hoststop failed: Please install the HostBridge and reopen the build environment!");
1262                     return CAFEX_ERROR.CHECKNAME_FAILED;
1263                 }
1264             }
1265 
1266             HOSTSTOP_RVAL.value = "0";
1267             HOSTSTOP_RETRIES.value = "0";
1268 
1269             getbridgetype();
1270 
1271             HOSTSTOP_RESET_OPTION.value = "-SMCResetHold";
1272 
1273             if (BRIDGE_TYPE.value == "Mion")
1274             {
1275                 int res = 0;
1276                 bool makemine = false;
1277                 string output = string.Empty;
1278                 bool singleCGI = USE_SINGLE_CGI.value == "1";
1279                 if (!singleCGI)
1280                 {
1281                     Environment.SetEnvironmentVariable("CHECK_NAME_STOP", null);
1282                 }
1283 
1284                 // Set the proper USE_SINGLE_CGI hint
1285                 if (args != null && args.Length > 0 && args[0] == "-makemine")
1286                 {
1287                     ToucanReset.Stop();
1288                     makemine = true;
1289                     if (singleCGI)
1290                     {
1291                         Environment.SetEnvironmentVariable("CHECK_NAME_STOP", "2");
1292                     }
1293                 }
1294                 else if (singleCGI)
1295                 {
1296                     Environment.SetEnvironmentVariable("CHECK_NAME_STOP", "1");
1297                 }
1298 
1299                 // Check the bridge name
1300                 res = checkbridgename.CheckName(ref output);
1301                 if (res != 0)
1302                 {
1303                     // Check if error string
1304                     res = output.IndexOf("ERROR :");
1305                     if (res < 0)
1306                     {
1307                         output = string.Format("Bridge with the name '{0}' was not found", BRIDGE_CURRENT_NAME.value);
1308                     }
1309                     else
1310                     {
1311                         // Report error string
1312                         int end = output.IndexOf('\n', res);
1313                         if (end < 0)
1314                         {
1315                             output = output.Substring(res);
1316                         }
1317                         else
1318                         {
1319                             output = output.Substring(res, end - res);
1320                         }
1321                     }
1322                     Console.WriteLine("CheckBridgeName: {0}", output);
1323                     return checkNameFail();
1324                 }
1325 
1326                 if (singleCGI)
1327                 {
1328                     if (output.Contains("INFO: CGI Reset"))
1329                     {
1330                         // Single pass supported firmware
1331                         if (command != "stop")
1332                         {
1333                             Console.WriteLine("cafex {0}: Single pass CGI enabled", command);
1334                         }
1335                         if (makemine)
1336                         {
1337                             res = output.IndexOf("oldhost:");
1338                             if (res < 0)
1339                             {
1340                                 return checkNameFail();
1341                             }
1342                             int end = output.IndexOf("\n", res += 8);
1343                             if (end < 0)
1344                             {
1345                                 return checkNameFail();
1346                             }
1347                             string old = output.Substring(res, (end - 1) - res);
1348                             res = output.IndexOf("curhost:");
1349                             if (res < 0)
1350                             {
1351                                 return checkNameFail();
1352                             }
1353                             end = output.IndexOf("\n", res += 8);
1354                             if (end < 0)
1355                             {
1356                                 return checkNameFail();
1357                             }
1358                             string host = output.Substring(res, (end - 1) - res);
1359                             Console.WriteLine("cafex {0}: Bridge old owner: [{1}] new owner: [{2}]", command, old, host);
1360                         }
1361                         else
1362                         {
1363                             ToucanReset.Stop();
1364                         }
1365 
1366                         return parseVersions(output, checkMionVersion, true);
1367                     }
1368 
1369                     // Not supported, clear hint
1370                     USE_SINGLE_CGI.value = null;
1371 
1372                     // Are we at least using single pass supported hostbridge?
1373                     res = output.IndexOf("INFO: Display info ");
1374                     if (res >= 0)
1375                     {
1376                         // Check the bridge query version
1377                         if (output[res + 19] != '(')
1378                         {
1379                             return checkNameFail();
1380                         }
1381                         int end = output.IndexOf(')', res += 20);
1382                         if (end < 0)
1383                         {
1384                             return checkNameFail();
1385                         }
1386 
1387                         // Parse the versions
1388                         CAFEX_ERROR err = parseVersions(output, checkMionVersion, int.Parse(output.Substring(res, end - res)) > 1);
1389                         if (err != CAFEX_ERROR.OK)
1390                         {
1391                             return err;
1392                         }
1393 
1394                         // Only display warning if firmware is out of sync
1395                         Console.WriteLine("cafex {0}: Disabling single pass CGI, not supported", command);
1396                     }
1397                 }
1398 
1399                 /*
1400                  * Old stop functionality
1401                 */
1402                 if (makemine)
1403                 {
1404                     FSEmul.makemine();
1405                 }
1406 
1407                 if ((MION_PWR_SEQ.value == "smcreset") && !HARD_STOP)
1408                 {
1409                     int mionbutton_ret = MionButton.rsthold(args);
1410                     HOSTSTOP_RVAL.value = mionbutton_ret.ToString();
1411                 }
1412                 else if ((MION_PWR_SEQ.value == "FOFF1") && !HARD_STOP)
1413                 {
1414                     int mionbutton_ret = MionButton.forceOff1(args);
1415                     HOSTSTOP_RVAL.value = mionbutton_ret.ToString();
1416                 }
1417                 else
1418                 {
1419                     string boot_mode_file = Path.Combine(CAFE_TEMP.value, BRIDGE_CURRENT_IP_ADDRESS.value.Replace('.', 'x') + "_" + BRIDGE_CURRENT_NAME.value + "_CAFE_BOOT_MODE");
1420                     string OLD_BOOT_MODE = string.Empty;
1421                     if (File.Exists(boot_mode_file))
1422                     {
1423                         OLD_BOOT_MODE = File.ReadAllText(boot_mode_file);
1424                     }
1425 
1426                     if (MION_PWR_SEQ.value == "G_SHUTDOWN" && !HARD_STOP && (OLD_BOOT_MODE == CAFE_BOOT_MODE.value))
1427                     {
1428                         int mionbutton_ret = MionButton.init_shutdown_w_FOFF2(args);
1429                         bAttemptedSoftwareShutdown = true;
1430                         HOSTSTOP_RVAL.value = mionbutton_ret.ToString();
1431                     }
1432                     else
1433                     {
1434                         HOSTSTOP_RVAL.value = "1";
1435                         HOSTSTOP_RETRIES.value = "0";
1436                         while (HOSTSTOP_RVAL.value != "0" && HexHandler.GetNumberFromString(HOSTSTOP_RETRIES.value) < 4)
1437                         {
1438                             if (HexHandler.GetNumberFromString(HOSTSTOP_RETRIES.value) > 0)
1439                             {
1440                                 Console.WriteLine("WARNING: MionButton powerdown failed with err={0}, will retry shortly, count={1}", HOSTSTOP_RVAL.value, HOSTSTOP_RETRIES.value);
1441                                 Thread.Sleep(new TimeSpan(0, 0, 30));
1442                             }
1443 
1444                             int mionbutton_ret = MionButton.forceOff2_off_single_cgi(args);
1445                             HOSTSTOP_RVAL.value = mionbutton_ret.ToString();
1446                             HOSTSTOP_RETRIES.value = (HexHandler.GetNumberFromString(HOSTSTOP_RETRIES.value) + 1).ToString();
1447                         }
1448                     }
1449                 }
1450 
1451                 if (HOSTSTOP_RVAL.value != "0")
1452                 {
1453                     Console.WriteLine("Gathering MION logs via telnet for the mionbutton return of " + HOSTSTOP_RVAL.value + ".");
1454                     string logfile = TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log";
1455                     FileStream fs = new FileStream(logfile, FileMode.Create);
1456                     StreamWriter sw = new StreamWriter(fs);
1457                     sw.WriteLine("----------------------------------------------------------------");
1458                     sw.WriteLine("----- MION telnet debug log @ " + DateTime.Now.ToLocalTime().ToString() + " -----");
1459                     sw.WriteLine("----------------------------------------------------------------");
1460                     output = string.Empty;
1461                     int miontelnet_ret = miontelnet.Run(out output);
1462                     sw.Write(output);
1463                     sw.Flush();
1464                     sw.Close();
1465                     Console.WriteLine("  See " + logfile + " for details.");
1466                 }
1467             }
1468             else
1469             {
1470                 int toucanreset_ret = ToucanReset.Reset();
1471                 HOSTSTOP_RVAL.value = toucanreset_ret.ToString();
1472             }
1473 
1474             ToucanReset.Stop();
1475 
1476             if (HOSTSTOP_RVAL.value == "0")
1477             {
1478                 return CAFEX_ERROR.OK;
1479             }
1480 
1481             if (BRIDGE_TYPE.value == "Mion")
1482             {
1483                 if (bAttemptedSoftwareShutdown && HOSTSTOP_RVAL.value == "1")
1484                 {
1485                     Console.WriteLine("cafex hoststop warning: Software shutdown failed.");
1486                     HOSTSTOP_RVAL.value = "0";
1487                 }
1488                 else
1489                 {
1490                     Console.WriteLine("cafex hoststop failed: Could not stop cafe through " + BRIDGE_CURRENT_NAME.value);
1491                     checkbridgename.CheckName_IPOnly();
1492                 }
1493             }
1494             else
1495             {
1496                 Console.WriteLine("cafex hoststop failed: Could not stop cafe through Toucan.");
1497             }
1498             return CAFEX_ERROR.CHECKNAME_FAILED;
1499         }
1500 
hoststop(string[] args)1501         static CAFEX_ERROR hoststop(string[] args)
1502         {
1503             return hoststop(args, false);
1504         }
1505 
1506         //Script function: getbridgetype
getbridgetype()1507         static void getbridgetype()
1508         {
1509             #if DEBUG
1510                 Log.WriteLine("getbridgetype started.");
1511             #endif
1512 
1513             BRIDGE_TYPE.value = "Mion";
1514             if (CAFE_HARDWARE.value.Length > 6)
1515             {
1516                 if (CAFE_HARDWARE.value.Substring(6).StartsWith("mp"))
1517                 {
1518                     BRIDGE_TYPE.value = "Mion";
1519                 }
1520                 else if (CAFE_HARDWARE.value.Substring(6) == "1" || CAFE_HARDWARE.value.Substring(6) == "2")
1521                 {
1522                     BRIDGE_TYPE.value = "Toucan";
1523                 }
1524             }
1525 
1526             #if DEBUG
1527                 Log.WriteLine("BRIDGE_TYPE set to = " + BRIDGE_TYPE.value);
1528             #endif
1529         }
1530 
1531         internal enum CafeBootStage
1532         {
1533             Off,
1534             ServerSync,
1535             SendingSync1,
1536             WaitingForSync1,
1537             SendingFlags,
1538             SendingSync2,
1539             WaitingForSync2,
1540             Booted,
1541         }
1542 
trySyncRequest()1543         static bool trySyncRequest()
1544         {
1545             if (cattoucan.SendSyncRequest(DEVKIT_HELP_REQUEST_TIMEOUT))
1546             {
1547                 CMD_RESULT.value = "0";
1548                 return true;
1549             }
1550 
1551             CMD_RESULT.value = "1";
1552             return false;
1553         }
1554 
1555         private class CafeBootProgress
1556         {
1557             public CafeBootStage stage        = CafeBootStage.Off;
1558             public bool          waitForTitle = false;
1559             public bool          checkPower   = true;
1560             public int           tries        = 0;
1561 
checkVDD2()1562             public void checkVDD2()
1563             {
1564                 if (checkPower && mionsig.getVDD2() == 0)
1565                 {
1566                     stage = CafeBootStage.Off;
1567                 }
1568             }
1569 
checkKillRestartSoftlaunch()1570             public bool checkKillRestartSoftlaunch()
1571             {
1572                 waitForTitle = Environment.GetEnvironmentVariable("USE_KILL_RESTART_SOFTLAUNCH") == "1";
1573                 return waitForTitle;
1574             }
1575 
1576             public bool Active
1577             {
1578                 get
1579                 {
1580                     return stage != CafeBootStage.Off;
1581                 }
1582             }
1583         }
1584 
bootCatDev()1585         static CafeBootStage bootCatDev()
1586         {
1587             cattoucan.FinishSync(true);
1588 
1589             List<string> onArguments = new List<string>();
1590             onArguments.Add("-noprompt");
1591             if (!string.IsNullOrEmpty(BRIDGE_PARAMETERS_WITH_E.value))
1592             {
1593                 onArguments.AddRange(BRIDGE_PARAMETERS_WITH_E.value.Split(' '));
1594             }
1595 
1596             // discrun support variables
1597             onArguments.Add(ELF_NEST_OPT.value);
1598             onArguments.Add(ELF_NEST_VALUE.value);
1599 
1600             string[] noprompt_args = onArguments.ToArray();
1601             EnvVar.BackUpCurrentEnvironment();
1602             // Save and check user input
1603             string userProvidedTitleId = CAFERUN_OPTION_MLC_EMU_TITLEID.value;
1604             if (!string.IsNullOrEmpty(userProvidedTitleId))
1605             {
1606                 userProvidedTitleId = userProvidedTitleId.StartsWith("0x") ? userProvidedTitleId.Substring(2).ToLowerInvariant() : userProvidedTitleId.ToLowerInvariant();
1607 
1608                 // Then assigns to the variable that will be passed in for verification
1609                 CAFERUN_WUMAD_TITLE_ID.value = userProvidedTitleId;
1610             }
1611             // Then assigns to the variable that will be passed in for verification
1612             CAFERUN_WUMAD_TITLE_ID.value = userProvidedTitleId;
1613 
1614             IsBooting = true;
1615             CafeXReturn ret = on(noprompt_args, true, true);
1616             IsBooting = false;
1617 
1618             if (ret.error != CAFEX_ERROR.OK)
1619             {
1620                 if (CMD_RESULT.value == "0")
1621                 {
1622                     CMD_RESULT.value = "1";
1623                 }
1624                 return CafeBootStage.Off;
1625             }
1626 
1627             string wumadRetrievedTitleId = CAFERUN_WUMAD_TITLE_ID.value;
1628             EnvVar.RestoreSavedEnvironment();
1629             // If a value returned and it's different, should take it.
1630             if (!string.IsNullOrEmpty(wumadRetrievedTitleId) &&
1631                 !wumadRetrievedTitleId.Equals(userProvidedTitleId))
1632             {
1633                 // This is the auto-discovery action. Reset the wumad title id.
1634                 CAFERUN_WUMAD_TITLE_ID.value = wumadRetrievedTitleId;
1635             }
1636 
1637             // We are cold booting, disable fast relaunch
1638             CAFERUN_OPTION_FAST_RELAUNCH.value = "0";
1639             return CafeBootStage.ServerSync;
1640         }
1641 
tryCafeReboot(bool launch, bool isWumadExecution, CafeBootProgress progress, out CAFEX_ERROR error)1642         static bool tryCafeReboot(bool             launch,
1643                                   bool             isWumadExecution,
1644                                   CafeBootProgress progress,
1645                                   out CAFEX_ERROR  error)
1646         {
1647             bool coldBootIntoApp = progress.waitForTitle                         &&
1648                                     CAFE_BOOT_MODE.value               == "PCFS" &&
1649                                     CAFERUN_OPTION_SOFT_LAUNCH.value   != "1"    &&
1650                                     CAFERUN_OPTION_FAST_RELAUNCH.value != "1";
1651 
1652             /* Cold booting
1653                 * don't wait for title to launch
1654                 * or check power on sync
1655                 */
1656             progress.waitForTitle = false;
1657             progress.checkPower = false;
1658 
1659             // Cold boot into app if PCFS and not trying to soft or fast launch
1660             if (coldBootIntoApp)
1661             {
1662                 error = startBootRun(isWumadExecution, launch, true);
1663                 if (error != CAFEX_ERROR.OK || !launch)
1664                 {
1665                     return false;
1666                 }
1667 
1668                 progress.tries = CAFERUN_RETRY_COUNT;
1669                 CMD_RESULT.value = "0";
1670             }
1671             else
1672             {
1673                 error = CAFEX_ERROR.OK;
1674                 // Try to boot into sysconfig
1675                 if (progress.tries < CAFERUN_LAST_RETRY)
1676                 {
1677                     progress.stage = bootCatDev();
1678                     if (!progress.Active)
1679                     {
1680                         progress.tries = CAFERUN_LAST_RETRY;
1681                     }
1682                 }
1683             }
1684             return true;
1685         }
1686 
startBootRun(bool isWumadExecution, bool launch, bool reboot)1687         static CAFEX_ERROR startBootRun(bool isWumadExecution, bool launch, bool reboot)
1688         {
1689             if (reboot)
1690             {
1691                 cattoucan.FinishSync(true);
1692                 hoststop(null, false);
1693             }
1694             PCFS_SYNC_DATE.value = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-ffff");
1695             string pcfsSync = string.Format("Starting PCFSServer.exe @ sync date [{0}]", PCFS_SYNC_DATE.value);
1696             Console.WriteLine(pcfsSync);
1697 #if DEBUG
1698             Log.WriteLine(pcfsSync);
1699 #endif
1700             pcfsSync = null;
1701 #if TIMER
1702             CafeXSetupTime.Report();
1703 #endif
1704             CMD_RESULT.value = PCFSServer.Start(PCFSSERVER_PARAMETERS.value, PCFS_DIR_MAPPING.value, PCFS_SRV_LOG_OUTPUT.value).ToString();
1705 
1706             Console.WriteLine("PCFSServer has started");
1707 #if DEBUG
1708             Log.WriteLine("PCFSServer has started");
1709 #endif
1710 
1711 #if TIMER
1712             CafeXSetupTime.Report();
1713 #endif
1714 
1715             if (PCFSSERVER_PARAMETERS.value != null)
1716             {
1717                 Console.WriteLine("Waiting for PCFSServer initialization...");
1718                 PCFSSERVERSYNC_RVAL.value = PCFSServerSync.wait_sync(PCFS_SYNC_DATE.value).ToString();
1719                 if (PCFSSERVERSYNC_RVAL.value != "0")
1720                 {
1721                     Console.WriteLine("PCFSServerSync exited with value " + PCFSSERVERSYNC_RVAL.value);
1722                     return CAFEX_ERROR.RUN_PCFSSERVER_SYNC_FAILED;
1723                 }
1724                 Console.WriteLine("PCFSServer initialization complete!");
1725             }
1726             else
1727             {
1728                 Console.WriteLine("PCFSServer started without synchronization");
1729             }
1730 
1731             BOOTRUN_ELF_OPT.value = "";
1732             BOOTRUN_ELF_VALUE.value = "";
1733             if (!string.IsNullOrEmpty(SOFT_LAUNCH_CAFE_ELF.value))
1734             {
1735                 BOOTRUN_ELF_OPT.value = "-usedlf";
1736                 BOOTRUN_ELF_VALUE.value = SOFT_LAUNCH_CAFE_ELF.value;
1737             }
1738 
1739             // Check if this is a wumad execution, so that bootrun can correctly assign the title Id
1740             if (isWumadExecution)
1741             {
1742                 if (!string.IsNullOrEmpty(CAFERUN_OPTION_MLC_EMU_TITLEID.value))
1743                 {
1744                     // Saves user input
1745                     string userProvidedTitleId = CAFERUN_OPTION_MLC_EMU_TITLEID.value.StartsWith("0x") ? CAFERUN_OPTION_MLC_EMU_TITLEID.value.Substring(2).ToLowerInvariant() : CAFERUN_OPTION_MLC_EMU_TITLEID.value.ToLowerInvariant();
1746                     // Then assigns to the variable that will be passed in for verification
1747                     CAFERUN_WUMAD_TITLE_ID.value = userProvidedTitleId;
1748                 }
1749                 else
1750                 {
1751                     // Ensure there is no title, so autodiscovery can run
1752                     CAFERUN_WUMAD_TITLE_ID.value = string.Empty;
1753                 }
1754             }
1755 
1756             if (launch == false)
1757             {
1758                 return CAFEX_ERROR.OK;
1759             }
1760 
1761 #if TIMER
1762             Log.WriteLine("Launching bootrun");
1763             CafeXSetupTime.Report();
1764 #endif
1765             CAFEX_ERROR bootrun_ret = bootrun(new List<string>() { BOOTRUN_ELF_OPT.value, BOOTRUN_ELF_VALUE.value }, fAppTypeDefined);
1766             if (bootrun_ret != CAFEX_ERROR.OK)
1767             {
1768                 return bootrun_ret;
1769             }
1770 #if TIMER
1771             Log.WriteLine("Bootrun end");
1772             CafeXSetupTime.Report();
1773 #endif
1774             return CAFEX_ERROR.OK;
1775         }
1776 
1777         //Script function: caferun
run(string[] args, bool runSetup, bool launch)1778         static CafeXReturn run(string[] args, bool runSetup, bool launch)
1779         {
1780             CafeXReturn ret = new CafeXReturn(CAFEX_ERROR.UNEXPECTED);  //TODO: Spread the love to the other return paths.
1781 
1782             // Check to see if we have default options
1783             if (!String.IsNullOrEmpty(CAFERUN_DEFAULT_OPTIONS.value))
1784             {
1785                 // Warn the user that any default options will get overwritten if matching switches are specified on the command line.
1786                 Log.WriteLine("*** CAFERUN_DEFAULT_OPTIONS *** Default options detected! Please be aware that any duplicate switches on the command line will overwrite the defaults specified!");
1787 
1788                 // Split the string into array elements and then create the new args array
1789                 string[] temp;
1790                 temp = CAFERUN_DEFAULT_OPTIONS.value.Split(' ');
1791 
1792                 // We need to expand the args array so we can add the new args into it.
1793                 int newLen = (temp.Length + args.Length);
1794                 Array.Resize<string>(ref args, newLen);
1795 
1796                 string[] defaultArgs = new string[newLen];
1797                 Array.Copy(temp, defaultArgs, temp.Length);
1798                 Array.Copy(args, 0, defaultArgs, temp.Length, (args.Length - temp.Length));
1799 
1800                 args = defaultArgs;
1801             }
1802 
1803             #if DEBUG
1804                 Log.WriteLine("~~~~~~~~~~~~~~~~ START ENV VARIABLES~~~~~~~~~~~~~~~~~~");
1805                 IDictionary	environmentVariables = Environment.GetEnvironmentVariables();
1806                 foreach (DictionaryEntry de in environmentVariables)
1807                 {
1808                    Log.WriteLine(string.Format("  {0} = {1}", de.Key, de.Value));
1809                 }
1810                 Log.WriteLine("~~~~~~~~~~~~~~~~ END ENV VARIABLES~~~~~~~~~~~~~~~~~~");
1811 
1812                 Log.WriteLine(string.Format("**** Current Working Directory = {0} ****", Directory.GetCurrentDirectory()));
1813                 Log.WriteLine("run started.");
1814                 string argString = null;
1815                 if (args != null)
1816                 {
1817                     foreach (string arg in args)
1818                     {
1819                         argString += arg + " ";
1820                     }
1821                 }
1822                 Log.WriteLine("Arguments=" + argString);
1823 
1824             #endif
1825             #region setup
1826             bool isWumadExecution = false;
1827             if (runSetup == true)
1828             {
1829                 if (CAFERUN_INS.value == null)
1830                 {
1831                     CAFERUN_INS.value = "0";
1832                 }
1833 
1834                 // This tells if the current call contains wumad parameters.
1835                 PLATFORM.value = "cafe";
1836 
1837                 QUIET.value = "-q";
1838                 CAFESTOP_ONLY_IF_FSEMUL.value = "0";
1839                 PPC_OS_FLAGS.value = "0";
1840                 PPC_APP_FLAGS.value = "0";
1841                 PCFS_SYNC_DATE.value = "";
1842                 MCP_LAUNCH_HINT.value = "";
1843                 MCP_INFO_OPTION.value = "";
1844                 if (DEBUGGER.value == null)
1845                 {
1846                     DEBUGGER.value = "none";
1847                 }
1848 
1849                 if (CAFE_CONSOLE.value == null)
1850                 {
1851                     CONSOLE.value = "cattoucan";
1852                 }
1853                 else
1854                 {
1855                     CONSOLE.value = CAFE_CONSOLE.value;
1856                 }
1857 
1858                 if (CAFE_DEBUG_PORT.value == null)
1859                 {
1860                     CAFE_DEBUG_PORT.value = "toucan";
1861                 }
1862 
1863                 if (DEBUG_ELF_FILE.value == null)
1864                 {
1865                     DEBUG_ELF_FILE.value = "";
1866                 }
1867 
1868                 CAFERUN_OPTION_SOFT_RESTART.value = "0";
1869                 CAFERUN_OPTION_FAST_RELAUNCH.value = "0";
1870                 CAFERUN_OPTION_MLC_EMU_LAUNCH.value = "0";
1871                 CAFERUN_OPTION_MLC_EMU_TITLEID.value = "0xFFFFFFFFFFFFFFFF";
1872                 string sdk_ver_file = CAFE_ROOT.value + "\\system\\include\\sdk_ver.h";
1873                 if (!File.Exists(sdk_ver_file))
1874                 {
1875                     Console.WriteLine("cafex run error: sdk_ver.h does not exist: " + sdk_ver_file);
1876                     return new CafeXReturn(CAFEX_ERROR.RUN_NO_SDK_VERSION_HEADER);
1877                 }
1878 
1879                 FileStream fs = new FileStream(CAFE_ROOT.value + "\\system\\include\\sdk_ver.h", FileMode.Open, FileAccess.Read);
1880                 StreamReader sr = new StreamReader(fs);
1881                 bool found_line = false;
1882                 while (!sr.EndOfStream)
1883                 {
1884                     string line = sr.ReadLine();
1885                     if (line.Contains("00050010"))
1886                     {
1887                         int index = line.IndexOf("00050010");
1888                         string version = line.Substring(index, 16);
1889                         CAFERUN_OS_MAJOR_VERSION_LO.value = version.Substring(8, 8);
1890                         CAFERUN_OS_MAJOR_VERSION.value = version.Substring(14, 2);
1891                         if (CAFERUN_COLDBOOT_OS_VERSION.value == null)
1892                             CAFERUN_COLDBOOT_OS_VERSION.value = "0x00050010100040" + CAFERUN_OS_MAJOR_VERSION.value;
1893                         else
1894                             CAFERUN_COLDBOOT_OS_VERSION.value = "0x" + CAFERUN_COLDBOOT_OS_VERSION.value;
1895                         found_line = true;
1896                         break;
1897                     }
1898                 }
1899                 sr.Close();
1900                 if (!found_line)
1901                 {
1902                     Console.WriteLine("cafex run error: couldn't find sdk version in sdk_ver.h");
1903                     return new CafeXReturn(CAFEX_ERROR.RUN_COULDNT_PARSE_SDK_VERSION_HEADER);
1904                 }
1905 #if DEBUG
1906             Log.WriteLine("CAFERUN_COLDBOOT_OS_VERSION set to '" + CAFERUN_COLDBOOT_OS_VERSION.value + "' from file " + CAFE_ROOT.value + "\\system\\include\\sdk_ver.h");
1907 #endif
1908                 HEARTBEAT_DISABLE.value = "0";
1909                 PCFS_DIR_MAPPING.value = "";
1910                 MAPDIR_MLC.value = "";
1911                 MAPDIR_SLC.value = "";
1912                 MAPDIR_CODE.value = "";
1913                 MAPDIR_META.value = "";
1914                 MAPDIR_CONTENT.value = "";
1915                 MAPDIR_SAVE.value = "";
1916                 PCFS_LOG_TIMESTAMP.value = "";
1917                 PCFS_SRV_LOG_OUTPUT.value = "";
1918                 RUN_FROM_HDD_BANK.value = "";
1919                 BRIDGE_PARAMETERS.value = "";
1920                 BRIDGE_PARAMETERS_WITH_E.value = "";
1921                 PCFSSERVER_PARAMETERS.value = "";
1922                 PCFS_OVER_SATA_PORT.value = "";
1923                 if (PCFS_HEADLESS_EMUL.value == null)
1924                 {
1925                     PCFS_HEADLESS_EMUL.value = "-pcfsenable";
1926                 }
1927 
1928                 PREPHDD_STAT.value = "";
1929                 DISC_EMU_TID.value = "";
1930                 SYSTEM_MODE.value = "";
1931                 RPL_DIRS.value = "";
1932                 RPL_FILES.value = "";
1933 
1934                 if (CAFERUN_OPTION_NO_DATA_SYNC.value == null)
1935                 {
1936                     CAFERUN_OPTION_NO_DATA_SYNC.value = "0";
1937                 }
1938 
1939                 if (command != "on" && command != "setbootmode" && CAFE_BOOT_MODE.value == "NAND")
1940                 {
1941                     CAFERUN_OPTION_SOFT_LAUNCH.value = "1";
1942                 }
1943                 else
1944                 {
1945                     CAFERUN_OPTION_SOFT_LAUNCH.value = "0";
1946                 }
1947 #if DEBUG
1948             Log.WriteLine("CAFERUN_OPTION_SOFT_LAUNCH set to " + CAFERUN_OPTION_SOFT_LAUNCH.value);
1949 #endif
1950 
1951                 CAFERUN_HOSTBRIDGE_VERSION.value = "unknown";
1952                 CAFERUN_FW_VERSION.value = "unknown";
1953 
1954                 if (CAFE_DEBUG_INIT.value == null)
1955                 {
1956                     CAFE_DEBUG_INIT.value = "0";
1957                 }
1958 
1959                 if (CAFE_DEBUG_PREINIT.value == null)
1960                 {
1961                     CAFE_DEBUG_PREINIT.value = "0";
1962                 }
1963 
1964                 if (CAFE_DEBUG_DONTSTOP.value == null)
1965                 {
1966                     CAFE_DEBUG_DONTSTOP.value = "0";
1967                 }
1968 
1969                 if (CAFE_LAUNCH_DEBUG.value == null)
1970                 {
1971                     CAFE_LAUNCH_DEBUG.value = "1";
1972                 }
1973 
1974                 if (CAFE_SYSLOG_LEVEL.value == null)
1975                 {
1976                     CAFE_SYSLOG_LEVEL.value = "1";
1977                 }
1978 
1979                 if (CAFE_RUN_FORCERESTART.value == null)
1980                 {
1981                     CAFE_RUN_FORCERESTART.value = "0";
1982                 }
1983 
1984                 if (DEBUG_PROC_ID.value == null)
1985                 {
1986                     DEBUG_PROC_ID.value = "15";
1987                 }
1988                 if (CAFERUN_OPTION_KILL_RESTART.value == null)
1989                 {
1990                     CAFERUN_OPTION_KILL_RESTART.value = "0";
1991                 }
1992 
1993                 DEBUG_FLAGS.value = "0";
1994 
1995                 if (CAFE_DEBUG_INIT.value != "0")
1996                 {
1997                     DEBUG_FLAGS.value = "16";
1998                 }
1999 
2000                 if (CAFE_DEBUG_DONTSTOP.value != "0")
2001                 {
2002                     DEBUG_FLAGS.value = "32";
2003                 }
2004 
2005                 if (CAFE_DEBUG_PREINIT.value != "0")
2006                 {
2007                     DEBUG_FLAGS.value = "64";
2008                 }
2009 
2010                 if (USE_EXI_AS_DEBUG_CHANNEL.value == null || USE_EXI_AS_DEBUG_CHANNEL.value.Equals("0"))
2011                 {
2012                     UInt32 dbgFlags = HexHandler.GetNumberFromString(DEBUG_FLAGS.value) | 256;
2013                     DEBUG_FLAGS.value = dbgFlags.ToString();
2014                 }
2015 
2016                 CATOUTPUT.value = "0";
2017                 CMDOUTPUT.value = "0";
2018 
2019                 switch (CONSOLE.value)
2020                 {
2021                     case "sdio":
2022                         {
2023                             CONSOLE.value = "toucan";
2024                             break;
2025                         }
2026                     case "cattoucan":
2027                         {
2028                             CONSOLE.value = "toucan";
2029                             DEBUGGER.value = "cattoucan";
2030                             CATOUTPUT.value = "1";
2031                             break;
2032                         }
2033                     case "cmdtoucan":
2034                         {
2035                             CONSOLE.value = "toucan";
2036                             DEBUGGER.value = "cattoucan";
2037                             CMDOUTPUT.value = "1";
2038                             break;
2039                         }
2040                 }
2041 
2042                 if (CAFE_AUTOTEST.value == "1")
2043                 {
2044                     DEBUGGER.value = "none";
2045                 }
2046 
2047 #if DEBUG
2048                 Log.WriteLine("CONSOLE  = " + CONSOLE.value);
2049                 Log.WriteLine("DEBUGGER = " + DEBUGGER.value);
2050                 Log.WriteLine("CATOUTPUT= " + CATOUTPUT.value);
2051                 Log.WriteLine("CMDOUTPUT= " + CMDOUTPUT.value);
2052 #endif
2053             }
2054             //if (launch == false)
2055             //{
2056             //    return new CafeXReturn(CAFEX_ERROR.OK);
2057             //}
2058             #endregion
2059 
2060             int rpx_index = args.Length;
2061             for (int i = 0; i < args.Length; ++i)
2062             {
2063                 if (args[i].ToLowerInvariant().Contains(".rpx") || args[i].ToLowerInvariant().Contains(".elf"))
2064                 {
2065                     // Ensure the RPX is not the argument of an option
2066                     if ( i > 0 &&
2067                        ( args[i - 1].Trim().Equals("-k") ||
2068                          args[i - 1].Trim().Equals("-l") ||
2069                          args[i - 1].ToLowerInvariant().Trim().Equals("-e")))
2070                     {
2071                         // Exceptions: If ELF/RPX is argument of "-k" or "-l".
2072                         continue;
2073                     }
2074                     else
2075                     {
2076                         // Default: ELF/RPX found is the one to run.
2077                         rpx_index = i;
2078                         break;
2079                     }
2080                 }
2081             }
2082 
2083 #if DEBUG
2084             Log.WriteLine("Search for RPX index returned index = " + rpx_index.ToString());
2085 #endif
2086 
2087             #region arguments
2088 
2089             for (int i = 0; i < rpx_index; ++i)
2090             {
2091                 switch (args[i])
2092                 {
2093                     case "-m":
2094                     {
2095                         Console.WriteLine("cafex run failed: memmap not supported");
2096                         run_usage();
2097                         return new CafeXReturn(CAFEX_ERROR.RUN_MEMMAP_NOT_SUPPORTED);
2098                     }
2099 
2100                     case "-g":
2101                     {
2102                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2103                         {
2104                             run_usage();
2105                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2106                         }
2107 
2108                         uint prev_value = HexHandler.GetNumberFromString(PPC_OS_FLAGS.value);
2109                         uint arg_value;
2110                         if (String.IsNullOrEmpty(args[i + 1]))
2111                         {
2112                             Console.WriteLine("WARNING: Value after -g is null or empty.  Option is ignored.");
2113                             arg_value = 0;
2114                         }
2115                         else
2116                         {
2117                             arg_value = HexHandler.GetNumberFromString(args[i + 1]);
2118                         }
2119 
2120                         uint new_value = prev_value | arg_value;
2121                         PPC_OS_FLAGS.value = new_value.ToString();
2122                         //MULTI sends -g 1 to PPC_OS_FLAGS telling it that debugger is attached
2123                         //equivalent to ==> -d multi
2124                         if ((arg_value & 0x1) == 1)
2125                         {
2126                             g_gArgValue = 1;
2127                         }
2128                         ++i;
2129                         break;
2130                     }
2131 
2132                     case "-p":
2133                     {
2134                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2135                         {
2136                             run_usage();
2137                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2138                         }
2139 
2140                         if (String.IsNullOrEmpty(args[i + 1]))
2141                         {
2142                             //DEBUG_PROC_ID has a default value of 15, or whatever the user may have set in the env
2143                             //This is why it's not set here.
2144                             Console.WriteLine("WARNING: Value for -p is null or empty.  Debugger will break in the default process ({0}).", DEBUG_PROC_ID.value);
2145                         }
2146                         else
2147                         {
2148                             DEBUG_PROC_ID.value = args[i + 1];
2149                         }
2150                         uint debug_flags = HexHandler.GetNumberFromString(DEBUG_FLAGS.value);
2151                         uint debug_proc_id = HexHandler.GetNumberFromString(DEBUG_PROC_ID.value);
2152                         if ((debug_flags & 0xf) != 0)
2153                         {
2154                             uint new_value = (uint)(debug_flags & ~0xf) | (debug_proc_id & 0xf);
2155                             DEBUG_FLAGS.value = new_value.ToString();
2156                         }
2157                         ++i;
2158                         break;
2159                     }
2160 
2161                     case "-d":
2162                     {
2163                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2164                         {
2165                             run_usage();
2166                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2167                         }
2168 
2169                         DEBUGGER.value = args[i + 1];
2170                         uint debug_flags = HexHandler.GetNumberFromString(DEBUG_FLAGS.value);
2171                         uint debug_proc_id = HexHandler.GetNumberFromString(DEBUG_PROC_ID.value);
2172                         uint new_value = debug_flags | (debug_proc_id & 0xf);
2173                         DEBUG_FLAGS.value = new_value.ToString();
2174                         //CAFE_RUN_FORCERESTART.value = "1";
2175                         ++i;
2176                         break;
2177                     }
2178 
2179                     case "-k":
2180                     {
2181                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2182                         {
2183                             run_usage();
2184                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2185                         }
2186 
2187                         DEBUG_ELF_FILE.value = args[i + 1];
2188                         ++i;
2189                         break;
2190                     }
2191 
2192                     case "-w":
2193                     {
2194                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2195                         {
2196                             run_usage();
2197                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2198                         }
2199 
2200                         uint prev_value = HexHandler.GetNumberFromString(PPC_OS_FLAGS.value);
2201                         uint arg_value = 0;
2202                         try
2203                         {
2204                             arg_value = HexHandler.GetNumberFromString(args[i + 1]);
2205                         }
2206                         catch (FormatException)
2207                         {
2208                             Console.WriteLine("cafex : argument for -w option is not a valid number and will be ignored.");
2209                         }
2210 
2211                         uint new_value = prev_value | arg_value;
2212                         PPC_OS_FLAGS.value = new_value.ToString();
2213                         ++i;
2214                         break;
2215                     }
2216 
2217                     case "-a":
2218                     {
2219                         if (!ArgumentChecks.ArgumentExists(args, i + 1))
2220                         {
2221                             run_usage();
2222                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2223                         }
2224 
2225                         DASH_A_ARGS.value = args[i + 1];
2226                         ++i;
2227                         break;
2228                     }
2229 
2230                     case "-o":
2231                     {
2232                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2233                         {
2234                             run_usage();
2235                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2236                         }
2237                         if (String.IsNullOrEmpty(args[i + 1]))
2238                         {
2239                             Console.WriteLine("WARNING: value for -o was null or empty, so it will be treated as 0.");
2240                             CAFERUN_COLDBOOT_OS_VERSION.value = "0x0000000000000000";
2241                         }
2242                         else
2243                         {
2244                             CAFERUN_COLDBOOT_OS_VERSION.value = args[i + 1];
2245                         }
2246                         ++i;
2247                         break;
2248                     }
2249 
2250                     case "-b":
2251                     {
2252                         CAFERUN_COLDBOOT_OS_VERSION.value = "0x00050010100080" + CAFERUN_OS_MAJOR_VERSION.value;
2253                         break;
2254                     }
2255 
2256                     case "-C":
2257                     {
2258                         CAFERUN_COLDBOOT_OS_VERSION.value = "0x00050010100040FE";
2259                         break;
2260                     }
2261 
2262                     case "-u":
2263                     {
2264                         CAFERUN_COLDBOOT_OS_VERSION.value = "0x000500101000C0" + CAFERUN_OS_MAJOR_VERSION.value;
2265                         break;
2266                     }
2267 
2268                     case "-n":
2269                     {
2270                         uint prev_value = HexHandler.GetNumberFromString(PPC_OS_FLAGS.value);
2271                         uint new_value = prev_value | 0x02000;
2272                         PPC_OS_FLAGS.value = new_value.ToString();
2273                         break;
2274                     }
2275 
2276                     case "-i":
2277                     {
2278                         uint prev_value = HexHandler.GetNumberFromString(DEBUG_FLAGS.value);
2279                         uint new_value = prev_value | 16;
2280                         DEBUG_FLAGS.value = new_value.ToString();
2281                         break;
2282                     }
2283 
2284                     case "-R":
2285                     {
2286                         uint prev_value = HexHandler.GetNumberFromString(DEBUG_FLAGS.value);
2287                         uint new_value = prev_value | 32;
2288                         DEBUG_FLAGS.value = new_value.ToString();
2289                         break;
2290                     }
2291 
2292                     case "-j":
2293                     {
2294                         uint prev_value = HexHandler.GetNumberFromString(DEBUG_FLAGS.value);
2295                         uint new_value = prev_value | 64;
2296                         DEBUG_FLAGS.value = new_value.ToString();
2297                         break;
2298                     }
2299 
2300                     case "-q":
2301                     {
2302                         CAFE_SYSLOG_LEVEL.value = "0";
2303                         break;
2304                     }
2305 
2306                     case "-v":
2307                     {
2308                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2309                         {
2310                             run_usage();
2311                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2312                         }
2313                         CAFE_SYSLOG_LEVEL.value = args[i + 1];
2314 
2315                         int sysloglvl = 0;
2316                         if (int.TryParse(CAFE_SYSLOG_LEVEL.value, out sysloglvl))
2317                         {
2318                             sysloglvl &= 7;
2319                             CAFE_SYSLOG_LEVEL.value = sysloglvl.ToString();
2320                         }
2321                         else
2322                         {
2323                             Console.WriteLine("Unable to convert CAFE_SYSLOG_LEVEL to integer.");
2324                             return new CafeXReturn(CAFEX_ERROR.SYSLOG_LEVEL_SET_FAILED);
2325                         }
2326 
2327                         ++i;
2328                         break;
2329                     }
2330 
2331                     case "-e":
2332                     {
2333                         if (!ArgumentChecks.ArgumentExists(args, i + 1))
2334                         {
2335                             run_usage();
2336                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2337                         }
2338 
2339                         if (args[i + 1].StartsWith("mcp"))
2340                         {
2341                             if (args[i + 1].Length < 4)
2342                             {
2343                                 return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2344                             }
2345 
2346                             string new_val = args[i + 1].Substring(4);
2347                             MCP_INFO_OPTION.value = new_val;
2348                             if (new_val.StartsWith("launch_hint"))
2349                             {
2350                                 if (new_val.Length < 12)
2351                                 {
2352                                     return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2353                                 }
2354 
2355                                 MCP_LAUNCH_HINT.value = new_val.Substring(12);
2356 
2357                                 // Check if user wants to launch from somewhere else than the wumad
2358                                 if (isWumadExecution && command != "on" && string.Compare(MCP_LAUNCH_HINT.value, "odd", true) != 0)
2359                                 {
2360                                     Console.WriteLine("WARNING: overriding launch hint for wumad with " + MCP_LAUNCH_HINT.value);
2361                                 }
2362                             }
2363                         }
2364                         else if (args[i + 1] == "nopcfs")
2365                         {
2366                             Console.WriteLine("cafex run: Emulating PCFS Headless Mode.");
2367                             PCFS_HEADLESS_EMUL.value = "-pcfsdisable";
2368                         }
2369                         else if (args[i + 1] == "noFFIO")
2370                         {
2371                             // This is the designation for PCFSServer to disable Fast File IO
2372                             Console.WriteLine("cafex run: Disabling PCFS Fast File IO.");
2373                             PCFSSERVER_PARAMETERS.AddToVar("-noFFIO", ' ');
2374                         }
2375                         else if (args[i + 1] == "noCSR")
2376                         {
2377                             // This is the designation for PCFSServer to disable cafe from using the combined send+recv in MION
2378                             Console.WriteLine("cafex run: Disabling MION send/recv support.");
2379                             PCFSSERVER_PARAMETERS.AddToVar("-noCSR", ' ');
2380                         }
2381                         else if (args[i + 1] == "sdioasdbgr")
2382                         {
2383                             // make sure to change the port for SDIO from 7977 to 6002
2384                             USE_EXI_AS_DEBUG_CHANNEL.value = "0";
2385                         }
2386                         else if (args[i + 1].ToLowerInvariant().StartsWith("ejectstate"))
2387                         {
2388                             // Set the MION eject state (in or out) before launching
2389                             if (args[i + 1].Length < 11)
2390                             {
2391                                 return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2392                             }
2393 
2394                             EJECT_STATE.value = args[i + 1].Substring(11);
2395                             if (EJECT_STATE.value != "in" && EJECT_STATE.value != "out")
2396                             {
2397                                 Console.WriteLine("cafex: Invalid eject state parameter '{0}'!  Please specify 'in' or 'out'.", EJECT_STATE.value);
2398                                 return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2399                             }
2400                         }
2401                         else if (args[i + 1].ToLowerInvariant().StartsWith("wumad"))
2402                         {
2403                             if (args[i + 1].Length < 6)
2404                             {
2405                                 return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2406                             }
2407 
2408                             CAFE_WUMAD.value = PathConverter.Windowsify(args[i + 1].Substring(6));
2409 
2410                             // Check to make sure CAFE_WUMAD.value isn't empty
2411                             //
2412                             if(String.IsNullOrEmpty(CAFE_WUMAD.value))
2413                             {
2414                                 Console.WriteLine("Invalid WUMAD argument!");
2415                                 return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2416                             }
2417 
2418                             BRIDGE_PARAMETERS.AddToVar("-sata", ' ');
2419                             BRIDGE_PARAMETERS_WITH_E.AddToVar("-e sata", ' ');
2420                             CAFE_RUN_FORCERESTART.value = "1";
2421                             isWumadExecution = true;
2422 
2423                             // Force launching the wumad from ODD (if user didn't specify a launch hint, or cafex on)
2424                             if (command != "on")
2425                             {
2426                                 if (string.IsNullOrEmpty(MCP_LAUNCH_HINT.value))
2427                                 {
2428                                     MCP_LAUNCH_HINT.value = "odd";
2429                                 }
2430                                 else if (string.Compare(MCP_LAUNCH_HINT.value, "odd", true) != 0)
2431                                 {
2432                                     Console.WriteLine("WARNING: overriding launch hint for wumad with " + MCP_LAUNCH_HINT.value);
2433                                 }
2434                             }
2435                         }
2436                         else if (args[i + 1].ToLowerInvariant().StartsWith("soft_launch_cafe_elf"))
2437                         {
2438                             // This is the CAFE_ELF of the top level execution
2439                             // that invoked this run to power on.  This is ued
2440                             // to create the disk image.
2441                             CAFERUN_OPTION_CALLED_FROM_CAFEDISCRUN.value = "yes";
2442                             SOFT_LAUNCH_CAFE_ELF.value = args[i + 1].Substring(21);
2443                         }
2444                         else if (args[i + 1].ToLowerInvariant().StartsWith("eco"))
2445                         {
2446                             // eco mode debugging case
2447                             ECO_MODE.value = "1";
2448                             _CCRSYSCFG1.value = "0x20000000";
2449                         }
2450                         else
2451                         {
2452                             BRIDGE_PARAMETERS.AddToVar("-" + args[i + 1], ' ');
2453                             BRIDGE_PARAMETERS_WITH_E.AddToVar("-e " + args[i + 1], ' ');
2454 
2455                             if (args[i + 1].StartsWith("h"))
2456                             {
2457                                 if (args[i + 1].Length < 2)
2458                                 {
2459                                     return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2460                                 }
2461 
2462                                 RUN_FROM_HDD_BANK.value = args[i + 1].Substring(2);
2463 
2464                                 // Check the value of RUN_FROM_HDD_BANK to be sure that it
2465                                 // is a number in the range of 0 - 60 (inclusive)
2466                                 //
2467                                 int hdd_bank = -1;
2468                                 bool result = int.TryParse(RUN_FROM_HDD_BANK.value, out hdd_bank);
2469                                 if (!result)
2470                                 {
2471                                     Console.WriteLine("CafeX: Invalid HDD bank value!");
2472                                     return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2473                                 }
2474                                 else
2475                                 {
2476                                     // Make sure the number is in range
2477                                     //
2478                                     int MinHDDBankNo = 0;
2479                                     int MaxHDDBankNo = 60;
2480                                     if ( (hdd_bank < MinHDDBankNo) || (hdd_bank > MaxHDDBankNo) )
2481                                     {
2482                                         Console.WriteLine("CafeX: Invalid HDD bank value!");
2483                                         return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2484                                     }
2485                                 }
2486                             }
2487                             if (args[i + 1].StartsWith("pcfsport"))
2488                             {
2489                                 if (args[i + 1].Length < 9)
2490                                 {
2491                                     return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2492                                 }
2493 
2494                                 PCFS_OVER_SATA_PORT.value = args[i + 1].Substring(9);
2495                                 USE_PCFS_OVER_SATA.value = "1";
2496                             }
2497                             if (args[i + 1].StartsWith("sdio"))
2498                             {
2499                                 // If the Host Bridge does not support this option, remove it
2500                                 // This option was implemented with HB 3.2.4.4
2501 
2502                                 CAFEX_ERROR hostcheckversion_ret = hostcheckversion();
2503                                 if(hostcheckversion_ret != CAFEX_ERROR.OK)
2504                                     return new CafeXReturn(hostcheckversion_ret);
2505 
2506                                 if (sw_ver_flat < compute_flat_version("3.2.4.4"))
2507                                 {
2508                                     BRIDGE_PARAMETERS.RemoveFromVar("-sdio", ' ');
2509                                     BRIDGE_PARAMETERS_WITH_E.RemoveFromVar("-sdio", ' ');
2510                                 }
2511                             }
2512                         }
2513 
2514                         ++i;
2515                         break;
2516                     }
2517 
2518                     case "-c":
2519                     {
2520                         DEBUGGER.value = "cattoucan";
2521                         break;
2522                     }
2523 
2524                     case "-f":
2525                     {
2526                         CAFESTOP_ONLY_IF_FSEMUL.value = "1";
2527                         break;
2528                     }
2529 
2530                     case "-s":
2531                     {
2532                         CAFERUN_OPTION_SOFT_LAUNCH.value = "1";
2533                         break;
2534                     }
2535 
2536                     case "-y":
2537                     {
2538                         CAFERUN_OPTION_FAST_RELAUNCH.value = "1";
2539                         if (string.IsNullOrEmpty(CAFERUN_OPTION_FASTLAUNCH_RETRIES.value))
2540                         {
2541                             CAFERUN_OPTION_FASTLAUNCH_RETRIES.value = COSDEBUG_FASTLAUNCH_RETRIES.ToString();
2542                         }
2543                         if (string.IsNullOrEmpty(CAFERUN_OPTION_FASTLAUNCH_TIMEOUT.value))
2544                         {
2545                             CAFERUN_OPTION_FASTLAUNCH_TIMEOUT.value = COSDEBUG_FASTLAUNCH_TIMEOUT.ToString();
2546                         }
2547                         if (string.IsNullOrEmpty(CAFERUN_OPTION_FASTLAUNCH_DELAY.value))
2548                         {
2549                             CAFERUN_OPTION_FASTLAUNCH_DELAY.value = COSDEBUG_FASTLAUNCH_DELAY.ToString();
2550                         }
2551                         break;
2552                     }
2553 
2554                     case "-r":
2555                     {
2556                         CAFERUN_OPTION_SOFT_RESTART.value = "1";
2557                         break;
2558                     }
2559 
2560                     case "-F":
2561                     {
2562                         CAFE_RUN_FORCERESTART.value = "1";
2563                         break;
2564                     }
2565 
2566                     case "-K":  //Option to execute kill restart
2567                     {
2568                         // Set the restart option as a backup
2569                         CAFERUN_OPTION_SOFT_RESTART.value = "1";
2570                         g_KOptionSet = true;
2571                         break;
2572                     }
2573 
2574                     case "-L":
2575                     {
2576                         IGNORE_VERSION.value = "1";
2577                         break;
2578                     }
2579 
2580                     case "-t":
2581                     {
2582                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2583                         {
2584                             run_usage();
2585                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2586                         }
2587 
2588                         if ((args[i + 1].Length == 18 && args[i + 1].StartsWith("0x")) || args[i + 1].Length == 16)
2589                         {
2590                             Int64 titleid;
2591                             bool isNumber = false;
2592 
2593                             if (args[i + 1].StartsWith("0x"))
2594                             {
2595 								//strip the 0x
2596                                 isNumber = Int64.TryParse(args[i + 1].Remove(0, 2), System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out titleid);
2597                             }
2598                             else
2599                             {
2600                                 isNumber = Int64.TryParse(args[i + 1], System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out titleid);
2601                             }
2602 
2603                             if (isNumber)
2604                             {
2605                                 CAFERUN_OPTION_MLC_EMU_LAUNCH.value = "1";
2606                                 CAFERUN_OPTION_MLC_EMU_TITLEID.value = (args[i + 1].Length == 16) ? "0x" + args[i + 1] : args[i + 1];
2607                             }
2608                             else
2609                             {
2610                                 Console.WriteLine("Invalid title ID detected!");
2611                                 Console.WriteLine("Please ensure that all characters in the -t argument are hexadecimal.");
2612                                 return new CafeXReturn(CAFEX_ERROR.RUN_BAD_TITLE_ID);
2613                             }
2614                         }
2615                         else
2616                         {
2617                             Console.WriteLine("Title ID has incorrect length.");
2618                             Console.WriteLine("A correct ID is 18 characters plus 0x in the beginning or 16 without 0x.");
2619                             Console.WriteLine("Ex: 0x1234567812345678 or 1234567812345678");
2620                             Console.WriteLine("Found: {0}", args[i + 1]);
2621                             return new CafeXReturn(CAFEX_ERROR.RUN_BAD_TITLE_ID);
2622                         }
2623                         ++i;
2624                         break;
2625                     }
2626 
2627                     case "-l":
2628                     {
2629                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2630                         {
2631                             run_usage();
2632                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2633                         }
2634 
2635                         if (!args[i + 1].EndsWith(".rpl"))
2636                         {
2637                             // CafeX addToVar does not use space as delimiter for the list, so there is no need to replace spaces with "|".
2638                             RPL_DIRS.AddToVar(args[i + 1], DEFAULT_DELIMITER);
2639                         }
2640                         else
2641                         {
2642                             // CafeX addToVar does not use space as delimiter for the list, so there is no need to replace spaces with "|".
2643                             RPL_FILES.AddToVar(args[i + 1], DEFAULT_DELIMITER);
2644                         }
2645                         ++i;
2646                         break;
2647                     }
2648 
2649                     case "-h":
2650                     {
2651                         run_usage();
2652                         return new CafeXReturn(CAFEX_ERROR.OK);
2653                     }
2654 
2655                     case "-H":
2656                     {
2657                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2658                         {
2659                             run_usage();
2660                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2661                         }
2662 
2663                         if (args[i + 1] == "disable")
2664                         {
2665                             HEARTBEAT_DISABLE.value = "0x00020000";
2666                         }
2667                         else if (args[i + 1] == "enable")
2668                         {
2669                             HEARTBEAT_DISABLE.value = "0";
2670                         }
2671                         else
2672                         {
2673                             run_usage();
2674                             return new CafeXReturn(CAFEX_ERROR.RUN_BAD_H_ARGUMENT);
2675                         }
2676                         ++i;
2677                         break;
2678                     }
2679 
2680                     case "-x":
2681                     {
2682                         BRIDGE_PARAMETERS.AddToVar("-sata", ' ');
2683                         break;
2684                     }
2685 
2686                     case "-z":
2687                     {
2688                         if (!Directory.Exists(CAFE_DATA_DIR.value))
2689                         {
2690                             Console.WriteLine("Session data directory is missing and needs to be sync'd!");
2691                             Console.WriteLine("  Please re-run without the '-z' option.");
2692                             return new CafeXReturn(CAFEX_ERROR.RUN_NO_CAFE_DATA_DIR);
2693                         }
2694 
2695                         CAFERUN_OPTION_NO_DATA_SYNC.value = "1";
2696                         break;
2697                     }
2698 
2699                     case "-A":
2700                     {
2701                         Console.WriteLine("*** -A option is deprecated and has no effect. ATFS is now the default file system. ***");
2702                         break;
2703                     }
2704 
2705                     case "-D":
2706                     {
2707                         Console.WriteLine("cafex run failed: -D option is deprecated. DVDFS is now unsupported.");
2708                         run_usage();
2709                         return new CafeXReturn(CAFEX_ERROR.RUN_D_OPTION_USED);
2710                     }
2711 
2712                     case "-M":
2713                     {
2714                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2715                         {
2716                             run_usage();
2717                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2718                         }
2719 
2720                         SYSTEM_MODE.value = args[i + 1];
2721                         ++i;
2722                         break;
2723                     }
2724 
2725                     case "-T":
2726                     {
2727                         // Check the apptype to make sure it is valid
2728                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
2729                         {
2730                             run_usage();
2731                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2732                         }
2733 
2734                         CAFERUN_APP_TYPE.value = args[i + 1];
2735 
2736                         // Make sure the value is valid.
2737                         if (CAFERUN_APP_TYPE.value.StartsWith("0x") || CAFERUN_APP_TYPE.value.StartsWith("0X")) // Check to see if the value is preceded by "0x"
2738                         {
2739                             CAFERUN_APP_TYPE.value.Remove(0, 2);  // Strip off the "0x" or "0X" because we won't need it
2740                         }
2741 
2742                         // Now check the length of the value.  We will only accept values that are 8 digits in length.
2743                         if (CAFERUN_APP_TYPE.value.Length != 8)
2744                         {
2745                             Console.WriteLine("-T value needs to be an 8 digit hex value");
2746                             run_usage();
2747                             return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
2748                         }
2749 
2750                         //  We know that there is no "0x" prefix and that the value is the correct length.
2751                         //  Now we need to check to make sure that it is a hex value between 00000000 - FFFFFFFF
2752                         try
2753                         {
2754                             Convert.ToUInt32(CAFERUN_APP_TYPE.value, 16);
2755                         }
2756                         catch ( Exception )
2757                         {
2758                             Console.WriteLine("AppType is not in Hex format");
2759                         }
2760 
2761                         fAppTypeDefined = true;
2762                         ++i;
2763 
2764                         break;
2765                     }
2766 
2767                     case "-N":
2768                     {
2769                         SKIP_OS_CHECK.value = "1";
2770                         break;
2771                     }
2772 
2773                     default:
2774                     {
2775                         Console.WriteLine("cafex run failed: invalid option: " + args[i]);
2776                         run_usage();
2777                         return new CafeXReturn(CAFEX_ERROR.RUN_INVALID_OPTION);
2778                     }
2779                 }
2780             }
2781 
2782             #endregion
2783 #if TIMER
2784             CafeXSetupTime.Report();
2785             Log.WriteLine("End of arguments");
2786 #endif
2787             // Check if we need to display the HBM warning. See bugzilla 11537 for more details.
2788             if (CAFE_BOOT_MODE.value == "PCFS")
2789             {
2790                 // These paths are where HBM is located.
2791                 if (!File.Exists(Path.Combine(CAFE_MLC_DIR.value, @"sys\title\00050030\1001000A\code\app.xml")) ||
2792                     !File.Exists(Path.Combine(CAFE_MLC_DIR.value, @"sys\title\00050030\1001010A\code\app.xml")) ||
2793                     !File.Exists(Path.Combine(CAFE_MLC_DIR.value, @"sys\title\00050030\1001020A\code\app.xml")))
2794                 {
2795                     Console.WriteLine(string.Concat("WARNING: Some system applications on the system might be missing. ",
2796                         "If the system fails to boot, please reinstall the SDK to restore the missing system applications and run cafeupdate."));
2797                 }
2798             }
2799 
2800             if (!(SKIP_OS_CHECK.value == "1") && Convert.ToInt32(RUN_FROM_HDD_BANK.value) > -1 &&
2801                 command == "discrun" && CAFERUN_OPTION_MLC_EMU_LAUNCH.value == "1")
2802             {
2803                 //Check the value on MION to see if we have an OS mismatch when booting from the HDD
2804                 int mion_os_ver = Convert.ToInt32(mionps.Run(BRIDGE_CURRENT_IP_ADDRESS.value + " " + (Convert.ToInt32(RUN_FROM_HDD_BANK.value) + 100)));
2805 
2806                 // 2 is the DEBUG OS on MION, 1 is NDEBUG
2807                 if (CAFERUN_COLDBOOT_OS_VERSION.value == "0x000500101000800A" && mion_os_ver != 2)
2808                 {
2809                     Console.WriteLine("ERROR: Uploaded title's OS version does not match command line arguments!");
2810                     Console.WriteLine("ERROR: Please omit \"-b\" on the command line.");
2811                     Console.WriteLine("If you uploaded the title using a HostBridge prior to 3.2.6.0, please install HostBridge 3.2.6.0 or later, re-upload the image, and try again.");
2812                     Console.WriteLine("If you want to skip this check, specify \"-N\" on the command line, but be warned that Cafe may return an error!");
2813                     return new CafeXReturn(CAFEX_ERROR.UPLOADED_IMAGE_OS_MISMATCH);
2814                 }
2815                 else if (CAFERUN_COLDBOOT_OS_VERSION.value == "0x000500101000400A" && mion_os_ver != 1)
2816                 {
2817                     Console.WriteLine("ERROR: Uploaded title's OS version does not match command line arguments!");
2818                     Console.WriteLine("ERROR: Please specify \"-b\" on the command line.");
2819                     Console.WriteLine("If you uploaded the title using a HostBridge prior to 3.2.6.0, please install HostBridge 3.2.6.0 or later, re-upload the image, and try again.");
2820                     Console.WriteLine("If you want to skip this check, specify \"-N\" on the command line, but be warned that Cafe may return an error!");
2821                     return new CafeXReturn(CAFEX_ERROR.UPLOADED_IMAGE_OS_MISMATCH);
2822                 }
2823             }
2824             //If MULTI is running make sure KILL_RESTART is enabled
2825             if (DEBUGGER.value == "multi" && CAFE_LAUNCH_DEBUG.value == "0"
2826                 && ((CAFERUN_DISABLE_KILL_RESTART.value == null) || (CAFERUN_DISABLE_KILL_RESTART.value == "0"))
2827                 && ((g_gArgValue == 1) || (CAFERUN_OPTION_SOFT_RESTART.value == "1")))
2828             {
2829                 CAFERUN_OPTION_KILL_RESTART.value = "1";
2830             }
2831             else
2832             {
2833                 CAFERUN_OPTION_KILL_RESTART.value = "0";
2834             }
2835 
2836             //This is a hack to make sure that killrestart happens from the console instead of multi
2837             if (g_KOptionSet)
2838             {
2839                 CAFERUN_OPTION_KILL_RESTART.value = "1";
2840                 g_gArgValue = 1;
2841             }
2842 
2843             // Wumad override: if "-e sata" was not provided and "-e wumad" was, sata bridge parameters should be added.
2844             if (!string.IsNullOrEmpty(CAFE_WUMAD.value) &&
2845                 (string.IsNullOrEmpty(BRIDGE_PARAMETERS.value) || !BRIDGE_PARAMETERS.value.Contains("-sata")) &&
2846                 (string.IsNullOrEmpty(BRIDGE_PARAMETERS_WITH_E.value) || !BRIDGE_PARAMETERS_WITH_E.value.Contains("-e sata")))
2847             {
2848                 BRIDGE_PARAMETERS.AddToVar("-sata", ' ');
2849                 BRIDGE_PARAMETERS_WITH_E.AddToVar("-e sata", ' ');
2850             }
2851 
2852             // Remove arguments before the .rpx
2853             string[] new_args = new string[args.Length - rpx_index];
2854             Array.Copy(args, rpx_index, new_args, 0, new_args.Length);
2855             args = new_args;
2856 
2857             //if (args.Length == 0)
2858             //{
2859             //    Console.WriteLine("cafex run failed: No arguments specified.");
2860             //    run_usage();
2861             //    return new CafeXReturn(CAFEX_ERROR.RUN_NO_ARGUMENTS);
2862             //}
2863 
2864 			readSDKFromMion();
2865             string catdev_sdk_ver = SDK_MAJ_VER.value + "." + SDK_MIN_VER.value + "." + SDK_MIC_VER.value;
2866             string sdk_ver = SDK_VER.value;
2867             if (catdev_sdk_ver != SDK_VER.value)
2868             {
2869                 Console.WriteLine("The CAT-DEV SDK version is not the same as the SDK you are running.");
2870                 Console.WriteLine("SDK Version: " + sdk_ver + " CAT-DEV SDK Version: " + catdev_sdk_ver);
2871                 Console.WriteLine("Please run cafeupdate to get in sync.");
2872             }
2873             if (PCFS_OVER_SATA_PORT.value == null)
2874             {
2875                 if (USE_PCFS_OVER_SATA.value == "1")
2876                 {
2877                     PCFS_OVER_SATA_PORT.value = SESSION_PCFS_SATA_PORT.value;
2878                     BRIDGE_PARAMETERS.AddToVar("-pcfsport:" + SESSION_PCFS_SATA_PORT.value, ' ');
2879 
2880                     Console.WriteLine("cafex run: using PCFS over SATA on port " + PCFS_OVER_SATA_PORT.value);
2881                 }
2882                 else
2883                 {
2884                     Console.WriteLine("cafex run: not using PCFS over SATA");
2885                 }
2886             }
2887 
2888             if (PCFS_OVER_SATA_PORT.value != null)
2889             {
2890                 PCFSSERVER_PARAMETERS.AddToVar("-c " + PCFS_OVER_SATA_PORT.value, ' ');
2891             }
2892             else
2893             {
2894                 Console.WriteLine("cafex run: PCFS_OVER_SATA_PORT is not set.");
2895             }
2896 
2897             if (PCFSSERVER_PARAMETERS.value != null)
2898             {
2899                 Console.WriteLine("cafex run: PCFSServer parameters " + PCFSSERVER_PARAMETERS.value);
2900             }
2901 
2902             if (BRIDGE_PARAMETERS.value == null || !BRIDGE_PARAMETERS.value.Contains("-h"))
2903             {
2904                 if (BRIDGE_PARAMETERS.value == null || !BRIDGE_PARAMETERS.value.Contains("-em"))
2905                 {
2906                     BRIDGE_PARAMETERS.AddToVar("-em", ' ');
2907                 }
2908             }
2909 
2910             DISC_EMU_TYPE.value = "hfio";
2911             if (CAFERUN_OPTION_CALLED_FROM_CAFEDISCRUN.value == "yes")
2912             {
2913                 if (RUN_FROM_HDD_BANK.value != null)
2914                 {
2915                     DISC_EMU_TYPE.value = "hdd";
2916                     Console.WriteLine("cafex run: Will launch HDD bank " + RUN_FROM_HDD_BANK.value);
2917                 }
2918                 else if (!string.IsNullOrEmpty(CAFE_WUMAD.value))
2919                 {
2920                     // wumad emulation started from cafediscrun
2921                     DISC_EMU_TYPE.value = "hdd";
2922                 }
2923                 else if (CAFERUN_OPTION_SOFT_LAUNCH.value == "1")
2924                 {
2925                     ALLOW_DISCRUN_IN_SOFTLAUNCH.value = "1";
2926                     DISC_EMU_TYPE.value = "blockemu";
2927                     BRIDGE_PARAMETERS.AddToVar("-em", ' '); //Tell FSEmul to use block emulation explicitly
2928                 }
2929                 else
2930                 {
2931                     DISC_EMU_TYPE.value = "blockemu";
2932 
2933                     if (BRIDGE_PARAMETERS.value == null || !BRIDGE_PARAMETERS.value.Contains("-em"))
2934                     {
2935                         BRIDGE_PARAMETERS.AddToVar("-em", ' ');
2936                     }
2937                 }
2938             }
2939             else if (!string.IsNullOrEmpty(CAFE_WUMAD.value))
2940             {
2941                 // wumad emulation started from caferun
2942                 DISC_EMU_TYPE.value = "hdd";
2943             }
2944             else
2945             {
2946                 // default
2947                 DISC_EMU_TYPE.value = "hfio";
2948                 if (CAFE_BOOT_MODE.value == "NAND")
2949                 {
2950                     if (SYSTEM_MODE.value == "test")
2951                     {
2952                         Console.WriteLine("cafex run failed: Test mode not supported on NAND.");
2953                         return new CafeXReturn(CAFEX_ERROR.RUN_TEST_MODE_WITH_NAND_BOOT);
2954                     }
2955                     Console.WriteLine("cafex run: Will use NAND file system");
2956                 }
2957                 else
2958                 {
2959                     Console.WriteLine("cafex run: Will use PCFS file system emulation");
2960                 }
2961                 if (RUN_FROM_HDD_BANK.value != null)
2962                 {
2963                     Console.WriteLine("cafex run: HDD bank " + RUN_FROM_HDD_BANK.value + " will be attached to odd");
2964                 }
2965             }
2966             Console.WriteLine("cafex run: bridge parameters: " + BRIDGE_PARAMETERS.value);
2967             // Console.WriteLine("cafex run: bridge parameters with -e: " + BRIDGE_PARAMETERS_WITH_E.value);
2968 
2969             long os_version = HexHandler.GetLongNumberFromString(CAFERUN_COLDBOOT_OS_VERSION.value);
2970             CAFERUN_COLDBOOT_OS_VERSION.value = os_version.ToString("X").PadLeft(16, '0');
2971 
2972             if (DEBUGGER.value == "multi" && CAFE_LAUNCH_DEBUG.value == "0"
2973                 && ((CAFERUN_DISABLE_KILL_RESTART.value == null) || (CAFERUN_DISABLE_KILL_RESTART.value == "0"))
2974                 && ((g_gArgValue == 1) || (CAFERUN_OPTION_SOFT_RESTART.value == "1")))
2975             {
2976                 CAFERUN_OPTION_KILL_RESTART.value = "1";
2977             }
2978             else
2979             {
2980                 CAFERUN_OPTION_KILL_RESTART.value = "0";
2981             }
2982 
2983             if(g_KOptionSet)
2984             {
2985                 CAFERUN_OPTION_KILL_RESTART.value = "1";
2986                 g_gArgValue = 1;
2987             }
2988 
2989             HOSTSTOP_RVAL.value = "0";
2990             Process[] fsEmulProcesses = Process.GetProcessesByName("FSEmul");
2991             if ((CAFESTOP_ONLY_IF_FSEMUL.value == "0" || (fsEmulProcesses != null && fsEmulProcesses.Length > 0)) &&
2992                 CAFERUN_OPTION_KILL_RESTART.value == "0")
2993             {
2994                 stop(null, true);
2995                 if (HOSTSTOP_RVAL.value != "0")
2996                 {
2997                     Console.WriteLine("cafex run failed: Please check the device is connected, powered on, and not in use by another host PC.");
2998                     return new CafeXReturn(CAFEX_ERROR.RUN_HOSTSTOP_RVAL_NON_ZERO);
2999                 }
3000             }
3001 #if TIMER
3002             Log.WriteLine("Hostcheckversion start");
3003             CafeXSetupTime.Report();
3004 #endif
3005             ret.error = hostcheckversion();
3006 #if TIMER
3007             Log.WriteLine("Hostcheckversion end");
3008             CafeXSetupTime.Report();
3009 #endif
3010             if (ret.error != CAFEX_ERROR.OK)
3011             {
3012                 return ret;
3013             }
3014 
3015             if (USE_EXI_AS_DEBUG_CHANNEL.value == null || USE_EXI_AS_DEBUG_CHANNEL.value.Equals("0"))
3016             {
3017                 // use SDIO as debugger. Default is EXI
3018                 DEBUG_FLAGS.value = (HexHandler.GetLongNumberFromString(DEBUG_FLAGS.value) | 256).ToString();
3019             }
3020 
3021             uint syslog_level = HexHandler.GetNumberFromString(CAFE_SYSLOG_LEVEL.value);
3022             CAFE_SYSLOG_LEVEL.value = (syslog_level & 7).ToString();
3023             PPC_OS_FLAGS.value = (HexHandler.GetNumberFromString(PPC_OS_FLAGS.value) | HexHandler.GetNumberFromString(HEARTBEAT_DISABLE.value) | HexHandler.GetNumberFromString(DEBUG_FLAGS.value) | (syslog_level << 9)).ToString();
3024             PPC_APP_FLAGS.value = ((HexHandler.GetNumberFromString(PPC_OS_FLAGS.value) & 0x00000e70) | ((HexHandler.GetNumberFromString(PPC_OS_FLAGS.value) >> 1) & 0x80) | ((HexHandler.GetNumberFromString(PPC_OS_FLAGS.value) >> 6) & 0x02) | Convert.ToUInt32(((HexHandler.GetNumberFromString(PPC_OS_FLAGS.value) & 0xf) != 0))).ToString();
3025 
3026             SYSTEM_XML.value = CAFE_SLC_DIR.value + "\\sys\\config\\system.xml";
3027 
3028             if (CAFE_TEMP.value == null)
3029             {
3030                 Console.WriteLine("cafex run failed: CAFE_TEMP environment variable is not set.");
3031                 return new CafeXReturn(CAFEX_ERROR.RUN_NO_TEMP_VAR);
3032             }
3033             else
3034             {
3035                 CAFERUN_WORK_DIR.value = CAFE_TEMP.value + "\\" + SESSION_PATH_PREFIX.value + "caferun";
3036             }
3037             create_directory_if_noexist(CAFERUN_WORK_DIR.value);
3038 
3039             if (SESSION_MANAGER.value == "1")
3040             {
3041                 Console.WriteLine("cafex run: Using CAFE_CONTENT_DIR = " + CAFE_CONTENT_DIR.value);
3042                 if (CAFERUN_OPTION_NO_DATA_SYNC.value == "0" && CAFERUN_OPTION_SOFT_RESTART.value == "0")
3043                 {
3044                     ret.error = syncsession (null);
3045                     if (CAFEX_ERROR.OK != ret.error)
3046                     {
3047                         return ret;
3048                     }
3049                     CAFERUN_OPTION_NO_DATA_SYNC.value = "1";
3050                 }
3051             }
3052             if (CAFERUN_OPTION_SOFT_RESTART.value == "0")
3053             {
3054                 create_directory_if_noexist(CAFE_SLC_DIR.value + "\\sys");
3055                 create_directory_if_noexist(CAFE_MLC_DIR.value);
3056 
3057                 if (args.Length != 0 && args[0] != null)
3058                 {
3059                     if (DISC_EMU_TYPE.value == "hdd")
3060                     {
3061                         Console.WriteLine("cafex run: Specified rpx/elf file is used for setting title id from app.xml only");
3062                     }
3063 
3064                     CAFE_ELF.value = PathConverter.Windowsify(args[0]);
3065                     CAFE_ELF.value = PathConverter.Root(CAFE_ELF.value);
3066 
3067                     if (SESSION_MANAGER.value == "1")
3068                     {
3069                         if (!File.Exists(CAFE_ELF.value))
3070                         {
3071                             Console.WriteLine("cafex run failed: Cannot find rpx application in " + CAFE_ELF.value);
3072                             return new CafeXReturn(CAFEX_ERROR.RUN_RPX_DOESNT_EXIST);
3073                         }
3074 
3075                         TMP_SUB_DIR.value = Path.GetFileNameWithoutExtension(args[0]);
3076                         string CAFE_DATA_TMP_DOS = CAFE_DATA_TMP.value + "\\" + TMP_SUB_DIR.value;
3077                         create_directory_if_noexist(CAFE_DATA_TMP_DOS);
3078 
3079                         CAFE_ELF_SRC_DIR.value = Path.GetDirectoryName(CAFE_ELF.value);
3080 
3081                         if (!string.Equals(CAFE_ELF_SRC_DIR.value, CAFE_DATA_TMP_DOS, StringComparison.InvariantCultureIgnoreCase))
3082                         {
3083                             // Don't sync if we are running from the data/tmp folder as this is most-likely
3084                             // a restart from the Multi debugger.  If not, the files are still ok as they were
3085                             // from a previous sync.
3086                             //
3087                             SYNCTOOL_CFG.value = CAFE_ROOT.value + "\\system\\bin\\tool\\synctool.code.xml";
3088                             SYNCTOOL_LOG.value = CAFE_DATA_TMP.value + "\\synctool.log";
3089                             int SYNCTOOL_RVAL = synctool.sync(SYNCTOOL_CFG.value, CAFE_ELF_SRC_DIR.value, CAFE_DATA_TMP_DOS, SYNCTOOL_LOG.value);
3090                             if (SYNCTOOL_RVAL != 0)
3091                             {
3092                                 Console.WriteLine("                 : Session data sync FAILED with exit code {0}!", SYNCTOOL_RVAL);
3093                                 Console.WriteLine("                 :   See {0} for details.", SYNCTOOL_LOG.value);
3094                                 return new CafeXReturn(CAFEX_ERROR.SYNCTOOL_FAILED);
3095                             }
3096                         }
3097                         CAFE_ELF.value = CAFE_DATA_TMP.value + "\\" + TMP_SUB_DIR.value + "\\" + Path.GetFileName(args[0]);
3098                     }
3099 
3100                     switch (Path.GetExtension(CAFE_ELF.value))
3101                     {
3102                         case ".elf":
3103                             {
3104                                 DEBUG_ELF_FILE.value = CAFE_ELF.value;
3105                                 string rpx = Path.ChangeExtension(CAFE_ELF.value, "rpx");
3106                                 if (File.Exists(rpx))
3107                                 {
3108                                     CAFE_ELF.value = rpx;
3109                                 }
3110                                 break;
3111                             }
3112 
3113                         case ".rpx":
3114                             {
3115                                 if (DEBUG_ELF_FILE.value == null)
3116                                 {
3117                                     string elf = Path.ChangeExtension(CAFE_ELF.value, "elf");
3118                                     if (File.Exists(elf))
3119                                     {
3120                                         DEBUG_ELF_FILE.value = elf;
3121                                     }
3122                                 }
3123                                 break;
3124                             }
3125                     }
3126 
3127                     if (!CAFE_ELF.value.EndsWith(".rpx"))
3128                     {
3129                         Console.WriteLine("cafex run failed: Please provide rpx application as first argument after run_options");
3130                         run_usage();
3131                         return new CafeXReturn(CAFEX_ERROR.RUN_NO_RPX_SPECIFIED);
3132                     }
3133 
3134                     if (!File.Exists(CAFE_ELF.value))
3135                     {
3136                         Console.WriteLine("cafex run failed: Cannot find rpx application in " + CAFE_ELF.value);
3137                         return new CafeXReturn(CAFEX_ERROR.RUN_RPX_DOESNT_EXIST);
3138                     }
3139 
3140                     CAFE_ELF_DIR.value = Path.GetDirectoryName(CAFE_ELF.value);
3141 
3142                     create_directory_if_noexist(CAFE_CONTENT_DIR.value);
3143                     create_directory_if_noexist(CAFE_META_DIR.value);
3144                     create_directory_if_noexist(CAFE_SAVE_DIR.value);
3145 
3146                     CAFE_CODE_DIR.value = CAFE_ELF_DIR.value;
3147 
3148                     APP_XML_FILE.value = CAFE_CODE_DIR.value + "\\app.xml";
3149                     if (!update_app_xml(APP_XML_FILE.value))
3150                     {
3151                         return new CafeXReturn(CAFEX_ERROR.RUN_UPDATE_APP_XML_FAILED);
3152                     }
3153 
3154                     COS_XML_FILE.value = CAFE_CODE_DIR.value + "\\cos.xml";
3155 
3156                     if (!update_cos_xml(COS_XML_FILE.value, PPC_APP_FLAGS.value))
3157                     {
3158                         return new CafeXReturn(CAFEX_ERROR.RUN_UPDATE_COS_XML_FAILED);
3159                     }
3160 
3161                     META_XML_FILE.value = CAFE_META_DIR.value + "\\meta.xml";
3162                     CAFEX_ERROR update_meta_ret = update_meta_xml(META_XML_FILE.value);
3163 
3164                     if (update_meta_ret != CAFEX_ERROR.OK)
3165                     {
3166                         return new CafeXReturn(update_meta_ret);
3167                     }
3168 
3169                     if (!update_arglist(COS_XML_FILE.value, CAFE_ELF.value, args))
3170                     {
3171                         return new CafeXReturn(CAFEX_ERROR.RUN_UPDATE_ARGLIST_FAILED);
3172                     }
3173 
3174                     update_boot_logos(CAFE_META_DIR.value);
3175 
3176                     if (RPL_DIRS.value != null)
3177                     {
3178                         string[] rpl_dirs = RPL_DIRS.value.Split(DEFAULT_DELIMITER);
3179 
3180                         foreach (string s in rpl_dirs)
3181                         {
3182                             string dir = PathConverter.Windowsify(s);
3183                             string[] contained_files = Directory.GetFiles(dir, "*.rpl");
3184                             if (contained_files.Length == 0)
3185                             {
3186                                 Console.WriteLine("cafex run : WARNING - No files found in directory {0}.", dir);
3187                             }
3188                             else
3189                             {
3190                                 foreach (string origin in contained_files)
3191                                 {
3192                                     string destination = CAFE_CODE_DIR.value + "\\" + Path.GetFileName(origin);
3193                                     Console.WriteLine("cafex run: copy {0} to {1}", origin, destination);
3194                                     File.Copy(origin, destination, true);
3195                                 }
3196                             }
3197                         }
3198                     }
3199                     if (RPL_FILES.value != null)
3200                     {
3201                         string[] rpl_files = RPL_FILES.value.Split(DEFAULT_DELIMITER);
3202                         foreach (string s in rpl_files)
3203                         {
3204                             string file = PathConverter.Windowsify(s);
3205                             if (File.Exists(file))
3206                             {
3207                                 string destination = CAFE_CODE_DIR.value + "\\" + Path.GetFileName(s);
3208                                 Console.WriteLine("cafex run: copy {0} to {1}", file, destination);
3209                                 File.Copy(file, destination, true);
3210                             }
3211                         }
3212                     }
3213                 }
3214 
3215                 if (CAFERUN_INS.value == "0")
3216                 {
3217 #if DEBUG
3218                     Log.WriteLine("CAFEX: Writing data to {0}\\previous_launch_info.xml", CAFERUN_WORK_DIR.value);
3219 #endif
3220                     FileStream previous_info_file = new FileStream(CAFERUN_WORK_DIR.value + "\\" + "previous_launch_info.xml", FileMode.Create);
3221                     StreamWriter writer = new StreamWriter(previous_info_file);
3222                     writer.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
3223                     writer.WriteLine("<prev type=\"complex\" access=\"777\">");
3224 
3225                     if (!string.IsNullOrEmpty(CAFERUN_OPTION_MLC_EMU_LAUNCH.value) && CAFERUN_OPTION_MLC_EMU_LAUNCH.value == "1")
3226                     {
3227                         writer.WriteLine("  <emu_tid type=\"string\" length=\"512\">" + CAFERUN_OPTION_MLC_EMU_TITLEID.value + "</emu_tid>");
3228                     }
3229                     else
3230                     {
3231                         writer.WriteLine("  <code_dir type=\"string\" length=\"512\">" + CAFE_CODE_DIR.value + "</code_dir>");
3232                         writer.WriteLine("  <disc_emu type=\"string\" length=\"8\">" + DISC_EMU_TYPE.value + "</disc_emu>");
3233                         writer.WriteLine("  <hdd_bank type=\"string\" length=\"8\">" + RUN_FROM_HDD_BANK.value + "</hdd_bank>");
3234                         writer.WriteLine("  <disc_emu_tid type=\"string\" length=\"8\">" + DISC_EMU_TID.value + "</disc_emu_tid>");
3235                     }
3236                     writer.WriteLine("  <coldboot_os type=\"string\" length=\"8\">" + CAFERUN_COLDBOOT_OS_VERSION.value + "</coldboot_os>");
3237                     writer.WriteLine("  <fast_relaunch type=\"string\" length=\"8\">" + CAFERUN_OPTION_FAST_RELAUNCH.value + "</fast_relaunch>");
3238                     writer.WriteLine("</prev>");
3239                     writer.Flush();
3240                     writer.Close();
3241                 }
3242                 CAFEX_ERROR updateResult = update_system_xml(SYSTEM_XML.value, PPC_OS_FLAGS.value, SYSTEM_MODE.value, MCP_LAUNCH_HINT.value);
3243                 if (updateResult != CAFEX_ERROR.OK)
3244                 {
3245                     return new CafeXReturn(updateResult);
3246                 }
3247             }
3248             else
3249             {
3250                 if (!File.Exists(SYSTEM_XML.value))
3251                 {
3252                     Console.WriteLine("cafex run failed: Please cafex run an rpx application first");
3253                     return new CafeXReturn(CAFEX_ERROR.RUN_DASH_R_WITH_NO_PREVIOUS_LAUNCH_INFO);
3254                 }
3255 
3256                 string prev_info_file = CAFERUN_WORK_DIR.value + "\\" + "previous_launch_info.xml";
3257 
3258                 CAFERUN_OPTION_FAST_RELAUNCH.value = XmlHandler.GetNodeValue(prev_info_file, "fast_relaunch");
3259                 CAFERUN_OPTION_MLC_EMU_TITLEID.value = XmlHandler.GetNodeValue(prev_info_file, "emu_tid");
3260 
3261                 if (!string.IsNullOrEmpty(CAFERUN_OPTION_MLC_EMU_TITLEID.value))
3262                 {
3263                     CAFERUN_OPTION_MLC_EMU_LAUNCH.value = "1";
3264                     CAFERUN_COLDBOOT_OS_VERSION.value = XmlHandler.GetNodeValue(SYSTEM_XML.value, "default_os_id");
3265                 }
3266                 else
3267                 {
3268                     CAFE_CODE_DIR.value = XmlHandler.GetNodeValue(prev_info_file, "code_dir");
3269                     DISC_EMU_TYPE.value = XmlHandler.GetNodeValue(prev_info_file, "disc_emu");
3270                     RUN_FROM_HDD_BANK.value = XmlHandler.GetNodeValue(prev_info_file, "hdd_bank");
3271                     DISC_EMU_TID.value = XmlHandler.GetNodeValue(prev_info_file, "disc_emu_tid");
3272                     PREV_CAFE_ARGSTR.value = XmlHandler.GetNodeValue(CAFE_CODE_DIR.value + "\\cos.xml", "argstr");
3273 
3274                     // Check "argstr" length to make sure it is less than 4096.
3275                     if (!string.IsNullOrEmpty(PREV_CAFE_ARGSTR.value) && PREV_CAFE_ARGSTR.value.Length > CAFE_ARGSTR_MAX_LENGTH)
3276                     {
3277                         Console.WriteLine("cafex run failed: argstr value in cos.xml is longer than 4096 characters. Please shorten the argstr and retry.");
3278                         return new CafeXReturn(CAFEX_ERROR.RUN_UPDATE_ARGLIST_FAILED);
3279                     }
3280 
3281                     CAFE_ELF.value = CAFE_CODE_DIR.value + "\\" + PREV_CAFE_ARGSTR.value.Split(' ')[0];
3282 
3283                     CAFERUN_COLDBOOT_OS_VERSION.value = XmlHandler.GetNodeValue(prev_info_file, "coldboot_os");
3284 
3285                     if (string.IsNullOrEmpty(CAFERUN_COLDBOOT_OS_VERSION.value))
3286                     {
3287                         CAFERUN_COLDBOOT_OS_VERSION.value = XmlHandler.GetNodeValue(SYSTEM_XML.value, "default_os_id");
3288                     }
3289                     if (DISC_EMU_TYPE.value != "hdd")
3290                     {
3291                         if (!File.Exists(CAFE_ELF.value))
3292                         {
3293                             Console.WriteLine("cafex run failed: Could not find " + CAFE_ELF.value);
3294                             return new CafeXReturn(CAFEX_ERROR.RUN_DASH_R_CANT_FIND_APPLICATION);
3295                         }
3296 
3297                         Console.WriteLine("cafex run: Restarting " + CAFE_ELF.value);
3298                     }
3299                 }
3300             }
3301 
3302             // Set up the title to be run in Eco mode. If we are not in ECO mode make sure to remove the node from system.xml
3303             if (ECO_MODE.value == "1")
3304             {
3305                 string default_title_id;
3306 
3307                 default_title_id = XmlHandler.GetNodeValue(SYSTEM_XML.value, "default_title_id");
3308                 if (XmlHandler.NodeExists(SYSTEM_XML.value, "default_eco_title_id"))
3309                 {
3310                     XmlHandler.UpdateNodeValue(SYSTEM_XML.value, "default_eco_title_id", default_title_id);
3311                 }
3312                 else
3313                 {
3314                     XmlHandler.AddNode(SYSTEM_XML.value, "default_eco_title_id", default_title_id, new string[4] { "type", "hexBinary", "length", "8" });
3315                 }
3316             }
3317             else
3318             {
3319                 if (XmlHandler.NodeExists(SYSTEM_XML.value, "default_eco_title_id"))
3320                 {
3321                     XmlHandler.RemoveNode(SYSTEM_XML.value, "default_eco_title_id");
3322                 }
3323             }
3324 
3325             if (CAFE_BOOT_MODE.value == "PCFS")
3326             {
3327                 string os_directory = CAFE_SLC_DIR.value + "\\sys\\title\\" + CAFERUN_COLDBOOT_OS_VERSION.value.Substring(0,8) + "\\" + CAFERUN_COLDBOOT_OS_VERSION.value.Substring(8,8) + "\\code";
3328                 if (!Directory.Exists(os_directory))
3329                 {
3330                     Console.WriteLine("cafex run failed: Cannot find OS in " + os_directory);
3331                     return new CafeXReturn(CAFEX_ERROR.RUN_CANT_FIND_OS_DIRECTORY);
3332                 }
3333 
3334                 string[] files = Directory.GetFiles(os_directory);
3335                 bool found_rpl = false;
3336                 foreach (string s in files)
3337                 {
3338                     if (s.EndsWith(".rpl"))
3339                     {
3340                         found_rpl = true;
3341                         break;
3342                     }
3343                 }
3344 
3345                 if (!found_rpl)
3346                 {
3347                     CAFERUN_OS_VERSION_PARTIAL_UNIQUE_ID.value = (HexHandler.GetLongNumberFromString("0x" + CAFERUN_COLDBOOT_OS_VERSION.value) >> 8 & 0xff).ToString();
3348 
3349                     uint value = HexHandler.GetNumberFromString(CAFERUN_OS_VERSION_PARTIAL_UNIQUE_ID.value);
3350                     if (value >= 192)
3351                     {
3352                         Console.WriteLine("cafex run failed: Please build FDEBUG os version " + CAFERUN_COLDBOOT_OS_VERSION.value);
3353                     }
3354                     else if (value >= 128)
3355                     {
3356                         Console.WriteLine("cafex run failed: Please build DEBUG os version " + CAFERUN_COLDBOOT_OS_VERSION.value);
3357                         Console.WriteLine("  or do not use \"cafex run -b\" to use NDEBUG version");
3358                     }
3359                     else if (value >= 64)
3360                     {
3361                         Console.WriteLine("cafex run failed: Please build NDEBUG os version " + CAFERUN_COLDBOOT_OS_VERSION.value);
3362                         Console.WriteLine("  or use \"cafex run -b\" to use the DEBUG version");
3363                     }
3364                     else if ((HexHandler.GetLongNumberFromString("0x" + CAFERUN_COLDBOOT_OS_VERSION.value) & 0xFF) == 0xFE)
3365                     {
3366                         Console.WriteLine("cafex run failed: Please build OS_SECURITY_LEVEL os version " + CAFERUN_COLDBOOT_OS_VERSION.value);
3367                     }
3368                     else
3369                     {
3370                         Console.WriteLine("cafex run failed: Non-standard titleId for os version " + CAFERUN_COLDBOOT_OS_VERSION.value);
3371                     }
3372 
3373                     return new CafeXReturn(CAFEX_ERROR.RUN_OS_NOT_PRESENT);
3374                 }
3375             }
3376 
3377             if (!string.IsNullOrEmpty(EJECT_STATE.value))
3378             {
3379                 int returnVal = mionurl.Run(BRIDGE_CURRENT_IP_ADDRESS.value + " /mion/status.cgi operation=eject disc=" + EJECT_STATE.value);
3380                 if (returnVal != 0)
3381                 {
3382                     Console.WriteLine("cafex run: Set disc eject state:'{0}' failed={1}!", EJECT_STATE.value, returnVal);
3383                     Console.WriteLine("           Continuing execution, Ignoring ejectstate");
3384                 }
3385                 else
3386                 {
3387                     Console.WriteLine("cafex run: Set disc eject state: '{0}' succeeded.", EJECT_STATE.value);
3388                 }
3389             }
3390 
3391             if (PCFS_SRV_LOG_DIR.value == null)
3392             {
3393                 PCFS_SRV_LOG_OUTPUT.value = "/dev/null";
3394             }
3395             else
3396             {
3397                 PCFS_LOG_TIMESTAMP.value = DateTime.Now.ToString("HHmmss");
3398                 PCFS_SRV_LOG_OUTPUT.value = PCFS_SRV_LOG_DIR.value + "\\" + SESSION_PATH_PREFIX.value + "pcfs_" + PCFS_LOG_TIMESTAMP.value + ".txt";
3399                 PCFS_SRV_LOG_OUTPUT.value = PathConverter.Windowsify(PCFS_SRV_LOG_OUTPUT.value);
3400                 Console.WriteLine("PCFS output logged to " + PCFS_SRV_LOG_OUTPUT.value);
3401             }
3402 
3403             if (DISC_EMU_TYPE.value == "hdd" ||
3404                 ((!string.IsNullOrEmpty(CAFE_ELF.value)) && CAFE_ELF.value.EndsWith(".rpx")))
3405             {
3406                 if (DISC_EMU_TYPE.value == "hfio")
3407                 {
3408                     MAPDIR_MLC.value = CAFE_MLC_DIR.value + "/";
3409                     MAPDIR_SLC.value = CAFE_SLC_DIR.value + "/";
3410                     MAPDIR_CODE.value = CAFE_CODE_DIR.value + "/";
3411                     MAPDIR_META.value = CAFE_META_DIR.value + "/";
3412                     MAPDIR_CONTENT.value = CAFE_CONTENT_DIR.value + "/";
3413                     MAPDIR_SAVE.value = CAFE_SAVE_DIR.value + "/";
3414 
3415                     PCFS_DIR_MAPPING.value = "-m /%MLC_EMU_DIR/ \"" + MAPDIR_MLC.value + "\"" +
3416                                              " -m /%SLC_EMU_DIR/ \"" + MAPDIR_SLC.value + "\"" +
3417                                              " -m /%DISC_EMU_DIR/code/ \"" + MAPDIR_CODE.value + "\"" +
3418                                              " -m /%DISC_EMU_DIR/meta/ \"" + MAPDIR_META.value + "\"" +
3419                                              " -m /%DISC_EMU_DIR/content/ \"" + MAPDIR_CONTENT.value + "\"" +
3420                                              " -m /%DISC_EMU_DIR/save/ \"" + MAPDIR_SAVE.value + "\"";
3421                 }
3422                 else
3423                 {
3424                     MAPDIR_MLC.value = CAFE_MLC_DIR.value + "/";
3425                     MAPDIR_SLC.value = CAFE_SLC_DIR.value + "/";
3426                     MAPDIR_SAVE.value = CAFE_SAVE_DIR.value + "/";
3427 
3428                     PCFS_DIR_MAPPING.value = "-m /%MLC_EMU_DIR/ \"" + MAPDIR_MLC.value + "\"" +
3429                                              " -m /%SLC_EMU_DIR/ \"" + MAPDIR_SLC.value + "\"" +
3430                                              " -m /%SAVE_EMU_DIR/ \"" + MAPDIR_SAVE.value + "\"";
3431                 }
3432             }
3433             else if (CAFERUN_OPTION_MLC_EMU_LAUNCH.value == "1")
3434             {
3435                 MAPDIR_MLC.value = CAFE_MLC_DIR.value + "/";
3436                 MAPDIR_SLC.value = CAFE_SLC_DIR.value + "/";
3437 
3438                 PCFS_DIR_MAPPING.value = "-m /%MLC_EMU_DIR/ \"" + MAPDIR_MLC.value + "\"" +
3439                                          " -m /%SLC_EMU_DIR/ \"" + MAPDIR_SLC.value + "\"";
3440             }
3441             else
3442             {
3443                 MAPDIR_MLC.value = CAFE_MLC_DIR.value + "/";
3444                 MAPDIR_SLC.value = CAFE_SLC_DIR.value + "/";
3445 
3446                 PCFS_DIR_MAPPING.value = "-m /%MLC_EMU_DIR/ \"" + MAPDIR_MLC.value + "\"" +
3447                                          " -m /%SLC_EMU_DIR/ \"" + MAPDIR_SLC.value + "\"";
3448             }
3449 
3450             ELF_NEST_OPT.value="";
3451             ELF_NEST_VALUE.value = "";
3452             if (ALLOW_DISCRUN_IN_SOFTLAUNCH.value == "1")
3453             {
3454                 // the DLF will not be used now - but it has to be made now,
3455                 // as this is the point where all input environment variables are set correctly
3456                 // for cafedevrun.sh to run
3457                 bootrun(new List<string>() {"-makedlf"} , fAppTypeDefined);
3458                 if (string.IsNullOrEmpty(BRIDGE_PARAMETERS_WITH_E.value) ||
3459                     !BRIDGE_PARAMETERS_WITH_E.value.Contains("soft_launch_cafe_elf"))
3460                 {
3461                     if (!string.IsNullOrEmpty(CAFE_ELF.value))
3462                     {
3463                         // we didn't get the ELF name from above. So we must to decide what it is.
3464                         ELF_NEST_OPT.value = "-e";
3465                         ELF_NEST_VALUE.value = "soft_launch_cafe_elf:" + CAFE_ELF.value;
3466 
3467                         // Since there is no way to communicate new DLF contents into an existing FSEmul,
3468                         // we need a forceful restart for this case - even though it is softlaunch
3469                         CAFE_RUN_FORCERESTART.value = "1";
3470                     }
3471                 }
3472             }
3473 
3474             // Bug 9826: Watch for magic token from IOS signifying crash
3475             if (Environment.GetEnvironmentVariable("CAFERUN_OPTION_IGNORE_CRASH_TOKEN") == null
3476                 || Environment.GetEnvironmentVariable("CAFERUN_OPTION_IGNORE_CRASH_TOKEN").Trim() != "0")
3477             {
3478                 {
3479                     Func<string, bool> callback = StartProcessOnCrashdump;
3480                     cattoucan.AddNotification(IOS_CRASHDUMP_TOKEN, callback);
3481                 }
3482             }
3483 
3484             CAFERUN_INS.value = "1";
3485             CMD_RESULT.value  = "0";
3486             if (CAFERUN_OPTION_SOFT_LAUNCH.value == "1"
3487                 || (CAFERUN_OPTION_KILL_RESTART.value == "1" && ((CAFERUN_DISABLE_KILL_RESTART.value == null) || (CAFERUN_DISABLE_KILL_RESTART.value == "0"))))
3488             {
3489                 CafeBootProgress progress = new CafeBootProgress();
3490                 if (CAFE_RUN_FORCERESTART.value == "1")
3491                 {
3492                     Console.WriteLine("**** FORCE REBOOT ****");
3493                     g_KOptionSet       = false;
3494                     g_gArgValue        = 0;
3495                     CAFERUN_OPTION_KILL_RESTART.value = "0";
3496                     progress.stage = bootCatDev();
3497                     CAFERUN_OPTION_SOFT_LAUNCH.value = "1";
3498                 }
3499                 else if (CAFERUN_OPTION_KILL_RESTART.value == "1"
3500                     && ((CAFERUN_DISABLE_KILL_RESTART.value == null) || (CAFERUN_DISABLE_KILL_RESTART.value == "0"))
3501                     && ((g_gArgValue == 1) || (CAFERUN_OPTION_SOFT_RESTART.value == "1")))
3502                 {
3503                     //Try executing kill restart operation.
3504                     //COS restarts the current running application/title
3505                     if (Program.CAFE_PROFILE.value != null && Program.CAFE_PROFILE.value == "1")
3506                     {
3507                         CafeXEventtLog.Instance.WriteToEventLog(562, DateTime.Now, EventStatus.BEGIN, EventProcess.CAFEX, "System is doing KILL RESTART");
3508                     }
3509 #if TIMER
3510                     Log.WriteLine("SendKillRestartAndResponse start");
3511                     CafeXSetupTime.Report();
3512 #endif
3513                     g_KOptionSet = cosdebug.SendKillRestartAndResponse(Convert.ToInt32(SESSION_NET_MANAGE_PORT.value),
3514                                                                        COSDEBUG_KILLRESTART_RETRIES,
3515                                                                        COSDEBUG_KILLRESTART_TIMEOUT,
3516                                                                        COSDEBUG_KILLRESTART_DELAY);
3517 #if TIMER
3518                     Log.WriteLine("SendKillRestartAndResponse end");
3519                     CafeXSetupTime.Report();
3520 #endif
3521                     // We're going to cold boot if g_KOptionSet was
3522                     // set to false, clear these values regardless
3523                     CAFERUN_OPTION_KILL_RESTART.value = "0";
3524                     g_gArgValue                       = 0;
3525 
3526                     // Check if we don't want to use softlaunch
3527                     if (!g_KOptionSet && !progress.checkKillRestartSoftlaunch())
3528                     {
3529                         // Boot run if PCFS
3530                         if (CAFE_BOOT_MODE.value == "PCFS" && CAFERUN_OPTION_SOFT_LAUNCH.value != "1")
3531                         {
3532                             ret.error = startBootRun(isWumadExecution, launch, true);
3533                             if (ret.error != CAFEX_ERROR.OK || !launch)
3534                             {
3535                                 return ret;
3536                             }
3537 
3538                             // Causes execution to jump to output
3539                             g_KOptionSet = true;
3540                         }
3541                         else
3542                         {
3543                             // Cold boot to sysconfig when in NAND
3544                             progress.stage = bootCatDev();
3545                             progress.waitForTitle = true;
3546                         }
3547                     }
3548                 }
3549                 else
3550                 {
3551                     // Ensure that the K flag is cleared
3552                     g_KOptionSet = false;
3553                     CAFERUN_OPTION_KILL_RESTART.value = "0";
3554                 }
3555 
3556                 if (CMD_RESULT.value == "0" && !g_KOptionSet)
3557                 {
3558                     for (progress.tries = 0; progress.tries < CAFERUN_RETRY_COUNT; ++progress.tries)
3559                     {
3560                         switch (progress.stage)
3561                         {
3562                             case CafeBootStage.Off:
3563                             case CafeBootStage.ServerSync:
3564 #if DEBUG
3565                                 Log.WriteLine("Iteration #{0} of {1}", progress.tries + 1, CAFERUN_RETRY_COUNT);
3566 #endif
3567                                 PCFS_SYNC_DATE.value = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-ffff");
3568                                 Console.WriteLine("Launching {0} @ sync date [{1}]", Path.GetFileName(CAFE_ELF.value), PCFS_SYNC_DATE.value);
3569 #if TIMER
3570                                 CafeXSetupTime.Report();
3571 #endif
3572                                 CMD_RESULT.value = PCFSServerSync.sync(PCFS_SYNC_DATE.value, CAFE_ELF.value, PCFS_DIR_MAPPING.value).ToString();
3573 #if DEBUG
3574                                 Log.WriteLine("PCFSServerSync process returned '{0}' from execution.", CMD_RESULT.value);
3575 #endif
3576 #if TIMER
3577                                 Log.WriteLine("PCFSServerSync end");
3578                                 CafeXSetupTime.Report();
3579 #endif
3580                                 if (CMD_RESULT.value != "0")
3581                                 {
3582                                     // Return error if we already booted
3583                                     if (progress.Active)
3584                                     {
3585                                         ret.error = CAFEX_ERROR.RUN_PCFSSERVER_SYNC_FAILED;
3586                                     }
3587                                     else if (tryCafeReboot(launch,
3588                                                            isWumadExecution,
3589                                                            progress,
3590                                                            out ret.error))
3591                                     {
3592                                         continue;
3593                                     }
3594 
3595                                     return ret;
3596                                 }
3597 
3598                                 if (CAFERUN_OPTION_FAST_RELAUNCH.value == "1")
3599                                 {
3600                                     progress.checkPower = false;
3601                                     progress.stage = CafeBootStage.SendingFlags;
3602                                     goto case CafeBootStage.SendingFlags;
3603                                 }
3604 
3605                                 cattoucan.BeginBootSync();
3606                                 progress.stage = CafeBootStage.SendingSync1;
3607                                 goto case CafeBootStage.SendingSync1;
3608 
3609                             case CafeBootStage.SendingSync1:
3610                                 // Try an initial sync request
3611                                 if (!trySyncRequest())
3612                                 {
3613                                     /* Sending the request failed
3614                                      * Check the power if we did not cold boot
3615                                      */
3616                                     progress.checkVDD2();
3617 
3618                                     // If we are running, try sending requests
3619                                     if (progress.Active)
3620                                     {
3621                                         int i = 1;
3622                                         for (; i < CAFERUN_RETRY_COUNT; ++i)
3623                                         {
3624                                             if (trySyncRequest())
3625                                             {
3626                                                 // Sending the sync was successful
3627                                                 break;
3628                                             }
3629                                         }
3630 
3631                                         // Check if not successful
3632                                         if (i > CAFERUN_LAST_RETRY)
3633                                         {
3634                                             // Check if this is the initial check
3635                                             if (!progress.checkPower)
3636                                             {
3637                                                 /* This is in a reboot process
3638                                                  * break loop and report error
3639                                                  */
3640                                                 progress.tries = CAFERUN_RETRY_COUNT;
3641                                                 continue;
3642                                             }
3643 
3644                                             // Reboot CAT-DEV
3645                                             progress.stage = CafeBootStage.Off;
3646                                         }
3647                                     }
3648 
3649                                     // Check if we need to reboot CAT-DEV
3650                                     if (!progress.Active)
3651                                     {
3652                                         if (tryCafeReboot(launch,
3653                                                           isWumadExecution,
3654                                                           progress,
3655                                                           out ret.error))
3656                                         {
3657                                             continue;
3658                                         }
3659 
3660                                         return ret;
3661                                     }
3662                                 }
3663 
3664                                 // Sync success, go to next stage
3665                                 progress.checkPower = false;
3666                                 progress.stage = CafeBootStage.WaitingForSync1;
3667                                 goto case CafeBootStage.WaitingForSync1;
3668 
3669                             case CafeBootStage.SendingSync2:
3670                                 if (trySyncRequest())
3671                                 {
3672                                     progress.stage = CafeBootStage.WaitingForSync2;
3673                                     goto case CafeBootStage.WaitingForSync2;
3674                                 }
3675 
3676                                 continue;
3677 
3678                             case CafeBootStage.WaitingForSync1:
3679                             case CafeBootStage.WaitingForSync2:
3680                                 // Wait for devkit message to respond
3681                                 if (!cattoucan.SyncWithBoot(DEVKIT_HELP_RESPONSE_TIMEOUT))
3682                                 {
3683                                     CMD_RESULT.value = "1";
3684                                     continue;
3685                                 }
3686 
3687                                 CMD_RESULT.value = "0";
3688                                 if (progress.stage == CafeBootStage.WaitingForSync2)
3689                                 {
3690                                     cattoucan.FinishSync(!progress.waitForTitle && quiet_mode);
3691                                     progress.stage = CafeBootStage.Booted;
3692                                     break;
3693                                 }
3694 
3695                                 progress.stage = CafeBootStage.SendingFlags;
3696                                 goto case CafeBootStage.SendingFlags;
3697 
3698                             case CafeBootStage.SendingFlags:
3699 #if DEBUG
3700                                 Log.WriteLine("setting cosflags now.");
3701 #endif
3702                                 // Set the COS flags
3703                                 CMD_RESULT.value = set_system_xml_cos_flags(PPC_OS_FLAGS.value).ToString();
3704                                 if (CMD_RESULT.value == "0")
3705                                 {
3706                                     if (CAFERUN_OPTION_FAST_RELAUNCH.value == "1")
3707                                     {
3708                                         progress.stage = CafeBootStage.Booted;
3709                                         break;
3710                                     }
3711 
3712                                     progress.stage = CafeBootStage.SendingSync2;
3713                                     goto case CafeBootStage.SendingSync2;
3714                                 }
3715 
3716                                 cattoucan.FinishSync(true);
3717 
3718                                 // Return error if we already booted
3719                                 if (progress.Active)
3720                                 {
3721                                     ret.error = CAFEX_ERROR.RUN_UPDATE_SYSTEM_XML_FAILED;
3722                                 }
3723                                 else if (tryCafeReboot(launch,
3724                                                        isWumadExecution,
3725                                                        progress,
3726                                                        out ret.error))
3727                                 {
3728                                     continue;
3729                                 }
3730 
3731                                 return ret;
3732                         }
3733 #if DEBUG
3734                         Log.WriteLine(command + " trying softlaunch now.");
3735 #endif
3736                         // discrun support.
3737                         // This is softlaunch, and there is no RPS specified.
3738                         // try to see if we can get it from the user - in case it applies
3739                         if (string.IsNullOrEmpty(DISC_EMU_TID.value))
3740                         {
3741                             if (CAFERUN_OPTION_MLC_EMU_LAUNCH.value == "1")
3742                             {
3743                                 DISC_EMU_TID.value = (!string.IsNullOrEmpty(CAFERUN_OPTION_MLC_EMU_TITLEID.value) && CAFERUN_OPTION_MLC_EMU_TITLEID.value.Length == 16) ?
3744                                     "0x" + CAFERUN_OPTION_MLC_EMU_TITLEID.value :
3745                                     CAFERUN_OPTION_MLC_EMU_TITLEID.value;
3746 
3747                                 Console.WriteLine("HDD emulation: using command line TID {0}", DISC_EMU_TID.value);
3748                             }
3749                             else if (!string.IsNullOrEmpty(CAFE_WUMAD.value) &&
3750                                         !string.IsNullOrEmpty(CAFERUN_WUMAD_TITLE_ID.value))
3751                             {
3752                                 // Check if a WUMAD was provided and see if title id is available
3753                                 DISC_EMU_TID.value = CAFERUN_WUMAD_TITLE_ID.value;
3754                                 Console.WriteLine("HDD WUMAD emulation: using command line TID {0}", DISC_EMU_TID.value);
3755                             }
3756                         }
3757 
3758                         // still not set despite our attempts?
3759                         if (string.IsNullOrEmpty(DISC_EMU_TID.value))
3760                         {
3761                             Console.WriteLine("cafex run failed: Unable to determine title ID, and it was not specified in the command line.");
3762                             return new CafeXReturn(CAFEX_ERROR.RUN_DISCRUN_NAND_UNABLE_TO_FIND_APPLICATION);
3763                         }
3764 
3765                         // this is to phase in adoption smoothly into autotest,
3766                         // avoiding any changes to tests other than cafediscrun.
3767                         // We may disable this check later.
3768                         if (ALLOW_DISCRUN_IN_SOFTLAUNCH.value == "1")
3769                         {
3770                             CMD_RESULT.value = "0";
3771                             if (!string.IsNullOrEmpty(SYSTEM_MODE.value))
3772                             {
3773                                 if (SYSTEM_MODE.value.ToLowerInvariant().Equals("prod"))
3774                                 {
3775                                     Console.WriteLine("Setting mode to 0");
3776                                     devkitmsg.sys_mode_prod();
3777                                 }
3778                                 else if (SYSTEM_MODE.value.ToLowerInvariant().Equals("dev"))
3779                                 {
3780                                     Console.WriteLine("Setting mode to 1");
3781                                     devkitmsg.sys_mode_dev();
3782                                 }
3783                                 else if (SYSTEM_MODE.value.ToLowerInvariant().Equals("test"))
3784                                 {
3785                                     Console.WriteLine("Setting mode to 2");
3786                                     devkitmsg.sys_mode_test();
3787                                 }
3788                             }
3789                         }
3790 
3791                         if (CAFERUN_OPTION_FAST_RELAUNCH.value == "1")
3792                         {
3793 #if false
3794                             string COSDEBUG_TID_HI = CAFERUN_OPTION_MLC_EMU_TITLEID.value.Substring(2, 8);
3795                             string COSDEBUG_TID_LO = CAFERUN_OPTION_MLC_EMU_TITLEID.value.Substring(10, 8);
3796 
3797                             cosdebug.launch_retry(Convert.ToInt32(SESSION_NET_MANAGE_PORT.value),
3798                                                     COSDEBUG_TID_HI, COSDEBUG_TID_LO,
3799                                                     Convert.ToInt32(CAFERUN_OPTION_FASTLAUNCH_RETRIES.value),
3800                                                     Convert.ToInt32(CAFERUN_OPTION_FASTLAUNCH_TIMEOUT.value),
3801                                                     Convert.ToInt32(CAFERUN_OPTION_FASTLAUNCH_DELAY.value));
3802                             if (Program.CAFE_PROFILE.value != null && Program.CAFE_PROFILE.value == "1")
3803                             {
3804                                 CafeXEventtLog.Instance.WriteToEventLog(562, "[" + DateTime.Now.ToString("HH:mm:ss:fff") + "] [BEGIN] [CafeX]" + " System is doing FAST RELAUNCH");
3805                             }
3806 
3807                             if (quiet_mode)
3808                             {
3809                                 // We need to start cattoucan to get our events and syncronize the launch
3810                                 CATTOUCAN_TERM.value = Nintendo.SDSG.CatToucan.Terms.KI_PIREPARE_TITLE_ASYNC;
3811                                 cattoucan.start(true, true, false);
3812                                 cosdebug.stop_retry(COSDEBUG_FASTLAUNCH_TIMEOUT);
3813                             }
3814 #endif
3815 
3816                             if (cosdebug.try_launch(CAFERUN_OPTION_MLC_EMU_TITLEID.value, 2))
3817                             {
3818                                 break;
3819                             }
3820                         }
3821                         else
3822                         {
3823                             if (Program.CAFE_PROFILE.value != null && Program.CAFE_PROFILE.value == "1")
3824                             {
3825                                 CafeXEventtLog.Instance.WriteToEventLog(552, DateTime.Now, EventStatus.BEGIN, EventProcess.CAFEX, "System is doing title soft launch");
3826                             }
3827 
3828                             if (progress.waitForTitle)
3829                             {
3830                                 cattoucan.BeginTitleSoftSync();
3831                             }
3832 
3833                             if (MCP_LAUNCH_HINT.value != null)
3834                             {
3835                                 CMD_RESULT.value = devkitmsg.title_softlaunch_with_hint(CAFERUN_COLDBOOT_OS_VERSION.value, DISC_EMU_TID.value, MCP_LAUNCH_HINT.value, SESSION_LAUNCH_CTRL_PORT.value).ToString();
3836                             }
3837                             else
3838                             {
3839                                 CMD_RESULT.value = devkitmsg.title_softlaunch(CAFERUN_COLDBOOT_OS_VERSION.value, DISC_EMU_TID.value, SESSION_LAUNCH_CTRL_PORT.value).ToString();
3840                             }
3841 
3842                             if (CMD_RESULT.value == "0")
3843                             {
3844                                 if (!progress.waitForTitle || cattoucan.SyncWithTitle(Program.KILLRESTART_SOFTLAUNCH_TIMEOUT, false))
3845                                 {
3846                                     break;
3847                                 }
3848 
3849                                 Console.WriteLine("cafex {0}: Timeout waiting for title launch", command);
3850                             }
3851                         }
3852 
3853                         if (!progress.waitForTitle)
3854                         {
3855                             CMD_RESULT.value = "1";
3856                         }
3857                         else if (!tryCafeReboot(launch,
3858                                                 isWumadExecution,
3859                                                 progress,
3860                                                 out ret.error))
3861                         {
3862                             return ret;
3863                         }
3864                     }
3865                 }
3866 
3867                 if (CMD_RESULT.value != "0")
3868                 {
3869                     cattoucan.FinishSync(true);
3870                     Console.WriteLine("Failed to launch application");
3871                     ret.error = CAFEX_ERROR.RUN_LAUNCH_FAILED;
3872                     return ret;
3873                 }
3874             }
3875             else
3876             {
3877                 if (IsBooting)
3878                 {
3879                     cattoucan.BeginMenuSync();
3880                 }
3881 
3882                 ret.error = startBootRun(isWumadExecution, launch, false);
3883                 if (ret.error != CAFEX_ERROR.OK)
3884                 {
3885                     cattoucan.FinishSync(true);
3886                     return ret;
3887                 }
3888 
3889                 if (IsBooting)
3890                 {
3891                     // We need to make sure system boots successfully
3892                     cattoucan.SyncWithMenu();
3893                     return ret;
3894                 }
3895             }
3896 
3897             ret = connect_serial_or_debugger(quiet_mode);
3898             return ret;
3899         }
3900 
3901         private struct WumadInfo
3902         {
3903             public bool titleFound;
3904             public string titleId;
3905             public string appXml;
3906             public string cosXml;
3907             public string metaXml;
3908         }
3909 
TryGetWumadInfo(string wumadTempDir, ref WumadInfo info)3910         private static CAFEX_ERROR TryGetWumadInfo(string wumadTempDir, ref WumadInfo info)
3911         {
3912             string[] metaFiles = Directory.GetFiles(wumadTempDir, "*metaxml.bin");
3913             string[] appFiles = Directory.GetFiles(wumadTempDir, "*appxml.bin");
3914             string[] cosFiles = Directory.GetFiles(wumadTempDir, "*cosxml.bin");
3915 
3916             // User provided title.
3917             string titleId = string.Empty;
3918             if (!string.IsNullOrEmpty(CAFERUN_WUMAD_TITLE_ID.value))
3919             {
3920                 titleId = CAFERUN_WUMAD_TITLE_ID.value.StartsWith("0x") ? CAFERUN_WUMAD_TITLE_ID.value.Substring(2).ToLowerInvariant() : CAFERUN_WUMAD_TITLE_ID.value.ToLowerInvariant();
3921             }
3922 
3923             info.titleFound = false;
3924             if (metaFiles.Length == 1)
3925             {
3926                 // The wumad has only one title
3927                 string singleTitleId = XmlHandler.GetNodeValue(appFiles[0], "title_id");
3928                 if (string.IsNullOrEmpty(titleId) ||
3929                     titleId.Equals("ffffffffffffffff") ||
3930                     titleId.Equals(singleTitleId) )
3931                 {
3932                     // Empty-> auto discovery *OR*
3933                     // Value-> matches user input
3934                     info.titleFound = true;
3935                     info.titleId = singleTitleId;
3936                     info.metaXml = metaFiles[0];
3937                     info.appXml = appFiles[0];
3938                     info.cosXml = cosFiles[0];
3939                 }
3940                 else
3941                 {
3942                     // We need to respect the title give by the user,
3943                     // but provide a warning that it didn't match.
3944                     if (!IsTitleIdReserved(titleId))
3945                     {
3946 
3947                         Console.WriteLine("cafex bootrun: WARNING: Unable to find title {0} in the wumad.", titleId);
3948                     }
3949 
3950                     return CAFEX_ERROR.RUN_BAD_TITLE_ID;
3951                 }
3952             }
3953             else
3954             {
3955                 // The wumad has multiple files... need to know the title id
3956                 if (string.IsNullOrEmpty(titleId) ||
3957                     titleId.Equals("ffffffffffffffff"))
3958                 {
3959                     Console.WriteLine("cafex bootrun failed: Multiple titles found in wumad. Either RPX or TitleId is required to select the title to run.");
3960                     return CAFEX_ERROR.RUN_TITLE_ID_REQUIRED;
3961                 }
3962 
3963                 // If in NAND/softlaunch mode, we shouldn't validate the title id, since
3964                 // the user may really want to launch a title there is not inside the wumad.
3965                 // However, we should alert the user that the title was not found, and also
3966                 // not search for if we already know it is the sysconfigtool title id.
3967                 if (!IsTitleIdReserved(titleId))
3968                 {
3969                     // Only looking if it's not a system/reserved titleid.
3970                     int targetIndex = 0;
3971 
3972                     for (targetIndex = 0; targetIndex < appFiles.Length; ++targetIndex)
3973                     {
3974                         string wumadTitle = XmlHandler.GetNodeValue(appFiles[targetIndex], "title_id").ToLowerInvariant();
3975                         Console.WriteLine("cafex run : wumad title {0} found and comparing to {1}.", wumadTitle, titleId);
3976                         if (wumadTitle.Equals(titleId))
3977                         {
3978                             info.titleId = titleId;
3979                             info.titleFound = true;
3980                             break;
3981                         }
3982                     }
3983 
3984                     if (!info.titleFound)
3985                     {
3986                         Console.WriteLine("cafex bootrun: WARNING: Unable to find title {0} in the wumad.", titleId);
3987                         return CAFEX_ERROR.RUN_BAD_TITLE_ID;
3988                     }
3989 
3990                     info.metaXml = metaFiles[targetIndex];
3991                     info.appXml = appFiles[targetIndex];
3992                     info.cosXml = cosFiles[targetIndex];
3993                 }
3994             }
3995 
3996             return CAFEX_ERROR.OK;
3997         }
3998 
IsTitleIdReserved(string fullTitleInHex)3999         private static bool IsTitleIdReserved(string fullTitleInHex)
4000         {
4001             // Reserved range:
4002             //0x00000 Through 0x000FF -> 0       <= TID <= 255
4003             //0xF7000 Through 0xF7FFF -> 1011712 <= TID <= 1015807
4004             uint badRangeMaxA = HexHandler.GetNumberFromString("0xff");
4005             uint badRangeMinB = HexHandler.GetNumberFromString("0xf7000");
4006             uint badRangeMaxB = HexHandler.GetNumberFromString("0xf7fff");
4007 
4008             if (string.IsNullOrEmpty(fullTitleInHex))
4009             {
4010                 // Empty title shouldn't be used, so it is reserved!
4011                 return true;
4012             }
4013 
4014             string titleId = fullTitleInHex.StartsWith("0x") ? fullTitleInHex.Substring(2).ToLowerInvariant() : fullTitleInHex.ToLowerInvariant();
4015             // Need to get the following digits of the title: 000500001XXXXX00 The five "X" hex values represent the Unique Id.
4016             string uniqueId = "0x" + titleId.Substring(9, 5);
4017             uint uniqueIdValue = HexHandler.GetNumberFromString(uniqueId);
4018 
4019             if (uniqueIdValue <= badRangeMaxA ||
4020                (uniqueIdValue >= badRangeMinB && uniqueIdValue <= badRangeMaxB))
4021             {
4022                 // is reserved
4023                 return true;
4024             }
4025             else
4026             {
4027                 // is not reserved
4028                 return false;
4029             }
4030 
4031         }
4032         //Script function: bootrun
bootrun(List<string> args, bool fAppTypeDefined)4033         static CAFEX_ERROR bootrun(List<string> args, bool fAppTypeDefined)
4034         {
4035             #if DEBUG
4036                 Log.WriteLine("bootrun started.");
4037             #endif
4038 
4039             int MAKE_DLF_ONLY = 0;
4040             int USE_DLF_ONLY = 0;
4041             string ELF_FILENAME = CAFE_ELF.value;
4042 
4043             if (args != null && args.Count > 0)
4044             {
4045                 // Check parameters
4046                 while (args.Count != 0)
4047                 {
4048                     string OPT = args[0];
4049                     args.RemoveAt(0);
4050                     switch(OPT)
4051                     {
4052                         case "-makedlf":
4053                             // It will make the DLF, but won't use it
4054                             MAKE_DLF_ONLY = 1;
4055                             break;
4056 
4057                         case "-usedlf":
4058                             USE_DLF_ONLY = 1;
4059                             if (args.Count > 0)
4060                             {
4061                                 ELF_FILENAME = args[0];
4062                                 args.RemoveAt(0);
4063                             }
4064                             break;
4065 
4066                     }
4067                 }
4068             }
4069 
4070             CAFERUN_COLDBOOT_OS_VERSION_HI.value = CAFERUN_COLDBOOT_OS_VERSION.value.Substring(0, 8);
4071             CAFERUN_COLDBOOT_OS_VERSION_LO.value = CAFERUN_COLDBOOT_OS_VERSION.value.Substring(8, 8);
4072 
4073             if (CAFERUN_OPTION_SOFT_LAUNCH.value == "1" && MAKE_DLF_ONLY == 0)
4074             {
4075                 if (CAFERUN_OPTION_FAST_RELAUNCH.value == "1")
4076                 {
4077 #if false
4078                     string COSDEBUG_TID_HI = DISC_EMU_TID.value.Substring(0, 8);
4079                     string COSDEBUG_TID_LO = DISC_EMU_TID.value.Substring(8, 8);
4080 
4081                     cosdebug.launch_retry(Convert.ToInt32(SESSION_NET_MANAGE_PORT.value),
4082                                                       COSDEBUG_TID_HI, COSDEBUG_TID_LO,
4083                                                       Convert.ToInt32(CAFERUN_OPTION_FASTLAUNCH_RETRIES.value),
4084                                                       Convert.ToInt32(CAFERUN_OPTION_FASTLAUNCH_TIMEOUT.value),
4085                                                       Convert.ToInt32(CAFERUN_OPTION_FASTLAUNCH_DELAY.value));
4086                     if (quiet_mode)
4087                     {
4088                         // We need to start cattoucan to get our events and syncronize the launch
4089                         CATTOUCAN_TERM.value = Nintendo.SDSG.CatToucan.Terms.KI_PIREPARE_TITLE_ASYNC;
4090                         cattoucan.start(false, false, false);
4091                         cosdebug.stop_retry(COSDEBUG_FASTLAUNCH_TIMEOUT);
4092                     }
4093 #endif
4094 
4095                     if (!cosdebug.try_launch(DISC_EMU_TID.value, 0))
4096                     {
4097                         return CAFEX_ERROR.TITLE_SYNC_FAILED;
4098                     }
4099                 }
4100                 else
4101                 {
4102                     devkitmsg.title_softlaunch(CAFERUN_COLDBOOT_OS_VERSION.value, DISC_EMU_TID.value, SESSION_LAUNCH_CTRL_PORT.value);
4103                 }
4104             }
4105             else
4106             {
4107                 if (CAFE_TEMP.value == null)
4108                 {
4109                     Console.WriteLine("cafex run failed: CAFE_TEMP environment variable is not set.");
4110                     return CAFEX_ERROR.BOOTRUN_NO_TEMP_VAR;
4111                 }
4112                 else
4113                 {
4114                     BOOTRUN_WORK_DIR.value = CAFE_TEMP.value + "\\" + SESSION_PATH_PREFIX.value + "caferun";
4115                     WUMAD_WORK_DIR.value = CAFE_TEMP.value + "\\" + SESSION_PATH_PREFIX.value + "makewumaddlf";
4116                 }
4117                 initialize_work_directory(BOOTRUN_WORK_DIR.value);
4118 
4119                 //FIRMWARE_FILE.value = CAFE_SLC_DIR.value + "\\sys\\title\\" + CAFERUN_COLDBOOT_OS_VERSION_HI.value + "\\" + CAFERUN_COLDBOOT_OS_VERSION_LO.value + "\\code\\fw.img";
4120 
4121                 if (!string.IsNullOrEmpty(BOOTRUN_USE_RECOVERY_IMAGE.value) && BOOTRUN_USE_RECOVERY_IMAGE.value == "1")
4122                 {
4123                     FIRMWARE_FILE.value = string.Concat(CAFE_ROOT.value, "\\system\\bin\\", TOOLCHAIN.value, "\\", PLATFORM.value, "\\boot\\recovery.img");
4124                 }
4125                 else if (CAFE_SECURITY.value == "off")
4126                 {
4127                     FIRMWARE_FILE.value = string.Concat(CAFE_SLC_DIR.value, "\\sys\\title\\", CAFERUN_COLDBOOT_OS_VERSION_HI.value, "\\", CAFERUN_COLDBOOT_OS_VERSION_LO.value, "\\code\\fw.bu.img");
4128                 }
4129                 else
4130                 {
4131                     FIRMWARE_FILE.value = string.Concat(CAFE_SLC_DIR.value, "\\sys\\title\\", CAFERUN_COLDBOOT_OS_VERSION_HI.value, "\\", CAFERUN_COLDBOOT_OS_VERSION_LO.value, "\\code\\fw.img");
4132                 }
4133 
4134                 BOOT_DLF_FILE.value = BOOTRUN_WORK_DIR.value + "\\ppc_boot.dlf";
4135 
4136                 CAFEX_ERROR boot1file_ret = make_boot1_system_file(BOOTRUN_WORK_DIR.value + "\\ppc.bsf");
4137                 if (boot1file_ret != CAFEX_ERROR.OK)
4138                 {
4139                     return boot1file_ret;
4140                 }
4141 
4142                 string diskid = BOOTRUN_WORK_DIR.value + "\\diskid.bin";
4143                 File.Copy(CAFE_ROOT.value + "\\system\\bin\\" + TOOLCHAIN.value + "\\" + PLATFORM.value + "\\boot\\diskid.bin", diskid, true);
4144                 File.SetAttributes(diskid, FileAttributes.Normal);
4145 
4146                 CAFEX_ERROR bootdlf_ret = make_boot_dlf(diskid + "," + BOOTRUN_WORK_DIR.value + "\\ppc.bsf," + FIRMWARE_FILE.value, BOOT_DLF_FILE.value);
4147                 if (bootdlf_ret != CAFEX_ERROR.OK)
4148                 {
4149                     return bootdlf_ret;
4150                 }
4151 
4152                 if (DISC_EMU_TYPE.value == "blockemu")
4153                 {
4154                     if (!string.IsNullOrEmpty(ELF_FILENAME) &&
4155                         ELF_FILENAME.EndsWith(".rpx"))
4156                     {
4157                         if (USE_DLF_ONLY == 0)
4158                         {
4159                             CAFEX_ERROR run_ret = devrun(ELF_FILENAME, null, null, null);
4160                             if (run_ret != CAFEX_ERROR.OK)
4161                             {
4162                                 return run_ret;
4163                             }
4164                         }
4165 
4166                         if (MAKE_DLF_ONLY == 0)
4167                         {
4168                             hostrun(BOOT_DLF_FILE.value + " " + Path.ChangeExtension(ELF_FILENAME, ".dlf"));
4169                         }
4170 
4171                     }
4172                 }
4173                 else // HFIO case & HDD case & WUMAD case
4174                 {
4175                     if (!string.IsNullOrEmpty(CAFE_WUMAD.value))
4176                     {
4177                         // WUMAD case
4178                         // Create the DLF from a WUMAD file.
4179                         string wumadTempName = null;
4180                         string wumadTempDir = null;
4181                         string wumadDlfName = null;
4182 
4183                         if (CAFE_WUMAD.value.ToLower().EndsWith("wumad"))
4184                         {
4185                             // A WUMAD file was passed instead of a directory.
4186                             Console.WriteLine("Creating DLF from WUMAD file...");
4187                             wumadTempName = Path.GetFileNameWithoutExtension(CAFE_WUMAD.value);
4188                             wumadTempDir = Path.Combine(WUMAD_WORK_DIR.value, wumadTempName);
4189                             wumadDlfName = Path.Combine(wumadTempDir, wumadTempName + ".dlf");
4190                         }
4191                         else
4192                         {
4193                             // A directory was passed in.
4194                             wumadTempName = null;
4195                             wumadTempDir = CAFE_WUMAD.value;
4196                             wumadDlfName = Path.Combine(WUMAD_WORK_DIR.value, "extractedWumad.dlf");
4197 
4198                         }
4199 
4200                         if (wumadTempName != null)
4201                         {
4202                             wumadTempName = CAFE_WUMAD.value;
4203                         }
4204 
4205                         Console.WriteLine("wumadName = " + wumadTempName);
4206                         Console.WriteLine("wumadDir  = " + wumadTempDir);
4207                         Console.WriteLine("wumadDlf  = " + wumadDlfName);
4208 
4209                         CAFEX_ERROR wumad_dlf_ret = make_wumad_dlf(wumadTempName, wumadTempDir, wumadDlfName);
4210                         if (wumad_dlf_ret != CAFEX_ERROR.OK)
4211                         {
4212                             return wumad_dlf_ret;
4213                         }
4214 
4215                         WumadInfo info = new WumadInfo();
4216                         CAFEX_ERROR wumadInfoResult = TryGetWumadInfo(wumadTempDir, ref info);
4217                         // If a title id is required because there are more than one in the wumad
4218                         // and none was provided, should stop here.
4219                         if (wumadInfoResult == CAFEX_ERROR.RUN_TITLE_ID_REQUIRED)
4220                         {
4221                             return wumadInfoResult;
4222                         }
4223 
4224                         // We always need to set the titleId, if the function
4225                         // returned one. This allows the data to be available upstream
4226                         // in a sequence of calls involving softlaunch.
4227                         if (info.titleFound)
4228                         {
4229                             CAFERUN_WUMAD_TITLE_ID.value = info.titleId;
4230                         }
4231                         else
4232                         {
4233                             CAFERUN_WUMAD_TITLE_ID.value = string.Empty;
4234                         }
4235 
4236                         // If no RPX was provided, the xmls not been updated.
4237                         // This is a valid assumption because the code in caferun
4238                         // sets all the xmls besed on an RPX provide prior to call
4239                         // bootrun
4240                         if (string.IsNullOrEmpty(ELF_FILENAME) &&
4241                             info.titleFound)
4242                         {
4243                             string contentMetaXml = CAFE_META_DIR.value + "\\meta.xml";
4244                             file_copy_retry(info.metaXml, contentMetaXml, true, 3);
4245 
4246                             // Get the title-id, version, app_type, etc from the WUMAD files
4247                             string title_id = XmlHandler.GetNodeValue(info.appXml, "title_id");
4248                             string title_version = XmlHandler.GetNodeValue(info.appXml, "title_version");
4249                             string os_version = XmlHandler.GetNodeValue(info.appXml, "os_version");
4250                             string app_type = XmlHandler.GetNodeValue(info.appXml, "app_type");
4251                             string app_group_id = XmlHandler.GetNodeValue(info.appXml, "group_id");
4252 
4253                             // Save config to meta.xml
4254                             XmlHandler.UpdateNodeValue(contentMetaXml, "title_id", title_id);
4255                             XmlHandler.UpdateNodeValue(contentMetaXml, "group_id", app_group_id);
4256                             XmlHandler.UpdateNodeValue(contentMetaXml, "title_version", title_version);
4257 
4258                             // Convert the title_id from a string to a number for lookup
4259                             Int64 iTitleID = Convert.ToInt64(title_id, 16);
4260 
4261                             if (fAppTypeDefined)
4262                             {
4263                                 app_type = CAFERUN_APP_TYPE.value;
4264                             }
4265                             else
4266                             {
4267                                 //Look up the App Type using the Title ID
4268                                 string calculated_app_type = FindAppType(iTitleID);
4269                                 if (app_type.CompareTo(calculated_app_type) != 0)
4270                                 {
4271                                     Console.WriteLine("WARNING: Calculated AppType does not match what was in APP.XML");
4272                                     Console.WriteLine("Overwriting with the calculated value for AppType");
4273                                 }
4274                                 app_type = calculated_app_type;
4275                             }
4276 
4277                             // Save config to system.xml
4278                             XmlHandler.UpdateNodeValue(SYSTEM_XML.value, "default_title_id", title_id);
4279                             XmlHandler.UpdateNodeValue(SYSTEM_XML.value, "default_app_type", app_type);
4280                             XmlHandler.UpdateNodeValue(SYSTEM_XML.value, "default_os_id", os_version);
4281                         }
4282 
4283                         // Starts the emulation
4284                         if (MAKE_DLF_ONLY == 0)
4285                         {
4286                             hostrun(BOOT_DLF_FILE.value + " " + wumadDlfName);
4287                         }
4288                     }
4289                     else
4290                     {
4291                         // HFIO and HDD cases
4292                         if (MAKE_DLF_ONLY == 0)
4293                         {
4294                             hostrun(BOOT_DLF_FILE.value);
4295                         }
4296                     }
4297                 }
4298             }
4299 
4300             return CAFEX_ERROR.OK;
4301         }
4302 
4303         //Script function: cafedevrun
devrun(string elf, string MAKE_PATCH, string CAFEMAKEDLF_OPTION, string KIOSK_DEFAULT_DDF)4304         static CAFEX_ERROR devrun(string elf, string MAKE_PATCH, string CAFEMAKEDLF_OPTION, string KIOSK_DEFAULT_DDF)
4305         {
4306             #if DEBUG
4307                 Log.WriteLine("devrun started.");
4308             #endif
4309 
4310             APP_TITLE_ID.value = "0000000000000000";
4311             APP_GROUP_ID.value = "00000000";
4312             APP_TITLE_VERSION.value = "0000";
4313 
4314             if (elf == null)
4315             {
4316                 Console.WriteLine("cafex cafedevrun failed: image file required!");
4317                 return CAFEX_ERROR.CAFEDEVRUN_NO_IMAGE_FILE;
4318             }
4319 
4320             CAFEDEVRUN_FILE.value = elf;
4321             CAFEDEVRUN_EXT.value = Path.GetExtension(elf).Remove(0, 1);
4322             CAFEDEVRUN_NAME.value = Path.GetDirectoryName(elf) + "\\" + Path.GetFileNameWithoutExtension(elf);
4323             CAFEDEVRUN_FILENAME.value = Path.GetFileNameWithoutExtension(elf);
4324             CAFEDEVRUN_DIR.value = Path.GetDirectoryName(elf);
4325 
4326             string GAME_TYPE = null;
4327             if (MAKE_PATCH != null && MAKE_PATCH == "1")
4328             {
4329                 GAME_TYPE = "GP";
4330             }
4331             else
4332             {
4333                 GAME_TYPE = "GM";
4334             }
4335 
4336             // Check temporary directory
4337             CAFEDEVRUN_WORK_DIR.value = CAFEDEVRUN_NAME.value + "_tmp";
4338             create_directory_if_noexist(CAFEDEVRUN_WORK_DIR.value);
4339 
4340             if (INCLUDE_SYSTEM_DIR.value == null)
4341             {
4342                 INCLUDE_SYSTEM_DIR.value = "0";
4343             }
4344 
4345             CAFE_BASEFILE_PATH.value = CAFE_ROOT.value + "\\system\\bin\\tool\\mastering\\resources";
4346             if (string.IsNullOrEmpty(KIOSK_DEFAULT_DDF))
4347             {
4348                 DEFAULT_DDF.value = CAFE_BASEFILE_PATH.value + "\\default.ddf";
4349             }
4350             else
4351             {
4352                 Console.WriteLine("Change default ddf -> " + KIOSK_DEFAULT_DDF);
4353                 DEFAULT_DDF.value = KIOSK_DEFAULT_DDF;
4354             }
4355 
4356             COMMON_DDF_FILE.value = CAFEDEVRUN_WORK_DIR.value + "\\common.ddf";
4357 
4358             string custom_ddf = Path.ChangeExtension(elf, ".ddf");
4359             // Use individual ddf file if exists
4360             if (File.Exists(custom_ddf))
4361             {
4362                 INDIVIDUAL_DDF_FILE.value = custom_ddf;
4363                 // TODO: Need to replace the game type in the custo_ddf file and save it.
4364             }
4365             else
4366             {
4367                 INDIVIDUAL_DDF_FILE.value = "";
4368             }
4369 
4370             APP_XML_FILE.value = CAFEDEVRUN_DIR.value + "\\app.xml";
4371             if (!File.Exists(APP_XML_FILE.value))
4372             {
4373                 Console.WriteLine("cafex cafedevrun failed: Cannot find " + APP_XML_FILE.value);
4374                 return CAFEX_ERROR.CAFEDEVRUN_CANT_FIND_APP_XML;
4375             }
4376 
4377             extract_info_from_app_xml(APP_XML_FILE.value);
4378 
4379             FileStream fs = new FileStream(COMMON_DDF_FILE.value, FileMode.Create);
4380             StreamWriter sw = new StreamWriter(fs);
4381             sw.WriteLine(";");
4382             sw.WriteLine("; " + CAFEDEVRUN_NAME.value + "." + CAFEDEVRUN_EXT.value);
4383             sw.WriteLine(";");
4384             sw.WriteLine("[Input]");
4385             sw.WriteLine("DiscHeaderBaseFileName=\"" + CAFE_BASEFILE_PATH.value + "\\discheader_base.bin\"");
4386             sw.WriteLine("VolumeHeaderBaseFileName=\"" + CAFE_BASEFILE_PATH.value + "\\volheader_base.bin\"");
4387             sw.WriteLine("[Output]");
4388             sw.WriteLine("LayoutFileName=\"" + CAFEDEVRUN_NAME.value + ".dlf\"");
4389             sw.WriteLine("OutputDirectory=\"" + CAFEDEVRUN_DIR.value + "\"");
4390             sw.WriteLine("AppName=\"" + CAFEDEVRUN_FILENAME.value + "\"");
4391             sw.WriteLine("Mode=WU");
4392             sw.WriteLine("[DiscID]");
4393             sw.WriteLine("GameType=" + GAME_TYPE);
4394             sw.WriteLine("TitleId=0x" + APP_TITLE_ID.value);
4395             sw.WriteLine("GroupId=0x" + APP_GROUP_ID.value);
4396             sw.WriteLine("DiskNumber=0");
4397             sw.WriteLine("GameVersion=" + (HexHandler.GetNumberFromString("0x" + APP_TITLE_VERSION.value) / 16).ToString());
4398             sw.WriteLine("[SectionParam]");
4399             sw.WriteLine("\"CONTENT\"=0x" + APP_TITLE_ID.value + ",0x" + APP_GROUP_ID.value + ",0x02");
4400             sw.WriteLine("[PathList]");
4401             sw.WriteLine("CODE_DIR_RPX=\"code\", \"$(CAFE_CODE_DIR)\\" + CAFEDEVRUN_FILENAME.value + ".rpx\"");
4402 
4403             if (INCLUDE_SYSTEM_DIR.value == "1")
4404             {
4405                 sw.WriteLine("[PathList]");
4406                 sw.WriteLine("SYSTEM_DIR=\"sys\", \"$(CAFE_SYSTEM_DIR)\"");
4407             }
4408 
4409             sw.Flush();
4410             sw.Close();
4411 
4412             int cafemakedlf_ret = cafemakedlf.make(DEFAULT_DDF.value, COMMON_DDF_FILE.value, INDIVIDUAL_DDF_FILE.value, CAFEMAKEDLF_OPTION);
4413 
4414             if (cafemakedlf_ret != 0)
4415             {
4416                 return CAFEX_ERROR.CAFEDEVRUN_CAFEMAKEDLF_FAILED;
4417             }
4418 
4419             fs = new FileStream(CAFEDEVRUN_NAME.value + ".dlf", FileMode.Append);
4420             sw = new StreamWriter(fs);
4421             sw.WriteLine("0x00000005D3A00000,\"\"");
4422             sw.Flush();
4423             sw.Close();
4424 
4425             return CAFEX_ERROR.OK;
4426         }
4427 
4428         //Script function: hostrun
hostrun(string arguments)4429         static void hostrun(string arguments)
4430         {
4431             #if DEBUG
4432                 Log.WriteLine("hostrun started. Arguments:" + arguments);
4433             #endif
4434 
4435             getbridgetype();
4436 
4437             FSEMUL_PARAMS.value = null;
4438             if (BRIDGE_TYPE.value == "Toucan")
4439             {
4440                 BRIDGE_INSTALL_PATH.value = SDIO_BRIDGE_TOOLS.value;
4441             }
4442             else
4443             {
4444                 BRIDGE_INSTALL_PATH.value = MION_BRIDGE_TOOLS.value;
4445             }
4446 
4447             if (BRIDGE_TYPE.value == "Mion")
4448             {
4449                 if (BRIDGE_PARAMETERS.value == null)
4450                 {
4451                     FSEMUL_PARAMS.value = "-em -ip " + BRIDGE_CURRENT_IP_ADDRESS.value;
4452                 }
4453                 else
4454                 {
4455                     FSEMUL_PARAMS.value = BRIDGE_PARAMETERS.value + " -ip " + BRIDGE_CURRENT_IP_ADDRESS.value;
4456                 }
4457             }
4458 
4459             if (execLaunchCmd && !string.IsNullOrEmpty(LAUNCH_DLF_FILE))
4460             {
4461                 string[] splitStrings = arguments.Split(' ');
4462                 int i = 0;
4463                 arguments = splitStrings[i++] + " " + LAUNCH_DLF_FILE + " ";
4464                 for (; i < splitStrings.Length; i++)
4465                 {
4466                     arguments += splitStrings[i] + " ";
4467                 }
4468             }
4469 
4470             // Need to figure out what the difference between these two options is in the scripts, and if it is possible to replicate here.
4471             if (CAFE_DETACH_FSEMUL.value == null || CAFE_DETACH_FSEMUL.value != "0")
4472             {
4473                 FSEmul.start(arguments, FSEMUL_PARAMS.value);
4474             }
4475             else
4476             {
4477                 FSEmul.start(arguments, FSEMUL_PARAMS.value);
4478             }
4479 
4480             // Remeber what the boot mode was when we cold booted the DEVKIT
4481             string boot_mode_file = Path.Combine(CAFE_TEMP.value, string.Format("{0}_{1}_CAFE_BOOT_MODE", BRIDGE_CURRENT_IP_ADDRESS.value.Replace('.', 'x'), BRIDGE_CURRENT_NAME.value));
4482             File.WriteAllText(boot_mode_file, CAFE_BOOT_MODE.value);
4483 
4484             if (Program.CAFE_PROFILE.value != null && Program.CAFE_PROFILE.value == "1")
4485             {
4486                 CafeXEventtLog.Instance.WriteToEventLog(572, DateTime.Now, EventStatus.DISCRETE, EventProcess.CAFEX, "System is going through cold boot");
4487             }
4488         }
4489 
4490         //Script function: cafediscrun
discrun(string[] args, bool runSetup, bool launch)4491         static CafeXReturn discrun(string[] args, bool runSetup, bool launch)
4492         {
4493             #if DEBUG
4494                 Log.WriteLine("discrun started.");
4495                 string argString = null;
4496                 if (args != null)
4497                 {
4498                     foreach (string arg in args)
4499                     {
4500                         argString += arg + " ";
4501                     }
4502                 }
4503                 Log.WriteLine("Arguments=" + argString);
4504 
4505             #endif
4506 
4507             CAFERUN_OPTION_CALLED_FROM_CAFEDISCRUN.value = "yes";
4508             return run(args, runSetup, launch);
4509         }
4510 
4511 
4512         //Script function: cafeheadlessrun
headlessrun(string[] args)4513         static CafeXReturn headlessrun(string[] args)
4514         {
4515 #if DEBUG
4516             Log.WriteLine("headlessrun started.");
4517             string argString = null;
4518             if (args != null)
4519             {
4520                 foreach (string arg in args)
4521                 {
4522                     argString += arg + " ";
4523                 }
4524             }
4525             Log.WriteLine("Arguments=" + argString);
4526 #endif
4527 
4528             string HLRUN_OUT = Path.Combine(CAFE_TEMP.value, SESSION_PATH_PREFIX.value + "headlessrun");
4529             string HLRUN_TMP = Path.Combine(HLRUN_OUT, "tmp");
4530 
4531             bool RUN_DEVMENU = true;            // Run Devmenu after upload
4532             bool BYPASS_SETUP = false;          // Bypass mastering step
4533             int TITLE_WAIT = 15;                // Time to wait for the title to boot (in seconds)
4534             bool DEBUG_FLAG = false;            // Use the DEBUG version of the OS
4535             int UPLOAD_BANK = 10;               // Bank to upload the mastered image to
4536             string RPX_PATH = string.Empty;     // Path to the RPX file
4537             string[] RPX_ARGS = new string[0];  // Arguments to the RPX file
4538 
4539             CafeXReturn ret = new CafeXReturn(CAFEX_ERROR.OK);
4540 
4541             //
4542             // check_args
4543             //
4544             for (int i = 0; i < args.Length; ++i)
4545             {
4546                 switch (args[i])
4547                 {
4548                     case "-b":
4549                         {
4550                             DEBUG_FLAG = true;
4551                             break;
4552                         }
4553 
4554                     case "-h":
4555                         {
4556                             if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
4557                             {
4558                                 headlessrun_usage();
4559                                 return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
4560                             }
4561 
4562                             if (!int.TryParse(args[i + 1], out UPLOAD_BANK))
4563                             {
4564                                 Console.WriteLine("Error: '{0}' is not a valid number!", args[i + 1]);
4565                                 headlessrun_usage();
4566                                 return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
4567                             }
4568                             ++i;
4569                             break;
4570                         }
4571 
4572                     case "-n":
4573                         {
4574                             RUN_DEVMENU = false;
4575                             break;
4576                         }
4577 
4578                     case "-m":
4579                         {
4580                             BYPASS_SETUP = true;
4581                             break;
4582                         }
4583 
4584                     case "-w":
4585                         {
4586                             if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
4587                             {
4588                                 headlessrun_usage();
4589                                 return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
4590                             }
4591 
4592                             if (!int.TryParse(args[i + 1], out TITLE_WAIT))
4593                             {
4594                                 Console.WriteLine("Error: '{0}' is not a valid number!", args[i + 1]);
4595                                 headlessrun_usage();
4596                                 return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
4597                             }
4598 
4599                             if (TITLE_WAIT < 0)
4600                             {
4601                                 Console.WriteLine("Error: Wait time can't be less than zero!");
4602                                 headlessrun_usage();
4603                                 return new CafeXReturn(CAFEX_ERROR.BAD_ARGUMENT);
4604                             }
4605 
4606                             ++i;
4607                             break;
4608                         }
4609 
4610                     case "-u":
4611                         {
4612                             headlessrun_usage();
4613                             return new CafeXReturn(CAFEX_ERROR.OK);
4614                         }
4615 
4616                     default:
4617                         {
4618                             if (string.IsNullOrEmpty(RPX_PATH))
4619                             {
4620                                 RPX_PATH = args[i];
4621                             }
4622                             else
4623                             {
4624                                 if (i < args.Length)
4625                                 {
4626                                     int start = i;
4627                                     RPX_ARGS = new string[args.Length - 1];
4628                                     while (i < args.Length)
4629                                     {
4630                                         RPX_ARGS[i - start] = args[i];
4631                                     }
4632                                 }
4633                                 i = args.Length;
4634                             }
4635                             break;
4636                         }
4637                 }
4638             }
4639 
4640             string makecfmaster = getPathToMakeCfMaster();
4641             if (makecfmaster == null)
4642             {
4643                 Console.WriteLine("headlessrun requires makecfmaster.exe but it's not found.");
4644                 return new CafeXReturn(CAFEX_ERROR.MASTERING_ERROR);
4645             }
4646 
4647             if (string.IsNullOrEmpty(RPX_PATH))
4648             {
4649                 Console.WriteLine("cafex headlessrun failed: RPX file is missing on command line!");
4650                 headlessrun_usage();
4651                 return new CafeXReturn(CAFEX_ERROR.RUN_NO_RPX_SPECIFIED);
4652             }
4653 
4654             //
4655             // update_bootloader
4656             //
4657             ret.error = hostcheckversion();
4658             if (ret.error != CAFEX_ERROR.OK)
4659             {
4660                 Console.WriteLine("cafex headlessrun: failed running hostcheckversion.");
4661                 return ret;
4662             }
4663 
4664             string boot_mode = string.Empty;
4665 
4666             int hb_ver_flat = compute_flat_version(CAFERUN_HOSTBRIDGE_VERSION.value);
4667             if (hb_ver_flat < compute_flat_version("3.2.4.8"))
4668             {
4669                 Console.WriteLine("cafex headlessrun: Using BOOT mode " + CAFE_BOOT_MODE.value);
4670             }
4671             else
4672             {
4673                 Console.WriteLine("cafex headlessrun: Checking for DUAL bootloader...");
4674 
4675                 // hostbridge 3.2.5.1 has a problem in mode detection that requires some time after stop
4676                 // in order to properly detect boot mode
4677                 try
4678                 {
4679                     stop(new string[] { "-hard" });
4680                 }
4681                 catch (Exception e)
4682                 {
4683                     Console.WriteLine("cafex recover[warning]: Failure to hard stop the DEVKIT prior to mode detection, error {0}", e.Message);
4684                 }
4685                 Thread.Sleep(1000);
4686 
4687                 int boot_mode_detect = FSEmul.boot_mode_detect(BRIDGE_CURRENT_IP_ADDRESS.value, out boot_mode);
4688                 if (boot_mode_detect != 0)
4689                 {
4690                     Console.WriteLine("cafex headlessrun: Unable to determine boot mode!");
4691                     return new CafeXReturn(CAFEX_ERROR.BOOTMODEDETECT_FSEMUL_FAILED);
4692                 }
4693 
4694                 Console.WriteLine("cafex headlessrun: Detected BOOT mode : {0}", boot_mode);
4695             }
4696 
4697             if (boot_mode.Substring(0, 4) != "DUAL")
4698             {
4699                 // Install the DUAL bootlooder
4700                 ret.error = recover(null);
4701                 if (ret.error != CAFEX_ERROR.OK)
4702                 {
4703                     return ret;
4704                 }
4705             }
4706 
4707             if (!BYPASS_SETUP)
4708             {
4709                 //
4710                 // prepare_rpx_for_mastering
4711                 //
4712                 CAFE_BOOT_MODE.value = "PCFS";
4713 
4714                 // Disable the builtin capturing of output
4715                 string OLD_CAFE_CONSOLE = CAFE_CONSOLE.value;
4716                 CAFE_CONSOLE.value = "notoucan";
4717 
4718                 // Run the RPX to create the dependent files needed for mastering
4719                 string[] discrun_args = new string[5 + (DEBUG_FLAG ? 1 : 0) + RPX_ARGS.Length];
4720                 int discrun_idx = 0;
4721 
4722                 if (DEBUG_FLAG)
4723                 {
4724                     discrun_args[discrun_idx++] = "-b";
4725                 }
4726                 discrun_args[discrun_idx++] = "-e";
4727                 discrun_args[discrun_idx++] = "em";
4728                 discrun_args[discrun_idx++] = "-e";
4729                 discrun_args[discrun_idx++] = "sata";
4730                 discrun_args[discrun_idx++] = RPX_PATH;
4731                 RPX_ARGS.CopyTo(discrun_args, discrun_idx);
4732 
4733                 Console.WriteLine("cafex headlessrun: calling discrun {0}", string.Join(" ", discrun_args));
4734                 ret = discrun(discrun_args, true, true);
4735 
4736                 // Wait for MCP to come up
4737                 int mon_ret = monitor_for_output("-k", "[+-* DK is ready for console input *-+]", "30", CAFE_TEMP.value, null, true);
4738                 if (mon_ret == 0)   // TODO: This should be from the MON_RESULT enumeration
4739                 {
4740                     Console.WriteLine("cafex headlessrun: Master image prep for '{0}' succeeded.", RPX_PATH);
4741                 }
4742                 else
4743                 {
4744                     Console.WriteLine("cafex headlessrun: Master image prep for '{0}' failed with code {1}!", RPX_PATH, mon_ret);
4745                     return new CafeXReturn(CAFEX_ERROR.MASTERING_ERROR);
4746                 }
4747 
4748                 // Give the title time to boot up in case it writes files needed for mastering
4749                 Console.WriteLine("cafex headlessrun: waiting {0} seconds for title to boot...", TITLE_WAIT);
4750                 Thread.Sleep(TITLE_WAIT * 1000);
4751 
4752                 CAFE_CONSOLE.value = OLD_CAFE_CONSOLE;
4753 
4754                 stop(null);
4755                 Thread.Sleep(2000);
4756             }
4757 
4758             //
4759             // master_image
4760             //
4761 
4762             // Create the working and temp folders
4763             Directory.CreateDirectory(HLRUN_TMP);
4764 
4765             // Create the master image for the last ran RPX
4766             ret.error = makeMaster(new string[] { "-r", RPX_PATH, "-o", Path.Combine(HLRUN_OUT, "title"), "-w", HLRUN_TMP });
4767             if (ret.error == CAFEX_ERROR.OK)
4768             {
4769                 Console.WriteLine("cafex headlessrun: Mastering image for {0} succeeded.", RPX_PATH);
4770             }
4771             else
4772             {
4773                 Console.WriteLine("cafex headlessrun:Mastering image for $RPX_PATH failed with code {0}!", ret);
4774                 return ret;
4775             }
4776 
4777             //
4778             // upload_image
4779             //
4780             int imageuploader_ret = ImageUploader.upload(BRIDGE_CURRENT_IP_ADDRESS.value, UPLOAD_BANK, Path.Combine(HLRUN_OUT, "title.wumad"));
4781             if (imageuploader_ret == 0)
4782             {
4783                 Console.WriteLine("cafex headlessrun: ImageUpload to bank {0} succeeded.", UPLOAD_BANK);
4784             }
4785             else
4786             {
4787                 Console.WriteLine("cafex headlessrun: ImageUpload to bank {0} failed with code {0}!", UPLOAD_BANK, imageuploader_ret);
4788                 return new CafeXReturn(CAFEX_ERROR.IMAGEUPLOADER_FAILED);
4789             }
4790 
4791             //
4792             // set_hreader_mode
4793             //
4794             int mionurl_ret = mionurl.Run(string.Format("{0} /setup.cgi id_27={1} id_32=1 op=0", BRIDGE_CURRENT_IP_ADDRESS.value, UPLOAD_BANK));
4795             if (mionurl_ret == 0)
4796             {
4797                 Console.WriteLine("cafex headlessrun: mionurl succeeded to set HREADER mode.");
4798             }
4799             else
4800             {
4801                 Console.WriteLine("cafex headlessrun: mionurl failed to set HREADER mode with code {0}!", mionurl_ret);
4802                 return new CafeXReturn(CAFEX_ERROR.MIONURL_FAILED);
4803             }
4804 
4805             // Reboot MION and wait for completion so Bank and HREADER mode can take effect
4806             string miontelnet_output;
4807             Console.WriteLine("cafex headlessrun: Rebooting MION...");
4808             int miontelnet_ret = miontelnet.Reboot(out miontelnet_output);
4809             Console.WriteLine(miontelnet_output);
4810 
4811             if (RUN_DEVMENU)
4812             {
4813                 //
4814                 // run_image
4815                 //
4816 
4817                 // Change the boot mode TO NAND
4818                 CAFE_BOOT_MODE.value = "NAND";
4819 
4820                 string[] discrun_args = new string[DEBUG_FLAG ? 6 : 5];
4821                 int discrun_idx = 0;
4822 
4823                 if (DEBUG_FLAG)
4824                 {
4825                     discrun_args[discrun_idx++] = "-b";
4826                 }
4827                 discrun_args[discrun_idx++] = "-e";
4828                 discrun_args[discrun_idx++] = string.Format("h:{0}", UPLOAD_BANK);
4829                 discrun_args[discrun_idx++] = "-e";
4830                 discrun_args[discrun_idx++] = "nopcfs";
4831                 discrun_args[discrun_idx++] = RPX_PATH;
4832 
4833                 Console.WriteLine("cafex headlessrun: calling discrun {0}", string.Join(" ", discrun_args));
4834                 return discrun(discrun_args, true, true);
4835             }
4836             else
4837             {
4838                 Console.WriteLine("cafex headlessrun: completed sucessfully.");
4839             }
4840 
4841             return new CafeXReturn(CAFEX_ERROR.OK);
4842         }
4843 
4844         //Script function: cafeon
on(string[] args, bool runSetup, bool launch)4845         static CafeXReturn on(string[] args, bool runSetup, bool launch)
4846         {
4847 #if DEBUG
4848             Log.WriteLine("on started.");
4849             string argString = null;
4850             if (args != null)
4851             {
4852                 foreach (string arg in args)
4853                 {
4854                     argString += arg + " ";
4855                 }
4856             }
4857             Log.WriteLine("Arguments=" + argString);
4858 
4859 #endif
4860             List<string> argList = new List<string>();
4861             CafeXReturn ret = new CafeXReturn(CAFEX_ERROR.OK);
4862 
4863             CAFEON_DISABLE_BGD.value = "0";
4864             CAFEON_NOBGD_META.value = "";
4865             BRIDGE_PARAMETERS_WITH_E.value = "";
4866             CAFE_RUN_DEBUG.value = "";
4867             BOOTRUN_USE_RECOVERY_IMAGE.value = "";
4868 
4869             CAFEON_OPTION_NO_DATA_SYNC.value = CAFERUN_OPTION_NO_DATA_SYNC.value;
4870 
4871             if (CAFEON_OPTION_NO_DATA_SYNC.value == null)
4872             {
4873                 CAFEON_OPTION_NO_DATA_SYNC.value = "0";
4874             }
4875 
4876             if (CAFE_RUN_RUNNING.value == null)
4877             {
4878                 CAFE_RUN_RUNNING.value = "0";
4879             }
4880 
4881             if (CAFE_RUN_RUNNING.value != "0")
4882             {
4883                 Console.WriteLine("****cafex on: RECURSIVE CALL TO cafex on EXITING***");
4884                 ret.error = CAFEX_ERROR.ON_RECURSIVE_CALL;
4885                 return ret;
4886             }
4887 
4888             CAFE_RUN_RUNNING.value = "1";
4889 
4890             if (args != null && args.Length > 0)
4891             {
4892                 for (int i = 0; i < args.Length; ++i)
4893                 {
4894                     if (args[i] == "-noprompt")
4895                     {
4896                         CATTOUCAN_TERM.value = Nintendo.SDSG.CatToucan.Terms.MENU_SOURCE;
4897                     }
4898                     else if (args[i] == "-d")
4899                     {
4900                         CAFE_RUN_DEBUG.value = args[i] + " " + args[i + 1];
4901                         ++i;
4902                     }
4903                     else if (args[i] == "-e")
4904                     {
4905                         BRIDGE_PARAMETERS_WITH_E.AddToVar(args[i] + " " + args[i + 1], ' ');
4906                         ++i;
4907                     }
4908                     else if (args[i] == "-nobgd")
4909                     {
4910                         CAFEON_DISABLE_BGD.value = "1";
4911                     }
4912                     else if (args[i] == "-nosync")
4913                     {
4914                         if (string.IsNullOrEmpty(CAFE_DATA_DIR.value) ||
4915                             !Directory.Exists(CAFE_DATA_DIR.value))
4916                         {
4917                             Console.WriteLine("Session data directory is missing and needs to be sync'd!");
4918                             Console.WriteLine("  Please re-run without the '-nosync' option.");
4919                             ret.error = CAFEX_ERROR.ON_DATA_DIR_MISSING;
4920                             return ret;
4921                         }
4922 
4923                         CAFEON_OPTION_NO_DATA_SYNC.value = "1";
4924                     }
4925                     else if (args[i] == "-recover")
4926                     {
4927                         _CCRSYSCFG1.value = "0x40000000";
4928                         BOOTRUN_USE_RECOVERY_IMAGE.value = "1";
4929                     }
4930                     else if (args[i] == "-h")
4931                     {
4932                         on_usage();
4933                         ret.error = CAFEX_ERROR.OK;
4934                         return ret;
4935                     }
4936                     else
4937                     {
4938                         // This is an argument that needs to be passed down
4939                         argList.Add(args[i]);
4940                     }
4941                 }
4942             }
4943 
4944             if (CAFEON_DISABLE_BGD.value == "1")
4945             {
4946                 if (!string.IsNullOrEmpty(CAFE_META_DIR.value) &&
4947                     Directory.Exists(CAFE_META_DIR.value))
4948                 {
4949                     CAFEON_NOBGD_META.value = CAFE_TEMP.value + "\\" + SESSION_PATH_PREFIX.value + "tmp_meta";
4950                     Console.WriteLine("Disabling background daemons in tmp dir " + CAFEON_NOBGD_META.value);
4951                     DirectoryInfo originMetaDiretory = new DirectoryInfo(CAFE_META_DIR.value);
4952                     FileSystemInfo[] filesToCopy = originMetaDiretory.GetFileSystemInfos();
4953                     if (filesToCopy.Length > 0)
4954                     {
4955                         create_directory_if_noexist(CAFEON_NOBGD_META.value);
4956                         string[] meta_files = Directory.GetFiles(CAFE_META_DIR.value);
4957                         foreach (FileSystemInfo file in filesToCopy)
4958                         {
4959                             string fileName = file.FullName;
4960                             string destinationFileName = CAFEON_NOBGD_META.value + "\\" + Path.GetFileName(fileName);
4961                             file_copy_retry(fileName, destinationFileName, true, 3);
4962                         }
4963 
4964                         XmlHandler.UpdateNodeValue(CAFEON_NOBGD_META.value + "\\meta.xml", "bg_daemon_enable", "0");
4965 
4966                         CAFE_META_DIR.value = CAFEON_NOBGD_META.value;
4967                     }
4968                 }
4969             }
4970 
4971             OS_VERSION_LO.value = XmlHandler.GetNodeValue(CAFE_ROOT.value + "\\data\\mlc\\sys\\title\\00050010\\1f700500\\code\\app.xml", "os_version").Substring(8, 6);
4972             string total_arglist_with_qs = StringCombiner.MakeDelimitedString(argList.ToArray(), ' ').Replace(' ', '?').Replace("-c?", "-c ").Replace("?-c", " -c");
4973 
4974             if (OS_VERSION_LO.value == null)
4975             {
4976                 Console.WriteLine("cafex on error: unable to locate System Config Tool app.xml or file is corrupt");
4977             }
4978             else
4979             {
4980                 if (CAFEON_OPTION_NO_DATA_SYNC.value == "0")
4981                 {
4982                     ret.error = syncsession(null);
4983                     if (CAFEX_ERROR.OK != ret.error)
4984                     {
4985                         return ret;
4986                     }
4987                 }
4988 
4989                 XmlHandler.UpdateNodeValue(CAFE_DATA_DIR.value + "\\mlc\\sys\\title\\00050010\\1f700500\\code\\cos.xml", "argstr", "system_config_tool.rpx " + total_arglist_with_qs);
4990 
4991                 // Keep the current command stored, so when run is called it knows it has last been called by 'on'
4992                 string currentCommand = command;
4993                 command = "on";
4994                 string OS_string = string.Empty;
4995                 if (OS_VERSION_LO.value == "100040")
4996                 {
4997                     // NDEBUG OS
4998                     OS_string = CAFE_ROOT.value + "\\system\\bin\\ghs\\cafe\\app\\system_config_tool\\base\\NDEBUG\\system_config_tool.rpx";
4999                 }
5000                 else if (OS_VERSION_LO.value == "100080")
5001                 {
5002                     // DEBUG OS
5003                     OS_string = "-b" + DEFAULT_DELIMITER + CAFE_ROOT.value + "\\system\\bin\\ghs\\cafe\\app\\system_config_tool\\base\\DEBUG\\system_config_tool.rpx";
5004                 }
5005 
5006                 string run_args = (!string.IsNullOrEmpty(CAFE_RUN_DEBUG.value) ? CAFE_RUN_DEBUG.value.Replace(' ', DEFAULT_DELIMITER) : string.Empty) +
5007                     DEFAULT_DELIMITER + (!string.IsNullOrEmpty(BRIDGE_PARAMETERS_WITH_E.value) ? BRIDGE_PARAMETERS_WITH_E.value.Replace(' ', DEFAULT_DELIMITER) : string.Empty) +
5008                     DEFAULT_DELIMITER + "-e" + DEFAULT_DELIMITER + "mcp:launch_hint:hfiomlc" + DEFAULT_DELIMITER + "-z" + DEFAULT_DELIMITER +
5009                     "-t" + DEFAULT_DELIMITER + "0x" + SYSCONFIGTOOL_TITLE_ID + DEFAULT_DELIMITER + OS_string;
5010 
5011                 if (argList != null)
5012                 {
5013                     run_args += DEFAULT_DELIMITER + StringCombiner.MakeDelimitedString(argList.ToArray(), DEFAULT_DELIMITER);
5014                 }
5015 
5016                 if (fAppTypeDefined)
5017                 {
5018                     fAppTypeDefined = false;
5019                     ret = run(run_args.Split(new char[] { DEFAULT_DELIMITER }, StringSplitOptions.RemoveEmptyEntries), runSetup, launch);
5020                     fAppTypeDefined = true;
5021                 }
5022                 else
5023                 {
5024                     ret = run(run_args.Split(new char[] { DEFAULT_DELIMITER }, StringSplitOptions.RemoveEmptyEntries), runSetup, launch);
5025                 }
5026 
5027                 // Return the current command
5028                 command = currentCommand;
5029                 XmlHandler.UpdateNodeValue(CAFE_DATA_DIR.value + "\\mlc\\sys\\title\\00050010\\1f700500\\code\\cos.xml", "argstr", "system_config_tool.rpx");
5030             }
5031 
5032             return ret;
5033         }
5034 
5035 
5036         // Helper function: DUAL bootloader availibility and requirement by SDK
is_DUAL_bootloader_available()5037         static private bool is_DUAL_bootloader_available()
5038         {
5039             int flat_sdk_ver = compute_flat_version(SDK_VER.value);
5040 
5041             if (flat_sdk_ver >= compute_flat_version("2.10.01"))
5042             {
5043                 // DUAL bootloader is available starting in SDK 2.10.01
5044                 if (Directory.Exists (Path.Combine(CAFE_MLC_DIR.value, "sys\\update\\mixed")))
5045                 {
5046                     // Found the mixed content folder in the MLC
5047                     return true;
5048                 }
5049             }
5050 
5051             return false;
5052         }
5053 
is_DUAL_bootloader_required()5054         static private bool is_DUAL_bootloader_required()
5055         {
5056             int flat_sdk_ver = compute_flat_version(SDK_VER.value);
5057 
5058             if (flat_sdk_ver >= compute_flat_version("2.10.11"))
5059             {
5060                 // DUAL bootloader is required starting in SDK 2.10.11
5061                 return true;
5062             }
5063 
5064             return false;
5065         }
5066 
5067 
5068         // Helper function: Prepares the mixed content folder in the current SDK
prepare_mlc_recover_content()5069         static private void prepare_mlc_recover_content ()
5070         {
5071             const string sdio_boot1_folder = "zzz-boot1-sdio";
5072             const string dual_boot1_folder = "aaa-boot1-dual";
5073             string MIXED_DIR = Path.Combine(Program.CAFE_MLC_DIR.value, "sys\\update\\mixed");
5074             string PCFS_DIR = Path.Combine(Program.CAFE_MLC_DIR.value, "sys\\update\\pcfs");
5075             string NAND_DIR = Path.Combine(Program.CAFE_MLC_DIR.value, "sys\\update\\nand");
5076             string BL_DIR = Path.Combine(Program.CAFE_MLC_DIR.value, "sys\\update\\bootloader");
5077 
5078             // Delete the standalone copy of the dual bootloader
5079             if (Directory.Exists(BL_DIR))
5080             {
5081                 FileUtil.DirectoryDelete(BL_DIR, true);
5082             }
5083 
5084             if (!Directory.Exists(MIXED_DIR))
5085             {
5086                 // Make a standalone copy of the SDIO bootloader since DUAL does not exist
5087                 FileUtil.DirectoryCopy(Path.Combine(PCFS_DIR, sdio_boot1_folder), Path.Combine(BL_DIR, sdio_boot1_folder), false);
5088             }
5089             else
5090             {
5091                 // Make a standalone copy of the DUAL bootloader
5092                 FileUtil.DirectoryCopy(Path.Combine(MIXED_DIR, dual_boot1_folder), Path.Combine(BL_DIR, dual_boot1_folder), false);
5093 
5094                 // Delete all of the folders except the bootloader in the MLC mixed folder
5095                 Console.WriteLine("cafex: Cleaning content in '{0}'", MIXED_DIR);
5096                 foreach (string srcEntry in Directory.GetDirectories(MIXED_DIR))
5097                 {
5098                     string srcName = Path.GetFileName(srcEntry);
5099                     if (!srcName.Equals(dual_boot1_folder, StringComparison.CurrentCultureIgnoreCase))
5100                     {
5101                         string destEntry = Path.Combine(MIXED_DIR, srcName);
5102                         FileUtil.DirectoryDelete(srcEntry, true);
5103                     }
5104                 }
5105 
5106                 // Delete all of the files in the MLC mixed folder
5107                 foreach (string srcEntry in Directory.GetFiles(MIXED_DIR))
5108                 {
5109 #if DEBUG
5110                     Console.WriteLine("Deleting file '{0}'", srcEntry);
5111 #endif
5112                     File.Delete(srcEntry);
5113                 }
5114 
5115                 //
5116                 // Start building the mixed content in dest_dir
5117                 //
5118                 Console.WriteLine("cafex: Preparing content in '{0}'", MIXED_DIR);
5119 
5120                 // Copy all of the folders except the bootloader from the src to the dest
5121                 foreach (string srcEntry in Directory.GetDirectories(NAND_DIR))
5122                 {
5123                     string srcName = Path.GetFileName(srcEntry);
5124                     if (!srcName.StartsWith("zzz-boot1-"))
5125                     {
5126                         string destEntry = Path.Combine(MIXED_DIR, srcName);
5127                         FileUtil.DirectoryCopy(srcEntry, destEntry, true);
5128                     }
5129                 }
5130 
5131                 // Copy the files from NAND content in the mixed dir
5132                 foreach (string srcEntry in Directory.GetFiles(NAND_DIR))
5133                 {
5134                     string srcName = Path.GetFileName(srcEntry);
5135                     string destEntry = Path.Combine(MIXED_DIR, srcName);
5136 
5137 #if DEBUG
5138                     Console.WriteLine("Copying file '{0}' => '{1}'", srcEntry, destEntry);
5139 #endif
5140                     File.Copy(srcEntry, destEntry);
5141                 }
5142             }
5143         }
5144 
5145         // Helper function: Prepares a revert content folder in the current SDK from the reversion SDK.
prepare_mlc_revert_content(string REVERT_DIR, string revert_cafe_root, bool use_mixed)5146         static private void prepare_mlc_revert_content(string REVERT_DIR, string revert_cafe_root, bool use_mixed)
5147         {
5148             const string sdio_boot1_folder = "zzz-boot1-sdio";
5149             const string dual_boot1_folder = "aaa-boot1-dual";
5150             string PCFS_DIR = Path.Combine(revert_cafe_root, "data\\mlc\\sys\\update\\pcfs");
5151             string NAND_DIR = Path.Combine(revert_cafe_root, "data\\mlc\\sys\\update\\nand");
5152             string MIXED_DIR = Path.Combine(revert_cafe_root, "data\\mlc\\sys\\update\\mixed");
5153 
5154             // Delete the standalone copy of the SDIO bootloader
5155             if (Directory.Exists(REVERT_DIR))
5156             {
5157                 FileUtil.DirectoryDelete(REVERT_DIR, true);
5158             }
5159 
5160             if (is_DUAL_bootloader_required())
5161             {
5162                 use_mixed = true;
5163             }
5164 
5165             Console.WriteLine("cafex: Preparing content in '{0}'", REVERT_DIR);
5166 
5167             // Copy directories from the NAND content folder (except the bootloader)
5168             foreach (string srcEntry in Directory.GetDirectories(NAND_DIR))
5169             {
5170                 string srcName = Path.GetFileName(srcEntry);
5171                 if (!srcName.StartsWith("zzz-boot1-"))
5172                 {
5173                     string destEntry = Path.Combine(REVERT_DIR, srcName);
5174                     FileUtil.DirectoryCopy(srcEntry, destEntry, true);
5175                 }
5176             }
5177 
5178             // Copy files from the NAND content folder
5179             foreach (string srcEntry in Directory.GetFiles(NAND_DIR))
5180             {
5181                 string srcName = Path.GetFileName(srcEntry);
5182                 string destEntry = Path.Combine(REVERT_DIR, srcName);
5183                 File.Copy(srcEntry, destEntry);
5184             }
5185 
5186             // Copy the bootloader depending of if we using the DUAL bootloader
5187             if (!is_DUAL_bootloader_available() || !use_mixed)
5188             {
5189                 // This is reverting to an SDK that doesn't have the DUAL bootloader or
5190                 //   an optional one where we don't want to use it.
5191                 FileUtil.DirectoryCopy(Path.Combine(PCFS_DIR, sdio_boot1_folder), Path.Combine(REVERT_DIR, sdio_boot1_folder), false);
5192             }
5193             else
5194             {
5195                 // This is reverting to an SDK that requires the DUAL booloader or
5196                 //   an optional one where we do want to use it.
5197                 FileUtil.DirectoryCopy(Path.Combine(MIXED_DIR, dual_boot1_folder), Path.Combine(REVERT_DIR, dual_boot1_folder), false);
5198             }
5199         }
5200 
5201         //Script function: cafeupdate
update(string[] args)5202         static CAFEX_ERROR update(string[] args)
5203         {
5204             #if DEBUG
5205                 Log.WriteLine("update started.");
5206                 string argString = null;
5207                 if (args != null)
5208                 {
5209                     foreach (string arg in args)
5210                     {
5211                         argString += arg + " ";
5212                     }
5213                 }
5214                 Log.WriteLine("Arguments=" + argString);
5215 
5216             #endif
5217 
5218             CAFEUPDATE_USE_SYSTEM_UPDATER.value = "0";
5219             CAFEUPDATE_TITLE.value = "";
5220             CAFEUPDATE_PACKAGE_DEFAULT.value = "/vol/storage_hfiomlc01/sys/update/pcfs";
5221             CAFEUPDATE_PACKAGE.value = CAFEUPDATE_PACKAGE_DEFAULT.value;
5222             bool USE_MIXED_BOOTLOADER = false;
5223             bool prod = true;
5224             bool reflash = false;
5225             bool noreflash = false;
5226             bool updateDRC = true;
5227             CAFEX_ERROR ret = CAFEX_ERROR.UPDATE_FAILED;
5228 
5229             if ((recover_flags & RECOVER_COMMAND_MASK) == RECOVER_COMMAND_INIT)
5230             {
5231                 recover_flags = (recover_flags & ~RECOVER_COMMAND_MASK) | RECOVER_COMMAND_UPDATE;
5232             }
5233 
5234             if (is_DUAL_bootloader_required())
5235             {
5236                 USE_MIXED_BOOTLOADER = true;
5237                 prod = false;
5238             }
5239             else //the bootloader isn't available or not required
5240             {
5241                 USE_MIXED_BOOTLOADER = false;
5242                 prod = true;
5243             }
5244 
5245             for (int i = 0; i < args.Length; ++i)
5246             {
5247                 switch (args[i].ToLowerInvariant())
5248                 {
5249                     case "-u":
5250                     {
5251                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
5252                         {
5253                             run_usage();
5254                             return CAFEX_ERROR.BAD_ARGUMENT;
5255                         }
5256 
5257                         CAFEUPDATE_PACKAGE.value = args[i + 1];
5258                         ++i;
5259                         break;
5260                     }
5261 
5262                     case "-s":
5263                     {
5264                         CAFEUPDATE_USE_SYSTEM_UPDATER.value = "1";
5265                         break;
5266                     }
5267 
5268                     case "-t":
5269                     {
5270                         if (!ArgumentChecks.IsArgumentValidSetting(args, i + 1))
5271                         {
5272                             run_usage();
5273                             return CAFEX_ERROR.BAD_ARGUMENT;
5274                         }
5275 
5276                         CAFEUPDATE_TITLE.value = args[i + 1];
5277                         ++i;
5278                         break;
5279                     }
5280 
5281                     case "-p":
5282                     {
5283                             recover_flags = (recover_flags & ~RECOPT_PROD_MASK) | RECOPT_PRODUCTION_DEF;
5284                             if (!is_DUAL_bootloader_required())
5285                             {
5286                                 Console.WriteLine("-p argument not supported on this SDK.");
5287                                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5288                             }
5289                         if (CAFE_BOOT_MODE.value != "NAND")
5290                         {
5291                             Console.WriteLine("Warning: Ignoring '{0}' switch because it is only valid in NAND mode.", args[i]);
5292                                 recover_flags = (recover_flags & ~RECOVER_ENV_BOOT_MASK) | RECOVER_ENV_BOOT_NAND;
5293                         }
5294                         else
5295                         {
5296                                 USE_MIXED_BOOTLOADER = false;
5297                                 prod = true;
5298                                 recover_flags = (recover_flags & ~RECOVER_ENV_BOOT_MASK) | RECOVER_ENV_BOOT_PCFS;
5299                                 //if (!noreflash)
5300                                 //{
5301                                 //    // the -noreflash option was found before the -P
5302                                 //    reflash = true;
5303                                 //}
5304                             }
5305                         break;
5306                     }
5307                     case "-noreflash":
5308                     {
5309                         reflash = false;
5310                         noreflash = true;
5311                             recover_flags = (recover_flags & ~RECOPT_NOREFLASH_MASK) | RECOPT_NOREFLASH_DEF;
5312                         break;
5313                     }
5314 
5315                     case "-reflash":
5316                     {
5317                         reflash = true;
5318                             recover_flags = (recover_flags & ~RECOPT_REFLASH_MASK) | RECOPT_REFLASH_DEF;
5319                         break;
5320                     }
5321 
5322                     case "-m":
5323                         {
5324                             recover_flags = (recover_flags & ~RECOPT_MIXED_MASK) | RECOPT_MIXED_DEF;
5325                             //This option was only valid on SDKs 2.10.01-2.10.09
5326                             if (is_DUAL_bootloader_available() && !is_DUAL_bootloader_required())
5327                             {
5328                                 USE_MIXED_BOOTLOADER = true;
5329                                 prod = false;
5330                             }
5331                             else
5332                             {
5333                                 Console.WriteLine("-M is not supported in this SDK.");
5334                                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5335                             }
5336                             break;
5337                         }
5338 
5339                     case "-l":
5340                         {
5341                             recover_flags = (recover_flags & ~RECOPT_LEGACY_MASK) | RECOPT_LEGACY_DEF;
5342 
5343                             //This option was only valid on SDKs 2.10.10 and above
5344                             if (is_DUAL_bootloader_required())
5345                             {
5346                                 USE_MIXED_BOOTLOADER = false;
5347                                 prod = true;
5348                             }
5349                             else
5350                             {
5351                                 Console.WriteLine("-L is not supported in this SDK.");
5352                                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5353                             }
5354                             break;
5355                         }
5356                     case "-nodrc":
5357                         {
5358                             //don't update the DRC firmware
5359                             updateDRC = false;
5360                             break;
5361                         }
5362 
5363                     case "-h":
5364                     {
5365                         update_usage();
5366                         return CAFEX_ERROR.OK;
5367                     }
5368 
5369                     default:
5370                     {
5371                         Console.WriteLine("cafex update failed: Invalid argument");
5372                         return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5373                     }
5374                 }
5375             }
5376 
5377             //I'd really like to check for -M and -L at the same time here, but the old code didn't check that.
5378             //So to maintain backcompat, whatever is specified last between -M and -L is what gets used.
5379             if (CAFE_BOOT_MODE.value == "NAND")
5380             {
5381                 recover_flags = (recover_flags & ~RECOVER_ENV_BOOT_MASK) | RECOVER_ENV_BOOT_NAND;
5382 
5383                 List<string> recover_args = new List<string>();
5384                 if (prod)
5385                 {
5386                     recover_args.Add("-production");
5387                 }
5388                 else if (USE_MIXED_BOOTLOADER && !is_DUAL_bootloader_required())
5389                 {
5390                     recover_args.Add("-mixed");
5391                 }
5392 
5393                 if (noreflash)
5394                 {
5395                     recover_args.Add("-noreflash");
5396                 }
5397                 else if (reflash)
5398                 {
5399                     recover_args.Add("-reflash");
5400                 }
5401 
5402                 ret = recover(recover_args.ToArray());
5403             }
5404             else
5405             {
5406                 recover_flags = (recover_flags & ~RECOVER_ENV_BOOT_MASK) | RECOVER_ENV_BOOT_PCFS;
5407                 if (CAFE_SECURITY.value == "off")
5408                 {
5409                     Console.WriteLine("Sorry, bringup boot1 update not supported yet");
5410                     return CAFEX_ERROR.UPDATE_BRINGUP_BOOT1_UPDATE;
5411                 }
5412 
5413 
5414                 if (CAFEUPDATE_TITLE.value != null)
5415                 {
5416                     Console.WriteLine("Installing title " + CAFEUPDATE_TITLE.value + " using System Config Tool...");
5417                     CAFEX_ERROR on_ret = on(new string[] { "-c", "install " + CAFEUPDATE_TITLE.value, "-c", "exit" }, true, true).error;
5418                     if (on_ret != CAFEX_ERROR.OK)
5419                     {
5420                         return on_ret;
5421                     }
5422                     else
5423                     {
5424                         readSDKFromMion();
5425                         setMionSDKVersion();
5426                     }
5427                 }
5428                 else
5429                 {
5430                     if (CAFEUPDATE_PACKAGE.value == CAFEUPDATE_PACKAGE_DEFAULT.value)
5431                     {
5432                         Console.WriteLine("Performing system update using System Config Tool...");
5433                     }
5434                     else
5435                     {
5436                         Console.WriteLine("Performing system update using System Config Tool from " + CAFEUPDATE_PACKAGE.value + "...");
5437                     }
5438 
5439                     if (CAFEUPDATE_USE_SYSTEM_UPDATER.value == "1")
5440                     {
5441                         Console.WriteLine("Using system updater...");
5442                         CAFEX_ERROR on_ret = on(new string[] { "-c", "update_launch " + CAFEUPDATE_PACKAGE.value }, true, true).error;
5443                         if (on_ret != CAFEX_ERROR.OK)
5444                         {
5445                             return on_ret;
5446                         }
5447                         else
5448                         {
5449                             readSDKFromMion();
5450                             setMionSDKVersion();
5451                         }
5452                     }
5453                     else
5454                     {
5455                         List<string> setbootmode_args = new List<string>();
5456                         if (USE_MIXED_BOOTLOADER && !is_DUAL_bootloader_required())
5457                         {
5458                             setbootmode_args.Add("-mixed");
5459                         }
5460                         setbootmode_args.Add("PCFS");
5461                         if (noreflash)
5462                         {
5463                             setbootmode_args.Add("-noreflash");
5464                         }
5465                         else if (reflash)
5466                         {
5467                             setbootmode_args.Add("-reflash");
5468                         }
5469 
5470                         ret = setbootmode(setbootmode_args.ToArray());
5471                     }
5472                 }
5473             }
5474 
5475             if (updateDRC && ret == CAFEX_ERROR.OK)
5476             {
5477                 Console.WriteLine("Attempting to update DRC");
5478                 //reset some values that on -recover set
5479                 CAFE_CONSOLE.value = "cattoucan";
5480                 CAFE_RUN_RUNNING.value = "0";
5481                 _CCRSYSCFG1.value = "";
5482                 BOOTRUN_USE_RECOVERY_IMAGE.value = "";
5483                 CATTOUCAN_TERM.value = "drc_update end";
5484                 ret = on(new string[] {"-c drc_update 1"}, true, true).error;
5485                 stop(null, true);
5486             }
5487 
5488             return ret;
5489         }
5490 
revert(string[] args)5491         static CAFEX_ERROR revert(string[] args)
5492         {
5493 #if DEBUG
5494             Log.WriteLine("revert started.");
5495             string argString = null;
5496             if (args != null)
5497             {
5498                 foreach (string arg in args)
5499                 {
5500                     argString += arg + " ";
5501                 }
5502             }
5503             Log.WriteLine("Arguments=" + argString);
5504 #endif
5505             bool reflash = false;
5506             bool noreflash = false;
5507             string revert_cafe_root = string.Empty;
5508             bool use_mixed = false;
5509             CAFEX_ERROR ret = CAFEX_ERROR.OK;
5510 
5511             for (int i = 0; i < args.Length; ++i)
5512             {
5513                 switch (args[i].ToLowerInvariant())
5514                 {
5515                     case "-noreflash":
5516                         if (reflash)
5517                         {
5518                             Console.WriteLine("cafex revert: '-reflash' and '-noreflash' can't be used together!");
5519                             return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5520                         }
5521                         noreflash = true;
5522                         break;
5523 
5524                     case "-reflash":
5525                         if (noreflash)
5526                         {
5527                             Console.WriteLine("cafex revert: '-reflash' and '-noreflash' can't be used together!");
5528                             return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5529                         }
5530                         reflash = true;
5531                         break;
5532 
5533                     case "-mixed":
5534                         use_mixed = true;
5535                         break;
5536 
5537                     case "-h":
5538                         revert_usage();
5539                         return CAFEX_ERROR.OK;
5540 
5541                     default:
5542                         if (args[i].StartsWith("-") || !string.IsNullOrEmpty(revert_cafe_root))
5543                         {
5544                             Console.WriteLine("cafex revert failed: Invalid argument: '{0}'", args[i]);
5545                             return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5546                         }
5547 
5548                         revert_cafe_root = PathConverter.Windowsify(args[i]);
5549                         break;
5550                 }
5551             }
5552 
5553             if (string.IsNullOrEmpty(revert_cafe_root))
5554             {
5555                 Console.WriteLine("cafex revert failed: Missing SDK root to revert to on command line!");
5556                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5557             }
5558 
5559             if (!Directory.Exists(revert_cafe_root))
5560             {
5561                 Console.WriteLine("cafex revert failed: Target SDK root folder '{0}' does not exist!", revert_cafe_root);
5562                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5563             }
5564 
5565             // Backup these as we and readSDKFromCafeRoot will modify them
5566             string OLD_SDK_VER = SDK_VER.value;
5567 
5568             // Update the SDK version for teh reversion to that of the target SDK
5569             if (CAFEX_ERROR.OK != readSDKFromCafeRoot(revert_cafe_root))
5570             {
5571                 Console.WriteLine("cafex revert failed: Unable to get SDK version from folder '{0}'!", revert_cafe_root);
5572                 return CAFEX_ERROR.UPDATE_FAILED;
5573             }
5574 
5575             if (compute_flat_version(SDK_VER.value) >= compute_flat_version(OLD_SDK_VER))
5576             {
5577                 Console.WriteLine("cafex revert failed: Can't revert to an earlier SDK.  Please update using the newer SDK.");
5578                 return CAFEX_ERROR.UPDATE_FAILED;
5579             }
5580 
5581             if (use_mixed && (is_DUAL_bootloader_required() || !is_DUAL_bootloader_available()))
5582             {
5583                 Console.WriteLine("cafex recover failed: -mixed argument not supported by this version of the SDK.");
5584                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5585             }
5586 
5587             if (SESSION_MANAGER.value == "1")
5588             {
5589                 if (string.IsNullOrEmpty(CAFERUN_OPTION_NO_DATA_SYNC.value) || CAFERUN_OPTION_NO_DATA_SYNC.value == "0")
5590                 {
5591                     ret = syncsession(null);
5592                     if (CAFEX_ERROR.OK != ret)
5593                     {
5594                         return ret;
5595                     }
5596                     CAFERUN_OPTION_NO_DATA_SYNC.value = "1";
5597                 }
5598             }
5599 
5600             string REVERT_DIR = Path.Combine(Program.CAFE_MLC_DIR.value, "revert");
5601             prepare_mlc_revert_content(REVERT_DIR, revert_cafe_root, use_mixed);
5602 
5603             List<string> recover_opts = new List<string>();
5604             if (reflash)
5605             {
5606                 recover_opts.Add("-reflash");
5607             }
5608             else if (noreflash)
5609             {
5610                 recover_opts.Add("-noreflash");
5611             }
5612 
5613             recover_opts.Add("-source");
5614             recover_opts.Add("/vol/storage_hfiomlc01/revert");
5615 
5616             ret = recover(recover_opts.ToArray());
5617             if (ret == 0)
5618             {
5619                 Console.WriteLine("cafex: DEVKIT reverted to SDK {0}", SDK_VER.value);
5620             }
5621 
5622             // Restore the SDK version in case we are called internally
5623             SDK_VER.value = OLD_SDK_VER;
5624 
5625             return ret;
5626         }
5627 
5628         // remove a directory for clean-up, avoiding any errors from removal
ForceRemoveDirectory(string dirName)5629         static void ForceRemoveDirectory(string dirName)
5630         {
5631             for (int retry = 0; retry < 3; ++retry)
5632             {
5633                 if (retry > 0)
5634                 {
5635                     Thread.Sleep(1000);
5636                 }
5637                 try
5638                 {
5639                     Directory.Delete(dirName, true);
5640                     break; // stop retrying
5641                 }
5642                 catch (Exception e)
5643                 {
5644                     Console.WriteLine("ForceRemoveDirecory: Warning: tried to remove [{0}], got exception [{1}], retry={2}",
5645                         dirName, e.Message, retry);
5646                 }
5647             }
5648         }
5649 
5650 
5651         //Script function: caferecover
5652         //
5653         //Recover_test number decomposition
5654         // Digit order: 0xBA9876543210
5655         // Digit 0:
5656         // Digit 1:
5657         // Digit 2:
5658         // Digit 3:
5659         // Digit 4:
5660         // Digit 5:
5661         // Digit 6:
5662         //
5663         // Default = 0x02223225
5664         internal static UInt64 RECOVER_SDK_MASK =               0x000000000000000F;
5665         internal static UInt64 RECOVER_COMMAND_MASK =           0x00000000000000F0;
5666         internal static UInt64 RECOVER_ENV_BOOT_MASK =          0x0000000000000F00;
5667         internal static UInt64 RECOPT_REFLASH_MASK =            0x000000000000F000;
5668         internal static UInt64 RECOPT_NOREFLASH_MASK =          0x00000000000F0000;
5669         internal static UInt64 RECOPT_PROD_MASK =               0x0000000000F00000;
5670         internal static UInt64 RECOPT_MIXED_MASK =              0x000000000F000000;
5671         internal static UInt64 RECOVER_DETECTED_BOOT_MASK =     0x00000000F0000000;
5672         internal static UInt64 RECOPT_QUICK_MASK =              0x0000000F00000000;
5673         internal static UInt64 RECOPT_DESIRED_BOOT_MASK =       0x000000F000000000;
5674         internal static UInt64 RECOPT_LEGACY_MASK =             0x00000F0000000000;
5675         internal static UInt64 RECOPT_BOOTLOADER_MASK =         0x0000F00000000000;
5676 
5677         internal static uint RECOPT_SDK_NOMIXED = 0x00000000;
5678         internal static uint RECOPT_SDK_MIXEDNOTREQ = 0x00000001;
5679         internal static uint RECOPT_SDK_MIXEDREQ = 0x00000002;
5680 
5681         internal static uint RECOVER_COMMAND_RECOVER = 0x00000000;
5682         internal static uint RECOVER_COMMAND_SBM = 0x00000010;
5683         internal static uint RECOVER_COMMAND_UPDATE = 0x00000020;
5684         internal static uint RECOVER_COMMAND_INIT = 0x000000030;
5685 
5686         internal static uint RECOVER_ENV_BOOT_NAND = 0x00000000;
5687         internal static uint RECOVER_ENV_BOOT_PCFS = 0x00000100;
5688         internal static uint RECOVER_ENV_BOOT_UNKNOWN = 0x00000200;
5689 
5690         internal static uint RECOPT_REFLASH_UNDEF = 0x00000000;
5691         internal static uint RECOPT_REFLASH_DEF = 0x00001000;
5692 
5693         internal static uint RECOPT_NOREFLASH_UNDEF = 0x00000000;
5694         internal static uint RECOPT_NOREFLASH_DEF = 0x00010000;
5695 
5696         internal static uint RECOPT_PRODUCTION_UNDEF = 0x00000000;
5697         internal static uint RECOPT_PRODUCTION_DEF = 0x00100000;
5698 
5699         internal static uint RECOPT_MIXED_UNDEF = 0x00000000;
5700         internal static uint RECOPT_MIXED_DEF = 0x010000000;
5701 
5702         internal static uint RECOVER_DETECT_BOOT_NAND = 0x00000000;
5703         internal static uint RECOVER_DETECT_BOOT_PCFS = 0x10000000;
5704         internal static uint RECOVER_DETECT_BOOT_DUAL = 0x20000000;
5705         internal static uint RECOVER_DETECT_BOOT_UNKNOWN = 0x30000000;
5706 
5707         internal static uint RECOPT_QUICK_UNDEF = 0x00000000;
5708         internal static UInt64 RECOPT_QUICK_DEF = 0x0000000100000000;
5709 
5710         internal static uint RECOPT_DESIRED_BOOT_UNDEF = 0x00000000;
5711         internal static UInt64 RECOPT_DESIRED_BOOT_PCFS = 0x0000001000000000;
5712         internal static UInt64 RECOPT_DESIRED_BOOT_NAND = 0x0000002000000000;
5713 
5714         internal static uint RECOPT_LEGACY_UNDEF = 0x00000000;
5715         internal static UInt64 RECOPT_LEGACY_DEF = 0x0000010000000000;
5716 
5717         internal static uint RECOPT_BOOTLOADER_UNDEF = 0x00000000;
5718         internal static UInt64 RECOPT_BOOTLOADER_DEF = 0x0000100000000000;
5719 
recover(string[] args)5720         static CAFEX_ERROR recover(string[] args)
5721         {
5722 #if DEBUG
5723             Log.WriteLine("recover started.");
5724             string argString = null;
5725             if (args != null)
5726             {
5727                 foreach (string arg in args)
5728                 {
5729                     argString += arg + " ";
5730                 }
5731             }
5732             Log.WriteLine("Arguments=" + argString);
5733             Log.WriteLine(String.Format("Recover_flags={0:X12}",recover_flags));
5734 #endif
5735             //
5736             // Command line processing
5737             //
5738 
5739             bool production_bootloader = false;
5740             bool bootloader_only = false;
5741             bool mixed_arg = false;
5742             bool reflash_arg = false;
5743             bool noreflash_arg = false;
5744             bool reflash = false;    // This sets the default behavior for the recover operation
5745             bool noreflash = false;
5746             string recover_source = "/vol/storage_hfiomlc01/sys/update/pcfs";
5747 
5748             if ((recover_flags & RECOVER_COMMAND_MASK) == RECOVER_COMMAND_INIT)
5749             {
5750                 recover_flags = (recover_flags & ~RECOVER_COMMAND_MASK) | RECOVER_COMMAND_RECOVER;
5751             }
5752 
5753             if (is_DUAL_bootloader_available())
5754             {
5755             if (is_DUAL_bootloader_required())
5756                     recover_flags = (recover_flags & ~RECOVER_SDK_MASK) | RECOPT_SDK_MIXEDREQ;
5757                 else
5758                     recover_flags = (recover_flags & ~RECOVER_SDK_MASK) | RECOPT_SDK_MIXEDNOTREQ;
5759             }
5760             else
5761                 recover_flags = (recover_flags & ~RECOVER_SDK_MASK) | RECOPT_SDK_NOMIXED;
5762 
5763             if (is_DUAL_bootloader_required())
5764             {
5765                 if (!Directory.Exists(Path.Combine(CAFE_MLC_DIR.value, "sys\\update\\mixed")))
5766                 {
5767                     Console.WriteLine("cafex recover failed: Required mixed content folder '{0}' is missing!");
5768                     return CAFEX_ERROR.UPDATE_FAILED;
5769                 }
5770                 recover_source = "/vol/storage_hfiomlc01/sys/update/mixed";
5771             }
5772 
5773             if (args != null)
5774             {
5775                 for (int i = 0; i < args.Length; ++i)
5776                 {
5777                     switch (args[i].ToLowerInvariant())
5778                     {
5779                         case "-production":
5780                             recover_source = "/vol/storage_hfiomlc01/sys/update/nand";
5781                             production_bootloader = true;
5782                             recover_flags = recover_flags & (~RECOPT_PROD_MASK) | RECOPT_PRODUCTION_DEF;
5783                             //{
5784                             //    // the -noreflash option was found before the -production
5785                             //    reflash = true;
5786                             //}
5787                             break;
5788 
5789                         case "-bootloader":
5790                             recover_source = "/vol/storage_hfiomlc01/sys/update/bootloader";
5791                             bootloader_only = true;
5792                             recover_flags = (recover_flags & ~RECOPT_BOOTLOADER_MASK) | RECOPT_BOOTLOADER_DEF;
5793                             break;
5794 
5795                         case "-source":
5796                             recover_source = args[++i];
5797                             break;
5798 
5799                         case "-noreflash":
5800                             noreflash_arg = true;
5801                             reflash = false;
5802                             noreflash = true;
5803                             recover_flags = (recover_flags & ~RECOPT_NOREFLASH_MASK) | RECOPT_NOREFLASH_DEF;
5804                             break;
5805 
5806                         case "-reflash":
5807                             reflash_arg = true;
5808                             reflash = true;
5809                             recover_flags = (recover_flags & ~RECOPT_REFLASH_MASK) | RECOPT_REFLASH_DEF;
5810                             break;
5811 
5812                         case "-mixed":
5813                             if (is_DUAL_bootloader_required() || !is_DUAL_bootloader_available())
5814                             {
5815                                 Console.WriteLine("cafex recover failed: -mixed argument not supported by this version of the SDK.");
5816                                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5817                             }
5818                             mixed_arg = true;
5819                             recover_source = "/vol/storage_hfiomlc01/sys/update/mixed";
5820                             recover_flags = recover_flags & ~(RECOPT_MIXED_MASK) | RECOPT_MIXED_DEF;
5821                             break;
5822 
5823                         case "-h":
5824                             recover_usage();
5825                             return CAFEX_ERROR.OK;
5826 
5827                         default:
5828                             Console.WriteLine("cafex recover failed: Invalid argument");
5829                             return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5830                     }
5831                 }
5832             }
5833 
5834             if (production_bootloader && bootloader_only)
5835             {
5836                 Console.WriteLine("cafex recover failed: Invalid arguments: Can't specify both -production and -bootloader options!");
5837                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5838             }
5839 
5840             if (production_bootloader && mixed_arg)
5841             {
5842                 Console.WriteLine("cafex recover failed: Invalid arguments: Can't specify both -production and -mixed options!");
5843                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5844             }
5845 
5846             if (mixed_arg && bootloader_only)
5847             {
5848                 Console.WriteLine("WARNING: Ignoring -bootloader option since -mixed was specified");
5849                 recover_source = "/vol/storage_hfiomlc01/sys/update/mixed";
5850             }
5851 
5852             if (reflash_arg && noreflash_arg)
5853             {
5854                 Console.WriteLine("cafex recover failed: Can't specify both -reflash and -noreflash!  Please remove one or the other.");
5855                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5856             }
5857 
5858             // can't do -reflash -bootloader, but it seems like the intent is to update the bootloader.
5859             // Also, only do this if -mixed isn't specified, since -mixed implies -bootloader, and we could be coming
5860             // from production NAND, which would require a reflash.
5861             if (bootloader_only && reflash_arg && !mixed_arg)
5862             {
5863                 Console.WriteLine("WARNING: Ignoring reflash/noreflash argument since only bootloader is being updated");
5864                 reflash = false;
5865                 noreflash = true;
5866             }
5867 
5868             // Covers the case where we try to specify reflash when targeting legacy PCFS mode
5869             // without breaking setbootmode
5870             if (recover_source.EndsWith("pcfs") && reflash_arg)
5871             {
5872                 Console.WriteLine("cafex recover failed: Cannot specify -reflash option with legacy PCFS as target package!");
5873                 Console.WriteLine("This is the default package for SDKs 2.10.03 and 2.10.04.  Please do not specify -reflash without specifying -mixed or -production");
5874                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5875             }
5876 
5877             // Production bootloader must always reflash unless specified
5878             if (production_bootloader && !noreflash_arg)
5879             {
5880                 noreflash = false;
5881                 reflash = true;
5882             }
5883 
5884             if (production_bootloader && mixed_arg)
5885             {
5886                 Console.WriteLine("cafex recover failed: Invalid arguments: Can't specify both -production and -mixed options!");
5887                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5888             }
5889 
5890             if (mixed_arg && bootloader_only)
5891             {
5892                 Console.WriteLine("WARNING: Ignoring -bootloader option since -mixed was specified");
5893                 recover_source = "/vol/storage_hfiomlc01/sys/update/mixed";
5894             }
5895 
5896             if (reflash_arg && noreflash_arg)
5897             {
5898                 Console.WriteLine("cafex recover failed: Can't specify both -reflash and -noreflash!  Please remove one or the other.");
5899                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5900             }
5901 
5902             // can't do -reflash -bootloader, but it seems like the intent is to update the bootloader.
5903             // Also, only do this if -mixed isn't specified, since -mixed implies -bootloader, and we could be coming
5904             // from production NAND, which would require a reflash.
5905             if (bootloader_only && reflash_arg && !mixed_arg)
5906             {
5907                 Console.WriteLine("WARNING: Ignoring reflash/noreflash argument since only bootloader is being updated");
5908                 reflash = false;
5909                 noreflash = true;
5910             }
5911 
5912             // Covers the case where we try to specify reflash when targeting legacy PCFS mode
5913             // without breaking setbootmode
5914             if (recover_source.EndsWith("pcfs") && reflash_arg)
5915             {
5916                 Console.WriteLine("cafex recover failed: Cannot specify -reflash option with legacy PCFS as target package!");
5917                 Console.WriteLine("This is the default package for SDKs 2.10.03 and 2.10.04.  Please do not specify -reflash without specifying -mixed or -production");
5918                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
5919             }
5920 
5921             // Production bootloader must always reflash unless specified
5922             if (production_bootloader && !noreflash_arg)
5923             {
5924                 noreflash = false;
5925                 reflash = true;
5926             }
5927 
5928             //
5929             // Initialization
5930             //
5931             SCRIPT_EXE_TIMESTAMP.value = DateTime.Now.ToString("MMMdd_yyyy_HHmmss");
5932             LOGDIR.value = CAFE_TEMP.value + "\\" + SESSION_PATH_PREFIX.value + "caferecover\\" + SCRIPT_EXE_TIMESTAMP.value;
5933             Console.WriteLine("cafex recover");
5934             Console.WriteLine("log directory is " + LOGDIR.value);
5935             Console.WriteLine("recover source directory is " + recover_source);
5936             create_directory_if_noexist(LOGDIR.value);
5937             string old_boot_mode = CAFE_BOOT_MODE.value;
5938             bool skip_update = false;
5939             CAFE_CONSOLE.value = "toucan";
5940 
5941             FileStream fs = null;
5942             TextWriter old_out = null;
5943             TextWriter old_err = null;
5944             StreamWriter sw = null;
5945 
5946             CAFEX_ERROR hostcheckversion_ret = hostcheckversion();
5947             if (hostcheckversion_ret != CAFEX_ERROR.OK)
5948             {
5949                 return hostcheckversion_ret;
5950             }
5951 
5952             // Stop the DEVKIT to release any resources it may have locked
5953             try
5954             {
5955                 stop(new string[] { "-hard" });
5956             }
5957             catch (Exception e)
5958             {
5959                 Console.WriteLine("cafex recover[warning]: Failure to hard stop the DEVKIT prior to mode detection, error {0}", e.Message);
5960             }
5961             Thread.Sleep(1000);
5962 
5963             if (CAFEX_RECOVER_TEST.value != "1")
5964             {
5965             if (SESSION_MANAGER.value == "1")
5966             {
5967                 if (string.IsNullOrEmpty(CAFERUN_OPTION_NO_DATA_SYNC.value) || CAFERUN_OPTION_NO_DATA_SYNC.value == "0")
5968                 {
5969                     CAFEX_ERROR ret = syncsession(null);
5970                     if (CAFEX_ERROR.OK != ret)
5971                     {
5972                         return ret;
5973                     }
5974                     CAFERUN_OPTION_NO_DATA_SYNC.value = "1";
5975                 }
5976             }
5977 
5978             // Prepare the mixed and bootloader MLC folders
5979             prepare_mlc_recover_content();
5980             }
5981             //
5982             // Boot mode detection
5983             //
5984             string boot_mode;
5985             int boot_mode_detect = FSEmul.boot_mode_detect(BRIDGE_CURRENT_IP_ADDRESS.value, out boot_mode);
5986             if (boot_mode_detect != 0)
5987             {
5988                 Console.WriteLine("Unable to determine boot mode!");
5989                 return CAFEX_ERROR.BOOTMODEDETECT_FSEMUL_FAILED;
5990             }
5991 
5992             Console.WriteLine("Detected BOOT mode : {0}", boot_mode);
5993 
5994             if( boot_mode.Contains("NAND"))
5995             {
5996                 CAFE_BOOT_MODE.value = "NAND";
5997                     recover_flags = (recover_flags & ~RECOVER_DETECTED_BOOT_MASK) | RECOVER_DETECT_BOOT_NAND;
5998                     if (!noreflash && (!recover_source.EndsWith("pcfs") || recover_source.EndsWith("nand")))
5999                 {
6000                         // Reflash by default unless -noreflash was specified or the recover source
6001                         // is the legacy PCFS boot
6002                     reflash = true;
6003                 }
6004             }
6005             else
6006             {
6007                 CAFE_BOOT_MODE.value = "PCFS";
6008                 if (boot_mode.Contains("DUAL"))
6009                 {
6010                     recover_flags = (recover_flags & ~RECOVER_DETECTED_BOOT_MASK) | RECOVER_DETECT_BOOT_DUAL;
6011             }
6012                 else
6013                 {
6014                     recover_flags = (recover_flags & ~RECOVER_DETECTED_BOOT_MASK) | RECOVER_DETECT_BOOT_PCFS;
6015                 }
6016             }
6017 
6018             Console.WriteLine("recover_flags={0:X12}", recover_flags);
6019             //if (CAFEX_RECOVER_TEST.value == "1")
6020             //{
6021             //    try
6022             //    {
6023             //        stop(new string[] { "-hard" });
6024             //    }
6025             //    catch (Exception e)
6026             //    {
6027             //        Console.WriteLine("cafex recover[warning]: Failure to hard stop the DEVKIT prior to mode detection, error {0}", e.Message);
6028             //    }
6029             //    return CAFEX_ERROR.OK;
6030             //}
6031 
6032             //
6033             // cafex on (using the recovery image if booting in PCFS mode)
6034             //
6035             if (CAFE_BOOT_MODE.value == "NAND")
6036             {
6037                 Console.WriteLine("Executing cafex on...");
6038                 fs = new FileStream(LOGDIR.value + "\\cafeon.txt", FileMode.Create);
6039                 old_out = Console.Out;
6040                 old_err = Console.Error;
6041                 sw = new StreamWriter(fs);
6042                 Console.SetOut(sw);
6043                 Console.SetError(sw);
6044                 if (CAFEX_RECOVER_TEST.value != "1")
6045                 {
6046                 on(new string[] { "-e", "nomodecheck" }, true, true);
6047                 }
6048 
6049                 Console.SetOut(old_out);
6050                 Console.SetError(old_err);
6051                 sw.Flush();
6052                 sw.Close();
6053 
6054                 if (File.Exists(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log"))
6055                 {
6056                     File.Move(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log", LOGDIR.value + "\\cafeon_mion.log");
6057                 }
6058                 if (CAFEX_RECOVER_TEST.value != "1")
6059                 {
6060                 if (monitor_for_output("-k", "source -p -q /vol/content/", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6061                 {
6062                     Console.WriteLine("cafex recover: monitor failed waiting for cafeon success message.");
6063                     return CAFEX_ERROR.RECOVERY_FAILED;
6064                 }
6065                 }
6066 
6067                 Console.WriteLine("Executing devkitmsg recover -v...");
6068                 devkitmsg.recover();
6069                 if (CAFEX_RECOVER_TEST.value != "1")
6070                 {
6071                 if (monitor_for_output("-K", "WUD_BCMFWCheck", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6072                 {
6073                     Console.WriteLine("cafex recover: monitor failed waiting for devkitmsg recover success message.");
6074                     return CAFEX_ERROR.RECOVERY_FAILED;
6075                 }
6076                 }
6077 
6078                 Console.WriteLine("Executing devkitmsg 'update /vol/storage_hfiomlc01/sys/update/bootloader' -v...");
6079                 devkitmsg.update("/vol/storage_hfiomlc01/sys/update/bootloader");
6080 
6081                 if (CAFEX_RECOVER_TEST.value != "1")
6082                 {
6083                 if (monitor_for_output("-k", "Update Done, err 0", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6084                 {
6085                     Console.WriteLine("cafex recover: monitor failed waiting for devkitmsg 1st update success message.");
6086                     return CAFEX_ERROR.RECOVERY_FAILED;
6087                 }
6088                 }
6089 
6090                 CAFE_BOOT_MODE.value = "PCFS"; // Change to PCFS for the rest of the update
6091                 if (bootloader_only)
6092                 {
6093                     // We have already updated the bootloader and since we were only
6094                     // going to update it, skip the rest of update.
6095                     skip_update = true;
6096                 }
6097 
6098                 //
6099                 // cafestop
6100                 //
6101                 Console.WriteLine("Executing cafex stop...");
6102                 try
6103                 {
6104                     stop(new string[] { "-hard" });
6105                 }
6106                 catch (Exception e)
6107                 {
6108                     Console.WriteLine("cafex recover[warning]: Failure to hard stop the DEVKIT after bootloader update, error {0}", e.Message);
6109                 }
6110                 CAFE_RUN_RUNNING.value = "0";
6111             }
6112 
6113             if (!skip_update)
6114             {
6115                 Console.WriteLine("Executing cafex on -recover...");
6116                 fs = new FileStream(LOGDIR.value + "\\cafeon.txt", FileMode.Create);
6117                 old_out = Console.Out;
6118                 old_err = Console.Error;
6119                 sw = new StreamWriter(fs);
6120                 Console.SetOut(sw);
6121                 Console.SetError(sw);
6122 
6123                 if(CAFEX_RECOVER_TEST.value != "1")
6124                 on(new string[] { "-e", "nomodecheck", "-recover" }, true, true);
6125 
6126                 Console.SetOut(old_out);
6127                 Console.SetError(old_err);
6128                 sw.Flush();
6129                 sw.Close();
6130 
6131                 if (File.Exists(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log"))
6132                 {
6133                     File.Move(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log", LOGDIR.value + "\\cafeon_mion.log");
6134                 }
6135                 if (CAFEX_RECOVER_TEST.value != "1")
6136                 {
6137                     if (monitor_for_output("-K", "WUD_BCMFWCheck", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6138                     {
6139                         Console.WriteLine("cafex recover: monitor failed waiting for devkitmsg recover success message.");
6140                         return CAFEX_ERROR.RECOVERY_FAILED;
6141                     }
6142                 }
6143 
6144                 // Make sure Cafe is ready for commands
6145                 int syncTry = 0;
6146                 cattoucan.BeginBootSync();
6147                 for (syncTry = 0; syncTry < CAFERUN_RETRY_COUNT; ++syncTry)
6148                 {
6149                     if (cattoucan.SendSyncRequest(DEVKIT_HELP_REQUEST_TIMEOUT))
6150                     {
6151                         break;
6152                     }
6153                 }
6154                 for (; syncTry < CAFERUN_RETRY_COUNT; ++syncTry)
6155                 {
6156                     if (cattoucan.SyncWithBoot(DEVKIT_HELP_RESPONSE_TIMEOUT))
6157                     {
6158                         break;
6159                     }
6160                 }
6161                 cattoucan.FinishSync(true);
6162 
6163                 if (syncTry >= CAFERUN_RETRY_COUNT)
6164                 {
6165                     Console.WriteLine("Failed to sync with device");
6166                     return CAFEX_ERROR.RECOVERY_FAILED;
6167                 }
6168 
6169                 //
6170                 // Install the bootloader and content
6171                 //
6172                 if (reflash)
6173                 {
6174                     Console.WriteLine("Executing devkitmsg 'reflash '{0}' -v...", recover_source);
6175                     devkitmsg.reflash(recover_source);
6176                     if (CAFEX_RECOVER_TEST.value != "1")
6177                     {
6178                     if (monitor_for_output("-k", "System update was successful", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6179                     {
6180                         Console.WriteLine("cafex recover: monitor failed waiting for devkitmsg 1st update success message.");
6181                         return CAFEX_ERROR.RECOVERY_FAILED;
6182                     }
6183                 }
6184                 else
6185                         return CAFEX_ERROR.OK;
6186                 }
6187                 else
6188                 {
6189                     Console.WriteLine("Executing devkitmsg 'update {0}' -v...", recover_source);
6190                     devkitmsg.update(recover_source);
6191                     if (CAFEX_RECOVER_TEST.value != "1")
6192                     {
6193                     if (monitor_for_output("-k", "Update Done, err 0", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6194                     {
6195                         Console.WriteLine("cafex recover: monitor failed waiting for devkitmsg 1st update success message.");
6196                         return CAFEX_ERROR.RECOVERY_FAILED;
6197                     }
6198                 }
6199                     else
6200                         return CAFEX_ERROR.OK;
6201                 }
6202 
6203                 //
6204                 // Enable self-refresh
6205                 //
6206                 if (CAFE_TEST_SELF_REFRESH.value == "1")
6207                 {
6208                     Console.WriteLine("Executing devkitmsg standby_en 1 -v...");
6209                     devkitmsg.standby_en(1);
6210                 }
6211 
6212                 // Update the DEV-KIT SDK variables to current
6213                 setMionSDKVersion();
6214                 readSDKFromMion();
6215 
6216                 //
6217                 // cafestop
6218                 //
6219                 Console.WriteLine("Executing cafex stop...");
6220                 fs = new FileStream(LOGDIR.value + "\\cafestop1.txt", FileMode.Create);
6221                 old_out = Console.Out;
6222                 old_err = Console.Error;
6223                 sw = new StreamWriter(fs);
6224                 Console.SetOut(sw);
6225                 Console.SetError(sw);
6226 
6227                 stop(null);
6228 
6229                 Console.SetOut(old_out);
6230                 Console.SetError(old_err);
6231                 sw.Flush();
6232                 sw.Close();
6233 
6234                 if (File.Exists(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log"))
6235                 {
6236                     File.Move(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log", LOGDIR.value + "\\cafestop1_mion.log");
6237                 }
6238 
6239                 if (CAFESTOP_STATUS.value != "0")
6240                 {
6241                     Console.WriteLine("cafex recover: cafestop failure.");
6242                     return CAFEX_ERROR.RECOVERY_FAILED;
6243                 }
6244             }
6245 
6246             if (production_bootloader || old_boot_mode == "NAND")
6247             {
6248                 // Update the MION parameter space for NAND boot mode
6249                 if (mionps.Run(String.Format("{0} {1} -s {2}",BRIDGE_CURRENT_IP_ADDRESS.value,MIONPS_BOOT_BYTE,MIONPS_BOOT_NAND)) != "1")
6250                 {
6251                     Console.WriteLine("cafex recover: unable to set NAND boot mode using mionps.");
6252                     return CAFEX_ERROR.RECOVERY_FAILED;
6253                 }
6254             }
6255             else
6256             {
6257                 // Update the MION parameter space for PCFS boot mode
6258                 if (mionps.Run(String.Format("{0} {1} -s {2}",BRIDGE_CURRENT_IP_ADDRESS.value,MIONPS_BOOT_BYTE,MIONPS_BOOT_PCFS)) != "2")
6259                 {
6260                     Console.WriteLine("cafex recover: unable to set PCFS boot mode using mionps.");
6261                     return CAFEX_ERROR.RECOVERY_FAILED;
6262                 }
6263             }
6264 
6265             //
6266             // Success!
6267             //
6268             Console.WriteLine("Removing log directory " + LOGDIR.value + "...");
6269             ForceRemoveDirectory(LOGDIR.value);
6270             Console.WriteLine("cafex recover complete. Exiting with code 0");
6271 
6272             if (production_bootloader && old_boot_mode != "NAND")
6273             {
6274                 Console.WriteLine();
6275                 Console.WriteLine("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
6276                 Console.WriteLine("!!                                                           !!");
6277                 Console.WriteLine("!!  Boot Loader/Boot Mode mis-match detected!                !!");
6278                 Console.WriteLine("!!                                                           !!");
6279                 Console.WriteLine("!!  Please export CAFE_BOOT_MODE=NAND for proper operation!  !!");
6280                 Console.WriteLine("!!                                                           !!");
6281                 Console.WriteLine("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
6282             }
6283 
6284             return CAFEX_ERROR.OK;
6285         }
6286 
6287         //Script function: cafex cleardata
cleardata(params string[] args)6288         static CAFEX_ERROR cleardata(params string[] args)
6289         {
6290 #if DEBUG
6291             Log.WriteLine("cleardata started.");
6292             string argString = null;
6293             if (args != null)
6294             {
6295                 foreach (string arg in args)
6296                 {
6297                     argString += arg + " ";
6298                 }
6299             }
6300             Log.WriteLine("Arguments=" + argString);
6301 #endif
6302             //
6303             // Initialization
6304             //
6305             SCRIPT_EXE_TIMESTAMP.value = DateTime.Now.ToString("MMMdd_yyyy_HHmmss");
6306             LOGDIR.value = CAFE_TEMP.value + "\\" + SESSION_PATH_PREFIX.value + "cleardata\\" + SCRIPT_EXE_TIMESTAMP.value;
6307             Console.WriteLine("cafex cleardata");
6308             Console.WriteLine("log directory is " + LOGDIR.value);
6309             create_directory_if_noexist(LOGDIR.value);
6310             CAFE_CONSOLE.value = "toucan";
6311 
6312             FileStream fs = null;
6313             TextWriter old_out = null;
6314             TextWriter old_err = null;
6315             StreamWriter sw = null;
6316 
6317             //
6318             // Boot mode detection
6319             //
6320             CAFEX_ERROR hostcheckversion_ret = hostcheckversion();
6321             if (hostcheckversion_ret != CAFEX_ERROR.OK)
6322             {
6323                 Console.WriteLine("cafex cleardata: failed running hostcheckversion.");
6324                 return hostcheckversion_ret;
6325             }
6326 
6327             int hb_ver_flat = compute_flat_version(CAFERUN_HOSTBRIDGE_VERSION.value);
6328             if (hb_ver_flat < compute_flat_version("3.2.4.8"))
6329             {
6330                 Console.WriteLine("Error: Clear user data not supported in this version of the HostBridge!");
6331                 Console.WriteLine("       Please update your HostBridge to at least version 3.2.4.8 (preferably the latest) and try again.");
6332                 Console.WriteLine("cafex cleardata failed.");
6333                 return CAFEX_ERROR.CLEARDATA_FAILED;
6334             }
6335             else
6336             {
6337                 string boot_mode;
6338 
6339                 // hostbridge 3.2.5.1 has a problem in mode detection that requires some time after stop
6340                 // in order to properly detect boot mode
6341                 try
6342                 {
6343                     stop(new string[] { "-hard" });
6344                 }
6345                 catch (Exception e)
6346                 {
6347                     Console.WriteLine("cafex recover[warning]: Failure to hard stop the DEVKIT prior to mode detection, error {0}", e.Message);
6348                 }
6349                 Thread.Sleep(1000);
6350 
6351                 int boot_mode_detect = FSEmul.boot_mode_detect(BRIDGE_CURRENT_IP_ADDRESS.value, out boot_mode);
6352                 if (boot_mode_detect != 0)
6353                 {
6354                     Console.WriteLine("Unable to determine boot mode!");
6355                     return CAFEX_ERROR.BOOTMODEDETECT_FSEMUL_FAILED;
6356                 }
6357 
6358                 Console.WriteLine("Detected BOOT mode : {0}", boot_mode);
6359                 if (boot_mode == "NAND")
6360                 {
6361                     CAFE_BOOT_MODE.value = "NAND";
6362                 }
6363                 else
6364                 {
6365                     CAFE_BOOT_MODE.value = "PCFS";
6366                 }
6367             }
6368 
6369             if (CAFE_BOOT_MODE.value == "NAND")
6370             {
6371                 stop(null);
6372 
6373                 Console.WriteLine("Error: Can't clear user data in NAND boot mode!  Please switch to PCFS boot mode and try again.");
6374                 Console.WriteLine("cafex cleardata failed.");
6375                 return CAFEX_ERROR.CLEARDATA_FAILED;
6376             }
6377 
6378             Console.WriteLine("Executing cafex on...");
6379             fs = new FileStream(LOGDIR.value + "\\cafeon.txt", FileMode.Create);
6380             old_out = Console.Out;
6381             old_err = Console.Error;
6382             sw = new StreamWriter(fs);
6383             Console.SetOut(sw);
6384             Console.SetError(sw);
6385 
6386             // cafeon
6387             if (hb_ver_flat < compute_flat_version("3.2.4.1"))
6388             {
6389                 on(null, true, true);
6390             }
6391             else
6392             {
6393                 on(new string[] { "-e", "nomodecheck" }, true, true);
6394             }
6395 
6396             Console.SetOut(old_out);
6397             Console.SetError(old_err);
6398             sw.Flush();
6399             sw.Close();
6400 
6401             if (File.Exists(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log"))
6402             {
6403                 File.Move(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log", LOGDIR.value + "\\cafeon_mion.log");
6404             }
6405 
6406             if (monitor_for_output("-k", Nintendo.SDSG.CatToucan.Terms.MENU_SOURCE, MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6407             {
6408                 Console.WriteLine("cafex cleardata: monitor failed waiting for cafeon success message.");
6409                 return CAFEX_ERROR.CLEARDATA_FAILED;
6410             }
6411 
6412             Console.WriteLine("Executing devkitmsg recover -v...");
6413             devkitmsg.recover();
6414 
6415             if (monitor_for_output("-K", "WUD_BCMFWCheck", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6416             {
6417                 Console.WriteLine("cafex cleardata: monitor failed waiting for devkitmsg recover success message.");
6418                 return CAFEX_ERROR.CLEARDATA_FAILED;
6419             }
6420 
6421             //clr_usrdata command
6422             Console.WriteLine("Executing devkitmsg clr_usrdata -v...");
6423             devkitmsg.clr_usrdata();
6424 
6425             if (monitor_for_output("-k", "Done, err 0", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6426             {
6427                 Console.WriteLine("cafex cleardata: monitor failed waiting for devkitmsg clr_usrdata success message.");
6428                 return CAFEX_ERROR.CLEARDATA_FAILED;
6429             }
6430 
6431             //cafestop
6432             Console.WriteLine("Executing cafex stop...");
6433             fs = new FileStream(LOGDIR.value + "\\cafestop1.txt", FileMode.Create);
6434             old_out = Console.Out;
6435             old_err = Console.Error;
6436             sw = new StreamWriter(fs);
6437             Console.SetOut(sw);
6438             Console.SetError(sw);
6439 
6440             stop(null);
6441 
6442             Console.SetOut(old_out);
6443             Console.SetError(old_err);
6444             sw.Flush();
6445             sw.Close();
6446 
6447             if (File.Exists(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log"))
6448             {
6449                 File.Move(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log", LOGDIR.value + "\\cafestop1_mion.log");
6450             }
6451 
6452             if (CAFESTOP_STATUS.value != "0")
6453             {
6454                 Console.WriteLine("cafex cleardata: cafestop failure.");
6455                 return CAFEX_ERROR.CLEARDATA_FAILED;
6456             }
6457 
6458             //success!
6459             Console.WriteLine("Removing log directory " + LOGDIR.value + "...");
6460             ForceRemoveDirectory(LOGDIR.value);
6461             Console.WriteLine("cafex cleardata complete. Exiting with code 0");
6462 
6463             return CAFEX_ERROR.OK;
6464         }
6465 
6466         //Script function: setbootmode
setbootmode(string[] args)6467         static CAFEX_ERROR setbootmode(string[] args)
6468         {
6469             #if DEBUG
6470                 Log.WriteLine("setbootmode started.");
6471                 string argString = null;
6472                 if (args != null)
6473                 {
6474                     foreach (string arg in args)
6475                     {
6476                         argString += arg + " ";
6477                     }
6478                 }
6479                 Log.WriteLine("Arguments=" + argString);
6480 
6481             #endif
6482 
6483             CAFEX_ERROR returnValue = CAFEX_ERROR.SETBOOTMODE_FAILED;
6484             bool reflash = false;
6485             bool noreflash = false;
6486             bool mixed = false;
6487             bool prod = true; //not having this will break "setbootmode PCFS" in SDKs 2.10.01-2.10.08
6488             bool prod_arg = false; //specifically for the -quick case conditional
6489 
6490             if ((recover_flags & RECOVER_COMMAND_MASK) == RECOVER_COMMAND_INIT)
6491             {
6492                 recover_flags = (recover_flags & ~RECOVER_COMMAND_MASK) | RECOVER_COMMAND_SBM;
6493             }
6494 
6495             if (is_DUAL_bootloader_required())
6496             {
6497                 mixed = true;
6498                 prod = false;
6499             }
6500             else //the bootloader isn't available or not required
6501             {
6502                 mixed = false;
6503                 prod = true;
6504             }
6505 
6506             bool quick = false;
6507             bool reflash_arg = false;
6508             bool noreflash_arg = false;
6509 
6510             int ret = 0;
6511             string target = string.Empty;
6512             for (int idx = 0; idx < args.Length; idx++)
6513             {
6514                 if (args[idx] == "-noreflash") //uses the update command with devkitmsg
6515                 {
6516                     noreflash_arg = true;
6517                     reflash = false;
6518                     noreflash = true;
6519                     recover_flags = (recover_flags & ~RECOPT_NOREFLASH_MASK) | RECOPT_NOREFLASH_DEF;
6520                 }
6521                 else if (args[idx] == "-reflash") //uses the reflash command with devkitmsg
6522                 {
6523                     reflash_arg = true;
6524                     noreflash = false;
6525                     reflash = true;
6526                     recover_flags = (recover_flags & ~RECOPT_REFLASH_MASK) | RECOPT_REFLASH_DEF;
6527                 }
6528                 else if (args[idx] == "-production" || args[idx] == "-P")
6529                 {
6530                     mixed = false;
6531                     prod = true;
6532                     prod_arg = true;
6533                     reflash = true;
6534                     recover_flags = (recover_flags & ~RECOPT_PROD_MASK) | RECOPT_PRODUCTION_DEF;
6535                     //if (!noreflash)
6536                     //{
6537                     //    // the -noreflash option was found before -production
6538                     //    reflash = true;
6539                     //}
6540                     }
6541                 else if (args[idx] == "-quick" || args[idx] == "-Q")
6542                 {
6543                     quick = true;
6544                     recover_flags = (recover_flags & ~RECOPT_QUICK_MASK) | RECOPT_QUICK_DEF;
6545                 }
6546                 else if (args[idx] == "-h")
6547                 {
6548                     setbootmode_usage();
6549                     return CAFEX_ERROR.OK;
6550                 }
6551                 //included for backward compatibility.  If both mixed and prod are specified, prod will take precedence.
6552                 else if (args[idx] == "-mixed")
6553                 {
6554                     recover_flags = (recover_flags & ~RECOPT_MIXED_MASK) | RECOPT_MIXED_DEF;
6555                     //This option was only valid on SDKs 2.10.01-2.10.09
6556                     if (is_DUAL_bootloader_available() && !is_DUAL_bootloader_required())
6557                     {
6558                         mixed = true;
6559                         prod = false;
6560                     }
6561                 else
6562                 {
6563                         Console.WriteLine("-mixed option is not supported on this SDK.");
6564                         return CAFEX_ERROR.BAD_ARGUMENT;
6565                     }
6566                 }
6567                 else
6568                 {
6569                     if (!string.IsNullOrEmpty(target))
6570                     {
6571                         setbootmode_usage();
6572                         return CAFEX_ERROR.BAD_ARGUMENT;
6573                     }
6574                     if (!ArgumentChecks.IsArgumentValidSetting(args, idx))
6575                     {
6576                         setbootmode_usage();
6577                         return CAFEX_ERROR.BAD_ARGUMENT;
6578                     }
6579                     target = args[idx];
6580                 }
6581             }
6582 
6583             if (string.IsNullOrEmpty(target))
6584             {
6585                 setbootmode_usage();
6586                 return CAFEX_ERROR.BAD_ARGUMENT;
6587             }
6588 
6589             if (reflash_arg && noreflash_arg)
6590             {
6591                 Console.WriteLine("Can't specify both -reflash and -noreflash!  Please remove one or the other.");
6592                 return CAFEX_ERROR.UPDATE_INVALID_OPTION;
6593             }
6594 
6595             string status_str = "FAIL";
6596 
6597             if (quick)
6598             {
6599                 if (target != "NAND" && target != "PCFS")
6600                 {
6601                     Console.WriteLine("cafex setbootmode error: {0} is not a valid boot mode!", target);
6602                     setbootmode_usage();
6603                     return  CAFEX_ERROR.SETBOOTMODE_BAD_MODE;
6604                 }
6605 
6606                 if (prod_arg)
6607                 {
6608                     Console.WriteLine("cafex setbootmode error: Can't specify both -quick and -production options!");
6609                     setbootmode_usage();
6610                     return CAFEX_ERROR.BAD_ARGUMENT;
6611                 }
6612 
6613                 CAFEX_ERROR hostcheckversion_ret = hostcheckversion();
6614 
6615                 if (hostcheckversion_ret != CAFEX_ERROR.OK)
6616                 {
6617                     Console.WriteLine("cafex setbootmode: failed running hostcheckversion.");
6618                     return CAFEX_ERROR.SETBOOTMODE_FAILED;
6619                 }
6620 
6621                 int hb_ver_flat = compute_flat_version(CAFERUN_HOSTBRIDGE_VERSION.value);
6622 
6623                 if (hb_ver_flat < compute_flat_version("3.2.4.8"))
6624                 {
6625                     Console.WriteLine("cafex setbootmode: This version of the HostBridge doesn't support boot mode detection!.");
6626                     Console.WriteLine("                   Please update to it at least version 3.2.4.8 and try again.");
6627                     return CAFEX_ERROR.SETBOOTMODE_FAILED;
6628                 }
6629 
6630                 string boot_mode;
6631 
6632                 // hostbridge 3.2.5.1 has a problem in mode detection that requires some time after stop
6633                 // in order to properly detect boot mode
6634                 stop(new string[] { "-hard" });
6635                 Thread.Sleep(1000);
6636 
6637                 int boot_mode_detect = FSEmul.boot_mode_detect(BRIDGE_CURRENT_IP_ADDRESS.value, out boot_mode);
6638                 if (boot_mode_detect != 0)
6639                 {
6640                     Console.WriteLine("cafex setbootmode: Error: Unable to determine boot mode!");
6641                     return CAFEX_ERROR.BOOTMODEDETECT_FSEMUL_FAILED;
6642                 }
6643 
6644                 stop(new string[] { "-hard" });
6645 
6646                 Console.WriteLine("cafex setbootmode: Detected BOOT mode : {0}", boot_mode);
6647                 if(boot_mode.Contains("PCFS"))
6648                 {
6649                     recover_flags = (recover_flags & ~RECOVER_DETECTED_BOOT_MASK) | RECOVER_DETECT_BOOT_PCFS;
6650                 }
6651                 else if (boot_mode.Contains("NAND"))
6652                 {
6653                     recover_flags = (recover_flags & ~RECOVER_DETECTED_BOOT_MASK) | RECOVER_DETECT_BOOT_NAND;
6654                 }
6655                 else if (boot_mode.Contains("DUAL"))
6656                 {
6657                     recover_flags = (recover_flags & ~RECOVER_DETECTED_BOOT_MASK) | RECOVER_DETECT_BOOT_DUAL;
6658                 }
6659 
6660                 if (!boot_mode.StartsWith ("DUAL"))
6661                 {
6662                     Console.WriteLine("cafex setbootmode: Error: DUAL bootloader is not installed.  Please re-run setbootmode without using the -quick option.");
6663                     return CAFEX_ERROR.SETBOOTMODE_FAILED;
6664                 }
6665 
6666                 if (target == "NAND")
6667                 {
6668                     recover_flags = (recover_flags & ~RECOPT_DESIRED_BOOT_MASK) | RECOPT_DESIRED_BOOT_NAND;
6669                     if (mionps.Run(BRIDGE_CURRENT_IP_ADDRESS.value + " 2 -s 1") != "1")
6670                     {
6671                         Console.WriteLine("cafex unable to set NAND mode using mionps.");
6672                         return CAFEX_ERROR.SETBOOTMODE_FAILED;
6673                     }
6674                 }
6675                 else
6676                 {
6677                     recover_flags = (recover_flags & ~RECOPT_DESIRED_BOOT_MASK) | RECOPT_DESIRED_BOOT_PCFS;
6678                     if (mionps.Run(BRIDGE_CURRENT_IP_ADDRESS.value + " 2 -s 2") != "2")
6679                     {
6680                         Console.WriteLine("cafex unable to set PCFS mode using mionps.");
6681                         return CAFEX_ERROR.SETBOOTMODE_FAILED;
6682                     }
6683                 }
6684 
6685                 if (CAFEX_RECOVER_TEST.value == "1")
6686                 {
6687                     Console.WriteLine("recover_flags={0:X12}", recover_flags);
6688                     Console.WriteLine("devkitmsg_cmd: NA");
6689                 }
6690 
6691                 returnValue = CAFEX_ERROR.OK;
6692                 status_str = "PASS";
6693             }
6694             else
6695             {
6696                 switch (target)
6697                 {
6698                     case "PCFS":
6699                         {
6700                             recover_flags = (recover_flags & ~RECOPT_DESIRED_BOOT_MASK) | RECOPT_DESIRED_BOOT_PCFS;
6701 
6702                             if (prod_arg)
6703                             {
6704                                 Console.WriteLine("cafex setbootmode: Can't specify -production with the PCFS boot mode!");
6705                                 return CAFEX_ERROR.SETBOOTMODE_FAILED;
6706                             }
6707 
6708                             List<string> recover_args = new List<string>();
6709 
6710                             if (mixed)
6711                             {
6712                             Console.WriteLine("Executing cafex recover for mixed PCFS...");
6713                                 if (!is_DUAL_bootloader_required())
6714                                     recover_args.Add("-mixed");
6715                             }
6716                             else
6717                             {
6718                                 Console.WriteLine("Executing cafex recover for legacy PCFS...");
6719                             }
6720 
6721                             if (noreflash)
6722                             {
6723                                 recover_args.Add("-noreflash");
6724                             }
6725                             else if (reflash)
6726                             {
6727                                 recover_args.Add("-reflash");
6728                             }
6729 
6730                             ret = (int)recover(recover_args.ToArray());
6731                             if (ret == 0)
6732                             {
6733                                 // Set the CAT-DEV mode inside mion...
6734                                 if (mionps.Run(BRIDGE_CURRENT_IP_ADDRESS.value + " 2 -s 2") != "2")
6735                                 {
6736                                     Console.WriteLine("cafex unable to set mode using mionps.");
6737                                     return CAFEX_ERROR.SETBOOTMODE_FAILED;
6738                                 }
6739 
6740                                 CAFE_BOOT_MODE.value = "PCFS";
6741                                 Console.WriteLine("CAFE_BOOT_MODE=" + CAFE_BOOT_MODE.value);
6742                                 status_str = "PASS";
6743                                 returnValue = CAFEX_ERROR.OK;
6744                             }
6745                             break;
6746                         }
6747 
6748                     case "NAND":
6749                         {
6750                             recover_flags = (recover_flags & ~RECOPT_DESIRED_BOOT_MASK) | RECOPT_DESIRED_BOOT_NAND;
6751 
6752                             List<string> recover_args = new List<string>();
6753                             if (prod)
6754                             {
6755                                 Console.WriteLine("Executing cafex recover for production NAND...");
6756                                 recover_args.Add("-production");
6757                             }
6758                             else
6759                             {
6760                                 Console.WriteLine("Executing cafex recover for mixed NAND...");
6761                                 if (!is_DUAL_bootloader_required()) // SDK 2.10.11+ will error if -mixed is specified
6762                                     recover_args.Add("-mixed");
6763                             }
6764 
6765                             if (noreflash)
6766                             {
6767                                 recover_args.Add("-noreflash");
6768                             }
6769                             else if (reflash)
6770                             {
6771                                 recover_args.Add("-reflash");
6772                             }
6773 
6774                             ret = (int)recover(recover_args.ToArray());
6775                             if (ret == 0)
6776                             {
6777                                 // Set the CAT-DEV mode inside mion...
6778                                 if (mionps.Run(BRIDGE_CURRENT_IP_ADDRESS.value + " 2 -s 1") != "1")
6779                                 {
6780                                     Console.WriteLine("cafex unable to set mode using mionps.");
6781                                     return CAFEX_ERROR.SETBOOTMODE_FAILED;
6782                                 }
6783 
6784                                 CAFE_BOOT_MODE.value = "NAND";
6785                                 Console.WriteLine("CAFE_BOOT_MODE=" + CAFE_BOOT_MODE.value);
6786                                 status_str = "PASS";
6787                                 returnValue = CAFEX_ERROR.OK;
6788                             }
6789                             break;
6790                         }
6791 
6792                     default:
6793                         {
6794                             Console.WriteLine("cafex setbootmode error: Invalid boot mode");
6795                             status_str = "BAD MODE";
6796                             setbootmode_usage();
6797                             returnValue = CAFEX_ERROR.SETBOOTMODE_BAD_MODE;
6798                             break;
6799                         }
6800                 }
6801             }
6802 
6803             Console.WriteLine("cafex setbootmode: " + status_str);
6804             if (returnValue == CAFEX_ERROR.OK)
6805             {
6806                 readSDKFromMion();
6807                 setMionSDKVersion();
6808             }
6809 
6810             return returnValue;
6811         }
6812 
6813 
6814 #if false
6815         //Script function: cafe_nand2pcfs
nand2pcfs(int call_mionps)6816         static int nand2pcfs(int call_mionps)
6817         {
6818             #if DEBUG
6819                 Log.WriteLine("nand2pcfs started.");
6820             #endif
6821 
6822             // Initialization
6823             SCRIPT_EXE_TIMESTAMP.value = DateTime.Now.ToString("MMMdd_yyyy_HHmmss");
6824             LOGDIR.value = CAFE_ROOT.value + "\\" + SESSION_PATH_PREFIX.value + "cafe_nand2pcfs\\" + SCRIPT_EXE_TIMESTAMP.value;
6825             Console.WriteLine("cafe_nand2pcfs");
6826             Console.WriteLine("log directory is " + LOGDIR.value);
6827             create_directory_if_noexist(LOGDIR.value);
6828 
6829             File.Delete(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log");
6830 
6831             CAFESTOP_STATUS.value = "0";
6832             _CCRSYSCFG1.value = "";
6833             if (initialize_serial_port_and_directory("cafestop") != 0)
6834                 return 1;
6835 
6836             //cafestop
6837             Console.WriteLine("Executing cafex stop...");
6838             FileStream fs = new FileStream(LOGDIR.value + "\\cafestop0.txt", FileMode.Create);
6839             TextWriter old_out = Console.Out;
6840             TextWriter old_err = Console.Error;
6841             StreamWriter sw = new StreamWriter(fs);
6842             Console.SetOut(sw);
6843             Console.SetError(sw);
6844 
6845             stop(new string[] {"-hard"});
6846 
6847             Console.SetOut(old_out);
6848             Console.SetError(old_err);
6849             sw.Flush();
6850             sw.Close();
6851 
6852             if (File.Exists(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log"))
6853             {
6854                 File.Move(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log", LOGDIR.value + "\\cafestop0_mion.log");
6855             }
6856 
6857             if (CAFESTOP_STATUS.value != "0")
6858             {
6859                 Console.WriteLine("cafex nand2pcfs: cafestop failure.");
6860                 return 1;
6861             }
6862 
6863             //cafeon
6864             CAFEX_ERROR hostcheckversion_ret = hostcheckversion();
6865 
6866             if (hostcheckversion_ret != CAFEX_ERROR.OK)
6867             {
6868                 Console.WriteLine("cafex nand2pcfs: failed running hostcheckversion.");
6869                 return 1;
6870             }
6871 
6872             int hb_ver_flat = compute_flat_version(CAFERUN_HOSTBRIDGE_VERSION.value);
6873 
6874             Console.WriteLine("Executing cafex on...");
6875             fs = new FileStream(LOGDIR.value + "\\cafeon.txt", FileMode.Create);
6876             old_out = Console.Out;
6877             old_err = Console.Error;
6878             sw = new StreamWriter(fs);
6879             Console.SetOut(sw);
6880             Console.SetError(sw);
6881 
6882             //quiet_mode = true; // This breaks setbootmode in NAND/softlaunch
6883             Console.WriteLine("at on command");
6884             if (hb_ver_flat < compute_flat_version("3.2.4.1"))
6885             {
6886                 on(null, true, true);
6887             }
6888             else
6889             {
6890                 on(new string[] { "-e", "nomodecheck" }, true, true);
6891             }
6892 
6893             Console.WriteLine("after on command");
6894 
6895             Console.SetOut(old_out);
6896             Console.SetError(old_err);
6897             sw.Flush();
6898             sw.Close();
6899 
6900             if (File.Exists(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log"))
6901             {
6902                 File.Move(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log", LOGDIR.value + "\\cafeon_mion.log");
6903             }
6904 
6905             if (monitor_for_output("-k", Nintendo.SDSG.CatToucan.Terms.MENU_SOURCE, MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6906             {
6907                 Console.WriteLine("cafex nand2pcfs: monitor failed waiting for cafeon success message.");
6908                 return 1;
6909             }
6910 
6911             //recover command
6912             Console.WriteLine("Executing devkitmsg recover -v...");
6913             devkitmsg.recover();
6914 
6915             if (monitor_for_output("-K", "WUD_BCMFWCheck", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6916             {
6917                 Console.WriteLine("cafex nand2pcfs: monitor failed waiting for devkitmsg recover success message.");
6918                 return 1;
6919             }
6920 
6921             //update to PCFS
6922             Console.WriteLine("Executing devkitmsg 'update /vol/storage_hfiomlc01/sys/update/pcfs' -v...");
6923             devkitmsg.update_pcfs();
6924 
6925             if (monitor_for_output("-k", "Update Done, err 0", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6926             {
6927                 Console.WriteLine("cafex nand2pcfs: monitor failed waiting for devkitmsg 1st update success message.");
6928                 return 1;
6929             }
6930 
6931             if (call_mionps == 1)
6932             {
6933                 // Set the CAT-DEV mode inside mion...
6934                 if (mionps.Run(BRIDGE_CURRENT_IP_ADDRESS.value + " 2 -s 2") != "2")
6935                 {
6936                     Console.WriteLine("cafex unable to set mode using mionps.");
6937                     return 1;
6938                 }
6939             }
6940 
6941             //clr_usrdata command
6942             Console.WriteLine("Executing devkitmsg clr_usrdata -v...");
6943             devkitmsg.clr_usrdata();
6944 
6945             if (monitor_for_output("-k", "Done, err 0", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
6946             {
6947                 Console.WriteLine("cafex nand2pcfs: monitor failed waiting for devkitmsg clr_usrdata success message.");
6948                 return 1;
6949             }
6950 
6951             //enable self-refresh
6952             if (CAFE_TEST_SELF_REFRESH.value == "1")
6953             {
6954                 Console.WriteLine("Executing devkitmsg standyby_en 1 -v...");
6955                 devkitmsg.standby_en(1);
6956             }
6957 
6958             //cafestop
6959             Console.WriteLine("Executing cafex stop...");
6960             fs = new FileStream(LOGDIR.value + "\\cafestop1.txt", FileMode.Create);
6961             old_out = Console.Out;
6962             old_err = Console.Error;
6963             sw = new StreamWriter(fs);
6964             Console.SetOut(sw);
6965             Console.SetError(sw);
6966 
6967             stop(null);
6968 
6969             Console.SetOut(old_out);
6970             Console.SetError(old_err);
6971             sw.Flush();
6972             sw.Close();
6973 
6974             if (File.Exists(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log"))
6975             {
6976                 File.Move(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log", LOGDIR.value + "\\cafestop1_mion.log");
6977             }
6978 
6979             if (CAFESTOP_STATUS.value != "0")
6980             {
6981                 Console.WriteLine("cafex nand2pcfs: cafestop failure.");
6982                 return 1;
6983             }
6984 
6985             //success!
6986             Console.WriteLine("Removing log directory " + LOGDIR.value + "...");
6987             ForceRemoveDirectory(LOGDIR.value);
6988             Console.WriteLine("cafex nand2pcfs complete. Exiting with code 0");
6989 
6990             return 0;
6991         }
6992 #endif
6993 
6994 #if false
6995         //Script function: cafe_pcfs2nand
pcfs2nand(int reflash, int call_mionps)6996         static int pcfs2nand(int reflash, int call_mionps)
6997         {
6998 #if DEBUG
6999                 Log.WriteLine("pcfs2nand started.");
7000 #endif
7001 
7002             // Initialization
7003             SCRIPT_EXE_TIMESTAMP.value = DateTime.Now.ToString("MMMdd_yyyy_HHmmss");
7004             LOGDIR.value = CAFE_ROOT.value + "\\" + SESSION_PATH_PREFIX.value + "cafe_pcfs2nand\\" + SCRIPT_EXE_TIMESTAMP.value;
7005             Console.WriteLine("cafe_pcfs2nand");
7006             Console.WriteLine("log directory is " + LOGDIR.value);
7007             create_directory_if_noexist(LOGDIR.value);
7008 
7009             File.Delete(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log");
7010 
7011             CAFESTOP_STATUS.value = "0";
7012             _CCRSYSCFG1.value = "";
7013             if (initialize_serial_port_and_directory("cafestop") != 0)
7014                 return 1;
7015 
7016             //cafestop
7017             Console.WriteLine("Executing cafex stop...");
7018             FileStream fs = new FileStream(LOGDIR.value + "\\cafestop0.txt", FileMode.Create);
7019             TextWriter old_out = Console.Out;
7020             TextWriter old_err = Console.Error;
7021             StreamWriter sw = new StreamWriter(fs);
7022             Console.SetOut(sw);
7023             Console.SetError(sw);
7024 
7025             stop(null);
7026 
7027             Console.SetOut(old_out);
7028             Console.SetError(old_err);
7029             sw.Flush();
7030             sw.Close();
7031 
7032             if (File.Exists(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log"))
7033             {
7034                 File.Move(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log", LOGDIR.value + "\\cafestop0_mion.log");
7035             }
7036 
7037             if (CAFESTOP_STATUS.value != "0")
7038             {
7039                 Console.WriteLine("cafex nand2pcfs: cafestop failure.");
7040                 return 1;
7041             }
7042 
7043             //cafeon
7044             CAFEX_ERROR hostcheckversion_ret = hostcheckversion();
7045             if (hostcheckversion_ret != CAFEX_ERROR.OK)
7046             {
7047                 Console.WriteLine("cafex nand2pcfs: failed running hostcheckversion.");
7048                 return 1;
7049             }
7050 
7051             int hb_ver_flat = compute_flat_version(CAFERUN_HOSTBRIDGE_VERSION.value);
7052 
7053             Console.WriteLine("Executing cafex on...");
7054             fs = new FileStream(LOGDIR.value + "\\cafeon.txt", FileMode.Create);
7055             old_out = Console.Out;
7056             old_err = Console.Error;
7057             sw = new StreamWriter(fs);
7058             Console.SetOut(sw);
7059             Console.SetError(sw);
7060 
7061             //quiet_mode = true; // This breaks setbootmode in NAND/softlaunch
7062             Console.WriteLine("at on command");
7063             if (hb_ver_flat < compute_flat_version("3.2.4.1"))
7064             {
7065                 on(null, true, true);
7066             }
7067             else
7068             {
7069                 on(new string[] { "-e", "nomodecheck" }, true, true);
7070             }
7071 
7072             Console.WriteLine("after on command");
7073 
7074             Console.SetOut(old_out);
7075             Console.SetError(old_err);
7076             sw.Flush();
7077             sw.Close();
7078 
7079             if (File.Exists(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log"))
7080             {
7081                 File.Move(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log", LOGDIR.value + "\\cafeon_mion.log");
7082             }
7083 
7084             if (monitor_for_output("-k", "source -p -q /vol/content/", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
7085             {
7086                 Console.WriteLine("cafex nand2pcfs: monitor failed waiting for cafeon success message.");
7087                 return 1;
7088             }
7089 
7090             bool was_pcfs_boot = false;
7091             fs = new FileStream(LOGDIR.value + "\\monitor_1.txt", FileMode.Open, FileAccess.Read);
7092             StreamReader sr = new StreamReader(fs);
7093             string contents = sr.ReadToEnd();
7094             sr.Close();
7095             if (contents.Contains("BOOT1: Loaded firmware image from SDIO."))
7096             {
7097                 was_pcfs_boot = true;
7098             }
7099 
7100             //recover command
7101             Console.WriteLine("Executing devkitmsg recover -v...");
7102             devkitmsg.recover();
7103 
7104             if (monitor_for_output("-K", "WUD_BCMFWCheck", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
7105             {
7106                 Console.WriteLine("cafex nand2pcfs: monitor failed waiting for devkitmsg recover success message.");
7107                 return 1;
7108             }
7109 
7110             // if last boot was NAND, first update BOOT1 to PCFS
7111             if (was_pcfs_boot == false)
7112             {
7113 	            const string dual_boot1_folder = "aaa-boot1-dual";
7114 	            string BL_DEST_DIR = Path.Combine(Program.CAFE_MLC_DIR.value, "sys\\update\\bootloader");
7115 	            string MIXED_DEST_DIR = Path.Combine(Program.CAFE_MLC_DIR.value, "sys\\update\\mixed");
7116 
7117                 Console.WriteLine("cafex pcfs2nand: NAND boot detected, BOOT1 will be updated before updating to NAND");
7118                 Console.WriteLine("Executing devkitmsg 'update /vol/storage_hfiomlc01/sys/update/mixed' -v...");
7119 				// here we ensure we start from a flexible, configurable system
7120 
7121 	            Console.WriteLine("cafex: Checking content in '{0}'", BL_DEST_DIR);
7122 
7123 	            // Create the DUAL boot loader only directory if ir does not exist
7124 	            create_directory_if_noexist(BL_DEST_DIR);
7125 
7126 	            // Create a junction for the DUAL bootloader in the bootloader dest dir
7127 	            if (!Directory.Exists(Path.Combine(BL_DEST_DIR, dual_boot1_folder)))
7128 	            {
7129 #if DEBUG
7130 	                 Console.WriteLine("Copying directory '{0}' => '{1}'", Path.Combine(MIXED_DEST_DIR, dual_boot1_folder), Path.Combine(BL_DEST_DIR, dual_boot1_folder));
7131 #endif
7132 	                //
7133 	                // Symbolic links require NTFS which *should* not be a problem for most but
7134 	                //   require elevated privledges, which is an issue if the user is not an admin or with UAC.
7135 	                //
7136 	                // We copy the folders instead of linking them as it is relatively fast and more compatible with UAC.
7137 	                //
7138 	                FileUtil.DirectoryCopy(Path.Combine(MIXED_DEST_DIR, dual_boot1_folder), Path.Combine(BL_DEST_DIR, dual_boot1_folder), false);
7139 	            }
7140 
7141 
7142 				devkitmsg.update("/vol/storage_hfiomlc01/sys/update/bootloader");
7143 
7144                 if (monitor_for_output("-k", "Update Done, err 0", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
7145                 {
7146                     Console.WriteLine("cafex pcfs2nand: monitor failed waiting for devkitmsg 1st update success message.");
7147                     return 1;
7148                 }
7149 
7150             }
7151             else
7152             {
7153                 Console.WriteLine("cafe_pcfs2nand: PCFS boot detected, no BOOT1 update needed");
7154             }
7155 
7156             //update command
7157             if (reflash == 1)
7158             {
7159                 Console.WriteLine("Executing devkitmsg 'reflash /vol/storage_hfiomlc01/sys/update/nand' -v...");
7160                 devkitmsg.update_reflash();
7161 
7162 
7163                 if (monitor_for_output("-k", "MCP: System update was successful", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
7164                 {
7165                     Console.WriteLine("cafex pcfs2nand: monitor failed waiting for devkitmsg reflash success message.");
7166                     return 1;
7167                 }
7168             }
7169             else
7170             {
7171                 Console.WriteLine("Executing devkitmsg 'update /vol/storage_hfiomlc01/sys/update/nand' -v...");
7172                 devkitmsg.update_nand();
7173 
7174                 if (monitor_for_output("-k", "Update Done, err 0", MONITOR_DEFAULT_TIMEOUT.value, LOGDIR.value, null, true) != 0)
7175                 {
7176                     Console.WriteLine("cafex pcfs2nand: monitor failed waiting for devkitmsg update success message.");
7177                     return 1;
7178                 }
7179             }
7180 
7181             if (call_mionps == 1)
7182             {
7183                 // Set the CAT-DEV mode inside mion...
7184                 if (mionps.Run(BRIDGE_CURRENT_IP_ADDRESS.value + " 2 -s 1") != "1")
7185                 {
7186                     Console.WriteLine("cafex unable to set mode using mionps.");
7187                     return 1;
7188                 }
7189             }
7190 
7191             // set default boot mode to development
7192             devkitmsg.sys_mode_dev();
7193 
7194             //cafestop
7195             Console.WriteLine("Executing cafex stop...");
7196             fs = new FileStream(LOGDIR.value + "\\cafestop1.txt", FileMode.Create);
7197             old_out = Console.Out;
7198             old_err = Console.Error;
7199             sw = new StreamWriter(fs);
7200             Console.SetOut(sw);
7201             Console.SetError(sw);
7202 
7203             stop(null);
7204 
7205             Console.SetOut(old_out);
7206             Console.SetError(old_err);
7207             sw.Flush();
7208             sw.Close();
7209 
7210             if (File.Exists(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log"))
7211             {
7212                 File.Move(TMP.value + "\\" + SESSION_PATH_PREFIX.value + "cafestop_mion.log", LOGDIR.value + "\\cafestop1_mion.log");
7213             }
7214 
7215             if (CAFESTOP_STATUS.value != "0")
7216             {
7217                 Console.WriteLine("cafex pcfs2nand: cafestop failure.");
7218                 return 1;
7219             }
7220 
7221             //success!
7222             Console.WriteLine("Removing log directory " + LOGDIR.value + "...");
7223             ForceRemoveDirectory(LOGDIR.value);
7224             Console.WriteLine("cafex pcfs2nand complete. Exiting with code 0");
7225 
7226             return 0;
7227         }
7228 #endif
7229 
7230         //Script function: hostcheckversion
hostcheckversion()7231         static CAFEX_ERROR hostcheckversion()
7232         {
7233             #if DEBUG
7234                 Log.WriteLine("hostcheckversion started.");
7235             #endif
7236 
7237             getbridgetype();
7238 
7239             string min_fw_ver = string.Empty;
7240             string min_sw_ver = string.Empty;
7241 
7242             if (BRIDGE_TYPE.value == "Mion")
7243             {
7244                 min_fw_ver = MIN_MION_FW_VER;
7245                 min_sw_ver = MIN_MION_SW_VER;
7246             }
7247             else
7248             {
7249                 min_sw_ver = "2.9.1.5";
7250                 min_fw_ver = "2.8.0.13";
7251             }
7252 
7253             if (SDIO_BRIDGE_TOOLS.value == null)
7254             {
7255                 if (MION_BRIDGE_TOOLS.value == null)
7256                 {
7257                     Console.WriteLine("cafex run failed: Please install HostBridge (version >= " + min_sw_ver + ") and reopen the build environment!");
7258                     return CAFEX_ERROR.HOSTCHECKVERSION_NO_HOSTBRIDGE;
7259                 }
7260             }
7261 
7262             if (fw_ver_flat == 0 || sw_ver_flat == 0)
7263             {
7264                 string fw_ver = string.Empty;
7265                 string sw_ver = string.Empty;
7266 
7267                 if (BRIDGE_TYPE.value == "Mion")
7268                 {
7269                     FSEmul.FW_SW_Version(BRIDGE_CURRENT_IP_ADDRESS.value, out fw_ver, out sw_ver);
7270                 }
7271                 else
7272                 {
7273                     FSEmul.FW_SW_Version(null, out fw_ver, out sw_ver);
7274                 }
7275 
7276                 if (fw_ver == string.Empty || sw_ver == string.Empty)
7277                 {
7278                     Console.WriteLine("cafex run failed: Cannot check HostBridge version. Please stop the DEVKIT and try again.");
7279                     return CAFEX_ERROR.HOSTCHECKVERSION_FSEMUL_FAILED;
7280                 }
7281 
7282                 fw_ver_flat = compute_flat_version(fw_ver);
7283                 sw_ver_flat = compute_flat_version(sw_ver);
7284 
7285                 CAFERUN_HOSTBRIDGE_VERSION.value = sw_ver;
7286                 CAFERUN_FW_VERSION.value = fw_ver;
7287             }
7288             else
7289             {
7290                 CAFERUN_HOSTBRIDGE_VERSION.value = compute_ver_string(sw_ver_flat);
7291                 CAFERUN_FW_VERSION.value = compute_ver_string(fw_ver_flat);
7292             }
7293 
7294             int min_fw_flat = compute_flat_version(min_fw_ver);
7295             int min_sw_flat = compute_flat_version(min_sw_ver);
7296 
7297             if (sw_ver_flat < min_sw_flat || fw_ver_flat < min_fw_flat)
7298             {
7299                 Console.WriteLine("cafex run failed: Please upgrade the HostBridge to at least version " + min_sw_ver + " and reopen the build environment!");
7300                 Console.WriteLine("                  Current software version is " + CAFERUN_HOSTBRIDGE_VERSION.value + " (need " + min_sw_ver + ")");
7301                 Console.WriteLine("                  Current firmware version is " + CAFERUN_FW_VERSION.value + " (need " + min_fw_ver + ")");
7302                 return CAFEX_ERROR.HOSTCHECKVERSION_OLD_VERSIONS;
7303             }
7304 
7305             return CAFEX_ERROR.OK;
7306         }
7307 
7308         //Script function: syncsession
syncsession(string[] args)7309         static CAFEX_ERROR syncsession(string[] args)
7310         {
7311             #if DEBUG
7312                 Log.WriteLine("syncsession started.");
7313                 string argString = null;
7314                 if (args != null)
7315                 {
7316                     foreach (string arg in args)
7317                     {
7318                         argString += arg + " ";
7319                     }
7320                 }
7321                 Log.WriteLine("Arguments=" + argString);
7322 
7323             #endif
7324 
7325             if (args != null && args.Length > 0)
7326             {
7327                 if (args[0] == "-h")
7328                 {
7329                     syncsession_usage();
7330                     return CAFEX_ERROR.OK;
7331                 }
7332                 else
7333                 {
7334                     Console.WriteLine("cafex syncsession failed: Invalid argument");
7335                     return CAFEX_ERROR.UPDATE_INVALID_OPTION;
7336                 }
7337             }
7338 
7339             if (SESSION_MANAGER.value == "1")
7340             {
7341                 stop(null);
7342 
7343                 SYNCTOOL_SRC.value = PathConverter.Windowsify(Path.Combine(CAFE_ROOT.value, "data"));
7344                 SYNCTOOL_DEST.value = PathConverter.Windowsify(CAFE_DATA_DIR.value);
7345                 SYNCTOOL_CFG.value = PathConverter.Windowsify(Path.Combine(CAFE_ROOT.value, "system/bin/tool/synctool.data.xml"));
7346                 SYNCTOOL_LOG.value = PathConverter.Windowsify(Path.Combine(CAFE_ROOT.value, SESSION_PATH_PREFIX.value + "sync.log"));
7347 
7348                 Console.WriteLine("cafex syncsession: Syncronizing {0} ===> {1}...", SYNCTOOL_SRC.value, SYNCTOOL_DEST.value);
7349 
7350                 int SYNCTOOL_RVAL = synctool.sync(SYNCTOOL_CFG.value, SYNCTOOL_SRC.value, SYNCTOOL_DEST.value, SYNCTOOL_LOG.value);
7351                 if (SYNCTOOL_RVAL != 0)
7352                 {
7353                     Console.WriteLine("                 : Session data sync FAILED with exit code {0}!", SYNCTOOL_RVAL);
7354                     Console.WriteLine("                 :   See {0} for details.", SYNCTOOL_LOG.value);
7355                     return CAFEX_ERROR.SYNCTOOL_FAILED;
7356                 }
7357                 else
7358                 {
7359                     Console.WriteLine("                 : Session data sync log at {0}", SYNCTOOL_LOG.value);
7360                 }
7361             }
7362 
7363             return CAFEX_ERROR.OK;
7364         }
7365 
getPathToMakeCfMaster()7366         private static String getPathToMakeCfMaster()
7367         {
7368             Assembly assembly = Assembly.GetExecutingAssembly();
7369             String path = assembly.Location;
7370             String directory = Path.GetDirectoryName(path);
7371             String filename = directory + @"\makecfmaster.exe";
7372 
7373             if (File.Exists(filename))
7374                 return filename;
7375 
7376             directory = Environment.GetEnvironmentVariable("CAFE_MASTERING_TOOLS");
7377             if (directory != null)
7378             {
7379                 filename = directory + @"\makecfmaster.exe";
7380 
7381                 if (File.Exists(filename))
7382             {
7383                     return filename;
7384             }
7385         }
7386 
7387             directory = Environment.GetEnvironmentVariable("CAFE_ROOT");
7388             if (directory != null)
7389         {
7390                 filename = directory + @"\system\bin\tool\mastering\makecfmaster.exe";
7391 
7392                 if (File.Exists(filename))
7393             {
7394                     return filename;
7395             }
7396 			}
7397 
7398             return null;
7399             }
7400 
processDataReceived(object sender, DataReceivedEventArgs args)7401         private static void processDataReceived(object sender, DataReceivedEventArgs args)
7402             {
7403             Console.WriteLine(args.Data);
7404             }
7405 
makeMaster(string[] args)7406         static CAFEX_ERROR makeMaster(string[] args)
7407         {
7408 
7409 #if DEBUG
7410             Log.WriteLine("master started.");
7411             string argString = null;
7412             if (args != null)
7413             {
7414                 foreach (string arg in args)
7415                 {
7416                     argString += arg + " ";
7417                 }
7418             }
7419             Log.WriteLine("Arguments=" + argString);
7420 
7421 #endif
7422             Process p = new Process();
7423 
7424             p.StartInfo.FileName = getPathToMakeCfMaster();
7425             p.StartInfo.Arguments = "archive " + string.Join(" ", args);
7426             p.StartInfo.CreateNoWindow = true;
7427             p.StartInfo.UseShellExecute = false;
7428             p.StartInfo.RedirectStandardOutput = true;
7429             p.StartInfo.RedirectStandardError = true;
7430 
7431             try
7432 			{
7433                 p.Start();
7434 
7435                 p.OutputDataReceived += processDataReceived;
7436                 p.ErrorDataReceived += processDataReceived;
7437 
7438                 p.BeginOutputReadLine();
7439                 p.BeginErrorReadLine();
7440                 p.WaitForExit();
7441                 }
7442             catch (Win32Exception e)
7443                 {
7444                 Console.Write(e.Message);
7445                     return CAFEX_ERROR.MASTERING_ERROR;
7446                 }
7447 
7448             Int64 returnVal = p.ExitCode;
7449                 if (returnVal != 0)
7450                 {
7451                     Console.WriteLine("MAKE DISC ERROR!!!  CODE: {0}", returnVal);
7452                     CAFEX_ERROR masteringError = (CAFEX_ERROR)returnVal;
7453                     return masteringError;
7454                 }
7455 
7456                 return CAFEX_ERROR.OK;
7457             }
7458 
7459         //this function emulates cafediscrun upto creation of
7460         //.dlf file. Then it calls cafeon with -c option to launch
7461         //the title through system config tool.
7462         //Steps:
7463         //1. Create dlf file
7464         //2. Make sure to append the <title.dlf> file to arguments to
7465         //   FSEmul.exe
7466         //3. Call on with -c "launch -p -l <titleid>. You can get the title
7467         // id from app.xml of the title
launchTitle(string[] args)7468         static CAFEX_ERROR launchTitle(string[] args)
7469         {
7470             CAFEX_ERROR result = CAFEX_ERROR.OK;
7471 #if DEBUG
7472             Log.WriteLine("makeDownload started.");
7473             string argString = null;
7474             if (args != null)
7475             {
7476                 foreach (string arg in args)
7477                 {
7478                     argString += arg + " ";
7479                 }
7480             }
7481             Log.WriteLine("Arguments=" + argString);
7482 
7483 #endif
7484             string rpxPath = string.Empty;
7485             StringBuilder launchArgs = null;
7486             bool gotRpx = false;
7487 
7488             execLaunchCmd = true;
7489 
7490             if (args.Length > 1)
7491             {
7492                 launchArgs = new StringBuilder();
7493             }
7494             for (int i = 0; i < args.Length; i++)
7495             {
7496                 string s = args[i];
7497                 if (!string.IsNullOrEmpty(s))
7498                 {
7499                     if (!gotRpx && (s.StartsWith("-") || s.CompareTo("help") == 0))
7500                     {
7501                         switch (s)
7502                         {
7503                             case "-h":
7504                             case "-?":
7505                             case "help":
7506                                 launch_usage();
7507                                 return CAFEX_ERROR.OK;
7508                             default:
7509                                 Console.WriteLine("cafex: Invalid parameter.");
7510                                 launch_usage();
7511                                 return CAFEX_ERROR.MASTERING_ERROR;
7512                         }
7513                     }
7514                     else if (s.Contains(".rpx")) //Must be path to the rpx file
7515                     {
7516                         rpxPath = s;
7517                         gotRpx = true;
7518                     }
7519                     else //must be arguments for the rpx
7520                     {
7521                         launchArgs.Append(" " + s);
7522                     }
7523                 }
7524             }
7525 
7526             if (string.IsNullOrEmpty(rpxPath))
7527             {
7528                 Console.WriteLine("cafex: Invalid parameter.");
7529                 launch_usage();
7530                 return CAFEX_ERROR.MASTERING_ERROR;
7531             }
7532 
7533             string winrpxPath = PathConverter.Windowsify(rpxPath);
7534             winrpxPath = PathConverter.Root(winrpxPath);
7535             winrpxPath = Path.GetFullPath(winrpxPath);
7536             //string rpxDir = winrpxPath.Substring(0, winrpxPath.LastIndexOf('\\'));
7537             //string rpxName = winrpxPath.Substring(winrpxPath.LastIndexOf('\\') + 1);
7538             //string rpxDLF = Path.ChangeExtension(winrpxPath, ".dlf");
7539             //string rpxELF = Path.ChangeExtension(winrpxPath, ".elf");
7540 
7541             string rpxDir = Path.GetDirectoryName(winrpxPath);
7542             string rpxName = Path.GetFileName(winrpxPath);
7543             string rpxDLF = Path.ChangeExtension(winrpxPath, ".dlf");
7544             string rpxELF = Path.ChangeExtension(winrpxPath, ".elf");
7545 
7546             //Below parameter must be set before we even start anything
7547             if (string.IsNullOrEmpty(CAFE_CODE_DIR.value))
7548             {
7549                 if (string.IsNullOrEmpty(CAFE_ELF_DIR.value))
7550                 {
7551                     CAFE_ELF_DIR.value = rpxDir;
7552                 }
7553                 CAFE_CODE_DIR.value = CAFE_ELF_DIR.value;
7554             }
7555 
7556 
7557             //Run discrun to enable all the required setup variables
7558             //Note that we are only doing initialization and not launching the
7559             //application.
7560             string[] runArgs =
7561             {
7562                 "-b",
7563                 winrpxPath
7564             };
7565             result = discrun(runArgs, true, false).error;
7566             if (result != CAFEX_ERROR.OK)
7567             {
7568                 return result;
7569             }
7570 
7571             //Make sure to remove "0x" from CAFERUN_COLDBOOT_OS_VERSION.value
7572             if (CAFERUN_COLDBOOT_OS_VERSION.value.Contains("0x"))
7573             {
7574                 CAFERUN_COLDBOOT_OS_VERSION.value = CAFERUN_COLDBOOT_OS_VERSION.value.Substring(2);
7575             }
7576 
7577             //Make ppc_boot.dlf and fw.img file which is needed to run system config tool
7578             result = bootrun(new List<string> { "-makedlf" }, false);
7579             if (result != CAFEX_ERROR.OK)
7580             {
7581                 Console.WriteLine("cafex: Failed to run bootrun.");
7582                 return result;
7583             }
7584 
7585             //Make dlf file and store it in the same directory as the rpx
7586             //The dlf generated here will be passed to FSEmul to mounting the title on ODD
7587             result = devrun(rpxELF, null, null, null);
7588             if (result != CAFEX_ERROR.OK)
7589             {
7590                 Console.WriteLine("cafex: Failed to run devrun.");
7591                 return result;
7592             }
7593 
7594             if (string.IsNullOrEmpty(BOOT_DLF_FILE.value))
7595             {
7596                 BOOT_DLF_FILE.value = CAFE_TEMP.value + "\\" + SESSION_PATH_PREFIX.value + "caferun" + "\\ppc_boot.dlf";
7597             }
7598 
7599             //Make sure SOFT_LUANCH is disabled
7600             CAFERUN_OPTION_SOFT_LAUNCH.value = "0";
7601 
7602 
7603             //call hostrun to launch FSEMUL
7604             hostrun(BOOT_DLF_FILE.value + " " + rpxDLF);
7605 
7606             extract_info_from_app_xml(rpxDir + "\\app.xml");
7607 
7608             LAUNCH_DLF_FILE = rpxDLF;
7609             string[] onArgs =
7610             {
7611                 "-c launch -p -l 0x" + APP_TITLE_ID.value + ((launchArgs != null) ? launchArgs.ToString():string.Empty)
7612             };
7613 
7614             on(onArgs, false, true);
7615             return CAFEX_ERROR.OK;
7616         }
7617         #endregion
7618 
7619         #region SCRIPT HELPERS
7620 
initialize_work_directory(string directory)7621         static void initialize_work_directory(string directory)
7622         {
7623             #if DEBUG
7624                 Log.WriteLine("initialize_work_diretory started.");
7625             #endif
7626 
7627             if (!Directory.Exists(directory))
7628             {
7629                 Directory.CreateDirectory(directory);
7630             }
7631 
7632             File.Delete(directory + "\\diskid.bin");
7633             File.Delete(directory + "\\ppc.bsf");
7634             File.Delete(directory + "\\ppc_boot.dlf");
7635         }
7636 
make_boot1_system_file(string bsf_file)7637         static CAFEX_ERROR make_boot1_system_file(string bsf_file)
7638         {
7639             #if DEBUG
7640                 Log.WriteLine("make_boot1_system_file started.");
7641             #endif
7642 
7643             string flags = "0";
7644 
7645             string firmware_filename = Path.GetFileName(FIRMWARE_FILE.value);
7646             if (firmware_filename.StartsWith("fw"))
7647             {
7648                 flags = "0x80000000";
7649             }
7650 
7651             if (makebsf.make(QUIET.value, bsf_file, flags) != 0)
7652             {
7653                 Console.WriteLine("cafex bootrun failed: Cannot generate bsf file.");
7654                 return CAFEX_ERROR.BOOTRUN_MAKEBSF_FAILED;
7655             }
7656 
7657             return CAFEX_ERROR.OK;
7658         }
7659 
make_boot_dlf(string file_list, string output_dlf_file)7660         static CAFEX_ERROR make_boot_dlf(string file_list, string output_dlf_file)
7661         {
7662             #if DEBUG
7663                 Log.WriteLine("make_boot_dlf started.");
7664             #endif
7665 
7666             string commandResult = string.Empty;
7667             if (makedlf.make(QUIET.value, file_list, output_dlf_file, out commandResult) != 0)
7668             {
7669                 Console.WriteLine("cafex bootrun failed: Cannot generate dlf file.");
7670                 Console.WriteLine("Command output: " + commandResult);
7671                 return CAFEX_ERROR.BOOTRUN_MAKEDLF_FAILED;
7672             }
7673 
7674             return CAFEX_ERROR.OK;
7675         }
7676 
make_wumad_dlf(string wumadFile, string extractionFolder, string output_dlf_file)7677         static CAFEX_ERROR make_wumad_dlf(string wumadFile, string extractionFolder, string output_dlf_file)
7678         {
7679             #if DEBUG
7680                 Log.WriteLine("make_wumad_dlf started. Arguments: wumadFile=" + wumadFile + ", extractionFolder=" + extractionFolder + ", output_dlf_file=" + output_dlf_file);
7681             #endif
7682 
7683             if (makewumaddlf.make(wumadFile, extractionFolder, output_dlf_file) != 0)
7684             {
7685                 Console.WriteLine("cafex bootrun failed: Cannot generate dlf file from WUMAD.");
7686                 return CAFEX_ERROR.BOOTRUN_MAKEDLF_FAILED;
7687             }
7688 
7689             return CAFEX_ERROR.OK;
7690         }
7691 
extract_info_from_app_xml(string app_xml_file)7692         static void extract_info_from_app_xml(string app_xml_file)
7693         {
7694             #if DEBUG
7695                 Log.WriteLine("extract_info_from_app_xml started.");
7696             #endif
7697 
7698             APP_TITLE_ID.value = XmlHandler.GetNodeValue(app_xml_file, "title_id");
7699             APP_GROUP_ID.value = XmlHandler.GetNodeValue(app_xml_file, "group_id");
7700             APP_TITLE_VERSION.value = XmlHandler.GetNodeValue(app_xml_file, "title_version");
7701 
7702             Console.WriteLine("App Title ID : " + APP_TITLE_ID.value);
7703             Console.WriteLine("App Group ID : " + APP_GROUP_ID.value);
7704             Console.WriteLine("App Title Version : " + APP_TITLE_VERSION.value);
7705         }
7706 
connect_serial_or_debugger(bool quiet_mode)7707         static CafeXReturn connect_serial_or_debugger(bool quiet_mode)
7708         {
7709             #if DEBUG
7710                 Log.WriteLine("connect_serial_or_debugger started. quiet_mode=" + quiet_mode.ToString() + ", DEBUGGER=" + DEBUGGER.value);
7711             #endif
7712 
7713             switch (DEBUGGER.value)
7714             {
7715                 case "multi":
7716                     {
7717                         break;
7718                     }
7719 
7720                 case "gdb":
7721                 case "gdbtui":
7722                     {
7723                         cattoucan.FinishSync(true);
7724                         if (FileUtil.RunningFromCygwin && DEBUGGER.value == "gdb")
7725                         {
7726                             Console.WriteLine("cafex run error: gdb debugger is not compatible with cafex.");
7727                             Console.WriteLine("Please disable cafex with \"export USE_CAFEX=0\" and run the command with BASH caferun.");
7728                         }
7729                         else
7730                         {
7731                             Console.WriteLine("cafex run error: Only Multi debugger supported");
7732                         }
7733 
7734                         return new CafeXReturn(CAFEX_ERROR.RUN_NON_MULTI_DEBUGGER);
7735                     }
7736 
7737                 case "cattoucan":
7738                     {
7739                         CafeXReturn ret = new CafeXReturn(CAFEX_ERROR.OK);
7740                         ret.appExitCode = cattoucan.start(no_console, false);
7741 
7742                         return ret;
7743                     }
7744 
7745                 case "none":
7746                     {
7747                         cattoucan.FinishSync(true);
7748                         if (CONSOLE.value != "toucan")
7749                         {
7750                             CAFE_DEBUG_PORT.value = "toucan";
7751                         }
7752                         return new CafeXReturn(CAFEX_ERROR.OK);
7753                     }
7754 
7755                 default:
7756                     {
7757                         cattoucan.FinishSync(true);
7758                         Console.WriteLine("cafex run failed: " + DEBUGGER.value + " unsupported debugger.");
7759                         return new CafeXReturn(CAFEX_ERROR.RUN_BAD_DEBUGGER);
7760                     }
7761             }
7762 
7763             if (CAFE_DEBUG_PORT.value != "toucan")
7764             {
7765                 cattoucan.FinishSync(true);
7766                 Console.WriteLine("cafex run failed: Unknown debugger port " + CAFE_DEBUG_PORT.value);
7767                 return new CafeXReturn(CAFEX_ERROR.RUN_BAD_DEBUGGER_PORT);
7768             }
7769 
7770 #if DEBUG
7771             Log.WriteLine("DEBUGGER = multi");
7772 #endif
7773             MULTIELF.value = "";
7774             if (DEBUG_ELF_FILE.value != null)
7775             {
7776                 // Make sure the MULTIELF has windows-style path
7777                 MULTIELF.value = PathConverter.Windowsify(DEBUG_ELF_FILE.value);
7778             }
7779 
7780             CATTOUCAN_STATUS.value = cattoucan.start(no_console, false).ToString();
7781 
7782             if (string.IsNullOrEmpty(MULTI_CONNECT.value))
7783             {
7784                 if (USE_EXI_AS_DEBUG_CHANNEL.value != null && USE_EXI_AS_DEBUG_CHANNEL.value.Equals("1"))
7785                 {
7786                     MULTI_CONNECT.value = "\"-connect=cafeserv -iphost " + BRIDGE_CURRENT_IP_ADDRESS.value + " -console_iphost localhost -ipport 7977 -console_ipport " + SESSION_DEBUG_OUT_PORT.value + " -auto_first\"";
7787                 }
7788                 else
7789                 {
7790                     MULTI_CONNECT.value = "\"-connect=cafeserv -iphost localhost -ipport " + SESSION_DEBUG_CONTROL_PORT.value + " -console_ipport " + SESSION_DEBUG_OUT_PORT.value + " -auto_first\"";
7791                 }
7792             }
7793 
7794 #if DEBUG
7795                 Log.WriteLine("MULTI_CONNECT before calling multi = " + MULTI_CONNECT.value);
7796                 Log.WriteLine("CATTOUCAN_STATUS.value = " + CATTOUCAN_STATUS.value);
7797                 Log.WriteLine("CAFE_LAUNCH_DEBUG.value = " + CAFE_LAUNCH_DEBUG.value);
7798 #endif
7799 
7800             if (CATTOUCAN_STATUS.value == "42")
7801             {
7802                 if (CAFE_LAUNCH_DEBUG.value == "1")
7803                 {
7804                     multi.start(MULTI_CONNECT.value, CAFE_MULTI_INIT.value, MULTIELF.value);
7805                 }
7806                 else
7807                 {
7808                     Console.WriteLine("Ready to connect from multi");
7809                     Console.WriteLine(GHS_ROOT.value + "\\multi.exe -cmd prepare_target " + MULTI_CONNECT.value + " " + CAFE_MULTI_INIT.value + " " + MULTIELF.value);
7810                 }
7811 
7812                 if (CMDOUTPUT.value == "1")
7813                 {
7814                     #if DEBUG
7815                         Log.WriteLine("CMDOUTPUT = 1 -> calling cattoucan.start...");
7816                     #endif
7817 
7818                     cattoucan.start(no_console, false);
7819                 }
7820             }
7821 #if DEBUG
7822             Log.WriteLine("connect_serial_or_debugger completed.");
7823 #endif
7824             return new CafeXReturn(CAFEX_ERROR.OK);
7825 
7826         }
7827 
initialize_serial_port_and_directory(string stop_cmd)7828         static int initialize_serial_port_and_directory(string stop_cmd)
7829         {
7830             #if DEBUG
7831                 Log.WriteLine("initialize_serial_port_and_directory started.");
7832             #endif
7833 
7834             if (stop_cmd == null)
7835             {
7836                 Console.WriteLine("\"Usage: Initialize_serial_port_and_directory stop_cmd\", where stop_cmd is cafestop or a bash function call.");
7837                 return 1;
7838             }
7839 
7840             create_directory_if_noexist(LOGDIR.value);
7841 
7842             if (stop_cmd == "cafestop")
7843             {
7844                 stop(null);
7845             }
7846 
7847             //trap
7848 
7849             if (CAFE_CONSOLE.value == "cattoucan")
7850             {
7851                 //trap
7852                 CAFE_CONSOLE.value = "toucan";
7853             }
7854 
7855             if (CAFE_CONSOLE.value == "cmdtoucan")
7856             {
7857                 //trap
7858                 CAFE_CONSOLE.value = "toucan";
7859             }
7860 
7861             if (CAFE_CONSOLE.value == "catwaikiki")
7862             {
7863                 //trap
7864                 CAFE_CONSOLE.value = "waikiki";
7865             }
7866 
7867             #if DEBUG
7868                 Log.WriteLine("CAFE_CONSOLE=" + CAFE_CONSOLE.value);
7869             #endif
7870 
7871             if (COMPORTS_SUPPORT.value == "-c")
7872             {
7873                 int init_flag = 0;
7874                 INITIALIZED_COMPORTS.value = "";
7875 
7876                 for (int COMPORT = 1; COMPORT <= 20; ++COMPORT)
7877                 {
7878                     if (cmd.mode(COMPORT) == 0)
7879                     {
7880                         Console.WriteLine("Initialized COM" + COMPORT);
7881                         init_flag = 1;
7882                         INITIALIZED_COMPORTS.AddToVar("COM" + COMPORT + " ", ' ');
7883                     }
7884                 }
7885 
7886                 if (init_flag == 0 && CAFE_CONSOLE.value != "toucan")
7887                 {
7888                     Console.WriteLine("ERROR: no serial port is available.");
7889                     Console.WriteLine("Please close other softwares using serial port,");
7890                     Console.WriteLine("such as HyperTerminal.");
7891                     Console.WriteLine();
7892                     Console.WriteLine("This automated test script cannot share the serial port");
7893                     Console.WriteLine("with other softwares.");
7894                     return 1;
7895                 }
7896             }
7897 
7898             return 0;
7899         }
7900 
monitor_for_output(string str_opt, string test_str, string timeout, string log_dir, string file_name, bool printToScreen)7901         static int monitor_for_output(string str_opt, string test_str, string timeout, string log_dir, string file_name, bool printToScreen)
7902         {
7903             #if DEBUG
7904                 Log.WriteLine("monitor_for_output started.");
7905             #endif
7906 
7907             create_directory_if_noexist(log_dir);
7908 
7909             if (MONITOR_FOR_OUTPUT_CALLS.value == null)
7910             {
7911                 MONITOR_FOR_OUTPUT_CALLS.value = "0";
7912             }
7913 
7914             MONITOR_FOR_OUTPUT_CALLS.value = (HexHandler.GetNumberFromString(MONITOR_FOR_OUTPUT_CALLS.value) + 1).ToString();
7915             string call_no = MONITOR_FOR_OUTPUT_CALLS.value;
7916             string mon_rc_file = log_dir + "\\monitor_return_code" + call_no + ".txt";
7917 
7918             if (file_name == null)
7919             {
7920                 file_name = "monitor_" + call_no + ".txt";
7921             }
7922 
7923             string log_file = log_dir + "\\" + file_name;
7924 
7925             // Write to the log file all the output and print to the screen, if printToScreen is true.
7926             FileStream fs = new FileStream(log_file, FileMode.Create);
7927             StreamWriter sw = new StreamWriter(fs);
7928             DataReceivedEventHandler callback = (sender, e) =>
7929             {
7930                 if (e != null && e.Data != null && sw != null)
7931                 {
7932                     string outputData = e.Data;
7933                     if (printToScreen)
7934                     {
7935                         Console.WriteLine(outputData);
7936                     }
7937                     try
7938                     {
7939                         sw.WriteLine(outputData);
7940                         sw.Flush();
7941                     }
7942                     catch (IOException)
7943                     { }
7944                     catch (ObjectDisposedException)
7945                     { }
7946                 }
7947             };
7948 
7949             int retVal =  monitor_for_output_redirectionCallback(str_opt, test_str, timeout, callback);
7950 
7951             sw.Close();
7952 
7953             fs = new FileStream(mon_rc_file, FileMode.Create);
7954             sw = new StreamWriter(fs);
7955             sw.WriteLine(retVal);
7956             sw.Flush();
7957             sw.Close();
7958 
7959             return retVal;
7960         }
7961 
monitor_for_output_redirectionCallback(string str_opt, string test_str, string timeout, DataReceivedEventHandler callback)7962         static int monitor_for_output_redirectionCallback(string str_opt, string test_str, string timeout, DataReceivedEventHandler callback)
7963         {
7964             #if DEBUG
7965                 Log.WriteLine("monitor_for_output_redirectionCallback started.");
7966             #endif
7967 
7968             string ret = monitor.start_redirectionCallback(str_opt, test_str, timeout, callback).ToString();
7969 
7970             int return_val = evaluate_monitor_return_value(ret);
7971             if (return_val == 0)
7972             {
7973                 Console.WriteLine("monitor returned PASS");
7974             }
7975             else
7976             {
7977                 return return_val;
7978             }
7979 
7980             return 0;
7981         }
7982 
evaluate_monitor_return_value(string mon_rval)7983         static int evaluate_monitor_return_value(string mon_rval)
7984         {
7985             #if DEBUG
7986                 Log.WriteLine("evaluate_monitor_return_value started.");
7987             #endif
7988 
7989             int return_val = 1;
7990             string status_str = string.Empty;
7991 
7992             if (mon_rval == MON_RESULT_PASS.value)
7993             {
7994                 return_val = 0;
7995             }
7996 
7997             else if (mon_rval == MON_RESULT_TIMEOUT.value)
7998             {
7999                 status_str = "TIMEOUT";
8000             }
8001 
8002             else if (mon_rval == MON_RESULT_UNDEF.value)
8003             {
8004                 status_str = "UNDEF";
8005             }
8006 
8007             else if (mon_rval == MON_RESULT_MANUAL.value)
8008             {
8009                 status_str = "MANUAL";
8010             }
8011 
8012             else if (mon_rval == MON_RESULT_NOLOG.value)
8013             {
8014                 status_str = "NOLOG";
8015             }
8016 
8017             else if (mon_rval == MON_RESULT_FAIL.value)
8018             {
8019                 status_str = "FAIL";
8020             }
8021 
8022             else if (mon_rval == MON_RESULT_EXPECTED_TERM.value)
8023             {
8024                 status_str = "EXPECTED_TERM";
8025             }
8026 
8027             else if (mon_rval == MON_RESULT_EXEC_WIN_APP.value)
8028             {
8029                 status_str = "EXEC_WIN_APP";
8030             }
8031 
8032             else if (mon_rval == MON_RESULT_NOPPC.value)
8033             {
8034                 status_str = "NOPPC";
8035             }
8036 
8037             else if (mon_rval == MON_RESULT_BOOT1.value)
8038             {
8039                 status_str = "BOOT1";
8040             }
8041 
8042             else if (mon_rval == MON_RESULT_RESTART.value)
8043             {
8044                 status_str = "RESTART";
8045             }
8046 
8047             else if (mon_rval == MON_RESULT_TEST_AS_RPL.value)
8048             {
8049                 status_str = "TEST_AS_RPL";
8050             }
8051 
8052             else if (mon_rval == MON_RESULT_END_OF_RPL_LOADER.value)
8053             {
8054                 status_str = "END_OF_RPL_LOADER";
8055             }
8056 
8057             else if (mon_rval == MON_RESULT_BRIDGE_COLLISION.value)
8058             {
8059                 status_str = "BRIDGE_COLLISION";
8060             }
8061 
8062             else if (mon_rval == MON_RESULT_TEST_DBG_OUT.value)
8063             {
8064                 status_str = "TEST_DBG_OUT";
8065             }
8066 
8067             else if (mon_rval == MON_RESULT_BRIDGE_OFF.value)
8068             {
8069                 status_str = "BRIDGE_OFF";
8070             }
8071 
8072             else if (mon_rval == MON_RESULT_ERROR.value)
8073             {
8074                 status_str = "ERROR";
8075             }
8076 
8077             else if (mon_rval == MON_RESULT_FATAL_ERROR.value)
8078             {
8079                 status_str = "FATAL_ERROR";
8080             }
8081 
8082             else if (mon_rval == MON_RESULT_MISSING.value)
8083             {
8084                 status_str = "MISSING";
8085             }
8086 
8087             else if (mon_rval == MON_RESULT_ABORTED.value)
8088             {
8089                 status_str = "ABORTED";
8090             }
8091 
8092             else
8093             {
8094                 status_str = mon_rval.ToString();
8095             }
8096 
8097             if (return_val != 0)
8098             {
8099                 Console.WriteLine("monitor returned " + status_str);
8100                 return return_val;
8101             }
8102 
8103             return 0;
8104         }
8105 
check_xml_version(string file_dest, string file_default, string file_option)8106         static bool check_xml_version(string file_dest, string file_default, string file_option)
8107         {
8108             #if DEBUG
8109                 Log.WriteLine("check_xml_version started.");
8110             #endif
8111 
8112             if (!File.Exists(file_dest))
8113             {
8114                 Console.WriteLine("cafex run: Copying default config file to " + file_dest);
8115                 if (!File.Exists(file_default))
8116                 {
8117                     Console.WriteLine("cafex run failed: Cannot find default config file " + file_default);
8118                     return false;
8119                 }
8120 
8121                 create_directory_if_noexist(Path.GetDirectoryName(file_dest));
8122 
8123                 File.Copy(file_default, file_dest, true);
8124                 File.SetAttributes(file_dest, FileAttributes.Normal);
8125             }
8126             else
8127             {
8128                 string ver_default = XmlHandler.GetNodeValue(file_default, "version");
8129                 string ver_dest = XmlHandler.GetNodeValue(file_dest, "version");
8130                 #if DEBUG
8131                     Log.WriteLine("file_dest: " + file_dest + ", ver_default: " + ver_default + " - ver_dest: " + ver_dest);
8132                 #endif
8133                 if (ver_dest == null || ver_default == null)
8134                 {
8135                     Console.WriteLine("cafex run failed: Cannot get xml version numbers");
8136                     return false;
8137                 }
8138 
8139                 if (IGNORE_VERSION.value == null)
8140                 {
8141                     if (ver_dest != ver_default)
8142                     {
8143                         if (file_option == "copy_default_if_mismatch")
8144                         {
8145                             Console.WriteLine("cafex run: Config file version mismatch detected: " + ver_dest + " vs. required " + ver_default);
8146                             Console.WriteLine("  Copying default config file to " + file_dest);
8147                             if (!File.Exists(file_default))
8148                             {
8149                                 Console.WriteLine("cafex run failed: Cannot find default config file " + file_default);
8150                                 return false;
8151                             }
8152 
8153                             create_directory_if_noexist(Path.GetDirectoryName(file_dest));
8154 
8155                             File.Copy(file_default, file_dest, true);
8156                             File.SetAttributes(file_dest, FileAttributes.Normal);
8157                         }
8158                         else
8159                         {
8160                             Console.WriteLine("cafex run failed: Please update or delete config file: " + file_dest);
8161                             Console.WriteLine("  Version number mismatch: " + ver_dest + " vs. required " + ver_default);
8162                             return false;
8163                         }
8164                     }
8165                 }
8166             }
8167 
8168             return true;
8169         }
8170 
args_to_bar_sep_list(string[] input)8171         static string args_to_bar_sep_list(string[] input)
8172         {
8173             return StringCombiner.MakeDelimitedString(input, '|');
8174         }
8175 
exit_if_specials(string[] arglist)8176         static bool exit_if_specials(string[] arglist)
8177         {
8178             #if DEBUG
8179                 Log.WriteLine("exit_if_specials started.");
8180             #endif
8181 
8182             foreach (string s in arglist)
8183             {
8184                 if (s.Contains("?") || s.Contains("+") || s.Contains("<") || s.Contains(">") || s.Contains("|"))
8185                 {
8186                     Console.WriteLine("cafex run failed: Unable to parse special character (?+<>|) in arg list.");
8187                     Console.WriteLine("  arglist: " + s);
8188                     return false;
8189                 }
8190             }
8191             return true;
8192         }
8193 
update_arglist(string file_dest, string cafe_elf, string[] arglist)8194         static bool update_arglist(string file_dest, string cafe_elf, string[] arglist)
8195         {
8196             #if DEBUG
8197                 Log.WriteLine("update_arglist started.");
8198             #endif
8199 
8200             string[] arglist_without_rpx = new string[arglist.Length - 1];
8201             Array.Copy(arglist, 1, arglist_without_rpx, 0, arglist_without_rpx.Length);
8202 
8203             bool exit_if_specials_ret = exit_if_specials(arglist_without_rpx);
8204             if (!exit_if_specials_ret)
8205             {
8206                 return false;
8207             }
8208 
8209             string args_trailing_with_bars = args_to_bar_sep_list(arglist_without_rpx);
8210 
8211             if (DASH_A_ARGS.value == null)
8212             {
8213                 ARGS_WITH_BARS.value = args_trailing_with_bars;
8214             }
8215             else
8216             {
8217                 ARGS_WITH_BARS.value = DASH_A_ARGS.value.Replace(',', '|');
8218                 if (args_trailing_with_bars != string.Empty)
8219                 {
8220                     ARGS_WITH_BARS.value = ARGS_WITH_BARS.value + "|" + args_trailing_with_bars;
8221                 }
8222             }
8223 
8224             string args_with_bars_no_quotes = string.Empty;
8225             //if (ARGS_WITH_BARS.value != null)
8226             //{
8227             //    args_with_bars_no_quotes = ARGS_WITH_BARS.value.Replace("\"", "\\\"");
8228             //}
8229             //else
8230             //{
8231             //    args_with_bars_no_quotes = ARGS_WITH_BARS.value;
8232             //}
8233 
8234             args_with_bars_no_quotes = ARGS_WITH_BARS.value;
8235 
8236 
8237             string total_arglist = Path.GetFileName(cafe_elf);
8238             if (args_with_bars_no_quotes != string.Empty)
8239             {
8240                 total_arglist += "|" + args_with_bars_no_quotes;
8241             }
8242 
8243             string total_arglist_with_qs = total_arglist.Replace(' ', '?');
8244             total_arglist_with_qs = total_arglist_with_qs.Replace('|', ' ');
8245 
8246             // Check argument length to make sure it is less than 4096.
8247             if (!string.IsNullOrEmpty(total_arglist_with_qs) && total_arglist_with_qs.Length > CAFE_ARGSTR_MAX_LENGTH)
8248             {
8249                 Console.WriteLine("cafex run failed: argument length is greater than 4096 characters. Please shorten and retry.");
8250                 return false;
8251             }
8252 
8253             XmlHandler.UpdateNodeValue(file_dest, "argstr", total_arglist_with_qs);
8254 
8255             return true;
8256         }
8257 
update_system_xml(string file_dest, string cmd_flags, string system_mode, string sys_xml_mcp_launch_hint)8258         static CAFEX_ERROR update_system_xml(string file_dest, string cmd_flags, string system_mode, string sys_xml_mcp_launch_hint)
8259         {
8260             #if DEBUG
8261                 Log.WriteLine("update_system_xml started.");
8262             #endif
8263 
8264             Int64 iTitleID = 0;
8265             string sys_default_xml = CAFE_ROOT.value + "\\system\\bin\\ghs\\cafe\\boot\\system_default.xml";
8266 
8267             if (!check_xml_version(file_dest, sys_default_xml, "copy_default_if_mismatch"))
8268             {
8269                 return CAFEX_ERROR.UNEXPECTED;
8270             }
8271 
8272             string old_system_mode_num = XmlHandler.GetNodeValue(file_dest, "dev_mode");
8273             string[] system_mode_name_table = new string[4];
8274             system_mode_name_table[0] = "PROD";
8275             system_mode_name_table[1] = "DEV";
8276             system_mode_name_table[2] = "TEST";
8277             system_mode_name_table[3] = "Unknown";
8278 
8279             if (old_system_mode_num != "0" && old_system_mode_num != "1" && old_system_mode_num != "2")
8280             {
8281                 old_system_mode_num = "3";
8282             }
8283 
8284             string new_system_mode_num = "3";
8285             if (system_mode == "dev")
8286             {
8287                 new_system_mode_num = "1";
8288             }
8289             else if (system_mode == "test")
8290             {
8291                 new_system_mode_num = "2";
8292             }
8293             else
8294             {
8295                 if (system_mode == "prod")
8296                 {
8297                     Console.WriteLine("cafex run Warning: Changing to PROD mode is not supported.");
8298                     Console.WriteLine("  Please specify '-M dev' or '-M test'.");
8299                 }
8300                 else if (system_mode != null)
8301                 {
8302                     Console.WriteLine("cafex run Warning: Invalid system mode is specified.");
8303                 }
8304 
8305                 if (old_system_mode_num != "3")
8306                 {
8307                     new_system_mode_num = old_system_mode_num;
8308                 }
8309                 else
8310                 {
8311                     new_system_mode_num = "1";
8312                     Console.WriteLine("cafex run: System mode is broken. Fixing it to DEV");
8313                 }
8314             }
8315 
8316             if (CAFE_BOOT_MODE.value == "PCFS")
8317             {
8318                 if (new_system_mode_num != old_system_mode_num)
8319                 {
8320                     Console.WriteLine("cafex run: Changing system mode " + system_mode_name_table[HexHandler.GetNumberFromString(old_system_mode_num)] + " to " + system_mode_name_table[HexHandler.GetNumberFromString(new_system_mode_num)]);
8321                     XmlHandler.UpdateNodeValue(file_dest, "dev_mode", new_system_mode_num);
8322                 }
8323                 else
8324                 {
8325                     Console.WriteLine("cafex run: Current system mode is " + system_mode_name_table[HexHandler.GetNumberFromString(new_system_mode_num)]);
8326                 }
8327                 if (!String.IsNullOrEmpty(CAFE_TEST_SELF_REFRESH.value))
8328                 {
8329                     XmlHandler.UpdateNodeValueByPath(file_dest, "//standby/enable", "1");
8330                 }
8331             }
8332 
8333             if (CAFERUN_OPTION_MLC_EMU_LAUNCH.value == "1")
8334             {
8335                 string mlc_emu_tid_hi = CAFERUN_OPTION_MLC_EMU_TITLEID.value.Substring(2, 8);
8336                 string mlc_emu_tid_lo = CAFERUN_OPTION_MLC_EMU_TITLEID.value.Substring(10, 8);
8337 
8338                 string mlc_emu_title_dir = string.Empty;
8339                 if (mlc_emu_tid_hi == "00050010")
8340                 {
8341                     mlc_emu_title_dir = CAFE_MLC_DIR.value + "\\sys\\title\\" + mlc_emu_tid_hi + "\\" + mlc_emu_tid_lo;
8342                 }
8343                 else
8344                 {
8345                     mlc_emu_title_dir = CAFE_MLC_DIR.value + "\\usr\\title\\" + mlc_emu_tid_hi + "\\" + mlc_emu_tid_lo;
8346                 }
8347 
8348                 if (File.Exists(mlc_emu_title_dir + "\\code\\app.xml"))
8349                 {
8350                     string mlc_emu_os_version = XmlHandler.GetNodeValue(mlc_emu_title_dir + "\\code\\app.xml", "os_version");
8351                     CAFERUN_COLDBOOT_OS_VERSION.value = String.Format("{0:x16}", mlc_emu_os_version);
8352                 }
8353                 else
8354                 {
8355                     if (DISC_EMU_TYPE.value != "hdd" && ALLOW_DISCRUN_IN_SOFTLAUNCH.value == "0")
8356                     {
8357                         Console.WriteLine("cafex run failed: Cannot find title 0x" + mlc_emu_tid_hi + mlc_emu_tid_lo + " on MLC emulation");
8358                         Console.WriteLine("  Please cafeinstall before using -t option");
8359                         return CAFEX_ERROR.RUN_TITLE_ID_NOT_FOUND_IN_MLC;
8360                     }
8361                 }
8362 
8363                 // Convert the title_id from a string to a number for lookup later
8364                 iTitleID = Convert.ToInt64(mlc_emu_tid_hi + mlc_emu_tid_lo, 16);
8365 
8366                 XmlHandler.UpdateNodeValue(file_dest, "default_title_id", mlc_emu_tid_hi + mlc_emu_tid_lo);
8367             }
8368             else
8369             {
8370                 if (APP_XML_FILE.value != null)
8371                 {
8372                     DISC_EMU_TID.value = XmlHandler.GetNodeValue(APP_XML_FILE.value, "title_id");
8373 
8374                     // Convert the title_id from a string to a number for lookup later
8375                     iTitleID = Convert.ToInt64(DISC_EMU_TID.value, 16 );
8376 
8377                     XmlHandler.UpdateNodeValue(file_dest, "default_title_id", DISC_EMU_TID.value);
8378                 }
8379                 else
8380                 {
8381                     if (DISC_EMU_TYPE.value == "hdd" && string.IsNullOrEmpty(CAFE_WUMAD.value))
8382                     {
8383                         Console.WriteLine();
8384                         Console.WriteLine("-------");
8385                         Console.WriteLine("cafex run WARNING: Title ID is not specified.");
8386                         Console.WriteLine("  Use -t option to specify Title ID of application on HDD.");
8387                         Console.WriteLine("  Title ID of previously launched app will be used at this time,");
8388                         Console.WriteLine("  but launch may fail if it was different from that of application on HDD.");
8389                         Console.WriteLine("-------");
8390                         Console.WriteLine();
8391                     }
8392                 }
8393             }
8394 
8395             if (APP_XML_FILE.value != null)
8396             {
8397                 string disc_emu_app_type = XmlHandler.GetNodeValue(APP_XML_FILE.value, "app_type");
8398 
8399                 if (fAppTypeDefined)
8400                 {
8401                     // AppType override was defined on the command line so use that instead of calculating based on TitleID
8402                     disc_emu_app_type = CAFERUN_APP_TYPE.value;
8403                     XmlHandler.UpdateNodeValue(file_dest, "default_app_type", disc_emu_app_type);
8404                 }
8405                 else
8406                 {
8407                     string calculated_disc_emu_app_type = FindAppType(iTitleID);  // Find the app type based on the title ID
8408                     if (disc_emu_app_type.CompareTo(calculated_disc_emu_app_type) != 0)
8409                     {
8410                         Console.WriteLine("WARNING: Calculated AppType does not match what was in APP.XML");
8411                         Console.WriteLine("Overwriting with the calculated value for AppType");
8412                     }
8413                     disc_emu_app_type = calculated_disc_emu_app_type;
8414                     XmlHandler.UpdateNodeValue(file_dest, "default_app_type", disc_emu_app_type);
8415                 }
8416             }
8417             else
8418             {
8419                 // There might not be an app.xml but we still want to change the default_app_type with what the user specified with -T
8420                 if (fAppTypeDefined)
8421                 {
8422                     // AppType override was defined on the command line so use that instead of calculating based on TitleID
8423                     XmlHandler.UpdateNodeValue(file_dest, "default_app_type", CAFERUN_APP_TYPE.value);
8424                 }
8425                 else
8426                 {
8427                     string calculated_disc_emu_app_type = FindAppType(iTitleID);  // Find the app type based on the title ID
8428                     XmlHandler.UpdateNodeValue(file_dest, "default_app_type", calculated_disc_emu_app_type);
8429                 }
8430             }
8431 
8432             if (CAFERUN_OPTION_SOFT_RESTART.value == "0")
8433             {
8434                 XmlHandler.UpdateNodeValue(file_dest, "cmdFlags", cmd_flags);
8435             }
8436 
8437             XmlHandler.UpdateNodeValue(file_dest, "default_os_id", CAFERUN_COLDBOOT_OS_VERSION.value);
8438 
8439             if (sys_xml_mcp_launch_hint != null)
8440             {
8441                 bool node_exists = XmlHandler.NodeExists(file_dest, "default_device_type");
8442                 if (!node_exists)
8443                 {
8444                     XmlHandler.AddNode(file_dest, "default_device_type", sys_xml_mcp_launch_hint, new string[4] { "type", "string", "length", "16" });
8445                 }
8446                 else
8447                 {
8448                     XmlHandler.UpdateNodeValue(file_dest, "default_device_type", sys_xml_mcp_launch_hint);
8449                 }
8450             }
8451             else
8452             {
8453                 XmlHandler.RemoveNode(file_dest, "default_device_type");
8454             }
8455 
8456             return CAFEX_ERROR.OK;
8457         }
8458 
set_system_xml_cos_flags(string ppc_os_flags)8459         static int set_system_xml_cos_flags(string ppc_os_flags)
8460         {
8461             #if DEBUG
8462                 Log.WriteLine("setting cos_flags:" + ppc_os_flags);
8463             #endif
8464             string file_dest = CAFE_SLC_DIR.value + "\\sys\\config\\system.xml";
8465             int ret = 0;
8466             XmlHandler.UpdateNodeValue(file_dest, "cmdFlags", ppc_os_flags);
8467             ret = devkitmsg.CosFlags(ppc_os_flags);
8468             if (ret != 0)
8469             {
8470                 Console.WriteLine("devkitmsg \"cos_flags " + ppc_os_flags + "\" - failed result = " + ret);
8471             }
8472             return ret;
8473         }
8474 
update_app_xml(string file_dest)8475         static bool update_app_xml(string file_dest)
8476         {
8477             #if DEBUG
8478                 Log.WriteLine("update_app_xml started.");
8479             #endif
8480 
8481             string app_default_xml = CAFE_ROOT.value + "\\system\\bin\\ghs\\cafe\\boot\\app_default.xml";
8482 
8483             if (!check_xml_version(file_dest, app_default_xml, ""))
8484             {
8485                 return false;
8486             }
8487 
8488             XmlHandler.UpdateNodeValue(file_dest, "os_version", CAFERUN_COLDBOOT_OS_VERSION.value);
8489 
8490             return true;
8491         }
8492 
update_cos_xml(string file_dest, string cmd_flags)8493         static bool update_cos_xml(string file_dest, string cmd_flags)
8494         {
8495             #if DEBUG
8496                 Log.WriteLine("update_cos_xml started.");
8497             #endif
8498                 Console.WriteLine("CAFEX: update_cos_xml started, cmd_flags = " + cmd_flags);
8499             string cos_default_xml = CAFE_ROOT.value + "\\system\\bin\\ghs\\cafe\\boot\\cos_default.xml";
8500 
8501             if (!check_xml_version(file_dest, cos_default_xml, ""))
8502             {
8503                 return false;
8504             }
8505 
8506             //Get original command flags from the xml file
8507             string orig_cmd_flags = XmlHandler.GetNodeValue(cos_default_xml, "cmdFlags");
8508 
8509             Console.WriteLine("CAFEX: HexHandler.GetNumberFromString(cmd_flags) = " + HexHandler.GetNumberFromString(cmd_flags).ToString());
8510 
8511             cmd_flags = (HexHandler.GetNumberFromString(cmd_flags) | (HexHandler.GetNumberFromString(orig_cmd_flags) & ~0xff)).ToString();
8512             Console.WriteLine("CAFEX: change cos.xml cmdFlags to " + cmd_flags);
8513 
8514             //Compare the command flags passed with the original one.
8515             //If the values are different then update the xml node for cmdFlags
8516             if (orig_cmd_flags != cmd_flags)
8517             {
8518                 XmlHandler.UpdateNodeValue(file_dest, "cmdFlags", cmd_flags);
8519             }
8520 
8521             return true;
8522         }
8523 
update_meta_xml(string file_dest)8524         static CAFEX_ERROR update_meta_xml(string file_dest)
8525         {
8526             #if DEBUG
8527                 Log.WriteLine("update_meta_xml started on file = " + file_dest);
8528             #endif
8529 
8530             string meta_default_xml = CAFE_ROOT.value + "\\system\\bin\\ghs\\cafe\\boot\\meta_default.xml";
8531             string own_meta_xml;
8532 
8533             //Since CAFE_CODE_DIR will be modified due to the existence of the session manager, we need to look
8534             //at the location of the original rpx to find the custom meta.xml file.
8535             if (SESSION_MANAGER.value == "1")
8536             {
8537                 own_meta_xml = Path.Combine(CAFE_ELF_SRC_DIR.value, "..\\meta\\meta.xml");
8538             }
8539             else
8540             {
8541                 own_meta_xml = CAFE_CODE_DIR.value + "\\..\\meta\\meta.xml";
8542             }
8543 
8544             if (CAFERUN_OPTION_MLC_EMU_LAUNCH.value == "0")
8545             {
8546                 if (File.Exists(own_meta_xml))
8547                 {
8548                     string abs_own_meta_xml = Path.GetFullPath(own_meta_xml);
8549                     string abs_file_dest = Path.GetFullPath(file_dest);
8550                     if (abs_own_meta_xml != abs_file_dest)
8551                     {
8552                         Console.Write("Copy " + own_meta_xml + " to " + file_dest);
8553                         File.Copy(own_meta_xml, file_dest, true);
8554                         File.SetAttributes(file_dest, FileAttributes.Normal);
8555                     }
8556                 }
8557                 else
8558                 {
8559                     CAFEX_ERROR ret = check_title_id(file_dest, meta_default_xml, APP_XML_FILE.value);
8560                     if (ret != CAFEX_ERROR.OK)
8561                     {
8562                         return ret;
8563                     }
8564                 }
8565 
8566                 if (!check_xml_version(file_dest, meta_default_xml, ""))
8567                 {
8568                     return CAFEX_ERROR.RUN_UPDATE_META_XML_FAILED;
8569                 }
8570 
8571                 XmlHandler.UpdateNodeValue(file_dest, "os_version", CAFERUN_COLDBOOT_OS_VERSION.value);
8572 
8573                 Console.WriteLine("Updating title id, group id, title version and app type in " + file_dest + ", based on " + APP_XML_FILE.value + "...");
8574 
8575                 // get titleId from disc emulation's app.xml
8576                 DISC_EMU_TID.value = XmlHandler.GetNodeValue(APP_XML_FILE.value, "title_id");
8577                 XmlHandler.UpdateNodeValue(file_dest, "title_id", DISC_EMU_TID.value);
8578 
8579                 // get group Id from disc emulation's app.xml
8580                 string disc_emu_gid = XmlHandler.GetNodeValue(APP_XML_FILE.value, "group_id");
8581                 XmlHandler.UpdateNodeValue(file_dest, "group_id", disc_emu_gid);
8582 
8583                 // get title version from disc emulation's app.xml
8584                 string disc_emu_titlever_hex = XmlHandler.GetNodeValue(APP_XML_FILE.value, "title_version").Trim();
8585                 if (!disc_emu_titlever_hex.StartsWith("0x"))
8586                 {
8587                     disc_emu_titlever_hex = "0x" + disc_emu_titlever_hex;
8588                 }
8589 
8590                 uint disc_emu_titlever_decimal = HexHandler.GetNumberFromString(disc_emu_titlever_hex);
8591                 // insert system default_title_id
8592                 XmlHandler.UpdateNodeValue(file_dest, "title_version", disc_emu_titlever_decimal.ToString("D5"));
8593             }
8594 
8595             return CAFEX_ERROR.OK;
8596         }
8597 
update_boot_logos(string file_dest)8598         static void update_boot_logos(string file_dest)
8599         {
8600             #if DEBUG
8601                 Log.WriteLine("update_boot_logos started.");
8602             #endif
8603 
8604             string boot_movie_h264 = CAFE_ROOT.value + "\\system\\bin\\ghs\\cafe\\meta\\bootMovie.h264";
8605             string boot_logo_tex_tga = CAFE_ROOT.value + "\\system\\bin\\ghs\\cafe\\meta\\bootLogoTex.tga";
8606 
8607             string icon_tex_tga = CAFE_ROOT.value + "\\system\\bin\\ghs\\cafe\\meta\\iconTex.tga";
8608             string boot_tv_tga = CAFE_ROOT.value + "\\system\\bin\\ghs\\cafe\\meta\\bootTvTex.tga";
8609             string boot_drc_tga = CAFE_ROOT.value + "\\system\\bin\\ghs\\cafe\\meta\\bootDrcTex.tga";
8610 
8611             string dest_boot_movie_h264 = file_dest + "\\bootMovie.h264";
8612             string dest_boot_logo_tex_tga = file_dest + "\\bootLogoTex.tga";
8613 
8614             string dest_icon_tex_tga = file_dest + "\\iconTex.tga";
8615             string dest_boot_tv_tga = file_dest + "\\bootTvTex.tga";
8616             string dest_boot_drc_tga = file_dest + "\\bootDrcTex.tga";
8617 
8618             // Copy boot_movie logo_text only if ghs\cafe\meta has a newer timestamp.
8619             // This replaces the "cp -u" from the BASH script.
8620             bool copyRequired = false;
8621 
8622             if (!File.Exists(dest_boot_movie_h264))
8623             {
8624                 // Should copy because it does not exist
8625                 copyRequired = true;
8626             }
8627             else
8628             {
8629                 // Check the timestamps
8630                 if (file_timestamp_compare(boot_movie_h264, dest_boot_movie_h264) > 0)
8631                 {
8632                     copyRequired = true;
8633                 }
8634             }
8635 
8636             if (copyRequired)
8637             {
8638                 file_copy_retry(boot_movie_h264, dest_boot_movie_h264, true, 1);
8639                 File.SetAttributes(dest_boot_movie_h264, FileAttributes.Normal);
8640             }
8641 
8642             // Copy logo_text only if ghs\cafe\meta has a newer timestamp
8643             copyRequired = false;
8644 
8645             if (!File.Exists(dest_boot_logo_tex_tga))
8646             {
8647                 // Should copy because it does not exist
8648                 copyRequired = true;
8649             }
8650             else
8651             {
8652                 // Check the timestamps
8653                 if (file_timestamp_compare(boot_logo_tex_tga, dest_boot_logo_tex_tga) > 0)
8654                 {
8655                     copyRequired = true;
8656                 }
8657             }
8658 
8659             if (copyRequired)
8660             {
8661                 file_copy_retry(boot_logo_tex_tga, dest_boot_logo_tex_tga, true, 1);
8662                 File.SetAttributes(dest_boot_logo_tex_tga, FileAttributes.Normal);
8663             }
8664 
8665             // Applicaion Boot Textures should be copy if files do not exist
8666             if (!File.Exists(dest_icon_tex_tga))
8667             {
8668                 file_copy_retry(icon_tex_tga, dest_icon_tex_tga, true, 1);
8669                 File.SetAttributes(dest_icon_tex_tga, FileAttributes.Normal);
8670             }
8671 
8672             if (!File.Exists(dest_boot_tv_tga))
8673             {
8674                 file_copy_retry(boot_tv_tga, dest_boot_tv_tga, true, 1);
8675                 File.SetAttributes(dest_boot_tv_tga, FileAttributes.Normal);
8676             }
8677 
8678             if (!File.Exists(dest_boot_drc_tga))
8679             {
8680                 file_copy_retry(boot_drc_tga, dest_boot_drc_tga, true, 1);
8681                 File.SetAttributes(dest_boot_drc_tga, FileAttributes.Normal);
8682             }
8683         }
8684 
create_directory_if_noexist(string directory)8685         static void create_directory_if_noexist(string directory)
8686         {
8687             #if DEBUG
8688                 Log.WriteLine("create_directory_if_noexist started.");
8689             #endif
8690 
8691             if (!Directory.Exists(directory))
8692             {
8693                 Directory.CreateDirectory(directory);
8694             }
8695         }
8696 
compute_flat_version(string version)8697         static int compute_flat_version(string version)
8698         {
8699             #if DEBUG
8700                 Log.WriteLine("compute_flat_version started.");
8701             #endif
8702 
8703             string[] numbers = version.Split('.');
8704             int ret = 0;
8705             if (numbers.Length > 0)
8706             {
8707                 ret += Convert.ToInt32(numbers[0]) * 1000000;
8708             }
8709             if (numbers.Length > 1)
8710             {
8711                 ret += Convert.ToInt32(numbers[1]) * 10000;
8712             }
8713             if (numbers.Length > 2)
8714             {
8715                 ret += Convert.ToInt32(numbers[2]) * 100;
8716             }
8717             if (numbers.Length > 3)
8718             {
8719                 ret += Convert.ToInt32(numbers[3]);
8720             }
8721 
8722 #if DEBUG
8723             Log.WriteLine(string.Format("compute_flat_version: '{0}' => {1}.", version, ret.ToString()));
8724 #endif
8725             return ret;
8726         }
8727 
compute_ver_string(int ver)8728         static string compute_ver_string(int ver)
8729         {
8730             string ver_str = (ver % 100).ToString();
8731 
8732             if (ver > 100)
8733             {
8734                 ver_str = string.Format("{0}.{1}", (ver / 100) % 100, ver_str);
8735 
8736                 if (ver > 10000)
8737                 {
8738                     ver_str = string.Format("{0}.{1}", (ver / 10000) % 100, ver_str);
8739 
8740                     if (ver > 1000000)
8741                     {
8742                         ver_str = string.Format("{0}.{1}", (ver / 1000000) % 100, ver_str);
8743                     }
8744                 }
8745             }
8746 
8747             return ver_str;
8748         }
8749 
check_title_id(string file_dest, string file_default, string file_app)8750         static CAFEX_ERROR check_title_id(string file_dest, string file_default, string file_app)
8751         {
8752             #if DEBUG
8753                 Log.WriteLine("check_title_id started. file_dest=" + file_dest + ",file_default=" + file_default + ",file_app=" + file_app);
8754             #endif
8755             if (!File.Exists(file_dest))
8756             {
8757                 Console.WriteLine("cafex run: Copying default config file to " + file_dest);
8758                 if (!File.Exists(file_default))
8759                 {
8760                     Console.WriteLine("cafex run failed: Cannot find default config file " + file_default);
8761                     return CAFEX_ERROR.RUN_CHECKTITLEID_FAILED;
8762                 }
8763 
8764                 File.Copy(file_default, file_dest, true);
8765                 File.SetAttributes(file_dest, FileAttributes.Normal);
8766             }
8767             else
8768             {
8769                 string titleid_dest = XmlHandler.GetNodeValue(file_dest, "title_id");
8770                 string titleid_app = XmlHandler.GetNodeValue(file_app, "title_id");
8771                 if (titleid_dest == string.Empty || titleid_app == string.Empty)
8772                 {
8773                     Console.WriteLine("cafex run failed: Cannot get title id");
8774                     return CAFEX_ERROR.RUN_CHECKTITLEID_FAILED;
8775                 }
8776 
8777                 if (titleid_dest != titleid_app)
8778                 {
8779                     Console.WriteLine("cafex run: Config file title id mismatch detected: " + titleid_dest + " vs. required " + titleid_app);
8780                     Console.WriteLine("  Copying default config file to " + file_dest);
8781 
8782                     if (!File.Exists(file_default))
8783                     {
8784                         Console.WriteLine("cafex run failed: Cannot find default config file " + file_default);
8785                         return CAFEX_ERROR.RUN_CHECKTITLEID_FAILED;
8786                     }
8787 
8788                     File.Copy(file_default, file_dest, true);
8789                     File.SetAttributes(file_dest, FileAttributes.Normal);
8790                 }
8791             }
8792 
8793             return CAFEX_ERROR.OK;
8794         }
8795 
8796         /// <summary>
8797         /// Compares timestamsp between two files.
8798         /// </summary>
8799         /// <param name="file1">The first file for comparison.</param>
8800         /// <param name="file2">The second file for comparison.</param>
8801         /// <returns>0 if timestamps are the same, negative if first file is older than the second, and positive if first is newer than the second.</returns>
file_timestamp_compare(string file1, string file2)8802         static int file_timestamp_compare(string file1, string file2)
8803         {
8804             if (!File.Exists(file1))
8805             {
8806                 throw new ArgumentException("file1 = " + file1);
8807             }
8808 
8809             if (!File.Exists(file2))
8810             {
8811                 throw new ArgumentException("file2 = " + file2);
8812             }
8813 
8814             DateTime file1Time = File.GetLastWriteTime(file1);
8815             DateTime file2Time = File.GetLastWriteTime(file2);
8816 
8817             return DateTime.Compare(file1Time, file2Time);
8818         }
8819 
8820         /// <summary>
8821         /// Tries to copy a file from source to destination, and if it fails and attempts is greater than one,
8822         /// it will wait for 1s and retry.
8823         /// </summary>
8824         /// <param name="sourceFileName">Source file.</param>
8825         /// <param name="destFileName">Destination file.</param>
8826         /// <param name="overwrite">Overwrite if destination exists.</param>
8827         /// <param name="attempts">Number of attempts</param>
file_copy_retry(string sourceFileName, string destFileName, bool overwrite, uint attempts)8828         static void file_copy_retry(string sourceFileName, string destFileName, bool overwrite, uint attempts)
8829         {
8830 
8831             try
8832             {
8833                 if (overwrite && File.Exists(destFileName))
8834                 {
8835                     // Force copy by stripping the read-only attribute
8836                     File.SetAttributes(destFileName, File.GetAttributes(destFileName) & ~FileAttributes.ReadOnly);
8837                 }
8838 
8839                 File.Copy(sourceFileName, destFileName, overwrite);
8840             }
8841             catch (IOException)
8842             {
8843                 if (attempts > 1)
8844                 {
8845                     --attempts;
8846                     // Wait a second
8847                     Thread.Sleep(Program.RETRY_TIMESPAN);
8848                     // Retry
8849                     file_copy_retry(sourceFileName, destFileName, overwrite, attempts);
8850                 }
8851                 else
8852                 {
8853                     // Re-throw if no attempts
8854                     throw;
8855                 }
8856             }
8857         }
8858 
8859         #endregion
8860 
8861         #region HELP
run_usage()8862         static void run_usage()
8863         {
8864             string caller;
8865             if (CAFERUN_OPTION_CALLED_FROM_CAFEDISCRUN.value == "yes")
8866             {
8867                 caller = "discrun";
8868             }
8869             else
8870             {
8871                 caller = "run";
8872             }
8873 
8874             Console.WriteLine("Usage: cafex " + caller + " [options] <app>.rpx \"[arg1]\" \"[arg2]\" ... \"[argN]\"");
8875             Console.WriteLine();
8876             Console.WriteLine("options:");
8877             Console.WriteLine("  -a a,b... : arguments (comma delimited)");
8878             Console.WriteLine("  -b        : use DEBUG OS version");
8879             Console.WriteLine("  -C        : use OS_SECURITY_LEVEL OS version");
8880             Console.WriteLine("  -u        : use FDEBUG OS version");
8881             Console.WriteLine("  -l <path> : user RPL directory or file to gather for RPX");
8882             Console.WriteLine();
8883             Console.WriteLine("  -d multi  : launch multi (GHS UI) on elf file");
8884             Console.WriteLine("  -L        : run legacy application independent of xml versions");
8885             Console.WriteLine("  -i        : stop debugger in the initialization code");
8886             Console.WriteLine("  -j        : stop debugger in the pre-initialization code");
8887             Console.WriteLine("  -R        : do not stop in debugger until OSDebug or OSDebugStr call");
8888             Console.WriteLine("  -p <n>    : indicate process to debug (defaults to game process)");
8889             Console.WriteLine("  -g <n>    : 32-bit flag to pass along to PPC COS");
8890             Console.WriteLine("  -w <n>    : 32-bit flag to pass along to PPC COS.");
8891             Console.WriteLine("  -k <file> : path to elf file for debugger");
8892             Console.WriteLine("  -x        : Enable AHCI/SATA disk access. Deprecated - will soon become default.");
8893             Console.WriteLine("  -r        : restart last application");
8894             Console.WriteLine("  -s        : use soft launch to run");
8895             Console.WriteLine("  -F		   : force restart (stop and then boot hw)");
8896             Console.WriteLine("  -t <tid>  : title launch from mlc emulation (tid is hex that starts with 0x)");
8897             Console.WriteLine("  -e <op>   : pass op through to FSEmul or MCP (e.g.: -e sata -> FSEmul -sata)");
8898             Console.WriteLine("  -e eco    : Set the system to boot in ECO mode");
8899             Console.WriteLine();
8900             Console.WriteLine("  -v <n>    : set COS verbose level (0=off 7 == MAX)");
8901             Console.WriteLine("  -q        : do not display OS warning or informational messages.");
8902             Console.WriteLine("  -z        : suppress mirroring the data to the session data directory.");
8903             Console.WriteLine("  -K        : Use kill restart to restart the application");
8904             Console.WriteLine("  -T        : apptype of the title being run (This will override the calculation of apptype)");
8905             Console.WriteLine();
8906             Console.WriteLine("  -h        : (help) display options");
8907         }
8908 
headlessrun_usage()8909         static void headlessrun_usage()
8910         {
8911             Console.WriteLine("Usage: cafex headlessrun [options] <app>.rpx \"[arg1]\" ... \"[argN]\"");
8912 
8913             Console.WriteLine();
8914             Console.WriteLine("options:");
8915             Console.WriteLine("  -b        : Use DEBUG version of the OS");
8916             Console.WriteLine("  -n        : Don't start the title after upload.");
8917             Console.WriteLine("  -m        : Bypass mastering setup.");
8918             Console.WriteLine("  -w <time> : Time (in seconds) to wait for title to boot during setup.");
8919             Console.WriteLine("              Default time is 15 seconds.");
8920             Console.WriteLine("  -h <bank> : Specify bank to run from.  Default is bank 10.");
8921             Console.WriteLine("  -u        : (help) display options");
8922         }
8923 
on_usage()8924         static void on_usage()
8925         {
8926             Console.WriteLine("Usage: cafex on [options]");
8927             Console.WriteLine();
8928             Console.WriteLine("options:");
8929             Console.WriteLine("  -d multi  : launch multi. (GHS UI)");
8930             Console.WriteLine("  -e <op>   : pass op through to FSEmul or MCP. (e.g.: -e sata -> FSEmul -sata)");
8931             Console.WriteLine("  -p <n>    : indicate process to debug. (defaults to game process)");
8932             Console.WriteLine("  -nobgd    : disables background daemons.");
8933             Console.WriteLine("  -noprompt : changes CATTOUCAN_TERM to \"source -p -q /vol/content\".");
8934             Console.WriteLine("  -nosync   : suppress mirroring the data to the session data directory.");
8935             Console.WriteLine();
8936             Console.WriteLine("  -h        : (help) display options.");
8937         }
8938 
update_usage()8939         static void update_usage()
8940         {
8941             Console.WriteLine("Usage: cafex update [-h]");
8942             Console.WriteLine();
8943             Console.WriteLine("options:");
8944             Console.WriteLine("  -u <package> : path to update package (from System Config Tool's perspective)");
8945             Console.WriteLine("  -s           : use system updater (update package should contain system updater)");
8946             Console.WriteLine("  -t <dir>     : patch to single title (from System Config Tool's perspective)");
8947             if (is_DUAL_bootloader_available())
8948             {
8949                 if (is_DUAL_bootloader_required())
8950                 {
8951                     Console.WriteLine("  -p           : use the production bootloader (only applies when in NAND mode)");
8952                 }
8953                 else
8954                     Console.WriteLine("  -M           : use the mixed bootloader.");
8955             }
8956 
8957             Console.WriteLine("  -reflash     : reflashes NAND during the update");
8958             Console.WriteLine("  -noreflash   : does not reflash NAND during the update(default)");
8959             Console.WriteLine("  -nodrc       : skip the firmware update for attached DRC");
8960             Console.WriteLine("  -h           : (help) display options");
8961         }
8962 
revert_usage()8963         static void revert_usage()
8964         {
8965             Console.WriteLine("Usage: cafex revert [-h] SDK_ROOT");
8966             Console.WriteLine();
8967             Console.WriteLine("options:");
8968             Console.WriteLine("  -reflash     : reflashes NAND during the update");
8969             Console.WriteLine("  -noreflash   : does not reflash NAND during the update (default)");
8970             if (is_DUAL_bootloader_available() && !is_DUAL_bootloader_required())
8971             {
8972                     Console.WriteLine("  -mixed       : use the DUAL instead of the PCFS bootloader");
8973             }
8974             Console.WriteLine("  -h           : (help) display options");
8975             Console.WriteLine("  SDK_ROOT     : root of the SDK to revert to");
8976         }
8977 
recover_usage()8978         static void recover_usage()
8979         {
8980             Console.WriteLine("Usage: cafex recover [-production|-bootloader][-h]");
8981             Console.WriteLine();
8982             Console.WriteLine("options:");
8983             Console.WriteLine("  -production  : use the production NAND bootloader");
8984             if (is_DUAL_bootloader_available())
8985             {
8986                 Console.WriteLine("  -bootloader  : update *only* the bootloader to the DUAL bootloader");
8987                 if (!is_DUAL_bootloader_required())
8988                 {
8989                     Console.WriteLine("  -mixed       : use the DUAL instead of the PCFS bootloader");
8990                 }
8991             }
8992             Console.WriteLine("  -noreflash   : does not reflash NAND during the recovery");
8993             Console.WriteLine("  -reflash     : reflashes NAND during the recovery");
8994 
8995             Console.WriteLine("  -h           : (help) display options");
8996         }
8997 
stop_usage()8998         static void stop_usage()
8999         {
9000             Console.WriteLine("Usage: cafex stop [-hostonly] [-makemine] [-h]");
9001             Console.WriteLine();
9002             Console.WriteLine("options:");
9003             Console.WriteLine("  -h           : (help) display options.");
9004             Console.WriteLine("  -hostonly    : stops the host applications that control the bridge, keeping the bridge on.");
9005             Console.WriteLine("  -makemine    : forces assigning the bridge to this host.");
9006         }
9007 
setbootmode_usage()9008         static void setbootmode_usage()
9009         {
9010             Console.WriteLine("Usage: cafex setbootmode [-noreflash] [-quick|-production] [PCFS|NAND]");
9011             Console.WriteLine();
9012             Console.WriteLine("options:");
9013             Console.WriteLine("  -h             : (help) display options.");
9014             Console.WriteLine("  -quick|-Q      : If the DUAL bootloader is installed, just change the boot");
9015             Console.WriteLine("                   mode environment variables.");
9016             if (is_DUAL_bootloader_available())
9017             {
9018                 if (is_DUAL_bootloader_required())
9019             Console.WriteLine("  -production|-P : Applies only to NAND mode. Uses the production bootloader.");
9020                 else
9021                     Console.WriteLine("  -mixed         : Install the mixed bootloader.");
9022             }
9023             Console.WriteLine("  -reflash       : reflashes NAND during the operation");
9024             Console.WriteLine("  -noreflash     : does not reflash NAND during the operation(default)");
9025             if (is_DUAL_bootloader_available())
9026             {
9027                 if (is_DUAL_bootloader_required())
9028             Console.WriteLine("  PCFS           : sets the Bridge to mixed boot using PCFS.");
9029                 else
9030                     Console.WriteLine("  PCFS           : sets the Bridge to boot using PCFS.");
9031             }
9032             Console.WriteLine("  NAND           : sets the Bridge to boot from internal NAND.");
9033         }
9034 
syncsession_usage()9035         static void syncsession_usage()
9036         {
9037             Console.WriteLine("Usage: cafex syncsession [-h]");
9038             Console.WriteLine();
9039             Console.WriteLine("options:");
9040             Console.WriteLine("  -h           : (help) display options.");
9041         }
9042 
launch_usage()9043         static void launch_usage()
9044         {
9045             Console.WriteLine("Usage: cafex launch <title path> [args]");
9046             Console.WriteLine();
9047             Console.WriteLine("options:");
9048             Console.WriteLine("  -h             : (help) display options");
9049             Console.WriteLine("  <title path>   : Full file path for the title rpx");
9050             Console.WriteLine("  [args]         : arguments to rpx");
9051             Console.WriteLine("");
9052         }
9053         #endregion
9054     }
9055 
9056 	public class getopts
9057 	{
9058 		private string[] args;
9059 		private string optstring;
9060 		private int optind;
9061 		private string optarg;
9062 		private string opt;
9063 		private string next = null;
9064 		int argc;
9065 
getopts(string[] args, string optstring)9066 		public getopts(string[] args, string optstring)
9067 		{
9068 			this.args = args;
9069 			this.argc = args.Length;
9070 			this.optstring = optstring;
9071 			this.optind = 0;
9072 		}
9073 
9074 		public int OPTIND
9075 		{
9076 			get
9077 			{
9078 				return this.optind;
9079 			}
9080 		}
9081 
9082 		public string OPT
9083 		{
9084 			get
9085 			{
9086 				return this.opt;
9087 			}
9088 		}
9089 
9090 		public string OPTARG
9091 		{
9092 			get
9093 			{
9094 				return this.optarg;
9095 			}
9096 		}
9097 
getNext()9098 		public bool getNext()
9099 		{
9100 
9101 			optarg = null;
9102 
9103 			if (string.IsNullOrEmpty(next))
9104 			{
9105 				// Check if that is the end of the args
9106 				if (optind >= argc)
9107 				{
9108 					// Done
9109 					optarg = null;
9110 					return false;
9111 				}
9112 
9113 				if (args[optind].Equals("-"))
9114 				{
9115 					// Invalid if only "-"
9116 					this.optind++;
9117 					optarg = null;
9118 					if (optind < argc)
9119 					{
9120 						optarg = args[optind];
9121 					}
9122 
9123 					return false;
9124 				}
9125 
9126 				if (optind >= argc || args[optind][0] != '-' || args[optind][1] == '\0')
9127 				{
9128 					optarg = null;
9129 					if (optind < argc)
9130 					{
9131 						optarg = args[optind];
9132 					}
9133 
9134 					return false;
9135 				}
9136 
9137 				if (args[optind].Equals("--"))
9138 				{
9139 					// Invalid if "--"
9140 					optind++;
9141 					optarg = null;
9142 					if (optind < argc)
9143 					{
9144 						optarg = args[optind];
9145 					}
9146 
9147 					return false;
9148 				}
9149 
9150 				// Set the current with the value calculated
9151 				next = args[optind];
9152 				if (next.StartsWith("-"))
9153 				{
9154 					next = next.Remove(0, 1);
9155 				}
9156 
9157 				optind++;
9158 			}
9159 
9160 			// handle the current argument
9161 			string configurationChar = next.Substring(0, 1);
9162 			// remove configuration char from argument
9163 			next = next.Substring(1);
9164 
9165 			int configurationCharPosition = optstring.IndexOf(configurationChar);
9166 			if (-1 == configurationCharPosition)
9167 			{
9168 				this.opt = "?";
9169 				return true;
9170 			}
9171 
9172 			configurationCharPosition++;
9173 			// Check if configuration character should have an argument or not (yes, if there is ":" in the optstring).
9174 			if (configurationCharPosition < optstring.Length
9175 				&& optstring[configurationCharPosition] == ':')
9176 			{
9177 				if (!string.IsNullOrEmpty(next))
9178 				{
9179 					optarg = next;
9180 					next = null;
9181 				}
9182 				else if (optind < argc)
9183 				{
9184 					// get the next argument from args and increase the index
9185 					optarg = args[optind];
9186 					optind++;
9187 				}
9188 				else
9189 				{
9190 					// failure case
9191 					this.opt = "?";
9192 					return true;
9193 				}
9194 			}
9195 
9196 			// Success
9197 			this.opt = configurationChar;
9198 			return true;
9199 		}
9200 	}
9201 }
9202