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