/*---------------------------------------------------------------------------* Project: TwlSDK - OS File: os_argument.c Copyright 2005-2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: 2009-02-04#$ $Rev: 9969 $ $Author: yada $ *---------------------------------------------------------------------------*/ #include #include #ifdef SDK_TWL #include #endif #define OSi_INIVALUE 0xffff #ifndef OS_NO_ARGUMENT #ifdef SDK_NITRO //---- for Nitro #include //---- This area is for argument string, and may be // modified from external tools. static OSArgumentBuffer OSi_ArgumentBuffer = { OS_ARGUMENT_ID_STRING, OS_ARGUMENT_BUFFER_SIZE, {'\0', '\0'}, }; #include //---- pointer to current argument buffer const char *sCurrentArgBuffer = &OSi_ArgumentBuffer.buffer[0]; #endif #ifdef SDK_TWL const char *sCurrentArgBuffer = (const char*)(HW_TWL_ROM_HEADER_BUF + 0xe00); #endif static const char *match_opt(int optchar, const char *optstring); #endif //ifndef OS_NO_ARGUMENT //---- for TWL #ifdef SDK_TWL static u32 sBufferState = OS_DELIVER_ARG_BUF_INVALID; static OSDeliverArgInfo* sBufferPtr = NULL; static u8* sPtr; static OSTitleId sEncodedTitleId = 0; #endif static int OSi_GetArgc_core(const char* p); static const char *OSi_GetArgv_core(const char *p, int n); /*---------------------------------------------------------------------------* Name: ( OSi_GetArgc_core ) Description: Get number of valid arguments. Arguments: p: pointer to argument buffer Returns: number of valid arguments. *---------------------------------------------------------------------------*/ static int OSi_GetArgc_core(const char* p) { int n = 0; for (; *p; p++, n++) { while (*p) { p++; } } return n; } /*---------------------------------------------------------------------------* Name: OS_GetArgc Description: Get number of valid arguments. This function is for debug. Arguments: None. Returns: number of valid arguments. return 1 if no argument. return 0 if not set argument buffer. *---------------------------------------------------------------------------*/ #ifndef OS_NO_ARGC_AND_ARGV int OS_GetArgc(void) { return OSi_GetArgc_core( (const char *)sCurrentArgBuffer ); } #endif /*---------------------------------------------------------------------------* Name: ( OSi_GetArgv_core ) Description: Get the pointer to the specified argument string. Arguments: n: index of argument. n==1 means the first argument. Returns: n must less than value of OS_GetArgc() *---------------------------------------------------------------------------*/ static const char *OSi_GetArgv_core(const char *p, int n) { SDK_ASSERT(n >= 0); for (; *p && n > 0; p++, n--) { while (*p) { p++; } } return (*p) ? p : NULL; } /*---------------------------------------------------------------------------* Name: OS_GetArgv Description: Get the pointer to the specified argument string. This function is for debug. Arguments: n: index of argument. n==1 means the first argument. n must less than value of OS_GetArgc() Returns: pointer to the specified argument string *---------------------------------------------------------------------------*/ #ifndef OS_NO_ARGC_AND_ARGV const char* OS_GetArgv(int n) { return OSi_GetArgv_core( (const char *)sCurrentArgBuffer, n ); } #endif /*---------------------------------------------------------------------------* Name: OS_GetOpt Description: getopt() like function to get command line options Arguments: optstring: Option character string Internal parameters are reset if NULL. Returns: Option character code. '?' Indicates the option character code is unclear. If -1, the option does not exist *---------------------------------------------------------------------------*/ #ifndef OS_NO_ARGUMENT const char *OSi_OptArg = NULL; int OSi_OptInd = 1; int OSi_OptOpt = 0; int OS_GetOpt(const char *optstring) { static BOOL end_of_option = FALSE; int optchar; const char *arg; const char *opt; const char *optarg; OSi_OptArg = NULL; OSi_OptOpt = 0; // Reset if optstring is NULL if (optstring == NULL) { OSi_OptInd = 1; end_of_option = FALSE; return 0; } // Get command line arguments arg = OS_GetArgv(OSi_OptInd); if (arg == NULL) { return -1; } if (optstring[0] == '-') // Minus Mode { OSi_OptInd++; // Consume arguments // Normal argument when it does not start with '-' if (end_of_option || arg[0] != '-') { OSi_OptArg = arg; // Normal arguments are also set to OptArg. return 1; } // Option analysis optchar = arg[1]; if (optchar == '-') // End of options when '--' is encountered { end_of_option = TRUE; // Normal arguments from here on return OS_GetOpt(optstring); } } else // normal mode { // Normal argument when it does not start with '-' if (end_of_option || arg[0] != '-') { return -1; // OptArg remains NULL } OSi_OptInd++; // Consume arguments // Option analysis optchar = arg[1]; if (optchar == '-') // End of options when '--' is encountered { end_of_option = TRUE; // Normal arguments from here on return -1; } } opt = match_opt(optchar, optstring); if (opt == NULL) { OSi_OptOpt = optchar; // Unknown option return '?'; } if (opt[1] == ':') // OptArg search specification? { optarg = OS_GetArgv(OSi_OptInd); if (optarg == NULL || optarg[0] == '-') { if (opt[2] != ':') // '::' Or not? { OSi_OptOpt = optchar; // OptArg not present. return '?'; } // OptArg not present. // OSi_OptArg = NULL } else { OSi_OptArg = optarg; OSi_OptInd++; // Consume arguments } } return optchar; } static const char *match_opt(int optchar, const char *optstring) { if (optstring[0] == '-' || optstring[0] == '+') { optstring++; } if (optchar != ':') { while (*optstring) { if (optchar == *optstring) { return optstring; } optstring++; } } return NULL; } #endif // ifndef OS_NO_ARGUMENT /*---------------------------------------------------------------------------* Name: OS_ConvertToArguments Description: convert string data to arg binary Arguments: str : string cs : character to separate buffer: buffer to store bufSize: max buffer size Returns: None. *---------------------------------------------------------------------------*/ #ifndef OS_NO_ARGUMENT void OS_ConvertToArguments(const char *str, char cs, char *buffer, u32 bufSize) { char *p = buffer; char *pEnd = buffer + bufSize; BOOL isQuoted = FALSE; while (1) { //---- skip separator while (*str == cs && p < pEnd) { str++; } //---- store argument string while (*str && p < pEnd) { //---- check quote if (*str == '\"') { isQuoted = (isQuoted == FALSE); str++; continue; } //---- found separator else if (*str == cs && isQuoted == FALSE) { break; } *p++ = *str++; } //---- 1) reached to the buffer end if (p >= pEnd) { *(pEnd - 2) = '\0'; *(pEnd - 1) = '\0'; break; } //---- 2) reached to the string end if (*str == '\0') { while ((p + 1) >= pEnd) { p--; } *p++ = '\0'; *p = '\0'; break; } //---- 3) separator if (*str == cs) { *p++ = '\0'; } } //---- end mark if (p < pEnd) { *p++ = '\0'; } } #endif //ifndef OS_NO_ARGUMENT /*---------------------------------------------------------------------------* Name: OS_SetArgumentBuffer Description: force to set argument buffer. Arguments: buffer: argument buffer Returns: None. *---------------------------------------------------------------------------*/ #ifndef OS_NO_ARGUMENT void OS_SetArgumentBuffer(const char *buffer) { sCurrentArgBuffer = buffer; } #endif //ifndef OS_NO_ARGUMENT /*---------------------------------------------------------------------------* Name: OS_GetArgumentBuffer Description: get pointer to argument buffer. Arguments: None. Returns: pointer to argument buffer. *---------------------------------------------------------------------------*/ #ifndef OS_NO_ARGUMENT const char *OS_GetArgumentBuffer(void) { return sCurrentArgBuffer; } #endif //ifndef OS_NO_ARGUMENT //================================================================================ // for TWL //================================================================================ #ifdef SDK_TWL /*---------------------------------------------------------------------------* Name: OS_InitDeliverArgInfo Description: initialize the argument delivery system for TWL Arguments: binSize : buffer size for binary area. Returns: None. *---------------------------------------------------------------------------*/ void OS_InitDeliverArgInfo( OSDeliverArgInfo* info, int binSize ) { SDK_ASSERT( 2<=(OS_DELIVER_ARG_BUFFER_SIZE-binSize) && binSize>=0); SDK_ASSERT( info != NULL ); sBufferPtr = info; //---- clear whole buffer MI_CpuClear8( sBufferPtr, HW_PARAM_DELIVER_ARG_SIZE ); //---- set parameters sBufferState = OS_DELIVER_ARG_BUF_ACCESSIBLE | OS_DELIVER_ARG_BUF_WRITABLE; sBufferPtr->header.argBufferSize = (u16)(OS_DELIVER_ARG_BUFFER_SIZE - binSize); sBufferPtr->header.binarySize = 0; //---- init pointer sPtr = &sBufferPtr->buf[0]; *sPtr = '\0'; *(sPtr+1) = '\0'; } /*---------------------------------------------------------------------------* Name: OS_SetStringToDeliverArg Description: write specified string as argument data Arguments: str : string to write Returns: OS_DELIVER_ARG_SUCCESS ... success. OS_DELIVER_ARG_OVER_SIZE ... failed. (over buffer) OS_DELIVER_ARG_NOT_READY ... failed. (buffer is not writable) *---------------------------------------------------------------------------*/ int OS_SetStringToDeliverArg( const char* str ) { int length; //---- check buffer state if ( !(sBufferState & OS_DELIVER_ARG_BUF_WRITABLE) ) { return OS_DELIVER_ARG_NOT_READY; } //---- check buffer over length = STD_StrLen( str ); if ( length > sBufferPtr->header.argBufferSize - (sPtr - &sBufferPtr->buf[0]) - 2) { return OS_DELIVER_ARG_OVER_SIZE; } //---- copy string (void)STD_StrCpy( (char*)sPtr, str ); sPtr += length; *sPtr++ = '\0'; *sPtr = '\0'; //---- return result return OS_DELIVER_ARG_SUCCESS; } /*---------------------------------------------------------------------------* Name: OS_SetBinaryToDeliverArg Description: write specified binary Arguments: bin : pointer for binary size: binary size Returns: OS_DELIVER_ARG_SUCCESS ... success. OS_DELIVER_ARG_OVER_SIZE ... failed. (over buffer) OS_DELIVER_ARG_NOT_READY ... failed. (buffer is not writable) *---------------------------------------------------------------------------*/ int OS_SetBinaryToDeliverArg( const void* bin, int size ) { u8* dest = &sBufferPtr->buf[ sBufferPtr->header.argBufferSize + sBufferPtr->header.binarySize ]; //---- check buffer state if ( !(sBufferState & OS_DELIVER_ARG_BUF_WRITABLE) ) { return OS_DELIVER_ARG_NOT_READY; } //---- check buffer over if ( size > OS_DELIVER_ARG_BUFFER_SIZE - sBufferPtr->header.argBufferSize - sBufferPtr->header.binarySize ) { return OS_DELIVER_ARG_OVER_SIZE; } //---- write binary data to buffer MI_CpuCopy8( bin, dest, (u32)size ); sBufferPtr->header.binarySize += (u16)size; //---- return result return OS_DELIVER_ARG_SUCCESS; } /*---------------------------------------------------------------------------* Name: OS_ConvertStringToDeliverArg Description: Coverts string to arguments Arguments: str : string cs : character to separate Returns: OS_DELIVER_ARG_SUCCESS ... success OS_DELIVER_ARG_OVER_SIZE ... failed. (over buffer) OS_DELIVER_ARG_NOT_READY ... failed. (buffer is not writable) *---------------------------------------------------------------------------*/ int OS_ConvertStringToDeliverArg(const char *str, char cs) { int length; const char* endp; //---- check buffer state if ( !(sBufferState & OS_DELIVER_ARG_BUF_WRITABLE) ) { return OS_DELIVER_ARG_NOT_READY; } while (1) { //---- skip separator while ( *str == cs ) { str++; } //---- check string end if ( ! *str ) { break; } //---- search separator endp = str; while ( *endp != cs && *endp != '\0' ) { endp++; } length = endp - str; //---- check buffer over if ( length > sBufferPtr->header.argBufferSize - (sPtr - &sBufferPtr->buf[0]) - 2) { return OS_DELIVER_ARG_OVER_SIZE; } //---- copy string while( str != endp ) { *sPtr ++ = *(u8*)str ++; } *sPtr ++ = '\0'; *sPtr = '\0'; } return OS_DELIVER_ARG_SUCCESS; } /*---------------------------------------------------------------------------* Name: OS_EncodeDeliverArg Description: Encodes argument buffer. Arguments: None. Returns: OS_DELIVER_ARG_SUCCESS ... success OS_DELIVER_ARG_NOT_READY ... failed. (buffer is not accesible) *---------------------------------------------------------------------------*/ int OS_EncodeDeliverArg(void) { //---- check buffer state if ( !(sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE) ) { return OS_DELIVER_ARG_NOT_READY; } //---- set makerCode, titleId sBufferPtr->header.makerCode = OS_GetMakerCode(); sBufferPtr->header.titleId = OS_GetTitleId(); //---- set flag sBufferPtr->header.flag = OS_DELIVER_ARG_ENCODE_FLAG | OS_DELIVER_ARG_VALID_FLAG; //---- set encoded titleId sEncodedTitleId = sBufferPtr->header.titleId; //---- calculate crc sBufferPtr->header.crc = 0; sBufferPtr->header.crc = SVC_GetCRC16( OSi_INIVALUE, (const void*)sBufferPtr, sizeof(OSDeliverArgInfo) ); //---- copy to HW_PARAM_DELIVER_ARG MI_CpuCopy8( sBufferPtr, (void*)HW_PARAM_DELIVER_ARG, sizeof(OSDeliverArgInfo) ); //---- clearArea MI_CpuClear8( sBufferPtr, sizeof(OSDeliverArgInfo) ); //---- buffer state sBufferState = OS_DELIVER_ARG_BUF_INVALID; return OS_DELIVER_ARG_SUCCESS; } /*---------------------------------------------------------------------------* Name: OS_DecodeDeliverArg Description: Decodes to work buffer from HW_PARAM_DELIVER_ARG Arguments: None. Returns: OS_DELIVER_ARG_SUCCESS ... success OS_DELIVER_ARG_NOT_READY ... not ready OS_DELIVER_ARG_INVALID ... invalid CRC check *---------------------------------------------------------------------------*/ int OS_DecodeDeliverArg(void) { //----check if deliver arg contains valid data if ( !OS_IsValidDeliverArg() ) { return OS_DELIVER_ARG_NOT_READY; } //----check buffer if ( ! sBufferPtr ) { return OS_DELIVER_ARG_NOT_READY; } //---- copy from HW_PARAM_DELIVER_ARG MI_CpuCopy8( (void*)HW_PARAM_DELIVER_ARG, sBufferPtr, sizeof(OSDeliverArgInfo) ); //---- crc check { u16 crc = sBufferPtr->header.crc; sBufferPtr->header.crc = 0; sBufferPtr->header.crc = SVC_GetCRC16( OSi_INIVALUE, (const void*)sBufferPtr, sizeof(OSDeliverArgInfo) ); if ( crc != sBufferPtr->header.crc ) { MI_CpuClear8( sBufferPtr, sizeof(OSDeliverArgInfo) ); OS_SetDeliverArgStateInvalid(); return OS_DELIVER_ARG_BUF_INVALID; } } //---- unset encode flag sBufferPtr->header.flag &= ~OS_DELIVER_ARG_ENCODE_FLAG; //---- buffer state sBufferState = OS_DELIVER_ARG_BUF_ACCESSIBLE; return OS_DELIVER_ARG_SUCCESS; } /*---------------------------------------------------------------------------* Name: OS_GetDeliverArgState Description: Gets deliver arg state Arguments: None. Returns: state. one of the following: OS_DELIVER_ARG_BUF_INVALID OS_DELIVER_ARG_BUF_ACCESSIBLE OS_DELIVER_ARG_BUF_ACCESSIBLE | OS_DELIVER_ARG_BUF_WRITABLE *---------------------------------------------------------------------------*/ u32 OS_GetDeliverArgState(void) { return sBufferState; } /*---------------------------------------------------------------------------* Name: OSi_SetDeliverArgState Description: Sets deliver arg state Arguments: state. one of the following: OS_DELIVER_ARG_BUF_INVALID OS_DELIVER_ARG_BUF_ACCESSIBLE OS_DELIVER_ARG_BUF_ACCESSIBLE | OS_DELIVER_ARG_BUF_WRITABLE Returns: None. *---------------------------------------------------------------------------*/ void OSi_SetDeliverArgState(u32 state) { sBufferState = state; } /*---------------------------------------------------------------------------* Name: OS_SetDeliverArgStateInvalid Description: Sets OS_DELIVER_ARG_BUF_INVALID to deliver arg state Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void OS_SetDeliverArgStateInvalid( void ) { sBufferState = OS_DELIVER_ARG_BUF_INVALID; } /*---------------------------------------------------------------------------* Name: OS_GetBinarySizeFromDeliverArg Description: Reads binary size Arguments: None. Returns: 0> ... size -1 ... work area not ready *---------------------------------------------------------------------------*/ int OS_GetBinarySizeFromDeliverArg(void) { if ( !(sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE) ) { return -1; } return sBufferPtr->header.binarySize; } /*---------------------------------------------------------------------------* Name: OS_GetBinaryFromDeliverArg Description: Reads binary data Arguments: buffer: pointer for binary size: pointer for binary size maxSize : Max size Returns: OS_DELIVER_ARG_SUCCESS ... success. OS_DELIVER_ARG_OVER_SIZE ... success but buffer over. OS_DELIVER_ARG_NOT_READY ... *---------------------------------------------------------------------------*/ int OS_GetBinaryFromDeliverArg( void* buffer, int* size, int maxSize ) { int retval; int copySize; //---- check buffer state if ( !(sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE) ) { return OS_DELIVER_ARG_NOT_READY; } //---- check buffer over if ( maxSize < sBufferPtr->header.binarySize ) { retval = OS_DELIVER_ARG_OVER_SIZE; copySize = maxSize; } else { retval = OS_DELIVER_ARG_SUCCESS; copySize = sBufferPtr->header.binarySize; } //---- read binary data MI_CpuCopy8( &sBufferPtr->buf[sBufferPtr->header.argBufferSize], buffer, (u32)copySize ); if ( size ) { *size = copySize; } return retval; } /*---------------------------------------------------------------------------* Name: OS_GetTitleIdFromDeliverArg Description: Gets the title ID Arguments: None. Returns: title ID. if not accessible, return 0 *---------------------------------------------------------------------------*/ OSTitleId OS_GetTitleIdFromDeliverArg( void ) { return (sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE)? sBufferPtr->header.titleId: 0; } /*---------------------------------------------------------------------------* Name: OS_GetGameCodeFromDeliverArg Description: Gets the game code Arguments: None. Returns: game code if not accessible, return 0 *---------------------------------------------------------------------------*/ u32 OS_GetGameCodeFromDeliverArg( void ) { return (sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE)? *(u32*)(&sBufferPtr->header.titleId): 0; } /*---------------------------------------------------------------------------* Name: OS_GetMakerCodeFromDeliverArg Description: Gets the maker code Arguments: None. Returns: maker code if not accessible, return 0 *---------------------------------------------------------------------------*/ u16 OS_GetMakerCodeFromDeliverArg( void ) { return (u16)((sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE)? sBufferPtr->header.makerCode: 0); } /*---------------------------------------------------------------------------* Name: OS_IsValidDeliverArg Description: Checks if deliver arg contains valid data Arguments: None. Returns: TRUE if valid FALSE if not valid *---------------------------------------------------------------------------*/ BOOL OS_IsValidDeliverArg( void ) { // TODO: a more reliable verification OSDeliverArgInfo* p = (OSDeliverArgInfo*)HW_PARAM_DELIVER_ARG; return (p->header.flag & OS_DELIVER_ARG_VALID_FLAG) ? TRUE : FALSE; } /*---------------------------------------------------------------------------* Name: OS_IsDeliverArgEncoded Description: Gets titleId that is contained in last encoded deliverArg Arguments: None. Returns: TRUE if deliverArg has been encoded FALSE if deliverArg has never been encoded since application was launched *---------------------------------------------------------------------------*/ BOOL OS_IsDeliverArgEncoded( void ) { OSDeliverArgInfo* p = (OSDeliverArgInfo*)HW_PARAM_DELIVER_ARG; return (p->header.flag & (OS_DELIVER_ARG_ENCODE_FLAG | OS_DELIVER_ARG_VALID_FLAG)) ? TRUE : FALSE; } /*---------------------------------------------------------------------------* Name: OS_GetTitleIdLastEncoded Description: Gets titleId that is contained in last encoded deliverArg Arguments: None. Returns: TitleID if deliverArg has been encoded 0 if deliverArg has never been encoded since application was launched *---------------------------------------------------------------------------*/ OSTitleId OS_GetTitleIdLastEncoded( void ) { return sEncodedTitleId; } /*---------------------------------------------------------------------------* Name: OS_SetSysParamToDeliverArg Description: set sysParam to deliverArg Arguments: param: parameter to set Returns: None. *---------------------------------------------------------------------------*/ int OS_SetSysParamToDeliverArg( u16 param ) { if ( !(sBufferState & OS_DELIVER_ARG_BUF_WRITABLE) ) { return OS_DELIVER_ARG_NOT_READY; } sBufferPtr->header.sysParam = param; return OS_DELIVER_ARG_SUCCESS; } /*---------------------------------------------------------------------------* Name: OS_GetSysParamFromDeliverArg Description: Gets sysParam from deliverArg Arguments: None. Returns: parameter. 0 if FAIL. *---------------------------------------------------------------------------*/ u16 OS_GetSysParamFromDeliverArg( void ) { if ( !(sBufferState & OS_DELIVER_ARG_BUF_ACCESSIBLE) ) { return 0; } return sBufferPtr->header.sysParam; } /*---------------------------------------------------------------------------* Name: OS_GetDeliverArgc Description: GEts number of valid arguments in deliverArg. Arguments: None. Returns: number of valid arguments. return 1 if no argument. return 0 if buffer is not prepared. *---------------------------------------------------------------------------*/ int OS_GetDeliverArgc(void) { if ( sBufferPtr && sBufferState == OS_DELIVER_ARG_BUF_ACCESSIBLE ) { return OSi_GetArgc_core( (const char *)sBufferPtr->buf ) + 1; } return 0; } /*---------------------------------------------------------------------------* Name: OS_GetDeliverArgv Description: Gets the pointer to the specified argument string in deliverArg. Arguments: n: index of argument. n==1 means the first argument. n must be less than value of the OS_GetDeliverArgc function Returns: pointer to string *---------------------------------------------------------------------------*/ const char *OS_GetDeliverArgv(int n) { static const char *procName = "main"; SDK_ASSERT(n >= 0); if ( sBufferPtr && sBufferState == OS_DELIVER_ARG_BUF_ACCESSIBLE ) { return (n==0)? procName: OSi_GetArgv_core( (const char *)sBufferPtr->buf, n-1 ); } return NULL; } #endif //ifdef SDK_TWL