3,970 bytes added
, 07:49, 19 April 2017
'''Title metadata''' is a format used to store information about a title (a single standalone game, channel, etc.) and all its installed contents, including which contents they consist of and their SHA1 hashes.
Many operations are done in terms of 64-byte blocks, which means you will often see padding out to the nearest 64-byte boundary at the end of a field.
== Structure ==
=== Header ===
{| class="wikitable"
|- style="background-color: #ddd;"
! Start
! Length
! Description
|-
| 0x000
| 4
| Signature type
|-
| 0x004
| 256
| Signature
|-
| 0x104
| 60
| Padding modulo 64
|-
| 0x140
| 64
| Issuer
|-
| 0x180
| 1
| Version
|-
| 0x181
| 1
| ca_crl_version
|-
| 0x182
| 1
| signer_crl_version
|-
| 0x183
| 1
| Padding modulo 64
|-
| 0x184
| 8
| System Version (the ios that the title needs)
|-
| 0x18C
| 8
| Title ID
|-
| 0x194
| 4
| Title type
|-
| 0x198
| 2
| Group ID
|-
| 0x19A
| 62
| reserved
|-
| 0x1D8
| 4
| Access rights (flags for [[DVDX|DVD-video access]] and [http://hackmii.com/2009/08/of-tmds-and-hardware/ full PPC hardware access])
|-
| 0x1DC
| 2
| Title version
|-
| 0x1DE
| 2
| Number of contents (nbr_cont)
|-
| 0x1E0
| 2
| boot index
|-
| 0x1E2
| 2
| Padding modulo 64
|-
| 0x1E4
| 36*nbr_cont
| Contents
|}
=== Content ===
{| class="wikitable"
|-
! Start
! Length
! Description
|-
| 0x00
| 4
| Content ID
|-
| 0x04
| 2
| Index
|-
| 0x06
| 2
| Type
|-
| 0x08
| 8
| Size
|-
| 0x10
| 20
| SHA1 hash
|}
=== Certificates ===
{| class="wikitable"
|-
! Start
! Length
! Description
|-
| 0x000
| 4
| Signature type
|-
| 0x004
| 256
| Signature
|-
| 0x104
| 64
| Issuer
|-
| 0x124
| 4
| Tag
|-
| 0x128
| 64
| Name
|-
| 0x168
|
| Key
|}
== Example code application ==
<source lang="c">
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
/* On a 32bit system, long is only 4 bytes- use long long instead */
typedef unsigned long u64;
</source>
<source lang="c">
typedef struct {
u32 cid; // content id
u16 index; // # number of the file
u16 type; // Wii: normal 0x0001; shared 0x8001 | Wii U: 0x2001; 0x2003; 0x6003; Bitmask, check last bit for .H3 extra hashes
u64 size;
u8 hash [20]; // SHA1 hash content
} content_record; // size: 0x24 bytes
</source>
<source lang="c">
enum sig_type {
RSA_2048 = 0x00010001,
RSA_4096 = 0x00010000
};
</source>
<source lang="c">
typedef struct {
u32 sig_type;
u8 sig[256];
u8 fill1[60];
u8 issuer[64]; // Root-CA%08x-CP%08x
u8 version;
u8 ca_crl_version;
u8 signer_crl_version;
u8 fill2;
u64 sys_version;
u64 title_id;
u32 title_type;
u16 group_id; // publisher
u8 reserved[62];
u32 access_rights;
u16 title_version;
u16 num_contents;
u16 boot_index;
u16 fill3;
content_record contents[num_contents];
} tmd;
</source>
The tmd is then followed by a chain of certificates, where each certificate is of the general form
<source lang="c">
u32 sig_type; //
u8 sig[256]; // 256 for RSA_2048, 512 for RSA_4096
u8 issuer[32];
u32 tag; // identifies what is being signed
u8 name[64]; // name of thing being signed
u8 key[...];
</source>
There is also a structure called a TmdView which is select sections of the Tmd. It has a length of 0x60+0x10*number_of_contents. The structure is somewhat like this [as returned by ES_GetTmdView] :
<source lang="c">
struct tmd_view_content_t
{
uint32_t id;
uint16_t index;
uint16_t type;
uint64_t size;
};
struct tmd_view_t
{
uint8_t version; // 0x0000;
uint8_t filler[3];
uint64_t ios_title_id; //0x0004
uint64_t title_id; // 0x00c
uint32_t title_type; //0x0014
uint16_t group_id; //0x0018
uint8_t reserved[0x3e]; //0x001a this is the same reserved 0x3e bytes from the tmd
uint16_t title_version; //0x0058
uint16_t number_contents; //0x005a
tmd_view_content_t contents[]; //0x005c
};
</source>
[[Category:File formats]]