Modernize MakeROM build system + bug fixes (#120)

* Move files around to new directory structure

* Rework libyaml into a stand-alone dep for makerom.

* Rework libpolarssl to be standalone dependency for makerom.

* Update includes.

* Delete makefile

* Add new makefile for makerom.

* Update MakeROM github actions script.

* Fix again.

* Update MakeROM's makefile

* Tweak makerom build script

* Tweak MakeROM build script.

* Fix typo

* Update MakeROM makefiles.

* Tweak CTRTool build script.

* Tweak build script

* Tweak CTRTool build script.

* Tweak CTRTool build script

* Add libmbedtls to makerom deps

* Partially migrate makerom to libmbedtls

* Break out libblz as an external dependency for makerom.

* Tweak makerom build script.

* Move dependencies to the top level.

* Put everything back.

* misc

* Update makerom documentation.

* Link to ctrtool/makerom readmes from the root readme.

* Update root readme again.

* Migrate makerom to modern mbedtls

* Bump makerom version to 0.18.1

* Change signing errors to be warnings when they fail.

* Add error verbosity to errors when generating CIA files.

* Fix bug in RSA code.

* misc.

* Remove polarssl now migration to mbedtls complete.

* Surface more makerom errors.

* [makerom] Tolerate CCI signing errors as a warning.

* Add missing return.

* Import initial data key_x (prod/dev included)

* [makerom] Fix initial data generation.
This commit is contained in:
Jack
2022-04-17 10:49:05 +08:00
committed by GitHub
parent 8a9f9bda55
commit cc707c160f
290 changed files with 115424 additions and 10431 deletions
+219
View File
@@ -0,0 +1,219 @@
#include "lib.h"
#include "ncch_build.h"
#include "exheader_build.h"
#include "accessdesc.h"
#include "desc/presets.h"
#include "desc/dev_sigdata.h"
const size_t RSF_RSA_DATA_LEN = 344;
const size_t RSF_DESC_DATA_LEN = 684;
int accessdesc_SignWithKey(exheader_settings *exhdrset);
int accessdesc_GetSignFromRsf(exheader_settings *exhdrset);
int accessdesc_GetSignFromPreset(exheader_settings *exhdrset);
const CtrSdkDesc* accessdesc_GetPresetData(keys_struct *keys);
const CtrSdkDescSignData* accessdesc_GetPresetSignData(keys_struct *keys);
const CtrSdkDepList* accessdesc_GetPresetDependencyList(keys_struct *keys);
int set_AccessDesc(exheader_settings *exhdrset)
{
if(exhdrset->useAccessDescPreset == true) // Use AccessDesc Template
return accessdesc_GetSignFromPreset(exhdrset);
else if(exhdrset->rsf->CommonHeaderKey.Found == true) // Keydata exists in RSF
return accessdesc_GetSignFromRsf(exhdrset);
return accessdesc_SignWithKey(exhdrset);
}
int accessdesc_SignWithKey(exheader_settings *exhdrset)
{
/* Set RSA Keys */
memcpy(exhdrset->keys->rsa.cxi.pvt, exhdrset->keys->rsa.cciCfa.pvt, 0x100);
memcpy(exhdrset->keys->rsa.cxi.pub, exhdrset->keys->rsa.cciCfa.pub, 0x100);
memcpy(&exhdrset->acexDesc->ncchRsaPubKey, exhdrset->keys->rsa.cxi.pub, 0x100);
/* Copy Data From ExHeader */
memcpy(&exhdrset->acexDesc->arm11SystemLocalCapabilities, &exhdrset->exHdr->arm11SystemLocalCapabilities, sizeof(exhdr_ARM11SystemLocalCapabilities));
memcpy(&exhdrset->acexDesc->arm11KernelCapabilities, &exhdrset->exHdr->arm11KernelCapabilities, sizeof(exhdr_ARM11KernelCapabilities));
memcpy(&exhdrset->acexDesc->arm9AccessControlInfo, &exhdrset->exHdr->arm9AccessControlInfo, sizeof(exhdr_ARM9AccessControlInfo));
/* Adjust Data */
exhdr_ARM11SystemLocalCapabilities *arm11 = &exhdrset->acexDesc->arm11SystemLocalCapabilities;
arm11->idealProcessor = 1 << arm11->idealProcessor;
arm11->threadPriority /= 2;
/* Sign AccessDesc */
if (Rsa2048Key_CanSign(&exhdrset->keys->rsa.acex) == false)
{
printf("[ACEXDESC WARNING] Failed to sign access descriptor (key was incomplete)\n");
memset(exhdrset->acexDesc->signature, 0xFF, 0x100);
return 0;
}
int rsa_ret = SignAccessDesc(exhdrset->acexDesc, exhdrset->keys);
if (rsa_ret != 0)
{
printf("[ACEXDESC WARNING] Failed to sign access descriptor (mbedtls error = -0x%x)\n", -rsa_ret);
memset(exhdrset->acexDesc->signature, 0xFF, 0x100);
return 0;
}
return 0;
}
int accessdesc_GetSignFromRsf(exheader_settings *exhdrset)
{
/* Yaml Option Sanity Checks */
if(!exhdrset->rsf->CommonHeaderKey.Found){
fprintf(stderr,"[ACEXDESC ERROR] RSF Section \"CommonHeaderKey\" not found\n");
return COMMON_HEADER_KEY_NOT_FOUND;
}
if(!exhdrset->rsf->CommonHeaderKey.D){
ErrorParamNotFound("CommonHeaderKey/D");
return COMMON_HEADER_KEY_NOT_FOUND;
}
if(b64_strlen(exhdrset->rsf->CommonHeaderKey.D) != RSF_RSA_DATA_LEN){
fprintf(stderr,"[ACEXDESC ERROR] \"CommonHeaderKey/D\" has invalid length (%d)\n", (int)b64_strlen(exhdrset->rsf->CommonHeaderKey.D));
return COMMON_HEADER_KEY_NOT_FOUND;
}
if(!exhdrset->rsf->CommonHeaderKey.Modulus){
ErrorParamNotFound("CommonHeaderKey/Modulus");
return COMMON_HEADER_KEY_NOT_FOUND;
}
if(b64_strlen(exhdrset->rsf->CommonHeaderKey.Modulus) != RSF_RSA_DATA_LEN){
fprintf(stderr,"[ACEXDESC ERROR] \"CommonHeaderKey/Modulus\" has invalid length (%d)\n", (int)b64_strlen(exhdrset->rsf->CommonHeaderKey.Modulus));
return COMMON_HEADER_KEY_NOT_FOUND;
}
if(!exhdrset->rsf->CommonHeaderKey.AccCtlDescSign){
ErrorParamNotFound("CommonHeaderKey/Signature");
return COMMON_HEADER_KEY_NOT_FOUND;
}
if(b64_strlen(exhdrset->rsf->CommonHeaderKey.AccCtlDescSign) != RSF_RSA_DATA_LEN){
fprintf(stderr,"[ACEXDESC ERROR] \"CommonHeaderKey/Signature\" has invalid length (%d)\n", (int)b64_strlen(exhdrset->rsf->CommonHeaderKey.AccCtlDescSign));
return COMMON_HEADER_KEY_NOT_FOUND;
}
if(!exhdrset->rsf->CommonHeaderKey.AccCtlDescBin){
ErrorParamNotFound("CommonHeaderKey/Descriptor");
return COMMON_HEADER_KEY_NOT_FOUND;
}
if(b64_strlen(exhdrset->rsf->CommonHeaderKey.AccCtlDescBin) != RSF_DESC_DATA_LEN){
fprintf(stderr,"[ACEXDESC ERROR] \"CommonHeaderKey/Descriptor\" has invalid length (%d)\n", (int)b64_strlen(exhdrset->rsf->CommonHeaderKey.AccCtlDescBin));
return COMMON_HEADER_KEY_NOT_FOUND;
}
/* Set RSA Keys */
int result = 0;
// NCCH Header pubk
result = b64_decode(exhdrset->keys->rsa.cxi.pub,exhdrset->rsf->CommonHeaderKey.Modulus,0x100);
if(result) return result;
// NCCH Header privk
result = b64_decode(exhdrset->keys->rsa.cxi.pvt,exhdrset->rsf->CommonHeaderKey.D,0x100);
if(result) return result;
/* Set AccessDesc */
// Signature
result = b64_decode(exhdrset->acexDesc->signature,exhdrset->rsf->CommonHeaderKey.AccCtlDescSign,0x100);
if(result) return result;
// NCCH Header pubk
memcpy(exhdrset->acexDesc->ncchRsaPubKey,exhdrset->keys->rsa.cxi.pub,0x100);
// Access Control
result = b64_decode((u8*)&exhdrset->acexDesc->arm11SystemLocalCapabilities,exhdrset->rsf->CommonHeaderKey.AccCtlDescBin,0x200);
if(result) return result;
return 0;
}
int accessdesc_GetSignFromPreset(exheader_settings *exhdrset)
{
const CtrSdkDesc *desc = accessdesc_GetPresetData(exhdrset->keys);
const CtrSdkDescSignData *pre_sign = accessdesc_GetPresetSignData(exhdrset->keys);
const CtrSdkDepList *dependency_list = accessdesc_GetPresetDependencyList(exhdrset->keys);
// Error Checking
if (!desc || !dependency_list) {
fprintf(stderr, "[ACEXDESC ERROR] AccessDesc template is unavailable, please configure RSF file\n");
return CANNOT_SIGN_ACCESSDESC;
}
// Setting data in Exheader
// Dependency List
memcpy(exhdrset->exHdr->dependencyList, dependency_list->dependency, 0x180);
// Backing Up Non Preset Data
u8 ProgramID[8];
exhdr_StorageInfo StorageInfoBackup;
exhdr_ARM9AccessControlInfo Arm9Desc;
memcpy(ProgramID, exhdrset->exHdr->arm11SystemLocalCapabilities.programId, 8);
memcpy(&StorageInfoBackup, &exhdrset->exHdr->arm11SystemLocalCapabilities.storageInfo, sizeof(exhdr_StorageInfo));
memcpy(&Arm9Desc, &exhdrset->exHdr->arm9AccessControlInfo, sizeof(exhdr_ARM9AccessControlInfo));
// Setting Preset Data
memcpy(&exhdrset->exHdr->arm11SystemLocalCapabilities, desc->exheader_desc, 0x200);
// Restoring Non Preset Data
memcpy(exhdrset->exHdr->arm11SystemLocalCapabilities.programId, ProgramID, 8);
memcpy(&exhdrset->exHdr->arm11SystemLocalCapabilities.storageInfo, &StorageInfoBackup, sizeof(exhdr_StorageInfo));
memcpy(&exhdrset->exHdr->arm9AccessControlInfo, &Arm9Desc, sizeof(exhdr_ARM9AccessControlInfo));
// Setting AccessDesc Area
// If presign available set static data & ncch hdr sig info
if (pre_sign)
{
memcpy(exhdrset->keys->rsa.cxi.pub, pre_sign->modulus, 0x100);
memcpy(exhdrset->keys->rsa.cxi.pvt, pre_sign->priv_exponent, 0x100);
memcpy(&exhdrset->acexDesc->signature, pre_sign->access_desc_signature, 0x100);
memcpy(&exhdrset->acexDesc->ncchRsaPubKey, pre_sign->modulus, 0x100);
memcpy(&exhdrset->acexDesc->arm11SystemLocalCapabilities, desc->signed_desc, 0x200);
}
// otherwise sign properly
else
{
return accessdesc_SignWithKey(exhdrset);
}
return 0;
}
const CtrSdkDesc* accessdesc_GetPresetData(keys_struct *keys)
{
for (int i = 0; i < sizeof(kDescPresets) / sizeof(CtrSdkDesc); i++) {
if (kDescPresets[i].type == keys->accessDescSign.presetType && kDescPresets[i].fw_minor == keys->accessDescSign.targetFirmware) {
return &kDescPresets[i];
}
}
return NULL;
}
const CtrSdkDescSignData* accessdesc_GetPresetSignData(keys_struct *keys)
{
if (keys->keyset != pki_DEVELOPMENT) {
return NULL;
}
for (int i = 0; i < sizeof(kDevDescSignData) / sizeof(CtrSdkDescSignData); i++) {
if (kDevDescSignData[i].type == keys->accessDescSign.presetType && kDevDescSignData[i].fw_minor == keys->accessDescSign.targetFirmware) {
return &kDevDescSignData[i];
}
}
return NULL;
}
const CtrSdkDepList* accessdesc_GetPresetDependencyList(keys_struct *keys)
{
for (int i = 0; i < sizeof(kExheaderDependencyLists) / sizeof(CtrSdkDepList); i++) {
if (kExheaderDependencyLists[i].fw_minor == keys->accessDescSign.targetFirmware) {
return &kExheaderDependencyLists[i];
}
}
return NULL;
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
int set_AccessDesc(exheader_settings *exhdrset);
+119
View File
@@ -0,0 +1,119 @@
#include "aes_keygen.h"
// 128bit wrap-around math
int32_t wrap_index(int32_t i)
{
return i < 0 ? ((i % 16) + 16) % 16 : (i > 15 ? i % 16 : i);
}
void n128_rrot(const uint8_t *in, uint32_t rot, uint8_t *out)
{
uint32_t bit_shift, byte_shift;
rot = rot % 128;
byte_shift = rot / 8;
bit_shift = rot % 8;
for (int32_t i = 0; i < 16; i++) {
out[i] = (in[wrap_index(i - byte_shift)] >> bit_shift) | (in[wrap_index(i - byte_shift - 1)] << (8 - bit_shift));
}
}
void n128_lrot(const uint8_t *in, uint32_t rot, uint8_t *out)
{
uint32_t bit_shift, byte_shift;
rot = rot % 128;
byte_shift = rot / 8;
bit_shift = rot % 8;
for (int32_t i = 0; i < 16; i++) {
out[i] = (in[wrap_index(i + byte_shift)] << bit_shift) | (in[wrap_index(i + byte_shift + 1)] >> (8 - bit_shift));
}
}
/* out = a + b
*/
void n128_add(const uint8_t *a, const uint8_t *b, uint8_t *out)
{
uint8_t carry = 0;
uint32_t sum = 0;
for (int i = 15; i >= 0; i--) {
sum = a[i] + b[i] + carry;
carry = sum >> 8;
out[i] = sum & 0xff;
}
}
/* out = a - b
*/
void n128_sub(const uint8_t *a, const uint8_t *b, uint8_t *out)
{
uint8_t carry = 0;
uint32_t sum = 0;
for (int i = 15; i >= 0; i--) {
sum = a[i] - (b[i] + carry);
// check to see if anything was borrowed from next byte
if (a[i] < (b[i] + carry)) {
sum += 0x100;
carry = 1;
}
else {
carry = 0;
}
// set value
out[i] = sum & 0xff;
}
}
void n128_xor(const uint8_t *a, const uint8_t *b, uint8_t *out)
{
for (int i = 0; i < 16; i++) {
out[i] = a[i] ^ b[i];
}
}
// keygen algorithm
/*
void n_aes_keygen(const uint8_t *x, uint8_t x_shift, const uint8_t *y, uint8_t y_shift, const uint8_t *keygen_constant, uint8_t *key)
{
// overall algo:
// key = ((x >>> x_shift) ^ (y >>> y_shift)) + keygen_constant
uint8_t x_rot[16], y_rot[16], key_xy[16];
// Rotate x and y
n128_rrot(x, x_shift, x_rot);
n128_rrot(y, y_shift, y_rot);
// XOR rotated x and y
n128_xor(x_rot, y_rot, key_xy);
// Add secret
n128_add(key_xy, keygen_constant, key);
}
*/
void ctr_aes_keygen(const uint8_t *x, const uint8_t *y, uint8_t *key)
{
static const uint8_t KEYGEN_CONST[16] = { 0x1F, 0xF9, 0xE9, 0xAA, 0xC5, 0xFE, 0x04, 0x08, 0x02, 0x45, 0x91, 0xDC, 0x5D, 0x52, 0x76, 0x8A };
// overall algo:
// key = (((x <<< 2) ^ y) + KEYGEN_CONST) >>> 41
uint8_t x_rot[16], key_xy[16], key_xyc[16];
// x_rot = x <<< 2
n128_lrot(x, 2, x_rot);
// key_xy = x_rot ^ y
n128_xor(x_rot, y, key_xy);
// key_xyc = key_xy + KEYGEN_CONST
n128_add(key_xy, KEYGEN_CONST, key_xyc);
n128_rrot(key_xyc, 41, key);
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include <stdint.h>
/*
AES Key generator for the Nintendo 3DS (CTR) Consoles
*/
void ctr_aes_keygen(const uint8_t *x, const uint8_t *y, uint8_t *key);
+286
View File
@@ -0,0 +1,286 @@
#include "lib.h"
#include <mbedtls/ccm.h>
#include "aes_keygen.h"
#include "ncch_read.h"
#include "ncsd_build.h"
#include "cardinfo.h"
void InitCardInfoHdr(cardinfo_hdr **cihdr, devcardinfo_hdr **dcihdr, cci_settings *set);
int SetWriteableAddress(cardinfo_hdr *hdr, cci_settings *set);
int SetCardInfoBitmask(cardinfo_hdr *hdr, cci_settings *set);
int SetCardInfoNotes(cardinfo_hdr *hdr, cci_settings *set);
void SetNcchHeader(cardinfo_hdr *hdr, cci_settings *set);
void SetCardSeedData(cardinfo_hdr *hdr, devcardinfo_hdr *devhdr, cci_settings *set);
int GenCardInfoHdr(cci_settings *set)
{
cardinfo_hdr *cihdr;
devcardinfo_hdr *dcihdr;
InitCardInfoHdr(&cihdr,&dcihdr,set);
if(SetWriteableAddress(cihdr,set))
return GEN_HDR_FAIL;
if(SetCardInfoBitmask(cihdr,set))
return GEN_HDR_FAIL;
if(SetCardInfoNotes(cihdr,set))
return GEN_HDR_FAIL;
SetNcchHeader(cihdr,set);
SetCardSeedData(cihdr,dcihdr,set);
return 0;
}
void InitCardInfoHdr(cardinfo_hdr **cihdr, devcardinfo_hdr **dcihdr, cci_settings *set)
{
set->headers.cardinfohdr.size = sizeof(cardinfo_hdr) + sizeof(devcardinfo_hdr);
set->headers.cardinfohdr.buffer = calloc(1,set->headers.cardinfohdr.size);
*cihdr = (cardinfo_hdr*)set->headers.cardinfohdr.buffer;
*dcihdr = (devcardinfo_hdr*)(set->headers.cardinfohdr.buffer+sizeof(cardinfo_hdr));
clrmem(set->headers.cardinfohdr.buffer, set->headers.cardinfohdr.size);
return;
}
u64 GetCciUnusedSize(u64 mediaSize, u8 cardType)
{
if(cardType == mediatype_CARD1){
switch(mediaSize){
case (u64)MB*128: return (u64)2621440;
case (u64)MB*256: return (u64)5242880;
case (u64)MB*512: return (u64)10485760;
case (u64)GB*1: return (u64)73924608;
case (u64)GB*2: return (u64)147324928;
case (u64)GB*4: return (u64)294649856;
case (u64)GB*8: return (u64)587202560;
default: return 0;
}
}
else if(cardType == mediatype_CARD2){
switch(mediaSize){
case (u64)MB*512: return (u64)37224448;
case (u64)GB*1: return (u64)73924608;
case (u64)GB*2: return (u64)147324928;
case (u64)GB*4: return (u64)294649856;
case (u64)GB*8: return (u64)587202560;
default: return 0;
}
}
return 0;
}
int SetWriteableAddress(cardinfo_hdr *hdr, cci_settings *set)
{
if(set->romInfo.mediaType != mediatype_CARD2){ // Can only be set for Card2 Media
u32_to_u8(hdr->writableAddress,(u32)-1,LE);
return 0;
}
char *str = set->rsf->CardInfo.WritableAddress;
set->romInfo.card2SaveOffset = -1;
if(str){
if(strncmp(str,"0x",2) != 0){
fprintf(stderr,"[CCI ERROR] WritableAddress requires a Hexadecimal value\n");
return INVALID_RSF_OPT;
}
set->romInfo.card2SaveOffset = strtoull(str,NULL,16);
}
else{
if ((set->romInfo.mediaSize / 2) < set->romInfo.saveSize || set->romInfo.saveSize > (u64)(2047*MB)){
u64 saveDataSize = set->romInfo.saveSize / KB;
fprintf(stderr,"[CCI ERROR] Too large SavedataSize %"PRIu64"K\n",saveDataSize);
return SAVE_DATA_TOO_LARGE;
}
if(set->options.closeAlignWR)
set->romInfo.card2SaveOffset = align(set->romInfo.usedSize, set->romInfo.blockSize); // invalid for "real" chips
else{
u64 unusedSize = GetCciUnusedSize(set->romInfo.mediaSize,set->romInfo.mediaType); // Some value related to the physical implementation of gamecards
if(unusedSize > 0)
set->romInfo.card2SaveOffset = set->romInfo.mediaSize - unusedSize - set->romInfo.saveSize; // Nintendo's method for calculating writable region offset
else{
fprintf(stderr,"[CCI WARNING] Nintendo does not support CARD2 for the current MediaSize, aligning save offset after last NCCH\n");
set->romInfo.card2SaveOffset = align(set->romInfo.usedSize, set->romInfo.blockSize); // invalid for "real" chips
}
}
}
u32_to_u8(hdr->writableAddress,(u32)(set->romInfo.card2SaveOffset/set->romInfo.blockSize),LE);
return 0;
}
int SetCardInfoBitmask(cardinfo_hdr *hdr, cci_settings *set)
{
u32 bitmask = 0;
char *str = set->rsf->CardInfo.CardType;
if(!str)
bitmask |= 0 << 5;
else{
if(strcasecmp(str,"s1") == 0)
bitmask |= 0 << 5;
else if(strcasecmp(str,"s2") == 0)
bitmask |= 1 << 5;
else {
fprintf(stderr,"[CCI ERROR] Invalid CardType: %s\n",str);
return INVALID_RSF_OPT;
}
}
str = set->rsf->CardInfo.CryptoType;
if(!str) {
if(set->options.useExternalSdkCardInfo)
bitmask |= (3 << 6);
else
bitmask |= 0;
}
else{
int val = strtol(str,NULL,10);
if(val < 0 || val > 3) {
fprintf(stderr,"[CCI ERROR] Invalid CryptoType: %s\n",str);
return INVALID_RSF_OPT;
}
if(val != 3 && set->keys->keyset == pki_DEVELOPMENT) {
fprintf(stderr,"[CCI WARNING] Card crypto type = '%d', this is not supported for development target.\n",val);
}
if(val == 3 && set->keys->keyset == pki_PRODUCTION) {
fprintf(stderr,"[CCI WARNING] Card crypto type = '%d', this is not supported for production target.\n",val);
}
bitmask |= val << 6;
}
u32_to_u8(hdr->cardInfoBitmask,bitmask,BE);
return 0;
}
int SetCardInfoNotes(cardinfo_hdr *hdr, cci_settings *set)
{
u64_to_u8(hdr->notes.mediaSizeUsed,set->romInfo.usedSize,LE);
u32_to_u8(hdr->notes.unknown,0,LE);
if(set->options.tmdHdr){
u64_to_u8(hdr->notes.cverTitleId,GetTmdTitleId(set->options.tmdHdr),LE);
u16_to_u8(hdr->notes.cverTitleId,GetTmdVersion(set->options.tmdHdr),LE);
}
return 0;
}
void SetNcchHeader(cardinfo_hdr *hdr, cci_settings *set)
{
u8 *ncch;
ncch_hdr *ncchHdr;
ncch = set->content.data + set->content.dOffset[0];
ncchHdr = (ncch_hdr*)ncch;
memcpy(hdr->ncch0Hdr,GetNcchHdrData(ncchHdr),GetNcchHdrDataLen(ncchHdr));
return;
}
void SetCardSeedData(cardinfo_hdr *hdr, devcardinfo_hdr *devhdr, cci_settings *set)
{
u8 *ncch;
ncch_hdr *ncchHdr;
ncch = set->content.data + set->content.dOffset[0];
ncchHdr = (ncch_hdr*)ncch;
/*
if (set->options.useExternalSdkCardInfo) {
// initial data
clrmem(hdr->cardSeedKeyY, 0x10);
memcpy(hdr->cardSeedKeyY, ncchHdr->titleId, 8);
clrmem(hdr->encCardSeed, 0x10);
memcpy(hdr->cardSeedMac, stock_card_seed_mac, 0x10);
clrmem(hdr->cardSeedNonce, 0xC);
// dev card info
memcpy(devhdr->titleKey, stock_title_key, 0x10);
return;
}
*/
// select title_key
u8 title_key[0x10] = {0};
if (set->options.useExternalSdkCardInfo)
{
memcpy(title_key, stock_title_key, 0x10);
}
else
{
rndset(title_key, 0x10);
}
// generate initial data
{
// set the keyY
clrmem(hdr->cardSeedKeyY, 0x10);
memcpy(hdr->cardSeedKeyY, ncchHdr->titleId, 8);
// use crypto type to determine initial data key
uint32_t crypto_type = (u8_to_u32(hdr->cardInfoBitmask, BE) >> 6) & 3;
u8 initial_data_key[0x10] = {0};
if (crypto_type == 3)
{
clrmem(initial_data_key, 0x10);
}
else
{
ctr_aes_keygen(set->keys->aes.initialDataKeyX, hdr->cardSeedKeyY, initial_data_key);
}
// determine nonce
if (set->options.useExternalSdkCardInfo)
{
clrmem(hdr->cardSeedNonce, 0xC);
}
else
{
rndset(hdr->cardSeedNonce, 0xC);
}
// encrypt title key (& generate MAC)
mbedtls_ccm_context ccm_ctx;
mbedtls_ccm_init(&ccm_ctx);
mbedtls_ccm_setkey(&ccm_ctx, MBEDTLS_CIPHER_ID_AES, initial_data_key, 128);
int ccm_ret = mbedtls_ccm_encrypt_and_tag(&ccm_ctx, sizeof(title_key), hdr->cardSeedNonce, sizeof(hdr->cardSeedNonce), NULL, 0, title_key, hdr->encCardSeed, hdr->cardSeedMac, sizeof(hdr->cardSeedMac));
if (ccm_ret != 0)
{
printf("[CARDINFO WARNING] Failed to encrypt initial data (mbedtls error: -0x%04X)\n", -ccm_ret);
}
mbedtls_ccm_free(&ccm_ctx);
}
// generate dev card info header
{
memcpy(devhdr->titleKey, title_key, 0x10);
}
return;
}
void SetDevCardInfo(devcardinfo_hdr *hdr, cci_settings *set)
{
clrmem(hdr,sizeof(devcardinfo_hdr));
if(set->options.useExternalSdkCardInfo)
memcpy(hdr->titleKey,(u8*)stock_title_key,0x10);
else
rndset(hdr->titleKey,0x10);
return;
}
+47
View File
@@ -0,0 +1,47 @@
#pragma once
typedef struct
{
u8 reserved0[0xf8];
u8 mediaSizeUsed[8];
u8 reserved1[0x8];
u8 unknown[0x4];
u8 reserved2[0xc];
u8 cverTitleId[8];
u8 cverTitleVersion[2];
u8 reserved3[0xcd6];
} cardinfo_notes; // reserved[0xDF8];
typedef struct
{
u8 writableAddress[4];
u8 cardInfoBitmask[4];
cardinfo_notes notes;
u8 cardSeedKeyY[0x10];
u8 encCardSeed[0x10];
u8 cardSeedMac[0x10];
u8 cardSeedNonce[0xc];
u8 reserved1[0xc4];
u8 ncch0Hdr[0x100];
} cardinfo_hdr;
typedef struct
{
u8 cardDeviceReserved1[0x200];
u8 titleKey[0x10];
u8 cardDeviceReserved2[0xf0];
} devcardinfo_hdr;
static const u8 stock_card_seed_mac[0x30] =
{
0xAD, 0x88, 0xAC, 0x41, 0xA2, 0xB1, 0x5E, 0x8F, 0x66, 0x9C, 0x97, 0xE5, 0xE1, 0x5E, 0xA3, 0xEB
};
static const u8 stock_title_key[0x10] =
{
0x6E, 0xC7, 0x5F, 0xB2, 0xE2, 0xB4,
0x87, 0x46, 0x1E, 0xDD, 0xCB, 0xB8,
0x97, 0x11, 0x92, 0xBA
};
int GenCardInfoHdr(cci_settings *set);
+113
View File
@@ -0,0 +1,113 @@
#include "lib.h"
#include "certs.h"
// Cert Sizes
void GetCertSigSectionSizes(u32 *sign_size, u32 *sign_padlen, u8 *cert)
{
u32 sig = u8_to_u32(cert,BE);
switch(sig){
case RSA_4096_SHA1 :
*sign_size = 0x200;
*sign_padlen = 0x3C;
break;
case RSA_2048_SHA1 :
*sign_size = 0x100;
*sign_padlen = 0x3C;
break;
case ECC_SHA1 :
*sign_size = 0x3C;
*sign_padlen = 0x40;
break;
case RSA_4096_SHA256 :
*sign_size = 0x200;
*sign_padlen = 0x3C;
break;
case RSA_2048_SHA256 :
*sign_size = 0x100;
*sign_padlen = 0x3C;
break;
case ECC_SHA256 :
*sign_size = 0x3C;
*sign_padlen = 0x40;
break;
default :
*sign_size = 0;
*sign_padlen = 0;
break;
}
return;
}
u32 GetCertSize(u8 *cert)
{
u32 sign_size = 0;
u32 sign_padlen = 0;
GetCertSigSectionSizes(&sign_size,&sign_padlen,cert);
if(!sign_size || !sign_padlen)
return 0;
return sizeof(u32) + sign_size + sign_padlen + sizeof(cert_hdr) + GetCertPubkSectionSize(GetCertPubkType(cert));
}
cert_hdr* GetCertHdr(u8 *cert)
{
u32 sign_size = 0;
u32 sign_padlen = 0;
GetCertSigSectionSizes(&sign_size,&sign_padlen,cert);
if(!sign_size || !sign_padlen) return NULL;
return (cert_hdr*)(cert+4+sign_size+sign_padlen);
}
u32 GetCertPubkSectionSize(pubk_types type)
{
switch(type){
case RSA_4096_PUBK : return sizeof(rsa_4096_pubk_struct);
case RSA_2048_PUBK : return sizeof(rsa_2048_pubk_struct);
case ECC_PUBK : return sizeof(ecc_pubk_struct);
default : return 0;
}
}
// Issuer/Name Functions
u8 *GetCertIssuer(u8 *cert)
{
cert_hdr *hdr = GetCertHdr(cert);
return hdr->issuer;
}
u8 *GetCertName(u8 *cert)
{
cert_hdr *hdr = GetCertHdr(cert);
return hdr->name;
}
void GenCertChildIssuer(u8 *dest, u8 *cert)
{
snprintf((char*)dest,0x40,"%s-%s",GetCertIssuer(cert),GetCertName(cert));
}
// Pubk
pubk_types GetCertPubkType(u8 *cert)
{
cert_hdr *hdr = GetCertHdr(cert);
return (pubk_types)u8_to_u32(hdr->keyType,BE);
}
u8 *GetCertPubk(u8 *cert)
{
if(!GetCertHdr(cert))
return NULL;
return ((u8*)GetCertHdr(cert)) + sizeof(cert_hdr);
}
bool VerifyCert(u8 *cert, u8 *pubk)
{
if(!GetCertHdr(cert))
return false;
u8 *signature = (cert+sizeof(u32));
u8 *data = (u8*)GetCertHdr(cert);
u32 datasize = sizeof(cert_hdr) + GetCertPubkSectionSize(GetCertPubkType(cert));
return RsaSignVerify(data,datasize,signature,pubk,NULL,u8_to_u32(cert,BE),CTR_RSA_VERIFY);
}
+44
View File
@@ -0,0 +1,44 @@
#pragma once
typedef struct
{
u8 issuer[0x40];
u8 keyType[4];
u8 name[0x40];
u8 id[4];
} cert_hdr;
typedef struct
{
u8 modulus[0x200];
u8 pubExponent[4];
u8 padding[0x34];
} rsa_4096_pubk_struct;
typedef struct
{
u8 modulus[0x100];
u8 pubExponent[4];
u8 padding[0x34];
} rsa_2048_pubk_struct;
typedef struct
{
u8 pubK[0x3C];
u8 padding[0x3C];
} ecc_pubk_struct;
// Cert Sizes
u32 GetCertSize(u8 *cert);
u32 GetCertPubkSectionSize(pubk_types type);
// Issuer/Name Functions
u8 *GetCertIssuer(u8 *cert);
u8 *GetCertName(u8 *cert);
void GenCertChildIssuer(u8 *dest, u8 *cert);
// Pubk
pubk_types GetCertPubkType(u8 *cert);
u8 *GetCertPubk(u8 *cert);
bool VerifyCert(u8 *cert, u8 *pubk);
+807
View File
@@ -0,0 +1,807 @@
#include "lib.h"
#include "srl.h"
#include "ncsd_read.h"
#include "ncch_read.h"
#include "exheader_read.h"
#include "exefs_read.h"
#include "cia_build.h"
#include "cia_read.h"
#include "tik_build.h"
#include "tmd_build.h"
#include "titleid.h"
#include "certs.h"
const int CIA_ALIGN_SIZE = 0x40;
const int CIA_CONTENT_ALIGN = 0x10;
// Private Prototypes
void FreeCiaSettings(cia_settings *set);
int GetCiaSettings(cia_settings *ciaset, user_settings *usrset);
int GetSettingsFromUsrset(cia_settings *ciaset, user_settings *usrset);
int GetSettingsFromNcch0(cia_settings *ciaset, u32 ncch0_offset);
int GetTmdDataFromNcch(cia_settings *ciaset, u8 *ncch, ncch_info *ncch_ctx, u8 *key);
int GetMetaRegion(cia_settings *ciaset, u8 *ncch, ncch_info *ncch_ctx, u8 *key);
int GetContentFilePtrs(cia_settings *ciaset, user_settings *usrset);
int ImportNcchContent(cia_settings *ciaset);
int GetSettingsFromSrl(cia_settings *ciaset);
int GetSettingsFromCci(cia_settings *ciaset);
u16 SetupVersion(u16 major, u16 minor, u16 micro);
void GetContentHashes(cia_settings *ciaset);
void EncryptContent(cia_settings *ciaset);
int BuildCiaCertChain(cia_settings *ciaset);
int BuildCiaHdr(cia_settings *ciaset);
int WriteCiaToFile(cia_settings *ciaset);
int build_CIA(user_settings *usrset)
{
int result = 0;
// Init Settings
cia_settings *ciaset = calloc(1,sizeof(cia_settings));
if(!ciaset) {
fprintf(stderr,"[CIA ERROR] Not enough memory\n");
return MEM_ERROR;
}
// Get Settings
result = GetCiaSettings(ciaset,usrset);
if(result) {
fprintf(stderr,"[CIA ERROR] Failed to initialize context.\n");
goto finish;
}
// Create Output File
ciaset->out = fopen(usrset->common.outFileName,"wb");
if(!ciaset->out){
fprintf(stderr,"[CIA ERROR] Failed to create \"%s\"\n",usrset->common.outFileName);
result = FAILED_TO_CREATE_OUTFILE;
goto finish;
}
// Create CIA Sections
/* Certificate Chain */
result = BuildCiaCertChain(ciaset);
if(result) {
fprintf(stderr,"[CIA ERROR] Failed to build Certificate Chain\n");
goto finish;
}
/* Ticket */
result = BuildTicket(ciaset);
if(result) {
fprintf(stderr,"[CIA ERROR] Failed to build Ticket\n");
goto finish;
}
/* Title Metadata */
result = BuildTMD(ciaset);
if(result) {
fprintf(stderr,"[CIA ERROR] Failed to build Title Metadata\n");
goto finish;
}
/* CIA Header */
result = BuildCiaHdr(ciaset);
if(result) {
fprintf(stderr,"[CIA ERROR] Failed to build CIA Header\n");
goto finish;
}
/* Write To File */
result = WriteCiaToFile(ciaset);
if(result) {
fprintf(stderr,"[CIA ERROR] Failed to write CIA to file\n");
goto finish;
}
finish:
if(result != FAILED_TO_CREATE_OUTFILE && ciaset->out)
fclose(ciaset->out);
FreeCiaSettings(ciaset);
return result;
}
void FreeCiaSettings(cia_settings *set)
{
if(set->content.filePtrs){
for(u32 i = 1; i < set->content.count; i++){
fclose(set->content.filePtrs[i]);
}
free(set->content.filePtrs);
}
free(set->ciaSections.certChain.buffer);
free(set->ciaSections.tik.buffer);
free(set->ciaSections.tmd.buffer);
free(set->ciaSections.meta.buffer);
free(set->ciaSections.content.buffer);
memset(set,0,sizeof(cia_settings));
free(set);
}
int GetCiaSettings(cia_settings *ciaset, user_settings *usrset)
{
int result = 0;
// Transfering data from usrset
result = GetSettingsFromUsrset(ciaset,usrset);
if(usrset->common.workingFileType == infile_ncch){
if((result = GetSettingsFromNcch0(ciaset,0)) != 0)
return result;
if((result = GetContentFilePtrs(ciaset,usrset)) != 0)
return result;
if((result = ImportNcchContent(ciaset)) != 0)
return result;
}
else if(usrset->common.workingFileType == infile_srl){
if((result = GetSettingsFromSrl(ciaset)) != 0)
return result;
}
else if(usrset->common.workingFileType == infile_ncsd){
if((result = GetSettingsFromCci(ciaset)) != 0)
return result;
}
GetContentHashes(ciaset);
if(ciaset->content.encryptCia)
EncryptContent(ciaset);
return 0;
}
int GetSettingsFromUsrset(cia_settings *ciaset, user_settings *usrset)
{
// General Stuff
ciaset->keys = &usrset->common.keys;
ciaset->rsf = &usrset->common.rsfSet;
ciaset->ciaSections.content.buffer = usrset->common.workingFile.buffer;
ciaset->ciaSections.content.size = usrset->common.workingFile.size;
usrset->common.workingFile.buffer = NULL;
usrset->common.workingFile.size = 0;
ciaset->content.includeUpdateNcch = usrset->cia.includeUpdateNcch;
ciaset->verbose = usrset->common.verbose;
ciaset->tmd.titleType = TYPE_CTR;
ciaset->content.encryptCia = usrset->common.rsfSet.Option.EnableCrypt || usrset->cia.titleKey != NULL;
ciaset->content.IsDlc = usrset->cia.DlcContent;
if(ciaset->keys->aes.commonKey[ciaset->keys->aes.currentCommonKey] == NULL && ciaset->content.encryptCia){
fprintf(stderr,"[CIA WARNING] Common Key could not be loaded, CIA will not be encrypted\n");
ciaset->content.encryptCia = false;
}
ciaset->cert.caCrlVersion = 0;
ciaset->cert.signerCrlVersion = 0;
ciaset->common.useCxiRemasterVersion = !usrset->cia.useFullTitleVer;
for(int i = 0; i < 3; i++){
ciaset->common.titleVersion[i] = usrset->cia.titleVersion[i];
}
// Ticket Data
ciaset->tik.ticketId = 0x0004000000000000 | (u64GetRand() & 0x0000FFFFFFFFFFFF);
ciaset->tik.deviceId = usrset->cia.deviceId;
ciaset->tik.eshopAccId = usrset->cia.eshopAccId;
ciaset->tik.licenceType = lic_Permanent;
ciaset->tik.audit = 0;
if(usrset->cia.randomTitleKey)
rndset(ciaset->common.titleKey,AES_128_KEY_SIZE);
else if(usrset->cia.titleKey){
for (size_t count = 0; count < sizeof(ciaset->common.titleKey)/sizeof(ciaset->common.titleKey[0]); count++) {
sscanf(usrset->cia.titleKey, "%2hhx", &ciaset->common.titleKey[count]);
usrset->cia.titleKey += 2;
}
}
else
clrmem(ciaset->common.titleKey,AES_128_KEY_SIZE);
if(ciaset->verbose)
memdump(stdout,"[CIA] CIA title key: ",ciaset->common.titleKey,AES_128_KEY_SIZE);
ciaset->tik.formatVersion = 1;
GenCertChildIssuer(ciaset->tik.issuer,ciaset->keys->certs.xsCert);
// Tmd Stuff
if(usrset->cia.contentId[0] > MAX_U32)
ciaset->content.id[0] = u32GetRand();
else
ciaset->content.id[0] = usrset->cia.contentId[0];
ciaset->tmd.formatVersion = 1;
ciaset->tmd.accessRights = 0;
GenCertChildIssuer(ciaset->tmd.issuer,ciaset->keys->certs.cpCert);
return 0;
}
int GetSettingsFromNcch0(cia_settings *ciaset, u32 ncch0_offset)
{
/* Sanity Checks */
if(!ciaset->ciaSections.content.buffer)
return CIA_NO_NCCH0;
u8 *ncch0 = (u8*)(ciaset->ciaSections.content.buffer+ncch0_offset);
if(!IsNcch(NULL,ncch0)){
fprintf(stderr,"[CIA ERROR] Content0 is not NCCH\n");
return CIA_INVALID_NCCH0;
}
/* Get Ncch0 Header */
ncch_hdr *hdr = (ncch_hdr*)ncch0;
ciaset->content.IsCfa = IsCfa(hdr);
ciaset->content.offset[0] = 0;
ciaset->content.size[0] = align(GetNcchSize(hdr),0x10);
ciaset->content.totalSize = ciaset->content.size[0];
/* Get Ncch0 Import Context */
ncch_info *info = calloc(1,sizeof(ncch_info));
if(!info){
fprintf(stderr,"[CIA ERROR] Not enough memory\n");
return MEM_ERROR;
}
GetNcchInfo(info,hdr);
/* Verify Ncch0 (Sig&Hash Checks) */
ciaset->content.keyFound = true;
int result = VerifyNcch(ncch0, ciaset->keys, false, ciaset->verbose == false);
if(result == UNABLE_TO_LOAD_NCCH_KEY){
ciaset->content.keyFound = false;
ciaset->common.useCxiRemasterVersion = false;
if(!ciaset->content.IsCfa){
fprintf(stderr,"[CIA WARNING] CXI AES Key could not be loaded\n");
fprintf(stderr," Meta Region, SaveDataSize, Remaster Version cannot be obtained\n");
}
}
else if(result != 0){
fprintf(stderr,"[CIA ERROR] Content 0 Is Corrupt (res = %d)\n",result);
return CIA_INVALID_NCCH0;
}
/* Gen Settings From Ncch0 */
ciaset->common.titleId = u8_to_u64(hdr->titleId,LE);
/* Getting NCCH key */
u8 *ncchkey = NULL;
if(ciaset->content.keyFound && IsNcchEncrypted(hdr)){
SetNcchKeys(ciaset->keys,hdr);
ncchkey = ciaset->keys->aes.ncchKey0;
if(ciaset->verbose){
printf("[CIA] NCCH AES keys:\n");
memdump(stdout," > key0: ",ciaset->keys->aes.ncchKey0,AES_128_KEY_SIZE);
memdump(stdout," > key1: ",ciaset->keys->aes.ncchKey1,AES_128_KEY_SIZE);
}
}
/* Get TMD Data from NCCH */
result = GetTmdDataFromNcch(ciaset,ncch0,info,ncchkey);
if(result) goto finish;
/* Get Meta Region from NCCH */
result = GetMetaRegion(ciaset,ncch0,info,ncchkey);
/* Finish */
finish:
/* Return */
free(info);
return result;
}
int GetTmdDataFromNcch(cia_settings *ciaset, u8 *ncch, ncch_info *ncch_ctx, u8 *key)
{
int result = 0;
extended_hdr *exhdr = NULL;
if(!ciaset->content.IsCfa && ciaset->content.keyFound){
exhdr = malloc(sizeof(extended_hdr));
memcpy(exhdr,ncch+ncch_ctx->exhdrOffset,sizeof(extended_hdr));
if(key != NULL)
CryptNcchRegion((u8*)exhdr,sizeof(extended_hdr),0,ncch_ctx->titleId,key,ncch_exhdr);
}
// If this title is a Patch or a CFA SaveData size cannot be set in TMD
if( IsPatch(GetTidCategory(ciaset->common.titleId)) || ciaset->content.IsCfa )
ciaset->tmd.savedataSize = 0;
// Otherwise read Savedata size from exheader, but only first word of savesize is read
else if(ciaset->content.keyFound)
ciaset->tmd.savedataSize = (u32)(GetSaveDataSize_frm_exhdr(exhdr) & MAX_U32);
// if it's a title which can have save data, but save data size could not be read from exhdr
else if(ciaset->rsf->SystemControlInfo.SaveDataSize){
u64 size = 0;
GetSaveDataSizeFromString(&size,ciaset->rsf->SystemControlInfo.SaveDataSize,"CIA");
ciaset->tmd.savedataSize = (u32)(size & MAX_U32);
}
// the user has neglected to provide any means of determining the savedata size
else
ciaset->tmd.savedataSize = 0;
// Process title version
// If this is a CXI, and we have to pull version major from exheader...
if(!ciaset->content.IsCfa && ciaset->common.useCxiRemasterVersion){
// Setting remaster ver
ciaset->common.titleVersion[VER_MAJOR] = GetRemasterVersion_frm_exhdr(exhdr);
}
// Calculate u16 title version
ciaset->tmd.version = ciaset->tik.version = SetupVersion(ciaset->common.titleVersion[VER_MAJOR],ciaset->common.titleVersion[VER_MINOR],ciaset->common.titleVersion[VER_MICRO]);
free(exhdr);
return result;
}
int GetMetaRegion(cia_settings *ciaset, u8 *ncch, ncch_info *info, u8 *key)
{
extended_hdr *exhdr;
exefs_hdr *exefsHdr;
cia_metadata *hdr;
u32 icon_size, icon_offset;
// Do not proceed if this is a CFA or can't be decrypted
if(ciaset->content.IsCfa || !ciaset->content.keyFound)
return 0;
// Obtain (&decrypt) exheader
exhdr = malloc(sizeof(extended_hdr));
memcpy(exhdr,ncch+info->exhdrOffset,sizeof(extended_hdr));
if(key != NULL)
CryptNcchRegion((u8*)exhdr,sizeof(extended_hdr),0,info->titleId,key,ncch_exhdr);
// Obtain (&decrypt) exefs header
exefsHdr = malloc(sizeof(exefs_hdr));
memcpy(exefsHdr,ncch+info->exefsOffset,sizeof(exefs_hdr));
if(key != NULL)
CryptNcchRegion((u8*)exefsHdr,sizeof(exefs_hdr),0,info->titleId,key,ncch_exefs);
// Only continue if icon exists
if(!DoesExeFsSectionExist("icon",(u8*)exefsHdr))
goto cleanup;
icon_size = GetExeFsSectionSize("icon",(u8*)exefsHdr);
icon_offset = GetExeFsSectionOffset("icon",(u8*)exefsHdr);
// Allocating memory for Meta region
ciaset->ciaSections.meta.size = sizeof(cia_metadata) + icon_size;
ciaset->ciaSections.meta.buffer = calloc(1,ciaset->ciaSections.meta.size);
if(!ciaset->ciaSections.meta.buffer){
fprintf(stderr,"[CIA ERROR] Not enough memory\n");
return MEM_ERROR;
}
// Writing Dependency List & Core Version to Meta region
hdr = (cia_metadata*)ciaset->ciaSections.meta.buffer;
GetDependencyList_frm_exhdr(hdr->dependencyList,exhdr);
GetCoreVersion_frm_exhdr(hdr->coreVersion,exhdr);
// Writing Icon data to Meta region
u8 *iconPos = (ciaset->ciaSections.meta.buffer + sizeof(cia_metadata));
memcpy(iconPos,ncch+info->exefsOffset+icon_offset,icon_size);
if(key != NULL)
CryptNcchRegion(iconPos,icon_size,icon_offset,info->titleId,key,ncch_exefs);
cleanup:
free(exefsHdr);
free(exhdr);
return 0;
}
int GetContentFilePtrs(cia_settings *ciaset, user_settings *usrset)
{
ciaset->content.filePtrs = malloc(sizeof(FILE*)*CIA_MAX_CONTENT);
if(!ciaset->content.filePtrs){
fprintf(stderr,"[CIA ERROR] Not enough memory\n");
return MEM_ERROR;
}
memset(ciaset->content.filePtrs,0,sizeof(FILE*)*CIA_MAX_CONTENT);
int j = 1;
ncch_hdr *hdr = malloc(sizeof(ncch_hdr));
for(int i = 1; i < CIA_MAX_CONTENT; i++){
if(usrset->common.contentPath[i]){
if(!AssertFile(usrset->common.contentPath[i])){
fprintf(stderr,"[CIA ERROR] Failed to open \"%s\"\n",usrset->common.contentPath[i]);
return FAILED_TO_OPEN_FILE;
}
ciaset->content.fileSize[j] = GetFileSize64(usrset->common.contentPath[i]);
ciaset->content.filePtrs[j] = fopen(usrset->common.contentPath[i],"rb");
if(usrset->cia.contentId[i] > MAX_U32)
ciaset->content.id[j] = u32GetRand();
else
ciaset->content.id[j] = (u32)usrset->cia.contentId[i];
ciaset->content.index[j] = (u16)i;
// Get Data from ncch HDR
ReadNcchHdr(hdr,ciaset->content.filePtrs[j]);
// Get Size
u64 calcSize = GetNcchSize(hdr);
if(calcSize != ciaset->content.fileSize[j]){
fprintf(stderr,"[CIA ERROR] \"%s\" is corrupt\n",usrset->common.contentPath[i]);
return FAILED_TO_OPEN_FILE;
}
ciaset->content.size[j] = align(calcSize,CIA_CONTENT_ALIGN);
ciaset->content.offset[j] = ciaset->content.totalSize;
ciaset->content.totalSize += ciaset->content.size[j];
// Finish get next content
j++;
}
}
free(hdr);
ciaset->content.count = j;
// Check Conflicting IDs
for(int i = 0; i < ciaset->content.count; i++){
for(j = i+1; j < ciaset->content.count; j++){
if(ciaset->content.id[j] == ciaset->content.id[i]){
fprintf(stderr,"[CIA ERROR] CIA Content %d and %d, have conflicting IDs\n",ciaset->content.index[j],ciaset->content.index[i]);
return CIA_CONFILCTING_CONTENT_IDS;
}
}
}
return 0;
}
int ImportNcchContent(cia_settings *ciaset)
{
ciaset->ciaSections.content.buffer = realloc(ciaset->ciaSections.content.buffer,ciaset->content.totalSize);
if(!ciaset->ciaSections.content.buffer){
fprintf(stderr,"[CIA ERROR] Not enough memory\n");
return MEM_ERROR;
}
ncch_hdr *ncch0hdr = (ncch_hdr*)ciaset->ciaSections.content.buffer;
for(int i = 1; i < ciaset->content.count; i++){
// Import
u8 *ncchpos = (u8*)(ciaset->ciaSections.content.buffer+ciaset->content.offset[i]);
ReadFile64(ncchpos, ciaset->content.fileSize[i], 0, ciaset->content.filePtrs[i]);
if(ModifyNcchIds(ncchpos, NULL, ncch0hdr->programId, ciaset->keys) != 0)
return -1;
// Set Additional Flags
if(ciaset->content.IsDlc)
ciaset->content.flags[i] |= content_Optional;
//if(unknown condition)
// ciaset->content.flags[i] |= content_Shared;
}
ciaset->ciaSections.content.size = ciaset->content.totalSize;
return 0;
}
int GetSettingsFromSrl(cia_settings *ciaset)
{
srl_hdr *hdr = (srl_hdr*)ciaset->ciaSections.content.buffer;
if(!hdr || ciaset->ciaSections.content.size < sizeof(srl_hdr)) {
fprintf(stderr,"[CIA ERROR] Invalid TWL SRL File\n");
return FAILED_TO_IMPORT_FILE;
}
// Check if TWL SRL File
if(u8_to_u16(&hdr->title_id[6],LE) != 0x0003){
fprintf(stderr,"[CIA ERROR] Invalid TWL SRL File\n");
return FAILED_TO_IMPORT_FILE;
}
// Generate and store Converted TitleID
ciaset->common.titleId = ConvertTwlIdToCtrId(u8_to_u64(hdr->title_id,LE));
// Get TWL Flag
ciaset->tmd.twlFlag = ((hdr->reserved_flags[3] & 6) >> 1);
// Get Remaster Version
u16 version = SetupVersion(hdr->romVersion,ciaset->common.titleVersion[1],0);
ciaset->tik.version = version;
ciaset->tmd.version = version;
// Get SaveDataSize (Public and Private)
ciaset->tmd.savedataSize = u8_to_u32(hdr->pubSaveDataSize,LE);
ciaset->tmd.privSavedataSize = u8_to_u32(hdr->privSaveDataSize,LE);
// Setting CIA Content Settings
ciaset->content.count = 1;
ciaset->content.offset[0] = 0;
ciaset->content.size[0] = ciaset->ciaSections.content.size;
ciaset->content.totalSize = ciaset->ciaSections.content.size;
return 0;
}
int GetSettingsFromCci(cia_settings *ciaset)
{
int result = 0;
if(!IsCci(ciaset->ciaSections.content.buffer)){
fprintf(stderr,"[CIA ERROR] Invalid CCI file\n");
return FAILED_TO_IMPORT_FILE;
}
u32 ncch0_offset = GetPartitionOffset(ciaset->ciaSections.content.buffer,0);
if(!ncch0_offset){
fprintf(stderr,"[CIA ERROR] Invalid CCI file (invalid ncch0)\n");
return FAILED_TO_IMPORT_FILE;
}
result = GetSettingsFromNcch0(ciaset, ncch0_offset);
if(result){
fprintf(stderr,"Import of Ncch 0 failed(%d)\n",result);
return result;
}
int j = 1;
u64 cciContentOffsets[CCI_MAX_CONTENT];
cciContentOffsets[0] = ncch0_offset;
for(int i = 1; i < 8; i++){
if(GetPartitionSize(ciaset->ciaSections.content.buffer,i)){
ncch_hdr *ncchHdr = (ncch_hdr*)GetPartition(ciaset->ciaSections.content.buffer, i);
if(IsUpdateCfa(ncchHdr) && !ciaset->content.includeUpdateNcch)
continue;
cciContentOffsets[j] = GetPartitionOffset(ciaset->ciaSections.content.buffer,i);
// Get Size
ciaset->content.size[j] = GetPartitionSize(ciaset->ciaSections.content.buffer,i);
ciaset->content.offset[j] = ciaset->content.totalSize;
ciaset->content.totalSize += ciaset->content.size[j];
// Get ID
ciaset->content.id[j] = u32GetRand();
// Get Index
ciaset->content.index[j] = i;
// Increment Content Count
j++;
}
}
ciaset->content.count = j;
for(int i = 0; i < ciaset->content.count; i++){ // Re-organising content positions in memory
u8 *cci_pos = (ciaset->ciaSections.content.buffer + cciContentOffsets[i]);
u8 *cia_pos = (ciaset->ciaSections.content.buffer + ciaset->content.offset[i]);
memcpy(cia_pos,cci_pos,ciaset->content.size[i]);
}
ciaset->ciaSections.content.size = ciaset->content.totalSize;
return 0;
}
u16 SetupVersion(u16 major, u16 minor, u16 micro)
{
return (((major << 10) & 0xFC00) | ((minor << 4) & 0x3F0) | (micro & 0xf));
}
void GetContentHashes(cia_settings *ciaset)
{
for (int i = 0; i < ciaset->content.count; i++) {
if (ciaset->verbose)
printf("[CIA] Hashing content %d... ", i);
ShaCalc(ciaset->ciaSections.content.buffer + ciaset->content.offset[i], ciaset->content.size[i], ciaset->content.hash[i], CTR_SHA_256);
if (ciaset->verbose)
printf("Done!\n");
}
}
void EncryptContent(cia_settings *ciaset)
{
for(int i = 0; i < ciaset->content.count; i++){
if (ciaset->verbose)
printf("[CIA] Encrypting content %d... ", i);
ciaset->content.flags[i] |= content_Encrypted;
u8 *content = ciaset->ciaSections.content.buffer+ciaset->content.offset[i];
CryptContent(content, content, ciaset->content.size[i], ciaset->common.titleKey, i, ENC);
if (ciaset->verbose)
printf("Done!\n");
}
}
int BuildCiaCertChain(cia_settings *ciaset)
{
ciaset->ciaSections.certChain.size = GetCertSize(ciaset->keys->certs.caCert) + GetCertSize(ciaset->keys->certs.xsCert) + GetCertSize(ciaset->keys->certs.cpCert);
ciaset->ciaSections.certChain.buffer = malloc(ciaset->ciaSections.certChain.size);
if(!ciaset->ciaSections.certChain.buffer) {
fprintf(stderr,"[CIA ERROR] Not enough memory\n");
return MEM_ERROR;
}
memcpy(ciaset->ciaSections.certChain.buffer,ciaset->keys->certs.caCert,GetCertSize(ciaset->keys->certs.caCert));
memcpy((ciaset->ciaSections.certChain.buffer+GetCertSize(ciaset->keys->certs.caCert)),ciaset->keys->certs.xsCert,GetCertSize(ciaset->keys->certs.xsCert));
memcpy((ciaset->ciaSections.certChain.buffer+GetCertSize(ciaset->keys->certs.caCert)+GetCertSize(ciaset->keys->certs.xsCert)),ciaset->keys->certs.cpCert,GetCertSize(ciaset->keys->certs.cpCert));
return 0;
}
int BuildCiaHdr(cia_settings *ciaset)
{
// Allocating memory for header
ciaset->ciaSections.ciaHdr.size = sizeof(cia_hdr);
ciaset->ciaSections.ciaHdr.buffer = malloc(ciaset->ciaSections.ciaHdr.size);
if(!ciaset->ciaSections.ciaHdr.buffer){
fprintf(stderr,"[CIA ERROR] Not enough memory\n");
return MEM_ERROR;
}
cia_hdr *hdr = (cia_hdr*)ciaset->ciaSections.ciaHdr.buffer;
// Clearing
memset(hdr,0,sizeof(cia_hdr));
// Setting Data
u32_to_u8(hdr->hdrSize,sizeof(cia_hdr),LE);
u16_to_u8(hdr->type,0x0,LE);
u16_to_u8(hdr->version,0x0,LE);
u32_to_u8(hdr->certChainSize,ciaset->ciaSections.certChain.size,LE);
u32_to_u8(hdr->tikSize,ciaset->ciaSections.tik.size,LE);
u32_to_u8(hdr->tmdSize,ciaset->ciaSections.tmd.size,LE);
u32_to_u8(hdr->metaSize,ciaset->ciaSections.meta.size,LE);
u64_to_u8(hdr->contentSize,ciaset->content.totalSize,LE);
// Recording Offsets
ciaset->ciaSections.certChainOffset = align(sizeof(cia_hdr),0x40);
ciaset->ciaSections.tikOffset = align(ciaset->ciaSections.certChainOffset+ciaset->ciaSections.certChain.size,0x40);
ciaset->ciaSections.tmdOffset = align(ciaset->ciaSections.tikOffset+ciaset->ciaSections.tik.size,0x40);
ciaset->ciaSections.contentOffset = align(ciaset->ciaSections.tmdOffset+ciaset->ciaSections.tmd.size,0x40);
ciaset->ciaSections.metaOffset = align(ciaset->ciaSections.contentOffset+ciaset->content.totalSize,0x40);
for(int i = 0; i < ciaset->content.count; i++)
hdr->contentIndex[ciaset->content.index[i]/8] |= 0x80 >> (ciaset->content.index[i] & 7);
return 0;
}
int WriteCiaToFile(cia_settings *ciaset)
{
if (ciaset->verbose) {
printf("[CIA] Writing to file... ");
}
WriteBuffer(ciaset->ciaSections.ciaHdr.buffer,ciaset->ciaSections.ciaHdr.size,0,ciaset->out);
WriteBuffer(ciaset->ciaSections.certChain.buffer,ciaset->ciaSections.certChain.size,ciaset->ciaSections.certChainOffset,ciaset->out);
WriteBuffer(ciaset->ciaSections.tik.buffer,ciaset->ciaSections.tik.size,ciaset->ciaSections.tikOffset,ciaset->out);
WriteBuffer(ciaset->ciaSections.tmd.buffer,ciaset->ciaSections.tmd.size,ciaset->ciaSections.tmdOffset,ciaset->out);
WriteBuffer(ciaset->ciaSections.content.buffer,ciaset->ciaSections.content.size,ciaset->ciaSections.contentOffset,ciaset->out);
WriteBuffer(ciaset->ciaSections.meta.buffer,ciaset->ciaSections.meta.size,ciaset->ciaSections.metaOffset,ciaset->out);
if (ciaset->verbose) {
printf("Done!\n");
}
return 0;
}
int CryptContent(u8 *input, u8 *output, u64 size, u8 *title_key, u16 index, u8 mode)
{
//generating IV
u8 iv[16];
clrmem(&iv,16);
iv[0] = (index >> 8) & 0xff;
iv[1] = index & 0xff;
//Crypting content
AesCbcCrypt(title_key,iv,input,output,size,mode);
return 0;
}
bool IsCia(u8 *cia)
{
if(!cia)
return false;
cia_hdr *hdr = (cia_hdr*)cia;
if(u8_to_u32(hdr->hdrSize,LE) != sizeof(cia_hdr) || u8_to_u16(hdr->type,LE) != 0 || u8_to_u16(hdr->version,LE) != 0)
return false;
if(!GetCiaCertSize(hdr) || !GetCiaTikSize(hdr) || !GetCiaTmdSize(hdr) || !GetCiaContentSize(hdr))
return false;
return true;
}
u64 GetCiaCertOffset(cia_hdr *hdr)
{
u64 hdrSize = u8_to_u32(hdr->hdrSize,LE);
return align(hdrSize,CIA_ALIGN_SIZE);
}
u64 GetCiaCertSize(cia_hdr *hdr)
{
return u8_to_u32(hdr->certChainSize,LE);
}
u64 GetCiaTikOffset(cia_hdr *hdr)
{
u64 certOffset = GetCiaCertOffset(hdr);
u64 certSize = GetCiaCertSize(hdr);
return align(certOffset + certSize,CIA_ALIGN_SIZE);
}
u64 GetCiaTikSize(cia_hdr *hdr)
{
return u8_to_u32(hdr->tikSize,LE);
}
u64 GetCiaTmdOffset(cia_hdr *hdr)
{
u64 tikOffset = GetCiaTikOffset(hdr);
u64 tikSize = GetCiaTikSize(hdr);
return align(tikOffset + tikSize,CIA_ALIGN_SIZE);
}
u64 GetCiaTmdSize(cia_hdr *hdr)
{
return u8_to_u32(hdr->tmdSize,LE);
}
u64 GetCiaContentOffset(cia_hdr *hdr)
{
u64 tmdOffset = GetCiaTmdOffset(hdr);
u64 tmdSize = GetCiaTmdSize(hdr);
return align(tmdOffset + tmdSize,CIA_ALIGN_SIZE);
}
u64 GetCiaContentSize(cia_hdr *hdr)
{
return u8_to_u64(hdr->contentSize,LE);
}
u64 GetCiaMetaOffset(cia_hdr *hdr)
{
u64 contentOffset = GetCiaContentOffset(hdr);
u64 contentSize = GetCiaContentSize(hdr);
return align(contentOffset + contentSize,CIA_ALIGN_SIZE);
}
u64 GetCiaMetaSize(cia_hdr *hdr)
{
return u8_to_u32(hdr->metaSize,LE);
}
u8* GetCiaCert(u8 *cia)
{
return cia + GetCiaCertOffset((cia_hdr*)cia);
}
u8* GetCiaTik(u8 *cia)
{
return cia + GetCiaTikOffset((cia_hdr*)cia);
}
u8* GetCiaTmd(u8 *cia)
{
return cia + GetCiaTmdOffset((cia_hdr*)cia);
}
u8* GetCiaContent(u8 *cia)
{
return cia + GetCiaContentOffset((cia_hdr*)cia);
}
u8* GetCiaMeta(u8 *cia)
{
if(GetCiaMetaSize((cia_hdr*)cia))
return cia + GetCiaMetaOffset((cia_hdr*)cia);
else
return NULL;
}
+26
View File
@@ -0,0 +1,26 @@
#pragma once
// Structs
typedef struct
{
u8 hdrSize[4];
u8 type[2];
u8 version[2];
u8 certChainSize[4];
u8 tikSize[4];
u8 tmdSize[4];
u8 metaSize[4];
u8 contentSize[8];
u8 contentIndex[0x2000];
} cia_hdr;
typedef struct
{
u8 dependencyList[0x30*0x8];
u8 padding0[0x180];
u8 coreVersion[4];
u8 padding1[0xfc];
} cia_metadata;
int CryptContent(u8 *input, u8 *output, u64 size, u8 *title_key, u16 index, u8 mode);
+108
View File
@@ -0,0 +1,108 @@
#pragma once
#include "cia.h"
// Enums
typedef enum
{
CIA_NO_NCCH0 = -1,
CIA_INVALID_NCCH0 = -2,
CIA_CONFILCTING_CONTENT_IDS = -3,
} cia_errors;
typedef struct
{
u8 *inFile;
u64 inFileSize;
FILE *out;
rsf_settings *rsf;
keys_struct *keys;
bool verbose;
struct{
bool useCxiRemasterVersion;
u64 titleId;
u16 titleVersion[3];
u8 titleKey[16];
} common;
struct{
u8 caCrlVersion;
u8 signerCrlVersion;
} cert;
struct{
u8 issuer[0x40];
u8 formatVersion;
u16 version;
u64 ticketId;
u32 deviceId;
u8 licenceType;
u8 audit;
u32 eshopAccId;
} tik;
struct{
u8 issuer[0x40];
u8 formatVersion;
u16 version;
u32 accessRights;
u32 titleType;
u32 savedataSize;
u32 privSavedataSize;
u8 twlFlag;
} tmd;
struct{
bool IsCfa;
bool IsDlc;
bool encryptCia;
bool includeUpdateNcch; // for cci -> cia conversions
bool keyFound;
FILE **filePtrs;
u64 fileSize[CIA_MAX_CONTENT];
/* Misc Records */
u16 count;
u64 offset[CIA_MAX_CONTENT];
u64 totalSize;
/* Content Chunk Records */
u64 size[CIA_MAX_CONTENT];
u16 index[CIA_MAX_CONTENT];
u16 flags[CIA_MAX_CONTENT];
u32 id[CIA_MAX_CONTENT];
u8 hash[CIA_MAX_CONTENT][0x20];
} content;
struct{
buffer_struct ciaHdr;
u32 certChainOffset;
buffer_struct certChain;
u32 tikOffset;
buffer_struct tik;
u32 tmdOffset;
buffer_struct tmd;
u32 metaOffset;
buffer_struct meta;
u64 contentOffset;
buffer_struct content;
} ciaSections;
} cia_settings;
// Public Prototypes
int build_CIA(user_settings *usrset);
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include "cia.h"
// Cia Read Functions
bool IsCia(u8 *cia);
u64 GetCiaCertOffset(cia_hdr *hdr);
u64 GetCiaCertSize(cia_hdr *hdr);
u64 GetCiaTikOffset(cia_hdr *hdr);
u64 GetCiaTikSize(cia_hdr *hdr);
u64 GetCiaTmdOffset(cia_hdr *hdr);
u64 GetCiaTmdSize(cia_hdr *hdr);
u64 GetCiaContentOffset(cia_hdr *hdr);
u64 GetCiaContentSize(cia_hdr *hdr);
u64 GetCiaMetaOffset(cia_hdr *hdr);
u64 GetCiaMetaSize(cia_hdr *hdr);
u8* GetCiaCert(u8 *cia);
u8* GetCiaTik(u8 *cia);
u8* GetCiaTmd(u8 *cia);
u8* GetCiaContent(u8 *cia);
u8* GetCiaMeta(u8 *cia);
+316
View File
@@ -0,0 +1,316 @@
#include "lib.h"
#include "elf.h"
#include "ncch_build.h"
#include "exheader_read.h"
#include "code.h"
#include <blz.h>
const u32 CTR_PAGE_SIZE = 0x1000;
const u32 DEFAULT_STACK_SIZE = 0x4000; // 10KB
typedef struct code_segment
{
u32 address;
u32 memSize;
u32 fileSize;
u32 pageNum;
const u8 *data;
} code_segment;
u32 SizeToPage(u32 memorySize)
{
return align(memorySize, CTR_PAGE_SIZE) / CTR_PAGE_SIZE;
}
u32 PageToSize(u32 pageNum)
{
return pageNum * CTR_PAGE_SIZE;
}
int ImportPlainRegionFromFile(ncch_settings *set)
{
set->sections.plainRegion.size = align(set->componentFilePtrs.plainregionSize, set->options.blockSize);
set->sections.plainRegion.buffer = calloc(set->sections.plainRegion.size, 1);
if (!set->sections.plainRegion.buffer) { fprintf(stderr, "[ELF ERROR] Not enough memory\n"); return MEM_ERROR; }
ReadFile64(set->sections.plainRegion.buffer, set->componentFilePtrs.plainregionSize, 0, set->componentFilePtrs.plainregion);
return 0;
}
int ImportExeFsCodeBinaryFromFile(ncch_settings *set)
{
u32 size = set->componentFilePtrs.codeSize;
u8 *buffer = malloc(size);
if (!buffer) {
fprintf(stderr, "[CODE ERROR] Not enough memory\n");
return MEM_ERROR;
}
ReadFile64(buffer, size, 0, set->componentFilePtrs.code);
set->exefsSections.code.size = set->componentFilePtrs.codeSize;
set->exefsSections.code.buffer = malloc(set->exefsSections.code.size);
if (!set->exefsSections.code.buffer) { fprintf(stderr, "[ELF ERROR] Not enough memory\n"); return MEM_ERROR; }
ReadFile64(set->exefsSections.code.buffer, set->exefsSections.code.size, 0, set->componentFilePtrs.code);
if (set->options.CompressCode) {
if (set->options.verbose)
printf("[CODE] Compressing code... ");
u32 new_len;
set->exefsSections.code.buffer = BLZ_Code(buffer, size, &new_len, BLZ_NORMAL);
set->exefsSections.code.size = new_len;
free(buffer);
if (set->options.verbose)
printf("Done!\n");
}
else {
set->exefsSections.code.size = size;
set->exefsSections.code.buffer = buffer;
}
size = set->componentFilePtrs.exhdrSize;
if (size < sizeof(extended_hdr)) {
fprintf(stderr, "[CODE ERROR] Exheader code info template is too small\n");
return FAILED_TO_IMPORT_FILE;
}
extended_hdr *exhdr = malloc(size);
if (!exhdr) {
fprintf(stderr, "[CODE ERROR] Not enough memory\n");
return MEM_ERROR;
}
ReadFile64(exhdr, size, 0, set->componentFilePtrs.exhdr);
/* Setting code_segment data */
set->codeDetails.textAddress = u8_to_u32(exhdr->codeSetInfo.text.address, LE);
set->codeDetails.textMaxPages = u8_to_u32(exhdr->codeSetInfo.text.numMaxPages, LE);
set->codeDetails.textSize = u8_to_u32(exhdr->codeSetInfo.text.codeSize, LE);
set->codeDetails.roAddress = u8_to_u32(exhdr->codeSetInfo.rodata.address, LE);
set->codeDetails.roMaxPages = u8_to_u32(exhdr->codeSetInfo.rodata.numMaxPages, LE);
set->codeDetails.roSize = u8_to_u32(exhdr->codeSetInfo.rodata.codeSize, LE);
set->codeDetails.rwAddress = u8_to_u32(exhdr->codeSetInfo.data.address, LE);
set->codeDetails.rwMaxPages = u8_to_u32(exhdr->codeSetInfo.data.numMaxPages, LE);
set->codeDetails.rwSize = u8_to_u32(exhdr->codeSetInfo.data.codeSize, LE);
set->codeDetails.bssSize = u8_to_u32(exhdr->codeSetInfo.bssSize, LE);
set->codeDetails.stackSize = u8_to_u32(exhdr->codeSetInfo.stackSize, LE);
free(exhdr);
return 0;
}
int ImportPlainRegionFromElf(elf_context *elf, ncch_settings *set)
{
elf_segment segment = elf_GetSegments(elf)[elf_SegmentNum(elf) - 1];
/* Check last segment
If the last segment is RO segment, this must be an SDK .module_id segment */
if (segment.flags != PF_RODATA) {
/* not a RO segment */
return 0;
}
if (segment.fileSize > 0) {
/* Creating Output Buffer */
set->sections.plainRegion.size = align(segment.fileSize, set->options.blockSize);
set->sections.plainRegion.buffer = calloc(set->sections.plainRegion.size, 1);
if (!set->sections.plainRegion.buffer) { fprintf(stderr, "[CODE ERROR] Not enough memory\n"); return MEM_ERROR; }
/* Copy Plain Region */
memcpy(set->sections.plainRegion.buffer, segment.ptr, segment.fileSize);
}
return 0;
}
void CreateCodeSegmentFromElf(code_segment *out, elf_context *elf, u64 segment_flags)
{
u32 segmentNum = elf_SegmentNum(elf);
const elf_segment *segments = elf_GetSegments(elf);
/* Initialise struct data */
out->address = 0;
out->memSize = 0;
out->pageNum = 0;
out->fileSize = 0;
out->data = NULL;
/* Find segment */
for (u16 i = 0; i < segmentNum; i++) {
/* Skip SDK ELF .module_id segment
The last segment should always be data in valid ELFs,
unless this is an SDK ELF with .module_id segment */
if (i == segmentNum-1 && segments[i].flags == PF_RODATA)
continue;
/* Found segment */
if ((segments[i].flags & ~PF_CTRSDK) == segment_flags && segments[i].type == PT_LOAD) {
out->address = segments[i].vAddr;
out->memSize = segments[i].memSize;
out->fileSize = segments[i].fileSize;
out->pageNum = SizeToPage(out->fileSize);
out->data = segments[i].ptr;
break;
}
}
}
int CreateExeFsCode(elf_context *elf, ncch_settings *set)
{
/* Getting Code Segments */
code_segment text;
code_segment rodata;
code_segment rwdata;
CreateCodeSegmentFromElf(&text, elf, PF_TEXT);
CreateCodeSegmentFromElf(&rodata, elf, PF_RODATA);
CreateCodeSegmentFromElf(&rwdata, elf, PF_DATA);
/* Checking the existence of essential ELF Segments */
if (!text.fileSize) return NOT_FIND_TEXT_SEGMENT;
if (!rwdata.fileSize) return NOT_FIND_DATA_SEGMENT;
/* Calculating BSS size */
set->codeDetails.bssSize = rwdata.memSize - rwdata.fileSize;
/* Allocating Buffer for ExeFs Code */
bool noCodePadding = set->options.noCodePadding;
u32 size;
if (noCodePadding) {
size = text.fileSize + rodata.fileSize + rwdata.fileSize;
}
else {
size = PageToSize(text.pageNum + rodata.pageNum + rwdata.pageNum);
}
u8 *code = calloc(1, size);
/* Writing Code into Buffer */
u8 *textPos = code;
u8 *rodataPos = (textPos + (noCodePadding ? text.fileSize : PageToSize(text.pageNum)));
u8 *rwdataPos = (rodataPos + (noCodePadding ? rodata.fileSize : PageToSize(rodata.pageNum)));
if (text.fileSize) memcpy(textPos, text.data, text.fileSize);
if (rodata.fileSize) memcpy(rodataPos, rodata.data, rodata.fileSize);
if (rwdata.fileSize) memcpy(rwdataPos, rwdata.data, rwdata.fileSize);
/* Compressing if needed */
if (set->options.CompressCode) {
if (set->options.verbose)
printf("[CODE] Compressing code... ");
u32 new_len;
set->exefsSections.code.buffer = BLZ_Code(code, size, &new_len, BLZ_NORMAL);
set->exefsSections.code.size = new_len;
free(code);
if (set->options.verbose)
printf("Done!\n");
}
else {
set->exefsSections.code.size = size;
set->exefsSections.code.buffer = code;
}
/* Setting code_segment data and freeing original buffers */
set->codeDetails.textAddress = text.address;
set->codeDetails.textMaxPages = text.pageNum;
set->codeDetails.textSize = text.fileSize;
set->codeDetails.roAddress = rodata.address;
set->codeDetails.roMaxPages = rodata.pageNum;
set->codeDetails.roSize = rodata.fileSize;
set->codeDetails.rwAddress = rwdata.address;
set->codeDetails.rwMaxPages = rwdata.pageNum;
set->codeDetails.rwSize = rwdata.fileSize;
if (set->rsfSet->SystemControlInfo.StackSize)
set->codeDetails.stackSize = strtoul(set->rsfSet->SystemControlInfo.StackSize, NULL, 0);
else {
set->codeDetails.stackSize = DEFAULT_STACK_SIZE;
fprintf(stderr, "[CODE WARNING] \"SystemControlInfo/StackSize\" not specified, defaulting to 0x%x bytes\n", DEFAULT_STACK_SIZE);
}
/* Return */
return 0;
}
/*
void PrintElfContext(elf_context *elf)
{
printf("[ELF] Program Table Data\n");
printf(" Offset: 0x%x\n", elf->programTableOffset);
printf(" Size: 0x%x\n", elf->programTableEntrySize);
printf(" Count: 0x%x\n", elf->programTableEntryCount);
printf("[ELF] Section Table Data\n");
printf(" Offset: 0x%x\n", elf->sectionTableOffset);
printf(" Size: 0x%x\n", elf->sectionTableEntrySize);
printf(" Count: 0x%x\n", elf->sectionTableEntryCount);
printf(" Label index: 0x%x\n", elf->sectionHeaderNameEntryIndex);
for (int i = 0; i < elf->activeSegments; i++) {
printf(" Segment [%d][%s]\n", i, elf->segments[i].name);
printf(" > Size(Memory): 0x%x\n", elf->segments[i].header->sizeInMemory);
printf(" > Size(File): 0x%x\n", elf->segments[i].header->sizeInFile);
printf(" > Address: 0x%x\n", elf->segments[i].vAddr);
printf(" > Flags: 0x%x\n", elf->segments[i].header->flags);
printf(" > Type: 0x%x\n", elf->segments[i].header->type);
printf(" > Sections: %d\n", elf->segments[i].sectionNum);
for (int j = 0; j < elf->segments[i].sectionNum; j++)
printf(" > Section [%d][%s][0x%x][0x%x]\n", j, elf->segments[i].sections[j].name, elf->segments[i].sections[j].flags, elf->segments[i].sections[j].type);
}
}
*/
int BuildExeFsCode(ncch_settings *set)
{
int result = 0;
if (set->options.IsCfa)
return result;
if (!set->options.IsBuildingCodeSection) { // Import ExeFs Code from file and return
if (set->componentFilePtrs.plainregion) // Import PlainRegion from file
if ((result = ImportPlainRegionFromFile(set))) return result;
return ImportExeFsCodeBinaryFromFile(set);
}
/* Import ELF */
u8 *elfFile = malloc(set->componentFilePtrs.elfSize);
if (!elfFile) {
fprintf(stderr, "[CODE ERROR] Not enough memory\n");
return MEM_ERROR;
}
ReadFile64(elfFile, set->componentFilePtrs.elfSize, 0, set->componentFilePtrs.elf);
/* Create ELF Context */
elf_context elf;
if ((result = elf_Init(&elf, elfFile))) goto finish;
if ((result = ImportPlainRegionFromElf(&elf, set))) goto finish;
if ((result = CreateExeFsCode(&elf, set))) goto finish;
finish:
switch (result) {
case (0) :
break;
case (NOT_ELF_FILE) :
fprintf(stderr, "[CODE ERROR] Not ELF File\n");
break;
case (NOT_CTR_ARM_ELF) :
fprintf(stderr, "[CODE ERROR] Not CTR ARM ELF\n");
break;
case (NON_EXECUTABLE_ELF) :
fprintf(stderr, "[CODE ERROR] Not Executeable ELF\n");
break;
case (NOT_FIND_TEXT_SEGMENT) :
fprintf(stderr, "[CODE ERROR] Failed to retrieve text sections from ELF\n");
break;
case (NOT_FIND_DATA_SEGMENT) :
fprintf(stderr, "[CODE ERROR] Failed to retrieve data sections from ELF\n");
break;
default:
fprintf(stderr, "[CODE ERROR] Failed to process ELF file (%d)\n", result);
}
elf_Free(&elf);
free(elfFile);
return result;
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
int BuildExeFsCode(ncch_settings *ncchset);
+25
View File
@@ -0,0 +1,25 @@
#pragma once
typedef struct
{
u8 magic[4];
u8 reserved0[4];
u8 node0[4];
u8 node1[4];
u8 debugInfoOffset[4]; //s32
u8 debugInfoSize[4]; //s32
u8 reserved1[8];
u8 uniqueIdMask[4];
u8 uniqueIdPattern[4];
u8 reserved2[0x18];
u8 signPublicKey[0x100];
u8 signPublicKeySign[0x100];
u8 sign[0x100];
u8 uniqueId[4];
u8 size[4];
u8 reserved3[8];
u8 hashOffset[4];
u8 numHash[4];
u8 moduleIdOffset[4];
u8 moduleIdSize[4];
} crr_hdr;
+210
View File
@@ -0,0 +1,210 @@
#include "lib.h"
#include "crypto.h"
#include <mbedtls/aes.h>
#include <mbedtls/rsa.h>
#include <mbedtls/md.h>
#include <mbedtls/sha1.h>
#include <mbedtls/sha256.h>
static const u8 RSA_PUB_EXP[0x3] = {0x01,0x00,0x01};
static const int HASH_MAX_LEN = 0x20;
bool VerifySha256(void *data, u64 size, u8 hash[32])
{
u8 calchash[32];
ShaCalc(data, size, calchash, CTR_SHA_256);
return memcmp(hash,calchash,32) == 0;
}
void ShaCalc(void *data, u64 size, u8 *hash, int mode)
{
switch(mode){
case(CTR_SHA_1): mbedtls_sha1((u8*)data, size, hash); break;
case(CTR_SHA_256): mbedtls_sha256((u8*)data, size, hash, 0); break;
}
}
void SetAesCtrOffset(u8 *ctr, u64 offset)
{
u64_to_u8(ctr+8,u8_to_u64(ctr+8,BE)|align(offset,16)/16,BE);
}
void AesCtrCrypt(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset)
{
u8 stream[16];
mbedtls_aes_context aes;
size_t nc_off = 0;
mbedtls_aes_init(&aes);
mbedtls_aes_setkey_enc(&aes, key, 128);
SetAesCtrOffset(ctr,offset);
mbedtls_aes_crypt_ctr(&aes, length, &nc_off, ctr, stream, input, output);
return;
}
void AesCbcCrypt(u8 *key, u8 *iv, u8 *input, u8 *output, u64 length, u8 mode)
{
mbedtls_aes_context aes;
mbedtls_aes_init(&aes);
switch(mode){
case(ENC):
mbedtls_aes_setkey_enc(&aes, key, 128);
mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, length, iv, input, output);
return;
case(DEC):
mbedtls_aes_setkey_dec(&aes, key, 128);
mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, length, iv, input, output);
return;
default:
return;
}
}
bool RsaKeyInit(mbedtls_rsa_context* ctx, const u8 *modulus, const u8 *private_exp, const u8 *public_exp, u8 rsa_type)
{
// Sanity Check
if(!ctx)
return false;
mbedtls_rsa_init( ctx, MBEDTLS_RSA_PKCS_V15, 0 );
u16 n_size = 0;
u16 d_size = 0;
u16 e_size = 0;
switch(rsa_type){
case RSA_2048:
ctx->len = 0x100;
n_size = 0x100;
d_size = 0x100;
e_size = 3;
break;
case RSA_4096:
ctx->len = 0x200;
n_size = 0x200;
d_size = 0x200;
e_size = 3;
break;
default: return false;
}
int ret = mbedtls_rsa_import_raw(ctx, \
modulus ? modulus : NULL, modulus ? n_size : 0, \
NULL, 0, \
NULL, 0, \
private_exp ? private_exp : NULL, private_exp ? d_size : 0, \
public_exp ? public_exp : NULL, public_exp ? e_size : 0);
if (ret != 0)
goto clean;
return true;
clean:
mbedtls_rsa_free(ctx);
return false;
}
u8 GetRsaType(u32 sig_type)
{
switch(sig_type){
case RSA_4096_SHA1:
case RSA_4096_SHA256:
return RSA_4096;
case RSA_2048_SHA1:
case RSA_2048_SHA256:
return RSA_2048;
}
return INVALID_SIG_TYPE;
}
u32 GetSigHashType(u32 sig_type)
{
switch(sig_type){
case RSA_4096_SHA1:
case RSA_2048_SHA1:
case ECC_SHA1:
return CTR_SHA_1;
case RSA_4096_SHA256:
case RSA_2048_SHA256:
case ECC_SHA256:
return CTR_SHA_256;
}
return 0;
}
u32 GetSigHashLen(u32 sig_type)
{
switch(sig_type){
case RSA_4096_SHA1:
case RSA_2048_SHA1:
case ECC_SHA1:
return SHA_1_LEN;
case RSA_4096_SHA256:
case RSA_2048_SHA256:
case ECC_SHA256:
return SHA_256_LEN;
}
return 0;
}
mbedtls_md_type_t getMdWrappedHashType(u32 sig_type)
{
mbedtls_md_type_t md_type = MBEDTLS_MD_NONE;
switch(sig_type){
case RSA_4096_SHA1:
case RSA_2048_SHA1:
case ECC_SHA1:
md_type = MBEDTLS_MD_SHA1;
break;
case RSA_4096_SHA256:
case RSA_2048_SHA256:
case ECC_SHA256:
md_type = MBEDTLS_MD_SHA256;
break;
default:
break;
}
return md_type;
}
bool CalcHashForSign(void *data, u64 len, u8 *hash, u32 sig_type)
{
if(GetSigHashType(sig_type) == 0)
return false;
ShaCalc(data, len, hash, GetSigHashType(sig_type));
return true;
}
int RsaSignVerify(void *data, u64 len, u8 *sign, u8 *mod, u8 *priv_exp, u32 sig_type, u8 rsa_mode)
{
int rsa_result = 0;
mbedtls_rsa_context ctx;
u8 hash[HASH_MAX_LEN];
if(!RsaKeyInit(&ctx, mod, priv_exp, RSA_PUB_EXP, GetRsaType(sig_type)))
return -1;
if(!CalcHashForSign(data, len, hash, sig_type))
return -1;
if(rsa_mode == CTR_RSA_VERIFY)
{
rsa_result = mbedtls_rsa_rsassa_pkcs1_v15_verify(&ctx, NULL, NULL, MBEDTLS_RSA_PUBLIC, getMdWrappedHashType(sig_type), GetSigHashLen(sig_type), hash, sign);
}
else // CTR_RSA_SIGN
{
rsa_result = mbedtls_rsa_rsassa_pkcs1_v15_sign(&ctx, NULL, NULL, MBEDTLS_RSA_PRIVATE, getMdWrappedHashType(sig_type), GetSigHashLen(sig_type), hash, sign);
}
mbedtls_rsa_free(&ctx);
return rsa_result;
}
+69
View File
@@ -0,0 +1,69 @@
#pragma once
typedef enum
{
RSA_4096_SHA1 = 0x00010000,
RSA_2048_SHA1 = 0x00010001,
ECC_SHA1 = 0x00010002,
RSA_4096_SHA256 = 0x00010003,
RSA_2048_SHA256 = 0x00010004,
ECC_SHA256 = 0x00010005
} ctr_sig_types;
typedef enum
{
CTR_RSA_VERIFY,
CTR_RSA_SIGN,
} ctr_rsa_mode;
typedef enum
{
RSA_4096,
RSA_2048,
ECC,
INVALID_SIG_TYPE,
} sig_types;
typedef enum
{
CTR_SHA_1,
CTR_SHA_256,
} ctr_sha_modes;
typedef enum
{
SHA_1_LEN = 0x14,
SHA_256_LEN = 0x20,
} sha_hash_len;
typedef enum
{
RSA_4096_PUBK = 0,
RSA_2048_PUBK,
ECC_PUBK
} pubk_types;
typedef enum
{
ENC,
DEC
} aes_mode;
#ifdef __cplusplus
extern "C" {
#endif
// SHA
bool VerifySha256(void *data, u64 size, u8 hash[32]);
void ShaCalc(void *data, u64 size, u8 *hash, int mode);
// AES
void AesCtrCrypt(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset);
void AesCbcCrypt(u8 *key, u8 *iv, u8 *input, u8 *output, u64 length, u8 mode);
// RSA
int RsaSignVerify(void *data, u64 len, u8 *sign, u8 *mod, u8 *priv_exp, u32 sig_type, u8 rsa_mode);
#ifdef __cplusplus
}
#endif
+14
View File
@@ -0,0 +1,14 @@
#include "lib.h"
u32 GetCtrBlockSize(u8 flag)
{
return 1 << (flag + 9);
}
u8 GetCtrBlockSizeFlag(u32 size)
{
u8 ret = 0;
for(u32 tmp = size; tmp > 0x200; tmp = tmp >> 1)
ret++;
return ret;
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
u32 GetCtrBlockSize(u8 flag);
u8 GetCtrBlockSizeFlag(u32 size);
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include <stdint.h>
enum SdkAppTypes {
desc_NotSpecified,
desc_Application,
desc_DlpChild,
desc_Demo,
desc_EcApplication, // intergrated in (Ext)Application since SDK 7
desc_ExtApplication, // Snake equivalent of desc_Application (128MB/804MHz/L2 Cache)
desc_ExtDlpChild, // Snake equivalent of desc_DlpChild (128MB/804MHz/L2 Cache)
desc_ExtDemo // Snake equivalent of desc_Demo (128MB/804MHz/L2 Cache)
};
typedef struct CtrSdkDepList {
uint32_t fw_minor;
uint8_t dependency[0x180];
} CtrSdkDepList;
typedef struct CtrSdkDesc {
uint32_t type;
uint32_t fw_minor;
uint8_t exheader_desc[0x200];
uint8_t signed_desc[0x200];
} CtrSdkDesc;
typedef struct CtrSdkDescSignData {
uint32_t type;
uint32_t fw_minor;
uint8_t modulus[0x100];
uint8_t priv_exponent[0x100];
uint8_t access_desc_signature[0x100];
} CtrSdkDescSignData;
+58
View File
@@ -0,0 +1,58 @@
#pragma once
#include "desc.h"
static const CtrSdkDescSignData kDevDescSignData[] =
{
/* CTR_SDK 1 (1.2.0) */
{
.type = desc_Application,
.fw_minor = 27,
.modulus = { 0x9B, 0x82, 0x9C, 0x19, 0x01, 0x73, 0x23, 0x50, 0x89, 0xE3, 0x0B, 0xC8, 0x8F, 0xFB, 0xA5, 0xE4, 0xFD, 0x44, 0xAE, 0x49, 0x32, 0xC7, 0xEF, 0x0A, 0x7E, 0x93, 0x95, 0xBA, 0xA2, 0x48, 0x4D, 0x8E, 0x18, 0x82, 0x34, 0x66, 0xFE, 0xDA, 0x7A, 0x45, 0x4A, 0x7D, 0xD5, 0x3C, 0xC6, 0x5C, 0xE0, 0x71, 0xFC, 0xD0, 0x82, 0xCC, 0xB2, 0xCF, 0x77, 0x0E, 0xAD, 0xCD, 0xD2, 0xAC, 0x1D, 0x66, 0x1B, 0xC1, 0xEA, 0xAC, 0x39, 0x96, 0x2C, 0x52, 0xDE, 0xFF, 0xF2, 0x74, 0xF6, 0xC5, 0xCA, 0x99, 0x31, 0x95, 0x13, 0xBB, 0x3F, 0xED, 0x30, 0xAE, 0x0A, 0xD3, 0x86, 0x0D, 0x0B, 0xF5, 0x56, 0x7D, 0x33, 0xBA, 0xA1, 0x39, 0xA2, 0xF5, 0xB6, 0x47, 0x78, 0x1F, 0xFD, 0x04, 0xA3, 0x49, 0xA9, 0x10, 0xD3, 0x41, 0x2E, 0x92, 0x7D, 0xE1, 0xA4, 0xA8, 0x02, 0x18, 0x01, 0x2C, 0xC2, 0x61, 0xB1, 0xAC, 0xCB, 0xB3, 0x7A, 0x64, 0xB1, 0xC3, 0xE6, 0x3B, 0x50, 0xAD, 0xDD, 0x55, 0xAB, 0x28, 0xDA, 0x59, 0xE7, 0x57, 0x6A, 0x76, 0x4F, 0x6B, 0x08, 0xD1, 0x61, 0x7D, 0x28, 0xD5, 0x88, 0x7B, 0x8E, 0x80, 0x78, 0xF3, 0xFF, 0x50, 0x00, 0xBD, 0x73, 0xFB, 0x62, 0xB3, 0xCA, 0xA8, 0x05, 0x48, 0xE6, 0xE6, 0x71, 0xB5, 0xAC, 0xDA, 0xE9, 0xC6, 0x1F, 0x9B, 0x72, 0x98, 0x2E, 0xFF, 0xB2, 0x9C, 0x36, 0x9F, 0x7E, 0x7D, 0x25, 0x65, 0x6F, 0xB0, 0x60, 0xB1, 0xB5, 0x5F, 0xCF, 0x74, 0x29, 0x91, 0x9D, 0xAB, 0x84, 0x97, 0x1A, 0x27, 0x5D, 0x69, 0x49, 0x16, 0xF8, 0x77, 0x31, 0x26, 0x3E, 0x6F, 0x97, 0x41, 0x4A, 0x26, 0xFD, 0x5B, 0xAB, 0x65, 0x77, 0x45, 0x1C, 0x76, 0x15, 0xDC, 0x1A, 0x63, 0x0F, 0x51, 0x2D, 0xA0, 0x07, 0x6E, 0xE5, 0x29, 0xD3, 0x37, 0x4B, 0xE5, 0x7F, 0xBB, 0x23, 0xD0, 0x2B, 0xB9, 0x76, 0x1F },
.priv_exponent = { 0x66, 0x9F, 0xB5, 0xC5, 0xA6, 0xB8, 0x45, 0xD8, 0xD3, 0x75, 0xFB, 0x03, 0xBB, 0x48, 0xF5, 0x7C, 0x7D, 0x4B, 0x02, 0xBD, 0x19, 0x7E, 0xE9, 0x98, 0x02, 0x5A, 0x00, 0xD8, 0x6E, 0x59, 0xCA, 0x9C, 0x78, 0x3E, 0x0C, 0xB8, 0xDF, 0x7C, 0x6C, 0x6E, 0x27, 0xAF, 0x8C, 0xB6, 0x13, 0xAD, 0x9D, 0x0C, 0x7C, 0x2B, 0x59, 0xF6, 0x1E, 0x16, 0x5D, 0x5A, 0x59, 0x86, 0x57, 0x7D, 0xEF, 0xD4, 0xBF, 0x82, 0xA4, 0x0C, 0x4D, 0xE0, 0x75, 0x95, 0xA6, 0xC6, 0x3F, 0x49, 0xC2, 0xC4, 0x5A, 0x63, 0xE8, 0x5D, 0x99, 0xEC, 0xDB, 0x4D, 0xFA, 0xEF, 0x10, 0x03, 0xF1, 0x15, 0xD1, 0x0B, 0x71, 0xAD, 0x24, 0x23, 0x08, 0x5C, 0x91, 0xD7, 0x17, 0x18, 0x69, 0x04, 0xAB, 0x23, 0x91, 0x62, 0x7D, 0xE8, 0xB5, 0x90, 0xF1, 0x5C, 0x09, 0x28, 0x8C, 0x51, 0xB7, 0x38, 0x02, 0x26, 0x78, 0x8C, 0xA2, 0x05, 0x07, 0x53, 0x7D, 0x99, 0x46, 0xFD, 0x12, 0x77, 0x32, 0x0E, 0xA8, 0x54, 0xE3, 0x32, 0x0E, 0x93, 0x05, 0x10, 0xFA, 0x59, 0x7A, 0x5D, 0x2E, 0xDE, 0x32, 0xE8, 0xE9, 0xF0, 0x27, 0x4E, 0x08, 0x83, 0x08, 0xD4, 0x92, 0x58, 0x4D, 0x6D, 0x34, 0x9F, 0xD9, 0xAF, 0xA9, 0x01, 0x62, 0xB5, 0x1A, 0x1D, 0x7E, 0x8D, 0xBB, 0x8A, 0x58, 0xBA, 0xFF, 0xB4, 0xD3, 0x75, 0xF3, 0x44, 0xE7, 0x13, 0x05, 0xC6, 0xC5, 0xA4, 0xD2, 0x6B, 0x18, 0x31, 0x9F, 0xBE, 0x42, 0x45, 0x82, 0x2E, 0x47, 0x9B, 0x26, 0x73, 0x28, 0xD7, 0x9A, 0x64, 0xA6, 0x3D, 0x38, 0x9C, 0x11, 0x36, 0x01, 0x5B, 0x82, 0x2F, 0x7E, 0xA8, 0xC4, 0x82, 0x15, 0x6C, 0x0B, 0xBA, 0x1C, 0x58, 0xF5, 0x81, 0xF9, 0x45, 0xA9, 0xC6, 0x05, 0x6A, 0x2C, 0xA6, 0xCF, 0xF5, 0xDF, 0xEB, 0xBB, 0xC0, 0x92, 0xE3, 0xA6, 0x9D, 0x23, 0x09, 0x09, 0x0E, 0x98, 0x39 },
.access_desc_signature = { 0x05, 0x90, 0xAF, 0x65, 0x16, 0x9F, 0x18, 0x2C, 0x17, 0x78, 0x9F, 0xDF, 0xB6, 0x37, 0xCF, 0x26, 0x9B, 0x1B, 0x75, 0x51, 0xB8, 0x57, 0xA3, 0x8F, 0xD7, 0x93, 0x19, 0x61, 0x81, 0x0D, 0x3D, 0xBC, 0x36, 0x50, 0x53, 0xDA, 0x7D, 0xA9, 0x7F, 0xAA, 0x3E, 0x51, 0x2C, 0x75, 0xA1, 0xB9, 0xB1, 0x56, 0xEB, 0x2A, 0x46, 0x21, 0xEC, 0x4F, 0xA7, 0x0C, 0xA1, 0xA8, 0xFD, 0xEE, 0xA3, 0x4A, 0xFD, 0x54, 0xB0, 0x3A, 0x49, 0x5C, 0x8F, 0x8D, 0xB2, 0xBC, 0x32, 0x50, 0x7E, 0x2C, 0x50, 0xD2, 0x1A, 0x6B, 0x61, 0xCB, 0x2A, 0xC9, 0x7E, 0x6E, 0x6A, 0xC8, 0xD6, 0x9B, 0x21, 0xE7, 0x3B, 0xB8, 0x39, 0x1C, 0xD7, 0xEB, 0x69, 0x35, 0xF5, 0xBC, 0xB5, 0x23, 0x54, 0x81, 0x4F, 0x73, 0xAB, 0x9C, 0x55, 0xF0, 0x04, 0x0B, 0x4A, 0xEA, 0x54, 0x08, 0xBF, 0x36, 0x28, 0x12, 0x5E, 0x44, 0x41, 0xF5, 0x3D, 0xFE, 0xA7, 0x6B, 0x35, 0xF2, 0x9A, 0xF2, 0x88, 0xCD, 0xD6, 0x2E, 0x7B, 0xF3, 0xF5, 0x0D, 0x06, 0x2E, 0x13, 0x4F, 0x78, 0xEE, 0x27, 0xAB, 0x31, 0x06, 0x62, 0xE9, 0xB2, 0x3E, 0xC6, 0x99, 0xD7, 0xA9, 0xCC, 0x21, 0x70, 0xD7, 0xCD, 0x9F, 0x03, 0x66, 0x91, 0x7E, 0xBD, 0x3E, 0x83, 0xC4, 0xFF, 0xC9, 0xAA, 0x7E, 0x27, 0xAE, 0x5C, 0x37, 0x7D, 0x93, 0x57, 0x60, 0xB9, 0x0B, 0x71, 0x43, 0x8A, 0x2F, 0x43, 0x50, 0x94, 0xF8, 0x0D, 0x40, 0xCC, 0x64, 0x16, 0x09, 0x70, 0xCD, 0x03, 0xCA, 0x95, 0x30, 0x20, 0xE2, 0x85, 0x2F, 0x2A, 0xCF, 0x65, 0xAA, 0xE9, 0xCF, 0x1F, 0x57, 0xC1, 0x8F, 0xD5, 0x46, 0x51, 0x5A, 0x99, 0x60, 0x65, 0x93, 0xA9, 0xBB, 0xEA, 0x5F, 0xA0, 0x47, 0xD7, 0x11, 0x04, 0xC7, 0xB4, 0x82, 0x66, 0x24, 0x17, 0x17, 0x5E, 0x9D, 0xC8, 0x50, 0x80, 0x63, 0x28, 0xB3, 0xF8, 0xE3 }
},
{
.type = desc_DlpChild,
.fw_minor = 27,
.modulus = { 0xD9, 0xF0, 0xC9, 0x35, 0x1E, 0x55, 0xD8, 0x7E, 0x96, 0x53, 0x33, 0x34, 0xBB, 0x8A, 0xAE, 0x03, 0x92, 0x35, 0xE2, 0x05, 0x58, 0x7C, 0xCC, 0x08, 0xB2, 0xDF, 0x43, 0x41, 0xB7, 0x7A, 0xB5, 0x29, 0xEE, 0x4E, 0xF3, 0xC7, 0x35, 0x3B, 0x7E, 0xC5, 0xEE, 0x74, 0xF0, 0xAA, 0x7E, 0x60, 0xF1, 0x28, 0x35, 0x17, 0xD6, 0xC9, 0x9A, 0xF2, 0x84, 0xFE, 0xC8, 0x93, 0x86, 0xF7, 0xA7, 0x36, 0xA6, 0xB0, 0x28, 0xDC, 0xE8, 0x38, 0x0B, 0x54, 0x42, 0x8D, 0x4E, 0x4B, 0x55, 0x0F, 0x4A, 0x0D, 0x72, 0xA0, 0x23, 0xC9, 0x68, 0x22, 0x37, 0x31, 0x88, 0x2C, 0x05, 0x49, 0x86, 0x80, 0x9A, 0xFC, 0x1D, 0x02, 0xE3, 0x20, 0x15, 0x0C, 0x7E, 0x28, 0x40, 0x57, 0xEF, 0xA7, 0xBC, 0xAA, 0xC5, 0xD6, 0xD7, 0x6F, 0xF9, 0x26, 0x9A, 0x32, 0xB2, 0x9E, 0x10, 0x5F, 0x93, 0xE6, 0xB2, 0xC6, 0xB2, 0x62, 0x34, 0x6A, 0xB0, 0xD9, 0x71, 0x3B, 0x0F, 0x34, 0x6C, 0xB1, 0xFE, 0x3A, 0x39, 0xDE, 0x3D, 0x6A, 0xCB, 0x32, 0x95, 0xFA, 0x18, 0x4F, 0xF4, 0xEB, 0x5F, 0x20, 0xE4, 0xEF, 0x64, 0xC5, 0x06, 0x27, 0xC3, 0x44, 0x2A, 0x39, 0x35, 0xD8, 0x00, 0xDF, 0x00, 0xAD, 0xC4, 0x98, 0x06, 0x52, 0xD8, 0x4A, 0xC5, 0x2A, 0x7F, 0x77, 0x50, 0x62, 0x7E, 0x05, 0x3E, 0x8C, 0x28, 0x0A, 0x26, 0xD2, 0x6C, 0x9B, 0x27, 0x65, 0xE9, 0x77, 0x68, 0xE9, 0xE6, 0xAA, 0xBA, 0xF5, 0x85, 0xFC, 0x75, 0x07, 0x84, 0xB2, 0xCA, 0x35, 0x85, 0x52, 0x10, 0x08, 0xEF, 0x85, 0xD3, 0x70, 0x17, 0x31, 0xE1, 0x44, 0xF6, 0x34, 0xDF, 0x7C, 0x42, 0xF7, 0x74, 0xAA, 0xFC, 0xC3, 0xE4, 0x84, 0x2D, 0xBF, 0x15, 0x1E, 0x84, 0x00, 0xE3, 0x80, 0xD7, 0x89, 0x56, 0xEE, 0x60, 0x09, 0x1F, 0xD3, 0xBF, 0xBF, 0x50, 0x8F, 0xA3, 0x0C, 0x72, 0x3F },
.priv_exponent = { 0x10, 0x19, 0x3A, 0x33, 0xA3, 0x47, 0x02, 0x13, 0xEF, 0xB4, 0xBB, 0x9E, 0x94, 0x8F, 0xDC, 0xE4, 0xC4, 0xA3, 0x18, 0x4B, 0xFE, 0xCA, 0x51, 0x23, 0xFF, 0x5A, 0x80, 0x94, 0x55, 0x22, 0x4A, 0x49, 0x8B, 0xA1, 0xE7, 0x5D, 0xFA, 0xAF, 0xA7, 0x60, 0xA5, 0x89, 0x9B, 0xD1, 0x6C, 0x3E, 0x6A, 0xF1, 0xE6, 0x62, 0x19, 0x6A, 0x90, 0xF8, 0x83, 0x1C, 0x72, 0xE2, 0x7A, 0xE0, 0xC6, 0x48, 0x42, 0x2D, 0xD7, 0x06, 0xE2, 0x5C, 0x69, 0x71, 0xD2, 0xEC, 0xAF, 0x30, 0xDF, 0x5A, 0x9E, 0xC4, 0xB9, 0x87, 0xDC, 0xBC, 0xDE, 0xE5, 0x50, 0x20, 0x67, 0x87, 0xA0, 0xE8, 0x5A, 0x78, 0x1B, 0x7A, 0xAE, 0x05, 0xED, 0x93, 0x0C, 0x1A, 0xFD, 0x22, 0xAA, 0x06, 0x14, 0xDC, 0xD6, 0x11, 0xE3, 0x45, 0x48, 0x6A, 0xAC, 0x03, 0xCE, 0xF6, 0x19, 0xBD, 0x95, 0x46, 0x0A, 0x1D, 0xCB, 0x6C, 0xE3, 0xF6, 0x5F, 0x1A, 0xB3, 0x81, 0xC7, 0xE2, 0xAB, 0xFE, 0xEF, 0xFB, 0xEC, 0xFE, 0x88, 0x36, 0x26, 0x60, 0x47, 0x43, 0x78, 0x36, 0xA7, 0xC8, 0xC9, 0x40, 0x98, 0x2E, 0xF2, 0x7E, 0xE4, 0x0D, 0x6C, 0x45, 0x88, 0x2A, 0x32, 0x9B, 0xA2, 0x7C, 0x39, 0x20, 0xAA, 0x6B, 0x64, 0x35, 0xC6, 0xA9, 0x20, 0x71, 0x4A, 0x78, 0x6E, 0x55, 0x3C, 0x9B, 0xEA, 0x10, 0x73, 0xBB, 0xA7, 0xD8, 0xFE, 0x69, 0x42, 0xB8, 0xE7, 0xA1, 0xE5, 0xDF, 0x8A, 0xDE, 0x4C, 0x2B, 0x3A, 0x92, 0xB8, 0x3E, 0x5E, 0x2C, 0x29, 0x0D, 0xC1, 0x3D, 0x10, 0x65, 0x1E, 0xF1, 0x95, 0xE5, 0xF6, 0x45, 0x15, 0xBF, 0xE2, 0x30, 0xA6, 0x70, 0x19, 0xA4, 0x11, 0x57, 0x12, 0x1C, 0x81, 0x4B, 0x54, 0x04, 0xBE, 0x67, 0xF5, 0x00, 0x22, 0x06, 0xDA, 0x6B, 0xCE, 0x23, 0x3F, 0x86, 0xE4, 0x70, 0x6A, 0xD1, 0x3E, 0xE5, 0x74, 0x44, 0x86, 0xDA, 0xBE, 0x79 },
.access_desc_signature = { 0x10, 0x19, 0x3A, 0x33, 0xA3, 0x47, 0x02, 0x13, 0xEF, 0xB4, 0xBB, 0x9E, 0x94, 0x8F, 0xDC, 0xE4, 0xC4, 0xA3, 0x18, 0x4B, 0xFE, 0xCA, 0x51, 0x23, 0xFF, 0x5A, 0x80, 0x94, 0x55, 0x22, 0x4A, 0x49, 0x8B, 0xA1, 0xE7, 0x5D, 0xFA, 0xAF, 0xA7, 0x60, 0xA5, 0x89, 0x9B, 0xD1, 0x6C, 0x3E, 0x6A, 0xF1, 0xE6, 0x62, 0x19, 0x6A, 0x90, 0xF8, 0x83, 0x1C, 0x72, 0xE2, 0x7A, 0xE0, 0xC6, 0x48, 0x42, 0x2D, 0xD7, 0x06, 0xE2, 0x5C, 0x69, 0x71, 0xD2, 0xEC, 0xAF, 0x30, 0xDF, 0x5A, 0x9E, 0xC4, 0xB9, 0x87, 0xDC, 0xBC, 0xDE, 0xE5, 0x50, 0x20, 0x67, 0x87, 0xA0, 0xE8, 0x5A, 0x78, 0x1B, 0x7A, 0xAE, 0x05, 0xED, 0x93, 0x0C, 0x1A, 0xFD, 0x22, 0xAA, 0x06, 0x14, 0xDC, 0xD6, 0x11, 0xE3, 0x45, 0x48, 0x6A, 0xAC, 0x03, 0xCE, 0xF6, 0x19, 0xBD, 0x95, 0x46, 0x0A, 0x1D, 0xCB, 0x6C, 0xE3, 0xF6, 0x5F, 0x1A, 0xB3, 0x81, 0xC7, 0xE2, 0xAB, 0xFE, 0xEF, 0xFB, 0xEC, 0xFE, 0x88, 0x36, 0x26, 0x60, 0x47, 0x43, 0x78, 0x36, 0xA7, 0xC8, 0xC9, 0x40, 0x98, 0x2E, 0xF2, 0x7E, 0xE4, 0x0D, 0x6C, 0x45, 0x88, 0x2A, 0x32, 0x9B, 0xA2, 0x7C, 0x39, 0x20, 0xAA, 0x6B, 0x64, 0x35, 0xC6, 0xA9, 0x20, 0x71, 0x4A, 0x78, 0x6E, 0x55, 0x3C, 0x9B, 0xEA, 0x10, 0x73, 0xBB, 0xA7, 0xD8, 0xFE, 0x69, 0x42, 0xB8, 0xE7, 0xA1, 0xE5, 0xDF, 0x8A, 0xDE, 0x4C, 0x2B, 0x3A, 0x92, 0xB8, 0x3E, 0x5E, 0x2C, 0x29, 0x0D, 0xC1, 0x3D, 0x10, 0x65, 0x1E, 0xF1, 0x95, 0xE5, 0xF6, 0x45, 0x15, 0xBF, 0xE2, 0x30, 0xA6, 0x70, 0x19, 0xA4, 0x11, 0x57, 0x12, 0x1C, 0x81, 0x4B, 0x54, 0x04, 0xBE, 0x67, 0xF5, 0x00, 0x22, 0x06, 0xDA, 0x6B, 0xCE, 0x23, 0x3F, 0x86, 0xE4, 0x70, 0x6A, 0xD1, 0x3E, 0xE5, 0x74, 0x44, 0x86, 0xDA, 0xBE, 0x79 }
},
/* CTR_SDK 2 (2.3.4) */
{
.type = desc_Application,
.fw_minor = 29,
.modulus = { 0xE9, 0x45, 0xF0, 0xC6, 0x96, 0xD5, 0x6F, 0x7E, 0xAE, 0x03, 0x92, 0x2E, 0xEA, 0xCB, 0xFD, 0xEA, 0xA4, 0x7A, 0x9F, 0x12, 0xDA, 0x4C, 0x10, 0x0A, 0xBE, 0x08, 0x9D, 0x87, 0xE0, 0x14, 0xAC, 0x7F, 0x39, 0xD2, 0xFE, 0x9D, 0x88, 0xB2, 0x81, 0xF6, 0x1A, 0x9E, 0x15, 0x57, 0xD4, 0xE2, 0x31, 0x08, 0x07, 0xEC, 0x4F, 0x10, 0x00, 0xDE, 0xEF, 0x8B, 0x6F, 0xCF, 0x84, 0xE7, 0x3B, 0x41, 0x08, 0x64, 0x3B, 0x1C, 0x00, 0x7C, 0x73, 0xBB, 0x59, 0x4D, 0xD8, 0xD6, 0xE7, 0x7B, 0xBE, 0xDD, 0x50, 0x98, 0xA1, 0x1A, 0xD5, 0xAA, 0x37, 0x69, 0xB8, 0x25, 0xCB, 0x7B, 0x03, 0x00, 0x90, 0x25, 0xF3, 0x7E, 0x9A, 0x0F, 0xA3, 0xAA, 0xC4, 0xB9, 0x3B, 0x3A, 0x18, 0x2B, 0xBC, 0x9C, 0x11, 0x04, 0x92, 0x16, 0x6E, 0xC3, 0xFA, 0x01, 0xD3, 0x00, 0x02, 0xF3, 0x2E, 0xD5, 0x60, 0xA8, 0xAF, 0xAB, 0xEE, 0x2F, 0x9D, 0x30, 0x3E, 0x0E, 0xDC, 0xB8, 0xEC, 0x87, 0x9E, 0x4A, 0xA9, 0x01, 0x34, 0x69, 0x2C, 0x4C, 0x34, 0xB7, 0x7D, 0xB9, 0x7A, 0x17, 0x74, 0x31, 0xB0, 0x29, 0xC4, 0x7D, 0x27, 0x1F, 0xBA, 0xBA, 0x3F, 0x5B, 0x62, 0xF6, 0x90, 0xB8, 0x37, 0x33, 0xFC, 0x73, 0xD6, 0x19, 0x11, 0xCA, 0x83, 0x2A, 0x58, 0x62, 0x9C, 0xB1, 0x83, 0x43, 0x1D, 0x2C, 0x00, 0xA2, 0xE5, 0x87, 0x97, 0x12, 0x63, 0x31, 0x83, 0x0E, 0xB1, 0x1E, 0x69, 0x99, 0x02, 0xAF, 0xDF, 0xFF, 0x0F, 0xA9, 0x7C, 0x1B, 0x33, 0x9E, 0xFF, 0x9C, 0x14, 0x19, 0xA6, 0xCA, 0xFD, 0xB9, 0x17, 0xE0, 0x22, 0xCF, 0xB5, 0x00, 0x77, 0x2E, 0x31, 0xAD, 0xF7, 0xE5, 0xAD, 0x98, 0x14, 0xDF, 0x19, 0xF0, 0xC9, 0xBE, 0x37, 0xF6, 0xF0, 0x23, 0x66, 0xCF, 0x34, 0xE3, 0xD5, 0x8F, 0xD4, 0x07, 0xBA, 0x06, 0x56, 0x00, 0x66, 0x9A, 0xEB, 0x93 },
.priv_exponent = { 0xBC, 0x49, 0x29, 0xB9, 0x01, 0x52, 0x31, 0x76, 0x4C, 0xBA, 0xB1, 0x29, 0x91, 0x77, 0x29, 0xF2, 0x54, 0xE4, 0x6C, 0xB5, 0x68, 0xE1, 0xF0, 0x28, 0xDB, 0x8E, 0x54, 0xA8, 0xB1, 0xA3, 0xBE, 0x3F, 0xCA, 0xCA, 0x95, 0x9D, 0x4E, 0x12, 0xD7, 0x77, 0x6F, 0xB0, 0x9D, 0x85, 0x91, 0x5D, 0x29, 0x3A, 0x54, 0x3A, 0xD6, 0xEE, 0x11, 0xE5, 0xDF, 0xEF, 0xEA, 0x45, 0xD3, 0xFE, 0x58, 0x03, 0x7B, 0xE4, 0x7B, 0x19, 0x75, 0x02, 0xFE, 0xDE, 0xFF, 0x8C, 0x28, 0x33, 0xFE, 0x10, 0x11, 0xD4, 0xCD, 0x13, 0x05, 0x26, 0x85, 0xC3, 0xA8, 0x8A, 0x7A, 0x8A, 0x77, 0x1D, 0x49, 0x25, 0x11, 0x34, 0xB0, 0xBF, 0x45, 0x56, 0xCE, 0x42, 0x2E, 0x1B, 0x5C, 0xC4, 0xDD, 0x71, 0xA0, 0x01, 0x50, 0x73, 0x21, 0xFF, 0x5D, 0x54, 0x6D, 0xDD, 0x3F, 0x14, 0x49, 0x4D, 0x44, 0x46, 0x12, 0x88, 0xD5, 0x92, 0xAE, 0xE2, 0xD0, 0xF6, 0x2C, 0x10, 0xD5, 0x67, 0x61, 0x87, 0x7F, 0x2A, 0x17, 0x9D, 0x4F, 0xC6, 0x79, 0xC3, 0xAF, 0x4D, 0x6F, 0xFB, 0x0F, 0x3B, 0x48, 0x5D, 0x46, 0x9A, 0xE8, 0x53, 0xB7, 0xC5, 0x69, 0xEC, 0x31, 0x25, 0xD1, 0xDC, 0x93, 0xAB, 0x2E, 0x53, 0x3B, 0x8E, 0x96, 0x27, 0x59, 0xD4, 0xF7, 0xB3, 0xAB, 0x51, 0x59, 0xAE, 0x6E, 0x26, 0x4F, 0xC2, 0x95, 0xCE, 0x42, 0xC6, 0xAF, 0x46, 0xC6, 0x2E, 0x32, 0x09, 0x7B, 0xAF, 0x67, 0x4E, 0x57, 0xC8, 0x93, 0x5F, 0x8C, 0xD5, 0x66, 0x7B, 0xCC, 0xE9, 0xBE, 0x86, 0xB9, 0xBB, 0xD0, 0xC8, 0xD2, 0xDC, 0x5F, 0x95, 0x83, 0x28, 0x55, 0x21, 0x1E, 0xEE, 0xCF, 0x23, 0xB7, 0x6D, 0xE0, 0x9A, 0x87, 0x99, 0xFB, 0x82, 0x50, 0xD0, 0x2D, 0xC4, 0xFB, 0xA0, 0x11, 0x2F, 0xDD, 0x05, 0x7E, 0x1C, 0xE3, 0xFB, 0x98, 0x69, 0xD4, 0x49, 0x2F, 0x0D, 0xF6, 0x61 },
.access_desc_signature = { 0x62, 0xFE, 0xD9, 0x12, 0x3D, 0x99, 0x53, 0xC4, 0x20, 0x25, 0xDE, 0x59, 0xEA, 0x6E, 0xF3, 0x16, 0x5B, 0x36, 0xBA, 0x1C, 0xB3, 0xB5, 0x48, 0x37, 0xD2, 0xA4, 0x04, 0xE5, 0x14, 0xC6, 0xE7, 0x22, 0x14, 0x40, 0x6F, 0x92, 0x6A, 0x9B, 0xDF, 0xDE, 0xFA, 0xCE, 0x3C, 0xBB, 0x4B, 0xC4, 0x66, 0xA8, 0x86, 0x58, 0xAC, 0xEB, 0x2F, 0xB7, 0xA3, 0xEC, 0xEA, 0x31, 0x23, 0x61, 0xF6, 0x72, 0x1E, 0x26, 0x8A, 0x1D, 0x68, 0x2A, 0x2A, 0x21, 0x5A, 0xA2, 0x6A, 0xBD, 0xCE, 0xC0, 0x19, 0x08, 0x61, 0x64, 0xB3, 0xF6, 0x90, 0xB1, 0x34, 0xF8, 0x50, 0x6F, 0x83, 0xB6, 0x8D, 0x35, 0x12, 0x7F, 0x9C, 0x7B, 0x6E, 0x3C, 0x4E, 0xD1, 0xFD, 0xC3, 0x30, 0xD2, 0xE8, 0x7E, 0x15, 0x1F, 0xAD, 0xDB, 0x1D, 0x92, 0xDA, 0x8C, 0x4E, 0xE9, 0x84, 0x83, 0xFF, 0x1A, 0x09, 0x77, 0x05, 0x5A, 0xCF, 0x5C, 0x8B, 0x4F, 0x68, 0x36, 0xC8, 0xDA, 0x5B, 0x1A, 0x5A, 0x49, 0xF9, 0xA1, 0xF2, 0xC8, 0x02, 0xFD, 0x69, 0x1F, 0x1D, 0xB3, 0xE8, 0xF8, 0xE1, 0x6B, 0x15, 0x9A, 0x5E, 0x41, 0x84, 0x06, 0x1F, 0x2A, 0xB3, 0xB2, 0xA1, 0xDC, 0x63, 0x81, 0xB3, 0x6B, 0x4B, 0x21, 0x67, 0x19, 0x82, 0x52, 0xFE, 0x75, 0x96, 0xA1, 0xDF, 0x02, 0xD4, 0x07, 0x1F, 0x1B, 0x88, 0x12, 0x5A, 0x76, 0x54, 0xC4, 0x06, 0x2D, 0xB1, 0xAA, 0x41, 0x3C, 0x9F, 0x43, 0xA2, 0x75, 0x20, 0x39, 0xB6, 0x06, 0xF9, 0x9C, 0xFC, 0x00, 0xC5, 0xBC, 0x84, 0x13, 0x80, 0xE4, 0x10, 0x1A, 0xCD, 0x95, 0xBB, 0xF2, 0xDC, 0x57, 0x7B, 0xBA, 0x87, 0x05, 0x0B, 0x96, 0xC1, 0xCD, 0x60, 0xC7, 0x10, 0x44, 0x78, 0x0E, 0x0F, 0x2F, 0x91, 0x54, 0x6C, 0xDE, 0xB8, 0x14, 0x46, 0xF3, 0x9C, 0xAC, 0x7B, 0xAA, 0xE7, 0x1B, 0x52, 0xD6, 0xBE, 0x71, 0x97, 0x22 }
},
{
.type = desc_DlpChild,
.fw_minor = 29,
.modulus = { 0xB9, 0xDE, 0x3D, 0xC0, 0x55, 0xB9, 0xCC, 0x3F, 0x55, 0xE0, 0x61, 0x1D, 0x6F, 0xCF, 0x3E, 0x7F, 0xE2, 0xF7, 0xF5, 0xAD, 0x5C, 0x02, 0x7F, 0x17, 0x5B, 0x44, 0x2F, 0x2D, 0xDC, 0xD4, 0xA6, 0x63, 0xD2, 0xA7, 0x82, 0xD3, 0x00, 0x77, 0xC8, 0x0B, 0x28, 0x09, 0x3D, 0x81, 0x86, 0x93, 0xF5, 0xF6, 0xE4, 0x69, 0x3B, 0x60, 0x4C, 0x7F, 0x8D, 0x72, 0xA3, 0x22, 0x42, 0x86, 0x87, 0x06, 0xD8, 0x29, 0x89, 0x8A, 0x9F, 0x5F, 0x6C, 0x06, 0x0C, 0x96, 0x84, 0x00, 0x24, 0x5D, 0x0B, 0xEA, 0x15, 0xEC, 0xAD, 0x90, 0xA4, 0x0C, 0x7B, 0xAE, 0x0E, 0x85, 0x3E, 0xA2, 0x20, 0x04, 0xE8, 0xD9, 0x59, 0x0F, 0x31, 0x0E, 0xD4, 0x5D, 0xC1, 0x18, 0xED, 0x0E, 0xB4, 0xD2, 0x5E, 0x65, 0xA2, 0x78, 0x0C, 0x76, 0x03, 0x3A, 0x71, 0x18, 0xE4, 0x38, 0x44, 0x14, 0xE0, 0x93, 0x84, 0xFE, 0x34, 0x82, 0xCA, 0x0B, 0xB8, 0xF2, 0x41, 0xAB, 0x63, 0xF3, 0xDE, 0xAE, 0xF4, 0x36, 0x81, 0xA4, 0x78, 0x7B, 0xF9, 0xA8, 0xFB, 0xC9, 0xA7, 0x6E, 0xA4, 0xD5, 0xE2, 0xA9, 0xD8, 0xD9, 0xE8, 0x98, 0x1B, 0x25, 0x75, 0x00, 0x11, 0x51, 0x97, 0x62, 0x0D, 0xF0, 0x0C, 0xE9, 0x6B, 0x0C, 0xEE, 0xCE, 0x25, 0x2C, 0x3F, 0xDF, 0xBE, 0x54, 0xD5, 0xD6, 0x5E, 0xEE, 0x1F, 0x73, 0xFC, 0xE8, 0xEC, 0xB3, 0x8A, 0x48, 0x9F, 0x6A, 0xC1, 0x63, 0x85, 0xE4, 0x94, 0x85, 0x8F, 0x3D, 0x9D, 0x43, 0xB4, 0xA7, 0x4C, 0x82, 0xA3, 0x0B, 0x67, 0x43, 0x12, 0x31, 0x77, 0x89, 0xB0, 0xD5, 0x00, 0x1B, 0x52, 0x29, 0xCE, 0x54, 0xC7, 0xC4, 0x7D, 0xB6, 0x69, 0x7B, 0xFE, 0xDC, 0xDB, 0x4E, 0xD8, 0x58, 0x42, 0x14, 0x34, 0x72, 0x64, 0xBC, 0x09, 0x6D, 0xAC, 0xD3, 0xC4, 0x1B, 0x5C, 0x8E, 0xF9, 0xBE, 0x84, 0xCD, 0x9A, 0x86, 0x4B, 0x17 },
.priv_exponent = { 0xAA, 0x51, 0x62, 0x58, 0x9A, 0xB5, 0x74, 0xDA, 0x1C, 0xC1, 0x4D, 0x7C, 0x81, 0xF6, 0x70, 0x99, 0x13, 0xCC, 0x90, 0x0D, 0xD9, 0xA0, 0x58, 0x01, 0x79, 0x1A, 0x53, 0xF9, 0x3C, 0xC0, 0x87, 0xF0, 0x35, 0x1A, 0x56, 0xA1, 0x2F, 0x6E, 0x93, 0x9A, 0xD5, 0x87, 0x12, 0x1B, 0x5C, 0xCC, 0xBC, 0xB9, 0x0E, 0xB8, 0xF7, 0x35, 0xD9, 0x23, 0x90, 0xE4, 0x19, 0x64, 0xCD, 0x7D, 0x24, 0xC2, 0x3A, 0xD6, 0x65, 0x38, 0xE7, 0xAD, 0xB2, 0xF9, 0x20, 0x13, 0xD4, 0xC5, 0xA4, 0x8C, 0xB6, 0xDC, 0x3C, 0x56, 0xF2, 0xFC, 0xF5, 0xB6, 0x92, 0xA6, 0xFE, 0x9B, 0x4E, 0xB7, 0x95, 0x8B, 0xAA, 0x2B, 0x70, 0x96, 0xA1, 0x27, 0xAB, 0xA6, 0x75, 0xC9, 0x77, 0x80, 0xE0, 0x65, 0x5D, 0x26, 0xD8, 0xE8, 0x14, 0xD3, 0x17, 0x46, 0x38, 0x58, 0xCC, 0xD8, 0x5A, 0x5A, 0x9F, 0x27, 0xCE, 0xD8, 0x7A, 0x19, 0xD7, 0x35, 0xB2, 0x32, 0xAF, 0x47, 0x2E, 0x9F, 0x4B, 0x64, 0xEC, 0x1F, 0xC6, 0x40, 0xD0, 0x2C, 0x47, 0xD1, 0xEA, 0x33, 0xE5, 0x0E, 0x80, 0xFC, 0x68, 0xEC, 0x8C, 0x12, 0x33, 0xCE, 0x34, 0x28, 0x79, 0xFA, 0x05, 0x5D, 0x70, 0x15, 0xDE, 0xB1, 0x22, 0x85, 0x18, 0x63, 0x15, 0x35, 0x57, 0x04, 0x17, 0x64, 0x20, 0xC8, 0x52, 0x44, 0x64, 0x5E, 0x47, 0x4E, 0x5F, 0x80, 0x21, 0x16, 0x94, 0x4B, 0x18, 0x11, 0x36, 0x67, 0x3B, 0x6C, 0x69, 0x19, 0xCF, 0xC9, 0x05, 0x85, 0x9B, 0x3A, 0xDE, 0x12, 0x1E, 0x0A, 0xC6, 0x22, 0xA8, 0xC7, 0x9A, 0x34, 0x14, 0x98, 0xFD, 0xD9, 0x0F, 0xE8, 0x64, 0xE6, 0x89, 0x63, 0x6E, 0x17, 0x76, 0xD7, 0x1B, 0x6F, 0x92, 0x00, 0xD8, 0xBB, 0xF6, 0xA0, 0x65, 0x9D, 0xAA, 0x7A, 0x0E, 0x4B, 0x56, 0xA5, 0x33, 0xDA, 0x3F, 0x5D, 0xFE, 0xD3, 0xAD, 0x6E, 0x0E, 0xB3, 0xD4, 0x41 },
.access_desc_signature = { 0x97, 0x84, 0x97, 0xEE, 0x4F, 0x35, 0xCC, 0xBE, 0x08, 0xB4, 0x5D, 0x7E, 0x17, 0xC3, 0x94, 0x2B, 0x4D, 0x3A, 0xA5, 0xB5, 0x01, 0xD4, 0xAE, 0x2A, 0x90, 0x26, 0x21, 0x8F, 0x56, 0x05, 0xB9, 0xA2, 0x5E, 0xCE, 0x73, 0xC7, 0x42, 0xDC, 0x99, 0xD2, 0x7C, 0x08, 0x62, 0xBF, 0x10, 0x7A, 0xC1, 0x5D, 0x22, 0x53, 0x8F, 0x63, 0x2D, 0x73, 0xF3, 0x05, 0xDA, 0x9D, 0x6A, 0xF8, 0xB9, 0x5B, 0x80, 0xB4, 0x30, 0xB3, 0x11, 0xF7, 0x96, 0x8A, 0xCF, 0x70, 0xD7, 0x62, 0x6E, 0x99, 0x32, 0xFD, 0x74, 0x34, 0x16, 0xFD, 0x17, 0x1F, 0xB1, 0xEC, 0xA4, 0x0F, 0x52, 0x13, 0x9F, 0x62, 0x0D, 0xE0, 0x50, 0xA6, 0xA0, 0x7B, 0x69, 0x95, 0xE0, 0xE9, 0xBB, 0x38, 0x0C, 0x62, 0xE0, 0xE3, 0xCE, 0x82, 0xE0, 0xB9, 0xE0, 0xF6, 0x61, 0x50, 0xBF, 0xA8, 0x18, 0x15, 0x38, 0xFE, 0xFA, 0x8C, 0xBA, 0xA5, 0xB9, 0x9C, 0x05, 0xA6, 0x91, 0x5C, 0xA7, 0x13, 0x6F, 0x13, 0x3F, 0xF1, 0xF6, 0x68, 0xAF, 0x40, 0xEC, 0x27, 0xE0, 0x33, 0x6B, 0xCF, 0x26, 0x06, 0xF8, 0x6A, 0x13, 0x6C, 0xBC, 0xDB, 0xAF, 0x6F, 0x78, 0xA0, 0x80, 0x10, 0x8F, 0xB6, 0x91, 0x5A, 0x43, 0x2C, 0x5F, 0x1D, 0xBA, 0xB4, 0x5E, 0xBE, 0xAE, 0x53, 0x09, 0x17, 0x5B, 0x6C, 0xC1, 0x5E, 0x0F, 0x72, 0x6E, 0xD6, 0x10, 0x0B, 0xC3, 0x26, 0xDC, 0xAF, 0xCA, 0x28, 0xAB, 0x00, 0x67, 0x04, 0xE3, 0x54, 0xE8, 0x95, 0xC6, 0x23, 0xB6, 0x79, 0x70, 0xA4, 0x87, 0x6D, 0x12, 0x48, 0xCC, 0x11, 0x86, 0xEC, 0x82, 0xF4, 0x30, 0xC9, 0xB1, 0x6D, 0x08, 0xA7, 0xEA, 0x8C, 0x6A, 0x97, 0xAA, 0x89, 0xD5, 0xC5, 0x07, 0xA9, 0xD5, 0xCF, 0x09, 0x08, 0xBC, 0x56, 0x63, 0x8D, 0x70, 0x2F, 0x64, 0xAF, 0x51, 0x9E, 0x22, 0xA4, 0x88, 0xF0, 0xDC, 0x56, 0x72, 0x28 }
},
/* CTR_SDK 4 (4.2.8) */
{
.type = desc_Application,
.fw_minor = 33,
.modulus = { 0xCF, 0xEC, 0xB2, 0x48, 0x03, 0x6D, 0xB8, 0x09, 0xE3, 0x5C, 0x6C, 0x62, 0x2C, 0xA9, 0x49, 0xE1, 0xF4, 0xF4, 0x0C, 0x6C, 0xC3, 0xE5, 0x2F, 0x9D, 0x50, 0xA0, 0x2B, 0x5A, 0x00, 0xC6, 0x72, 0x00, 0x0B, 0xA3, 0x04, 0x5D, 0x94, 0x46, 0xE7, 0x00, 0x1B, 0x48, 0x85, 0xB5, 0x61, 0x2C, 0xC9, 0x74, 0xCA, 0x2B, 0x43, 0x13, 0xC1, 0x78, 0x97, 0x5C, 0x33, 0x2F, 0x07, 0xC7, 0x85, 0xF0, 0xDA, 0xDB, 0x60, 0x96, 0x50, 0x0F, 0x7C, 0x4B, 0x7A, 0xD7, 0x17, 0x9D, 0xE4, 0xE5, 0xC3, 0xAB, 0x6F, 0x5D, 0xA5, 0x78, 0x32, 0xAD, 0x04, 0xDD, 0x96, 0x6E, 0xDC, 0x75, 0xFF, 0xC2, 0x2F, 0xFA, 0xA2, 0xEE, 0x46, 0x89, 0xCD, 0xAE, 0x69, 0x92, 0xA4, 0x48, 0xBC, 0x46, 0x47, 0xC4, 0x8C, 0x89, 0x63, 0xE1, 0x0A, 0x4D, 0x1C, 0xDC, 0x46, 0x2F, 0x5B, 0x70, 0x8A, 0x7C, 0xE9, 0x22, 0x9C, 0x09, 0x0B, 0xA8, 0x97, 0x40, 0xCA, 0x2A, 0x7D, 0x84, 0xA1, 0x04, 0x4A, 0x2E, 0xDB, 0xD7, 0xD0, 0x64, 0x43, 0x9C, 0xD0, 0x78, 0x11, 0x41, 0x88, 0x33, 0xDD, 0x31, 0x62, 0x90, 0x2D, 0x17, 0xF2, 0xC6, 0xA9, 0x2B, 0x9C, 0x70, 0xAB, 0xDC, 0xD3, 0xAB, 0x5D, 0xDA, 0xEE, 0x3D, 0x6C, 0x0E, 0x81, 0xFF, 0xF6, 0x67, 0x5A, 0x44, 0xF9, 0xAC, 0x07, 0x3D, 0x23, 0x94, 0x75, 0x65, 0x93, 0x20, 0x0C, 0xC5, 0x76, 0x1D, 0x0F, 0x65, 0x06, 0x3D, 0x21, 0xA2, 0xF0, 0x96, 0x80, 0xB7, 0x0A, 0x49, 0x53, 0x38, 0xA3, 0x5D, 0xC0, 0x74, 0x3C, 0xA4, 0xD9, 0x40, 0x36, 0x85, 0x1F, 0x8C, 0xD1, 0x2D, 0x15, 0xF9, 0xEF, 0x24, 0xA9, 0x7E, 0x9D, 0xB2, 0x1E, 0xF8, 0xA0, 0x72, 0x81, 0x17, 0x77, 0x73, 0xB1, 0x56, 0x7F, 0xAD, 0x05, 0xA2, 0xD2, 0x30, 0x5A, 0xF5, 0xD3, 0xAF, 0x0F, 0x10, 0x4A, 0x52, 0xD8, 0x09, 0x47, 0x97 },
.priv_exponent = { 0x8C, 0xBD, 0xB2, 0x3B, 0xCE, 0x9E, 0x51, 0x09, 0xD8, 0x6D, 0x72, 0x2B, 0xCE, 0x01, 0x55, 0x32, 0x6E, 0xC5, 0x57, 0x37, 0xB4, 0x2E, 0x09, 0x59, 0xD9, 0xFE, 0x60, 0xF9, 0xCE, 0x36, 0x85, 0x6A, 0x04, 0x76, 0x76, 0xF9, 0x04, 0xEA, 0x2D, 0x68, 0xC4, 0x0F, 0x05, 0xFA, 0xAD, 0x69, 0x4C, 0x80, 0x12, 0x6C, 0xD0, 0x3D, 0xAA, 0x22, 0xFF, 0x89, 0x78, 0x57, 0xE8, 0x53, 0x25, 0x15, 0xD0, 0x7E, 0xD8, 0x55, 0x46, 0xA2, 0x04, 0xC7, 0x6E, 0xC1, 0xF3, 0x89, 0x7C, 0x2C, 0x0E, 0x93, 0x97, 0x91, 0x72, 0xF4, 0xF6, 0x90, 0x69, 0x0F, 0xB8, 0xC9, 0x17, 0xCF, 0x83, 0xAC, 0xA5, 0x1F, 0x69, 0x74, 0x12, 0x29, 0x2B, 0x21, 0x58, 0xF2, 0xDA, 0xE3, 0x25, 0x16, 0x09, 0x74, 0x40, 0x90, 0xAB, 0x1B, 0xE4, 0x06, 0x28, 0x77, 0xED, 0xC6, 0x16, 0x86, 0x0A, 0x27, 0xDD, 0x03, 0x01, 0x4D, 0x9A, 0x26, 0x6E, 0xC8, 0x9F, 0xD3, 0x9A, 0x4B, 0x59, 0xD1, 0x10, 0x9B, 0xEB, 0xA9, 0x58, 0x72, 0xBD, 0xA1, 0xFE, 0x9D, 0x86, 0xED, 0x29, 0xE9, 0x29, 0x49, 0x62, 0x4B, 0xD8, 0x7D, 0x2A, 0x7A, 0x66, 0x1B, 0xE5, 0x04, 0x81, 0x56, 0x10, 0x50, 0xAF, 0xB8, 0x48, 0x27, 0xC1, 0xC9, 0x46, 0xBD, 0x3F, 0x16, 0x06, 0xA5, 0x3D, 0x04, 0x9F, 0x0D, 0x54, 0x71, 0x1C, 0xF4, 0x82, 0xC0, 0x66, 0x74, 0xEA, 0x9C, 0x83, 0x3C, 0x27, 0x01, 0xDF, 0x6F, 0x56, 0xA8, 0x1B, 0xE3, 0x68, 0x55, 0x9F, 0xAB, 0x90, 0x67, 0x20, 0x25, 0xFA, 0x3D, 0x51, 0x2A, 0x23, 0x16, 0xCB, 0x06, 0x5A, 0xAD, 0xAC, 0xC8, 0x47, 0xF9, 0x39, 0x2E, 0x6A, 0xF8, 0xFA, 0x0A, 0xE8, 0x8A, 0x64, 0x84, 0x6B, 0xED, 0xDA, 0x8F, 0x2A, 0x08, 0x86, 0x8F, 0x56, 0x69, 0x64, 0xC3, 0x98, 0x55, 0x37, 0x9A, 0x48, 0x40, 0xDA, 0xD5, 0x03, 0x21 },
.access_desc_signature = { 0xDF, 0x1C, 0x8B, 0x98, 0xE4, 0x6F, 0xA2, 0x35, 0x6C, 0xC3, 0x18, 0x17, 0x98, 0xF3, 0xCE, 0x54, 0x7E, 0x14, 0x2E, 0x7F, 0x1E, 0xD8, 0x6D, 0xCF, 0xBC, 0x29, 0x4E, 0xFE, 0x32, 0x2E, 0xC1, 0x11, 0xAD, 0x46, 0x9A, 0xC6, 0x70, 0xEA, 0xEE, 0x28, 0x55, 0x22, 0xE1, 0x36, 0x05, 0x1C, 0x04, 0x8A, 0xCE, 0x0F, 0x0C, 0x83, 0x8F, 0xC8, 0xD6, 0xDE, 0x11, 0x8E, 0xEA, 0xCF, 0xAD, 0x9B, 0xCF, 0x81, 0x0D, 0xEB, 0x71, 0x13, 0xB3, 0xD3, 0xAE, 0x83, 0x02, 0x4C, 0x0E, 0x10, 0x50, 0x59, 0x3C, 0xEE, 0x60, 0x06, 0xFB, 0x8C, 0x7F, 0xC2, 0x20, 0x24, 0x01, 0x62, 0x55, 0x87, 0x60, 0x0F, 0xAD, 0xFA, 0x73, 0x2E, 0xF6, 0x65, 0x62, 0xD2, 0xE5, 0x10, 0x45, 0x69, 0x70, 0x39, 0x03, 0xD1, 0x39, 0xEC, 0x50, 0xC1, 0xD4, 0x25, 0x39, 0xB2, 0x90, 0x11, 0x4E, 0x95, 0xCB, 0x19, 0xEB, 0xCA, 0x0F, 0xB5, 0xFA, 0xC7, 0xB0, 0xE2, 0xD7, 0xE0, 0x71, 0xC3, 0xE5, 0x55, 0x33, 0x9E, 0x5C, 0xDC, 0x4D, 0x3B, 0x51, 0x11, 0x0D, 0x31, 0x78, 0x96, 0xCA, 0xD7, 0x18, 0x58, 0xEE, 0x00, 0xE9, 0x28, 0xF2, 0x68, 0x76, 0xD4, 0x57, 0xFE, 0x65, 0xB1, 0x4B, 0x49, 0x3F, 0xF6, 0xA6, 0x58, 0x4A, 0xC7, 0xFC, 0xC4, 0xBB, 0x61, 0xBC, 0x58, 0x8D, 0x55, 0x65, 0xE6, 0x0A, 0x79, 0x39, 0x41, 0xB8, 0x80, 0x61, 0xF7, 0x05, 0xC3, 0xFE, 0xD6, 0x8B, 0x09, 0x82, 0xC2, 0x5F, 0xA6, 0x56, 0xF9, 0xEE, 0x1D, 0x0E, 0x06, 0x3E, 0x9F, 0x3F, 0xF1, 0x93, 0x9A, 0x4F, 0xA2, 0xD5, 0x91, 0x87, 0x8A, 0xFE, 0xCF, 0xC3, 0xFC, 0x8A, 0xB1, 0xC4, 0x78, 0xE9, 0xD1, 0x1A, 0xF7, 0xB1, 0xD3, 0x20, 0xCB, 0x83, 0xBE, 0x03, 0xD5, 0xCA, 0xA5, 0x5E, 0x17, 0xA6, 0x91, 0x10, 0xD4, 0xBE, 0x23, 0xD6, 0x4B, 0x4F, 0x03, 0xA9, 0xAE }
},
{
.type = desc_DlpChild,
.fw_minor = 33,
.modulus = { 0xB3, 0x16, 0x68, 0xF1, 0xED, 0x59, 0xC8, 0x7F, 0xC6, 0x50, 0x21, 0xFE, 0x36, 0x7C, 0x55, 0xE7, 0x07, 0xF9, 0x1D, 0x1B, 0xF5, 0xB1, 0x2A, 0x6B, 0x3A, 0xDE, 0x2D, 0x4C, 0x51, 0xCD, 0x4C, 0x9F, 0xEE, 0x1D, 0xE4, 0xE8, 0xF0, 0xFD, 0x09, 0x8E, 0x0F, 0x92, 0x5F, 0xDB, 0x9C, 0x5C, 0x15, 0x55, 0x1A, 0x4D, 0x04, 0x8C, 0xB0, 0xA4, 0x88, 0x97, 0xC4, 0xD5, 0x92, 0x04, 0x42, 0x33, 0x84, 0x81, 0x06, 0xD6, 0xF2, 0x17, 0xDE, 0x83, 0x17, 0x50, 0xD0, 0x47, 0x61, 0x14, 0x0D, 0xB7, 0xC7, 0xA0, 0xC1, 0x8B, 0x82, 0x47, 0x13, 0xEE, 0x76, 0xA2, 0xA3, 0x8D, 0xCE, 0x55, 0xC1, 0xF3, 0x7A, 0xEA, 0x91, 0xE1, 0xB9, 0x2F, 0x8F, 0x9B, 0xC3, 0x7B, 0x51, 0x2F, 0xE7, 0xAD, 0x93, 0x9C, 0xFD, 0xDF, 0x19, 0xC8, 0x6C, 0x24, 0xC2, 0xE2, 0x91, 0x97, 0x1F, 0xEB, 0x4B, 0xD4, 0x46, 0x6C, 0x06, 0x93, 0xAF, 0xF5, 0x5E, 0x8F, 0x77, 0x25, 0xC4, 0x28, 0xC0, 0x82, 0x4A, 0x78, 0xE9, 0x14, 0x08, 0xC3, 0xC3, 0x58, 0x24, 0x44, 0x2D, 0x2B, 0xA7, 0xEE, 0x28, 0xEF, 0x1B, 0x6D, 0xAA, 0x9C, 0xED, 0x7F, 0x35, 0xCE, 0x86, 0x5C, 0x6B, 0x8A, 0x23, 0xD3, 0x9D, 0x05, 0x8F, 0xD2, 0x41, 0x93, 0x1D, 0x1D, 0x7E, 0xB0, 0x46, 0x23, 0x63, 0x07, 0xEA, 0x5F, 0x26, 0xE3, 0x81, 0x27, 0xB3, 0x95, 0xB1, 0x93, 0x59, 0xD4, 0x1A, 0xB8, 0x73, 0xD0, 0x09, 0x95, 0x2B, 0xE8, 0x8B, 0xE2, 0x73, 0x5F, 0x34, 0xB9, 0x98, 0x82, 0xF0, 0x11, 0xC6, 0x8F, 0x12, 0x4D, 0x09, 0x57, 0x10, 0x97, 0x22, 0x0E, 0xC8, 0x7D, 0x40, 0xC1, 0x9D, 0x12, 0x1F, 0x71, 0xFE, 0x1E, 0x1A, 0x8C, 0x3F, 0x56, 0xAC, 0x43, 0xC3, 0x66, 0x0C, 0x81, 0xAE, 0xC1, 0x8F, 0x68, 0xFF, 0x87, 0x07, 0x3C, 0xCD, 0x0A, 0x23, 0xDE, 0xBA, 0x9B },
.priv_exponent = { 0x77, 0xC2, 0x7A, 0xB7, 0x9E, 0x13, 0xB6, 0x62, 0xCC, 0x09, 0x76, 0x51, 0xFB, 0xB9, 0xB5, 0xF0, 0x63, 0x82, 0x91, 0x96, 0xCA, 0xFC, 0x88, 0xF3, 0x60, 0x50, 0x87, 0x56, 0x4C, 0x35, 0xD0, 0x11, 0xFB, 0x38, 0x7E, 0x85, 0xCF, 0xF2, 0x46, 0xDB, 0x7B, 0x4A, 0x55, 0x54, 0x15, 0x01, 0xF7, 0x3A, 0x0B, 0xF6, 0x89, 0x1E, 0x54, 0x5A, 0x13, 0x05, 0xFB, 0x19, 0x1F, 0x26, 0x3D, 0xE7, 0x19, 0xAA, 0xF7, 0x19, 0xF2, 0x97, 0x47, 0xB3, 0xBE, 0x79, 0xCA, 0x6E, 0x91, 0x5A, 0xC9, 0xB9, 0xA6, 0x83, 0xB8, 0x2A, 0x45, 0x1A, 0xA7, 0x17, 0x86, 0xBA, 0x48, 0x49, 0x62, 0x3C, 0x33, 0x11, 0x51, 0x97, 0x5F, 0xAA, 0xE5, 0x1E, 0x0B, 0x19, 0x0C, 0xE6, 0x80, 0x6A, 0x5A, 0xB1, 0xD6, 0xCE, 0xDB, 0x6E, 0xC0, 0x5D, 0x29, 0x04, 0x84, 0x56, 0xE3, 0x29, 0x7E, 0xAC, 0xE8, 0xEE, 0xB1, 0x91, 0x37, 0xEB, 0x98, 0x9C, 0xBD, 0x02, 0x6A, 0x78, 0x61, 0xB0, 0x79, 0x1A, 0x9F, 0x30, 0x86, 0xF6, 0x71, 0x5A, 0x5A, 0x12, 0xA1, 0x9E, 0xA1, 0x68, 0x03, 0xE5, 0x95, 0xA8, 0x38, 0x58, 0x87, 0x08, 0x57, 0x35, 0x32, 0x47, 0x3B, 0xFC, 0x02, 0x6F, 0xCE, 0x55, 0x61, 0xA3, 0x2A, 0x6B, 0x2F, 0xF8, 0xEE, 0x8D, 0xFA, 0x43, 0x33, 0x02, 0x63, 0x47, 0x02, 0x78, 0x5A, 0x7F, 0x64, 0x07, 0x92, 0xB7, 0x7C, 0x09, 0x7C, 0xFE, 0x2D, 0x1C, 0xFC, 0x77, 0x9F, 0x19, 0x20, 0xDD, 0x6D, 0x4C, 0xFE, 0x49, 0x09, 0x47, 0xCA, 0x9B, 0x1C, 0x8C, 0x1F, 0x37, 0xAC, 0x14, 0x85, 0x56, 0xC0, 0xFD, 0xD6, 0x01, 0xB3, 0x40, 0xA3, 0x1A, 0x32, 0x78, 0xA0, 0xDD, 0x21, 0x75, 0xBF, 0x24, 0xD2, 0x93, 0x85, 0xED, 0x22, 0xAD, 0x99, 0x91, 0x87, 0x4A, 0xEC, 0xC0, 0x6C, 0x71, 0x00, 0x76, 0x08, 0x23, 0xA2, 0xF3, 0xCF, 0x61 },
.access_desc_signature = { 0xAC, 0xE2, 0xA7, 0xC3, 0x00, 0xDE, 0xE8, 0xE9, 0xE0, 0x03, 0xB3, 0x54, 0x08, 0xA8, 0xF8, 0x3A, 0x2E, 0xD8, 0x10, 0x6B, 0xEC, 0xDC, 0x4E, 0xEE, 0x62, 0x10, 0x71, 0x49, 0xD4, 0x43, 0xB1, 0x0E, 0x6B, 0x8C, 0xD7, 0x54, 0xD5, 0x62, 0x28, 0x3F, 0xAA, 0xDE, 0xA9, 0x7D, 0xED, 0x37, 0x7C, 0xE7, 0x89, 0x0B, 0x02, 0xB2, 0x72, 0x4B, 0x17, 0xDB, 0xE2, 0xD3, 0x7C, 0x94, 0x12, 0x3F, 0x2E, 0xA1, 0x08, 0x99, 0xCC, 0x7F, 0x93, 0xE6, 0x38, 0xC9, 0x37, 0x84, 0xD7, 0x11, 0x9D, 0x02, 0x4D, 0x66, 0xB4, 0x70, 0x9F, 0xD8, 0xC6, 0xDD, 0xD5, 0x13, 0x52, 0xF0, 0xA6, 0x78, 0x8C, 0x8E, 0x15, 0xA0, 0xA1, 0xF3, 0xC4, 0xC3, 0x48, 0x45, 0xA5, 0xBE, 0xC9, 0x7A, 0x8B, 0xD3, 0x95, 0xA5, 0x4C, 0xF1, 0xB3, 0x0C, 0x6C, 0x76, 0xA7, 0x57, 0xA1, 0x77, 0xDF, 0x2F, 0xC8, 0x06, 0xA6, 0x0D, 0x1A, 0x09, 0xE4, 0x38, 0x64, 0x07, 0xBE, 0x6A, 0xD2, 0xA0, 0xC0, 0xEC, 0x09, 0x64, 0x9F, 0x0D, 0x93, 0x0C, 0x89, 0xA2, 0x71, 0xD6, 0xC6, 0xC2, 0x54, 0x79, 0x2A, 0xA4, 0x31, 0x28, 0x24, 0x1A, 0xF3, 0x56, 0x78, 0x63, 0x99, 0x97, 0xA5, 0xCE, 0x8F, 0x52, 0x7A, 0x79, 0x51, 0xEE, 0x4C, 0x8B, 0x00, 0x9D, 0x5C, 0x3E, 0xD5, 0xAA, 0x24, 0x9C, 0x94, 0xC6, 0xA3, 0x99, 0x1B, 0x2D, 0xD4, 0xFF, 0xB4, 0x25, 0x73, 0x13, 0x33, 0x9F, 0x03, 0x6F, 0x1E, 0x75, 0xC4, 0x70, 0xF4, 0x07, 0x4F, 0x18, 0xFE, 0xBD, 0x8F, 0x2C, 0x9B, 0x33, 0xD4, 0x30, 0xA7, 0x18, 0x4A, 0xF1, 0xA4, 0xDD, 0x78, 0x41, 0xA0, 0xB8, 0x02, 0x8D, 0x51, 0x96, 0xBE, 0xE7, 0x17, 0x94, 0x66, 0x65, 0x27, 0xF7, 0x69, 0x48, 0x7E, 0xA9, 0x08, 0x71, 0x20, 0x76, 0xB7, 0x8E, 0xD2, 0xBF, 0x5C, 0x7E, 0x5E, 0x06, 0x45, 0xAB, 0x7E, 0x2E }
},
{
.type = desc_Demo,
.fw_minor = 33,
.modulus = { 0xB5, 0x11, 0x8D, 0x9E, 0x2D, 0xDB, 0x70, 0x6D, 0x6E, 0xEE, 0xAA, 0x21, 0xE0, 0x4E, 0x80, 0x0A, 0x96, 0x4A, 0x10, 0xD0, 0x9C, 0xD7, 0xD9, 0xD4, 0x94, 0x87, 0x72, 0xA2, 0xAF, 0x02, 0xA0, 0x05, 0x2E, 0xBF, 0x17, 0xEB, 0xFE, 0x5B, 0x9F, 0xB7, 0x0B, 0x1E, 0x3E, 0xF9, 0xAC, 0xBC, 0x7B, 0xB1, 0x56, 0x10, 0x24, 0x5F, 0x57, 0x2C, 0x08, 0xD0, 0x14, 0x79, 0x83, 0x84, 0x6A, 0x45, 0x25, 0xEB, 0xD9, 0xBE, 0x02, 0x21, 0xF7, 0x35, 0xC2, 0x74, 0x57, 0xC5, 0xAC, 0x34, 0x05, 0xC6, 0x9E, 0x82, 0xB8, 0xED, 0x78, 0xC4, 0x3B, 0xFD, 0x23, 0x59, 0x54, 0xD2, 0x0A, 0x0B, 0x5B, 0x25, 0xC0, 0x71, 0xC3, 0x84, 0x3A, 0xA7, 0xF9, 0x99, 0x86, 0xD8, 0xFE, 0x60, 0x10, 0x85, 0x77, 0x57, 0x76, 0x0C, 0x25, 0xE1, 0x18, 0x18, 0x3B, 0x83, 0xFD, 0x36, 0x7C, 0x84, 0x58, 0xC2, 0xC4, 0x68, 0x4F, 0xD1, 0xD7, 0x0A, 0x88, 0xFD, 0xCA, 0x97, 0xA1, 0xE5, 0xCE, 0x72, 0x63, 0xCF, 0x74, 0xD0, 0x20, 0xD9, 0xDE, 0x3F, 0xBB, 0x11, 0xF9, 0x21, 0xAB, 0x3F, 0x54, 0x41, 0xA7, 0xAA, 0xCA, 0xFC, 0xE1, 0x1A, 0x8C, 0x12, 0xC9, 0x39, 0x13, 0x5A, 0x81, 0x29, 0x49, 0xE8, 0xFB, 0x48, 0xC9, 0x4D, 0x50, 0x87, 0xAE, 0x51, 0xFB, 0x94, 0xFC, 0xF0, 0x9C, 0x70, 0x1C, 0xE8, 0x6E, 0x44, 0x53, 0x1E, 0x2F, 0x27, 0x5C, 0xB8, 0xEC, 0xBE, 0xFC, 0xD9, 0x98, 0x6A, 0x08, 0xD0, 0x5C, 0x4D, 0x78, 0x2D, 0x4D, 0x07, 0xAD, 0x5E, 0xB8, 0x51, 0x40, 0xE2, 0x2A, 0x7F, 0xB1, 0x54, 0x47, 0x5C, 0x99, 0x12, 0xC2, 0x6D, 0x5E, 0xED, 0x25, 0x30, 0x6A, 0x99, 0xC5, 0x0D, 0x65, 0x83, 0x68, 0x3A, 0xFD, 0x82, 0x59, 0x0D, 0xCE, 0x0B, 0x49, 0xBE, 0x17, 0x46, 0x51, 0xA9, 0xB6, 0x54, 0xE1, 0x18, 0xBD, 0x49, 0xE6, 0x7F },
.priv_exponent = { 0x1D, 0x7B, 0x79, 0x32, 0xAB, 0x46, 0xD2, 0xBC, 0x8E, 0xD6, 0x7F, 0x8F, 0x3A, 0x85, 0xAD, 0xA5, 0x8B, 0xA9, 0x0D, 0xA9, 0xDA, 0x0F, 0xEF, 0x61, 0x04, 0xBA, 0x35, 0x39, 0x36, 0x03, 0xD8, 0x68, 0x5F, 0x9F, 0x2F, 0xD6, 0xF6, 0x38, 0x96, 0xFD, 0xE7, 0xEA, 0x89, 0xD8, 0x7F, 0x7E, 0xC5, 0x29, 0x2F, 0xD9, 0x3B, 0x02, 0xE7, 0x1F, 0xBD, 0x63, 0x9C, 0x21, 0xD8, 0xFF, 0x43, 0x8A, 0x74, 0xCD, 0x3D, 0x4C, 0x09, 0xEE, 0xDB, 0xE0, 0xBE, 0x03, 0xD1, 0x92, 0xD7, 0x22, 0x35, 0x5A, 0x8C, 0xCE, 0xBE, 0x2B, 0xB4, 0x81, 0x47, 0x3F, 0x45, 0x75, 0x33, 0x31, 0x6B, 0xFF, 0x43, 0x5D, 0x17, 0x43, 0xAE, 0xD1, 0x25, 0xF7, 0xD9, 0xD5, 0x5C, 0xB6, 0x92, 0x5C, 0xB3, 0xF3, 0xF7, 0x65, 0x9F, 0x4C, 0x05, 0x12, 0xEC, 0xA8, 0x6D, 0x70, 0x65, 0x57, 0x6C, 0xD8, 0xE3, 0xD6, 0xFA, 0xC1, 0xFD, 0x54, 0xE8, 0x34, 0x67, 0x4D, 0x0A, 0x14, 0x2F, 0xA3, 0xD4, 0x81, 0x8C, 0xC3, 0xD0, 0x8B, 0x09, 0x08, 0x90, 0x70, 0x68, 0xA0, 0x0E, 0xD1, 0x0B, 0xAA, 0x71, 0xEC, 0x9A, 0x1A, 0x83, 0xFF, 0xA1, 0x70, 0xEB, 0xAC, 0xF2, 0xE9, 0x80, 0xA1, 0xB8, 0x20, 0x31, 0x83, 0xF5, 0x37, 0x01, 0x72, 0x06, 0x50, 0x05, 0x3F, 0x14, 0xF9, 0x29, 0x48, 0x84, 0xA0, 0x0E, 0xF7, 0xB8, 0x1D, 0xA3, 0x36, 0x5A, 0x78, 0x6D, 0x83, 0x90, 0x27, 0xE3, 0x50, 0x49, 0x2F, 0x65, 0xE5, 0x61, 0xED, 0x65, 0xBE, 0xEA, 0x34, 0xA6, 0x6A, 0xEF, 0x49, 0xB4, 0xE0, 0xBC, 0xC2, 0xA5, 0xB8, 0xEB, 0xA9, 0x2F, 0xBA, 0x26, 0x76, 0xB2, 0x5A, 0x3A, 0x3B, 0xFD, 0xAD, 0xFB, 0xE4, 0x79, 0xE2, 0x85, 0x54, 0x5B, 0xAB, 0x1F, 0x0A, 0xE5, 0x8B, 0x77, 0x3A, 0x10, 0x98, 0x26, 0x74, 0xC8, 0xB0, 0x82, 0xB1, 0xF9, 0x8F, 0x68, 0x59 },
.access_desc_signature = { 0xD3, 0x7D, 0x42, 0xBA, 0x6A, 0x1E, 0xD8, 0x07, 0x3C, 0x4A, 0xC4, 0xCD, 0x8C, 0x68, 0x3D, 0xCD, 0xCD, 0xBD, 0x9D, 0xCE, 0xB5, 0x2A, 0xF9, 0x63, 0x3D, 0xA9, 0x54, 0x0A, 0x2E, 0x4C, 0xE1, 0x60, 0x4B, 0xD0, 0xC9, 0xEB, 0xEF, 0x31, 0x65, 0x70, 0xB9, 0x0E, 0x06, 0x3B, 0x3D, 0x42, 0x4C, 0x6E, 0x8D, 0x2C, 0xD4, 0x71, 0x29, 0x76, 0xB7, 0xDD, 0x8C, 0xDA, 0xE7, 0xE3, 0x96, 0xA7, 0xAA, 0xF8, 0xCA, 0x05, 0xE8, 0xA7, 0x0A, 0xDD, 0x01, 0x49, 0xBD, 0xF1, 0xA5, 0xE8, 0x16, 0x22, 0xEE, 0x47, 0x1F, 0xEF, 0x28, 0x48, 0x87, 0xA9, 0x2D, 0xFC, 0x4E, 0xD5, 0xA5, 0x98, 0xB1, 0xFE, 0x1B, 0xEB, 0xA9, 0x06, 0x3C, 0x76, 0xD9, 0xAA, 0x0E, 0x9C, 0x60, 0xFC, 0xE9, 0x77, 0x9D, 0x7F, 0x67, 0xAC, 0xF5, 0xC7, 0x49, 0x12, 0xFD, 0x76, 0xAC, 0xD2, 0x54, 0xDB, 0x73, 0x41, 0x10, 0x1F, 0x04, 0x3F, 0xD0, 0x6F, 0xE0, 0x80, 0x24, 0xCC, 0xEE, 0xBF, 0x25, 0x9D, 0x0D, 0x5A, 0x2A, 0x1C, 0xC5, 0xD4, 0xE3, 0x5D, 0x3A, 0xC1, 0x86, 0xD3, 0xD4, 0x52, 0x1C, 0x4C, 0xBF, 0x31, 0xEB, 0x54, 0xCA, 0x4C, 0x06, 0x50, 0x52, 0x87, 0xD4, 0x9D, 0x4A, 0x4B, 0x22, 0xE1, 0x4A, 0xE9, 0x4D, 0x05, 0xA8, 0x57, 0xEC, 0xF8, 0x90, 0xF8, 0x58, 0xC3, 0x8B, 0x3A, 0x0F, 0x88, 0x36, 0xF4, 0xE5, 0x44, 0x10, 0x80, 0x68, 0x86, 0x1D, 0xAE, 0x90, 0x20, 0x03, 0x22, 0x2D, 0x44, 0xBF, 0xAB, 0x2B, 0xA1, 0x14, 0xAD, 0x6B, 0x40, 0x57, 0xDB, 0xBB, 0xDA, 0x09, 0x4C, 0x51, 0x26, 0x9B, 0xE3, 0xD9, 0xF9, 0xE1, 0xBC, 0xF1, 0xF1, 0xCD, 0x30, 0xB4, 0xF5, 0x39, 0xD0, 0xBC, 0xF7, 0x98, 0x05, 0xAF, 0xA8, 0x33, 0x4B, 0xC1, 0x16, 0x0F, 0xF2, 0xC2, 0x79, 0x96, 0xEC, 0xBE, 0xA9, 0xF5, 0x55, 0x7C, 0x82, 0x95, 0x73 }
},
};
+132
View File
@@ -0,0 +1,132 @@
#pragma once
#include "desc.h"
static const CtrSdkDesc kDescPresets[] =
{
/* CTR_SDK 1 (1.2.0) (2.27 - 2.28) */
{
.type = desc_Application,
.fw_minor = 27,
.exheader_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
{
.type = desc_DlpChild,
.fw_minor = 27,
.exheader_desc = { 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
/* CTR_SDK 2 (2.3.4) */
{
.type = desc_Application,
.fw_minor = 29,
.exheader_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x1D, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x1D, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
{
.type = desc_DlpChild,
.fw_minor = 29,
.exheader_desc = { 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x1D, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x1D, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
{
.type = desc_Application,
.fw_minor = 30,
.exheader_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x1E, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x1E, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
{
.type = desc_Demo,
.fw_minor = 30,
.exheader_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x1E, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFB, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x1E, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
/* CTR_SDK 3 (3.2.5) (2.32) */
{
.type = desc_Application,
.fw_minor = 32,
.exheader_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x20, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x20, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
{
.type = desc_EcApplication,
.fw_minor = 32,
.exheader_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6E, 0x69, 0x6D, 0x3A, 0x61, 0x6F, 0x63, 0x00, 0x61, 0x6D, 0x3A, 0x61, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x20, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6E, 0x69, 0x6D, 0x3A, 0x61, 0x6F, 0x63, 0x00, 0x61, 0x6D, 0x3A, 0x61, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x20, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
/* CTR_SDK 4 (4.2.8) (2.33) */
{
.type = desc_Application,
.fw_minor = 33,
.exheader_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x21, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x21, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
{
.type = desc_DlpChild,
.fw_minor = 33,
.exheader_desc = { 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x21, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x21, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
{
.type = desc_Demo,
.fw_minor = 33,
.exheader_desc = { 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x21, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x21, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
/* CTR_SDK 5 (5.2.3) (2.35) */
{
.type = desc_Application,
.fw_minor = 35,
.exheader_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x23, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x23, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
{
.type = desc_EcApplication,
.fw_minor = 35,
.exheader_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6E, 0x69, 0x6D, 0x3A, 0x61, 0x6F, 0x63, 0x00, 0x61, 0x6D, 0x3A, 0x61, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x23, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6E, 0x69, 0x6D, 0x3A, 0x61, 0x6F, 0x63, 0x00, 0x61, 0x6D, 0x3A, 0x61, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x23, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
/* SDK 7 (7.1.0) (2.39) */
{
.type = desc_Application,
.fw_minor = 39,
.exheader_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x41, 0x00, 0x00, 0x00, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x74, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x61, 0x6D, 0x3A, 0x61, 0x70, 0x70, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x69, 0x6D, 0x3A, 0x61, 0x6F, 0x63, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x27, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.signed_desc = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x18, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x68, 0x69, 0x6F, 0x46, 0x49, 0x4F, 0x00, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x30, 0x24, 0x68, 0x6F, 0x73, 0x74, 0x69, 0x6F, 0x31, 0x63, 0x66, 0x67, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x66, 0x73, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x67, 0x73, 0x70, 0x3A, 0x3A, 0x47, 0x70, 0x75, 0x68, 0x69, 0x64, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x6E, 0x64, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x70, 0x78, 0x69, 0x3A, 0x64, 0x65, 0x76, 0x00, 0x41, 0x50, 0x54, 0x3A, 0x41, 0x00, 0x00, 0x00, 0x61, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x74, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x61, 0x6D, 0x3A, 0x61, 0x70, 0x70, 0x00, 0x00, 0x62, 0x6F, 0x73, 0x73, 0x3A, 0x55, 0x00, 0x00, 0x63, 0x61, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x63, 0x65, 0x63, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x64, 0x6C, 0x70, 0x3A, 0x46, 0x4B, 0x43, 0x4C, 0x64, 0x6C, 0x70, 0x3A, 0x53, 0x52, 0x56, 0x52, 0x64, 0x73, 0x70, 0x3A, 0x3A, 0x44, 0x53, 0x50, 0x66, 0x72, 0x64, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x43, 0x00, 0x00, 0x69, 0x72, 0x3A, 0x55, 0x53, 0x45, 0x52, 0x00, 0x6C, 0x64, 0x72, 0x3A, 0x72, 0x6F, 0x00, 0x00, 0x6D, 0x69, 0x63, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x6E, 0x65, 0x77, 0x73, 0x3A, 0x75, 0x00, 0x00, 0x6E, 0x69, 0x6D, 0x3A, 0x61, 0x6F, 0x63, 0x00, 0x6E, 0x77, 0x6D, 0x3A, 0x3A, 0x55, 0x44, 0x53, 0x70, 0x74, 0x6D, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x73, 0x6F, 0x63, 0x3A, 0x55, 0x00, 0x00, 0x00, 0x73, 0x73, 0x6C, 0x3A, 0x43, 0x00, 0x00, 0x00, 0x79, 0x32, 0x72, 0x3A, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x9F, 0xFA, 0xF0, 0xFF, 0xBF, 0xFF, 0xF1, 0xE7, 0x3F, 0x00, 0xF2, 0x00, 0xF0, 0x91, 0xFF, 0x00, 0xF6, 0x91, 0xFF, 0x50, 0xFF, 0x81, 0xFF, 0x58, 0xFF, 0x81, 0xFF, 0x70, 0xFF, 0x81, 0xFF, 0x78, 0xFF, 0x81, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x00, 0x02, 0x00, 0xFE, 0x27, 0x02, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
},
};
static const CtrSdkDepList kExheaderDependencyLists[] =
{
{
.fw_minor = 27,
.dependency = { 0x02, 0x24, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x15, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x34, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x16, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x26, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x17, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x18, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x27, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x28, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1A, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x32, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x29, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x20, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x35, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x21, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x31, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x22, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x23, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
},
{
.fw_minor = 28,
.dependency = { 0x02, 0x24, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x15, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x34, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x16, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x26, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x17, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x18, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x27, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x28, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1A, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x32, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x29, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x20, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x35, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x21, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x31, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x22, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x23, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
},
{
.fw_minor = 29,
.dependency = { 0x02, 0x24, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x15, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x34, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x16, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x26, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x17, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x18, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x27, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x28, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1A, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x32, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x29, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x20, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x35, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x21, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x31, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x22, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x23, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
},
{
.fw_minor = 30,
.dependency = { 0x02, 0x24, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x15, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x34, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x16, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x26, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x17, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x18, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x27, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x28, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1A, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x32, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x29, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x20, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x35, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x21, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x31, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x22, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x23, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
},
{
.fw_minor = 32,
.dependency = { 0x02, 0x24, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x15, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x34, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x16, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x26, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x17, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x18, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x27, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x28, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1A, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x32, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x29, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x33, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x20, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x35, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x21, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x31, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x22, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x37, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x23, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
},
{
.fw_minor = 33,
.dependency = { 0x02, 0x24, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x15, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x34, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x16, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x26, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x17, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x18, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x27, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x28, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1A, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x32, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x29, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x33, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x20, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x35, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x21, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x31, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x22, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x37, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x23, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
},
{
.fw_minor = 35,
.dependency = { 0x02, 0x24, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x15, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x34, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x16, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x26, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x17, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x18, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x27, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x28, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1A, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x32, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x29, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x33, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x20, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x35, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x21, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x31, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x22, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x37, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x23, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
},
{
.fw_minor = 39,
.dependency = { 0x02, 0x24, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x38, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x15, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x34, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x16, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x26, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x17, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x18, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x27, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x28, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1A, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x32, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x29, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x33, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x20, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2B, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x35, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2D, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x21, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x31, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x22, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x37, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2E, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x23, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x02, 0x2F, 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
}
};
+194
View File
@@ -0,0 +1,194 @@
#include "lib.h"
#include "elf.h"
static const u32 ELF_MAGIC = 0x7f454c46;
typedef enum elf_bit_format_types
{
elf_32_bit = 1,
elf_64_bit = 2,
} elf_bit_format_types;
typedef enum elf_endianness
{
elf_little_endian = 1,
elf_big_endian = 2,
} elf_endianness;
typedef enum elf_type
{
elf_relocatable = 1,
elf_executeable = 2,
elf_shared = 3,
elf_core = 4,
} elf_type;
typedef enum elf_target_architecture
{
elf_arm = 0x28,
} elf_target_architecture;
typedef struct elf_hdr
{
u8 magic[4];
u8 bitFormat;
u8 endianness;
u8 elfVersion;
u8 os;
u8 padding0[8];
u8 type[2];
u8 targetArchitecture[2];
u8 version[4];
u8 entryPoint[4];
u8 programHeaderTableOffset[4];
u8 sectionHeaderTableOffset[4];
u8 flags[4];
u8 headerSize[2];
u8 programHeaderEntrySize[2];
u8 programHeaderEntryCount[2];
u8 sectionTableEntrySize[2];
u8 sectionHeaderEntryCount[2];
u8 sectionHeaderNameEntryIndex[2];
} elf_hdr;
/* taken from elf specs, will not follow global style */
/* Section header. */
typedef struct elf_shdr
{
u8 name[4]; /* Section name (string tbl index) */
u8 type[4]; /* Section type */
u8 flags[4]; /* Section flags */
u8 addr[4]; /* Section virtual addr at execution */
u8 offset[4]; /* Section file offset */
u8 size[4]; /* Section size in bytes */
u8 link[4]; /* Link to another section */
u8 info[4]; /* Additional section information */
u8 addralign[4]; /* Section alignment */
u8 entsize[4]; /* Entry size if section holds table */
} elf_shdr;
/* Program segment header. */
typedef struct elf_phdr
{
u8 type[4]; /* Segment type */
u8 offset[4]; /* Segment file offset */
u8 vaddr[4]; /* Segment virtual address */
u8 paddr[4]; /* Segment physical address */
u8 filesz[4]; /* Segment size in file */
u8 memsz[4]; /* Segment size in memory */
u8 flags[4]; /* Segment flags */
u8 align[4]; /* Segment alignment */
} elf_phdr;
// ELF Functions
int elf_ProcessHeader(elf_context *elf)
{
const elf_hdr *hdr = (const elf_hdr*)elf->file;
/* Check conditions for valid CTR ELF */
if (u8_to_u32(hdr->magic, BE) != ELF_MAGIC)
return NOT_ELF_FILE;
if (hdr->bitFormat != elf_32_bit)
return NOT_CTR_ARM_ELF;
if (hdr->endianness != elf_little_endian)
return NOT_CTR_ARM_ELF;
if (u8_to_u16(hdr->targetArchitecture, LE) != elf_arm)
return NOT_CTR_ARM_ELF;
if (u8_to_u16(hdr->type, LE) != elf_executeable)
return NON_EXECUTABLE_ELF;
elf->phdrOffset = u8_to_u32(hdr->programHeaderTableOffset, LE);
elf->segmentNum = u8_to_u16(hdr->programHeaderEntryCount, LE);
elf->segments = calloc(elf->segmentNum, sizeof(elf_segment));
if (!elf->segments) {
fprintf(stderr, "[ELF ERROR] Not enough memory\n");
return MEM_ERROR;
}
elf->shdrOffset = u8_to_u32(hdr->sectionHeaderTableOffset, LE);
elf->shdrNameIndex = u8_to_u16(hdr->sectionHeaderNameEntryIndex, LE);
elf->sectionNum = u8_to_u16(hdr->sectionHeaderEntryCount, LE);
elf->sections = calloc(elf->sectionNum, sizeof(elf_section));
if (!elf->sections) {
fprintf(stderr, "[ELF ERROR] Not enough memory\n");
return MEM_ERROR;
}
return 0;
}
void elf_PopulateSections(elf_context *elf)
{
const elf_shdr *shdr = (const elf_shdr *)(elf->file + elf->shdrOffset);
const char *nameTable = (const char*)(elf->file + u8_to_u32(shdr[elf->shdrNameIndex].offset, LE));
for (int i = 0; i < elf->sectionNum; i++) {
elf->sections[i].name = nameTable + u8_to_u32(shdr[i].name, LE);
elf->sections[i].type = u8_to_u32(shdr[i].type, LE);
elf->sections[i].flags = u8_to_u32(shdr[i].flags, LE);
elf->sections[i].fileOffset = u8_to_u32(shdr[i].offset, LE);
elf->sections[i].size = u8_to_u32(shdr[i].size, LE);
elf->sections[i].ptr = elf->file + elf->sections[i].fileOffset;
elf->sections[i].vAddr = u8_to_u32(shdr[i].addr, LE);
elf->sections[i].alignment = u8_to_u32(shdr[i].addralign, LE);
}
}
void elf_PopulateSegments(elf_context *elf)
{
const elf_phdr *phdr = (const elf_phdr *)(elf->file + elf->phdrOffset);
for (int i = 0; i < elf->segmentNum; i++) {
elf->segments[i].type = u8_to_u32(phdr[i].type, LE);
elf->segments[i].flags = u8_to_u32(phdr[i].flags, LE);
elf->segments[i].fileOffset = u8_to_u32(phdr[i].offset, LE);
elf->segments[i].fileSize = u8_to_u32(phdr[i].filesz, LE);
elf->segments[i].ptr = elf->file + elf->segments[i].fileOffset;
elf->segments[i].pAddr = u8_to_u32(phdr[i].paddr, LE);
elf->segments[i].vAddr = u8_to_u32(phdr[i].vaddr, LE);
elf->segments[i].memSize = u8_to_u32(phdr[i].memsz, LE);
elf->segments[i].alignment = u8_to_u32(phdr[i].align, LE);
}
}
int elf_Init(elf_context *elf, const u8 *elfFile)
{
elf->file = elfFile;
int result;
if((result = elf_ProcessHeader(elf))) return result;
elf_PopulateSections(elf);
elf_PopulateSegments(elf);
return 0;
}
void elf_Free(elf_context *elf)
{
free(elf->sections);
free(elf->segments);
memset(elf, 0, sizeof(elf_context));
}
u16 elf_SectionNum(elf_context *ctx)
{
return ctx->sectionNum;
}
const elf_section* elf_GetSections(elf_context *ctx)
{
return ctx->sections;
}
u16 elf_SegmentNum(elf_context *ctx)
{
return ctx->segmentNum;
}
const elf_segment* elf_GetSegments(elf_context *ctx)
{
return ctx->segments;
}
+130
View File
@@ -0,0 +1,130 @@
#pragma once
typedef enum elf_errors
{
NOT_ELF_FILE = -10,
NOT_CTR_ARM_ELF = -11,
NON_EXECUTABLE_ELF = -12,
ELF_SECTION_NOT_FOUND = -13,
NOT_FIND_TEXT_SEGMENT = -14,
NOT_FIND_DATA_SEGMENT = -15,
ELF_SEGMENT_SECTION_SIZE_MISMATCH = -16,
ELF_SEGMENTS_NOT_CONTINUOUS = -17,
ELF_SEGMENTS_NOT_FOUND = -18,
} elf_errors;
typedef enum elf_section_type
{
SHT_NULL,
SHT_PROGBITS,
SHT_SYMTAB,
SHT_STRTAB,
SHT_RELA,
SHT_HASH,
SHT_DYNAMIC,
SHT_NOTE,
SHT_NOBITS,
SHT_REL,
SHT_SHLIB,
SHT_DYNSYM,
SHT_UNKNOWN12,
SHT_UNKNOWN13,
SHT_INIT_ARRAY,
SHT_FINI_ARRAY,
SHT_PREINIT_ARRAY,
SHT_GROUP,
SHT_SYMTAB_SHNDX,
SHT_NUM,
SHT_ARM_EXIDX = 0x70000001,
SHT_ARM_PREEMPTMAP,
SHT_ARM_ATTRIBUTES,
SHT_ARM_DEBUGOVERLAY,
SHT_ARM_OVERLAYSECTION
} elf_section_type;
typedef enum elf_section_flag
{
SHF_WRITE = 0x1,
SHF_ALLOC = 0x2,
SHF_EXECINSTR = 0x4,
SHF_MERGE = 0x10,
SHF_STRINGS = 0x20,
SHF_INFO_LINK = 0x40,
SHF_LINK_ORDER = 0x80,
SHF_OS_NONCONFORMING = 0x100,
SHF_GROUP = 0x200,
SHF_TLS = 0x400
} elf_section_flag;
typedef struct elf_section
{
const char *name;
u32 type;
u32 flags;
const u8 *ptr;
u32 fileOffset;
u32 size;
u32 vAddr;
u32 alignment;
} elf_section;
typedef enum elf_program_type
{
PT_NULL,
PT_LOAD,
PT_DYNAMIC,
PT_INTERP,
PT_NOTE,
PT_SHLIB,
PT_PHDR,
} elf_program_type;
typedef enum elf_program_flag
{
PF_X = 0x1,
PF_W = 0x2,
PF_R = 0x4,
PF_CTRSDK = 0x80000000,
PF_TEXT = (PF_R|PF_X),
PF_DATA = (PF_R|PF_W),
PF_RODATA = PF_R
} elf_program_flag;
typedef struct elf_segment
{
u32 type;
u32 flags;
const u8 *ptr;
u32 fileOffset;
u32 fileSize;
u32 memSize;
u32 vAddr;
u32 pAddr;
u32 alignment;
} elf_segment;
typedef struct elf_context
{
const u8 *file;
u32 shdrOffset;
u16 shdrNameIndex;
u32 phdrOffset;
u16 sectionNum;
elf_section *sections;
u16 segmentNum;
elf_segment *segments;
} elf_context;
int elf_Init(elf_context *ctx, const u8 *fp);
void elf_Free(elf_context *ctx);
u16 elf_SectionNum(elf_context *ctx);
const elf_section* elf_GetSections(elf_context *ctx);
u16 elf_SegmentNum(elf_context *ctx);
const elf_segment* elf_GetSegments(elf_context *ctx);
+179
View File
@@ -0,0 +1,179 @@
#include "lib.h"
#include "ncch_build.h"
#include "exefs_build.h"
// Private Prototypes
u32 PredictExeFS_Size(exefs_buildctx *ctx);
int GenerateExeFS_Header(exefs_buildctx *ctx, u8 *outbuff);
void FreeExeFSContext(exefs_buildctx *ctx);
int ImportDatatoExeFS(exefs_buildctx *ctx, u8 *outbuff);
int ImportToExeFSContext(exefs_buildctx *ctx, char *name, u8 *buffer, u32 size);
// ExeFs Build Functions
int BuildExeFs(ncch_settings *ncchset)
{
/* Intialising ExeFs Build Context */
exefs_buildctx *ctx = calloc(1,sizeof(exefs_buildctx));
if(!ctx) {
fprintf(stderr,"[EXEFS ERROR] Not enough memory\n");
return MEM_ERROR;
}
ctx->blockSize = ncchset->options.blockSize;
/* Importing ExeFs */
if(ncchset->exefsSections.code.size)
ImportToExeFSContext(ctx,".code",ncchset->exefsSections.code.buffer,ncchset->exefsSections.code.size);
if(ncchset->exefsSections.banner.size)
ImportToExeFSContext(ctx,"banner",ncchset->exefsSections.banner.buffer,ncchset->exefsSections.banner.size);
if(ncchset->exefsSections.icon.size)
ImportToExeFSContext(ctx,"icon",ncchset->exefsSections.icon.buffer,ncchset->exefsSections.icon.size);
if(ncchset->sections.logo.size && ncchset->options.IncludeExeFsLogo)
ImportToExeFSContext(ctx,"logo",ncchset->sections.logo.buffer,ncchset->sections.logo.size);
if(ctx->fileCount == 0){ // no exefs needed
ncchset->sections.exeFs.size = 0;
ncchset->sections.exeFs.buffer = NULL;
return 0;
}
/* Allocating Memory for ExeFs */
ncchset->sections.exeFs.size = PredictExeFS_Size(ctx);
ncchset->sections.exeFs.buffer = malloc(ncchset->sections.exeFs.size);
if(!ncchset->sections.exeFs.buffer){
printf("[EXEFS ERROR] Could Not Allocate Memory for ExeFS\n");
return Fail;
}
memset(ncchset->sections.exeFs.buffer,0,ncchset->sections.exeFs.size);
/* Generating Header, and writing sections to buffer */
GenerateExeFS_Header(ctx,ncchset->sections.exeFs.buffer);
ImportDatatoExeFS(ctx,ncchset->sections.exeFs.buffer);
/* Finish */
FreeExeFSContext(ctx);
return 0;
}
u32 PredictExeFS_Size(exefs_buildctx *ctx)
{
u32 exefs_size = sizeof(exefs_hdr); // Size of header
for(int i = 0; i < ctx->fileCount; i++)
exefs_size += align(ctx->fileSize[i],ctx->blockSize);
//exefs_size = align(ctx->exefs_size,ctx->mediaUnit);
return exefs_size;
}
int GenerateExeFS_Header(exefs_buildctx *ctx, u8 *outbuff)
{
exefs_hdr *exefs = (exefs_hdr*)outbuff;
for(int i = 0; i < ctx->fileCount; i++){
if(i == 0)
ctx->fileOffset[i] = 0;
else
ctx->fileOffset[i] = align((ctx->fileOffset[i-1]+ctx->fileSize[i-1]),ctx->blockSize);
memcpy(exefs->fileHdr[i].name,ctx->fileName[i],8);
u32_to_u8(exefs->fileHdr[i].offset,ctx->fileOffset[i],LE);
u32_to_u8(exefs->fileHdr[i].size,ctx->fileSize[i],LE);
ShaCalc(ctx->file[i],ctx->fileSize[i],exefs->fileHashes[MAX_EXEFS_SECTIONS-1-i],CTR_SHA_256);
}
return 0;
}
void FreeExeFSContext(exefs_buildctx *ctx)
{
/*
if(ctx->outbuff != NULL)
free(ctx->outbuff);
for(int i = 0; i < 10; i++){
if(ctx->file[i] != NULL)
free(ctx->file[i]);
}
*/
memset(ctx,0,sizeof(exefs_buildctx));
free(ctx);
}
int ImportDatatoExeFS(exefs_buildctx *ctx, u8 *outbuff)
{
for(int i = 0; i < ctx->fileCount; i++){
memcpy(outbuff+ctx->fileOffset[i]+0x200,ctx->file[i],ctx->fileSize[i]);
}
return 0;
}
int ImportToExeFSContext(exefs_buildctx *ctx, char *name, u8 *buffer, u32 size)
{
if(ctx == NULL || name == NULL || buffer == NULL){
printf("[!] PTR ERROR\n");
return PTR_ERROR;
}
if(ctx->fileCount >= MAX_EXEFS_SECTIONS){
printf("[!] Maximum ExeFS Capacity Reached\n");
return EXEFS_MAX_REACHED;
}
if(strlen(name) > 8){
printf("[!] ExeFS File Name: '%s' is too large\n",name);
return EXEFS_SECTION_NAME_ERROR;
}
ctx->fileCount++;
ctx->file[ctx->fileCount - 1] = buffer;
ctx->fileSize[ctx->fileCount - 1] = size;
strcpy(ctx->fileName[ctx->fileCount - 1],name);
return 0;
}
// ExeFs Read Functions
bool DoesExeFsSectionExist(char *section, u8 *ExeFs)
{
exefs_hdr *hdr = (exefs_hdr*) ExeFs;
for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
if(strncmp(hdr->fileHdr[i].name,section,8) == 0) return true;
}
return false;
}
u8* GetExeFsSection(char *section, u8 *ExeFs)
{
exefs_hdr *hdr = (exefs_hdr*) ExeFs;
for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
if(strncmp(hdr->fileHdr[i].name,section,8) == 0){
u32 offset = u8_to_u32(hdr->fileHdr[i].offset,LE) + sizeof(exefs_hdr);
return (u8*)(ExeFs+offset);
}
}
return NULL;
}
u8* GetExeFsSectionHash(char *section, u8 *ExeFs)
{
exefs_hdr *hdr = (exefs_hdr*) ExeFs;
for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
if(strncmp(hdr->fileHdr[i].name,section,8) == 0){
return (u8*)(hdr->fileHashes[MAX_EXEFS_SECTIONS-1-i]);
}
}
return NULL;
}
u32 GetExeFsSectionSize(char *section, u8 *ExeFs)
{
exefs_hdr *hdr = (exefs_hdr*) ExeFs;
for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
if(strncmp(hdr->fileHdr[i].name,section,8) == 0){
return u8_to_u32(hdr->fileHdr[i].size,LE);
}
}
return 0;
}
u32 GetExeFsSectionOffset(char *section, u8 *ExeFs)
{
exefs_hdr *hdr = (exefs_hdr*) ExeFs;
for(int i = 0; i < MAX_EXEFS_SECTIONS; i++){
if(strncmp(hdr->fileHdr[i].name,section,8) == 0){
return u8_to_u32(hdr->fileHdr[i].offset,LE) + sizeof(exefs_hdr);
}
}
return 0;
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#define MAX_EXEFS_SECTIONS 8
typedef struct
{
char name[8];
u8 offset[4];
u8 size[4];
} exefs_filehdr;
typedef struct
{
exefs_filehdr fileHdr[MAX_EXEFS_SECTIONS];
u8 reserved[0x80];
u8 fileHashes[MAX_EXEFS_SECTIONS][0x20];
} exefs_hdr;
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include "exefs.h"
typedef enum
{
PTR_ERROR = -10,
EXEFS_MAX_REACHED = -11,
EXEFS_SECTION_NAME_ERROR = -12,
} exefs_errors;
typedef struct
{
//Input
int fileCount;
u8 *file[MAX_EXEFS_SECTIONS];
u32 fileSize[MAX_EXEFS_SECTIONS];
u32 fileOffset[MAX_EXEFS_SECTIONS];
char fileName[MAX_EXEFS_SECTIONS][8];
u32 blockSize;
//Working Data
exefs_filehdr fileHdr[MAX_EXEFS_SECTIONS];
u8 fileHashes[MAX_EXEFS_SECTIONS][0x20];
} exefs_buildctx;
/* ExeFs Build Functions */
int BuildExeFs(ncch_settings *ncchset);
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "exefs.h"
/* ExeFs Read Functions */
bool DoesExeFsSectionExist(char *section, u8 *ExeFs);
u8* GetExeFsSection(char *section, u8 *ExeFs);
u8* GetExeFsSectionHash(char *section, u8 *ExeFs);
u32 GetExeFsSectionSize(char *section, u8 *ExeFs);
u32 GetExeFsSectionOffset(char *section, u8 *ExeFs);
File diff suppressed because it is too large Load Diff
+248
View File
@@ -0,0 +1,248 @@
#pragma once
typedef enum
{
infoflag_COMPRESS_EXEFS_0 = 1,
infoflag_SD_APPLICATION = 2,
} system_info_flags;
typedef enum
{
sysmode_64MB, // prod
sysmode_UNK, // null
sysmode_96MB, // dev1
sysmode_80MB, // dev2
sysmode_72MB, // dev3
sysmode_32MB, // dev4
} system_mode;
typedef enum
{
sysmode_ext_LEGACY,
sysmode_ext_124MB, // snake Prod
sysmode_ext_178MB, // snake Dev1
} system_mode_ext;
typedef enum
{
memtype_APPLICATION = 1,
memtype_SYSTEM = 2,
memtype_BASE = 3
} memory_type;
typedef enum
{
processtype_DEFAULT = -1,
processtype_SYSTEM = 0,
processtype_APPLICATION = 1
} process_type;
typedef enum
{
resrc_limit_APPLICATION,
resrc_limit_SYS_APPLET,
resrc_limit_LIB_APPLET,
resrc_limit_OTHER
} resource_limit_category;
typedef enum
{
cpuspeed_268MHz,
cpuspeed_804MHz
} cpu_speed;
typedef enum
{
othcap_PERMIT_DEBUG = (1 << 0),
othcap_FORCE_DEBUG = (1 << 1),
othcap_CAN_USE_NON_ALPHABET_AND_NUMBER = (1 << 2),
othcap_CAN_WRITE_SHARED_PAGE = (1 << 3),
othcap_CAN_USE_PRIVILEGE_PRIORITY = (1 << 4),
othcap_PERMIT_MAIN_FUNCTION_ARGUMENT = (1 << 5),
othcap_CAN_SHARE_DEVICE_MEMORY = (1 << 6),
othcap_RUNNABLE_ON_SLEEP = (1 << 7),
othcap_SPECIAL_MEMORY_ARRANGE = (1 << 12),
othcap_CAN_ACCESS_CORE2 = (1 << 13),
} other_capabilities_flags;
typedef enum
{
fsaccess_CATEGORY_SYSTEM_APPLICATION = (1 << 0), // 0x00000001 used by all sys apps?
fsaccess_CATEGORY_HARDWARE_CHECK = (1 << 1), // 0x00000002
fsaccess_CATEGORY_FILE_SYSTEM_TOOL = (1 << 2), // 0x00000004
fsaccess_DEBUG = (1 << 3), // 0x00000008
fsaccess_TWL_CARD_BACKUP = (1 << 4), // 0x00000010
fsaccess_TWL_NAND_DATA = (1 << 5), // 0x00000020
fsaccess_BOSS = (1 << 6), // 0x00000040
fsaccess_DIRECT_SDMC = (1 << 7), // 0x00000080
fsaccess_CORE = (1 << 8), // 0x00000100
fsaccess_CTR_NAND_RO = (1 << 9), // 0x00000200
fsaccess_CTR_NAND_RW = (1 << 10), // 0x00000400
fsaccess_CTR_NAND_RO_WRITE = (1 << 11), // 0x00000800
fsaccess_CATEGORY_SYSTEM_SETTINGS = (1 << 12), // 0x00001000
fsaccess_CARD_BOARD = (1 << 13), // 0x00002000 probably used by sys transfer
fsaccess_EXPORT_IMPORT_IVS = (1 << 14), // 0x00004000
fsaccess_DIRECT_SDMC_WRITE = (1 << 15), // 0x00008000
fsaccess_SWITCH_CLEANUP = (1 << 16), // 0x00010000 reference to Sys Transfer?
fsaccess_SAVE_DATA_MOVE = (1 << 17), // 0x00020000 used by save transfer tool
fsaccess_SHOP = (1 << 18), // 0x00040000 probably used by eshop
fsaccess_SHELL = (1 << 19), // 0x00080000 reference to "Nintendo [User Interface] Shell" (NS)?
fsaccess_CATEGORY_HOME_MENU = (1 << 20), // 0x00100000 used by homemenu
fsaccess_SEEDDB = (1 << 21), // 0x00200000 seeddb access
} file_system_access;
typedef enum
{
attribute_NOT_USE_ROMFS = (1 << 0),
attribute_USE_EXTENDED_SAVEDATA_ACCESS_CONTROL = (1 << 1),
} attribute_name;
typedef enum
{
arm9cap_FS_MOUNT_NAND = (1 << 0),
arm9cap_FS_MOUNT_NAND_RO_WRITE = (1 << 1),
arm9cap_FS_MOUNT_TWLN = (1 << 2),
arm9cap_FS_MOUNT_WNAND = (1 << 3),
arm9cap_FS_MOUNT_CARD_SPI = (1 << 4),
arm9cap_USE_SDIF3 = (1 << 5),
arm9cap_CREATE_SEED = (1 << 6),
arm9cap_USE_CARD_SPI = (1 << 7),
arm9cap_SD_APPLICATION = (1 << 8),
arm9cap_USE_DIRECT_SDMC = (1 << 9),
} arm9_capability;
typedef struct
{
u8 address[4]; // le u32
u8 numMaxPages[4]; // le u32
u8 codeSize[4]; // le u32
} exhdr_CodeSegmentInfo;
typedef struct
{
u8 name[8];
u8 padding0[5];
union {
u8 flag;
struct {
u8 compressExeFs0 : 1;
u8 useOnSd : 1;
};
};
u8 remasterVersion[2]; // le u16
exhdr_CodeSegmentInfo text;
u8 stackSize[4]; // le u32
exhdr_CodeSegmentInfo rodata;
u8 padding1[4];
exhdr_CodeSegmentInfo data;
u8 bssSize[4]; // le u32
} exhdr_CodeSetInfo;
typedef struct
{
u8 savedataSize[8];
u8 jumpId[8];
u8 padding0[0x30];
} exhdr_SystemInfo;
typedef struct
{
u8 extSavedataId[8];
u8 systemSavedataId[2][4];
u8 storageAccessableUniqueIds[8];
u8 accessInfo[7];
u8 otherAttributes;
} exhdr_StorageInfo;
typedef struct
{
u8 programId[8];
u8 coreVersion[4];
union {
u8 flag[4];
struct {
u8 enableL2Cache : 1;
u8 cpuSpeed : 1;
u8: 6;
u8 systemModeExt : 4;
u8: 4;
u8 idealProcessor : 2;
u8 affinityMask : 2;
u8 systemMode : 4;
s8 threadPriority;
};
};
u8 resourceLimitDescriptor[16][2];
exhdr_StorageInfo storageInfo;
u8 serviceAccessControl[34][8]; // Those char[8] server names
u8 padding1[0xf];
u8 resourceLimitCategory;
} exhdr_ARM11SystemLocalCapabilities;
typedef struct
{
u16 num;
u32 *data;
} ARM11KernelCapabilityDescriptor;
typedef enum
{
desc_InteruptNumList = 0xe0000000,
desc_SysCallControl = 0xf0000000,
desc_KernelReleaseVersion = 0xfc000000,
desc_HandleTableSize = 0xfe000000,
desc_OtherCapabilities = 0xff000000,
desc_MappingStatic = 0xff800000,
desc_MappingIO = 0xffc00000,
} ARM11KernelCapabilityDescriptorBitmask;
typedef struct
{
u8 descriptors[28][4];// Descripters are a collection of u32s, with bitmask idents so they can be identified, 'no matter the pos'
u8 reserved[0x10];
} exhdr_ARM11KernelCapabilities;
typedef struct
{
u8 descriptors[16]; //descriptors[15] = DescVersion
} exhdr_ARM9AccessControlInfo;
typedef struct
{
// systemcontrol info {
// coreinfo {
exhdr_CodeSetInfo codeSetInfo;
u8 dependencyList[0x30][8];
// }
exhdr_SystemInfo systemInfo;
// }
// accesscontrolinfo {
exhdr_ARM11SystemLocalCapabilities arm11SystemLocalCapabilities;
exhdr_ARM11KernelCapabilities arm11KernelCapabilities;
exhdr_ARM9AccessControlInfo arm9AccessControlInfo;
// }
} extended_hdr;
typedef struct
{
u8 signature[0x100];
u8 ncchRsaPubKey[0x100];
exhdr_ARM11SystemLocalCapabilities arm11SystemLocalCapabilities;
exhdr_ARM11KernelCapabilities arm11KernelCapabilities;
exhdr_ARM9AccessControlInfo arm9AccessControlInfo;
} access_descriptor;
/* ExHeader Signature Functions */
int SignAccessDesc(access_descriptor *acexDesc, keys_struct *keys);
int CheckAccessDescSignature(access_descriptor *acexDesc, keys_struct *keys);
/* ExHeader Settings Read from Rsf */
int GetSaveDataSizeFromString(u64 *out, char *string, char *moduleName);
int GetRemasterVersion_rsf(u16 *RemasterVersion, user_settings *usrset);
void ErrorParamNotFound(char *string);
void WarnParamNotFound(char *string);
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "exheader.h"
typedef enum
{
COMMON_HEADER_KEY_NOT_FOUND = -10,
EXHDR_BAD_RSF_OPT = -11,
CANNOT_SIGN_ACCESSDESC = -12
} exheader_errors;
typedef struct
{
keys_struct *keys;
rsf_settings *rsf;
bool useAccessDescPreset;
/* Output, these ptrs where created originally in ncchset */
extended_hdr *exHdr;
access_descriptor *acexDesc;
} exheader_settings;
/* ExHeader Build Functions */
int BuildExHeader(ncch_settings *ncchset);
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include "exheader.h"
/* ExHeader Binary Print Functions */
void exhdr_Print_ServiceAccessControl(extended_hdr *hdr);
/* ExHeader Binary Read Functions */
u8* GetAcexRsaSig(access_descriptor *acexDesc);
u8* GetAcexNcchPubKey(access_descriptor *acexDesc);
u16 GetRemasterVersion_frm_exhdr(extended_hdr *hdr);
u64 GetSaveDataSize_frm_exhdr(extended_hdr *hdr);
int GetDependencyList_frm_exhdr(u8 *Dest,extended_hdr *hdr);
void GetCoreVersion_frm_exhdr(u8 *Dest, extended_hdr *hdr);
+418
View File
@@ -0,0 +1,418 @@
#include "lib.h"
#include "aes_keygen.h"
// KeyData
#include "pki/test.h" // Test PKI
#include "pki/prod.h" // Production PKI
#include "pki/dev.h" // Development PKI
// Private Prototypes
int SetRsaKeySet(u8 **priv_exp_dst, const u8 *priv_exp_src, u8 **modulus_dst, const u8 *modulus_src);
void InitCommonKeySlots(keys_struct *keys);
void InitNcchKeyXSlots(keys_struct *keys);
int SetNcchKeyX(keys_struct *keys, const u8 *keyX, u8 index);
void keysetOpenError(char *file);
FILE* keyset_OpenFile(char *dir, char *name, bool FileRequired);
int SetCaCert(keys_struct *keys, const u8 *cert);
int SetTikCert(keys_struct *keys, const u8 *cert);
int SetTmdCert(keys_struct *keys, const u8 *cert);
int LoadKeysFromResources(keys_struct *keys);
void SetDummyRsaData(keys_struct *keys);
int LoadKeysFromKeyfile(keys_struct *keys);
void DumpKeyset(keys_struct *keys);
// Code
void InitKeys(keys_struct *keys)
{
memset(keys,0,sizeof(keys_struct));
InitCommonKeySlots(keys);
InitNcchKeyXSlots(keys);
Rsa2048Key_Alloc(&keys->rsa.xs);
Rsa2048Key_Alloc(&keys->rsa.cp);
Rsa2048Key_Alloc(&keys->rsa.cciCfa);
Rsa2048Key_Alloc(&keys->rsa.acex);
Rsa2048Key_Alloc(&keys->rsa.cxi);
keys->aes.ncchKey0 = malloc(AES_128_KEY_SIZE);
keys->aes.ncchKey1 = malloc(AES_128_KEY_SIZE);
}
void PrintBadKeySize(char *path, u32 size)
{
fprintf(stderr,"[KEYSET ERROR] %s has invalid size (0x%x)\n",path,size);
}
int SetKeys(keys_struct *keys)
{
if (LoadKeysFromResources(keys) != 0)
{
return KEYSET_ERROR;
}
if (!keys->keysetLoaded)
{
return KEYSET_ERROR;
}
if (keys->dumpkeys)
{
DumpKeyset(keys);
}
return 0;
}
int LoadKeysFromResources(keys_struct *keys)
{
if(keys->keyset == pki_TEST){
keys->keysetLoaded = true;
/* AES Keys */
// CIA
//SetCommonKey(keys, zeros_aesKey,1);
if(keys->aes.currentCommonKey > MAX_CMN_KEY)
SetCurrentCommonKey(keys,0);
// NCCH
SetNormalKey(keys,zeros_aesKey);
SetSystemFixedKey(keys,zeros_aesKey);
// CCI
SetCciInitialDataKeyX(keys, zeros_aesKey);
/* RSA Keys */
// CIA
Rsa2048Key_Set(&keys->rsa.xs, tpki_rsa.priv_exponent, tpki_rsa.modulus);
Rsa2048Key_Set(&keys->rsa.cp, tpki_rsa.priv_exponent, tpki_rsa.modulus);
// CCI/CFA
Rsa2048Key_Set(&keys->rsa.cciCfa, tpki_rsa.priv_exponent, tpki_rsa.modulus);
// CXI
Rsa2048Key_Set(&keys->rsa.acex, tpki_rsa.priv_exponent, tpki_rsa.modulus);
/* Certs */
SetCaCert(keys, ca3_tpki_cert);
SetTikCert(keys, xsC_tpki_cert);
SetTmdCert(keys, cpB_tpki_cert);
}
else if(keys->keyset == pki_DEVELOPMENT){
keys->keysetLoaded = true;
/* AES Keys */
// CIA
for(int i = 0; i < 6; i++)
SetCommonKey(keys, ctr_common_etd_key_dpki[i],i);
if(keys->aes.currentCommonKey > MAX_CMN_KEY)
SetCurrentCommonKey(keys,0);
// NCCH
SetNormalKey(keys, dev_fixed_ncch_key[0]);
SetSystemFixedKey(keys, dev_fixed_ncch_key[1]);
for(int i = 0; i < 4; i++)
SetNcchKeyX(keys, dev_unfixed_ncch_keyX[i],i);
// CCI
SetCciInitialDataKeyX(keys, dev_initial_data_keyx);
/* RSA Keys */
// CIA
Rsa2048Key_Set(&keys->rsa.xs, xs9_dpki_rsa.priv_exponent, xs9_dpki_rsa.modulus);
Rsa2048Key_Set(&keys->rsa.cp, cpA_dpki_rsa.priv_exponent, cpA_dpki_rsa.modulus);
// CCI/CFA
Rsa2048Key_Set(&keys->rsa.cciCfa, dev_ncsd_cfa_rsa.priv_exponent, dev_ncsd_cfa_rsa.modulus);
// CXI
Rsa2048Key_Set(&keys->rsa.acex, dev_accessdesc_rsa.priv_exponent, dev_accessdesc_rsa.modulus);
/* Certs */
SetCaCert(keys, ca4_dpki_cert);
SetTikCert(keys, xs9_dpki_cert);
SetTmdCert(keys, cpA_dpki_cert);
}
else if(keys->keyset == pki_PRODUCTION){
keys->keysetLoaded = true;
/* AES Keys */
// CIA
for (int i = 0; i < 6; i++)
SetCommonKey(keys, ctr_common_etd_key_ppki[i], i);
if(keys->aes.currentCommonKey > MAX_CMN_KEY)
SetCurrentCommonKey(keys,0);
// NCCH
keys->aes.normalKey = NULL;
keys->aes.systemFixedKey = NULL;
for(int i = 0; i < 4; i++)
SetNcchKeyX(keys, prod_unfixed_ncch_keyX[i],i);
// CCI
SetCciInitialDataKeyX(keys, dev_initial_data_keyx);
/* RSA Keys */
// CIA
Rsa2048Key_Set(&keys->rsa.xs, xsC_ppki_rsa.priv_exponent, xsC_ppki_rsa.modulus);
Rsa2048Key_Set(&keys->rsa.cp, cpB_ppki_rsa.priv_exponent, cpB_ppki_rsa.modulus);
// CCI/CFA
Rsa2048Key_Set(&keys->rsa.cciCfa, prod_ncsd_cfa_rsa.priv_exponent, prod_ncsd_cfa_rsa.modulus);
// CXI
Rsa2048Key_Set(&keys->rsa.acex, prod_accessdesc_rsa.priv_exponent, prod_accessdesc_rsa.modulus);
/* Certs */
SetCaCert(keys, ca3_ppki_cert);
SetTikCert(keys, xsC_ppki_cert);
SetTmdCert(keys, cpB_ppki_cert);
}
return 0;
}
/*
void SetDummyRsaData(keys_struct *keys)
{
// CIA
if (Rsa2048Key_CanSign(&keys->rsa.xs) == false)
Rsa2048Key_Set(&keys->rsa.xs, tpki_rsa.priv_exponent, tpki_rsa.modulus);
if (Rsa2048Key_CanSign(&keys->rsa.cp) == false)
Rsa2048Key_Set(&keys->rsa.cp, tpki_rsa.priv_exponent, tpki_rsa.modulus);
// CCI/CFA
if (Rsa2048Key_CanSign(&keys->rsa.cciCfa) == false)
Rsa2048Key_Set(&keys->rsa.cciCfa, tpki_rsa.priv_exponent, tpki_rsa.modulus);
// CXI
if (Rsa2048Key_CanSign(&keys->rsa.acex) == false)
Rsa2048Key_Set(&keys->rsa.acex, tpki_rsa.priv_exponent, tpki_rsa.modulus);
// Certs
if(!keys->certs.caCert)
SetCaCert(keys, ca3_tpki_cert);
if(!keys->certs.xsCert)
SetTikCert(keys, xsC_tpki_cert);
if(!keys->certs.cpCert)
SetTmdCert(keys, cpB_tpki_cert);
}
*/
void DumpKeyset(keys_struct *keys)
{
bool showNcchFixedKeys = (keys->aes.normalKey || keys->aes.systemFixedKey);
bool showCommonKeys = false;
bool showNcchKeyXs = false;
for(int i = 0; i < 256; i++){
if(keys->aes.commonKey[i]){
showCommonKeys = true;
break;
}
}
for (int i = 0; i < 256; i++) {
if (keys->aes.ncchKeyX[i]) {
showNcchKeyXs = true;
break;
}
}
printf("[*] Keyset\n");
if(showCommonKeys){
printf(" > eTicket Common Keys\n");
for(int i = 0; i < 256; i++){
if(keys->aes.commonKey[i]){
printf(" [0x%02x] ",i);
memdump(stdout,"",keys->aes.commonKey[i],16);
}
}
}
if (showNcchKeyXs) {
printf(" > Unfixed NCCH KeyXs\n");
for (int i = 0; i < 256; i++) {
if (keys->aes.ncchKeyX[i]) {
printf(" [0x%02x] ", i);
memdump(stdout, "", keys->aes.ncchKeyX[i], 16);
}
}
}
if(showNcchFixedKeys){
printf(" > Fixed NCCH Keys\n");
if(keys->aes.normalKey)
memdump(stdout," [Normal] ",keys->aes.normalKey,16);
if(keys->aes.systemFixedKey)
memdump(stdout," [System] ",keys->aes.systemFixedKey,16);
}
printf(" > TIK RSA Keys\n");
memdump(stdout," [PUB] ",keys->rsa.xs.pub,0x100);
memdump(stdout," [PVT] ",keys->rsa.xs.pvt,0x100);
printf(" > TMD RSA Keys\n");
memdump(stdout," [PUB] ",keys->rsa.cp.pub,0x100);
memdump(stdout," [PVT] ",keys->rsa.cp.pvt,0x100);
printf(" > AcexDesc RSA Keys\n");
memdump(stdout," [PUB] ",keys->rsa.acex.pub,0x100);
memdump(stdout," [PVT] ",keys->rsa.acex.pvt,0x100);
printf(" > NcsdCfa RSA Keys\n");
memdump(stdout," [PUB] ",keys->rsa.cciCfa.pub,0x100);
memdump(stdout," [PVT] ",keys->rsa.cciCfa.pvt,0x100);
}
void keysetOpenError(char *file)
{
fprintf(stderr, "[KEYSET ERROR] Failed to open: %s\n", file);
}
FILE* keyset_OpenFile(char *dir, char *name, bool is_required)
{
int file_path_len = sizeof(char)*(strlen(dir)+strlen(name)+1);
char *file_path = malloc(file_path_len);
memset(file_path,0,file_path_len);
sprintf(file_path,"%s%s",dir,name);
FILE *fp = fopen(file_path,"rb");
if (!fp && is_required)
keysetOpenError(file_path);
free(file_path);
return fp;
}
void FreeKeys(keys_struct *keys)
{
// AES
if(keys->aes.commonKey){
for(int i = 0; i <= MAX_CMN_KEY; i++)
free(keys->aes.commonKey[i]);
}
free(keys->aes.commonKey);
free(keys->aes.normalKey);
free(keys->aes.systemFixedKey);
if(keys->aes.ncchKeyX){
for(int i = 0; i <= MAX_NCCH_KEYX; i++)
free(keys->aes.ncchKeyX[i]);
}
free(keys->aes.ncchKeyX);
free(keys->aes.ncchKey0);
free(keys->aes.ncchKey1);
// RSA
Rsa2048Key_Free(&keys->rsa.xs);
Rsa2048Key_Free(&keys->rsa.cp);
Rsa2048Key_Free(&keys->rsa.cciCfa);
Rsa2048Key_Free(&keys->rsa.acex);
Rsa2048Key_Free(&keys->rsa.cxi);
// Certs
free(keys->certs.caCert);
free(keys->certs.xsCert);
free(keys->certs.cpCert);
memset(keys,0,sizeof(keys_struct));
}
int SetRsaKeySet(u8 **priv_exp_dst, const u8 *priv_exp_src, u8 **modulus_dst, const u8 *modulus_src)
{
int result = 0;
if(priv_exp_src){
result = CopyData(priv_exp_dst,priv_exp_src,0x100);
if(result) return result;
}
if(modulus_src){
result = CopyData(modulus_dst,modulus_src,0x100);
if(result) return result;
}
return 0;
}
int SetCommonKey(keys_struct *keys, const u8 *key, u8 index)
{
if(!keys) return -1;
return CopyData(&keys->aes.commonKey[index],key,AES_128_KEY_SIZE);
}
void InitCommonKeySlots(keys_struct *keys)
{
if(!keys->aes.commonKey)
keys->aes.commonKey = calloc(MAX_CMN_KEY+1,sizeof(u8*));
}
int SetNcchKeyX(keys_struct *keys, const u8 *keyX, u8 index)
{
if(!keys) return -1;
return CopyData(&keys->aes.ncchKeyX[index],keyX,AES_128_KEY_SIZE);
}
void InitNcchKeyXSlots(keys_struct *keys)
{
if(!keys->aes.ncchKeyX)
keys->aes.ncchKeyX = calloc(MAX_NCCH_KEYX+1,sizeof(u8*));
}
int SetCurrentCommonKey(keys_struct *keys, u8 Index)
{
if(!keys) return -1;
keys->aes.currentCommonKey = Index;
return 0;
}
int SetNormalKey(keys_struct *keys, const u8 *key)
{
if(!keys) return -1;
return CopyData(&keys->aes.normalKey,key,16);
}
int SetSystemFixedKey(keys_struct *keys, const u8 *key)
{
if(!keys) return -1;
return CopyData(&keys->aes.systemFixedKey,key,16);
}
int SetCciInitialDataKeyX(keys_struct *keys, const u8 *key)
{
if(!keys) return -1;
return CopyData(&keys->aes.initialDataKeyX,key,16);
}
int SetCaCert(keys_struct *keys, const u8 *cert)
{
if(!keys) return -1;
return CopyData(&keys->certs.caCert,cert,0x400);
}
int SetTikCert(keys_struct *keys, const u8 *cert)
{
if(!keys) return -1;
return CopyData(&keys->certs.xsCert,cert,0x300);
}
int SetTmdCert(keys_struct *keys, const u8 *cert)
{
if(!keys) return -1;
return CopyData(&keys->certs.cpCert,cert,0x400);
}
void Rsa2048Key_Alloc(rsa2048_key* key)
{
key->pub = malloc(RSA_2048_KEY_SIZE);
key->pvt = malloc(RSA_2048_KEY_SIZE);
}
void Rsa2048Key_Free(rsa2048_key* key)
{
free(key->pub);
free(key->pvt);
}
void Rsa2048Key_Set(rsa2048_key* key, const u8* pvt, const u8* pub)
{
memcpy(key->pub, pub, RSA_2048_KEY_SIZE);
memcpy(key->pvt, pvt, RSA_2048_KEY_SIZE);
}
bool Rsa2048Key_CanSign(const rsa2048_key* key)
{
static const u8 rsa2048[RSA_2048_KEY_SIZE] = { 0 };
return memcmp(key->pub, rsa2048, RSA_2048_KEY_SIZE) != 0 && memcmp(key->pvt, rsa2048, RSA_2048_KEY_SIZE) != 0;
}
+107
View File
@@ -0,0 +1,107 @@
#pragma once
#include "desc/desc.h"
typedef enum
{
AES_128_KEY_SIZE = 16,
MAX_CMN_KEY = 0x05,
MAX_NCCH_KEYX = MAX_U8
} keydata_limits;
typedef enum
{
KEYSET_ERROR = -10,
} keyset_errors;
typedef enum
{
RSA_1024_KEY_SIZE = 0x80,
RSA_2048_KEY_SIZE = 0x100,
RSA_4096_KEY_SIZE = 0x200,
} rsa_keysize;
typedef enum
{
pki_TEST,
pki_BETA, // Not used, but is here for completeness
pki_DEVELOPMENT,
pki_PRODUCTION,
pki_CUSTOM,
} pki_keyset;
// Structs
typedef struct
{
u8 *pub;
u8 *pvt;
} rsa2048_key;
typedef struct
{
pki_keyset keyset;
bool keysetLoaded;
bool dumpkeys;
bool ignore_sign;
struct
{
u32 presetType;
u32 targetFirmware;
} accessDescSign;
struct
{
// CIA
u8 **commonKey;
u16 currentCommonKey;
// NCCH Keys
u8 *normalKey;
u8 *systemFixedKey;
u8 **ncchKeyX;
u8 *ncchKey0;
u8 *ncchKey1;
// CCI
u8 *initialDataKeyX;
} aes;
struct
{
// CIA RSA
rsa2048_key cp;
rsa2048_key xs;
// CCI/CFA
rsa2048_key cciCfa;
// CXI
rsa2048_key acex;
rsa2048_key cxi;
} rsa;
struct
{
// CIA
u8 *caCert;
u8 *xsCert;
u8 *cpCert;
} certs;
} keys_struct;
// Public Prototypes
void InitKeys(keys_struct *keys);
int SetKeys(keys_struct *keys);
void FreeKeys(keys_struct *keys);
int SetCommonKey(keys_struct *keys, const u8 *key, u8 Index);
int SetCurrentCommonKey(keys_struct *keys, u8 Index);
int SetNormalKey(keys_struct *keys, const u8 *key);
int SetSystemFixedKey(keys_struct *keys, const u8 *key);
int SetCciInitialDataKeyX(keys_struct *keys, const u8 *key);
void Rsa2048Key_Alloc(rsa2048_key* key);
void Rsa2048Key_Free(rsa2048_key* key);
void Rsa2048Key_Set(rsa2048_key* key, const u8* pvt, const u8* pub);
bool Rsa2048Key_CanSign(const rsa2048_key* key);
+39
View File
@@ -0,0 +1,39 @@
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <time.h>
#include <unistd.h>
#include <math.h>
#include <dirent.h>
#include <wchar.h>
#include <inttypes.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifdef _WIN32
#include <io.h>
#include <direct.h>
#include <windows.h>
#endif
#include "types.h"
#include "utils.h"
#include "ctr_utils.h"
#include "crypto.h"
#include "keyset.h"
#include "user_settings.h"
#include "yaml_parser.h"
#include "rsf_settings.h"
+107
View File
@@ -0,0 +1,107 @@
#include "lib.h"
#include "ncch_build.h"
#include "ncsd_build.h"
#include "cia_build.h"
int main(int argc, char *argv[])
{
// Setting up user settings
user_settings *set = calloc(1,sizeof(user_settings));
if(set == NULL) {
fprintf(stderr,"[!] Not enough memory\n");
return -1;
}
init_UserSettings(set);
initRand();
int result;
// Parsing command args
if((result = ParseArgs(argc,argv,set)) < 0)
goto finish;
// Import RSF Settings if present
if((result = GetRsfSettings(set)) < 0)
goto finish;
// Setup Content 0
if(!set->ncch.buildNcch0){ // Import Content
if(set->common.workingFileType == infile_ncch){
if(!AssertFile(set->common.contentPath[0])){
fprintf(stderr,"[MAKEROM ERROR] Failed to open Content 0: %s\n",set->common.contentPath[0]);
goto finish;
}
u64 fileSize = GetFileSize64(set->common.contentPath[0]);
u64 calcSize = 0;
FILE *ncch0 = fopen(set->common.contentPath[0],"rb");
ncch_hdr hdr;
ReadNcchHdr(&hdr,ncch0);
calcSize = GetNcchSize(&hdr);
if(calcSize != fileSize){
fprintf(stderr,"[MAKEROM ERROR] Content 0 is corrupt\n");
fclose(ncch0);
goto finish;
}
set->common.workingFile.size = fileSize;
set->common.workingFile.buffer = malloc(fileSize);
ReadFile64(set->common.workingFile.buffer, set->common.workingFile.size,0,ncch0);
fclose(ncch0);
}
else{
if(!AssertFile(set->common.workingFilePath)) {
fprintf(stderr,"[MAKEROM ERROR] Failed to open: %s\n",set->common.workingFilePath);
goto finish;
}
u64 size = GetFileSize64(set->common.workingFilePath);
set->common.workingFile.size = align(size,0x10);
set->common.workingFile.buffer = malloc(set->common.workingFile.size);
FILE *fp = fopen(set->common.workingFilePath,"rb");
ReadFile64(set->common.workingFile.buffer,size,0,fp);
fclose(fp);
}
}
else{// Build Content 0
result = build_NCCH(set);
if(result < 0) {
//fprintf(stderr,"[ERROR] %s generation failed\n",set->build_ncch_type == CXI? "CXI" : "CFA");
fprintf(stderr,"[RESULT] Failed to build NCCH (ret = %d)\n", result);
goto finish;
}
}
// Make CCI
if(set->common.outFormat == CCI){
result = build_CCI(set);
if(result < 0) {
fprintf(stderr,"[RESULT] Failed to build CCI (ret = %d)\n", result);
goto finish;
}
}
// Make CIA
else if(set->common.outFormat == CIA){
result = build_CIA(set);
if(result < 0) {
fprintf(stderr,"[RESULT] Failed to build CIA (ret = %d)\n", result);
goto finish;
}
}
// No Container Raw CXI/CFA
else if(set->common.outFormat == CXI || set->common.outFormat == CFA){
FILE *ncch_out = fopen(set->common.outFileName,"wb");
if(!ncch_out) {
fprintf(stderr,"[MAKEROM ERROR] Failed to create '%s'\n",set->common.outFileName);
fprintf(stderr,"[RESULT] Failed to build '%s'\n",set->common.outFormat == CXI? "CXI" : "CFA");
result = FAILED_TO_CREATE_OUTFILE;
goto finish;
}
WriteBuffer(set->common.workingFile.buffer,set->common.workingFile.size,0,ncch_out);
fclose(ncch_out);
}
finish:
free_UserSettings(set);
return result;
}
+1201
View File
File diff suppressed because it is too large Load Diff
+156
View File
@@ -0,0 +1,156 @@
#pragma once
typedef enum
{
NCCH_MEMERROR = -1,
SAVE_DATA_TOO_LARGE = -2,
NCCH_SECTION_NOT_EXIST = -3,
UNABLE_TO_LOAD_NCCH_KEY = -4,
NCCH_EXPORT_BUFFER_TOO_SMALL = -5,
NO_ROMFS_IN_CFA = -6,
NO_EXHEADER_IN_CXI = -7,
NO_EXEFS_IN_CXI = -8,
// SigCheck Errors
CXI_CORRUPT = -9,
ACCESSDESC_SIG_BAD = -10,
NCCH_HDR_SIG_BAD = -11,
// HashCheck Errors
EXHDR_CORRUPT = -12,
LOGO_CORRUPT = -13,
EXEFS_CORRUPT = -14,
ROMFS_CORRUPT = -15,
// Others
NCCH_BAD_RSF_SET = -16,
DATA_POS_DNE = -17,
} ncch_errors;
typedef enum
{
ncch_exhdr = 1,
ncch_exefs,
ncch_romfs,
} ncch_section;
typedef enum
{
ncchflag_CONTENT_KEYX = 3,
ncchflag_CONTENT_PLATFORM = 4,
ncchflag_CONTENT_TYPE = 5,
ncchflag_CONTENT_BLOCK_SIZE = 6,
ncchflag_OTHER_FLAG = 7
} ncch_flags;
typedef enum
{
otherflag_Clear = 0,
otherflag_FixedCryptoKey = (1 << 0),
otherflag_NoMountRomFs = (1 << 1),
otherflag_NoCrypto = (1 << 2),
} ncch_otherflag_bitmask;
typedef enum
{
form_Unassigned,
form_SimpleContent,
form_ExecutableWithoutRomfs,
form_Executable
} ncch_form_type;
typedef enum
{
content_Application,
content_SystemUpdate,
content_Manual,
content_Child,
content_Trial,
content_ExtendedSystemUpdate
} ncch_content_bitmask;
typedef enum
{
platform_CTR = 0x1,
platform_SNAKE = 0x2
} ncch_platform;
typedef enum
{
keyx_regular = 0x00,
keyx_7_0 = 0x01,
keyx_9_3 = 0x0A,
keyx_9_6 = 0x0B,
} ncch_keyx_id;
typedef struct
{
u16 formatVersion;
u32 exhdrOffset;
u32 exhdrSize;
u32 acexOffset;
u32 acexSize;
u64 logoOffset;
u64 logoSize;
u64 plainRegionOffset;
u64 plainRegionSize;
u64 exefsOffset;
u64 exefsSize;
u64 exefsHashDataSize;
u64 romfsOffset;
u64 romfsSize;
u64 romfsHashDataSize;
u64 titleId;
u64 programId;
} ncch_info;
typedef struct
{
u8 signature[0x100];
u8 magic[4];
u8 ncchSize[4];
u8 titleId[8];
u8 makerCode[2];
u8 formatVersion[2];
u8 padding0[4];
u8 programId[8];
u8 padding1[0x10];
u8 logoHash[0x20]; // SHA-256 over the entire logo region
u8 productCode[0x10];
u8 exhdrHash[0x20]; // SHA-256 over exhdrSize of the exhdr region
u8 exhdrSize[4];
u8 padding2[4];
u8 flags[8];
u8 plainRegionOffset[4];
u8 plainRegionSize[4];
u8 logoOffset[4];
u8 logoSize[4];
u8 exefsOffset[4];
u8 exefsSize[4];
u8 exefsHashSize[4];
u8 padding4[4];
u8 romfsOffset[4];
u8 romfsSize[4];
u8 romfsHashSize[4];
u8 padding5[4];
u8 exefsHash[0x20];
u8 romfsHash[0x20];
} ncch_hdr;
// NCCH Read Functions
int VerifyNcch(u8 *ncch, keys_struct *keys, bool checkHash, bool suppressOutput);
int ModifyNcchIds(u8 *ncch, u8 *titleId, u8 *programId, keys_struct *keys);
void ReadNcchHdr(ncch_hdr *hdr, FILE *fp);
u8* GetNcchHdrSig(ncch_hdr *hdr);
u8* GetNcchHdrData(ncch_hdr *hdr);
u32 GetNcchHdrSigLen(ncch_hdr *hdr);
u32 GetNcchHdrDataLen(ncch_hdr *hdr);
bool IsNcch(FILE *fp, u8 *buf);
bool IsCfa(ncch_hdr* hdr);
bool IsUpdateCfa(ncch_hdr* hdr);
u32 GetNcchBlockSize(ncch_hdr* hdr);
u64 GetNcchSize(ncch_hdr* hdr);
bool IsNcchEncrypted(ncch_hdr *hdr);
bool SetNcchKeys(keys_struct *keys, ncch_hdr *hdr);
int GetNcchInfo(ncch_info *ctx, ncch_hdr *header);
void GetNcchAesCounter(u8 ctr[16], u64 titleId, u8 type);
void CryptNcchRegion(u8 *buffer, u64 size, u64 src_pos, u64 titleId, u8 key[16], u8 type);
+90
View File
@@ -0,0 +1,90 @@
#pragma once
#include "ncch.h"
typedef struct
{
buffer_struct *out;
keys_struct *keys;
rsf_settings *rsfSet;
struct
{
u32 blockSize;
bool verbose;
bool IncludeExeFsLogo;
bool CompressCode;
bool UseOnSD;
bool Encrypt;
bool FreeProductCode;
bool IsCfa;
bool IsBuildingCodeSection;
bool UseRomFS;
bool noCodePadding;
bool useSecCrypto;
u8 keyXID;
} options;
struct
{
FILE *elf;
u64 elfSize;
FILE *banner;
u64 bannerSize;
FILE *icon;
u64 iconSize;
FILE *logo;
u64 logoSize;
FILE *code;
u64 codeSize;
FILE *exhdr;
u64 exhdrSize;
FILE *romfs;
u64 romfsSize;
FILE *plainregion;
u64 plainregionSize;
} componentFilePtrs;
struct
{
buffer_struct code;
buffer_struct banner;
buffer_struct icon;
} exefsSections;
struct
{
u32 textAddress;
u32 textSize;
u32 textMaxPages;
u32 roAddress;
u32 roSize;
u32 roMaxPages;
u32 rwAddress;
u32 rwSize;
u32 rwMaxPages;
u32 bssSize;
u32 stackSize;
} codeDetails;
struct
{
buffer_struct exhdr;
buffer_struct acexDesc;
buffer_struct logo;
buffer_struct plainRegion;
buffer_struct exeFs;
} sections;
ncch_info cryptoDetails;
} ncch_settings;
// NCCH Build Functions
int build_NCCH(user_settings *usrset);
File diff suppressed because one or more lines are too long
+2
View File
@@ -0,0 +1,2 @@
#pragma once
#include "ncch.h"
+727
View File
@@ -0,0 +1,727 @@
#include "lib.h"
#include "ncch_read.h"
#include "exheader_read.h"
#include "tik_read.h"
#include "tmd_read.h"
#include "cia_read.h"
#include "ncsd_build.h"
#include "cardinfo.h"
#include "titleid.h"
const int NCCH0_OFFSET = 0x4000;
const int CCI_BLOCK_SIZE = 0x200;
const char MEDIA_SIZE_STR[10][6] = {"128MB","256MB","512MB","1GB","2GB","4GB","8GB","16GB","32GB"};
void ImportCciSettings(cci_settings *set, user_settings *usrset);
void FreeCciSettings(cci_settings *set);
int ImportCciNcch(cci_settings *set);
int ProcessNcchForCci(cci_settings *set);
int GenCciHdr(cci_settings *set);
int CheckRomConfig(cci_settings *set);
void WriteCciDataToOutput(cci_settings *set);
int build_CCI(user_settings *usrset)
{
int result = 0;
cci_settings *set = calloc(1,sizeof(cci_settings));
if(!set){
fprintf(stderr,"[CCI ERROR] Not enough memory\n");
return MEM_ERROR;
}
ImportCciSettings(set,usrset);
if(ImportCciNcch(set)){
result = FAILED_TO_IMPORT_FILE;
goto finish;
}
if(ProcessNcchForCci(set)){
result = FAILED_TO_IMPORT_FILE;
goto finish;
}
if(GenCciHdr(set)){
result = GEN_HDR_FAIL;
goto finish;
}
if(GenCardInfoHdr(set)){
result = GEN_HDR_FAIL;
goto finish;
}
if(CheckRomConfig(set)){
result = CCI_CONFIG_FAIL;
goto finish;
}
set->out = fopen(usrset->common.outFileName,"wb");
if(!set->out){
fprintf(stderr,"[CCI ERROR] Failed to create '%s'\n",usrset->common.outFileName);
result = FAILED_TO_CREATE_OUTFILE;
goto finish;
}
WriteCciDataToOutput(set);
finish:
FreeCciSettings(set);
return result;
}
void ImportCciSettings(cci_settings *set, user_settings *usrset)
{
set->keys = &usrset->common.keys;
set->rsf = &usrset->common.rsfSet;
set->content.data = usrset->common.workingFile.buffer;
set->content.dataLen = usrset->common.workingFile.size;
set->content.dataType = usrset->common.workingFileType;
set->content.path = usrset->common.contentPath;
set->content.dSize = usrset->common.contentSize;
usrset->common.workingFile.buffer = NULL;
usrset->common.workingFile.size = 0;
set->options.verbose = usrset->common.verbose;
set->options.padCci = set->rsf->Option.MediaFootPadding;
set->options.noModTid = usrset->cci.dontModifyNcchTitleID;
set->options.useExternalSdkCardInfo = usrset->cci.useSDKStockData;
set->options.closeAlignWR = usrset->cci.closeAlignWritableRegion;
set->options.cverDataType = usrset->cci.cverDataType;
set->options.cverDataPath = usrset->cci.cverDataPath;
set->romInfo.blockSize = CCI_BLOCK_SIZE;
set->romInfo.saveSize = 0;
}
void FreeCciSettings(cci_settings *set)
{
free(set->options.tmdHdr);
free(set->content.data);
free(set->headers.ccihdr.buffer);
free(set->headers.cardinfohdr.buffer);
if(set->out)
fclose(set->out);
free(set);
}
int ImportNcchForCci(cci_settings *set)
{
for(int i = 0; i < CCI_MAX_CONTENT; i++){
if(i == 0){
set->content.active[i] = true;
set->content.dSize[i] = set->content.dataLen;
set->content.dOffset[i] = 0;
}
else if(set->content.dSize[i] && set->content.path[i]){
set->content.active[i] = true;
set->content.dOffset[i] = set->content.dataLen;
set->content.dataLen += set->content.dSize[i];
}
else
set->content.active[i] = false;
}
set->content.data = realloc(set->content.data,set->content.dataLen);
if(!set->content.data){
fprintf(stderr,"[CCI ERROR] Not enough memory\n");
return MEM_ERROR;
}
FILE *ncch;
for(int i = 1; i < CCI_MAX_CONTENT; i++){
if(!set->content.active[i])
continue;
u8 *ncchpos = (u8*)(set->content.data+set->content.dOffset[i]);
ncch = fopen(set->content.path[i],"rb");
ReadFile64(ncchpos, set->content.dSize[i], 0, ncch);
fclose(ncch);
}
return 0;
}
bool CanCiaBeCci(u64 titleId, u16 count, tmd_content_chunk *content)
{
if(GetTidCategory(titleId) != PROGRAM_ID_CATEGORY_APPLICATION)
return false;
if(count > CCI_MAX_CONTENT)
return false;
for(int i = 0; i < count; i++){
if(GetTmdContentIndex(content[i]) >= CCI_MAX_CONTENT)
return false;
}
return true;
}
int ProcessCiaForCci(cci_settings *set)
{
if(!IsCia(set->content.data)){
fprintf(stderr,"[CCI ERROR] CIA is corrupt\n");
return FAILED_TO_IMPORT_FILE;
}
tik_hdr *tik = GetTikHdr(GetCiaTik(set->content.data));
tmd_hdr *tmd = GetTmdHdr(GetCiaTmd(set->content.data));
tmd_content_chunk *contentInfo = GetTmdContentInfo(GetCiaTmd(set->content.data));
u64 contentOffset = GetCiaContentOffset((cia_hdr*)set->content.data);
u16 contentCount = GetTmdContentCount(tmd);
set->romInfo.saveSize = GetTmdSaveSize(tmd);
if(!CanCiaBeCci(GetTmdTitleId(tmd),contentCount,contentInfo)){
fprintf(stderr,"[CCI ERROR] This CIA cannot be converted to CCI\n");
return INCOMPAT_CIA;
}
bool canDecrypt;
u8 titleKey[AES_128_KEY_SIZE];
canDecrypt = GetTikTitleKey(titleKey,tik,set->keys);
if(set->options.verbose){
if(canDecrypt)
memdump(stdout,"[CCI] CIA title key: ",titleKey,AES_128_KEY_SIZE);
else
fprintf(stdout,"[CCI] CIA title key could not be decrypted\n");
}
for(u16 i = 0; i < contentCount; i++){
u16 index = GetTmdContentIndex(contentInfo[i]);
set->content.active[index] = true;
set->content.dOffset[index] = contentOffset;
set->content.dSize[index] = GetTmdContentSize(contentInfo[i]);
u8 *content = set->content.data + contentOffset;
if(IsTmdContentEncrypted(contentInfo[i])){
if(canDecrypt)
CryptContent(content,content,set->content.dSize[index],titleKey,i,DEC);
else{
fprintf(stderr,"[CCI ERROR] Failed to decrypt CIA content: 0x%08x\n",GetTmdContentId(contentInfo[i]));
return INCOMPAT_CIA;
}
}
if(!ValidateTmdContent(content,contentInfo[i])){
fprintf(stderr,"[CCI ERROR] CIA content: 0x%08x is corrupt\n",GetTmdContentId(contentInfo[i]));
return NCSD_INVALID_NCCH;
}
contentOffset += set->content.dSize[index];
}
return 0;
}
/* This need to be more automagical */
void GetTitleSaveSize(cci_settings *set)
{
if(set->rsf->SystemControlInfo.SaveDataSize)
GetSaveDataSizeFromString(&set->romInfo.saveSize,set->rsf->SystemControlInfo.SaveDataSize,"CCI");
// Adjusting save size
if(set->romInfo.saveSize > 0 && set->romInfo.saveSize < (u64)(128*KB))
set->romInfo.saveSize = (u64)(128*KB);
else if(set->romInfo.saveSize > (u64)(128*KB) && set->romInfo.saveSize < (u64)(512*KB))
set->romInfo.saveSize = (u64)(512*KB);
else if(set->romInfo.saveSize > (u64)(512*KB))
set->romInfo.saveSize = align(set->romInfo.saveSize,MB);
}
int ImportCciNcch(cci_settings *set)
{
int ret = 0;
if(set->content.dataType == infile_ncch)
ret = ImportNcchForCci(set);
else if(set->content.dataType == infile_cia)
ret = ProcessCiaForCci(set);
else{
fprintf(stderr,"[CCI ERROR] Unrecognised input data type\n");
return FAILED_TO_IMPORT_FILE;
}
GetTitleSaveSize(set);
return ret;
}
int ProcessCverDataForCci(cci_settings *set)
{
u64 tmdSize,tmdOffset;
u64 dataSize = GetFileSize64(set->options.cverDataPath);
FILE *data = fopen(set->options.cverDataPath,"rb");
if(set->options.cverDataType == CVER_DTYPE_CIA){
cia_hdr *ciaHdr = calloc(1,sizeof(cia_hdr));
ReadFile64(ciaHdr,sizeof(cia_hdr),0,data);
tmdSize = GetCiaTmdSize(ciaHdr);
tmdOffset = GetCiaTmdOffset(ciaHdr);
free(ciaHdr);
}
else{
tmdSize = dataSize;
tmdOffset = 0;
}
u8 *tmd = calloc(1,tmdSize);
ReadFile64(tmd,tmdSize,tmdOffset,data);
fclose(data);
tmd_hdr *tmdHdr = GetTmdHdr(tmd);
if(!tmdHdr){
fprintf(stderr,"[CCI ERROR] Corrupt cver TMD\n");
free(tmd);
return FAILED_TO_IMPORT_FILE;
}
set->options.tmdHdr = calloc(1,sizeof(tmd_hdr));
memcpy(set->options.tmdHdr,tmdHdr,sizeof(tmd_hdr));
free(tmd);
return 0;
}
void GetNewNcchIdForCci(u8 *newTid, u8 *srcTid, u8 index, tmd_hdr *tmdHdr)
{
u64 titleId = u8_to_u64(srcTid,LE) & 0xffffffffffff;
if(tmdHdr && index == 7)
titleId |= (u64)(GetTmdVersion(tmdHdr)) << 48;
else
titleId |= (u64)(index+4) << 48;
u64_to_u8(newTid,titleId,LE);
}
int ProcessNcchForCci(cci_settings *set)
{
u8 *ncch;
ncch_hdr *hdr;
u8 titleId[8];
u8 srcId[8];
if(set->options.cverDataPath && set->content.active[7]){
if(ProcessCverDataForCci(set))
return FAILED_TO_IMPORT_FILE;
}
for(int i = 0; i < CCI_MAX_CONTENT; i++){
if(set->content.active[i]){
ncch = set->content.data + set->content.dOffset[i];
if(!IsNcch(NULL,ncch)){
fprintf(stderr,"[CCI ERROR] NCCH %d is corrupt\n",i);
return NCSD_INVALID_NCCH;
}
hdr = (ncch_hdr*)ncch;
if(i > 0 && !set->options.noModTid){
if(set->options.verbose){
printf("[CCI] Modifying NCCH %d IDs\n",i);
printf("[Old Ids]\n");
memdump(stdout," > TitleId: 0x",hdr->titleId,8);
memdump(stdout," > ProgramId: 0x",hdr->programId,8);
}
GetNewNcchIdForCci(titleId,srcId,i,set->options.tmdHdr);
if(ModifyNcchIds(ncch, titleId, srcId, set->keys))
return -1;
if(set->options.verbose){
printf("[New Ids]\n");
memdump(stdout," > TitleId: 0x",hdr->titleId,8);
memdump(stdout," > ProgramId: 0x",hdr->programId,8);
}
}
set->content.titleId[i] = u8_to_u64(hdr->titleId,LE);
if(i == 0)
memcpy(srcId,hdr->titleId,8);
}
}
return 0;
}
void SetCciNcchInfo(cci_hdr *hdr, cci_settings *set)
{
u64 ncchSize,ncchOffset;
ncchOffset = NCCH0_OFFSET;
for(int i = 0; i < CCI_MAX_CONTENT; i++){
if(set->content.active[i]){
set->content.cOffset[i] = ncchOffset;
ncchSize = align(set->content.dSize[i],set->romInfo.blockSize);
u32_to_u8(hdr->offset_sizeTable[i].offset,(ncchOffset/set->romInfo.blockSize),LE);
u32_to_u8(hdr->offset_sizeTable[i].size,(ncchSize/set->romInfo.blockSize),LE);
u64_to_u8(hdr->ncchIdTable[i],set->content.titleId[i],LE);
ncchOffset += ncchSize;
}
}
set->romInfo.usedSize = ncchOffset;
return;
}
int SetMediaSize(u8 *mediaSize, cci_settings *set)
{
char *str = set->rsf->CardInfo.MediaSize;
if(str){
if(strcasecmp(str,"128MB") == 0) set->romInfo.mediaSize = (u64)MB*128;
else if(strcasecmp(str,"256MB") == 0) set->romInfo.mediaSize = (u64)MB*256;
else if(strcasecmp(str,"512MB") == 0) set->romInfo.mediaSize = (u64)MB*512;
else if(strcasecmp(str,"1GB") == 0) set->romInfo.mediaSize = (u64)GB*1;
else if(strcasecmp(str,"2GB") == 0) set->romInfo.mediaSize = (u64)GB*2;
else if(strcasecmp(str,"4GB") == 0) set->romInfo.mediaSize = (u64)GB*4;
else if(strcasecmp(str,"8GB") == 0) set->romInfo.mediaSize = (u64)GB*8;
//else if(strcasecmp(str,"16GB") == 0) set->romInfo.mediaSize = (u64)GB*16;
//else if(strcasecmp(str,"32GB") == 0) set->romInfo.mediaSize = (u64)GB*32;
else {
fprintf(stderr,"[CCI ERROR] Invalid MediaSize: %s\n",str);
return INVALID_RSF_OPT;
}
}
else{
u64 dataSize = set->romInfo.usedSize + (set->romInfo.saveSize >= MB ? set->romInfo.saveSize : 0);
if(dataSize < (u64)MB*128)
set->romInfo.mediaSize = (u64)MB*128;
else if(dataSize < (u64)MB*256)
set->romInfo.mediaSize = (u64)MB*256;
else if(dataSize < (u64)MB*512)
set->romInfo.mediaSize = (u64)MB*512;
else if(dataSize < (u64)GB*1)
set->romInfo.mediaSize = (u64)GB*1;
else if(dataSize < (u64)GB*2)
set->romInfo.mediaSize = (u64)GB*2;
else if(dataSize < (u64)GB*4)
set->romInfo.mediaSize = (u64)GB*4;
else if(dataSize < (u64)GB*8)
set->romInfo.mediaSize = (u64)GB*8;
//else if(dataSize < (u64)GB*16)
// set->romInfo.mediaSize = (u64)GB*16;
//else if(dataSize < (u64)GB*32)
// set->romInfo.mediaSize = (u64)GB*32;
else {
fprintf(stderr,"[CCI ERROR] NCCH Partitions are too large\n");
return INVALID_RSF_OPT;
}
}
u32_to_u8(mediaSize,(set->romInfo.mediaSize/set->romInfo.blockSize),LE);
return 0;
}
int SetBackupWriteWaitTime(u8 *flag, rsf_settings *rsf)
{
char *str = rsf->CardInfo.BackupWriteWaitTime;
if(!str)
*flag = 0;
else{
u32 waitTime = strtoul(str,NULL,0);
if(waitTime > 255){
fprintf(stderr,"[CCI ERROR] Invalid Card BackupWriteWaitTime (%d) : must 0-255\n",waitTime);
return INVALID_RSF_OPT;
}
*flag = (u8)waitTime;
}
return 0;
}
int SetMediaType(u8 *flag, cci_settings *set)
{
char *str = set->rsf->CardInfo.MediaType;
if(str){
if(strcasecmp(str,"Card1") == 0)
*flag = mediatype_CARD1;
else if(strcasecmp(str,"Card2") == 0)
*flag = mediatype_CARD2;
else {
fprintf(stderr,"[CCI ERROR] Invalid MediaType: %s\n",str);
return INVALID_RSF_OPT;
}
}
else{
if(set->romInfo.saveSize >= (u64)1*MB)
*flag = mediatype_CARD2;
else
*flag = mediatype_CARD1;
}
return 0;
}
int SetCardDevice(u8 *flags, u64 saveSize, rsf_settings *rsf)
{
u8 saveCrypto;
if(!rsf->CardInfo.SaveCrypto)
saveCrypto = 3;
else{
if(strcasecmp(rsf->CardInfo.SaveCrypto,"fw1") == 0 || strcasecmp(rsf->CardInfo.SaveCrypto,"ctr fail") == 0 ) saveCrypto = 1;
else if(strcasecmp(rsf->CardInfo.SaveCrypto,"fw2") == 0) saveCrypto = 2;
else if(strcasecmp(rsf->CardInfo.SaveCrypto,"fw3") == 0) saveCrypto = 3;
else if(strcasecmp(rsf->CardInfo.SaveCrypto,"fw6") == 0) saveCrypto = 6;
else {
fprintf(stderr,"[CCI ERROR] Invalid SaveCrypto: %s\n",rsf->CardInfo.SaveCrypto);
return INVALID_RSF_OPT;
}
}
/* FW6x SaveCrypto */
if(saveCrypto == 6)
flags[cciflag_FW6_SAVE_CRYPTO] = 1;
else
flags[cciflag_FW6_SAVE_CRYPTO] = 0;
/* CardDevice */
u8 cardDevice = 0;
if(rsf->CardInfo.CardDevice){
if(strcmp(rsf->CardInfo.CardDevice,"NorFlash") == 0)
cardDevice = carddevice_NOR_FLASH;
else if(strcmp(rsf->CardInfo.CardDevice,"None") == 0)
cardDevice = carddevice_NONE;
else if(strcmp(rsf->CardInfo.CardDevice,"BT") == 0)
cardDevice = carddevice_BT;
else {
fprintf(stderr,"[CCI ERROR] Invalid CardDevice: %s\n",rsf->CardInfo.CardDevice);
return INVALID_RSF_OPT;
}
}
else{
if(saveSize == 0 || saveSize >= (u64)1*MB)
cardDevice = carddevice_NONE;
else
cardDevice = carddevice_NOR_FLASH;
}
if(flags[cciflag_MEDIA_TYPE] == mediatype_CARD1){
if(saveSize != (u64)(128*KB) && saveSize != (u64)(512*KB) && cardDevice == carddevice_NOR_FLASH){
fprintf(stderr,"[CCI ERROR] 'CardDevice: NorFlash' can only be used with save-data sizes: 128K & 512K\n");
return INVALID_RSF_OPT;
}
}
if(flags[cciflag_MEDIA_TYPE] == mediatype_CARD2){
if(cardDevice == carddevice_NOR_FLASH){
fprintf(stderr,"[CCI WARNING] 'CardDevice: NorFlash' is invalid for Card2\n");
cardDevice = carddevice_NONE;
}
}
if(saveCrypto > 1)
flags[saveCrypto == 2? cciflag_CARD_DEVICE_OLD : cciflag_CARD_DEVICE] = cardDevice;
return 0;
}
int SetCciFlags(u8 *flags, cci_settings *set)
{
// Backup Write Wait Time
if(SetBackupWriteWaitTime(&flags[cciflag_BACKUP_WRITE_WAIT_TIME], set->rsf))
return INVALID_RSF_OPT;
// Platform
flags[cciflag_MEDIA_PLATFORM] = cciplatform_CTR;
// Card Type
if(SetMediaType(&flags[cciflag_MEDIA_TYPE], set))
return INVALID_RSF_OPT;
// Media Unit
flags[cciflag_MEDIA_BLOCK_SIZE] = GetCtrBlockSizeFlag(set->romInfo.blockSize);
// Card Device
if(SetCardDevice(flags, set->romInfo.saveSize, set->rsf))
return INVALID_RSF_OPT;
set->romInfo.mediaType = flags[cciflag_MEDIA_TYPE];
set->romInfo.cardDevice = flags[cciflag_CARD_DEVICE] | flags[cciflag_CARD_DEVICE_OLD];
return 0;
}
int GenCciHdr(cci_settings *set)
{
set->headers.ccihdr.size = sizeof(cci_hdr);
set->headers.ccihdr.buffer = calloc(1,set->headers.ccihdr.size);
if(!set->headers.ccihdr.buffer){
set->headers.ccihdr.size = 0;
fprintf(stderr,"[CCI ERROR] Not enough memory\n");
return MEM_ERROR;
}
cci_hdr *hdr = (cci_hdr*)set->headers.ccihdr.buffer;
// Magic & TitleId
memcpy(hdr->magic,"NCSD",4);
u64_to_u8(hdr->titleId,set->content.titleId[0],LE);
SetCciNcchInfo(hdr,set);
if(SetMediaSize(hdr->mediaSize,set))
return GEN_HDR_FAIL;
if(SetCciFlags(hdr->flags,set))
return GEN_HDR_FAIL;
// Sign Header
if (Rsa2048Key_CanSign(&set->keys->rsa.cciCfa) == false)
{
printf("[NCSD WARNING] Failed to sign header\n");
memset(hdr->signature, 0xFF, 0x100);
return 0;
}
int rsa_ret = RsaSignVerify(&hdr->magic, sizeof(cci_hdr) - RSA_2048_KEY_SIZE, hdr->signature, set->keys->rsa.cciCfa.pub, set->keys->rsa.cciCfa.pvt, RSA_2048_SHA256, CTR_RSA_SIGN);
if (rsa_ret != 0)
{
printf("[NCSD WARNING] Failed to sign header (mbedtls error = -0x%x)\n", -rsa_ret);
memset(hdr->signature, 0xFF, 0x100);
return 0;
}
return 0;
}
char* GetMediaSizeStr(u64 mediaSize)
{
//MEDIA_SIZE_STR
switch(mediaSize){
case (u64)MB*128: return (char*)MEDIA_SIZE_STR[0];
case (u64)MB*256: return (char*)MEDIA_SIZE_STR[1];
case (u64)MB*512: return (char*)MEDIA_SIZE_STR[2];
case (u64)GB*1: return (char*)MEDIA_SIZE_STR[3];
case (u64)GB*2: return (char*)MEDIA_SIZE_STR[4];
case (u64)GB*4: return (char*)MEDIA_SIZE_STR[5];
case (u64)GB*8: return (char*)MEDIA_SIZE_STR[6];
default: return 0;
}
}
int CheckRomConfig(cci_settings *set)
{
u64 cciUsedSize;
if(set->romInfo.mediaType == mediatype_CARD2)
cciUsedSize = set->romInfo.card2SaveOffset + set->romInfo.saveSize;
else
cciUsedSize = set->romInfo.usedSize;
if(cciUsedSize > set->romInfo.mediaSize){
fprintf(stderr,"[CCI ERROR] MediaSize '%s' is insufficient for the CCI data\n",GetMediaSizeStr(set->romInfo.mediaSize));
return CCI_CONFIG_FAIL;
}
return 0;
}
void WriteCciDataToOutput(cci_settings *set)
{
if (set->options.verbose) {
printf("[CCI] Writing header to file... ");
}
// 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);
if (set->options.verbose) {
printf("Done!\n");
}
// NCCH Partitions
u8 *ncch;
for(int i = 0; i < CCI_MAX_CONTENT; i++){
if(set->content.active[i]){
if (set->options.verbose) {
printf("[CCI] Writing content %d to file... ", i);
}
ncch = set->content.data + set->content.dOffset[i];
WriteBuffer(ncch, set->content.dSize[i], set->content.cOffset[i], set->out);
if (set->options.verbose) {
printf("Done!\n");
}
}
}
// Cci Padding
if(set->options.padCci){
if (set->options.verbose) {
printf("[CCI] Writing padding to file... ");
}
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);
if (set->options.verbose) {
printf("Done!");
}
}
return;
}
bool IsCci(u8 *ncsd)
{
cci_hdr *hdr = (cci_hdr*)ncsd;
if(!hdr) return false;
if(memcmp(hdr->magic,"NCSD",4)!=0) return false;
if(hdr->flags[cciflag_MEDIA_PLATFORM] != cciplatform_CTR) return false;
if(hdr->flags[cciflag_MEDIA_TYPE] != mediatype_CARD1 && hdr->flags[cciflag_MEDIA_TYPE] != mediatype_CARD2) return false;
return true;
}
u64 GetPartitionOffset(u8 *ncsd, u8 index)
{
cci_hdr *hdr = (cci_hdr*)ncsd;
return (u64)u8_to_u64(hdr->offset_sizeTable[index].offset,LE) * (u64)GetCtrBlockSize(hdr->flags[cciflag_MEDIA_BLOCK_SIZE]);
}
u64 GetPartitionSize(u8 *ncsd, u8 index)
{
cci_hdr *hdr = (cci_hdr*)ncsd;
return (u64)u8_to_u64(hdr->offset_sizeTable[index].size,LE) * (u64)GetCtrBlockSize(hdr->flags[cciflag_MEDIA_BLOCK_SIZE]);
}
u8* GetPartition(u8 *ncsd, u8 index)
{
return ncsd + GetPartitionOffset(ncsd,index);
}
+54
View File
@@ -0,0 +1,54 @@
#pragma once
typedef enum
{
cciflag_BACKUP_WRITE_WAIT_TIME = 0,
cciflag_FW6_SAVE_CRYPTO = 1,
cciflag_CARD_DEVICE = 3,
cciflag_MEDIA_PLATFORM = 4,
cciflag_MEDIA_TYPE = 5,
cciflag_MEDIA_BLOCK_SIZE = 6,
cciflag_CARD_DEVICE_OLD = 7
} cci_flagindex;
typedef enum
{
carddevice_NOR_FLASH = 1,
carddevice_NONE = 2,
carddevice_BT = 3
} cci_carddevice;
typedef enum
{
cciplatform_CTR = 1,
} cci_platform;
typedef enum
{
mediatype_INNER_DEVICE, // NAND
mediatype_CARD1,
mediatype_CARD2,
mediatype_EXTENDED_DEVICE
} cci_mediatype;
// Structs
typedef struct
{
u8 offset[4];
u8 size[4];
} ncch_offsetsize;
typedef struct
{
u8 signature[0x100];
u8 magic[4];
u8 mediaSize[4];
u8 titleId[8];
u8 padding0[0x10];
ncch_offsetsize offset_sizeTable[8];
u8 padding1[0x28];
u8 flags[8];
u8 ncchIdTable[8][8];
u8 padding2[0x30];
} cci_hdr;
+72
View File
@@ -0,0 +1,72 @@
#pragma once
#include "ncsd.h"
#include "tmd_read.h"
// Enums
typedef enum
{
NCSD_NO_NCCH0 = -1,
NCSD_INVALID_NCCH0 = -2,
NCSD_INVALID_NCCH = -3,
INVALID_RSF_OPT = -4,
GEN_HDR_FAIL = -5,
INCOMPAT_CIA = -6,
CCI_CONFIG_FAIL = -7,
} ncsd_errors;
typedef struct
{
rsf_settings *rsf;
keys_struct *keys;
FILE *out;
struct{
bool verbose;
bool padCci;
bool noModTid;
bool useExternalSdkCardInfo;
bool closeAlignWR;
u8 cverDataType;
char *cverDataPath;
tmd_hdr *tmdHdr;
} options;
struct{
u32 blockSize;
u64 mediaSize;
u64 usedSize;
u8 mediaType;
u8 cardDevice;
u64 saveSize;
u64 card2SaveOffset;
} romInfo;
struct{
u8 *data;
u64 dataLen;
infile_type dataType;
char **path;
bool active[CCI_MAX_CONTENT];
u64 dOffset[CCI_MAX_CONTENT];
u64 *dSize;
u64 titleId[CCI_MAX_CONTENT];
u64 cOffset[CCI_MAX_CONTENT];
} content;
struct{
buffer_struct ccihdr;
buffer_struct cardinfohdr;
} headers;
} cci_settings;
// Public Prototypes
// Build Functions
int build_CCI(user_settings *usrset);
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include "ncsd.h"
// Read Functions
bool IsCci(u8 *ncsd);
u8* GetPartition(u8 *ncsd, u8 index);
u64 GetPartitionOffset(u8 *ncsd, u8 index);
u64 GetPartitionSize(u8 *ncsd, u8 index);
+210
View File
@@ -0,0 +1,210 @@
#include <stdlib.h>
#ifndef _WIN32
#ifndef __CYGWIN__
#define LIBICONV_PLUG
#endif
#include <iconv.h>
#endif
#include "oschar.h"
int os_fstat(const oschar_t *path)
{
struct _osstat st;
return os_stat(path, &st);
}
uint64_t os_fsize(const oschar_t *path)
{
struct _osstat st;
if (os_stat(path, &st) != 0)
return 0;
else
return st.st_size;
}
int os_makedir(const oschar_t *dir)
{
#ifdef _WIN32
return _wmkdir(dir);
#else
return mkdir(dir, 0777);
#endif
}
uint32_t utf16_strlen(const utf16char_t *str)
{
uint32_t i;
for (i = 0; str[i] != 0x0; i++);
return i;
}
void utf16_fputs(const utf16char_t *str, FILE *out)
{
oschar_t *_str = os_CopyConvertUTF16Str(str);
os_fputs(_str, out);
free(_str);
}
char* strcopy_8to8(const char *src)
{
uint32_t src_len;
char *dst;
if (!src)
return NULL;
src_len = strlen(src);
// Allocate memory for expanded string
dst = calloc(src_len + 1, sizeof(char));
if (!dst)
return NULL;
// Copy elements from src into dst
strncpy(dst, src, src_len);
return dst;
}
utf16char_t* strcopy_8to16(const char *src)
{
uint32_t src_len, i;
utf16char_t *dst;
if (!src)
return NULL;
src_len = strlen(src);
// Allocate memory for expanded string
dst = calloc(src_len + 1, sizeof(utf16char_t));
if (!dst)
return NULL;
// Copy elements from src into dst
for (i = 0; i < src_len; i++)
dst[i] = src[i];
return dst;
}
utf16char_t* strcopy_16to16(const utf16char_t *src)
{
uint32_t src_len, i;
utf16char_t *dst;
if (!src)
return NULL;
src_len = utf16_strlen(src);
// Allocate memory for expanded string
dst = calloc(src_len + 1, sizeof(utf16char_t));
if (!dst)
return NULL;
// Copy elements from src into dst
for (i = 0; i < src_len; i++)
dst[i] = src[i];
return dst;
}
#ifndef _WIN32
utf16char_t* strcopy_UTF8toUTF16(const char *src)
{
uint32_t src_len, dst_len;
size_t in_bytes, out_bytes;
utf16char_t *dst;
char *in, *out;
if (!src)
return NULL;
src_len = strlen(src);
dst_len = src_len + 1;
// Allocate memory for string
dst = calloc(dst_len, sizeof(utf16char_t));
if (!dst)
return NULL;
in = (char*)src;
out = (char*)dst;
in_bytes = src_len*sizeof(char);
out_bytes = dst_len*sizeof(utf16char_t);
iconv_t cd = iconv_open("UTF-16LE", "UTF-8");
iconv(cd, &in, &in_bytes, &out, &out_bytes);
iconv_close(cd);
return dst;
}
char* strcopy_UTF16toUTF8(const utf16char_t *src)
{
uint32_t src_len, dst_len;
size_t in_bytes, out_bytes;
char *dst;
char *in, *out;
if (!src)
return NULL;
src_len = utf16_strlen(src);
// UTF-8 can use up to 3 bytes per UTF-16 code unit, or four for a surrogate pair
dst_len = src_len * 3;
// Allocate memory for string
dst = calloc(dst_len, sizeof(char));
if (!dst)
return NULL;
in = (char*)src;
out = (char*)dst;
in_bytes = src_len*sizeof(uint16_t);
out_bytes = dst_len*sizeof(char);
iconv_t cd = iconv_open("UTF-8", "UTF-16LE");
iconv(cd, &in, &in_bytes, &out, &out_bytes);
iconv_close(cd);
return dst;
}
#endif
oschar_t* os_AppendToPath(const oschar_t *src, const oschar_t *add)
{
uint32_t len;
oschar_t *new_path;
len = os_strlen(src) + os_strlen(add) + 0x10;
new_path = calloc(len, sizeof(oschar_t));
#ifdef _WIN32
_snwprintf(new_path, len, L"%s%c%s", src, OS_PATH_SEPARATOR, add);
#else
snprintf(new_path, len, "%s%c%s", src, OS_PATH_SEPARATOR, add);
#endif
return new_path;
}
oschar_t* os_AppendUTF16StrToPath(const oschar_t *src, const utf16char_t *add)
{
uint32_t len;
oschar_t *new_path, *_add;
_add = os_CopyConvertUTF16Str(add);
len = os_strlen(src) + os_strlen(_add) + 0x10;
new_path = calloc(len, sizeof(oschar_t));
#ifdef _WIN32
_snwprintf(new_path, len, L"%s%c%s", src, OS_PATH_SEPARATOR, _add);
#else
snprintf(new_path, len, "%s%c%s", src, OS_PATH_SEPARATOR, _add);
#endif
free(_add);
return new_path;
}
+95
View File
@@ -0,0 +1,95 @@
#pragma once
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <wchar.h>
#endif
// Nintendo uses UTF16-LE chars for extended ASCII support
typedef uint16_t utf16char_t;
// Native OS char type for unicode support
#ifdef _WIN32
typedef wchar_t oschar_t; // UTF16-LE
#else
typedef char oschar_t; // UTF8
#endif
// Simple redirect macros for functions and types
#ifdef _WIN32
#define os_strlen wcslen
#define os_strcmp wcscmp
#define os_fputs fputws
#define os_CopyStr strcopy_16to16
#define os_CopyConvertCharStr strcopy_8to16
#define os_CopyConvertUTF16Str strcopy_16to16
#define utf16_CopyStr strcopy_16to16
#define utf16_CopyConvertOsStr strcopy_16to16
#define _osdirent _wdirent
#define _OSDIR _WDIR
#define os_readdir _wreaddir
#define os_opendir _wopendir
#define os_closedir _wclosedir
#define os_chdir _wchdir
#define _osstat _stat64
#define os_stat _wstat64
#define os_fopen _wfopen
#define OS_MODE_READ L"rb"
#define OS_MODE_WRITE L"wb"
#define OS_MODE_EDIT L"rb+"
#define OS_PATH_SEPARATOR '\\'
#else
#define os_strlen strlen
#define os_strcmp strcmp
#define os_fputs fputs
#define os_CopyStr strcopy_8to8
#define os_CopyConvertUTF16Str strcopy_UTF16toUTF8
#define os_CopyConvertCharStr strcopy_8to8
#define utf16_CopyStr strcopy_16to16
#define utf16_CopyConvertOsStr strcopy_UTF8toUTF16
#define _osdirent dirent
#define _OSDIR DIR
#define os_readdir readdir
#define os_opendir opendir
#define os_closedir closedir
#define os_chdir chdir
#define _osstat stat
#define os_stat stat
#define os_fopen fopen
#define OS_MODE_READ "rb"
#define OS_MODE_WRITE "wb"
#define OS_MODE_EDIT "rb+"
#define OS_PATH_SEPARATOR '/'
#endif
/* File related */
int os_fstat(const oschar_t* path);
uint64_t os_fsize(const oschar_t* path);
int os_makedir(const oschar_t *dir);
/* UTF16 String property functions */
uint32_t utf16_strlen(const utf16char_t* str);
void utf16_fputs(const utf16char_t *str, FILE *out);
/* String Copy and Conversion */
char* strcopy_8to8(const char *src);
utf16char_t* strcopy_8to16(const char *src);
utf16char_t* strcopy_16to16(const utf16char_t *src);
#ifndef _WIN32
utf16char_t* strcopy_UTF8toUTF16(const char *src);
char* strcopy_UTF16toUTF8(const utf16char_t *src);
#endif
/* String Append and Create */
oschar_t* os_AppendToPath(const oschar_t *src, const oschar_t *add);
oschar_t* os_AppendUTF16StrToPath(const oschar_t *src, const utf16char_t *add);
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+17
View File
@@ -0,0 +1,17 @@
#pragma once
// AES Keys
static const unsigned char rvl_common_etd_key_ppki[2][16] =
{
{0xEB, 0xE4, 0x2A, 0x22, 0x5E, 0x85, 0x93, 0xE4, 0x48, 0xD9, 0xC5, 0x45, 0x73, 0x81, 0xAA, 0xF7} , // 0 - Normal
{0x63, 0xB8, 0x2B, 0xB4, 0xF4, 0x61, 0x4E, 0x2E, 0x13, 0xF2, 0xFE, 0xFB, 0xBA, 0x4C, 0x9B, 0x7E} , // 1 - Korean
};
static const unsigned char twl_common_etd_key_ppki[1][16] =
{
{0xAF, 0x1B, 0xF5, 0x16, 0xA8, 0x07, 0xD2, 0x1A, 0xEA, 0x45, 0x98, 0x4F, 0x04, 0x74, 0x28, 0x61} , // 0 - Normal
};
// RSA Keys
// Certificates
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include <stdint.h>
typedef struct CtrRsa2048Key {
uint8_t modulus[0x100];
uint8_t priv_exponent[0x100];
//uint8_t pub_exponent[0x3];
} CtrRsa2048Key;
typedef struct CtrRsa4096Key {
uint8_t modulus[0x200];
uint8_t priv_exponent[0x200];
//uint8_t pub_exponent[0x3];
} CtrRsa4096Key;
+349
View File
@@ -0,0 +1,349 @@
#pragma once
#include "rsa_key.h"
// AES KEYS
static const unsigned char zeros_aesKey[16] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// RSA KEYS
static const CtrRsa2048Key tpki_rsa =
{
.modulus = { 0xCA, 0xC5, 0x88, 0xC7, 0xF1, 0x2A, 0x09, 0x2B, 0x76, 0x49, 0xC0, 0xA8, 0x35, 0x75, 0x10, 0x82, 0xC2, 0xB5, 0xE5, 0xB2, 0xE9, 0xC8, 0x18, 0x88, 0xF3, 0x98, 0x89, 0xBF, 0x9D, 0xE6, 0xE4, 0x0B, 0x71, 0x5D, 0xDD, 0x3F, 0x13, 0x82, 0x71, 0xF2, 0xED, 0x31, 0x86, 0x99, 0xD9, 0x47, 0xFE, 0xC5, 0x7A, 0x75, 0x93, 0xE1, 0xF8, 0x6D, 0xC6, 0x3D, 0x9B, 0xE1, 0x15, 0x99, 0xE1, 0xC2, 0xE0, 0x5C, 0x38, 0x4B, 0x35, 0xA2, 0x4D, 0x3E, 0xE2, 0xCE, 0xFB, 0xB3, 0x08, 0xA3, 0xDD, 0x0C, 0x26, 0x31, 0x84, 0x92, 0x27, 0xC8, 0x8A, 0x8E, 0xC8, 0x83, 0xA8, 0x6C, 0xA7, 0xA3, 0x39, 0x71, 0x9E, 0xF1, 0x34, 0x91, 0x01, 0xDF, 0x11, 0x4A, 0x9C, 0xF9, 0x8B, 0xF9, 0x2F, 0x46, 0x44, 0x0A, 0x72, 0x38, 0xF3, 0x8B, 0x6D, 0x23, 0x33, 0x89, 0xBF, 0x66, 0x34, 0xA7, 0x86, 0xE6, 0xAD, 0xF2, 0xDE, 0xF9, 0xAB, 0x16, 0xA1, 0x40, 0xEE, 0xD8, 0xF7, 0x6C, 0xDC, 0x00, 0x92, 0xCB, 0x31, 0x49, 0xFC, 0x26, 0x64, 0x24, 0x08, 0x8F, 0xC6, 0x60, 0xFF, 0x1E, 0xE3, 0xF0, 0xDD, 0xFB, 0x6D, 0x0D, 0x0F, 0x49, 0x7C, 0xAD, 0x03, 0xEC, 0x9F, 0x63, 0x58, 0xFA, 0x46, 0xDF, 0xA2, 0x64, 0x0E, 0xCC, 0x85, 0x57, 0xE7, 0x2C, 0x61, 0x7F, 0x59, 0xB8, 0x62, 0x7D, 0x59, 0x0E, 0xF6, 0x84, 0x96, 0x99, 0x42, 0xB0, 0x39, 0x83, 0x80, 0xB5, 0x52, 0x2E, 0x07, 0x3F, 0x92, 0xE3, 0x9E, 0xF5, 0x47, 0xEB, 0xA7, 0xD7, 0xD4, 0x15, 0xF1, 0x22, 0x82, 0x32, 0xBE, 0x2A, 0xD0, 0x8C, 0x01, 0xCC, 0x30, 0xA9, 0x11, 0x96, 0xF6, 0xE9, 0x2B, 0xEA, 0x0E, 0xF8, 0x2D, 0x0D, 0xB1, 0x91, 0xD5, 0x1A, 0x94, 0x51, 0xB9, 0x85, 0x39, 0xB0, 0xAF, 0x9F, 0x54, 0x9E, 0x99, 0xE1, 0x46, 0xE5, 0x6F, 0xE2, 0x5F, 0x4B, 0x4E, 0x23 },
.priv_exponent = { 0x3E, 0x2B, 0xBE, 0xBA, 0x7F, 0x29, 0x02, 0x52, 0xBF, 0x1B, 0xF1, 0xE4, 0x21, 0x2F, 0xD9, 0x76, 0x1E, 0x39, 0x23, 0x4A, 0x6D, 0xFF, 0x99, 0xF6, 0x33, 0xAA, 0x2B, 0x62, 0x03, 0x0A, 0x0E, 0x15, 0xAC, 0x16, 0xB9, 0x85, 0x63, 0x77, 0xF5, 0x74, 0x24, 0x61, 0xB1, 0x01, 0x6E, 0xEB, 0x72, 0x24, 0x1E, 0x5D, 0xFA, 0x8F, 0xA8, 0x5A, 0x10, 0x14, 0x47, 0xBD, 0x05, 0xA0, 0x7E, 0xE5, 0xFF, 0x60, 0x87, 0x2A, 0x18, 0x31, 0xC1, 0x39, 0x6C, 0xD5, 0x45, 0xBB, 0x29, 0x05, 0x04, 0xFB, 0x7A, 0xA2, 0x68, 0x21, 0x5F, 0xED, 0x4E, 0xFE, 0x64, 0x60, 0x69, 0xBD, 0x96, 0xD0, 0xA7, 0x06, 0x3D, 0x53, 0x7B, 0x68, 0x92, 0x88, 0x50, 0x86, 0xEE, 0x06, 0x5D, 0x72, 0x73, 0x9A, 0x39, 0xB6, 0x72, 0x3B, 0x20, 0x01, 0x39, 0xDF, 0x37, 0x28, 0x1E, 0xF5, 0x39, 0x63, 0xBC, 0x2A, 0xF2, 0x5E, 0xAB, 0x1A, 0x99, 0xE4, 0x5B, 0xEB, 0xE6, 0x36, 0x30, 0x6C, 0x40, 0x01, 0x61, 0x60, 0xCC, 0x55, 0x89, 0x6D, 0xCA, 0x7E, 0xE0, 0x64, 0x78, 0x7F, 0x7B, 0x26, 0xAE, 0x3E, 0xA3, 0x12, 0x45, 0x16, 0xF6, 0xC8, 0xD0, 0xB9, 0x4F, 0x91, 0x11, 0x12, 0x11, 0xBB, 0xBB, 0x7F, 0xAB, 0xC7, 0x82, 0xDC, 0x4A, 0x61, 0x9C, 0x14, 0xAE, 0x29, 0xFD, 0x3A, 0x60, 0x13, 0x93, 0x19, 0x2F, 0x54, 0x49, 0xB2, 0x44, 0x34, 0x58, 0x14, 0xD7, 0x2F, 0x70, 0x25, 0xA0, 0x48, 0x66, 0x76, 0x55, 0x87, 0x9B, 0x25, 0x77, 0x6D, 0x0B, 0x75, 0x98, 0x8B, 0xA6, 0x39, 0x40, 0x3C, 0x21, 0x7F, 0x2A, 0x24, 0xC1, 0xA5, 0xC1, 0xDC, 0x5A, 0x57, 0x54, 0xF6, 0x03, 0xF6, 0xAD, 0x51, 0x33, 0x40, 0x6D, 0x5C, 0x26, 0x5E, 0x29, 0x92, 0x82, 0xE5, 0x29, 0x13, 0x7D, 0x7D, 0xFE, 0x08, 0x73, 0xBC, 0x5D, 0xC4, 0xE9, 0x2B, 0xD6, 0x71 }
};
//Certificates
static const unsigned char ca3_tpki_cert[0x400] =
{
0x00, 0x01, 0x00, 0x03, 0x70, 0x41, 0x38, 0xEF,
0xBB, 0xBD, 0xA1, 0x6A, 0x98, 0x7D, 0xD9, 0x01,
0x32, 0x6D, 0x1C, 0x94, 0x59, 0x48, 0x4C, 0x88,
0xA2, 0x86, 0x1B, 0x91, 0xA3, 0x12, 0x58, 0x7A,
0xE7, 0x0E, 0xF6, 0x23, 0x7E, 0xC5, 0x0E, 0x10,
0x32, 0xDC, 0x39, 0xDD, 0xE8, 0x9A, 0x96, 0xA8,
0xE8, 0x59, 0xD7, 0x6A, 0x98, 0xA6, 0xE7, 0xE3,
0x6A, 0x0C, 0xFE, 0x35, 0x2C, 0xA8, 0x93, 0x05,
0x82, 0x34, 0xFF, 0x83, 0x3F, 0xCB, 0x3B, 0x03,
0x81, 0x1E, 0x9F, 0x0D, 0xC0, 0xD9, 0xA5, 0x2F,
0x80, 0x45, 0xB4, 0xB2, 0xF9, 0x41, 0x1B, 0x67,
0xA5, 0x1C, 0x44, 0xB5, 0xEF, 0x8C, 0xE7, 0x7B,
0xD6, 0xD5, 0x6B, 0xA7, 0x57, 0x34, 0xA1, 0x85,
0x6D, 0xE6, 0xD4, 0xBE, 0xD6, 0xD3, 0xA2, 0x42,
0xC7, 0xC8, 0x79, 0x1B, 0x34, 0x22, 0x37, 0x5E,
0x5C, 0x77, 0x9A, 0xBF, 0x07, 0x2F, 0x76, 0x95,
0xEF, 0xA0, 0xF7, 0x5B, 0xCB, 0x83, 0x78, 0x9F,
0xC3, 0x0E, 0x3F, 0xE4, 0xCC, 0x83, 0x92, 0x20,
0x78, 0x40, 0x63, 0x89, 0x49, 0xC7, 0xF6, 0x88,
0x56, 0x5F, 0x64, 0x9B, 0x74, 0xD6, 0x3D, 0x8D,
0x58, 0xFF, 0xAD, 0xDA, 0x57, 0x1E, 0x95, 0x54,
0x42, 0x6B, 0x13, 0x18, 0xFC, 0x46, 0x89, 0x83,
0xD4, 0xC8, 0xA5, 0x62, 0x8B, 0x06, 0xB6, 0xFC,
0x5D, 0x50, 0x7C, 0x13, 0xE7, 0xA1, 0x8A, 0xC1,
0x51, 0x1E, 0xB6, 0xD6, 0x2E, 0xA5, 0x44, 0x8F,
0x83, 0x50, 0x14, 0x47, 0xA9, 0xAF, 0xB3, 0xEC,
0xC2, 0x90, 0x3C, 0x9D, 0xD5, 0x2F, 0x92, 0x2A,
0xC9, 0xAC, 0xDB, 0xEF, 0x58, 0xC6, 0x02, 0x18,
0x48, 0xD9, 0x6E, 0x20, 0x87, 0x32, 0xD3, 0xD1,
0xD9, 0xD9, 0xEA, 0x44, 0x0D, 0x91, 0x62, 0x1C,
0x7A, 0x99, 0xDB, 0x88, 0x43, 0xC5, 0x9C, 0x1F,
0x2E, 0x2C, 0x7D, 0x9B, 0x57, 0x7D, 0x51, 0x2C,
0x16, 0x6D, 0x6F, 0x7E, 0x1A, 0xAD, 0x4A, 0x77,
0x4A, 0x37, 0x44, 0x7E, 0x78, 0xFE, 0x20, 0x21,
0xE1, 0x4A, 0x95, 0xD1, 0x12, 0xA0, 0x68, 0xAD,
0xA0, 0x19, 0xF4, 0x63, 0xC7, 0xA5, 0x56, 0x85,
0xAA, 0xBB, 0x68, 0x88, 0xB9, 0x24, 0x64, 0x83,
0xD1, 0x8B, 0x9C, 0x80, 0x6F, 0x47, 0x49, 0x18,
0x33, 0x17, 0x82, 0x34, 0x4A, 0x4B, 0x85, 0x31,
0x33, 0x4B, 0x26, 0x30, 0x32, 0x63, 0xD9, 0xD2,
0xEB, 0x4F, 0x4B, 0xB9, 0x96, 0x02, 0xB3, 0x52,
0xF6, 0xAE, 0x40, 0x46, 0xC6, 0x9A, 0x5E, 0x7E,
0x8E, 0x4A, 0x18, 0xEF, 0x9B, 0xC0, 0xA2, 0xDE,
0xD6, 0x13, 0x10, 0x41, 0x70, 0x12, 0xFD, 0x82,
0x4C, 0xC1, 0x16, 0xCF, 0xB7, 0xC4, 0xC1, 0xF7,
0xEC, 0x71, 0x77, 0xA1, 0x74, 0x46, 0xCB, 0xDE,
0x96, 0xF3, 0xED, 0xD8, 0x8F, 0xCD, 0x05, 0x2F,
0x0B, 0x88, 0x8A, 0x45, 0xFD, 0xAF, 0x2B, 0x63,
0x13, 0x54, 0xF4, 0x0D, 0x16, 0xE5, 0xFA, 0x9C,
0x2C, 0x4E, 0xDA, 0x98, 0xE7, 0x98, 0xD1, 0x5E,
0x60, 0x46, 0xDC, 0x53, 0x63, 0xF3, 0x09, 0x6B,
0x2C, 0x60, 0x7A, 0x9D, 0x8D, 0xD5, 0x5B, 0x15,
0x02, 0xA6, 0xAC, 0x7D, 0x3C, 0xC8, 0xD8, 0xC5,
0x75, 0x99, 0x8E, 0x7D, 0x79, 0x69, 0x10, 0xC8,
0x04, 0xC4, 0x95, 0x23, 0x50, 0x57, 0xE9, 0x1E,
0xCD, 0x26, 0x37, 0xC9, 0xC1, 0x84, 0x51, 0x51,
0xAC, 0x6B, 0x9A, 0x04, 0x90, 0xAE, 0x3E, 0xC6,
0xF4, 0x77, 0x40, 0xA0, 0xDB, 0x0B, 0xA3, 0x6D,
0x07, 0x59, 0x56, 0xCE, 0xE7, 0x35, 0x4E, 0xA3,
0xE9, 0xA4, 0xF2, 0x72, 0x0B, 0x26, 0x55, 0x0C,
0x7D, 0x39, 0x43, 0x24, 0xBC, 0x0C, 0xB7, 0xE9,
0x31, 0x7D, 0x8A, 0x86, 0x61, 0xF4, 0x21, 0x91,
0xFF, 0x10, 0xB0, 0x82, 0x56, 0xCE, 0x3F, 0xD2,
0x5B, 0x74, 0x5E, 0x51, 0x94, 0x90, 0x6B, 0x4D,
0x61, 0xCB, 0x4C, 0x2E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x52, 0x6F, 0x6F, 0x74, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x43, 0x41, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7B, 0xE8, 0xEF, 0x6C,
0xB2, 0x79, 0xC9, 0xE2, 0xEE, 0xE1, 0x21, 0xC6,
0xEA, 0xF4, 0x4F, 0xF6, 0x39, 0xF8, 0x8F, 0x07,
0x8B, 0x4B, 0x77, 0xED, 0x9F, 0x95, 0x60, 0xB0,
0x35, 0x82, 0x81, 0xB5, 0x0E, 0x55, 0xAB, 0x72,
0x11, 0x15, 0xA1, 0x77, 0x70, 0x3C, 0x7A, 0x30,
0xFE, 0x3A, 0xE9, 0xEF, 0x1C, 0x60, 0xBC, 0x1D,
0x97, 0x46, 0x76, 0xB2, 0x3A, 0x68, 0xCC, 0x04,
0xB1, 0x98, 0x52, 0x5B, 0xC9, 0x68, 0xF1, 0x1D,
0xE2, 0xDB, 0x50, 0xE4, 0xD9, 0xE7, 0xF0, 0x71,
0xE5, 0x62, 0xDA, 0xE2, 0x09, 0x22, 0x33, 0xE9,
0xD3, 0x63, 0xF6, 0x1D, 0xD7, 0xC1, 0x9F, 0xF3,
0xA4, 0xA9, 0x1E, 0x8F, 0x65, 0x53, 0xD4, 0x71,
0xDD, 0x7B, 0x84, 0xB9, 0xF1, 0xB8, 0xCE, 0x73,
0x35, 0xF0, 0xF5, 0x54, 0x05, 0x63, 0xA1, 0xEA,
0xB8, 0x39, 0x63, 0xE0, 0x9B, 0xE9, 0x01, 0x01,
0x1F, 0x99, 0x54, 0x63, 0x61, 0x28, 0x70, 0x20,
0xE9, 0xCC, 0x0D, 0xAB, 0x48, 0x7F, 0x14, 0x0D,
0x66, 0x26, 0xA1, 0x83, 0x6D, 0x27, 0x11, 0x1F,
0x20, 0x68, 0xDE, 0x47, 0x72, 0x14, 0x91, 0x51,
0xCF, 0x69, 0xC6, 0x1B, 0xA6, 0x0E, 0xF9, 0xD9,
0x49, 0xA0, 0xF7, 0x1F, 0x54, 0x99, 0xF2, 0xD3,
0x9A, 0xD2, 0x8C, 0x70, 0x05, 0x34, 0x82, 0x93,
0xC4, 0x31, 0xFF, 0xBD, 0x33, 0xF6, 0xBC, 0xA6,
0x0D, 0xC7, 0x19, 0x5E, 0xA2, 0xBC, 0xC5, 0x6D,
0x20, 0x0B, 0xAF, 0x6D, 0x06, 0xD0, 0x9C, 0x41,
0xDB, 0x8D, 0xE9, 0xC7, 0x20, 0x15, 0x4C, 0xA4,
0x83, 0x2B, 0x69, 0xC0, 0x8C, 0x69, 0xCD, 0x3B,
0x07, 0x3A, 0x00, 0x63, 0x60, 0x2F, 0x46, 0x2D,
0x33, 0x80, 0x61, 0xA5, 0xEA, 0x6C, 0x91, 0x5C,
0xD5, 0x62, 0x35, 0x79, 0xC3, 0xEB, 0x64, 0xCE,
0x44, 0xEF, 0x58, 0x6D, 0x14, 0xBA, 0xAA, 0x88,
0x34, 0x01, 0x9B, 0x3E, 0xEB, 0xEE, 0xD3, 0x79,
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char xsC_tpki_cert[0x300] =
{
0x00, 0x01, 0x00, 0x04, 0x91, 0x9E, 0xBE, 0x46,
0x4A, 0xD0, 0xF5, 0x52, 0xCD, 0x1B, 0x72, 0xE7,
0x88, 0x49, 0x10, 0xCF, 0x55, 0xA9, 0xF0, 0x2E,
0x50, 0x78, 0x96, 0x41, 0xD8, 0x96, 0x68, 0x3D,
0xC0, 0x05, 0xBD, 0x0A, 0xEA, 0x87, 0x07, 0x9D,
0x8A, 0xC2, 0x84, 0xC6, 0x75, 0x06, 0x5F, 0x74,
0xC8, 0xBF, 0x37, 0xC8, 0x80, 0x44, 0x40, 0x95,
0x02, 0xA0, 0x22, 0x98, 0x0B, 0xB8, 0xAD, 0x48,
0x38, 0x3F, 0x6D, 0x28, 0xA7, 0x9D, 0xE3, 0x96,
0x26, 0xCC, 0xB2, 0xB2, 0x2A, 0x0F, 0x19, 0xE4,
0x10, 0x32, 0xF0, 0x94, 0xB3, 0x9F, 0xF0, 0x13,
0x31, 0x46, 0xDE, 0xC8, 0xF6, 0xC1, 0xA9, 0xD5,
0x5C, 0xD2, 0x8D, 0x9E, 0x1C, 0x47, 0xB3, 0xD1,
0x1F, 0x4F, 0x54, 0x26, 0xC2, 0xC7, 0x80, 0x13,
0x5A, 0x27, 0x75, 0xD3, 0xCA, 0x67, 0x9B, 0xC7,
0xE8, 0x34, 0xF0, 0xE0, 0xFB, 0x58, 0xE6, 0x88,
0x60, 0xA7, 0x13, 0x30, 0xFC, 0x95, 0x79, 0x17,
0x93, 0xC8, 0xFB, 0xA9, 0x35, 0xA7, 0xA6, 0x90,
0x8F, 0x22, 0x9D, 0xEE, 0x2A, 0x0C, 0xA6, 0xB9,
0xB2, 0x3B, 0x12, 0xD4, 0x95, 0xA6, 0xFE, 0x19,
0xD0, 0xD7, 0x26, 0x48, 0x21, 0x68, 0x78, 0x60,
0x5A, 0x66, 0x53, 0x8D, 0xBF, 0x37, 0x68, 0x99,
0x90, 0x5D, 0x34, 0x45, 0xFC, 0x5C, 0x72, 0x7A,
0x0E, 0x13, 0xE0, 0xE2, 0xC8, 0x97, 0x1C, 0x9C,
0xFA, 0x6C, 0x60, 0x67, 0x88, 0x75, 0x73, 0x2A,
0x4E, 0x75, 0x52, 0x3D, 0x2F, 0x56, 0x2F, 0x12,
0xAA, 0xBD, 0x15, 0x73, 0xBF, 0x06, 0xC9, 0x40,
0x54, 0xAE, 0xFA, 0x81, 0xA7, 0x14, 0x17, 0xAF,
0x9A, 0x4A, 0x06, 0x6D, 0x0F, 0xFC, 0x5A, 0xD6,
0x4B, 0xAB, 0x28, 0xB1, 0xFF, 0x60, 0x66, 0x1F,
0x44, 0x37, 0xD4, 0x9E, 0x1E, 0x0D, 0x94, 0x12,
0xEB, 0x4B, 0xCA, 0xCF, 0x4C, 0xFD, 0x6A, 0x34,
0x08, 0x84, 0x79, 0x82, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x43, 0x41, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x58, 0x53, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x63, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x13, 0x7A, 0x08, 0x94,
0xAD, 0x50, 0x5B, 0xB6, 0xC6, 0x7E, 0x2E, 0x5B,
0xDD, 0x6A, 0x3B, 0xEC, 0x43, 0xD9, 0x10, 0xC7,
0x72, 0xE9, 0xCC, 0x29, 0x0D, 0xA5, 0x85, 0x88,
0xB7, 0x7D, 0xCC, 0x11, 0x68, 0x0B, 0xB3, 0xE2,
0x9F, 0x4E, 0xAB, 0xBB, 0x26, 0xE9, 0x8C, 0x26,
0x01, 0x98, 0x5C, 0x04, 0x1B, 0xB1, 0x43, 0x78,
0xE6, 0x89, 0x18, 0x1A, 0xAD, 0x77, 0x05, 0x68,
0xE9, 0x28, 0xA2, 0xB9, 0x81, 0x67, 0xEE, 0x3E,
0x10, 0xD0, 0x72, 0xBE, 0xEF, 0x1F, 0xA2, 0x2F,
0xA2, 0xAA, 0x3E, 0x13, 0xF1, 0x1E, 0x18, 0x36,
0xA9, 0x2A, 0x42, 0x81, 0xEF, 0x70, 0xAA, 0xF4,
0xE4, 0x62, 0x99, 0x82, 0x21, 0xC6, 0xFB, 0xB9,
0xBD, 0xD0, 0x17, 0xE6, 0xAC, 0x59, 0x04, 0x94,
0xE9, 0xCE, 0xA9, 0x85, 0x9C, 0xEB, 0x2D, 0x2A,
0x4C, 0x17, 0x66, 0xF2, 0xC3, 0x39, 0x12, 0xC5,
0x8F, 0x14, 0xA8, 0x03, 0xE3, 0x6F, 0xCC, 0xDC,
0xCC, 0xDC, 0x13, 0xFD, 0x7A, 0xE7, 0x7C, 0x7A,
0x78, 0xD9, 0x97, 0xE6, 0xAC, 0xC3, 0x55, 0x57,
0xE0, 0xD3, 0xE9, 0xEB, 0x64, 0xB4, 0x3C, 0x92,
0xF4, 0xC5, 0x0D, 0x67, 0xA6, 0x02, 0xDE, 0xB3,
0x91, 0xB0, 0x66, 0x61, 0xCD, 0x32, 0x88, 0x0B,
0xD6, 0x49, 0x12, 0xAF, 0x1C, 0xBC, 0xB7, 0x16,
0x2A, 0x06, 0xF0, 0x25, 0x65, 0xD3, 0xB0, 0xEC,
0xE4, 0xFC, 0xEC, 0xDD, 0xAE, 0x8A, 0x49, 0x34,
0xDB, 0x8E, 0xE6, 0x7F, 0x30, 0x17, 0x98, 0x62,
0x21, 0x15, 0x5D, 0x13, 0x1C, 0x6C, 0x3F, 0x09,
0xAB, 0x19, 0x45, 0xC2, 0x06, 0xAC, 0x70, 0xC9,
0x42, 0xB3, 0x6F, 0x49, 0xA1, 0x18, 0x3B, 0xCD,
0x78, 0xB6, 0xE4, 0xB4, 0x7C, 0x6C, 0x5C, 0xAC,
0x0F, 0x8D, 0x62, 0xF8, 0x97, 0xC6, 0x95, 0x3D,
0xD1, 0x2F, 0x28, 0xB7, 0x0C, 0x5B, 0x7D, 0xF7,
0x51, 0x81, 0x9A, 0x98, 0x34, 0x65, 0x26, 0x25,
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char cpB_tpki_cert[0x300] =
{
0x00, 0x01, 0x00, 0x04, 0x2E, 0xA6, 0x6C, 0x66,
0xCF, 0xF3, 0x35, 0x79, 0x7D, 0x04, 0x97, 0xB7,
0x7A, 0x19, 0x7F, 0x9F, 0xE5, 0x1A, 0xB5, 0xA4,
0x13, 0x75, 0xDC, 0x73, 0xFD, 0x9E, 0x0B, 0x10,
0x66, 0x9B, 0x1B, 0x9A, 0x5B, 0x7E, 0x8A, 0xB2,
0x8F, 0x01, 0xB6, 0x7B, 0x62, 0x54, 0xC1, 0x4A,
0xA1, 0x33, 0x14, 0x18, 0xF2, 0x5B, 0xA5, 0x49,
0x00, 0x4C, 0x37, 0x8D, 0xD7, 0x2F, 0x0C, 0xE6,
0x3B, 0x1F, 0x70, 0x91, 0xAA, 0xFE, 0x38, 0x09,
0xB7, 0xAC, 0x6C, 0x28, 0x76, 0xA6, 0x1D, 0x60,
0x51, 0x6C, 0x43, 0xA6, 0x37, 0x29, 0x16, 0x2D,
0x28, 0x0B, 0xE2, 0x1B, 0xE8, 0xE2, 0xFE, 0x05,
0x7D, 0x8E, 0xB6, 0xE2, 0x04, 0x24, 0x22, 0x45,
0x73, 0x1A, 0xB6, 0xFE, 0xE3, 0x0E, 0x53, 0x35,
0x37, 0x3E, 0xEB, 0xA9, 0x70, 0xD5, 0x31, 0xBB,
0xA2, 0xCB, 0x22, 0x2D, 0x96, 0x84, 0x38, 0x7D,
0x5F, 0x2A, 0x1B, 0xF7, 0x52, 0x00, 0xCE, 0x06,
0x56, 0xE3, 0x90, 0xCE, 0x19, 0x13, 0x5B, 0x59,
0xE1, 0x4F, 0x0F, 0xA5, 0xC1, 0x28, 0x1A, 0x73,
0x86, 0xCC, 0xD1, 0xC8, 0xEC, 0x3F, 0xAD, 0x70,
0xFB, 0xCE, 0x74, 0xDE, 0xEE, 0x1F, 0xD0, 0x5F,
0x46, 0x33, 0x0B, 0x51, 0xF9, 0xB7, 0x9E, 0x1D,
0xDB, 0xF4, 0xE3, 0x3F, 0x14, 0x88, 0x9D, 0x05,
0x28, 0x29, 0x24, 0xC5, 0xF5, 0xDC, 0x27, 0x66,
0xEF, 0x06, 0x27, 0xD7, 0xEE, 0xDC, 0x73, 0x6E,
0x67, 0xC2, 0xE5, 0xB9, 0x38, 0x34, 0x66, 0x80,
0x72, 0x21, 0x6D, 0x1C, 0x78, 0xB8, 0x23, 0xA0,
0x72, 0xD3, 0x4F, 0xF3, 0xEC, 0xF9, 0xBD, 0x11,
0xA2, 0x9A, 0xF1, 0x6C, 0x33, 0xBD, 0x09, 0xAF,
0xB2, 0xD7, 0x4D, 0x53, 0x4E, 0x02, 0x7C, 0x19,
0x24, 0x0D, 0x59, 0x5A, 0x68, 0xEB, 0xB3, 0x05,
0xAC, 0xC4, 0x4A, 0xB3, 0x8A, 0xB8, 0x20, 0xC6,
0xD4, 0x26, 0x56, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x43, 0x41, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x43, 0x50, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x62, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x13, 0x7A, 0x08, 0x0B,
0xA6, 0x89, 0xC5, 0x90, 0xFD, 0x0B, 0x2F, 0x0D,
0x4F, 0x56, 0xB6, 0x32, 0xFB, 0x93, 0x4E, 0xD0,
0x73, 0x95, 0x17, 0xB3, 0x3A, 0x79, 0xDE, 0x04,
0x0E, 0xE9, 0x2D, 0xC3, 0x1D, 0x37, 0xC7, 0xF7,
0x3B, 0xF0, 0x4B, 0xD3, 0xE4, 0x4E, 0x20, 0xAB,
0x5A, 0x6F, 0xEA, 0xF5, 0x98, 0x4C, 0xC1, 0xF6,
0x06, 0x2E, 0x9A, 0x9F, 0xE5, 0x6C, 0x32, 0x85,
0xDC, 0x6F, 0x25, 0xDD, 0xD5, 0xD0, 0xBF, 0x9F,
0xE2, 0xEF, 0xE8, 0x35, 0xDF, 0x26, 0x34, 0xED,
0x93, 0x7F, 0xAB, 0x02, 0x14, 0xD1, 0x04, 0x80,
0x9C, 0xF7, 0x4B, 0x86, 0x0E, 0x6B, 0x04, 0x83,
0xF4, 0xCD, 0x2D, 0xAB, 0x2A, 0x96, 0x02, 0xBC,
0x56, 0xF0, 0xD6, 0xBD, 0x94, 0x6A, 0xED, 0x6E,
0x0B, 0xE4, 0xF0, 0x8F, 0x26, 0x68, 0x6B, 0xD0,
0x9E, 0xF7, 0xDB, 0x32, 0x5F, 0x82, 0xB1, 0x8F,
0x6A, 0xF2, 0xED, 0x52, 0x5B, 0xFD, 0x82, 0x8B,
0x65, 0x3F, 0xEE, 0x6E, 0xCE, 0x40, 0x0D, 0x5A,
0x48, 0xFF, 0xE2, 0x2D, 0x53, 0x8B, 0xB5, 0x33,
0x5B, 0x41, 0x53, 0x34, 0x2D, 0x43, 0x35, 0xAC,
0xF5, 0x90, 0xD0, 0xD3, 0x0A, 0xE2, 0x04, 0x3C,
0x7F, 0x5A, 0xD2, 0x14, 0xFC, 0x9C, 0x0F, 0xE6,
0xFA, 0x40, 0xA5, 0xC8, 0x65, 0x06, 0xCA, 0x63,
0x69, 0xBC, 0xEE, 0x44, 0xA3, 0x2D, 0x9E, 0x69,
0x5C, 0xF0, 0x0B, 0x4F, 0xD7, 0x9A, 0xDB, 0x56,
0x8D, 0x14, 0x9C, 0x20, 0x28, 0xA1, 0x4C, 0x9D,
0x71, 0xB8, 0x50, 0xCA, 0x36, 0x5B, 0x37, 0xF7,
0x0B, 0x65, 0x77, 0x91, 0xFC, 0x5D, 0x72, 0x8C,
0x4E, 0x18, 0xFD, 0x22, 0x55, 0x7C, 0x40, 0x62,
0xD7, 0x47, 0x71, 0x53, 0x3C, 0x70, 0x17, 0x9D,
0x3D, 0xAE, 0x8F, 0x92, 0xB1, 0x17, 0xE4, 0x5C,
0xB3, 0x32, 0xF3, 0xB3, 0xC2, 0xA2, 0x2E, 0x70,
0x5C, 0xFE, 0xC6, 0x6F, 0x6D, 0xA3, 0x77, 0x2B,
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+52
View File
@@ -0,0 +1,52 @@
#include "lib.h"
#include "ncch_build.h"
#include "romfs.h"
#include "romfs_gen.h"
#include "romfs_import.h"
void FreeRomFsCtx(romfs_buildctx *ctx);
// RomFs Build Functions
int SetupRomFs(ncch_settings *ncchset, romfs_buildctx *ctx)
{
ctx->verbose = ncchset->options.verbose;
ctx->output = NULL;
ctx->romfsSize = 0;
// If Not Using RomFS Return
if(!ncchset->options.UseRomFS)
return 0;
if(ncchset->componentFilePtrs.romfs)// The user has specified a pre-built RomFs Binary
return PrepareImportRomFsBinaryFromFile(ncchset,ctx);
else // Otherwise build ROMFS
return PrepareBuildRomFsBinary(ncchset,ctx);
}
int BuildRomFs(romfs_buildctx *ctx)
{
// If Not Using RomFS Return
if(!ctx->romfsSize)
return 0;
int result = 0;
if(ctx->ImportRomfsBinary) // The user has specified a pre-built RomFs Binary
result = ImportRomFsBinaryFromFile(ctx);
else // Otherwise build ROMFS
result = BuildRomFsBinary(ctx);
FreeRomFsCtx(ctx);
return result;
}
void FreeRomFsCtx(romfs_buildctx *ctx)
{
if(ctx->fs){
FreeDir(ctx->fs);
free(ctx->fs);
}
}
+117
View File
@@ -0,0 +1,117 @@
#pragma once
#include "romfs_fs.h"
typedef enum
{
INVALID_ROMFS_FILE = -10,
} romfs_errors;
// IVFC Structs
typedef struct
{
u64 size;
u64 offset;
u64 logicalOffset;
u8 *pos;
u8 reserved[8];
} ivfc_level;
typedef struct
{
u8 logicalOffset[8];
u8 hashDataSize[8];
u8 blockSize[4];
u8 reserved[4];
} ivfc_levelheader;
typedef struct
{
u8 magic[4];
u8 id[4];
u8 masterHashSize[4];
ivfc_levelheader level[3];
u8 optionalSize[4];
u8 reserved[4];
} ivfc_hdr;
typedef struct
{
u8 offset[4];
u8 size[4];
} romfs_sectionheader;
typedef struct
{
u8 headersize[4];
romfs_sectionheader section[4]; // 8*4 = 0x20
u8 dataoffset[4];
} romfs_infoheader; //sizeof(romfs_infoheader) = 0x28
typedef struct
{
u8 parentoffset[4];
u8 siblingoffset[4];
u8 childoffset[4];
u8 fileoffset[4];
u8 hashoffset[4];
u8 namesize[4];
//u8 name[ROMFS_MAXNAMESIZE];
} romfs_direntry; //sizeof(romfs_direntry) = 0x18
typedef struct
{
u8 parentdiroffset[4];
u8 siblingoffset[4];
u8 dataoffset[8];
u8 datasize[8];
u8 hashoffset[4];
u8 namesize[4];
//u8 name[ROMFS_MAXNAMESIZE];
} romfs_fileentry; //sizeof(romfs_fileentry) = 0x20
typedef struct
{
bool verbose;
u8 *output;
u64 romfsSize;
u64 romfsHeaderSize;
/* For Importing ROMFS Binaries */
bool ImportRomfsBinary;
FILE *romfsBinary;
/* For Creating ROMFS Binaries */
ivfc_hdr *ivfcHdr;
romfs_infoheader *romfsHdr;
romfs_dir *fs;
u8 *dirHashTable;
u32 m_dirHashTable;
u8 *dirTable;
u32 dirNum;
u32 m_dirTableLen;
u32 u_dirTableLen;
u8 *fileHashTable;
u32 m_fileHashTable;
u8 *fileTable;
u32 fileNum;
u32 m_fileTableLen;
u32 u_fileTableLen;
u8 *data;
u64 m_dataLen;
u64 u_dataLen;
// Levels
ivfc_level level[4];
} romfs_buildctx;
int SetupRomFs(ncch_settings *ncchset, romfs_buildctx *ctx);
int BuildRomFs(romfs_buildctx *ctx);
+164
View File
@@ -0,0 +1,164 @@
#include "lib.h"
#include "romfs_fs.h"
/* This is the FS interface for ROMFS generation */
/* Tested working on Windows/Linux/OSX */
int PopulateDir(romfs_dir *dir);
int InitDir(romfs_dir *dir);
int ManageDir(romfs_dir *dir);
int InitDir(romfs_dir *dir)
{
dir->m_child = 10;
dir->u_child = 0;
dir->child = calloc(dir->m_child,sizeof(romfs_dir));
dir->m_file = 10;
dir->u_file = 0;
dir->file = calloc(dir->m_file,sizeof(romfs_file));
if (dir->child == NULL || dir->file == NULL)
return MEM_ERROR;
return 0;
}
int ManageDir(romfs_dir *dir)
{
if (dir->u_child >= dir->m_child) {
dir->m_child = 2 * dir->u_child;
dir->child = realloc(dir->child, dir->m_child*sizeof(romfs_dir));
}
if (dir->u_file >= dir->m_file) {
dir->m_file = 2 * dir->u_file;
dir->file = realloc(dir->file, dir->m_file*sizeof(romfs_file));
}
if (dir->child == NULL || dir->file == NULL)
return MEM_ERROR;
return 0;
}
int OpenRootDir(const char *path, romfs_dir *dir)
{
// Create native FS path
dir->path = os_CopyConvertCharStr(path);
// Copy romfs name (empty string)
dir->name = utf16_CopyStr(ROMFS_EMPTY_PATH);
dir->namesize = 0;
return PopulateDir(dir);
}
int PopulateDir(romfs_dir *dir)
{
_OSDIR *dp, *tmp_dp;
struct _osdirent *entry;
if (InitDir(dir))
return MEM_ERROR;
// Open Directory
if((dp = os_opendir(dir->path)) == NULL)
{
printf("[ROMFS] Failed to open directory: \"");
os_fputs(dir->path, stdout);
printf("\"\n");
return -1;
}
// Process Entries
while ((entry = os_readdir(dp)) != NULL)
{
// Skip if "." or ".."
if (os_strcmp(entry->d_name, OS_CURRENT_DIR_PATH) == 0 || os_strcmp(entry->d_name, OS_PARENT_DIR_PATH) == 0)
continue;
// Ensures that there is always memory for child directory and file structs
if (ManageDir(dir))
return MEM_ERROR;
// Get native FS path
oschar_t *path = os_AppendToPath(dir->path, entry->d_name);
// Opening directory with fs path to test if directory
if ((tmp_dp = os_opendir(path)) != NULL) {
os_closedir(tmp_dp);
dir->child[dir->u_child].path = path;
dir->child[dir->u_child].name = utf16_CopyConvertOsStr(entry->d_name);
dir->child[dir->u_child].namesize = os_strlen(entry->d_name)*sizeof(utf16char_t);
dir->u_child++;
// Populate directory
PopulateDir(&dir->child[dir->u_child-1]);
}
// Otherwise this is a file
else {
dir->file[dir->u_file].path = path;
dir->file[dir->u_file].name = utf16_CopyConvertOsStr(entry->d_name);
dir->file[dir->u_file].namesize = os_strlen(entry->d_name)*sizeof(utf16char_t);
dir->file[dir->u_file].size = os_fsize(path);
dir->u_file++;
}
}
os_closedir(dp);
return 0;
}
void PrintDir(romfs_dir *dir, u32 depth)
{
for(u32 i = 0; i < depth; i++)
printf(" ");
if (depth > 0)
utf16_fputs(dir->name, stdout);
else
printf("romfs:");
putchar('\n');
if(dir->u_file)
{
for(u32 i = 0; i < dir->u_file; i++)
{
for(u32 j = 0; j < depth+1; j++)
printf(" ");
utf16_fputs(dir->file[i].name, stdout);
printf(" (0x%"PRIx64")\n", dir->file[i].size);
}
}
if(dir->u_child)
{
for(u32 i = 0; i < dir->u_child; i++)
PrintDir(&dir->child[i],depth+1);
}
}
void FreeDir(romfs_dir *dir)
{
//printf("DIR!! free file names\n");
for(u32 i = 0; i < dir->u_file; i++)
{
free(dir->file[i].path);
free(dir->file[i].name);
}
//printf("free file struct\n");
free(dir->file);
//printf("free dir names and\n");
for(u32 i = 0; i < dir->u_child; i++)
{
free(dir->child[i].path);
free(dir->child[i].name);
FreeDir(&dir->child[i]);
}
//printf("free dir struct\n");
free(dir->child);
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include "oschar.h"
struct romfs_file
{
oschar_t *path;
utf16char_t *name;
u32 namesize;
u64 size;
};
struct romfs_dir
{
oschar_t *path;
utf16char_t *name;
u32 namesize;
struct romfs_dir *child;
u32 m_child;
u32 u_child;
struct romfs_file *file;
u32 m_file;
u32 u_file;
};
typedef struct romfs_file romfs_file;
typedef struct romfs_dir romfs_dir;
static const utf16char_t ROMFS_EMPTY_PATH[2] = { 0 };
static const oschar_t OS_EMPTY_PATH[2] = { 0 };
static const oschar_t OS_CURRENT_DIR_PATH[2] = { '.' };
static const oschar_t OS_PARENT_DIR_PATH[3] = { '.', '.' };
int OpenRootDir(const char *path, romfs_dir *dir);
void PrintDir(romfs_dir *dir, u32 depth);
void FreeDir(romfs_dir *dir);
+475
View File
@@ -0,0 +1,475 @@
#include "lib.h"
#include "ncch_build.h"
#include "romfs.h"
const int ROMFS_BLOCK_SIZE = 0x1000;
const unsigned int ROMFS_UNUSED_ENTRY = 0xffffffff;
// Build
bool IsFileWanted(romfs_file *file, void *filter_criteria);
bool IsDirWanted(romfs_dir *dir, void *filter_criteria);
void CalcDirSize(romfs_buildctx *ctx, romfs_dir *fs);
void CalcRomfsSize(romfs_buildctx *ctx);
int FilterRomFS(romfs_dir *fs_raw, romfs_dir *fs_filtered, void *filter_criteria);
void AddFileToRomfs(romfs_buildctx *ctx, romfs_file *file, u32 parent, u32 sibling);
void AddDirToRomfs(romfs_buildctx *ctx, romfs_dir *fs, u32 parent, u32 sibling);
void AddDirChildrenToRomfs(romfs_buildctx *ctx, romfs_dir *fs, u32 parent, u32 dir);
void PopulateHashTable(romfs_buildctx *ctx);
void PopulateRomfs(romfs_buildctx *ctx);
void BuildRomfsHeader(romfs_buildctx *ctx);
void BuildIvfcHeader(romfs_buildctx *ctx);
void GenIvfcHashTree(romfs_buildctx *ctx);
u32 CalcPathHash(u32 parent, const utf16char_t* path);
int PrepareBuildRomFsBinary(ncch_settings *ncchset, romfs_buildctx *ctx)
{
/* FS Structures */
void *filter_criteria = NULL;
romfs_dir *fs_raw = calloc(1,sizeof(romfs_dir));
ctx->fs = calloc(1,sizeof(romfs_dir));
/* Import FS and process */
OpenRootDir(ncchset->rsfSet->RomFs.RootPath,fs_raw);
FilterRomFS(fs_raw,ctx->fs,filter_criteria);
/* free unfiltered FS */
FreeDir(fs_raw);
free(fs_raw);
/* Abort romfs making, if no wanted files/directories were found */
if(ctx->fs->u_file == 0 && ctx->fs->u_child == 0){
ctx->romfsSize = 0;
return 0;
}
CalcRomfsSize(ctx);
if (ctx->verbose) {
printf("[ROMFS] File System:\n");
printf(" > Size: %"PRIx64"\n", ctx->romfsSize);
printf(" > Directories: %d\n", ctx->dirNum);
printf(" > Files: %d\n", ctx->fileNum);
}
return 0;
}
int BuildRomFsBinary(romfs_buildctx *ctx)
{
/* Decide IVFC Level Actual Offsets */
ctx->level[0].offset = 0;
ctx->level[3].offset = ctx->level[0].offset + align(ctx->level[0].size, ROMFS_BLOCK_SIZE);
ctx->level[1].offset = ctx->level[3].offset + align(ctx->level[3].size, ROMFS_BLOCK_SIZE);
ctx->level[2].offset = ctx->level[1].offset + align(ctx->level[1].size, ROMFS_BLOCK_SIZE);
/* Decide IVFC Level Logical Offsets */
for(int i = 1; i < 4; i++){
if(i == 1)
ctx->level[i].logicalOffset = 0;
else
ctx->level[i].logicalOffset = align(ctx->level[i-1].logicalOffset + ctx->level[i-1].size,ROMFS_BLOCK_SIZE);
}
/* Setup IVFC Level Ptrs */
for(int i = 0; i < 4; i++){
ctx->level[i].pos = (ctx->output + ctx->level[i].offset);
if(i == 0)
ctx->level[i].pos += align(sizeof(ivfc_hdr),0x10);
}
/* Build Romfs */
ctx->romfsHdr = (romfs_infoheader*)(ctx->level[3].pos);
BuildRomfsHeader(ctx);
PopulateRomfs(ctx);
/* Finalise by building IVFC hash tree */
ctx->ivfcHdr = (ivfc_hdr*)(ctx->output + ctx->level[0].offset);
BuildIvfcHeader(ctx);
GenIvfcHashTree(ctx);
return 0;
}
bool IsFileWanted(romfs_file *file, void *filter_criteria)
{
return true;
}
bool IsDirWanted(romfs_dir *dir, void *filter_criteria)
{
bool ret = false;
for(u32 i = 0; i < dir->u_file; i++)
{
if(IsFileWanted(&dir->file[i],filter_criteria))
{
ret = true;
break;
}
}
for(u32 i = 0; i < dir->u_child; i++)
{
if(IsDirWanted(&dir->child[i],filter_criteria))
{
ret = true;
break;
}
}
return ret;
}
void CalcDirSize(romfs_buildctx *ctx, romfs_dir *fs)
{
if(ctx->m_dirTableLen == 0)
ctx->m_dirTableLen = sizeof(romfs_direntry);
else
ctx->m_dirTableLen += sizeof(romfs_direntry) + align(fs->namesize,4);
for(u32 i = 0; i < fs->u_file; i++)
{
ctx->m_fileTableLen += sizeof(romfs_fileentry) + align(fs->file[i].namesize,4);
if(fs->file[i].size)
ctx->m_dataLen = align(ctx->m_dataLen,0x10) + fs->file[i].size;
}
for(u32 i = 0; i < fs->u_child; i++)
{
CalcDirSize(ctx,&fs->child[i]);
}
ctx->fileNum += fs->u_file;
ctx->dirNum += fs->u_child;
}
u32 GetHashTableCount(u32 num)
{
u32 count = num;
if (num < 3)
count = 3;
else if (count < 19)
count |= 1;
else {
while (count % 2 == 0 || count % 3 == 0 || count % 5 == 0 || count % 7 == 0 || count % 11 == 0 || count % 13 == 0 || count % 17 == 0)
count++;
}
return count;
}
void CalcRomfsSize(romfs_buildctx *ctx)
{
ctx->dirNum = 1; // root dir
CalcDirSize(ctx,ctx->fs);
ctx->m_dirHashTable = GetHashTableCount(ctx->dirNum);
ctx->m_fileHashTable = GetHashTableCount(ctx->fileNum);
u32 romfsHdrSize = align(sizeof(romfs_infoheader) + ctx->m_dirHashTable*sizeof(u32) + ctx->m_dirTableLen + ctx->m_fileHashTable*sizeof(u32) + ctx->m_fileTableLen,0x10);
ctx->level[3].size = romfsHdrSize + ctx->m_dataLen; // data
ctx->level[2].size = align(ctx->level[3].size,ROMFS_BLOCK_SIZE) / ROMFS_BLOCK_SIZE * SHA_256_LEN ;
ctx->level[1].size = align(ctx->level[2].size,ROMFS_BLOCK_SIZE) / ROMFS_BLOCK_SIZE * SHA_256_LEN ;
ctx->level[0].size = align(ctx->level[1].size,ROMFS_BLOCK_SIZE) / ROMFS_BLOCK_SIZE * SHA_256_LEN + align(sizeof(ivfc_hdr),0x10); // hdr
ctx->romfsHeaderSize = ctx->level[0].size;
ctx->romfsSize = 0;
for(int i = 0; i < 4; i++)
ctx->romfsSize += align(ctx->level[i].size,ROMFS_BLOCK_SIZE);
}
int FilterRomFS(romfs_dir *fs_raw, romfs_dir *fs_filtered, void *filter_criteria)
{
memset(fs_filtered,0,sizeof(romfs_dir));
if(!IsDirWanted(fs_raw,filter_criteria))
return 0;
fs_filtered->path = os_CopyStr(fs_raw->path);
fs_filtered->namesize = fs_raw->namesize;
fs_filtered->name = utf16_CopyStr(fs_raw->name);
fs_filtered->u_child = 0;
fs_filtered->m_child = fs_raw->u_child;
fs_filtered->child = calloc(fs_filtered->m_child,sizeof(romfs_dir));
fs_filtered->u_file = 0;
fs_filtered->m_file = fs_raw->u_file;
fs_filtered->file = calloc(fs_filtered->m_file,sizeof(romfs_file));
for(u32 i = 0; i < fs_raw->u_child; i++)
{
if(IsDirWanted(&fs_raw->child[i],filter_criteria))
{
FilterRomFS(&fs_raw->child[i],&fs_filtered->child[fs_filtered->u_child],filter_criteria);
fs_filtered->u_child++;
}
}
for(u32 i = 0; i < fs_raw->u_file; i++)
{
if(IsFileWanted(&fs_raw->file[i],filter_criteria))
{
fs_filtered->file[fs_filtered->u_file].path = os_CopyStr(fs_raw->file[i].path);
fs_filtered->file[fs_filtered->u_file].namesize = fs_raw->file[i].namesize;
fs_filtered->file[fs_filtered->u_file].name = utf16_CopyStr(fs_raw->file[i].name);
fs_filtered->file[fs_filtered->u_file].size = fs_raw->file[i].size;
fs_filtered->u_file++;
}
}
return 0;
}
void BuildRomfsHeader(romfs_buildctx *ctx)
{
u32 level3_pos = 0;
u32_to_u8(ctx->romfsHdr->headersize,sizeof(romfs_infoheader),LE);
level3_pos += sizeof(romfs_infoheader);
for(int i = 0; i < 4; i++){
if(i == 0){
ctx->dirHashTable = ctx->level[3].pos + level3_pos;
u32_to_u8(ctx->romfsHdr->section[i].offset,level3_pos,LE);
u32_to_u8(ctx->romfsHdr->section[i].size,ctx->m_dirHashTable*sizeof(u32),LE);
level3_pos += ctx->m_dirHashTable*sizeof(u32);
}
else if(i == 1 && ctx->m_dirTableLen){
ctx->dirTable = ctx->level[3].pos + level3_pos;
u32_to_u8(ctx->romfsHdr->section[i].offset,level3_pos,LE);
u32_to_u8(ctx->romfsHdr->section[i].size,ctx->m_dirTableLen,LE);
level3_pos += ctx->m_dirTableLen;
}
else if(i == 2){
ctx->fileHashTable = ctx->level[3].pos + level3_pos;
u32_to_u8(ctx->romfsHdr->section[i].offset,level3_pos,LE);
u32_to_u8(ctx->romfsHdr->section[i].size,ctx->m_fileHashTable*sizeof(u32),LE);
level3_pos += ctx->m_fileHashTable*sizeof(u32);
}
else if(i == 3 && ctx->m_fileTableLen){
ctx->fileTable = ctx->level[3].pos + level3_pos;
u32_to_u8(ctx->romfsHdr->section[i].offset,level3_pos,LE);
u32_to_u8(ctx->romfsHdr->section[i].size,ctx->m_fileTableLen,LE);
level3_pos += ctx->m_fileTableLen;
}
else{
u32_to_u8(ctx->romfsHdr->section[i].offset,0,LE);
u32_to_u8(ctx->romfsHdr->section[i].size,0,LE);
}
}
ctx->data = ctx->level[3].pos + align(level3_pos,0x10);
u32_to_u8(ctx->romfsHdr->dataoffset,align(level3_pos,0x10),LE);
for (u32 i = 0; i < ctx->m_dirHashTable; i++) {
u32_to_u8(ctx->dirHashTable+i*4, ROMFS_UNUSED_ENTRY, LE);
}
for (u32 i = 0; i < ctx->m_fileHashTable; i++) {
u32_to_u8(ctx->fileHashTable+i*4, ROMFS_UNUSED_ENTRY, LE);
}
}
u32 GetFileHashTableIndex(romfs_buildctx *ctx, u32 parent, const utf16char_t *path)
{
u32 hash = CalcPathHash(parent, path);
return hash % ctx->m_fileHashTable;
}
u32 GetDirHashTableIndex(romfs_buildctx *ctx, u32 parent, const utf16char_t* path)
{
u32 hash = CalcPathHash(parent, path);
return hash % ctx->m_dirHashTable;
}
void AddFileToRomfs(romfs_buildctx *ctx, romfs_file *file, u32 parent, u32 sibling)
{
romfs_fileentry *entry = (romfs_fileentry*)(ctx->fileTable + ctx->u_fileTableLen);
u32_to_u8(entry->parentdiroffset,parent,LE);
u32_to_u8(entry->siblingoffset,sibling,LE);
/* Import name */
u32_to_u8(entry->namesize,file->namesize,LE);
u8 *name_pos = (u8*)(ctx->fileTable + ctx->u_fileTableLen + sizeof(romfs_fileentry));
memset(name_pos,0,align(file->namesize,4));
memcpy(name_pos,(u8*)file->name,file->namesize);
/* Set hash data */
u32 hashindex = GetFileHashTableIndex(ctx, parent, file->name);
u32_to_u8(entry->hashoffset, u8_to_u32(ctx->fileHashTable + hashindex*4, LE), LE);
u32_to_u8(ctx->fileHashTable + hashindex*4, ctx->u_fileTableLen, LE);
/* Import data */
if(file->size)
{
ctx->u_dataLen = align(ctx->u_dataLen,0x10); // Padding
u64_to_u8(entry->dataoffset,ctx->u_dataLen,LE);
u64_to_u8(entry->datasize,file->size,LE);
u8 *data_pos = (ctx->data + ctx->u_dataLen);
if (ctx->verbose) {
printf("[ROMFS] Reading \"");
os_fputs(file->path, stdout);
printf("\"... ");
}
FILE *fp = os_fopen(file->path, OS_MODE_READ);
fread(data_pos, file->size, 1, fp);
fclose(fp);
if (ctx->verbose) {
printf("Done!\n");
}
ctx->u_dataLen += file->size; // adding file size
}
else
u64_to_u8(entry->dataoffset,0x00,LE);
/* Increment used file table length */
ctx->u_fileTableLen += sizeof(romfs_fileentry) + align(file->namesize,4);
}
void AddDirToRomfs(romfs_buildctx *ctx, romfs_dir *fs, u32 parent, u32 sibling)
{
u32 offset = ctx->u_dirTableLen;
romfs_direntry *entry = (romfs_direntry*)(ctx->dirTable + offset);
/* Set entry data */
u32_to_u8(entry->parentoffset,parent,LE);
u32_to_u8(entry->siblingoffset,sibling,LE);
u32_to_u8(entry->childoffset, ROMFS_UNUSED_ENTRY, LE);
u32_to_u8(entry->fileoffset, ROMFS_UNUSED_ENTRY, LE);
/* Import name */
u32_to_u8(entry->namesize,fs->namesize,LE);
u8 *name_pos = (u8*)(ctx->dirTable + ctx->u_dirTableLen + sizeof(romfs_direntry));
memset(name_pos,0,(u32)align(fs->namesize,4));
memcpy(name_pos,(u8*)fs->name,fs->namesize);
/* Set hash data */
u32 hashindex = GetDirHashTableIndex(ctx, parent, fs->name);
u32_to_u8(entry->hashoffset, u8_to_u32(ctx->dirHashTable + hashindex * 4, LE), LE);
u32_to_u8(ctx->dirHashTable + hashindex * 4, offset, LE);
/* Increment used dir table length */
ctx->u_dirTableLen += sizeof(romfs_direntry) + (u32)align(fs->namesize,4);
}
void AddDirChildrenToRomfs(romfs_buildctx *ctx, romfs_dir *fs, u32 parent, u32 dir)
{
romfs_direntry *entry = (romfs_direntry*)(ctx->dirTable + dir);
if (fs->u_file)
{
u32_to_u8(entry->fileoffset, ctx->u_fileTableLen, LE);
/* Create file entries*/
for (u32 i = 0; i < fs->u_file; i++)
{
/* If is the last file, no more siblings */
u32 file_sibling = 0;
if (i >= fs->u_file - 1)
file_sibling = ROMFS_UNUSED_ENTRY;
else
file_sibling = ctx->u_fileTableLen + sizeof(romfs_fileentry) + (u32)align(fs->file[i].namesize, 4);
/* Create file entry */
AddFileToRomfs(ctx, &fs->file[i], dir, file_sibling);
}
}
if (fs->u_child)
{
/* Prepare to store child addresses */
u32 *childs = calloc(fs->u_child, sizeof(u32));
/* Create child directory entries*/
u32_to_u8(entry->childoffset, ctx->u_dirTableLen, LE);
for (u32 i = 0; i < fs->u_child; i++)
{
/* Store address for child */
childs[i] = ctx->u_dirTableLen;
/* If is the last child directory, no more siblings */
u32 dir_sibling = 0;
if (i >= fs->u_child - 1)
dir_sibling = ROMFS_UNUSED_ENTRY;
else
dir_sibling = ctx->u_dirTableLen + sizeof(romfs_direntry) + (u32)align(fs->child[i].namesize, 4);
/* Create child directory entry */
AddDirToRomfs(ctx, &fs->child[i], dir, dir_sibling);
}
/* Populate child's childs */
for (u32 i = 0; i < fs->u_child; i++)
{
AddDirChildrenToRomfs(ctx, &fs->child[i], dir, childs[i]);
}
free(childs);
}
}
void PopulateRomfs(romfs_buildctx *ctx)
{
AddDirToRomfs(ctx, ctx->fs, 0x0, ROMFS_UNUSED_ENTRY);
AddDirChildrenToRomfs(ctx, ctx->fs, 0x0, 0);
}
void BuildIvfcHeader(romfs_buildctx *ctx)
{
memcpy(ctx->ivfcHdr->magic,"IVFC",4);
u32_to_u8(ctx->ivfcHdr->id,0x10000,LE);
u32 masterHashSize = ( align(ctx->level[1].size,ROMFS_BLOCK_SIZE) / ROMFS_BLOCK_SIZE ) * SHA_256_LEN ;
u32_to_u8(ctx->ivfcHdr->masterHashSize,masterHashSize,LE);
for(int i = 1; i < 4; i++){
u64_to_u8(ctx->ivfcHdr->level[i-1].logicalOffset,ctx->level[i].logicalOffset,LE);
u64_to_u8(ctx->ivfcHdr->level[i-1].hashDataSize,ctx->level[i].size,LE);
u32_to_u8(ctx->ivfcHdr->level[i-1].blockSize,log2l(ROMFS_BLOCK_SIZE),LE);
}
u32_to_u8(ctx->ivfcHdr->optionalSize,sizeof(ivfc_hdr),LE);
return;
}
void GenIvfcHashTree(romfs_buildctx *ctx)
{
for(int i = 2; i >= 0; i--){
if (ctx->verbose)
printf("[ROMFS] Generating IVFC level %d hashes... ", i+1);
u32 numHashes = align(ctx->level[i+1].size,ROMFS_BLOCK_SIZE) / ROMFS_BLOCK_SIZE;
for(u32 j = 0; j < numHashes; j++){
u8 *datapos = (u8*)(ctx->level[i+1].pos + ROMFS_BLOCK_SIZE * j);
u8 *hashpos = (u8*)(ctx->level[i].pos + SHA_256_LEN * j);
ShaCalc(datapos, ROMFS_BLOCK_SIZE, hashpos, CTR_SHA_256);
}
if (ctx->verbose)
printf("Done!\n");
}
return;
}
u32 CalcPathHash(u32 parent, const utf16char_t* path)
{
u32 len = utf16_strlen(path);
u32 hash = parent ^ 123456789;
for( u32 i = 0; i < len; i++ )
{
hash = (u32)((hash >> 5) | (hash << 27));//ror
hash ^= (u16)path[i];
}
return hash;
}
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include "romfs.h"
int PrepareBuildRomFsBinary(ncch_settings *ncchset, romfs_buildctx *ctx);
int BuildRomFsBinary(romfs_buildctx *ctx);
+33
View File
@@ -0,0 +1,33 @@
#include "lib.h"
#include "romfs_fs.h"
#include "ncch_build.h"
#include "romfs.h"
int PrepareImportRomFsBinaryFromFile(ncch_settings *ncchset, romfs_buildctx *ctx)
{
ctx->ImportRomfsBinary = true;
ctx->romfsSize = ncchset->componentFilePtrs.romfsSize;
ctx->romfsBinary = ncchset->componentFilePtrs.romfs;
ivfc_hdr *hdr = calloc(1,sizeof(ivfc_hdr));
ReadFile64(hdr,sizeof(ivfc_hdr),0,ctx->romfsBinary);
if(memcmp(hdr->magic,"IVFC",4) != 0){
fprintf(stderr,"[ROMFS ERROR] Invalid RomFS Binary.\n");
return INVALID_ROMFS_FILE;
}
ctx->romfsHeaderSize = align(sizeof(ivfc_hdr),0x10) + (u64)u8_to_u32(hdr->masterHashSize,LE);
return 0;
}
int ImportRomFsBinaryFromFile(romfs_buildctx *ctx)
{
ReadFile64(ctx->output,ctx->romfsSize,0,ctx->romfsBinary);
if(memcmp(ctx->output,"IVFC",4) != 0){
fprintf(stderr,"[ROMFS ERROR] Invalid RomFS Binary.\n");
return INVALID_ROMFS_FILE;
}
return 0;
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
int PrepareImportRomFsBinaryFromFile(ncch_settings *ncchset, romfs_buildctx *ctx);
int ImportRomFsBinaryFromFile(romfs_buildctx *ctx);
+486
View File
@@ -0,0 +1,486 @@
#include "lib.h"
void GET_Option(ctr_yaml_context *ctx, rsf_settings *rsf);
void GET_AccessControlInfo(ctr_yaml_context *ctx, rsf_settings *rsf);
void GET_SystemControlInfo(ctr_yaml_context *ctx, rsf_settings *rsf);
void GET_BasicInfo(ctr_yaml_context *ctx, rsf_settings *rsf);
void GET_RomFs(ctr_yaml_context *ctx, rsf_settings *rsf);
void GET_TitleInfo(ctr_yaml_context *ctx, rsf_settings *rsf);
void GET_CardInfo(ctr_yaml_context *ctx, rsf_settings *rsf);
void GET_CommonHeaderKey(ctr_yaml_context *ctx, rsf_settings *rsf);
void EvaluateRSF(rsf_settings *rsf, ctr_yaml_context *ctx)
{
u32 start_level = ctx->Level-1;
/* Check Group Key for Validity */
CHECK_Group:
//printf("RSF Found: %s\n",GetYamlString(ctx));
if(cmpYamlValue("Option",ctx)) {FinishEvent(ctx); GET_Option(ctx,rsf); goto GET_NextGroup;}
else if(cmpYamlValue("AccessControlInfo",ctx)) {FinishEvent(ctx); GET_AccessControlInfo(ctx,rsf); goto GET_NextGroup;}
else if(cmpYamlValue("SystemControlInfo",ctx)) {FinishEvent(ctx); GET_SystemControlInfo(ctx,rsf); goto GET_NextGroup;}
else if(cmpYamlValue("BasicInfo",ctx)) {FinishEvent(ctx); GET_BasicInfo(ctx,rsf); goto GET_NextGroup;}
else if(cmpYamlValue("RomFs",ctx)) {FinishEvent(ctx); GET_RomFs(ctx,rsf); goto GET_NextGroup;}
else if(cmpYamlValue("TitleInfo",ctx)) {FinishEvent(ctx); GET_TitleInfo(ctx,rsf); goto GET_NextGroup;}
else if(cmpYamlValue("CardInfo",ctx)) {FinishEvent(ctx); GET_CardInfo(ctx,rsf); goto GET_NextGroup;}
else if(cmpYamlValue("CommonHeaderKey",ctx)) {FinishEvent(ctx); GET_CommonHeaderKey(ctx,rsf); goto GET_NextGroup;}
// If not recognised escape:
fprintf(stderr,"[RSF ERROR] Unrecognised Key: '%s'\n",GetYamlString(ctx));
FinishEvent(ctx);
ctx->error = YAML_BAD_GROUP_HEADER;
return;
/* Get Next Group and call check */
GET_NextGroup:
// If done return
if(ctx->done || ctx->error) return;
// Recursively getting events until done or has value
if(!ctx->event.type) GetEvent(ctx);
if(ctx->Level <= start_level) return; // No longer in RSF Domain
while(!EventIsScalar(ctx)){
if(ctx->done || ctx->error) return;
if(ctx->Level <= start_level) return; // No longer in RSF Domain
FinishEvent(ctx);
GetEvent(ctx);
}
goto CHECK_Group;
}
void GET_Option(ctr_yaml_context *ctx, rsf_settings *rsf)
{
/* Checking That Group is in a map */
if(!CheckMappingEvent(ctx)) return;
u32 InitLevel = ctx->Level;
/* Checking each child */
GetEvent(ctx);
while(ctx->Level == InitLevel){
if(ctx->error || ctx->done) return;
// Handle childs
if(cmpYamlValue("AllowUnalignedSection",ctx)) SetBoolYAMLValue(&rsf->Option.AllowUnalignedSection,"AllowUnalignedSection",ctx);
else if(cmpYamlValue("MediaFootPadding",ctx)) SetBoolYAMLValue(&rsf->Option.MediaFootPadding,"MediaFootPadding",ctx);
else if(cmpYamlValue("EnableCrypt",ctx)) SetBoolYAMLValue(&rsf->Option.EnableCrypt,"EnableCrypt",ctx);
else if(cmpYamlValue("EnableCompress",ctx)) SetBoolYAMLValue(&rsf->Option.EnableCompress,"EnableCompress",ctx);
else if(cmpYamlValue("FreeProductCode",ctx)) SetBoolYAMLValue(&rsf->Option.FreeProductCode,"FreeProductCode",ctx);
else if(cmpYamlValue("UseOnSD",ctx)) SetBoolYAMLValue(&rsf->Option.UseOnSD,"UseOnSD",ctx);
else{
fprintf(stderr,"[RSF ERROR] Unrecognised key '%s'\n",GetYamlString(ctx));
ctx->error = YAML_UNKNOWN_KEY;
FinishEvent(ctx);
return;
}
// Finish event start next
FinishEvent(ctx);
GetEvent(ctx);
}
FinishEvent(ctx);
}
void GET_AccessControlInfo(ctr_yaml_context *ctx, rsf_settings *rsf)
{
/* Checking That Group is in a map */
if(!CheckMappingEvent(ctx)) return;
u32 InitLevel = ctx->Level;
/* Checking each child */
GetEvent(ctx);
while(ctx->Level == InitLevel){
if(ctx->error || ctx->done) return;
// Handle childs
if(cmpYamlValue("DisableDebug",ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.DisableDebug,"DisableDebug",ctx);
else if(cmpYamlValue("EnableForceDebug",ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.EnableForceDebug,"EnableForceDebug",ctx);
else if(cmpYamlValue("CanWriteSharedPage",ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.CanWriteSharedPage,"CanWriteSharedPage",ctx);
else if(cmpYamlValue("CanUsePrivilegedPriority",ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.CanUsePrivilegedPriority,"CanUsePrivilegedPriority",ctx);
else if(cmpYamlValue("CanUseNonAlphabetAndNumber",ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.CanUseNonAlphabetAndNumber,"CanUseNonAlphabetAndNumber",ctx);
else if(cmpYamlValue("PermitMainFunctionArgument",ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.PermitMainFunctionArgument,"PermitMainFunctionArgument",ctx);
else if(cmpYamlValue("CanShareDeviceMemory",ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.CanShareDeviceMemory,"CanShareDeviceMemory",ctx);
else if(cmpYamlValue("UseOtherVariationSaveData",ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.UseOtherVariationSaveData,"UseOtherVariationSaveData",ctx);
else if(cmpYamlValue("RunnableOnSleep",ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.RunnableOnSleep,"RunnableOnSleep",ctx);
else if(cmpYamlValue("SpecialMemoryArrange",ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.SpecialMemoryArrange,"SpecialMemoryArrange",ctx);
else if(cmpYamlValue("CanAccessCore2", ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.CanAccessCore2, "CanAccessCore2", ctx);
else if(cmpYamlValue("UseExtSaveData", ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.UseExtSaveData, "UseExtSaveData", ctx);
else if(cmpYamlValue("EnableL2Cache", ctx)) SetBoolYAMLValue(&rsf->AccessControlInfo.EnableL2Cache, "EnableL2Cache", ctx);
else if(cmpYamlValue("IdealProcessor",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.IdealProcessor,"IdealProcessor",ctx,0);
else if(cmpYamlValue("Priority",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.Priority,"Priority",ctx,0);
else if(cmpYamlValue("MemoryType",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.MemoryType,"MemoryType",ctx,0);
else if(cmpYamlValue("SystemMode",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.SystemMode,"SystemMode",ctx,0);
else if(cmpYamlValue("SystemModeExt", ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.SystemModeExt, "SystemModeExt", ctx, 0);
else if(cmpYamlValue("CpuSpeed", ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.CpuSpeed, "CpuSpeed", ctx, 0);
else if(cmpYamlValue("CoreVersion",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.CoreVersion,"CoreVersion",ctx,0);
else if(cmpYamlValue("HandleTableSize",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.HandleTableSize,"HandleTableSize",ctx,0);
else if(cmpYamlValue("SystemSaveDataId1",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.SystemSaveDataId1,"SystemSaveDataId1",ctx,0);
else if(cmpYamlValue("SystemSaveDataId2",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.SystemSaveDataId2,"SystemSaveDataId2",ctx,0);
else if(cmpYamlValue("OtherUserSaveDataId1",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.OtherUserSaveDataId1,"OtherUserSaveDataId1",ctx,0);
else if(cmpYamlValue("OtherUserSaveDataId2",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.OtherUserSaveDataId2,"OtherUserSaveDataId2",ctx,0);
else if(cmpYamlValue("OtherUserSaveDataId3",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.OtherUserSaveDataId3,"OtherUserSaveDataId3",ctx,0);
else if(cmpYamlValue("ExtSaveDataId",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.ExtSaveDataId,"ExtSaveDataId",ctx,0);
else if(cmpYamlValue("AffinityMask",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.AffinityMask,"AffinityMask",ctx,0);
else if(cmpYamlValue("DescVersion",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.DescVersion,"DescVersion",ctx,0);
else if(cmpYamlValue("ResourceLimitCategory",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.ResourceLimitCategory,"ResourceLimitCategory",ctx,0);
else if(cmpYamlValue("ReleaseKernelMajor",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.ReleaseKernelMajor,"ReleaseKernelMajor",ctx,0);
else if(cmpYamlValue("ReleaseKernelMinor",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.ReleaseKernelMinor,"ReleaseKernelMinor",ctx,0);
else if(cmpYamlValue("MaxCpu",ctx)) SetSimpleYAMLValue(&rsf->AccessControlInfo.MaxCpu,"MaxCpu",ctx,0);
else if(cmpYamlValue("MemoryMapping",ctx)) rsf->AccessControlInfo.MemoryMappingNum = SetYAMLSequence(&rsf->AccessControlInfo.MemoryMapping,"MemoryMapping",ctx);
else if(cmpYamlValue("IORegisterMapping",ctx)) rsf->AccessControlInfo.IORegisterMappingNum = SetYAMLSequence(&rsf->AccessControlInfo.IORegisterMapping,"IORegisterMapping",ctx);
else if(cmpYamlValue("FileSystemAccess",ctx)) rsf->AccessControlInfo.FileSystemAccessNum = SetYAMLSequence(&rsf->AccessControlInfo.FileSystemAccess,"FileSystemAccess",ctx);
else if(cmpYamlValue("IoAccessControl",ctx)) rsf->AccessControlInfo.IoAccessControlNum = SetYAMLSequence(&rsf->AccessControlInfo.IoAccessControl,"IoAccessControl",ctx);
else if(cmpYamlValue("InterruptNumbers",ctx)) rsf->AccessControlInfo.InterruptNumbersNum = SetYAMLSequence(&rsf->AccessControlInfo.InterruptNumbers,"InterruptNumbers",ctx);
else if(cmpYamlValue("SystemCallAccess",ctx)) rsf->AccessControlInfo.SystemCallAccessNum = SetYAMLSequenceFromMapping(&rsf->AccessControlInfo.SystemCallAccess,"SystemCallAccess",ctx,false);
else if(cmpYamlValue("ServiceAccessControl",ctx)) rsf->AccessControlInfo.ServiceAccessControlNum = SetYAMLSequence(&rsf->AccessControlInfo.ServiceAccessControl,"ServiceAccessControl",ctx);
else if(cmpYamlValue("AccessibleSaveDataIds",ctx)) rsf->AccessControlInfo.AccessibleSaveDataIdsNum = SetYAMLSequence(&rsf->AccessControlInfo.AccessibleSaveDataIds,"AccessibleSaveDataIds",ctx);
else{
fprintf(stderr,"[RSF ERROR] Unrecognised key '%s'\n",GetYamlString(ctx));
ctx->error = YAML_UNKNOWN_KEY;
FinishEvent(ctx);
return;
}
// Finish event start next
FinishEvent(ctx);
GetEvent(ctx);
}
FinishEvent(ctx);
}
void GET_SystemControlInfo(ctr_yaml_context *ctx, rsf_settings *rsf)
{
/* Checking That Group is in a map */
if(!CheckMappingEvent(ctx)) return;
u32 InitLevel = ctx->Level;
/* Checking each child */
GetEvent(ctx);
while(ctx->Level == InitLevel){
if(ctx->error || ctx->done) return;
// Handle childs
if(cmpYamlValue("AppType",ctx)) SetSimpleYAMLValue(&rsf->SystemControlInfo.AppType,"AppType",ctx,0);
else if(cmpYamlValue("StackSize",ctx)) SetSimpleYAMLValue(&rsf->SystemControlInfo.StackSize,"StackSize",ctx,0);
else if(cmpYamlValue("RemasterVersion",ctx)) SetSimpleYAMLValue(&rsf->SystemControlInfo.RemasterVersion,"RemasterVersion",ctx,0);
else if(cmpYamlValue("JumpId",ctx)) SetSimpleYAMLValue(&rsf->SystemControlInfo.JumpId,"JumpId",ctx,0);
else if(cmpYamlValue("SaveDataSize",ctx)) SetSimpleYAMLValue(&rsf->SystemControlInfo.SaveDataSize,"SaveDataSize",ctx,0);
else if(cmpYamlValue("Dependency",ctx)) rsf->SystemControlInfo.DependencyNum = SetYAMLSequenceFromMapping(&rsf->SystemControlInfo.Dependency,"Dependency",ctx,false);
else{
fprintf(stderr,"[RSF ERROR] Unrecognised key '%s'\n",GetYamlString(ctx));
ctx->error = YAML_UNKNOWN_KEY;
FinishEvent(ctx);
return;
}
// Finish event start next
FinishEvent(ctx);
GetEvent(ctx);
}
FinishEvent(ctx);
}
void GET_BasicInfo(ctr_yaml_context *ctx, rsf_settings *rsf)
{
/* Checking That Group is in a map */
if(!CheckMappingEvent(ctx)) return;
u32 InitLevel = ctx->Level;
/* Checking each child */
GetEvent(ctx);
while(ctx->Level == InitLevel){
if(ctx->error || ctx->done) return;
// Handle childs
if(cmpYamlValue("Title",ctx)) SetSimpleYAMLValue(&rsf->BasicInfo.Title,"Title",ctx,0);
else if(cmpYamlValue("CompanyCode",ctx)) SetSimpleYAMLValue(&rsf->BasicInfo.CompanyCode,"CompanyCode",ctx,0);
else if(cmpYamlValue("ProductCode",ctx)) SetSimpleYAMLValue(&rsf->BasicInfo.ProductCode,"ProductCode",ctx,0);
else if(cmpYamlValue("ContentType",ctx)) SetSimpleYAMLValue(&rsf->BasicInfo.ContentType,"ContentType",ctx,0);
else if(cmpYamlValue("Logo",ctx)) SetSimpleYAMLValue(&rsf->BasicInfo.Logo,"Logo",ctx,0);
else{
fprintf(stderr,"[RSF ERROR] Unrecognised key '%s'\n",GetYamlString(ctx));
ctx->error = YAML_UNKNOWN_KEY;
FinishEvent(ctx);
return;
}
// Finish event start next
FinishEvent(ctx);
GetEvent(ctx);
}
FinishEvent(ctx);
}
void GET_RomFs(ctr_yaml_context *ctx, rsf_settings *rsf)
{
/* Checking That Group is in a map */
if(!CheckMappingEvent(ctx)) return;
u32 InitLevel = ctx->Level;
/* Checking each child */
GetEvent(ctx);
while(ctx->Level == InitLevel){
if(ctx->error || ctx->done) return;
// Handle childs
if(cmpYamlValue("RootPath",ctx)) SetSimpleYAMLValue(&rsf->RomFs.RootPath,"RootPath",ctx,0);
else if(cmpYamlValue("DefaultReject",ctx)) rsf->RomFs.DefaultRejectNum = SetYAMLSequence(&rsf->RomFs.DefaultReject,"DefaultReject",ctx);
else if(cmpYamlValue("Reject",ctx)) rsf->RomFs.RejectNum = SetYAMLSequence(&rsf->RomFs.Reject,"Reject",ctx);
else if(cmpYamlValue("Include",ctx)) rsf->RomFs.IncludeNum = SetYAMLSequence(&rsf->RomFs.Include,"Include",ctx);
else if(cmpYamlValue("File",ctx)) rsf->RomFs.FileNum = SetYAMLSequence(&rsf->RomFs.File,"File",ctx);
else{
fprintf(stderr,"[RSF ERROR] Unrecognised key '%s'\n",GetYamlString(ctx));
ctx->error = YAML_UNKNOWN_KEY;
FinishEvent(ctx);
return;
}
// Finish event start next
FinishEvent(ctx);
GetEvent(ctx);
}
FinishEvent(ctx);
}
void GET_TitleInfo(ctr_yaml_context *ctx, rsf_settings *rsf)
{
/* Checking That Group is in a map */
if(!CheckMappingEvent(ctx)) return;
u32 InitLevel = ctx->Level;
/* Checking each child */
GetEvent(ctx);
while(ctx->Level == InitLevel){
if(ctx->error || ctx->done) return;
// Handle childs
if (cmpYamlValue("Platform", ctx)) SetSimpleYAMLValue(&rsf->TitleInfo.Platform, "Platform", ctx, 0);
else if(cmpYamlValue("Category",ctx)) SetSimpleYAMLValue(&rsf->TitleInfo.Category,"Category",ctx,0);
else if(cmpYamlValue("UniqueId",ctx)) SetSimpleYAMLValue(&rsf->TitleInfo.UniqueId,"UniqueId",ctx,0);
else if(cmpYamlValue("Version",ctx)) SetSimpleYAMLValue(&rsf->TitleInfo.Version,"Version",ctx,0);
else if(cmpYamlValue("ContentsIndex",ctx)) SetSimpleYAMLValue(&rsf->TitleInfo.ContentsIndex,"ContentsIndex",ctx,0);
else if(cmpYamlValue("Variation",ctx)) SetSimpleYAMLValue(&rsf->TitleInfo.Variation,"Variation",ctx,0);
else if(cmpYamlValue("ChildIndex",ctx)) SetSimpleYAMLValue(&rsf->TitleInfo.ChildIndex,"ChildIndex",ctx,0);
else if(cmpYamlValue("DemoIndex",ctx)) SetSimpleYAMLValue(&rsf->TitleInfo.DemoIndex,"DemoIndex",ctx,0);
else if(cmpYamlValue("TargetCategory",ctx)) SetSimpleYAMLValue(&rsf->TitleInfo.TargetCategory,"TargetCategory",ctx,0);
else if(cmpYamlValue("CategoryFlags",ctx)) rsf->TitleInfo.CategoryFlagsNum = SetYAMLSequence(&rsf->TitleInfo.CategoryFlags,"CategoryFlags",ctx);
else{
fprintf(stderr,"[RSF ERROR] Unrecognised key '%s'\n",GetYamlString(ctx));
ctx->error = YAML_UNKNOWN_KEY;
FinishEvent(ctx);
return;
}
// Finish event start next
FinishEvent(ctx);
GetEvent(ctx);
}
FinishEvent(ctx);
}
void GET_CardInfo(ctr_yaml_context *ctx, rsf_settings *rsf)
{
/* Checking That Group is in a map */
if(!CheckMappingEvent(ctx)) return;
u32 InitLevel = ctx->Level;
/* Checking each child */
GetEvent(ctx);
while(ctx->Level == InitLevel){
if(ctx->error || ctx->done) return;
// Handle childs
if(cmpYamlValue("WritableAddress",ctx)) SetSimpleYAMLValue(&rsf->CardInfo.WritableAddress,"WritableAddress",ctx,0);
else if(cmpYamlValue("CardType",ctx)) SetSimpleYAMLValue(&rsf->CardInfo.CardType,"CardType",ctx,0);
else if(cmpYamlValue("CryptoType",ctx)) SetSimpleYAMLValue(&rsf->CardInfo.CryptoType,"CryptoType",ctx,0);
else if(cmpYamlValue("CardDevice",ctx)) SetSimpleYAMLValue(&rsf->CardInfo.CardDevice,"CardDevice",ctx,0);
else if(cmpYamlValue("MediaType",ctx)) SetSimpleYAMLValue(&rsf->CardInfo.MediaType,"MediaType",ctx,0);
else if(cmpYamlValue("MediaSize",ctx)) SetSimpleYAMLValue(&rsf->CardInfo.MediaSize,"MediaSize",ctx,0);
else if(cmpYamlValue("BackupWriteWaitTime",ctx)) SetSimpleYAMLValue(&rsf->CardInfo.BackupWriteWaitTime,"BackupWriteWaitTime",ctx,0);
else if(cmpYamlValue("SaveCrypto",ctx)) SetSimpleYAMLValue(&rsf->CardInfo.SaveCrypto,"SaveCrypto",ctx,0);
else{
fprintf(stderr,"[RSF ERROR] Unrecognised key '%s'\n",GetYamlString(ctx));
ctx->error = YAML_UNKNOWN_KEY;
FinishEvent(ctx);
return;
}
// Finish event start next
FinishEvent(ctx);
GetEvent(ctx);
}
FinishEvent(ctx);
}
void GET_CommonHeaderKey(ctr_yaml_context *ctx, rsf_settings *rsf)
{
/* Checking That Group is in a map */
if(!CheckMappingEvent(ctx)) return;
u32 InitLevel = ctx->Level;
/* Checking each child */
GetEvent(ctx);
rsf->CommonHeaderKey.Found = true;
while(ctx->Level == InitLevel){
if(ctx->error || ctx->done) return;
// Handle childs
if(cmpYamlValue("D",ctx)) SetSimpleYAMLValue(&rsf->CommonHeaderKey.D,"D",ctx,0);
else if(cmpYamlValue("P",ctx)) SetSimpleYAMLValue(&rsf->CommonHeaderKey.P,"P",ctx,0);
else if(cmpYamlValue("Q",ctx)) SetSimpleYAMLValue(&rsf->CommonHeaderKey.Q,"Q",ctx,0);
else if(cmpYamlValue("DP",ctx)) SetSimpleYAMLValue(&rsf->CommonHeaderKey.DP,"DP",ctx,0);
else if(cmpYamlValue("DQ",ctx)) SetSimpleYAMLValue(&rsf->CommonHeaderKey.DQ,"DQ",ctx,0);
else if(cmpYamlValue("InverseQ",ctx)) SetSimpleYAMLValue(&rsf->CommonHeaderKey.InverseQ,"InverseQ",ctx,0);
else if(cmpYamlValue("Modulus",ctx)) SetSimpleYAMLValue(&rsf->CommonHeaderKey.Modulus,"Modulus",ctx,0);
else if(cmpYamlValue("Exponent",ctx)) SetSimpleYAMLValue(&rsf->CommonHeaderKey.Exponent,"Exponent",ctx,0);
else if(cmpYamlValue("Signature",ctx)) SetSimpleYAMLValue(&rsf->CommonHeaderKey.AccCtlDescSign,"Signature",ctx,0);
else if(cmpYamlValue("Descriptor",ctx)) SetSimpleYAMLValue(&rsf->CommonHeaderKey.AccCtlDescBin,"Descriptor",ctx,0);
else{
fprintf(stderr,"[RSF ERROR] Unrecognised key '%s'\n",GetYamlString(ctx));
ctx->error = YAML_UNKNOWN_KEY;
FinishEvent(ctx);
return;
}
// Finish event start next
FinishEvent(ctx);
GetEvent(ctx);
}
FinishEvent(ctx);
}
void free_RsfSettings(rsf_settings *set)
{
//AccessControlInfo
free(set->AccessControlInfo.IdealProcessor);
free(set->AccessControlInfo.Priority);
free(set->AccessControlInfo.MemoryType);
free(set->AccessControlInfo.SystemMode);
free(set->AccessControlInfo.SystemModeExt);
free(set->AccessControlInfo.CpuSpeed);
free(set->AccessControlInfo.CoreVersion);
free(set->AccessControlInfo.HandleTableSize);
free(set->AccessControlInfo.SystemSaveDataId1);
free(set->AccessControlInfo.SystemSaveDataId2);
free(set->AccessControlInfo.OtherUserSaveDataId1);
free(set->AccessControlInfo.OtherUserSaveDataId2);
free(set->AccessControlInfo.OtherUserSaveDataId3);
free(set->AccessControlInfo.ExtSaveDataId);
free(set->AccessControlInfo.AffinityMask);
free(set->AccessControlInfo.DescVersion);
free(set->AccessControlInfo.ResourceLimitCategory);
free(set->AccessControlInfo.ReleaseKernelMajor);
free(set->AccessControlInfo.ReleaseKernelMinor);
free(set->AccessControlInfo.MaxCpu);
for(u32 i = 0; i < set->AccessControlInfo.MemoryMappingNum; i++){
free(set->AccessControlInfo.MemoryMapping[i]);
}
free(set->AccessControlInfo.MemoryMapping);
for(u32 i = 0; i < set->AccessControlInfo.IORegisterMappingNum; i++){
free(set->AccessControlInfo.IORegisterMapping[i]);
}
free(set->AccessControlInfo.IORegisterMapping);
for(u32 i = 0; i < set->AccessControlInfo.FileSystemAccessNum; i++){
free(set->AccessControlInfo.FileSystemAccess[i]);
}
free(set->AccessControlInfo.FileSystemAccess);
for(u32 i = 0; i < set->AccessControlInfo.IoAccessControlNum; i++){
free(set->AccessControlInfo.IoAccessControl[i]);
}
free(set->AccessControlInfo.IoAccessControl);
for(u32 i = 0; i < set->AccessControlInfo.InterruptNumbersNum; i++){
free(set->AccessControlInfo.InterruptNumbers[i]);
}
free(set->AccessControlInfo.InterruptNumbers);
for(u32 i = 0; i < set->AccessControlInfo.SystemCallAccessNum; i++){
free(set->AccessControlInfo.SystemCallAccess[i]);
}
free(set->AccessControlInfo.SystemCallAccess);
for(u32 i = 0; i < set->AccessControlInfo.ServiceAccessControlNum; i++){
free(set->AccessControlInfo.ServiceAccessControl[i]);
}
free(set->AccessControlInfo.ServiceAccessControl);
for(u32 i = 0; i < set->AccessControlInfo.AccessibleSaveDataIdsNum; i++){
free(set->AccessControlInfo.AccessibleSaveDataIds[i]);
}
free(set->AccessControlInfo.AccessibleSaveDataIds);
//SystemControlInfo
free(set->SystemControlInfo.AppType);
free(set->SystemControlInfo.StackSize);
free(set->SystemControlInfo.RemasterVersion);
free(set->SystemControlInfo.SaveDataSize);
free(set->SystemControlInfo.JumpId);
for(u32 i = 0; i < set->SystemControlInfo.DependencyNum; i++){
free(set->SystemControlInfo.Dependency[i]);
}
free(set->SystemControlInfo.Dependency);
//BasicInfo
free(set->BasicInfo.Title);
free(set->BasicInfo.CompanyCode);
free(set->BasicInfo.ProductCode);
free(set->BasicInfo.ContentType);
free(set->BasicInfo.Logo);
//Rom
free(set->RomFs.RootPath);
for(u32 i = 0; i < set->RomFs.DefaultRejectNum; i++){
free(set->RomFs.DefaultReject[i]);
}
free(set->RomFs.DefaultReject);
for(u32 i = 0; i < set->RomFs.RejectNum; i++){
free(set->RomFs.Reject[i]);
}
free(set->RomFs.Reject);
for(u32 i = 0; i < set->RomFs.IncludeNum; i++){
free(set->RomFs.Include[i]);
}
free(set->RomFs.Include);
for(u32 i = 0; i < set->RomFs.FileNum; i++){
free(set->RomFs.File[i]);
}
free(set->RomFs.File);
//TitleInfo
free(set->TitleInfo.Platform);
free(set->TitleInfo.Category);
free(set->TitleInfo.UniqueId);
free(set->TitleInfo.Version);
free(set->TitleInfo.ContentsIndex);
free(set->TitleInfo.Variation);
free(set->TitleInfo.ChildIndex);
free(set->TitleInfo.DemoIndex);
free(set->TitleInfo.TargetCategory);
for(u32 i = 0; i < set->TitleInfo.CategoryFlagsNum; i++){
free(set->TitleInfo.CategoryFlags[i]);
}
free(set->TitleInfo.CategoryFlags);
//CardInfo
free(set->CardInfo.WritableAddress);
free(set->CardInfo.CardType);
free(set->CardInfo.CryptoType);
free(set->CardInfo.CardDevice);
free(set->CardInfo.MediaType);
free(set->CardInfo.MediaSize);
free(set->CardInfo.BackupWriteWaitTime);
free(set->CardInfo.SaveCrypto);
//CommonHeaderKey
free(set->CommonHeaderKey.D);
free(set->CommonHeaderKey.P);
free(set->CommonHeaderKey.Q);
free(set->CommonHeaderKey.DP);
free(set->CommonHeaderKey.DQ);
free(set->CommonHeaderKey.InverseQ);
free(set->CommonHeaderKey.Modulus);
free(set->CommonHeaderKey.Exponent);
free(set->CommonHeaderKey.AccCtlDescSign);
free(set->CommonHeaderKey.AccCtlDescBin);
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
void EvaluateRSF(rsf_settings *rsf, ctr_yaml_context *ctx);
void free_RsfSettings(rsf_settings *set);
+93
View File
@@ -0,0 +1,93 @@
#pragma once
typedef struct
{
u8 gameTitle[0xC];
u8 gameCode[4];
u8 makerCode[2];
u8 unitCode;
u8 encryptionSeedSelect;
u8 deviceCapacity;
u8 reserved0[9];
u8 romVersion;
u8 internalFlag;
u8 arm9RomOffset[4];
u8 arm9EntryAddress[4];
u8 arm9RamAddress[4];
u8 arm9Size[4];
u8 arm7RomOffset[4];
u8 arm7EntryAddress[4];
u8 arm7RamAddress[4];
u8 arm7Size[4];
u8 fntOffset[4];
u8 fntSize[4];
u8 fatOffset[4];
u8 fatSize[4];
u8 arm9OverlayOffset[4];
u8 arm9OverlaySize[4];
u8 arm7OverlayOffset[4];
u8 arm7OverlaySize[4];
u8 normalCardControlRegSettings[4];
u8 secureCardControlRegSettings[4];
u8 icon_bannerOffset[4];
u8 secureAreaCrc[2];
u8 secure_transfer_timeout[2];
u8 arm9Autoload[4];
u8 arm7Autoload[4];
u8 secureDisable[8];
u8 ntrRomSize[4];
u8 headerSize[4];
u8 reserved1[0x38];
u8 nintendoLogo[0x9C];
u8 nintendoLogoCrc[2];
u8 headerCrc[2];
u8 debugReserved[0x20];
//TWL Only Data
u8 configSettings[0x34];
u8 accessControl[4];
u8 arm7ScfgExtMask[4];
u8 reserved_flags[4];
u8 arm9iRomOffset[4];
u8 reserved2[4];
u8 arm9iLoadAddress[4];
u8 arm9iSize[4];
u8 arm7iRomOffset[4];
u8 struct_param_baseAddress[4];
u8 arm7iLoadAddress[4];
u8 arm7iSize[4];
u8 digest_ntrRegionOffset[4];
u8 digest_ntrRegionSize[4];
u8 digest_twlRegionOffset[4];
u8 digest_twlRegionSize[4];
u8 digestSectorHashtableOffset[4];
u8 digestSectorHashtableSize[4];
u8 digest_blockHashtableOffset[4];
u8 digest_blockHashtableSize[4];
u8 digestSectorSize[4];
u8 digest_blockSectorcount[4];
u8 reserved3[8];
u8 twlRomSize[8];
u8 unknown[8];
u8 modcryptArea1Offset[4];
u8 modcryptArea1Size[4];
u8 modcryptArea2Offset[4];
u8 modcryptArea2Size[4];
u8 title_id[8];
u8 pubSaveDataSize[4];
u8 privSaveDataSize[4];
u8 reserved4[0xC0];
// TWL and Signed NTR
u8 arm9WithSecAreaSha1Hmac[0x14];
u8 arm7Sha1Hmac[0x14];
u8 digestMasterSha1Hmac[0x14];
u8 bannerSha1Hmac[0x14];
u8 arm9iSha1Hmac[0x14];
u8 arm7iSha1Hmac[0x14];
u8 reserved5[0x28];
u8 arm9Sha1Hmac[0x14];
u8 reserved6[0xA4C];
u8 reserved7[0x180];
u8 signature[0x80];
} srl_hdr;
+208
View File
@@ -0,0 +1,208 @@
#include "lib.h"
#include "cia_build.h"
#include "tik_build.h"
// Private Prototypes
int SetupTicketBuffer(cia_settings *set);
void SetupTicketHeader(tik_hdr *hdr, cia_settings *ciaset);
int SignTicketHeader(buffer_struct *tik, keys_struct *keys);
void SetLimits(tik_hdr *hdr, cia_settings *ciaset);
u32 GetContentIndexSegNum(cia_settings *set);
void SetContentIndexHeader(tik_content_index_hdr *hdr, cia_settings *set);
void SetContentIndexData(tik_content_index_struct *data, cia_settings *set);
int CryptTitleKey(u8 *input, u8 *output, u8 *titleId, keys_struct *keys, u8 mode);
int BuildTicket(cia_settings *set)
{
if(SetupTicketBuffer(set))
return MEM_ERROR;
// Setting Ticket Struct Ptrs
buffer_struct *tik = &set->ciaSections.tik;
tik_hdr *hdr = (tik_hdr*) (tik->buffer + sizeof(tik_signature));
tik_content_index_hdr *idxHdr = (tik_content_index_hdr*) (tik->buffer + sizeof(tik_signature) + sizeof(tik_hdr));
tik_content_index_struct *idxData = (tik_content_index_struct*) (tik->buffer + sizeof(tik_signature) + sizeof(tik_hdr) + sizeof(tik_content_index_hdr));
SetupTicketHeader(hdr,set);
SetContentIndexHeader(idxHdr,set);
SetContentIndexData(idxData,set);
return SignTicketHeader(tik,set->keys);
}
int SetupTicketBuffer(cia_settings *set)
{
buffer_struct *tik = &set->ciaSections.tik;
tik->size = sizeof(tik_signature) + sizeof(tik_hdr) + sizeof(tik_content_index_hdr) + sizeof(tik_content_index_struct)*GetContentIndexSegNum(set);
tik->buffer = calloc(1,tik->size);
if(!tik->buffer) {
fprintf(stderr,"[TIK ERROR] Not enough memory\n");
return MEM_ERROR;
}
return 0;
}
void SetupTicketHeader(tik_hdr *hdr, cia_settings *ciaset)
{
clrmem(hdr,sizeof(tik_hdr));
memcpy(hdr->issuer,ciaset->tik.issuer,0x40);
hdr->formatVersion = ciaset->tik.formatVersion;
hdr->caCrlVersion = ciaset->cert.caCrlVersion;
hdr->signerCrlVersion = ciaset->cert.signerCrlVersion;
u64_to_u8(hdr->ticketId,ciaset->tik.ticketId,BE);
u32_to_u8(hdr->deviceId,ciaset->tik.deviceId,BE);
u64_to_u8(hdr->titleId,ciaset->common.titleId,BE);
u16_to_u8(hdr->ticketVersion,ciaset->tik.version,BE);
hdr->licenceType = ciaset->tik.licenceType;
hdr->keyId = ciaset->keys->aes.currentCommonKey;
u32_to_u8(hdr->eshopAccId,ciaset->tik.eshopAccId,BE);
hdr->audit = ciaset->tik.audit;
SetLimits(hdr,ciaset);
// Crypt TitleKey
if(ciaset->content.encryptCia)
CryptTitleKey(ciaset->common.titleKey, hdr->encryptedTitleKey, hdr->titleId, ciaset->keys, ENC);
else
rndset(hdr->encryptedTitleKey,AES_128_KEY_SIZE);
}
int SignTicketHeader(buffer_struct *tik, keys_struct *keys)
{
tik_signature *sig = (tik_signature*)tik->buffer;
u8 *data = tik->buffer + sizeof(tik_signature);
u32 len = tik->size - sizeof(tik_signature);
clrmem(sig,sizeof(tik_signature));
u32_to_u8(sig->sigType,RSA_2048_SHA256,BE);
if (Rsa2048Key_CanSign(&keys->rsa.xs) == false)
{
printf("[TIK WARNING] Failed to sign header (key was incomplete)\n");
memset(sig->data, 0xFF, 0x100);
return 0;
}
int rsa_ret = RsaSignVerify(data, len, sig->data, keys->rsa.xs.pub, keys->rsa.xs.pvt, RSA_2048_SHA256, CTR_RSA_SIGN);
if (rsa_ret != 0)
{
printf("[TIK WARNING] Failed to sign header (mbedtls error = -0x%x)\n", -rsa_ret);
memset(sig->data, 0xFF, 0x100);
return 0;
}
return 0;
}
int CryptTitleKey(u8 *input, u8 *output, u8 *titleId, keys_struct *keys, u8 mode)
{
//Generating IV
u8 iv[16];
clrmem(&iv,16);
memcpy(iv,titleId,0x8);
//Crypting TitleKey
AesCbcCrypt(keys->aes.commonKey[keys->aes.currentCommonKey],iv,input,output,0x10,mode);
// Return
return 0;
}
void SetLimits(tik_hdr *hdr, cia_settings *ciaset) // TODO?
{
memset(hdr->limits,0,0x40);
}
u32 GetContentIndexSegNum(cia_settings *set)
{
u32 num, level, i;
num = level = 0;
for( i = 0; i < set->content.count; i++)
{
if(set->content.index[i] >= level)
{
level = roundup(set->content.index[i],0x400);
num++;
}
}
return num;
}
void SetContentIndexHeader(tik_content_index_hdr *hdr, cia_settings *set)
{
u32 hdrSize = sizeof(tik_content_index_hdr);
u32 segNum = GetContentIndexSegNum(set);
u32 segSize = sizeof(tik_content_index_struct);
u32 segTotalSize = segSize * segNum;
u32 totalSize = hdrSize + segTotalSize;
u32_to_u8(hdr->unk0,0x00010014,BE);
u32_to_u8(hdr->totalSize,totalSize,BE);
u32_to_u8(hdr->unk1,0x00000014,BE);
u32_to_u8(hdr->unk2,0x00010014,BE);
u32_to_u8(hdr->unk3,0x00000000,BE);
u32_to_u8(hdr->hdrSize,hdrSize,BE);
u32_to_u8(hdr->segNum,segNum,BE);
u32_to_u8(hdr->segSize,segSize,BE);
u32_to_u8(hdr->segTotalSize,segTotalSize,BE);
u32_to_u8(hdr->unk4,0x00030000,BE);
}
void SetContentIndexData(tik_content_index_struct *data, cia_settings *set)
{
u32 level, i;
int j;
j = -1;
level = 0;
for( i = 0; i < set->content.count; i++)
{
if(set->content.index[i] >= level)
{
level = roundup(set->content.index[i],0x400);
j++;
u32_to_u8(data[j].level,(set->content.index[i]/0x400)*0x400,BE);
}
data[j].index[(set->content.index[i] & 0x3ff)/8] |= 1 << (set->content.index[i] & 0x7);
}
}
tik_hdr *GetTikHdr(u8 *tik)
{
u32 sigType = u8_to_u32(tik,BE);
switch(sigType){
case(RSA_4096_SHA1):
case(RSA_4096_SHA256):
return (tik_hdr*)(tik+0x240);
case(RSA_2048_SHA1):
case(RSA_2048_SHA256):
return (tik_hdr*)(tik+0x140);
case(ECC_SHA1):
case(ECC_SHA256):
return (tik_hdr*)(tik+0x7C);
}
return NULL;
}
bool GetTikTitleKey(u8 *titleKey, tik_hdr *hdr, keys_struct *keys)
{
if(keys->aes.commonKey[hdr->keyId] == NULL)
return false;
keys->aes.currentCommonKey = hdr->keyId;
CryptTitleKey(hdr->encryptedTitleKey, titleKey, hdr->titleId, keys, DEC);
return true;
}
+78
View File
@@ -0,0 +1,78 @@
#pragma once
typedef enum
{
lic_Permanent = 0,
lic_Demo = 1,
lic_Trial = 2,
lic_Rental = 3,
lic_Subscription = 4,
lic_Service = 5,
lic_Mask = 15
} tik_license_type;
typedef enum
{
right_Permanent = 1,
right_Subscription = 2,
right_Content = 3,
right_ContentConsumption = 4,
right_AccessTitle = 5
} tik_item_rights;
typedef struct
{
u8 unk0[4];
u8 totalSize[4];
u8 unk1[4];
u8 unk2[4];
u8 unk3[4];
u8 hdrSize[4];
u8 segNum[4];
u8 segSize[4];
u8 segTotalSize[4];
u8 unk4[4];
} tik_content_index_hdr;
typedef struct
{
u8 level[4];
u8 index[0x80];
} tik_content_index_struct;
typedef struct
{
u8 sigType[4];
u8 data[0x100];
u8 padding[0x3C];
} tik_signature;
typedef struct
{
u8 issuer[0x40];
u8 eccPubKey[0x3c];
u8 formatVersion;
u8 caCrlVersion;
u8 signerCrlVersion;
u8 encryptedTitleKey[0x10];
u8 padding0;
u8 ticketId[8];
u8 deviceId[4];
u8 titleId[8];
u8 padding1[2];
u8 ticketVersion[2];
u8 padding2[8];
u8 licenceType;
u8 keyId;
u8 propertyMask[2];
u8 customData[0x14];
u8 padding3[0x14];
u8 eshopAccId[4];
u8 padding4;
u8 audit;
u8 padding5[0x42];
u8 limits[0x40];
} tik_hdr;
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include "tik.h"
// Prototypes
int BuildTicket(cia_settings *ciaset);
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include "tik.h"
tik_hdr *GetTikHdr(u8 *tik);
bool GetTikTitleKey(u8 *titleKey, tik_hdr *hdr, keys_struct *keys);
+249
View File
@@ -0,0 +1,249 @@
#include "lib.h"
#include "ncch_read.h"
#include "titleid.h"
const u16 DEFAULT_CATEGORY = PROGRAM_ID_CATEGORY_APPLICATION;
const u32 DEFAULT_UNIQUE_ID = 0xff3ff;
void SetPIDType(u16 *type);
int SetPIDCategoryFromName(u16 *cat, char *CategoryStr);
int SetPIDCategoryFromFlags(u16 *cat, char **CategoryFlags, u32 FlagNum);
int SetPIDCategoryFromFlag(u16 *cat, u16 flag, char *flagName);
u32 SetPIDUniqueId(char *UniqueIdStr);
int SetTitleVariation(u8 *var, u16 cat, rsf_settings *rsf);
u64 ConvertTwlIdToCtrId(u64 pgid)
{
return 0x0004800000000000 | (pgid & 0x00007FFFFFFFFFFF);
}
u16 GetTidCategory(u64 titleId)
{
return (titleId>>32) & MAX_U16;
}
u32 GetTidUniqueId(u64 titleId)
{
return (titleId>>8) & 0xFFFFFF;
}
int GetProgramID(u64 *dest, rsf_settings *rsf, bool IsForExheader)
{
int ret = 0;
u32 uniqueId;
u16 type,category;
u8 variation;
if(rsf->TitleInfo.Category && rsf->TitleInfo.CategoryFlags){
fprintf(stderr,"[ID ERROR] Can not set \"Category\" and \"CategoryFlags\" at the same time.\n");
return PID_BAD_RSF_SET;
}
// Getting Type
SetPIDType(&type);
// Getting Category
if(IsForExheader && rsf->TitleInfo.TargetCategory)
ret = SetPIDCategoryFromName(&category,rsf->TitleInfo.TargetCategory);
else if (rsf->TitleInfo.Category)
ret = SetPIDCategoryFromName(&category, rsf->TitleInfo.Category);
else if (rsf->TitleInfo.CategoryFlags)
ret = SetPIDCategoryFromFlags(&category, rsf->TitleInfo.CategoryFlags, rsf->TitleInfo.CategoryFlagsNum);
else
category = DEFAULT_CATEGORY;
if(ret == PID_INVALID_CATEGORY) // Error occured
return PID_BAD_RSF_SET;
// Getting UniqueId
if(rsf->TitleInfo.UniqueId)
GetUniqueID(&uniqueId,rsf);
else
uniqueId = DEFAULT_UNIQUE_ID;
if(uniqueId & 0xFFF00000u){
fprintf(stderr,"[ID ERROR] Unique ID is out of range.\n");
return PID_BAD_RSF_SET;
}
// Getting Variation
if(SetTitleVariation(&variation,category,rsf) == PID_INVALID_VARIATION)
return PID_BAD_RSF_SET;
u64 programId = 0;
programId |= (u64)variation<<0;
programId |= (u64)uniqueId<<8;
programId |= (u64)category<<32;
programId |= (u64)type<<48;
*dest = programId;
return 0;
}
void SetPIDType(u16 *type)
{
*type = 0x0004;
}
int GetUniqueID(u32 *uid, rsf_settings *rsf)
{
if(rsf->TitleInfo.UniqueId) *uid = 0xffffff & SetPIDUniqueId(rsf->TitleInfo.UniqueId);
else{
fprintf(stderr,"[ID ERROR] ParameterNotFound: \"TitleInfo/UniqueId\"\n");
return PID_BAD_RSF_SET;
}
return 0;
}
int SetPIDCategoryFromName(u16 *cat, char *CategoryStr)
{
if(strcmp(CategoryStr,"Application") == 0) *cat = PROGRAM_ID_CATEGORY_APPLICATION;
else if(strcmp(CategoryStr,"SystemApplication") == 0) *cat = PROGRAM_ID_CATEGORY_SYSTEM_APPLICATION;
else if(strcmp(CategoryStr,"Applet") == 0) *cat = PROGRAM_ID_CATEGORY_APPLET;
else if(strcmp(CategoryStr,"Firmware") == 0) *cat = PROGRAM_ID_CATEGORY_FIRMWARE;
else if(strcmp(CategoryStr,"Base") == 0) *cat = PROGRAM_ID_CATEGORY_BASE;
else if(strcmp(CategoryStr,"DlpChild") == 0) *cat = PROGRAM_ID_CATEGORY_DLP_CHILD;
else if(strcmp(CategoryStr,"Demo") == 0) *cat = PROGRAM_ID_CATEGORY_DEMO;
else if(strcmp(CategoryStr,"Contents") == 0) *cat = PROGRAM_ID_CATEGORY_CONTENTS;
else if(strcmp(CategoryStr,"SystemContents") == 0) *cat = PROGRAM_ID_CATEGORY_SYSTEM_CONTENT;
else if(strcmp(CategoryStr,"SharedContents") == 0) *cat = PROGRAM_ID_CATEGORY_SHARED_CONTENT;
else if(strcmp(CategoryStr,"AddOnContents") == 0) *cat = PROGRAM_ID_CATEGORY_ADD_ON_CONTENTS;
else if(strcmp(CategoryStr,"Patch") == 0) *cat = PROGRAM_ID_CATEGORY_PATCH;
else if(strcmp(CategoryStr,"AutoUpdateContents") == 0) *cat = PROGRAM_ID_CATEGORY_AUTO_UPDATE_CONTENT;
else {
fprintf(stderr,"[ID ERROR] Invalid Category: \"%s\"\n",CategoryStr);
return PID_INVALID_CATEGORY;
}
return 0;
}
int SetPIDCategoryFromFlags(u16 *cat, char **CategoryFlags, u32 FlagNum)
{
int ret = 0;
for(u32 i = 0; i < FlagNum; i++){
if(strcmp(CategoryFlags[i],"Normal") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_NORMAL,"Normal");
else if(strcmp(CategoryFlags[i],"DlpChild") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_DLP_CHILD,"DlpChild");
else if(strcmp(CategoryFlags[i],"Demo") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_DEMO,"Demo");
else if(strcmp(CategoryFlags[i],"Contents") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_CONTENTS,"Contents");
else if(strcmp(CategoryFlags[i],"AddOnContents") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_ADD_ON_CONTENTS,"AddOnContents");
else if(strcmp(CategoryFlags[i],"Patch") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_PATCH,"Patch");
else if(strcmp(CategoryFlags[i],"CannotExecution") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_CANNOT_EXECUTION,"CannotExecution");
else if(strcmp(CategoryFlags[i],"System") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_SYSTEM,"System");
else if(strcmp(CategoryFlags[i],"RequireBatchUpdate") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_REQUIRE_BATCH_UPDATE,"RequireBatchUpdate");
else if(strcmp(CategoryFlags[i],"NotRequireUserApproval") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_NOT_REQUIRE_USER_APPROVAL,"NotRequireUserApproval");
else if(strcmp(CategoryFlags[i],"NotRequireRightForMount") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_NOT_REQUIRE_RIGHT_FOR_MOUNT,"NotRequireRightForMount");
else if(strcmp(CategoryFlags[i],"CanSkipConvertJumpId") == 0)
ret = SetPIDCategoryFromFlag(cat,PROGRAM_ID_CATEGORY_FLAG_CAN_SKIP_CONVERT_JUMP_ID,"CanSkipConvertJumpId");
else {
fprintf(stderr,"[ID ERROR] Invalid CategoryFlag: \"%s\"\n",CategoryFlags[i]);
return PID_INVALID_CATEGORY;
}
}
return ret;
}
int SetPIDCategoryFromFlag(u16 *cat, u16 flag, char *flagName)
{
if(!flag) return 0;
if((*cat & flag) == flag){
fprintf(stderr,"[ID ERROR] Failed to set \"%s\" for category. CategoryFlag was already set.\n",flagName);
return PID_INVALID_CATEGORY;
}
*cat |= flag;
return 0;
}
u32 SetPIDUniqueId(char *UniqueIdStr)
{
return 0xffffff & strtoull(UniqueIdStr,NULL,0);
}
int SetTitleVariation(u8 *var, u16 cat, rsf_settings *rsf)
{
if(IsDemo(cat)){
if(rsf->TitleInfo.DemoIndex){
u8 DemoIndex = 0xff & strtol(rsf->TitleInfo.DemoIndex,NULL,10);
if(DemoIndex == 0){
fprintf(stderr,"[ID ERROR] Invalid demo index \"%d\"\n",DemoIndex);
return PID_INVALID_VARIATION;
}
*var = DemoIndex;
}
else{
fprintf(stderr,"[ID ERROR] ParameterNotFound: \"TitleInfo/DemoIndex\"\n");
return PID_INVALID_VARIATION;
}
}
else if(IsDlpChild(cat)){
if(rsf->TitleInfo.ChildIndex)
*var = 0xff & strtol(rsf->TitleInfo.ChildIndex,NULL,10);
else
*var = 0;
}
else if(IsAddOnContent(cat)){
if(rsf->TitleInfo.Variation) // Might Rename to DataTitleIndex
*var = 0xff & strtol(rsf->TitleInfo.Variation,NULL,10);
else
*var = 0;
}
else if(IsContents(cat)){
if(rsf->TitleInfo.ContentsIndex)
*var = 0xff & strtol(rsf->TitleInfo.ContentsIndex,NULL,10);
else
*var = 0;
}
else{
if(rsf->TitleInfo.Version)
*var = 0xff & strtol(rsf->TitleInfo.Version,NULL,10);
else
*var = 0;
}
return 0;
}
bool IsDemo(u16 Category)
{
return Category == PROGRAM_ID_CATEGORY_DEMO;
}
bool IsSystem(u16 Category)
{
return (Category & PROGRAM_ID_CATEGORY_FLAG_SYSTEM) == PROGRAM_ID_CATEGORY_FLAG_SYSTEM;
}
bool IsDlpChild(u16 Category)
{
return Category == PROGRAM_ID_CATEGORY_DLP_CHILD;
}
bool IsPatch(u16 Category)
{
return Category == PROGRAM_ID_CATEGORY_PATCH;
}
bool IsContents(u16 Category)
{
return (Category & PROGRAM_ID_CATEGORY_FLAG_CONTENTS) == PROGRAM_ID_CATEGORY_FLAG_CONTENTS;
}
bool IsAddOnContent(u16 Category)
{
return Category == PROGRAM_ID_CATEGORY_ADD_ON_CONTENTS;
}
+99
View File
@@ -0,0 +1,99 @@
#pragma once
typedef enum
{
PID_BAD_RSF_SET = -1,
PID_INVALID_CATEGORY = -2,
PID_INVALID_UNIQUE_ID = -3,
PID_INVALID_VARIATION = -4,
} Pid_Errors;
typedef enum
{
PROGRAM_ID_CATEGORY_FLAG_NORMAL = 0x0000,
PROGRAM_ID_CATEGORY_FLAG_DLP_CHILD = 0x0001,
PROGRAM_ID_CATEGORY_FLAG_DEMO = 0x0002,
PROGRAM_ID_CATEGORY_FLAG_CONTENTS = 0x0003,
PROGRAM_ID_CATEGORY_FLAG_ADD_ON_CONTENTS = 0x0004,
PROGRAM_ID_CATEGORY_FLAG_PATCH = 0x0006,
PROGRAM_ID_CATEGORY_FLAG_CANNOT_EXECUTION = 0x0008,
PROGRAM_ID_CATEGORY_FLAG_SYSTEM = 0x0010,
PROGRAM_ID_CATEGORY_FLAG_REQUIRE_BATCH_UPDATE = 0x0020,
PROGRAM_ID_CATEGORY_FLAG_NOT_REQUIRE_USER_APPROVAL = 0x0040,
PROGRAM_ID_CATEGORY_FLAG_NOT_REQUIRE_RIGHT_FOR_MOUNT = 0x0080,
PROGRAM_ID_CATEGORY_FLAG_CAN_SKIP_CONVERT_JUMP_ID = 0x0100,
PROGRAM_ID_CATEGORY_FLAG_TWL = 0x8000,
} ProgramIdCategoryFlag;
typedef enum
{
PROGRAM_ID_CATEGORY_APPLICATION = ( PROGRAM_ID_CATEGORY_FLAG_NORMAL ),
PROGRAM_ID_CATEGORY_DLP_CHILD = ( PROGRAM_ID_CATEGORY_FLAG_DLP_CHILD ),
PROGRAM_ID_CATEGORY_DEMO = ( PROGRAM_ID_CATEGORY_FLAG_DEMO ),
PROGRAM_ID_CATEGORY_CONTENTS = ( PROGRAM_ID_CATEGORY_FLAG_CONTENTS ),
PROGRAM_ID_CATEGORY_PATCH = ( PROGRAM_ID_CATEGORY_FLAG_CANNOT_EXECUTION
| PROGRAM_ID_CATEGORY_FLAG_PATCH),
PROGRAM_ID_CATEGORY_ADD_ON_CONTENTS = ( PROGRAM_ID_CATEGORY_FLAG_ADD_ON_CONTENTS
| PROGRAM_ID_CATEGORY_FLAG_CANNOT_EXECUTION
| PROGRAM_ID_CATEGORY_FLAG_NOT_REQUIRE_RIGHT_FOR_MOUNT ),
PROGRAM_ID_CATEGORY_FIRMWARE = ( PROGRAM_ID_CATEGORY_FLAG_NORMAL
| PROGRAM_ID_CATEGORY_FLAG_CANNOT_EXECUTION
| PROGRAM_ID_CATEGORY_FLAG_SYSTEM
| PROGRAM_ID_CATEGORY_FLAG_REQUIRE_BATCH_UPDATE
| PROGRAM_ID_CATEGORY_FLAG_CAN_SKIP_CONVERT_JUMP_ID ),
PROGRAM_ID_CATEGORY_BASE = ( PROGRAM_ID_CATEGORY_FLAG_NORMAL
| PROGRAM_ID_CATEGORY_FLAG_SYSTEM
| PROGRAM_ID_CATEGORY_FLAG_REQUIRE_BATCH_UPDATE
| PROGRAM_ID_CATEGORY_FLAG_CAN_SKIP_CONVERT_JUMP_ID ),
PROGRAM_ID_CATEGORY_APPLET = ( PROGRAM_ID_CATEGORY_FLAG_NORMAL
| PROGRAM_ID_CATEGORY_FLAG_SYSTEM
| PROGRAM_ID_CATEGORY_FLAG_REQUIRE_BATCH_UPDATE ),
PROGRAM_ID_CATEGORY_SYSTEM_APPLICATION = ( PROGRAM_ID_CATEGORY_FLAG_NORMAL
| PROGRAM_ID_CATEGORY_FLAG_SYSTEM ),
PROGRAM_ID_CATEGORY_SYSTEM_CONTENT = ( PROGRAM_ID_CATEGORY_FLAG_CONTENTS
| PROGRAM_ID_CATEGORY_FLAG_CANNOT_EXECUTION
| PROGRAM_ID_CATEGORY_FLAG_SYSTEM ),
PROGRAM_ID_CATEGORY_SHARED_CONTENT = ( PROGRAM_ID_CATEGORY_FLAG_CONTENTS
| PROGRAM_ID_CATEGORY_FLAG_CANNOT_EXECUTION
| PROGRAM_ID_CATEGORY_FLAG_SYSTEM
| PROGRAM_ID_CATEGORY_FLAG_NOT_REQUIRE_RIGHT_FOR_MOUNT ),
PROGRAM_ID_CATEGORY_AUTO_UPDATE_CONTENT = ( PROGRAM_ID_CATEGORY_FLAG_CONTENTS
| PROGRAM_ID_CATEGORY_FLAG_CANNOT_EXECUTION
| PROGRAM_ID_CATEGORY_FLAG_SYSTEM
| PROGRAM_ID_CATEGORY_FLAG_NOT_REQUIRE_USER_APPROVAL
| PROGRAM_ID_CATEGORY_FLAG_NOT_REQUIRE_RIGHT_FOR_MOUNT ),
} ProgramIdCategory;
u64 ConvertTwlIdToCtrId(u64 pgid);
int GetProgramID(u64 *dest, rsf_settings *rsf, bool IsForExheader);
int GetUniqueID(u32 *dest, rsf_settings *rsf);
u16 GetTidCategory(u64 titleId);
u32 GetTidUniqueId(u64 titleId);
bool IsDemo(u16 Category);
bool IsSystem(u16 Category);
bool IsDlpChild(u16 Category);
bool IsPatch(u16 Category);
bool IsContents(u16 Category);
bool IsAddOnContent(u16 Category);
+195
View File
@@ -0,0 +1,195 @@
#include "lib.h"
#include "cia_build.h"
#include "tmd_build.h"
// Private Prototypes
int SetupTMDBuffer(buffer_struct *tik);
int SetupTMDHeader(tmd_hdr *hdr, tmd_content_info_record *info_record, cia_settings *ciaset);
int SignTMDHeader(tmd_hdr *hdr, tmd_signature *sig, keys_struct *keys);
int SetupTMDInfoRecord(tmd_content_info_record *info_record, u8 *content_record, u16 ContentCount);
int SetupTMDContentRecord(u8 *content_record, cia_settings *ciaset);
u32 PredictTMDSize(u16 ContentCount)
{
return sizeof(tmd_signature) + sizeof(tmd_hdr) + sizeof(tmd_content_info_record)*64 + sizeof(tmd_content_chunk)*ContentCount;
}
int BuildTMD(cia_settings *ciaset)
{
int result = 0;
ciaset->ciaSections.tmd.size = PredictTMDSize(ciaset->content.count);
result = SetupTMDBuffer(&ciaset->ciaSections.tmd);
if(result) return result;
// Setting TMD Struct Ptrs
tmd_signature *sig = (tmd_signature*)ciaset->ciaSections.tmd.buffer;
tmd_hdr *hdr = (tmd_hdr*)(ciaset->ciaSections.tmd.buffer+sizeof(tmd_signature));
tmd_content_info_record *info_record = (tmd_content_info_record*)(ciaset->ciaSections.tmd.buffer+sizeof(tmd_signature)+sizeof(tmd_hdr));
u8 *content_record = (u8*)(ciaset->ciaSections.tmd.buffer+sizeof(tmd_signature)+sizeof(tmd_hdr)+sizeof(tmd_content_info_record)*64);
SetupTMDContentRecord(content_record,ciaset);
SetupTMDInfoRecord(info_record,content_record,ciaset->content.count);
result = SetupTMDHeader(hdr,info_record,ciaset);
if(result) return result;
result = SignTMDHeader(hdr,sig,ciaset->keys);
return result;
}
int SetupTMDBuffer(buffer_struct *tmd)
{
tmd->buffer = calloc(1,tmd->size);
if(!tmd->buffer) {
fprintf(stderr,"[TMD ERROR] Not enough memory\n");
return MEM_ERROR;
}
return 0;
}
int SetupTMDHeader(tmd_hdr *hdr, tmd_content_info_record *info_record, cia_settings *ciaset)
{
clrmem(hdr,sizeof(tmd_hdr));
memcpy(hdr->issuer,ciaset->tmd.issuer,0x40);
hdr->formatVersion = ciaset->tmd.formatVersion;
hdr->caCrlVersion = ciaset->cert.caCrlVersion;
hdr->signerCrlVersion = ciaset->cert.signerCrlVersion;
u64_to_u8(hdr->titleID,ciaset->common.titleId,BE);
u32_to_u8(hdr->titleType,ciaset->tmd.titleType,BE);
u32_to_u8(hdr->savedataSize,ciaset->tmd.savedataSize,LE);
u32_to_u8(hdr->privSavedataSize,ciaset->tmd.privSavedataSize,LE);
hdr->twlFlag = ciaset->tmd.twlFlag;
u32_to_u8(hdr->accessRights,ciaset->tmd.accessRights,BE);
u16_to_u8(hdr->titleVersion,ciaset->tmd.version,BE);
u16_to_u8(hdr->contentCount,ciaset->content.count,BE);
ShaCalc(info_record,sizeof(tmd_content_info_record)*64,hdr->infoRecordHash,CTR_SHA_256);
return 0;
}
int SignTMDHeader(tmd_hdr *hdr, tmd_signature *sig, keys_struct *keys)
{
clrmem(sig,sizeof(tmd_signature));
u32_to_u8(sig->sigType,RSA_2048_SHA256,BE);
if (Rsa2048Key_CanSign(&keys->rsa.cp) == false)
{
printf("[TMD WARNING] Failed to sign header (key was incomplete)\n");
memset(sig->data, 0xFF, 0x100);
return 0;
}
int rsa_ret = RsaSignVerify((u8*)hdr, sizeof(tmd_hdr), sig->data, keys->rsa.cp.pub, keys->rsa.cp.pvt, RSA_2048_SHA256, CTR_RSA_SIGN);
if (rsa_ret != 0)
{
printf("[TMD WARNING] Failed to sign header (mbedtls error = -0x%x)\n", -rsa_ret);
memset(sig->data, 0xFF, 0x100);
return 0;
}
return 0;
}
int SetupTMDInfoRecord(tmd_content_info_record *info_record, u8 *content_record, u16 ContentCount)
{
clrmem(info_record,sizeof(tmd_content_info_record)*0x40);
u16_to_u8(info_record->contentIndexOffset,0x0,BE);
u16_to_u8(info_record->contentCommandCount,ContentCount,BE);
ShaCalc(content_record,sizeof(tmd_content_chunk)*ContentCount,info_record->contentChunkHash,CTR_SHA_256);
return 0;
}
int SetupTMDContentRecord(u8 *content_record, cia_settings *ciaset)
{
for(int i = 0; i < ciaset->content.count; i++){
tmd_content_chunk *ptr = (tmd_content_chunk*)(content_record+sizeof(tmd_content_chunk)*i);
u32_to_u8(ptr->id,ciaset->content.id[i],BE);
u16_to_u8(ptr->index,ciaset->content.index[i],BE);
u16_to_u8(ptr->flags,ciaset->content.flags[i],BE);
u64_to_u8(ptr->size,ciaset->content.size[i],BE);
memcpy(ptr->hash,ciaset->content.hash[i],0x20);
}
return 0;
}
tmd_hdr *GetTmdHdr(u8 *tmd)
{
u32 sigType = u8_to_u32(tmd,BE);
switch(sigType){
case(RSA_4096_SHA1):
case(RSA_4096_SHA256):
return (tmd_hdr*)(tmd+0x240);
case(RSA_2048_SHA1):
case(RSA_2048_SHA256):
return (tmd_hdr*)(tmd+0x140);
case(ECC_SHA1):
case(ECC_SHA256):
return (tmd_hdr*)(tmd+0x7C);
}
return NULL;
}
tmd_content_chunk* GetTmdContentInfo(u8 *tmd)
{
tmd_hdr *hdr = GetTmdHdr(tmd);
if(!hdr)
return NULL;
return (tmd_content_chunk*)((u8*)hdr + sizeof(tmd_hdr) + (sizeof(tmd_content_info_record)*64));
}
u64 GetTmdTitleId(tmd_hdr *hdr)
{
return u8_to_u64(hdr->titleID,BE);
}
u32 GetTmdSaveSize(tmd_hdr *hdr)
{
return u8_to_u32(hdr->savedataSize,LE);
}
u16 GetTmdContentCount(tmd_hdr *hdr)
{
return u8_to_u16(hdr->contentCount,BE);
}
u16 GetTmdVersion(tmd_hdr *hdr)
{
return u8_to_u16(hdr->titleVersion,BE);
}
u32 GetTmdContentId(tmd_content_chunk info)
{
return u8_to_u32(info.id,BE);
}
u16 GetTmdContentIndex(tmd_content_chunk info)
{
return u8_to_u16(info.index,BE);
}
u16 GetTmdContentFlags(tmd_content_chunk info)
{
return u8_to_u16(info.flags,BE);
}
u64 GetTmdContentSize(tmd_content_chunk info)
{
return u8_to_u64(info.size,BE);
}
u8* GetTmdContentHash(tmd_content_chunk *info)
{
return (u8*)info->hash;
}
bool IsTmdContentEncrypted(tmd_content_chunk info)
{
return (GetTmdContentFlags(info) & content_Encrypted) == content_Encrypted;
}
bool ValidateTmdContent(u8 *data, tmd_content_chunk info)
{
return VerifySha256(data, GetTmdContentSize(info), GetTmdContentHash(&info));
}
+61
View File
@@ -0,0 +1,61 @@
#pragma once
typedef enum
{
TYPE_CTR = 0x40,
TYPE_DATA = 0x8
} tmd_title_type;
typedef enum
{
content_Encrypted = 0x0001,
content_Optional = 0x4000,
content_Shared = 0x8000
} tmd_content_types;
typedef struct
{
u8 id[4];
u8 index[2];
u8 flags[2];
u8 size[8];
u8 hash[0x20]; // SHA 256
} tmd_content_chunk;
typedef struct
{
u8 contentIndexOffset[2];
u8 contentCommandCount[2];
u8 contentChunkHash[0x20]; // SHA 256
} tmd_content_info_record;
typedef struct
{
u8 sigType[4];
u8 data[0x100];
u8 padding[0x3C];
} tmd_signature;
typedef struct
{
u8 issuer[0x40];
u8 formatVersion;
u8 caCrlVersion;
u8 signerCrlVersion;
u8 padding0;
u8 systemVersion[8];
u8 titleID[8];
u8 titleType[4];
u8 groupID[2];
u8 savedataSize[4];
u8 privSavedataSize[4]; // Zero for CXI Content0
u8 padding1[4];
u8 twlFlag; // Zero for CXI Content0
u8 padding2[0x31];
u8 accessRights[4];
u8 titleVersion[2];
u8 contentCount[2];
u8 bootContent[2];
u8 padding3[2];
u8 infoRecordHash[0x20]; // SHA-256
} tmd_hdr;
+6
View File
@@ -0,0 +1,6 @@
#pragma once
#include "tmd.h"
// Prototypes
u32 PredictTMDSize(u16 ContentCount);
int BuildTMD(cia_settings *ciaset);
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include "tmd.h"
// Read TMD
tmd_hdr *GetTmdHdr(u8 *tmd);
tmd_content_chunk* GetTmdContentInfo(u8 *tmd);
u64 GetTmdTitleId(tmd_hdr *hdr);
u32 GetTmdSaveSize(tmd_hdr *hdr);
u16 GetTmdContentCount(tmd_hdr *hdr);
u16 GetTmdVersion(tmd_hdr *hdr);
u32 GetTmdContentId(tmd_content_chunk info);
u16 GetTmdContentIndex(tmd_content_chunk info);
u16 GetTmdContentFlags(tmd_content_chunk info);
u64 GetTmdContentSize(tmd_content_chunk info);
u8* GetTmdContentHash(tmd_content_chunk info);
bool IsTmdContentEncrypted(tmd_content_chunk info);
bool ValidateTmdContent(u8 *data, tmd_content_chunk info);
+47
View File
@@ -0,0 +1,47 @@
#include <stdlib.h>
#include <stdint.h>
//Bools
typedef enum
{
Good,
Fail
} return_basic;
typedef enum
{
MEM_ERROR = -1,
FAILED_TO_OPEN_FILE = -2,
FAILED_TO_IMPORT_FILE = -3,
FAILED_TO_CREATE_OUTFILE = -4,
} global_errors;
typedef enum
{
BE = 0,
LE = 1
} endianness_flag;
typedef enum
{
KB = 1024,
MB = 1048576,
GB = 1073741824
} file_unit_size;
typedef enum
{
MAX_U8 = 0xff,
MAX_U16 = 0xffff,
MAX_U32 = 0xffffffff,
MAX_U64 = 0xffffffffffffffff,
} data_type_max;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
File diff suppressed because it is too large Load Diff
+308
View File
@@ -0,0 +1,308 @@
#pragma once
typedef enum
{
CCI_MAX_CONTENT = 8,
CIA_MAX_CONTENT = MAX_U16,
} content_limits;
typedef enum
{
VER_MAJOR,
VER_MINOR,
VER_MICRO
} title_ver_index;
typedef enum
{
VER_MAX = 65535,
VER_MAJOR_MAX = 63,
VER_MINOR_MAX = 63,
VER_MICRO_MAX = 15,
VER_DVER_MAX = 4095,
} title_ver_max;
typedef enum
{
CVER_DTYPE_TMD,
CVER_DTYPE_CIA,
} cver_data_type;
typedef enum
{
USR_PTR_PASS_FAIL = -1,
USR_HELP = -2,
USR_ARG_REQ_PARAM = -3,
USR_UNK_ARG = -4,
USR_BAD_ARG = -5,
USR_MEM_ERROR = -6,
} user_settings_errors;
typedef enum
{
infile_none,
infile_ncch,
infile_ncsd,
infile_srl,
infile_cia,
} infile_type;
typedef enum
{
format_not_set,
CXI,
CFA,
CCI,
CIA,
NCCH
} output_format;
static const char output_extention[5][5] = {".cxi",".cfa",".cci",".cia",".app"};
/* This does not follow style, so the rsf string names match the variables where they're stored */
typedef struct
{
struct{
// Booleans
bool MediaFootPadding;
bool AllowUnalignedSection;
bool EnableCrypt;
bool EnableCompress;
bool FreeProductCode;
bool UseOnSD;
} Option;
struct{
// Booleans
bool DisableDebug;
bool EnableForceDebug;
bool CanWriteSharedPage;
bool CanUsePrivilegedPriority;
bool CanUseNonAlphabetAndNumber;
bool PermitMainFunctionArgument;
bool CanShareDeviceMemory;
bool UseOtherVariationSaveData;
bool RunnableOnSleep;
bool SpecialMemoryArrange;
bool CanAccessCore2;
bool UseExtSaveData;
bool EnableL2Cache;
// Strings
char *IdealProcessor;
char *Priority;
char *MemoryType;
char *SystemMode;
char *SystemModeExt;
char *CpuSpeed;
char *CoreVersion;
char *HandleTableSize;
char *SystemSaveDataId1;
char *SystemSaveDataId2;
char *OtherUserSaveDataId1;
char *OtherUserSaveDataId2;
char *OtherUserSaveDataId3;
char *ExtSaveDataId;
char *AffinityMask;
// Strings From DESC
char *DescVersion;
char *ResourceLimitCategory;
char *ReleaseKernelMajor;
char *ReleaseKernelMinor;
char *MaxCpu;
// String Collections
u32 MemoryMappingNum;
char **MemoryMapping;
u32 IORegisterMappingNum;
char **IORegisterMapping;
u32 FileSystemAccessNum;
char **FileSystemAccess;
u32 IoAccessControlNum;
char **IoAccessControl; //Equiv to Arm9AccessControl
u32 InterruptNumbersNum;
char **InterruptNumbers;
u32 SystemCallAccessNum;
char **SystemCallAccess;
u32 ServiceAccessControlNum;
char **ServiceAccessControl;
u32 AccessibleSaveDataIdsNum;
char **AccessibleSaveDataIds;
} AccessControlInfo;
struct{
// Strings
char *AppType;
char *StackSize;
char *RemasterVersion;
char *SaveDataSize;
char *JumpId;
// String Collections
u32 DependencyNum;
char **Dependency;
} SystemControlInfo;
struct{
// Strings
char *Title;
char *CompanyCode;
char *ProductCode;
char *ContentType;
char *Logo;
} BasicInfo;
struct{
// Strings
char *RootPath;
// String Collections
u32 DefaultRejectNum;
char **DefaultReject;
u32 RejectNum;
char **Reject;
u32 IncludeNum;
char **Include;
u32 FileNum;
char **File;
} RomFs;
struct{
// Strings
char *Platform;
char *Category;
char *UniqueId;
char *Version;
char *ContentsIndex;
char *Variation;
char *ChildIndex;
char *DemoIndex;
char *TargetCategory;
// String Collections
u32 CategoryFlagsNum;
char **CategoryFlags;
} TitleInfo;
struct{
char *WritableAddress;
char *CardType;
char *CryptoType;
char *CardDevice;
char *MediaType;
char *MediaSize;
char *BackupWriteWaitTime;
char *SaveCrypto;
} CardInfo;
struct{
bool Found;
char *D;
char *P;
char *Q;
char *DP;
char *DQ;
char *InverseQ;
char *Modulus;
char *Exponent;
char *AccCtlDescSign;
char *AccCtlDescBin;
} CommonHeaderKey;
} rsf_settings;
typedef struct
{
char *name;
char *value;
} dname_item;
typedef struct
{
dname_item *items;
u32 m_items;
u32 u_items;
} dname_struct;
typedef struct
{
struct{
bool verbose;
char *rsfPath;
bool outFileName_mallocd;
char *outFileName;
output_format outFormat;
// Keys
keys_struct keys;
// RSF Imported Settings
rsf_settings rsfSet;
// Content Details
char **contentPath;
u64 contentSize[CIA_MAX_CONTENT];
char *workingFilePath;
infile_type workingFileType; // Could Be ncch/ncsd/srl/cia.
buffer_struct workingFile;
} common;
dname_struct dname; // For RSF value subsitution
struct{
bool buildNcch0;
output_format ncchType;
char *elfPath;
char *iconPath;
char *bannerPath;
char *logoPath; // override logo specs in RSF
bool includeExefsLogo; // for <5.x compatibility
// ncch rebuild settings
char *codePath; // uncompressed exefs .code
char *exheaderPath; // for .code details
char *plainRegionPath; // prebuilt Plain Region
char *romfsPath; // Prebuild _cleartext_ romfs binary
bool noCodePadding; // do not pad code.bin for sysmodule
bool useSecCrypto;
u8 keyXID;
} ncch; // Ncch0 Build
struct{
bool useSDKStockData; // incase we want to use the SDK stock data, for whatever reason.
bool dontModifyNcchTitleID;
bool closeAlignWritableRegion;
u8 cverDataType;
char *cverDataPath;
} cci; // CCI Settings
struct{
bool randomTitleKey;
char *titleKey;
bool encryptCia;
bool DlcContent;
bool includeUpdateNcch;
bool useNormTitleVer;
bool useDataTitleVer;
bool useFullTitleVer;
u16 titleVersion[3];
u32 deviceId;
u32 eshopAccId;
u64 contentId[CIA_MAX_CONTENT]; // For CIA
} cia; // CIA Settings
} user_settings;
// Prototypes
void init_UserSettings(user_settings *set);
void free_UserSettings(user_settings *set);
int ParseArgs(int argc, char *argv[], user_settings *usr_settings);
+422
View File
@@ -0,0 +1,422 @@
#include "lib.h"
#include <mbedtls/base64.h>
#define IO_BLOCKSIZE 5*MB
// Memory
int CopyData(u8 **dest, const u8 *source, u64 size)
{
if(!*dest){
*dest = malloc(size);
if(!*dest) return -1;
}
memcpy(*dest,source,size);
return 0;
}
void rndset(void *ptr, u64 num)
{
u8 *tmp = (u8*)ptr;
for(u64 i = 0; i < num ; i++)
tmp[i] = u8GetRand();
}
void clrmem(void *ptr, u64 num)
{
memset(ptr,0,num);
}
// Misc
u64 roundup(u64 value, u64 alignment)
{
return value + alignment - value % alignment;
}
u64 align(u64 value, u64 alignment)
{
if(value % alignment != 0)
return roundup(value,alignment);
else
return value;
}
u64 min64(u64 a, u64 b)
{
if(a < b) return a;
return b;
}
u64 max64(u64 a, u64 b)
{
if(a > b) return a;
return b;
}
// Strings
char* replace_filextention(const char *input, const char *new_ext)
{
if(input == NULL || new_ext == NULL)
return NULL;
char *new_name;
char *ext = strrchr(input, '.');
// If there is no existing extention, just append new_ext
if (!ext) {
new_name = calloc(strlen(input) + strlen(new_ext), 1);
sprintf(new_name, "%s%s", input, new_ext);
}
else {
u32 size = ext - input;
new_name = calloc(size + strlen(new_ext) + 1, 1);
strncpy(new_name, input, size);
sprintf(new_name, "%s%s", new_name, new_ext);
}
return new_name;
}
void memdump(FILE* fout, const char* prefix, const u8* data, u32 size)
{
u32 i;
u32 prefixlen = strlen(prefix);
u32 offs = 0;
u32 line = 0;
while(size)
{
u32 max = 32;
if (max > size)
max = size;
if (line==0)
fprintf(fout, "%s", prefix);
else
fprintf(fout, "%*s", prefixlen, "");
for(i=0; i<max; i++)
fprintf(fout, "%02X", data[offs+i]);
fprintf(fout, "\n");
line++;
size -= max;
offs += max;
}
}
// Base64
bool IsValidB64Char(char chr)
{
return (isalnum(chr) || chr == '+' || chr == '/' || chr == '=');
}
size_t b64_strlen(const char *str)
{
size_t count = 0;
size_t i = 0;
while(str[i] != 0x0){
if(IsValidB64Char(str[i])) {
//printf("Is Valid: %c\n",str[i]);
count++;
}
i++;
}
return count;
}
void b64_strcpy(char *dst, const char *src)
{
size_t src_len = strlen(src);
size_t j = 0;
for(size_t i = 0; i < src_len; i++){
if(IsValidB64Char(src[i])){
dst[j] = src[i];
j++;
}
}
dst[j] = 0;
//memdump(stdout,"src: ",(u8*)src,src_len+1);
//memdump(stdout,"dst: ",(u8*)dst,j+1);
}
int b64_decode(u8 *dst, const char *src, size_t dst_size)
{
int ret;
size_t size = dst_size;
ret = mbedtls_base64_decode(dst, size, &size, (const u8*)src, strlen(src));
if(size != dst_size)
ret = MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
return ret;
}
// Pseudo-Random Number Generator
void initRand(void)
{
srand(time(0));
}
u8 u8GetRand(void)
{
return rand() % 0xff;
}
u16 u16GetRand(void)
{
return rand() % 0xffff;
}
u32 u32GetRand(void)
{
return (u32)u16GetRand() | (u32)u16GetRand() << 16;
}
u64 u64GetRand(void)
{
return (u64)u32GetRand() | (u64)u32GetRand() << 32;
}
//Char IO
bool AssertFile(char *filename)
{
if(filename == NULL)
return false;
#ifdef _WIN32
struct _stat64 st;
return _stat64(filename, &st) == 0;
#else
struct stat st;
return stat(filename, &st) == 0;
#endif
}
u64 GetFileSize64(char *filename)
{
#ifdef _WIN32
struct _stat64 st;
if( _stat64(filename, &st) != 0)
return 0;
else
return st.st_size;
#else
struct stat st;
if( stat(filename, &st) != 0)
return 0;
else
return st.st_size;
#endif
}
int makedir(const char* dir)
{
#ifdef _WIN32
return _mkdir(dir);
#else
return mkdir(dir, 0777);
#endif
}
char *getcwdir(char *buffer,int maxlen)
{
#ifdef _WIN32
return _getcwd(buffer,maxlen);
#else
return getcwd(buffer,maxlen);
#endif
}
int TruncateFile64(char *filename, u64 filelen)
{
#ifdef _WIN32
HANDLE fh;
LARGE_INTEGER fp;
fp.QuadPart = filelen;
fh = CreateFile(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (fh == INVALID_HANDLE_VALUE) {
printf("[!] Invalid File handle\n");
return 1;
}
if (SetFilePointerEx(fh, fp, NULL, FILE_BEGIN) == 0 || SetEndOfFile(fh) == 0) {
printf("[!] Truncate failed\n");
CloseHandle(fh);
return 1;
}
CloseHandle(fh);
return 0;
#else
return truncate(filename,filelen);
#endif
}
//IO Misc
u8* ImportFile(char *file, u64 size)
{
u64 fsize = GetFileSize64(file);
if(size > 0 && size != fsize){
fprintf(stderr,"[!] %s has an invalid size (0x%"PRIx64")\n",file, fsize);
return NULL;
}
u8 *data = (u8*)calloc(1,fsize);
if(!data){
fprintf(stderr,"[!] Not enough memory\n");
return NULL;
}
FILE *fp = fopen(file,"rb");
ReadFile64(data, fsize, 0, fp);
fclose(fp);
return data;
}
void WriteBuffer(const void *buffer, u64 size, u64 offset, FILE *fp)
{
const u8* _buffer = (const u8*)buffer;
fseek_64(fp,offset);
for (; size > IO_BLOCKSIZE; size -= IO_BLOCKSIZE, _buffer += IO_BLOCKSIZE)
fwrite(_buffer, IO_BLOCKSIZE, 1, fp);
fwrite(_buffer,size,1,fp);
}
void ReadFile64(void *outbuff, u64 size, u64 offset, FILE *fp)
{
u8* _buffer = (u8*)outbuff;
fseek_64(fp, offset);
for (; size > IO_BLOCKSIZE; size -= IO_BLOCKSIZE, _buffer += IO_BLOCKSIZE)
fread(_buffer, IO_BLOCKSIZE, 1, fp);
fread(_buffer, size, 1, fp);
}
int fseek_64(FILE *fp, u64 file_pos)
{
#ifdef _WIN32
fpos_t pos = file_pos;
return fsetpos(fp,&pos);
#else
return fseeko(fp,file_pos,SEEK_SET);
#endif
}
//Data Size conversion
u16 u8_to_u16(const u8 *value, u8 endianness)
{
u16 new_value = 0;
switch(endianness){
case(BE): new_value = (value[1]<<0) | (value[0]<<8); break;
case(LE): new_value = (value[0]<<0) | (value[1]<<8); break;
}
return new_value;
}
u32 u8_to_u32(const u8 *value, u8 endianness)
{
u32 new_value = 0;
switch(endianness){
case(BE): new_value = (value[3]<<0) | (value[2]<<8) | (value[1]<<16) | (value[0]<<24); break;
case(LE): new_value = (value[0]<<0) | (value[1]<<8) | (value[2]<<16) | (value[3]<<24); break;
}
return new_value;
}
u64 u8_to_u64(const u8 *value, u8 endianness)
{
u64 ret = 0;
switch(endianness){
case(BE):
ret |= (u64)value[7]<<0;
ret |= (u64)value[6]<<8;
ret |= (u64)value[5]<<16;
ret |= (u64)value[4]<<24;
ret |= (u64)value[3]<<32;
ret |= (u64)value[2]<<40;
ret |= (u64)value[1]<<48;
ret |= (u64)value[0]<<56;
break;
//return (value[7]<<0) | (value[6]<<8) | (value[5]<<16) | (value[4]<<24) | (value[3]<<32) | (value[2]<<40) | (value[1]<<48) | (value[0]<<56);
case(LE):
ret |= (u64)value[0]<<0;
ret |= (u64)value[1]<<8;
ret |= (u64)value[2]<<16;
ret |= (u64)value[3]<<24;
ret |= (u64)value[4]<<32;
ret |= (u64)value[5]<<40;
ret |= (u64)value[6]<<48;
ret |= (u64)value[7]<<56;
break;
//return (value[0]<<0) | (value[1]<<8) | (value[2]<<16) | (value[3]<<24) | (value[4]<<32) | (value[5]<<40) | (value[6]<<48) | (value[7]<<56);
}
return ret;
}
int u16_to_u8(u8 *out_value, u16 in_value, u8 endianness)
{
switch(endianness){
case(BE):
out_value[0]=(in_value >> 8);
out_value[1]=(in_value >> 0);
break;
case(LE):
out_value[0]=(in_value >> 0);
out_value[1]=(in_value >> 8);
break;
}
return 0;
}
int u32_to_u8(u8 *out_value, u32 in_value, u8 endianness)
{
switch(endianness){
case(BE):
out_value[0]=(in_value >> 24);
out_value[1]=(in_value >> 16);
out_value[2]=(in_value >> 8);
out_value[3]=(in_value >> 0);
break;
case(LE):
out_value[0]=(in_value >> 0);
out_value[1]=(in_value >> 8);
out_value[2]=(in_value >> 16);
out_value[3]=(in_value >> 24);
break;
}
return 0;
}
int u64_to_u8(u8 *out_value, u64 in_value, u8 endianness)
{
switch(endianness){
case(BE):
out_value[0]=(in_value >> 56);
out_value[1]=(in_value >> 48);
out_value[2]=(in_value >> 40);
out_value[3]=(in_value >> 32);
out_value[4]=(in_value >> 24);
out_value[5]=(in_value >> 16);
out_value[6]=(in_value >> 8);
out_value[7]=(in_value >> 0);
break;
case(LE):
out_value[0]=(in_value >> 0);
out_value[1]=(in_value >> 8);
out_value[2]=(in_value >> 16);
out_value[3]=(in_value >> 24);
out_value[4]=(in_value >> 32);
out_value[5]=(in_value >> 40);
out_value[6]=(in_value >> 48);
out_value[7]=(in_value >> 56);
break;
}
return 0;
}
+55
View File
@@ -0,0 +1,55 @@
#pragma once
typedef struct
{
u64 size;
u8 *buffer;
} buffer_struct;
// Memory
int CopyData(u8 **dest, const u8 *source, u64 size);
void rndset(void *ptr, u64 num);
void clrmem(void *ptr, u64 num);
// MISC
u64 roundup(u64 value, u64 alignment);
u64 align(u64 value, u64 alignment);
u64 min64(u64 a, u64 b);
u64 max64(u64 a, u64 b);
// Strings
void memdump(FILE* fout, const char* prefix, const u8* data, u32 size);
char* replace_filextention(const char *input, const char *extention);
// Base64
bool IsValidB64Char(char chr);
size_t b64_strlen(const char *str);
void b64_strcpy(char *dst, const char *src);
int b64_decode(u8 *dst, const char *src, size_t dst_size);
// Pseudo-Random Number Generator
void initRand(void);
u8 u8GetRand(void);
u16 u16GetRand(void);
u32 u32GetRand(void);
u64 u64GetRand(void);
//Char IO
bool AssertFile(char *filename);
u64 GetFileSize64(char *filename);
int makedir(const char* dir);
int TruncateFile64(char *filename, u64 filelen);
//IO Misc
u8* ImportFile(char *file, u64 size);
void WriteBuffer(const void *buffer, u64 size, u64 offset, FILE *output);
void ReadFile64(void *outbuff, u64 size, u64 offset, FILE *file);
int fseek_64(FILE *fp, u64 file_pos);
//Data Size conversion
u16 u8_to_u16(const u8 *value, u8 endianness);
u32 u8_to_u32(const u8 *value, u8 endianness);
u64 u8_to_u64(const u8 *value, u8 endianness);
int u16_to_u8(u8 *out_value, u16 in_value, u8 endianness);
int u32_to_u8(u8 *out_value, u32 in_value, u8 endianness);
int u64_to_u8(u8 *out_value, u64 in_value, u8 endianness);
+583
View File
@@ -0,0 +1,583 @@
#include "lib.h"
#include "rsf_settings.h"
// Private Prototypes
void InitYamlContext(ctr_yaml_context *ctx);
int ParseSpecFile(rsf_settings *set, char *path, dname_struct *dname);
void ProcessYamlString(ctr_yaml_context *ctx);
void CheckEvent(ctr_yaml_context *ctx);
void BadYamlFormatting(void);
// Code
int GetRsfSettings(user_settings *set)
{
int ret = 0;
if(set->common.rsfPath) {
if(!AssertFile(set->common.rsfPath)) {
fprintf(stderr,"[RSF ERROR] Failed to open %s\n",set->common.rsfPath);
return FAILED_TO_OPEN_FILE;
}
ret = ParseSpecFile(&set->common.rsfSet,set->common.rsfPath, &set->dname);
}
return ret;
}
int ParseSpecFile(rsf_settings *set, char *path, dname_struct *dname)
{
ctr_yaml_context *ctx = malloc(sizeof(ctr_yaml_context));
InitYamlContext(ctx);
/* Set Specfile Type */
/* Create the Parser object. */
yaml_parser_initialize(&ctx->parser);
/* Set a file input. */
FILE *input = fopen(path,"rb");
yaml_parser_set_input_file(&ctx->parser, input);
ctx->dname = dname;
ctx->IsSequence = false;
ctx->IsKey = true;
ctx->prev_event = 0;
ctx->Level = 0;
/* Read the event sequence. */
while (!ctx->done) {
/* Get the next event. */
GetEvent(ctx);
if(ctx->error) goto error;
/* Proccess Event */
if(EventIsScalar(ctx)){
EvaluateRSF(set,ctx);
if(ctx->error) goto error;
break;
}
/*
if((ctx->event.type == YAML_SEQUENCE_START_EVENT|| ctx->event.type == YAML_MAPPING_START_EVENT) && ctx->prev_event == YAML_SCALAR_EVENT) printf(":\n");
if(ctx->event.type == YAML_SCALAR_EVENT){
if(ctx->IsSequence){
printf(" - %s\n",ctx->event.data.scalar.value);
}
else{
if(!ctx->IsKey) printf(": %s\n",ctx->event.data.scalar.value);
else printf("%s",ctx->event.data.scalar.value);
}
}
*/
/* Finish Event */
FinishEvent(ctx);
if(ctx->error) goto error;
}
/* Destroy the Parser object. */
yaml_parser_delete(&ctx->parser);
fclose(input);
return 0;
/* On error. */
error:
fprintf(stderr,"[RSF ERROR] Error Proccessing RSF file\n");
/* Destroy the Parser object. */
yaml_parser_delete(&ctx->parser);
fclose(input);
return ctx->error;
}
void InitYamlContext(ctr_yaml_context *ctx)
{
memset(ctx,0,sizeof(ctr_yaml_context));
}
void ProcessYamlString(ctr_yaml_context *ctx)
{
if(ctx->string)
{
free(ctx->string);
ctx->string = NULL;
}
if(!ctx->event.data.scalar.value)
return;
char *rawStr = (char*)ctx->event.data.scalar.value;
int rawStrLen = strlen(rawStr);
int procStrLen = 0;
char *subStart = NULL;
char *subEnd = NULL;
char *pos = rawStr;
char *end = (rawStr+rawStrLen);
while(pos < end)
{
// Find substution syntax in string
subStart = strstr(pos,"$(");
if(!subStart)
{
procStrLen += (end - pos);
break;
}
// Check For errors
if((end - subStart) <= 3) // Valid use of substitution syntax is not possible
{
ctx->error = true;
return;
}
subEnd = strstr((subStart+2),")");
if(!subEnd) // no closing bracket
{
ctx->error = true;
return;
}
// Add length of string not accounted for
procStrLen += (int)(subStart - pos);
// Get Length Of substitution key
char *subName = (subStart+2);
int subNameLen = (int)((subEnd - subStart) - 2);
// Add length of substitutiion value
for(u32 i = 0; i < ctx->dname->u_items; i++){
char *testSubName = ctx->dname->items[i].name;
int testSubNameLen = strlen(testSubName);
char *testSubValue = ctx->dname->items[i].value;
int testSubValueLen = strlen(testSubValue);
if(testSubNameLen != subNameLen)
continue;
if(strncmp(testSubName,subName,subNameLen) != 0)
continue;
procStrLen += testSubValueLen;
break;
}
// Increment pos
pos = (subEnd + 1);
}
// Allocate memory for processed string
ctx->string = calloc(procStrLen+1,sizeof(char));
char *procStr = ctx->string;
pos = rawStr;
end = (rawStr+rawStrLen);
while(pos < end)
{
// Find substution syntax in string
subStart = strstr(pos,"$(");
if(!subStart)
{
strncat(procStr,pos,(end - pos));
break;
}
// Check For errors
if((end - subStart) <= 3) // Valid use of substitution syntax is not possible
{
ctx->error = true;
return;
}
subEnd = strstr((subStart+2),")");
if(!subEnd) // no closing bracket
{
ctx->error = true;
return;
}
// Add length of string not accounted for
strncat(procStr,pos,(subStart - pos));
// Get Length Of substitution key
char *subName = (subStart+2);
int subNameLen = (int)((subEnd - subStart) - 2);
// Add length of substitutiion value
for(u32 i = 0; i < ctx->dname->u_items; i++){
char *testSubName = ctx->dname->items[i].name;
int testSubNameLen = strlen(testSubName);
char *testSubValue = ctx->dname->items[i].value;
int testSubValueLen = strlen(testSubValue);
if(testSubNameLen != subNameLen)
continue;
if(strncmp(testSubName,subName,subNameLen) != 0)
continue;
strncat(procStr,testSubValue,testSubValueLen);
break;
}
// Increment pos
pos = (subEnd + 1);
}
return;
}
char *GetYamlString(ctr_yaml_context *ctx)
{
return ctx->string;
}
u32 GetYamlStringSize(ctr_yaml_context *ctx)
{
return strlen(GetYamlString(ctx)); // can't read size from yaml, as string may have been intercepted
}
void GetEvent(ctr_yaml_context *ctx)
{
if (!yaml_parser_parse(&ctx->parser, &ctx->event)){
ctx->error = YAML_API_ERROR;
return;
}
CheckEvent(ctx);
}
void CheckEvent(ctr_yaml_context *ctx)
{
switch(ctx->event.type){
case YAML_SCALAR_EVENT:
ProcessYamlString(ctx);
break;
case YAML_SEQUENCE_START_EVENT:
ctx->IsSequence = true;
ctx->IsKey = true;
ctx->Level++;
//printf("[LEVEL] %d\n",ctx->Level);
break;
case YAML_SEQUENCE_END_EVENT:
ctx->IsSequence = false;
ctx->IsKey = true;
ctx->Level--;
//printf("[LEVEL] %d\n",ctx->Level);
break;
case YAML_MAPPING_START_EVENT:
ctx->IsKey = true;
ctx->Level++;
//printf("[LEVEL] %d\n",ctx->Level);
break;
case YAML_MAPPING_END_EVENT:
ctx->IsKey = true;
ctx->Level--;
//printf("[LEVEL] %d\n",ctx->Level);
break;
case YAML_DOCUMENT_END_EVENT:
case YAML_STREAM_END_EVENT:
ctx->done = true;
break;
default: break;
}
}
void FinishEvent(ctr_yaml_context *ctx)
{
if(ctx->event.type == YAML_SCALAR_EVENT) {
if(!ctx->IsSequence){
ctx->IsKey = !ctx->IsKey;
//if(!ctx->IsKey)ctx->IsKey = true;
//else ctx->IsKey = false;
}
if(ctx->string){
free(ctx->string);
ctx->string = NULL;
}
}
ctx->prev_event = ctx->event.type;
yaml_event_delete(&ctx->event);
}
bool EventIsScalar(ctr_yaml_context *ctx)
{
return (ctx->event.type == YAML_SCALAR_EVENT);
}
bool EventIsMappingStart(ctr_yaml_context *ctx)
{
return (ctx->event.type == YAML_MAPPING_START_EVENT);
}
bool EventIsMappingEnd(ctr_yaml_context *ctx)
{
return (ctx->event.type == YAML_MAPPING_END_EVENT);
}
bool EventIsSequenceStart(ctr_yaml_context *ctx)
{
return (ctx->event.type == YAML_SEQUENCE_START_EVENT);
}
bool EventIsSequenceEnd(ctr_yaml_context *ctx)
{
return (ctx->event.type == YAML_SEQUENCE_END_EVENT);
}
bool CheckSequenceEvent(ctr_yaml_context *ctx)
{
GetEvent(ctx);
if(!EventIsSequenceStart(ctx)){
FinishEvent(ctx);
//fprintf(stderr,"[-] Bad formatting in Spec file (Expected Sequence)\n");
//ctx->error = YAML_BAD_FORMATTING;
return false;
}
FinishEvent(ctx);
return true;
}
bool CheckMappingEvent(ctr_yaml_context *ctx)
{
GetEvent(ctx);
if(!EventIsMappingStart(ctx)){
FinishEvent(ctx);
//fprintf(stderr,"[-] Bad formatting in Spec file (Expected Mapping)\n");
//ctx->error = YAML_BAD_FORMATTING;
return false;
}
FinishEvent(ctx);
return true;
}
void BadYamlFormatting(void)
{
fprintf(stderr,"[-] Bad formatting in Spec file\n");
}
bool cmpYamlValue(char *string,ctr_yaml_context *ctx)
{
return (strcmp(GetYamlString(ctx),string) == 0);
}
bool casecmpYamlValue(char *string,ctr_yaml_context *ctx)
{
return (strcasecmp(GetYamlString(ctx),string) == 0);
}
void SetSimpleYAMLValue(char **dest, char *key, ctr_yaml_context *ctx, u32 size_limit)
{
if(*dest){
fprintf(stderr,"[RSF ERROR] Item '%s' is already set\n",key);
ctx->error = YAML_MEM_ERROR;
return;
}
GetEvent(ctx);
if(ctx->error || ctx->done) return;
if(!EventIsScalar(ctx)){
fprintf(stderr,"[RSF ERROR] '%s' requires a value\n",key);
ctx->error = YAML_BAD_FORMATTING;
return;
}
if(!GetYamlStringSize(ctx)) return;
u32 size = GetYamlStringSize(ctx);
if(size > size_limit && size_limit) size = size_limit;
char *tmp = *dest;
tmp = malloc(size+2);
if(!tmp) {
ctx->error = YAML_MEM_ERROR;
return;
}
memset(tmp,0,size+2);
memcpy(tmp,GetYamlString(ctx),size);
//printf("Setting %s to %s (size of %d)\n",key,GetYamlString(ctx),size);
//printf("Check: %s & %x\n",tmp,tmp);
*dest = tmp;
}
void SetBoolYAMLValue(bool *dest, char *key, ctr_yaml_context *ctx)
{
GetEvent(ctx);
if(ctx->error || ctx->done) return;
if(!EventIsScalar(ctx)){
fprintf(stderr,"[RSF ERROR] '%s' requires a value\n",key);
ctx->error = YAML_BAD_FORMATTING;
return;
}
if(!GetYamlStringSize(ctx)){
fprintf(stderr,"[RSF ERROR] '%s' requires a value\n",key);
ctx->error = YAML_BAD_FORMATTING;
return;
}
if(casecmpYamlValue("true",ctx))
*dest = true;
else if(casecmpYamlValue("false",ctx))
*dest = false;
else{
fprintf(stderr,"[RSF ERROR] Invalid '%s'\n",key);
ctx->error = YAML_BAD_FORMATTING;
}
return;
}
u32 SetYAMLSequence(char ***dest, char *key, ctr_yaml_context *ctx)
{
if(*dest){
fprintf(stderr,"[RSF ERROR] %s already set\n",key);
ctx->error = YAML_MEM_ERROR;
return 0;
}
u32 ActualCount = 0;
u32 SlotCount = 0;
char **tmp = *dest;
if(!CheckSequenceEvent(ctx)) return 0;
SlotCount = 10;
tmp = malloc((SlotCount+1)*sizeof(char*));
if(!tmp){
ctx->error = YAML_MEM_ERROR;
return 0;
}
memset(tmp,0,(SlotCount+1)*sizeof(char*));
GetEvent(ctx);
if(ctx->error || ctx->done) return 0;
if(!EventIsScalar(ctx)){
fprintf(stderr,"[RSF ERROR] '%s' requires a value\n",key);
ctx->error = YAML_BAD_FORMATTING;
return 0;
}
if(!GetYamlStringSize(ctx)) return 0;
u32 InitLevel = ctx->Level;
while(ctx->Level == InitLevel){
if(ctx->error || ctx->done) return 0;
tmp[ActualCount] = malloc(GetYamlStringSize(ctx)+1);
memset(tmp[ActualCount],0,GetYamlStringSize(ctx)+1);
memcpy(tmp[ActualCount],GetYamlString(ctx),GetYamlStringSize(ctx));
ActualCount++;
if(ActualCount >= SlotCount){ // if Exceeding Ptr capacity, expand buffer
SlotCount = SlotCount*2;
/*
char **tmp1 = malloc((SlotCount+1)*sizeof(char*)); // allocate new buffer
if(!tmp1){
ctx->error = YAML_MEM_ERROR;
return 0;
}
memset(tmp1,0,(SlotCount+1)*sizeof(char*));
for(u32 i = 0; i < ActualCount; i++) tmp1[i] = tmp[i]; // Transfer ptrs
free(tmp); // free original buffer
tmp = tmp1; // transfer main ptr
*/
tmp = realloc(tmp,(SlotCount+1)*sizeof(char*));
if(!tmp){
ctx->error = true;
return 0;
}
}
FinishEvent(ctx);
GetEvent(ctx);
}
FinishEvent(ctx);
*dest = tmp; // Give main ptr to location
return ActualCount++; // return number of strings
}
u32 SetYAMLSequenceFromMapping(char ***dest, char *key, ctr_yaml_context *ctx, bool StoreKey)
{
if(*dest){
fprintf(stderr,"[RSF ERROR] %s already set\n",key);
ctx->error = YAML_MEM_ERROR;
return 0;
}
u32 ActualCount = 0;
u32 SlotCount = 0;
char **tmp = *dest;
if(!CheckMappingEvent(ctx)) return 0;
SlotCount = 10;
tmp = malloc((SlotCount+1)*sizeof(char*));
if(!tmp){
ctx->error = YAML_MEM_ERROR;
return 0;
}
memset(tmp,0,(SlotCount+1)*sizeof(char*));
GetEvent(ctx);
if(ctx->error || ctx->done) return 0;
if(!EventIsScalar(ctx)){
fprintf(stderr,"[RSF ERROR] '%s' requires a value\n",key);
ctx->error = YAML_BAD_FORMATTING;
return 0;
}
if(!GetYamlStringSize(ctx)) return 0;
u32 InitLevel = ctx->Level;
while(ctx->Level == InitLevel){
if(ctx->error || ctx->done) return 0;
if(ctx->IsKey == StoreKey){
tmp[ActualCount] = malloc(GetYamlStringSize(ctx)+1);
memset(tmp[ActualCount],0,GetYamlStringSize(ctx)+1);
memcpy(tmp[ActualCount],GetYamlString(ctx),GetYamlStringSize(ctx));
ActualCount++;
if(ActualCount >= SlotCount){ // if Exceeding Ptr capacity, expand buffer
SlotCount = SlotCount*2;
char **tmp1 = malloc((SlotCount+1)*sizeof(char*)); // allocate new buffer
if(!tmp1){
ctx->error = YAML_MEM_ERROR;
return 0;
}
memset(tmp1,0,(SlotCount+1)*sizeof(char*));
for(u32 i = 0; i < ActualCount; i++) tmp1[i] = tmp[i]; // Transfer ptrs
free(tmp); // free original buffer
tmp = tmp1; // transfer main ptr
}
}
FinishEvent(ctx);
GetEvent(ctx);
}
FinishEvent(ctx);
*dest = tmp; // Give main ptr to location
return ActualCount++; // return number of strings
}
/*
void SkipYAMLGroup(ctr_yaml_context *ctx)
{
FinishEvent(ctx);
GetEvent(ctx);
if(!EventIsMappingStart(ctx) && !EventIsSequenceStart(ctx) && EventIsScalar(ctx)) return;
FinishEvent(ctx);
GetEvent(ctx);
if(ctx->error || ctx->done) return;
if(!EventIsScalar(ctx)){
fprintf(stderr,"[RSF ERROR] Format error\n");
ctx->error = YAML_BAD_FORMATTING;
return;
}
if(!GetYamlStringSize(ctx)) return;
u32 InitLevel = ctx->Level;
while(ctx->Level == InitLevel){
if(ctx->error || ctx->done) return;
FinishEvent(ctx);
GetEvent(ctx);
}
FinishEvent(ctx);
}
*/
+62
View File
@@ -0,0 +1,62 @@
#pragma once
#include <libyaml/yaml.h>
typedef enum
{
YAML_API_ERROR = -1,
YAML_BAD_GROUP_HEADER = -2,
YAML_BAD_FORMATTING = -3,
YAML_MEM_ERROR = -4,
YAML_UNKNOWN_KEY = -5,
} ctr_yaml_error;
typedef struct
{
// For Continued Parsing of file
yaml_parser_t parser;
yaml_event_t event;
bool done;
int error;
// Important Details
dname_struct *dname;
bool IsSequence;
bool IsKey;
yaml_event_type_t prev_event;
u32 Level;
// Processed String
char *string;
} ctr_yaml_context;
// Public Prototypes
int GetRsfSettings(user_settings *set);
// For scalar events
char *GetYamlString(ctr_yaml_context *ctx);
u32 GetYamlStringSize(ctr_yaml_context *ctx);
bool cmpYamlValue(char *string,ctr_yaml_context *ctx); // Compares a string to the current scalar event
bool casecmpYamlValue(char *string,ctr_yaml_context *ctx); // same as above but ignores case
// Event Handlers
void GetEvent(ctr_yaml_context *ctx);
void FinishEvent(ctr_yaml_context *ctx);
// Event Type Checks
bool EventIsScalar(ctr_yaml_context *ctx);
bool EventIsMappingStart(ctr_yaml_context *ctx);
bool EventIsMappingEnd(ctr_yaml_context *ctx);
bool EventIsSequenceStart(ctr_yaml_context *ctx);
bool EventIsSequenceEnd(ctr_yaml_context *ctx);
bool CheckMappingEvent(ctr_yaml_context *ctx); // With extra implement, use if lazy
bool CheckSequenceEvent(ctr_yaml_context *ctx); // With extra implement, use if lazy
// Functions which store values
void SetSimpleYAMLValue(char **dest, char *key, ctr_yaml_context *ctx, u32 size_limit);
void SetBoolYAMLValue(bool *dest, char *key, ctr_yaml_context *ctx);
u32 SetYAMLSequence(char ***dest, char *key, ctr_yaml_context *ctx);
u32 SetYAMLSequenceFromMapping(char ***dest, char *key, ctr_yaml_context *ctx, bool StoreKey);
//void SkipYAMLGroup(ctr_yaml_context *ctx);