コード例 #1
0
ファイル: ncsd.c プロジェクト: EmmetCooper/ctr_toolkit
int ExtractCCIPartitions(CCI_CONTEXT *ctx)
{
	FILE *cci = fopen(ctx->cci_file.argument,"rb");
	if(cci == NULL)
		return Fail;
		
	chdir(ctx->outfile.argument);
	
	u64 chunk_size = ctx->ncsd_struct->MEDIA_UNIT_SIZE;
	u8 *chunk = malloc(chunk_size);
	for(int i = 0; i < 8; i++){	
		if(ctx->ncsd_struct->partition_data[i].active == True){
			char output[1024];
			memset(&output,0,1024);
			switch(ctx->ncsd_struct->partition_data[i].content_type){
				case CXI : snprintf(output,1024,"%s_%d_APPDATA.cxi",ctx->ncsd_struct->partition_data[i].product_code,i); break;
				case CFA_Manual : snprintf(output,1024,"%s_%d_MANUAL.cfa",ctx->ncsd_struct->partition_data[i].product_code,i); break;
				case CFA_DLPChild : snprintf(output,1024,"%s_%d_DLP.cfa",ctx->ncsd_struct->partition_data[i].product_code,i); break;
				case CFA_Update : snprintf(output,1024,"%s_%d_UPDATEDATA.cfa",ctx->ncsd_struct->partition_data[i].product_code,i); break;
				case CFA_Simple : snprintf(output,1024,"%s_%d.cfa",ctx->ncsd_struct->partition_data[i].product_code,i); break;
				default: snprintf(output,1024,"%s_%d.bin",ctx->ncsd_struct->partition_data[i].product_code,i); break;
			}
			FILE *out = fopen(output,"wb");
			if(out == NULL){
				fclose(cci);
				return Fail;
			}
			printf("[+] Writing '%s'\n",output);
			u64 size = ctx->ncsd_struct->partition_data[i].size;
			u64 chunk_num = (size/chunk_size);
			u64 in_offset = ctx->ncsd_struct->partition_data[i].offset;
			u64 out_offset = 0;
			for(u64 i = 0; i < chunk_num; i++){				
				fseek_64(cci,in_offset,SEEK_SET);
				fseek_64(out,out_offset,SEEK_SET);
				
				fread(chunk,chunk_size,1,cci);
				fwrite(chunk,chunk_size,1,out);
				
				in_offset += chunk_size;
				out_offset += chunk_size;
			}
			fclose(out);
		}
	}
	free(chunk);
	fclose(cci);
	return 0;
}
コード例 #2
0
ファイル: ncsd.c プロジェクト: enler/Project_CTR
void WriteCciDataToOutput(cci_settings *set)
{
	// NCSD Header
	WriteBuffer(set->headers.ccihdr.buffer, set->headers.ccihdr.size, 0, set->out);
	// Card Info Header
	WriteBuffer(set->headers.cardinfohdr.buffer, set->headers.cardinfohdr.size, set->headers.ccihdr.size, set->out);
	
	// Dummy data between header and first NCCH
	u64 len = set->content.cOffset[0] - (set->headers.ccihdr.size + set->headers.cardinfohdr.size);
	u8 *dummy_data = malloc(len);
	if(set->headers.cardinfohdr.size > sizeof(cardinfo_hdr)) // additional debug header data exists
		memset(dummy_data, 0x00, len);
	else // normal production cci image
		memset(dummy_data, 0xff, len);
	WriteBuffer(dummy_data, len, (set->headers.ccihdr.size + set->headers.cardinfohdr.size),set->out);	
	free(dummy_data);
	
	// NCCH Partitions
	u8 *ncch;
	for(int i = 0; i < CCI_MAX_CONTENT; i++){
		if(set->content.active[i]){
			ncch = set->content.data + set->content.dOffset[i];
			WriteBuffer(ncch, set->content.dSize[i], set->content.cOffset[i], set->out);
		}
	}	
	
	// Cci Padding
	if(set->options.padCci){
		fseek_64(set->out,set->romInfo.usedSize);

		// Determining Size of Padding
		u64 len = set->romInfo.mediaSize - set->romInfo.usedSize;
		
		// Create Padding chunk
		u8 *pad = malloc(set->romInfo.blockSize);
		memset(pad,0xff,set->romInfo.blockSize);
		
		// Writing Dummy Bytes to file
		for(u64 i = 0; i < len; i += set->romInfo.blockSize)
			fwrite(pad,set->romInfo.blockSize,1,set->out);
			
		free(pad);
	}
	
	return;
}
コード例 #3
0
ファイル: ncsd.c プロジェクト: EmmetCooper/ctr_toolkit
int RestoreCCI(CCI_CONTEXT *ctx)
{
	printf("[+] Restoring CCI\n");
	if(ctx->ncsd_struct->CCI_FILE_STATUS == IS_S_TRIM){
		printf("[!] Update Data has been removed, CCI cannot be restored\n");
		return Fail;
	}
	if(TruncateFile_u64(ctx->cci_file.argument,ctx->ncsd_struct->MEDIA_SIZE) != 0){
		printf("[!] Failed to Restore CCI\n");
		return Fail;
	}
	FILE *cci = fopen(ctx->cci_file.argument,"rb+");
	fseek_64(cci,ctx->ncsd_struct->CCI_IMAGE_SIZE,SEEK_SET);
	WriteDummyBytes(cci,0xff,(ctx->ncsd_struct->MEDIA_SIZE - ctx->ncsd_struct->CCI_IMAGE_SIZE));
	fclose(cci);
	return 0;
}
コード例 #4
0
ファイル: utils.c プロジェクト: EmmetCooper/ctr_toolkit
void ReadFile_64(void *outbuff, u64 size, u64 offset, FILE *file)
{
	fseek_64(file,offset,SEEK_SET);
	fread(outbuff,size,1,file);
}
コード例 #5
0
ファイル: utils.c プロジェクト: EmmetCooper/ctr_toolkit
//IO Related
void WriteBuffer(void *buffer, u64 size, u64 offset, FILE *output)
{
	fseek_64(output,offset,SEEK_SET);
	fwrite(buffer,size,1,output);
} 
コード例 #6
0
ファイル: ncsd.c プロジェクト: EmmetCooper/ctr_toolkit
int GetNCSDData(CCI_CONTEXT *ctx)
{
	// Opening CCI
	FILE *cci = fopen(ctx->cci_file.argument,"rb");
	if(ctx->ncsd_struct == NULL)
		return Fail;
	memset(ctx->ncsd_struct,0x0,sizeof(NCSD_STRUCT));
	
	// Getting File Size of CCI File
	ctx->ncsd_struct->CCI_FILE_SIZE = GetFileSize_u64(ctx->cci_file.argument);

	NCSD_HEADER header;
	CARD_INFO_HEADER card_info;
	DEV_CARD_INFO_HEADER dev_card_info;
	
	// Reading CCI Header Sections
	fseek(cci,0x0,SEEK_SET);
	fread(&ctx->ncsd_struct->signature,0x100,1,cci);
	fseek(cci,0x100,SEEK_SET);
	fread(&header,sizeof(NCSD_HEADER),1,cci);
	fseek(cci,0x200,SEEK_SET);
	fread(&card_info,sizeof(CARD_INFO_HEADER),1,cci);
	fseek(cci,0x1200,SEEK_SET);
	fread(&dev_card_info,sizeof(DEV_CARD_INFO_HEADER),1,cci);
	
	// Checking CCI Magic
	if(u8_to_u32(header.magic,BE) != NCSD_MAGIC){
		printf("[!] NCSD File is corrupt\n");
		goto fail;
	}
	
	// Checking Media Type to see if suitable for CCI
	if(header.partition_flags[MEDIA_TYPE_INDEX] != CARD1 && header.partition_flags[MEDIA_TYPE_INDEX] != CARD2){
		printf("[!] NCSD File is not CCI\n");
		goto fail;
	}	
	
	// Determining Media Unit Size
	ctx->ncsd_struct->MEDIA_UNIT_SIZE = 0x200*pow(2,header.partition_flags[MEDIA_UNIT_SIZE]);
	
	// Media Size
	ctx->ncsd_struct->MEDIA_SIZE = u8_to_u32(header.media_size,LE)*(ctx->ncsd_struct->MEDIA_UNIT_SIZE);
	
	// Get Writable Address
	ctx->ncsd_struct->WRITABLE_ADDRESS = u8_to_u32(card_info.writable_address,LE)*(ctx->ncsd_struct->MEDIA_UNIT_SIZE);
	ctx->ncsd_struct->CARD2_MAX_SAVEDATA_SIZE = ctx->ncsd_struct->MEDIA_SIZE - ctx->ncsd_struct->WRITABLE_ADDRESS;
	// Getting CCI Image Size by summing total size of NCSD Partitions
	u32 tmp = u8_to_u32(header.offsetsize_table[0].offset,LE);
	for(int i = 0; i < 8; i++){
		tmp += u8_to_u32(header.offsetsize_table[i].size,LE);
		if (i == 6) ctx->ncsd_struct->CCI_S_TRIM_SIZE = tmp*ctx->ncsd_struct->MEDIA_UNIT_SIZE; // The Update Partition is always in Partition 7, so this size doesn't include Partition 7
	}
	ctx->ncsd_struct->CCI_IMAGE_SIZE = tmp*ctx->ncsd_struct->MEDIA_UNIT_SIZE;
	
	// Comparing CCI File Size, with calculated size
	ctx->ncsd_struct->CCI_FILE_STATUS = 0;
	if(ctx->ncsd_struct->CCI_FILE_SIZE == ctx->ncsd_struct->MEDIA_SIZE) ctx->ncsd_struct->CCI_FILE_STATUS = IS_FULL;
	else if(ctx->ncsd_struct->CCI_FILE_SIZE == ctx->ncsd_struct->CCI_IMAGE_SIZE) ctx->ncsd_struct->CCI_FILE_STATUS = IS_TRIM;
	else if(ctx->ncsd_struct->CCI_FILE_SIZE == ctx->ncsd_struct->CCI_S_TRIM_SIZE) ctx->ncsd_struct->CCI_FILE_STATUS = IS_S_TRIM;
	else {
		/*
		printf("CCI_FILE_SIZE = 0x%llx\n",ctx->ncsd_struct->CCI_FILE_SIZE);
		printf("MEDIA_SIZE = 0x%llx\n",ctx->ncsd_struct->MEDIA_SIZE);
		printf("CCI_IMAGE_SIZE = 0x%llx\n",ctx->ncsd_struct->CCI_IMAGE_SIZE);
		printf("CCI_S_TRIM_SIZE = 0x%llx\n",ctx->ncsd_struct->CCI_S_TRIM_SIZE);
		*/
		ctx->ncsd_struct->CCI_FILE_STATUS = IS_MALFORMED;
		goto fail;
	}
	
	// Storing Partition Offsets
	ctx->ncsd_struct->partition_count = 0;
	for(int i = 0; i < 8; i++){
		ctx->ncsd_struct->partition_data[i].offset = u8_to_u32(header.offsetsize_table[i].offset,LE)*ctx->ncsd_struct->MEDIA_UNIT_SIZE;
		ctx->ncsd_struct->partition_data[i].size = u8_to_u32(header.offsetsize_table[i].size,LE)*ctx->ncsd_struct->MEDIA_UNIT_SIZE;
		if(ctx->ncsd_struct->partition_data[i].offset != 0 && ctx->ncsd_struct->partition_data[i].size != 0)
			ctx->ncsd_struct->partition_data[i].active = True;
		ctx->ncsd_struct->partition_data[i].title_id = u8_to_u64(header.partition_id_table[i],LE);
		ctx->ncsd_struct->partition_data[i].fs_type = header.partitions_fs_type[i];
		ctx->ncsd_struct->partition_data[i].crypto_type = header.partitions_crypto_type[i];
		
		// Checking to see if partition actually exists
		if(ctx->ncsd_struct->partition_data[i].offset >= ctx->ncsd_struct->CCI_FILE_SIZE){
			ctx->ncsd_struct->partition_data[i].active = False;
			break;
		}
		if(ctx->ncsd_struct->partition_data[i].active) ctx->ncsd_struct->partition_count++;
	}
	
	// Exit if no CXI found
	if(!ctx->ncsd_struct->partition_data[0].active){
		printf("[!] CXI Not Found\n");
		goto fail;
	}
	
	// Getting Data from CXI
	NCCH_HEADER cxi_header;
	fseek_64(cci,(ctx->ncsd_struct->partition_data[0].offset + 0x100),SEEK_SET);
	fread(&cxi_header,sizeof(NCCH_HEADER),1,cci);
	if(u8_to_u32(cxi_header.magic,BE) != NCCH_MAGIC){
		printf("[!] CXI is Corrupt\n");
		goto fail;
	}
	// Must have ExeFS region to be CXI
	if((cxi_header.flags[MEDIA_TYPE_INDEX] & ExeFS) != ExeFS){
		printf("[!] CXI Not Found\n");
		goto fail;
	}
	ctx->ncsd_struct->partition_data[0].content_type = CXI;
	
	// Getting Product Code
	fseek_64(cci,(ctx->ncsd_struct->partition_data[0].offset + 0x150),SEEK_SET);
	fread(ctx->ncsd_struct->partition_data[0].product_code,16,1,cci);
	
	// Checking 'other flag' for crypto settings
	if((cxi_header.flags[OtherFlag] & 1) == 1){
		if((cxi_header.flags[OtherFlag] & 4) == 4) ctx->ncsd_struct->partition_data[0].ncch_crypto_key = no_crypto;	
		else if ((cxi_header.program_id[4] && 0x10) == 0x10) ctx->ncsd_struct->partition_data[0].ncch_crypto_key = fixed_system;
		else ctx->ncsd_struct->partition_data[0].ncch_crypto_key = fixed_zeros;
	}
	else if(!cxi_header.flags[OtherFlag]){
		ctx->ncsd_struct->partition_data[0].ncch_crypto_key = secure_key;
		if(cxi_header.flags[SecureCryptoType2Flag]) ctx->ncsd_struct->partition_data[0].ncch_crypto_key = secure_key2;
	}
	
	// Getting SDK Version
	u32 CXI_Media_Unit_Size = 0x200*pow(2,cxi_header.flags[MEDIA_UNIT_SIZE]);
	u64 plain_region_offset = ctx->ncsd_struct->partition_data[0].offset + u8_to_u32(cxi_header.plain_region_offset,LE)*CXI_Media_Unit_Size;
	u64 plain_region_size = u8_to_u32(cxi_header.plain_region_size,LE)*CXI_Media_Unit_Size;
	int result = GetSDKVersion(cci,plain_region_offset,plain_region_size,ctx->ncsd_struct);
	// If that failed, attempt to guess SDK version
	if(result){
		strcpy(ctx->ncsd_struct->SDK_PATCH,"Release");
		memset(&ctx->ncsd_struct->SDK_VER,0,3);
		ctx->ncsd_struct->SDK_VER[0] = 1;
		if(header.partition_flags[MEDIA_CARD_DEVICE_OLD]) ctx->ncsd_struct->SDK_VER[0] = 2;
		if(header.partition_flags[MEDIA_CARD_DEVICE]) ctx->ncsd_struct->SDK_VER[0] = 3;
		if(u8_to_u32(cxi_header.logo_region_offset,LE) || u8_to_u32(cxi_header.logo_region_size,LE)) ctx->ncsd_struct->SDK_VER[0] = 5;
		if(cxi_header.flags[SecureCryptoType2Flag])  ctx->ncsd_struct->SDK_VER[0] = 6;
	}
	
	
	// Getting Data from remaining CFA partitions	
	for(int i = 1; i < 8; i++){
		u8 magic[4];
		fseek_64(cci,(ctx->ncsd_struct->partition_data[i].offset + 0x100),SEEK_SET);
		fread(&magic,4,1,cci);
		if(u8_to_u32(magic,BE) == NCCH_MAGIC){
			u8 flags[8];
			u8 ProgramID[8];
			fseek_64(cci,(ctx->ncsd_struct->partition_data[i].offset + 0x188),SEEK_SET);
			fread(&flags,8,1,cci);
			fseek_64(cci,(ctx->ncsd_struct->partition_data[i].offset + 0x118),SEEK_SET);
			fread(&ProgramID,8,1,cci);
			if( (flags[NCCH_Type] & ExeFS) != ExeFS && (flags[NCCH_Type] & RomFS) == RomFS ){
				if((flags[NCCH_Type] & Manual) == Manual && (flags[NCCH_Type] & SystemUpdate) != SystemUpdate)
					ctx->ncsd_struct->partition_data[i].content_type = CFA_Manual;
				else if((flags[NCCH_Type] & Child) == Child)
					ctx->ncsd_struct->partition_data[i].content_type = CFA_DLPChild;
				else if((flags[NCCH_Type] & SystemUpdate) == SystemUpdate && (flags[NCCH_Type] & Manual) != Manual)
					ctx->ncsd_struct->partition_data[i].content_type = CFA_Update;
				else
					ctx->ncsd_struct->partition_data[i].content_type = CFA_Simple;
			}
			else if((flags[NCCH_Type] & ExeFS) == ExeFS)
				ctx->ncsd_struct->partition_data[i].content_type = CXI;
			else
				ctx->ncsd_struct->partition_data[i].content_type = _unknown;


			// Checking 'other flag' for crypto settings
			if((flags[OtherFlag] & 1) == 1){
				if((flags[OtherFlag] & 4) == 4) ctx->ncsd_struct->partition_data[i].ncch_crypto_key = no_crypto;	
				else if ((ProgramID[4] && 0x10) == 0x10) ctx->ncsd_struct->partition_data[i].ncch_crypto_key = fixed_system;
				else ctx->ncsd_struct->partition_data[i].ncch_crypto_key = fixed_zeros;
			}
			else if(!flags[OtherFlag]){
				ctx->ncsd_struct->partition_data[i].ncch_crypto_key = secure_key;
				if(flags[SecureCryptoType2Flag]) ctx->ncsd_struct->partition_data[i].ncch_crypto_key = secure_key2;
			}

			fseek_64(cci,(ctx->ncsd_struct->partition_data[i].offset + 0x150),SEEK_SET);
			fread(ctx->ncsd_struct->partition_data[i].product_code,16,1,cci);
		}
		else
			ctx->ncsd_struct->partition_data[i].content_type = _unknown;
	} 
		
	if(ctx->flags[info])
		PrintNCSDHeaderData(ctx->ncsd_struct,&header,&card_info,&dev_card_info);
	if(ctx->flags[part_info])
		PrintCCIPartitionData(ctx->ncsd_struct,&header,&card_info,&dev_card_info);
	fclose(cci);
	return 0;
fail:
	fclose(cci);
	return Fail;

}
コード例 #7
0
ファイル: ncsd.c プロジェクト: EmmetCooper/ctr_toolkit
int GetSDKVersion(FILE *cxi, u64 plain_region_offset, u64 plain_region_size, NCSD_STRUCT *ctx)
{
	// Counting Strings in Plain Region
	int string_count = 0;
	fseek_64(cxi,plain_region_offset,SEEK_SET);
	while (ftell(cxi) <= (u32)(plain_region_offset+plain_region_size)){
		if(fgetc(cxi) == '[') string_count++;
	}
	
	// Storing Plain Region Strings
	fseek_64(cxi,plain_region_offset,SEEK_SET);
	char tmp = '\0';
	int j = 0;
	char MiddleWareString[string_count][100];
	memset(&MiddleWareString,0,100*string_count*sizeof(char));
	for(int i = 0; i < string_count; i++){
		while(tmp != '[') tmp = fgetc(cxi);
		tmp = fgetc(cxi);
		while(tmp != ']') {
			MiddleWareString[i][j] = tmp;
			tmp = fgetc(cxi);
			j++;
		}
		MiddleWareString[i][j] = '\0';
		j = 0;
	}
	//printf("Total MDW Strings: %d\n",string_count);
	
	// Checking Plain Region Strings
	int found_sdk_ver = 0;
	char SDK_VER[3][4];
	char FW_VER[3][4];
	for(int i = 0; i < string_count; i++){
		//printf(" %s\n",MiddleWareString[i]);
		if(strncmp("SDK+NINTENDO:DEBUG",MiddleWareString[i],18) == 0) ctx->BUILD_TYPE = 1;
		else if(strncmp("SDK+NINTENDO:CTR_SDK-",MiddleWareString[i],21) == 0 && !found_sdk_ver){
			found_sdk_ver = true;
			int set = 0;
			memset(&SDK_VER,0,4*3*sizeof(char));
			int len = strlen(MiddleWareString[i]);
			for(int k = 21, ver_str = 0; k < len; k++){
				//printf(" %c\n",MiddleWareString[i][k]); 
				if(MiddleWareString[i][k] == '_'){
					if(set < 3){
						SDK_VER[set][ver_str] = '\0';
					}
					else{
						ctx->SDK_PATCH[ver_str] = '\0';
					}
					ver_str = 0;
					set++;
					k++;
				}
				if(set < 3)
					SDK_VER[set][ver_str] = MiddleWareString[i][k];
				else
					ctx->SDK_PATCH[ver_str] = MiddleWareString[i][k];
				
				ver_str++;
			}
		}
		else if(strncmp("SDK+NINTENDO:Firmware-",MiddleWareString[i],22) == 0){
			int set = 0;
			memset(&FW_VER,0,4*3*sizeof(char));
			int len = strlen(MiddleWareString[i]);
			for(int k = 22, ver_str = 0; k < len; k++){
				//printf(" %c\n",MiddleWareString[i][k]); 
				if(MiddleWareString[i][k] == '_'){
					FW_VER[set][ver_str] = '\0';
					ver_str = 0;
					set++;
					k++;
				}
				FW_VER[set][ver_str] = MiddleWareString[i][k];
				ver_str++;
			}
		}
	}
	if(!found_sdk_ver) return 1;
	
	if(strcmp(ctx->SDK_PATCH,"none") == 0) strcpy(ctx->SDK_PATCH,"Release");
	
	for(int i = 0; i < 3; i++){
		ctx->SDK_VER[i] = strtol(SDK_VER[i],NULL,10);
	}
	for(int i = 0; i < 3; i++){
		ctx->FW_VER[i] = strtol(FW_VER[i],NULL,10);
	}
	
	return 0;
}
コード例 #8
0
ファイル: ncsd.c プロジェクト: EmmetCooper/ctr_toolkit
int GetNCSDData(USER_CONTEXT *ctx, NCSD_STRUCT *ncsd_struct, FILE *ncsd)
{
	if(ncsd_struct == NULL)
		return Fail;
	memset(ncsd_struct,0x0,sizeof(NCSD_STRUCT));
	
	NCSD_HEADER header;
	CARD_INFO_HEADER card_info;
	DEV_CARD_INFO_HEADER dev_card_info;
	
	fseek(ncsd,0x0,SEEK_SET);
	fread(&ncsd_struct->signature,0x100,1,ncsd);
	fseek(ncsd,0x100,SEEK_SET);
	fread(&header,sizeof(NCSD_HEADER),1,ncsd);
	fseek(ncsd,0x200,SEEK_SET);
	fread(&card_info,sizeof(CARD_INFO_HEADER),1,ncsd);
	fseek(ncsd,0x1200,SEEK_SET);
	fread(&dev_card_info,sizeof(DEV_CARD_INFO_HEADER),1,ncsd);
	
	ctr_sha(&header,sizeof(NCSD_HEADER),ncsd_struct->ncsd_header_hash,CTR_SHA_256);
	
	if(u8_to_u32(header.magic,BE) != NCSD_MAGIC){
		printf("[!] ROM is Corrupt\n");
		return Fail;
	}
	
	ncsd_struct->sig_valid = ctr_rsa(ncsd_struct->ncsd_header_hash,ncsd_struct->signature,ctx->keys.NcsdCfa.n,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY);
	
	u32 media_size = ((header.partition_flags[6] + 1)*0x200);
	
	ncsd_struct->rom_size = u8_to_u32(header.rom_size,LE)*media_size;
	ncsd_struct->used_rom_size = 0;
	if(ncsd_struct->used_rom_size == 0){
		u32 tmp = u8_to_u32(header.offsetsize_table[0].offset,LE);
		for(int i = 0; i < 8; i++){
			tmp += u8_to_u32(header.offsetsize_table[i].size,LE);
		}
		ncsd_struct->used_rom_size = tmp*media_size;
	}
		
	
	for(int i = 0; i < 8; i++){
		ncsd_struct->partition_data[i].offset = u8_to_u32(header.offsetsize_table[i].offset,LE)*media_size;
		ncsd_struct->partition_data[i].size = u8_to_u32(header.offsetsize_table[i].size,LE)*media_size;
		if(ncsd_struct->partition_data[i].offset != 0 && ncsd_struct->partition_data[i].size != 0)
			ncsd_struct->partition_data[i].active = True;
		ncsd_struct->partition_data[i].title_id = u8_to_u64(header.partition_id_table[i],LE);
		ncsd_struct->partition_data[i].fs_type = header.partitions_fs_type[i];
		ncsd_struct->partition_data[i].crypto_type = header.partitions_crypto_type[i];
		
		u8 magic[4];
		fseek_64(ncsd,(ncsd_struct->partition_data[i].offset + 0x100),SEEK_SET);
		fread(&magic,4,1,ncsd);
		if(u8_to_u32(magic,BE) == NCCH_MAGIC){
			u8 flags[8];
			u8 flag_bool[8];
			fseek_64(ncsd,(ncsd_struct->partition_data[i].offset + 0x188),SEEK_SET);
			fread(&flags,8,1,ncsd);
			resolve_flag(flags[5],flag_bool);
			if(flag_bool[1] == False && flag_bool[0] == True){
				if(flag_bool[2] == False && flag_bool[3] == True)
					ncsd_struct->partition_data[i].content_type = CFA_Manual;
				else if(flag_bool[2] == True && flag_bool[3] == True)
					ncsd_struct->partition_data[i].content_type = CFA_DLPChild;
				else if(flag_bool[2] == True && flag_bool[3] == False)
					ncsd_struct->partition_data[i].content_type = CFA_Update;
				else
					ncsd_struct->partition_data[i].content_type = _unknown;
			}
			else if(flag_bool[1] == True)
				ncsd_struct->partition_data[i].content_type = CXI;
			else
				ncsd_struct->partition_data[i].content_type = _unknown;
		}
		else
			ncsd_struct->partition_data[i].content_type = _unknown;
	}
	
	if(u8_to_u64(card_info.cver_title_id,LE) == 0){
		u8 stock_title_key[0x10] = {0x6E, 0xC7, 0x5F, 0xB2, 0xE2, 0xB4, 0x87, 0x46, 0x1E, 0xDD, 0xCB, 0xB8, 0x97, 0x11, 0x92, 0xBA};
		if(memcmp(dev_card_info.TitleKey,stock_title_key,0x10) == 0)
			ncsd_struct->type = dev_external_SDK;
		else
			ncsd_struct->type = dev_internal_SDK;
	}
	else
		ncsd_struct->type = retail;
	
	/**
	if(ncsd_struct->type != retail){
		u8 iv[16];
		u8 key[16];
		memset(&iv,0x0,16);
		memset(&key,0x0,16);
		//iv[0] = header.partition_flags[7];
		//memcpy(iv+11,header.partition_flags,5);
		u8 tmp[16] = {0xB2, 0x57, 0xA7, 0xC0, 0x24, 0xC8, 0xC1, 0xB0, 0x75, 0x91, 0xC4, 0xC5, 0x1D, 0x96, 0x67, 0x4F};
		
		memcpy(iv,tmp,16);
		memcpy(key,common_dpki_aesKey,16);
		
		ctr_aes_context aes;
		memset(&aes,0x0,sizeof(ctr_aes_context));
		
		memdump(stdout,"ENC Title Key:   ",dev_card_info.TitleKey,0x10);
		
		ctr_init_aes_cbc(&aes,key,iv,DEC);
		ctr_aes_cbc(&aes,dev_card_info.TitleKey,dev_card_info.TitleKey,0x10,DEC);
		
		memdump(stdout,"DEC Title Key:   ",dev_card_info.TitleKey,0x10);
	}
	**/
	/**
	for(int i = 0; i < 8; i++){
		if(ncsd_struct->partition_data[i].active == True){
			ncsd_struct->partition_data[i].sig_valid = VerifyNCCHSection(ctx,dev_card_info.TitleKey,ncsd_struct->partition_data[i].offset,ncsd);
		}
	}
	**/
	ncsd_struct->valid = True;
	if(ctx->flags[info])
		PrintNCSDData(ncsd_struct,&header,&card_info,&dev_card_info);
	return 0;
}