In memory of Ben “bushing” Byer, who passed away on Monday, February 8th, 2016.

Difference between revisions of "Title metadata"

From WiiBrew
Jump to navigation Jump to search
 
(31 intermediate revisions by 16 users not shown)
Line 1: Line 1:
これは日本のニンテンドーfucking !私は神のCEOは、午前くそー!お客様の製品やfucking私fucking私のfuckingの雌ロバが改造停止を訴える!あなたファック
+
'''Title metadata''' (aka '''TMD''') is a format used to store information about a [[title]] and all its installed contents, including which contents they consist of and their SHA1 hashes.
  
=これは日本のニンテンドーfucking !私は神のCEOは、午前くそー!お客様の製品やfucking私fucking私のfuckingの雌ロバが改造停止を訴える!あなたファック=
+
TMDs seem to have been originally intended to all be stored in [[:/title/00000001/00000002/data/tmds.sys]], much like ticket.sys on the iQue Player; on release consoles, most TMDs are still stored there, but the TMD files actually used are stored in separate title.tmd files.
==これは日本のニンテンドーfucking !私は神のCEOは、午前くそー!お客様の製品やfucking私fucking私のfuckingの雌ロバが改造停止を訴える!あなたファック==
 
===これは日本のニンテンドーfucking !私は神のCEOは、午前くそー!お客様の製品やfucking私fucking私のfuckingの雌ロバが改造停止を訴える!あなたファック===
 
これは日本のニンテンドーfucking !私は神のCEOは、午前くそー!お客様の製品やfucking私fucking私のfuckingの雌ロバが改造停止を訴える!あなたファック
 
====これは日本のニンテンドーfucking !私は神のCEOは、午前くそー!お客様の製品やfucking私fucking私のfuckingの雌ロバが改造停止を訴える!あなたファック=====
 
  
これは日本のニンテンドーfucking !私は神のCEOは、午前くそー!お客様の製品やfucking私fucking私のfuckingの雌ロバが改造停止を訴える!あなたファック
+
== Structure ==
 +
=== Signed blob header ===
 +
{| class="wikitable"
 +
|- style="background-color: #ddd;"
 +
! Absolute offset
 +
! Length
 +
! Description
 +
|-
 +
| 0x000
 +
| 4
 +
| Signature type (always 0x10001 for RSA-2048 w/ SHA-1)
 +
|-
 +
| 0x004
 +
| 256
 +
| Signature covering the main header as well as all CMDs
 +
|-
 +
| 0x104
 +
| 60
 +
| Padding for 64-byte alignment
 +
|}
  
[[これは日本のニンテンドーfucking !私は神のCEOは、午前くそー!お客様の製品やfucking私fucking私のfuckingの雌ロバが改造停止を訴える!あなたファック]]
+
=== Main header ===
 +
{| class="wikitable"
 +
|- style="background-color: #ddd;"
 +
! Absolute offset
 +
! Length
 +
! Description
 +
|-
 +
| 0x140
 +
| 64
 +
| Certificate issuer
 +
|-
 +
| 0x180
 +
| 1
 +
| Version
 +
|-
 +
| 0x181
 +
| 1
 +
| ca_crl_version
 +
|-
 +
| 0x182
 +
| 1
 +
| signer_crl_version
 +
|-
 +
| 0x183
 +
| 1
 +
| Is vWii (1 for vWii titles, 0 for normal titles)
 +
|-
 +
| 0x184
 +
| 8
 +
| System Version (the IOS that the title needs, Set to 0 for IOS itself. For the boot2, this is identical to the boot2 version.)
 +
|-
 +
| 0x18C
 +
| 8
 +
| Title ID
 +
|-
 +
| 0x194
 +
| 4
 +
| Title type
 +
|-
 +
| 0x198
 +
| 2
 +
| Group ID
 +
|-
 +
| 0x19A
 +
| 2
 +
| Zero
 +
|-
 +
| 0x19C
 +
| 2
 +
| Region (0: Japan, 1: USA, 2: Europe, 3: Region Free, 4: Korea)
 +
|-
 +
| 0x19E
 +
| 16
 +
| Ratings
 +
|-
 +
| 0x1AE
 +
| 12
 +
| Reserved
 +
|-
 +
| 0x1BA
 +
| 12
 +
| IPC Mask
 +
|-
 +
| 0x1C6
 +
| 18
 +
| 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 (content index for boot file. For [[Broadway]] titles, this is typically the [[NAND Boot Program]]. For [[Starlet]] titles, this is the main binary with the kernel/ES/FS, or the single binary for monolithic IOSes)
 +
|-
 +
| 0x1E2
 +
| 2
 +
| Minor version (unused - the term typically refers to the lower half of the main version instead)
 +
|}
  
[これは日本のニンテンドーfucking !私は神のCEOは、午前くそー!お客様の製品やfucking私fucking私のfuckingの雌ロバが改造停止を訴える!あなたファック]
+
=== Content metadata (CMD) ===
 +
Following the main header (starting at offset 0x1E4) is a list of CMDs (one per content).
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Length
 +
! Description
 +
|-
 +
| 0x00
 +
| 4
 +
| Content ID
 +
|-
 +
| 0x04
 +
| 2
 +
| Index
 +
|-
 +
| 0x06
 +
| 2
 +
| Type (0x0001: Normal, 0x4001: DLC, 0x8001: [[:/shared1|Shared]])
 +
|-
 +
| 0x08
 +
| 8
 +
| Size
 +
|-
 +
| 0x10
 +
| 20
 +
| SHA1 hash
 +
|}
 +
 
 +
=== Certificates ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Length
 +
! Description
 +
|-
 +
| 0x000
 +
| 4
 +
| Signature type
 +
|-
 +
| 0x004
 +
| 256
 +
| Signature
 +
|-
 +
| 0x104
 +
| 64
 +
| Issuer
 +
|-
 +
| 0x124
 +
| 4
 +
| Public Key Type
 +
|-
 +
| 0x128
 +
| 64
 +
| Name
 +
|-
 +
| 0x12C
 +
| 4
 +
| Date
 +
|-
 +
| 0x16C
 +
|
 +
| Public 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; // normal: 0x0001; dlc: 0x4001; shared: 0x8001
 +
  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
 +
};
 +
 
 +
// High 32 bits of the title ID
 +
enum title_type : u32 {
 +
  System = 0x00000001,
 +
  Game = 0x00010000,
 +
  Channel = 0x00010001,
 +
  SystemChannel = 0x00010002,
 +
  GameWithChannel = 0x00010004,
 +
  DLC = 0x00010005,
 +
  HiddenChannel = 0x00010008,
 +
};
 +
 
 +
// title_type (offset 0x194)
 +
enum title_flags {
 +
  // All official titles have this flag set.
 +
  Default = 0x1,
 +
  Unknown_0x4 = 0x4,
 +
  // Used for DLC titles.
 +
  Data = 0x8,
 +
  Unknown_0x10 = 0x10,
 +
  // Seems to be used for WFS titles.
 +
  Maybe_WFS = 0x20,
 +
  Unknown_CT = 0x40,
 +
};
 +
</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 vwii;
 +
        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 fill2;
 +
        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 key_type;  // the type of public key
 +
  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]]

Latest revision as of 21:25, 31 October 2022

Title metadata (aka TMD) is a format used to store information about a title and all its installed contents, including which contents they consist of and their SHA1 hashes.

TMDs seem to have been originally intended to all be stored in /title/00000001/00000002/data/tmds.sys, much like ticket.sys on the iQue Player; on release consoles, most TMDs are still stored there, but the TMD files actually used are stored in separate title.tmd files.

Structure

Signed blob header

Absolute offset Length Description
0x000 4 Signature type (always 0x10001 for RSA-2048 w/ SHA-1)
0x004 256 Signature covering the main header as well as all CMDs
0x104 60 Padding for 64-byte alignment

Main header

Absolute offset Length Description
0x140 64 Certificate issuer
0x180 1 Version
0x181 1 ca_crl_version
0x182 1 signer_crl_version
0x183 1 Is vWii (1 for vWii titles, 0 for normal titles)
0x184 8 System Version (the IOS that the title needs, Set to 0 for IOS itself. For the boot2, this is identical to the boot2 version.)
0x18C 8 Title ID
0x194 4 Title type
0x198 2 Group ID
0x19A 2 Zero
0x19C 2 Region (0: Japan, 1: USA, 2: Europe, 3: Region Free, 4: Korea)
0x19E 16 Ratings
0x1AE 12 Reserved
0x1BA 12 IPC Mask
0x1C6 18 Reserved
0x1D8 4 Access rights (flags for DVD-video access and full PPC hardware access)
0x1DC 2 Title version
0x1DE 2 Number of contents (nbr_cont)
0x1E0 2 boot index (content index for boot file. For Broadway titles, this is typically the NAND Boot Program. For Starlet titles, this is the main binary with the kernel/ES/FS, or the single binary for monolithic IOSes)
0x1E2 2 Minor version (unused - the term typically refers to the lower half of the main version instead)

Content metadata (CMD)

Following the main header (starting at offset 0x1E4) is a list of CMDs (one per content).

Offset Length Description
0x00 4 Content ID
0x04 2 Index
0x06 2 Type (0x0001: Normal, 0x4001: DLC, 0x8001: Shared)
0x08 8 Size
0x10 20 SHA1 hash

Certificates

Offset Length Description
0x000 4 Signature type
0x004 256 Signature
0x104 64 Issuer
0x124 4 Public Key Type
0x128 64 Name
0x12C 4 Date
0x16C Public Key

Example code application

 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;
 typedef struct {
   u32 cid;		// content id
   u16 index;		// # number of the file
   u16  type;		// normal: 0x0001; dlc: 0x4001; shared: 0x8001
   u64 size;
   u8  hash [20]; 		//  SHA1 hash content
 } content_record; 			// size: 0x24 bytes
enum sig_type {
  RSA_2048 = 0x00010001,
  RSA_4096 = 0x00010000
};

// High 32 bits of the title ID
enum title_type : u32 {
  System = 0x00000001,
  Game = 0x00010000,
  Channel = 0x00010001,
  SystemChannel = 0x00010002,
  GameWithChannel = 0x00010004,
  DLC = 0x00010005,
  HiddenChannel = 0x00010008,
};

// title_type (offset 0x194)
enum title_flags {
  // All official titles have this flag set.
  Default = 0x1,
  Unknown_0x4 = 0x4,
  // Used for DLC titles.
  Data = 0x8,
  Unknown_0x10 = 0x10,
  // Seems to be used for WFS titles.
  Maybe_WFS = 0x20,
  Unknown_CT = 0x40,
};
 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 vwii;
        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 fill2;
        content_record contents[num_contents];
 } tmd;

The tmd is then followed by a chain of certificates, where each certificate is of the general form

  u32 sig_type;  //
  u8 sig[256];   // 256 for RSA_2048, 512 for RSA_4096
  u8 issuer[32];
  u32 key_type;  // the type of public key
  u8 name[64]; // name of thing being signed
  u8 key[...];

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] :

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
};