Example #1
0
/*
 * Return the working directory for the current buffer, terminated
 * with a '/'. First, try to extract it from the current buffer's
 * filename. If that fails, use global cwd.
 */
int
getbufcwd(char *path, size_t plen)
{
	char cwd[NFILEN];

	if (plen == 0)
		return (FALSE);

	if (globalwd == FALSE && curbp->b_cwd[0] != '\0') {
		(void)strlcpy(path, curbp->b_cwd, plen);
	} else {
		if (getcwdir(cwd, sizeof(cwd)) == FALSE)
			goto error;
		(void)strlcpy(path, cwd, plen);
	}
	return (TRUE);
error:
	path[0] = '\0';
	return (FALSE);
}
Example #2
0
error_t
fshelp_start_translator (fshelp_open_fn_t underlying_open_fn,
			 void *cookie, char *name, char *argz,
			 int argz_len, int timeout, fsys_t *control)
{
  mach_port_t ports[INIT_PORT_MAX];
  mach_port_t fds[STDERR_FILENO + 1];
  int ints[INIT_INT_MAX];
  int i;
  error_t err;

  for (i = 0; i < INIT_PORT_MAX; i++)
    ports[i] = MACH_PORT_NULL;
  for (i = 0; i < STDERR_FILENO + 1; i++)
    fds[i] = MACH_PORT_NULL;
  memset (ints, 0, INIT_INT_MAX * sizeof(int));

  ports[INIT_PORT_CWDIR] = getcwdir ();
  ports[INIT_PORT_CRDIR] = getcrdir ();
  ports[INIT_PORT_AUTH] = getauth ();
  fds[STDERR_FILENO] = getdport (STDERR_FILENO);

  err = fshelp_start_translator_long (underlying_open_fn, cookie,
				      name, argz, argz_len,
				      fds, MACH_MSG_TYPE_COPY_SEND,
				      STDERR_FILENO + 1,
				      ports, MACH_MSG_TYPE_COPY_SEND,
				      INIT_PORT_MAX,
				      ints, INIT_INT_MAX,
				      geteuid (),
				      timeout, control);
  for (i = 0; i < INIT_PORT_MAX; i++)
    mach_port_deallocate (mach_task_self (), ports[i]);
  for (i = 0; i <= STDERR_FILENO; i++)
    mach_port_deallocate (mach_task_self (), fds[i]);

  return err;
}
Example #3
0
int main(int argc, char *argv[])
{
	app_title();
	
	//Argument Checks
	if(argc < 3){
		printf("[!] Not Enough Arguments\n");
		help(argv[0]);
		return 1;
	}
	if(argc > 3){
		printf("[!] Too Many Arguments\n");
		help(argv[0]);
		return 1;
	}
	
	//Storing Current Working Directory
	char cwd[1024];
	if (getcwdir(cwd, sizeof(cwd)) == NULL){
		printf("[!] Could not store Current Working Directory\n");
		return IO_FAIL;
	}
	
	//Changing to CDN Content Directory
	chdir(argv[1]);
	
	//Processing TIK
	FILE *tik = fopen("cetk","rb");
	if(tik == NULL){
		printf("[!] Could not open 'tik'\n");
		return IO_FAIL;
	}
	TIK_CONTEXT tik_context = process_tik(tik);
	
	//Processing TMD
	FILE *tmd = fopen("tmd","rb");
	if(tmd == NULL){
		printf("[!] Could not open 'tmd'\n");
		return IO_FAIL;
	}
	TMD_CONTEXT tmd_context = process_tmd(tmd);
	
	//Error Checking
	if(tik_context.result != 0 || tmd_context.result != 0){
		printf("[!] Input files could not be processed successfully\n");
		free(tmd_context.content_struct);
		free(tmd_context.content);
		fclose(tik);
		fclose(tmd);
		return FILE_PROCESS_FAIL;
	}
	//TID comparison check
	if(check_tid(tik_context.title_id,tmd_context.title_id) != TRUE){
		printf("[!] Caution, Ticket and TMD Title IDs do not match\n");
		printf("[!] CETK Title ID:  "); u8_hex_print_be(tik_context.title_id,0x8); printf("\n");
		printf("[!] TMD Title ID:   "); u8_hex_print_be(tmd_context.title_id,0x8); printf("\n");
	}
	//Title Version comparison
	if(tik_context.title_version != tmd_context.title_version){
		printf("[!] Caution, Ticket and TMD Title Versions do not match\n");
		printf("[!] CETK Title Ver: %d\n",tik_context.title_version);
		printf("[!] TMD Title Ver:  %d\n",tmd_context.title_version);
	}
	
	//Returning to Original Working Directory
	chdir(cwd);
	
	//Opening Output file
	FILE *output = fopen(argv[2],"wb");
	if(output == NULL){
		printf("[!] Could not create '%s'\n",argv[2]);
		return IO_FAIL;
	}
	
	int result = generate_cia(tmd_context,tik_context,output);
	if(result != 0){
		printf("[!] Failed to Generate %s\n",argv[2]);
		remove(argv[2]);
	}
	else
		printf("[*] %s Generated Sucessfully\n",argv[2]);
	
	return 0;
}
Example #4
0
int main(int argc, char *argv[])
{
    if(argc < 2) {
        printf("[!] Invalid Arguments (Not Enough Arguments)\n");
        help(argv[0]);
        return 1;
    }
    int mode = -1;
    // Deciding Mode of Operation
    for(int i = 1; i < argc; i++) {
        if(strcmp(argv[i],"-g") == 0 || strcmp(argv[i],"--genxor") == 0) {
            mode = gen_xorpad;
            break;
        }
        else if(strcmp(argv[i],"-d") == 0 || strcmp(argv[i],"--decrypt") == 0) {
            mode = dec_icondata;
            break;
        }
        else if(strcmp(argv[i],"-t") == 0 || strcmp(argv[i],"--disp_tid") == 0) {
            mode = read_cache_dat;
            break;
        }
        else if(strcmp(argv[i],"-o") == 0 || strncmp(argv[i],"--dec_list=",11) == 0) {
            mode = read_cache_dat;
            break;
        }
    }
    if(mode == -1) {
        printf("[!] Invalid Arguments (No Mode Specified)\n");
        help(argv[0]);
        return 1;
    }

    if(mode == read_cache_dat) {
        return ReadCacheDat(argc,argv);
    }

    // Getting Current Working Directory
    char CWD[1024];
    memset(CWD,0,1024);
    getcwdir(CWD,1024);

    // Getting Data from args
    s32 pre_existing_icons = -1;
    s32 icons_to_crypt = -1;
    char *xor_dir = NULL;
    char *dec_icn_dir = NULL;
    char *cacheD_path = NULL;
    char xor_abs_dir[1024];
    memset(xor_abs_dir,0,1024);
    char dec_icn_abs_dir[1024];
    memset(dec_icn_abs_dir,0,1024);

    for(int i = 1; i < argc; i++) {
        if(strcmp(argv[i],"-i") == 0 && dec_icn_dir == NULL && i < argc-1) {
            dec_icn_dir = argv[i+1];
        }
        else if(strncmp(argv[i],"--decdata=",10) == 0 && dec_icn_dir == NULL) {
            dec_icn_dir = (char*)(argv[i]+10);
        }
        else if(strcmp(argv[i],"-x") == 0 && xor_dir == NULL && i < argc-1) {
            xor_dir = argv[i+1];
        }
        else if(strncmp(argv[i],"--xorpaddir=",12) == 0 && xor_dir == NULL) {
            xor_dir = (char*)(argv[i]+12);
        }
        else if(strcmp(argv[i],"-c") == 0 && cacheD_path == NULL && i < argc-1) {
            cacheD_path = argv[i+1];
        }
        else if(strncmp(argv[i],"--iconcache=",12) == 0 && cacheD_path == NULL) {
            cacheD_path = (char*)(argv[i]+12);
        }
        else if(strcmp(argv[i],"-0") == 0 && pre_existing_icons == -1 && i < argc-1) {
            pre_existing_icons = strtoul(argv[i+1],NULL,10);
        }
        else if(strncmp(argv[i],"--unused_slots=",15) == 0 && pre_existing_icons == -1) {
            pre_existing_icons = strtoul((argv[i]+15),NULL,10);
        }
        else if(strcmp(argv[i],"-1") == 0 && icons_to_crypt == -1 && i < argc-1) {
            icons_to_crypt = strtoul(argv[i+1],NULL,10);
        }
        else if(strncmp(argv[i],"--num_decrypt=",14) == 0 && icons_to_crypt == -1) {
            icons_to_crypt = strtoul((argv[i]+14),NULL,10);
        }
    }

    // Sorting out bad input
    if(pre_existing_icons < 0 || pre_existing_icons > 360) {
        printf("[!] Invalid input or no input, for option '-0'/'--unused_slots='\n");
        help(argv[0]);
        return 1;
    }
    if(icons_to_crypt < 1 || icons_to_crypt > 360) {
        printf("[!] Invalid input or no input, for option '-1'/'--num_decrypt='\n");
        help(argv[0]);
        return 1;
    }
    if(dec_icn_dir == NULL) {
        printf("[!] No Plaintext Icon directory was specified\n");
        help(argv[0]);
        return 1;
    }
    if(xor_dir == NULL) {
        printf("[!] No XOR pad Directory was specified\n");
        help(argv[0]);
        return 1;
    }
    if(cacheD_path == NULL) {
        printf("[!] No Encryption Icon Cache was specified\n");
        help(argv[0]);
        return 1;
    }
    // Opening Icon Cache File
    FILE *cacheD = fopen(cacheD_path,"rb");
    if(cacheD == NULL) {
        printf("[!] Failed to open '%s'\n",cacheD_path);
        return 1;
    }

    // Allocating Buffers
    u8 *DecIconData = malloc(SMDH_SIZE);
    u8 *EncIconData = malloc(SMDH_SIZE);
    u8 *XORpad = malloc(SMDH_SIZE);
    if(DecIconData == NULL || EncIconData == NULL || XORpad == NULL) {
        printf("[!] Memory Error\n");
        return 1;
    }

    // Getting Absolute Dir Paths for Icon Dir and XOR pad DIR
    if(mode == gen_xorpad) makedir(xor_dir);
    else if(mode == dec_icondata) makedir(dec_icn_dir);

    chdir(xor_dir);
    getcwdir(xor_abs_dir,1024);
    chdir(CWD);
    chdir(dec_icn_dir);
    getcwdir(dec_icn_abs_dir,1024);
    chdir(CWD);

    // Informing the user what the program will do
    if(mode == gen_xorpad) printf("[+] Generating XOR pad(s)\n");
    else if(mode == dec_icondata) printf("[+] Decrypting Icon Data\n");

    // Init File Pointers / Arrays / Values
    FILE *dec_icon_fp = NULL;
    FILE *xor_pad_fp = NULL;
    char deciconfile[100];
    char xorfile[100];
    u32 enc_icon_pos = 0;

    for(int i = pre_existing_icons; i < (pre_existing_icons+icons_to_crypt); i++) {
        enc_icon_pos = CACHE_EXTDATA_OFFSET + SMDH_SIZE*i;

        // Getting File Names
        memset(&deciconfile,0,100);
        memset(&xorfile,0,100);
        sprintf(deciconfile,"icon_%d.icn",i);
        sprintf(xorfile,"icon_%d.xor",i);


        // Getting Enc Icon
        ReadFile_64(EncIconData,SMDH_SIZE,enc_icon_pos,cacheD);

        // Getting File Pointers and Storing Data
        if(mode == gen_xorpad) {
            chdir(dec_icn_abs_dir);
            dec_icon_fp = fopen(deciconfile,"rb");
            if(dec_icon_fp == NULL) {
                printf("[!] Failed To Open '%s'\n",deciconfile);
                return 1;
            }
            chdir(xor_abs_dir);
            xor_pad_fp = fopen(xorfile,"wb");
            if(xor_pad_fp == NULL) {
                printf("[!] Failed To Create '%s'\n",xorfile);
                return 1;
            }

            // Storing Dec Icon
            ReadFile_64(DecIconData,SMDH_SIZE,0,dec_icon_fp);
            int icon_check = CheckDecIcon(DecIconData);
            if(icon_check == BAD_ICON) printf("[!] Caution '%s' does not appear to be an icon file, '%s' may be invalid\n",deciconfile,xorfile);
        }
        else if(mode == dec_icondata) {
            chdir(dec_icn_abs_dir);
            dec_icon_fp = fopen(deciconfile,"wb");
            if(dec_icon_fp == NULL) {
                printf("[!] Failed To Create '%s'\n",deciconfile);
                return 1;
            }
            chdir(xor_abs_dir);
            xor_pad_fp = fopen(xorfile,"rb");
            if(xor_pad_fp == NULL) {
                printf("[!] Failed To Open '%s'\n",xorfile);
                return 1;
            }

            // Storing XOR pad
            ReadFile_64(XORpad,SMDH_SIZE,0,xor_pad_fp);
        }

        // Perform XOR crypto
        if(mode == gen_xorpad) xor_file(XORpad, DecIconData, EncIconData, SMDH_SIZE);
        else if(mode == dec_icondata) {
            xor_file(DecIconData, XORpad, EncIconData, SMDH_SIZE);
            int icon_check = CheckDecIcon(DecIconData);
            if(icon_check == BAD_ICON) printf("[!] '%s' does not appear to have decrypted properly\n",deciconfile);
        }

        // Writing Output to File
        if(mode == gen_xorpad) WriteBuffer(XORpad, SMDH_SIZE, 0, xor_pad_fp);
        else if(mode == dec_icondata) WriteBuffer(DecIconData, SMDH_SIZE, 0, dec_icon_fp);

        fclose(dec_icon_fp);
        fclose(xor_pad_fp);
    }

    // Freeing Buffers and Icon Cache File Pointer
    free(EncIconData);
    free(DecIconData);
    free(XORpad);
    fclose(cacheD);

    printf("[*] Done\n");
    return 0;
}
Example #5
0
int main(int argc, char *argv[])
{
	if(argc < 2){
		help(argv[0]);
		return 1;
	}
	int action = 0;
	int i = 1;
	while(!action){
		if(i == argc) break; 
		if(strcmp(argv[i],"-i") == 0 || strncmp(argv[i],"--image=",8) == 0) action = image;
		if(strcmp(argv[i],"-d") == 0 || strncmp(argv[i],"--FSdir=",8) == 0) action = fs;
		if(strcmp(argv[i],"-g") == 0 || strncmp(argv[i],"--genextdata=",13) == 0) action = generate;
		i++;
	}	
	if(action == 0){
		printf("[!] Nothing to do\n");
		help(argv[0]);
		return ARG_ERROR;
	}
	
	if(action == image){
		ExtdataContext *extdata = malloc(sizeof(ExtdataContext));
		InitaliseExtdataContext(extdata);
		char *input = NULL;
		char *output = NULL;
		int DB_Mode = -1;
		u8 Extract = False;
		extdata->PrintInfo = False;
		extdata->Verbose = False;
		extdata->OverrideActiveDIFI = False;
		u8 result = 0;
		
		for(i = 1; i < argc; i++){
			if(strcmp(argv[i],"-i") == 0 && input == NULL && i < argc-1){
				input = argv[i+1];
			}
			else if(strncmp(argv[i],"--image=",8) == 0 && input == NULL){
				input = (char*)(argv[i]+8);
			}
			else if(strcmp(argv[i],"-x") == 0 && output == NULL && i < argc-1 && Extract == False){
				Extract = True;
				output = argv[i+1];
			}
			else if(strncmp(argv[i],"--extract=",10) == 0 && output == NULL && Extract == False){
				Extract = True;
				output = (char*)(argv[i]+10);
			}
			else if(strcmp(argv[i],"-a") == 0 && i < argc-1){
				extdata->OverrideActiveDIFI = True;
				extdata->DIFIPartition = strtol(argv[i+1],NULL,10);
			}
			else if(strncmp(argv[i],"--forcedifi=",12) == 0){
				extdata->OverrideActiveDIFI = True;
				extdata->DIFIPartition = strtol((argv[i]+12),NULL,10);
			}
			else if(strcmp(argv[i],"-p") == 0 || strcmp(argv[i],"--info") == 0){
				extdata->PrintInfo = True;
			}
			else if(strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0){
				extdata->Verbose = True;
			}
			else if(strcmp(argv[i],"-l") == 0 || strcmp(argv[i],"--listDB") == 0){
				DB_Mode = DB_Normal;
			}
			else if(strcmp(argv[i],"-0") == 0 || strcmp(argv[i],"--listTID") == 0){
				DB_Mode = DB_ByTID;
			}
		}
		
		if(input == NULL){
			printf("[!] No input extdata image was specified\n");
			FreeExtdataContext(extdata);
			help(argv[0]);
			return ARG_ERROR;
		}
		if(Extract == False && extdata->PrintInfo == False && extdata->Verbose == False && DB_Mode == -1){
			printf("[!] Nothing to do\n");
			FreeExtdataContext(extdata);
			help(argv[0]);
			return ARG_ERROR;
		}
		
		if(extdata->OverrideActiveDIFI && extdata->DIFIPartition != 0 && extdata->DIFIPartition != 1){
			printf("[!] Invalid DIFI partition: %d\n",extdata->DIFIPartition);
			FreeExtdataContext(extdata);
			help(argv[0]);
			return ARG_ERROR;
		}
		FILE *fp = fopen(input,"rb");
		if(fp == NULL){
			printf("[!] Failed to open '%s'\n",input);
			FreeExtdataContext(extdata);
			return IO_ERROR;
		}
		fclose(fp);
		extdata->extdata.size = GetFileSize_u64(input);
		extdata->extdata.buffer = malloc(extdata->extdata.size);
		if(extdata->extdata.buffer == NULL){
			printf("[!] Failed to allocate memory for extdata image\n");
			FreeExtdataContext(extdata);
			return MEM_ERROR;
		}
		fp = fopen(input,"rb");
		ReadFile_64(extdata->extdata.buffer,extdata->extdata.size,0,fp);
		fclose(fp);
		result = GetExtdataContext(extdata);
		if(result != 0){
			printf("[!] Failed to interprete extdata image (%d)\n",result);
			FreeExtdataContext(extdata);
			return 1;
		}
		
		if(extdata->Files.Count > 0){
			u8* embedded_data = extdata->extdata.buffer + extdata->Files.Data[0].offset;
		
			// Extracting Data
			if(extdata->Files.Count == 1 && Extract){
				fp = fopen(output,"wb");
				if(fp == NULL){
					printf("[!] Failed to create '%s'\n",output);
					FreeExtdataContext(extdata);
					return IO_ERROR;
				}
				if(extdata->Verbose) printf("[+] Writing data to '%s'\n",output);
				WriteBuffer(embedded_data,extdata->Files.Data[0].size,0,fp);
				fclose(fp);
			}
		
			// Displaying DB... if possible
			if(DB_Mode >= 0){
				if(extdata->ExtdataType == RawIVFC && extdata->Files.Count == 1 && IsTitleDB(embedded_data)){
					result = ProcessTitleDB(embedded_data,DB_Mode);
					if(result){
						printf("[!] Failed to read DB (%d)\n",result);
					}
				}
				else{
					printf("[!] No valid Title Database in extdata\n"); 
				}
			
			}
		}
		else{
			printf("[!] No data exists embedded in extdata\n"); 
		}
		FreeExtdataContext(extdata);
	}
	
	else if(action == fs){
		VSXEContext *vsxe_ctx = malloc(sizeof(VSXEContext));
		ExtdataContext *vsxe = malloc(sizeof(ExtdataContext));
		char *input = NULL;
		char *output = NULL;
		char cwd[IO_PATH_LEN];
		char VSXE_image_path[IO_PATH_LEN];
		memset(vsxe_ctx,0,sizeof(VSXEContext));
		memset(&cwd,0,IO_PATH_LEN);
		memset(&VSXE_image_path,0,IO_PATH_LEN);
		memset(vsxe,0,sizeof(ExtdataContext));
		
		if(getcwdir(cwd,IO_PATH_LEN) == NULL){
			printf("[!] Could not store Current Working Directory\n");
			return IO_ERROR;
		}
		
		
		for(i = 1; i < argc; i++){
			if(strcmp(argv[i],"-d") == 0 && input == NULL && i < argc-1){
				input = argv[i+1];
			}
			else if(strncmp(argv[i],"--FSdir=",8) == 0 && input == NULL){
				input = (char*)(argv[i]+8);
			}
			else if(strcmp(argv[i],"-x") == 0 && output == NULL && i < argc-1){
				vsxe_ctx->Flags[vsxe_extract] = True;
				output = argv[i+1];
			}
			else if(strncmp(argv[i],"--extractFS=",12) == 0 && output == NULL){
				vsxe_ctx->Flags[vsxe_extract] = True;
				output = (char*)(argv[i]+12);
			}
			else if(strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"--showFS") == 0){
				vsxe_ctx->Flags[vsxe_show_fs] = True;
			}
			else if(strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0){
				vsxe_ctx->Flags[vsxe_verbose] = True;
			}
			else if(strcmp(argv[i],"-f") == 0 || strcmp(argv[i],"--FStable") == 0){
				vsxe_ctx->Flags[vsxe_fstable] = True;
			}
			else if(strcmp(argv[i],"-a") == 0 && i < argc-1){
				vsxe->OverrideActiveDIFI = True;
				vsxe->DIFIPartition = strtol(argv[i+1],NULL,10);
			}
			else if(strncmp(argv[i],"--forcedifi=",12) == 0){
				vsxe->OverrideActiveDIFI = True;
				vsxe->DIFIPartition = strtol((argv[i]+12),NULL,10);
			}
		}
		
		if(input == NULL){
			printf("[!] No Extdata FS directory was specified\n");
			free(vsxe_ctx);
			FreeExtdataContext(vsxe);
			return ARG_ERROR;
		}
		
		if(vsxe_ctx->Flags[vsxe_extract] && output == NULL){
			printf("[!] No Output directory was specified\n");
			free(vsxe_ctx);
			FreeExtdataContext(vsxe);
			return ARG_ERROR;
		}
		
		if(vsxe_ctx->Flags[vsxe_show_fs] == False && vsxe_ctx->Flags[vsxe_extract] == False && vsxe_ctx->Flags[vsxe_fstable] == False){
			printf("[!] Nothing to do\n");
			free(vsxe_ctx);
			FreeExtdataContext(vsxe);
			return ARG_ERROR;
		}
		
#ifdef _WIN32
		vsxe_ctx->platform = WIN_32;
#else
		vsxe_ctx->platform = UNIX;
#endif
		
		// Storing Input Directory
		vsxe_ctx->input = malloc(IO_PATH_LEN);
		if(vsxe_ctx->input == NULL){
			printf("[!] Failed to allocate memory for input path\n");
			free(vsxe_ctx);
			FreeExtdataContext(vsxe);
			return MEM_ERROR;
		}
		chdir(input);
		if(getcwdir(vsxe_ctx->input,IO_PATH_LEN) == NULL){
			printf("[!] Could not store input Directory\n");
			free(vsxe_ctx->input);
			free(vsxe_ctx);
			FreeExtdataContext(vsxe);
			return IO_ERROR;
		}
		chdir(cwd);
		
		// Storing Output Directory
		vsxe_ctx->output = malloc(IO_PATH_LEN);
		if(vsxe_ctx->output == NULL){
			printf("[!] Failed to allocate memory for output path\n");
			free(vsxe_ctx->input);
			free(vsxe_ctx);
			FreeExtdataContext(vsxe);
			return MEM_ERROR;
		}
		chdir(output);
		if(getcwdir(vsxe_ctx->output,IO_PATH_LEN) == NULL){
			printf("[!] Could not store output Directory\n");
			free(vsxe_ctx->input);
			free(vsxe_ctx->output);
			free(vsxe_ctx);
			FreeExtdataContext(vsxe);
			return IO_ERROR;
		}
		chdir(cwd);
		
		// Getting path to VSXE FS Image
		sprintf(VSXE_image_path,"%s%c00000001.dec",vsxe_ctx->input,vsxe_ctx->platform);
		
		FILE *fp = fopen(VSXE_image_path,"rb");
		if(fp == NULL){
			printf("[!] Could not open '%s'\n",VSXE_image_path);
			free(vsxe_ctx->input);
			free(vsxe_ctx->output);
			free(vsxe_ctx);
			FreeExtdataContext(vsxe);
			return IO_ERROR;
		}
		
		fclose(fp);
		vsxe->extdata.size = GetFileSize_u64(VSXE_image_path);
		vsxe->extdata.buffer = malloc(vsxe->extdata.size);
		if(vsxe->extdata.buffer == NULL){
			printf("[!] Failed to allocate memory for VSXE FST Image\n");
			free(vsxe_ctx->input);
			free(vsxe_ctx->output);
			free(vsxe_ctx);
			FreeExtdataContext(vsxe);
			return MEM_ERROR;
		}
		
		// Getting VSXE FST Image
		fp = fopen(VSXE_image_path,"rb");
		ReadFile_64(vsxe->extdata.buffer,vsxe->extdata.size,0,fp);
		fclose(fp);
		
		u8 result = GetExtdataContext(vsxe);
		if(result){
			printf("[!] Failed to obtain VSXE FST from image '%s' (%d)\n",VSXE_image_path,result);
			free(vsxe_ctx->input);
			free(vsxe_ctx->output);
			free(vsxe_ctx);
			FreeExtdataContext(vsxe);
			return result;
		}
		
		if(vsxe->Files.Count > 0){
			u8 *vsxe_offset = vsxe->extdata.buffer + vsxe->Files.Data[0].offset;
			if(vsxe->ExtdataType == RawIVFC && vsxe->Files.Count == 1 && IsVSXEFileSystem(vsxe_offset)){
				vsxe_ctx->vsxe = vsxe_offset;
				result = ProcessExtData_FS(vsxe_ctx);
				if(result){
					printf("[!] Failed to read VSXE FST (%d)\n",result);
				}
			}
			else{
				printf("[!] No valid VSXE FST exists in '%s'\n",output); 
			}
		}
		else{
			printf("[!] No data exists embedded in extdata\n"); 
		}
		free(vsxe_ctx->input);
		free(vsxe_ctx->output);
		free(vsxe_ctx);
		FreeExtdataContext(vsxe);
	}
	
	else if(action == generate){
		// Extdata Gen
		COMPONENT_STRUCT sourcedata;
		memset(&sourcedata,0,sizeof(COMPONENT_STRUCT));
		COMPONENT_STRUCT outdata;
		memset(&outdata,0,sizeof(COMPONENT_STRUCT));
		
		char *input = NULL;
		char *output = NULL;
		char *extdatatype = NULL;
		u32 activeDIFI = 0;
		u8 type = 0;
		u8 Verbose = False;
		u8 UniqueExtdataID[8];
		memset(&UniqueExtdataID,0,8);
		
		u8 GenMAC = False;
		
		for(i = 1; i < argc; i++){
			if(strcmp(argv[i],"-1") == 0 || strcmp(argv[i],"-2") == 0 || strncmp(argv[i],"--keyX=",6) == 0 || strncmp(argv[i],"--keyY=",6) == 0){
				GenMAC = True;
			}
			else if(strcmp(argv[i],"-g") == 0 && input == NULL && i < argc-1){
				input = argv[i+1];
			}
			else if(strncmp(argv[i],"--genextdata=",13) == 0 && input == NULL){
				input = (char*)(argv[i]+13);
			}
			else if(strcmp(argv[i],"-o") == 0 && output == NULL && i < argc-1){
				output = argv[i+1];
			}
			else if(strncmp(argv[i],"--outimage=",11) == 0 && output == NULL){
				output = (char*)(argv[i]+11);
			}
			else if(strcmp(argv[i],"-t") == 0 && extdatatype == NULL && i < argc-1){
				extdatatype = argv[i+1];
			}
			else if(strncmp(argv[i],"--type=",7) == 0 && extdatatype == NULL){
				extdatatype = (char*)(argv[i]+7);
			}
			else if(strcmp(argv[i],"-a") == 0 && i < argc-1){
				activeDIFI = strtol(argv[i+1],NULL,10);
			}
			else if(strncmp(argv[i],"--activedifi=",13) == 0){
				activeDIFI = strtol((argv[i]+13),NULL,10);
			}
			else if(strcmp(argv[i],"-u") == 0 && i < argc-1){
				if(strlen(argv[i+1]) == 16)
					char_to_u8_array(UniqueExtdataID,argv[i+1],8,BE,16);
				else
					printf("[!] Invalid length for Extdata Unique ID (expected 16 hex characters)\n"); 
			}
			else if(strncmp(argv[i],"--uniqueID=",11) == 0){
				if(strlen((argv[i]+11)) == 16)
					char_to_u8_array(UniqueExtdataID,(argv[i]+11),8,BE,16);
				else
					printf("[!] Invalid length for Extdata Unique ID (expected 16 hex characters)\n"); 
			}
			else if(strcmp(argv[i],"-v") == 0 || strcmp(argv[i],"--verbose") == 0){
				Verbose = True;
			}
		}
		
		if(input == NULL){
			printf("[!] No input image was specified\n");
			help(argv[0]);
			return ARG_ERROR;
		}
		
		if(output == NULL){
			printf("[!] No output extdata image was specified\n");
			help(argv[0]);
			return ARG_ERROR;
		}
		
		if(extdatatype == NULL){
			printf("[!] No extdata type was specified\n");
			help(argv[0]);
			return ARG_ERROR;
		}
		
		// MAC Gen
		AESMAC_CTX *aes_ctx = malloc(sizeof(AESMAC_CTX));
		memset(aes_ctx,0,sizeof(AESMAC_CTX));
		u8 KeyX[0x10];
		u8 KeyY[0x10];
		memset(&KeyX,0,0x10);
		memset(&KeyY,0,0x10);
		
		aes_ctx->Verbose = Verbose;

		if(strcmp(extdatatype,"DATA") == 0){
			type = BUILD_DATA;
			aes_ctx->type = mac_extdata;	
		}
		else if(strcmp(extdatatype,"FS") == 0){
			type = BUILD_FS;
			aes_ctx->type = mac_extdata;	
		}
		else if(strcmp(extdatatype,"TDB") == 0){
			type = BUILD_DB;
			aes_ctx->type = mac_title_db;	
		}
		else if(strcmp(extdatatype,"IDB") == 0){
			type = BUILD_DB;
			aes_ctx->type = mac_import_db;	
		}
			
		if(type == 0){
			printf("[!] Invalid Extdata type '%s'\n",extdatatype);
			help(argv[0]);
			free(aes_ctx);
			return ARG_ERROR;
		}
			
		if(GenMAC){
			for(i = 1; i < argc; i++){
				if(strcmp(argv[i],"-1") == 0 && i < argc-1){
					if(strlen(argv[i+1]) == 32)
						char_to_u8_array(KeyX,argv[i+1],16,BE,16);
					else{
						printf("[!] Invalid length for KeyX (expected 32 hex characters)\n"); 
						help(argv[0]);
						free(aes_ctx);
						return ARG_ERROR;
					}
				}
				else if(strncmp(argv[i],"--keyX=",7) == 0){
					if(strlen((argv[i]+7)) == 32)
						char_to_u8_array(KeyX,(argv[i]+7),16,BE,16);
					else{
						printf("[!] Invalid length for KeyX (expected 32 hex characters)\n"); 
						help(argv[0]);
						free(aes_ctx);
						return ARG_ERROR;
					}
				}
				else if(strcmp(argv[i],"-2") == 0 && i < argc-1){
					if(strlen(argv[i+1]) == 32)
						char_to_u8_array(KeyY,argv[i+1],16,BE,16);
					else{
						printf("[!] Invalid length for KeyY (expected 32 hex characters)\n"); 
						help(argv[0]);
						free(aes_ctx);
						return ARG_ERROR;
					}
				}
				else if(strncmp(argv[i],"--keyY=",7) == 0){
					if(strlen((argv[i]+7)) == 32)
						char_to_u8_array(KeyY,(argv[i]+7),16,BE,16);
					else{
						printf("[!] Invalid length for KeyY (expected 32 hex characters)\n"); 
						help(argv[0]);
						free(aes_ctx);
						return ARG_ERROR;
					}
				}
				else if(strcmp(argv[i],"-3") == 0 && i < argc-1){
					u32_to_u8(aes_ctx->subdir_id,strtol(argv[i+1],NULL,16),BE);
				}
				else if(strncmp(argv[i],"--SubDirID=",11) == 0){
					u32_to_u8(aes_ctx->subdir_id,strtol((argv[i]+11),NULL,16),BE);
				}
				else if(strcmp(argv[i],"-4") == 0 && i < argc-1){
					u32_to_u8(aes_ctx->image_id,strtol(argv[i+1],NULL,16),BE);				
				}
				else if(strncmp(argv[i],"--ImageID=",10) == 0){
					u32_to_u8(aes_ctx->image_id,strtol((argv[i]+11),NULL,16),BE);
				}
				else if(strcmp(argv[i],"-5") == 0 || strcmp(argv[i],"--IsQuotaDat") == 0){
					aes_ctx->is_quote_dat = 1;
				}
			}
			if(aes_ctx->is_quote_dat == 1){
				memset(aes_ctx->image_id,0,4);
				memset(aes_ctx->subdir_id,0,4);
			}
		}
	
		//Extdata creation
		FILE *outfile = fopen(output,"wb");
		if(outfile == NULL){
			printf("[!] Failed to create '%s'\n",output);
			free(aes_ctx);
			return IO_ERROR;
		}
		FILE *infile = fopen(input,"rb");
		if(infile == NULL){
			printf("[!] Failed to open '%s'\n",input);
			free(aes_ctx);
			free(sourcedata.buffer);
			return IO_ERROR;
		}
		fclose(infile);
		sourcedata.size = GetFileSize_u64(input);
		sourcedata.buffer = malloc(sourcedata.size);
		if(sourcedata.buffer == NULL){
			printf("[!] Failed to allocate memory to generate Extdata\n");
			free(aes_ctx);
			return MEM_ERROR;
		}
		infile = fopen(input,"rb");
		ReadFile_64(sourcedata.buffer,sourcedata.size,0,infile);
		fclose(infile);
		
		u8 result = CreateExtdata(&outdata,&sourcedata,type,activeDIFI,UniqueExtdataID);
		if(result){
			free(aes_ctx);
			free(sourcedata.buffer);
			if(outdata.size > 0){ free(outdata.buffer); }
			return result;
		}
		if(GenMAC){
			if(Verbose) printf("[+] Generating AES MAC\n");
			memcpy(aes_ctx->header,(outdata.buffer+0x100),0x100);
			GenAESMAC(KeyX,KeyY,aes_ctx);
			memcpy(outdata.buffer,aes_ctx->aesmac,16);
		}
		if(Verbose) printf("[+] Writing '%s'\n",output);
		WriteBuffer(outdata.buffer,outdata.size,0,outfile);
		if(outdata.size > 0) free(outdata.buffer);
		if(sourcedata.size > 0)free(sourcedata.buffer);
		free(aes_ctx);
		fclose(outfile);
	}
	return 0;
}