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