NCCH/Extended Header: Difference between revisions
Nicholatian (talk | contribs) This should be a lot more readable |
|||
Line 1: | Line 1: | ||
This page documents the format of the '''NCCH Extended Header''' | This page documents the format of the '''NCCH Extended Header''', or '''exheader''' for short. | ||
The exheader | The exheader has two sections: | ||
* The actual exheader data, containing System Control Info and Access Control Info | |||
* | * The actual exheader data, containing System Control Info (SCI) and Access Control Info (ACI); | ||
* A signed copy of NCCH HDR public key, and exheader ACI. This version of the ACI is used as limitation to the actual ACI. | |||
== Main Structure == | == Main Structure == | ||
Line 12: | Line 13: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Offset | ||
! | ! Size | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0x0</code> | ||
| | | <code>0x200</code> | ||
| | | SCI | ||
|- | |- | ||
| | | <code>0x200</code> | ||
| | | <code>0x200</code> | ||
| | | ACI | ||
|- | |- | ||
| | | <code>0x400</code> | ||
| | | <code>0x100</code> | ||
| | | <code>AccessDesc</code> signature (RSA-2048-SHA256) | ||
|- | |- | ||
| | | <code>0x500</code> | ||
| | | <code>0x100</code> | ||
| | | NCCH HDR RSA-2048 public key | ||
|- | |- | ||
| | | <code>0x600</code> | ||
| | | <code>0x200</code> | ||
| | | ACI (for limitation of first ACI) | ||
|} | |} | ||
The AccessDesc | The <code>AccessDesc</code> signature covers the NCCH HDR public key and second ACI. The <code>AccessDesc</code> public key is initialised by the boot ROM. | ||
When loading the exheader, [[FIRM|Process9]] compares the exheader data with the data in the | When loading the exheader, [[FIRM|Process9]] compares the exheader data with the data in the <code>AccessDesc</code> (note that not everything is compared here). When these don't match, an error is returned. The Process9 code handling this validation was updated with [[6.0.0-11|v6.0]]; the only change in this function seems to be the check for the "Ideal processor" field. | ||
== System Control Info == | == System Control Info == | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Offset | ||
! | ! Size | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0x0</code> | ||
| | | <code>0x8</code> | ||
| | | Application title | ||
|- | |- | ||
| | | <code>0x8</code> | ||
| | | <code>0x5</code> | ||
| | | Reserved | ||
|- | |- | ||
| | | <code>0xD</code> | ||
| | | <code>0x1</code> | ||
| | | Flag (bit 0: <code>CompressExefsCode</code>, bit 1: <code>SDApplication</code>) | ||
|- | |- | ||
| | | <code>0xE</code> | ||
| | | <code>0x2</code> | ||
| | | Remaster version | ||
|- | |- | ||
| | | <code>0x10</code> | ||
| | | <code>0xC</code> | ||
| | | Text code set info | ||
|- | |- | ||
| | | <code>0x1C</code> | ||
| | | <code>0x4</code> | ||
| | | Stack size | ||
|- | |- | ||
| | | <code>0x20</code> | ||
| | | <code>0xC</code> | ||
| | | Read-only code set info | ||
|- | |- | ||
| | | <code>0x2C</code> | ||
| | | <code>0x4</code> | ||
| | | Reserved | ||
|- | |- | ||
| | | <code>0x30</code> | ||
| | | <code>0xC</code> | ||
| | | Data code set info | ||
|- | |- | ||
| | | <code>0x3C</code> | ||
| | | <code>0x4</code> | ||
| | | BSS size | ||
|- | |- | ||
| | | <code>0x40</code> | ||
| | | <code>0x180</code> (<code>48*8</code>) | ||
| | | Dependency module (program ID) list | ||
|- | |- | ||
| | | <code>0x1C0</code> | ||
| | | <code>0x40</code> | ||
| | | <code>SystemInfo</code> | ||
|} | |} | ||
Line 102: | Line 103: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Offset | ||
! | ! Size | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0x0</code> | ||
| | | <code>4</code> | ||
| | | Address | ||
|- | |- | ||
| | | <code>0x4</code> | ||
| | | <code>4</code> | ||
| | | Physical region size (in page-multiples) | ||
|- | |- | ||
| | | <code>0x8</code> | ||
| | | <code>4</code> | ||
| | | Size (in bytes) | ||
|} | |} | ||
Line 122: | Line 123: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Offset | ||
! | ! Size | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0x0</code> | ||
| | | <code>0x8</code> | ||
| | | <code>SaveData</code> Size | ||
|- | |- | ||
| | | <code>0x8</code> | ||
| | | <code>0x8</code> | ||
| | | Jump ID | ||
|- | |- | ||
| | | <code>0x10</code> | ||
| | | <code>0x30</code> | ||
| | | Reserved | ||
|} | |} | ||
Line 142: | Line 143: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Offset | ||
! | ! Size | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0x0</code> | ||
| | | <code>0x170</code> | ||
| | | [[#ARM11 Local System Capabilities|ARM11 local system capabilities]] | ||
|- | |- | ||
| | | <code>0x170</code> | ||
| | | <code>0x80</code> | ||
| | | [[#ARM11 Kernel Capabilities|ARM11 kernel capabilities]] | ||
|- | |- | ||
| | | <code>0x1F0</code> | ||
| | | <code>0x10</code> | ||
| | | [[#ARM9 Access Control|ARM9 access control]] | ||
|} | |} | ||
Line 162: | Line 163: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Offset | ||
! | ! Size | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0x0</code> | ||
| | | <code>0x8</code> | ||
| | | Program ID | ||
|- | |- | ||
| | | <code>0x8</code> | ||
| | | <code>0x4</code> | ||
| | | Core version (The Title ID low of the required [[FIRM]]) | ||
|- | |- | ||
| | | <code>0xC</code> | ||
| | | <code>0x2</code> | ||
| | | [[#Flag1|Flag1]] and [[#Flag2|Flag2]] (both implemented starting from [[8.0.0-18]]). | ||
|- | |- | ||
| | | <code>0xE</code> | ||
| | | <code>0x1</code> | ||
| | | [[#Flag0|Flag0]] | ||
|- | |- | ||
| | | <code>0xF</code> | ||
| | | <code>0x1</code> | ||
| | | Priority | ||
|- | |- | ||
| | | <code>0x10</code> | ||
| | | <code>0x20</code> (<code>16*2</code>) | ||
| | | Resource limit descriptors. The first byte here controls the maximum allowed [[PMApp:SetAppResourceLimit|<code>CpuTime</code>]]. | ||
|- | |- | ||
| | | <code>0x30</code> | ||
| | | <code>0x20</code> | ||
| | | [[#Storage Info|Storage info]] | ||
|- | |- | ||
| | | <code>0x50</code> | ||
| | | <code>0x100</code> (<code>32*8</code>) | ||
| | | [[#Service Access Control|Service access control]] | ||
|- | |- | ||
| | | <code>0x150</code> | ||
| | | <code>0x10</code> (<code>2*8</code>) | ||
| | | Extended service access control, support for this was implemented with [[9.3.0-21|9.3.0-X]]. | ||
|- | |- | ||
| | | <code>0x160</code> | ||
| | | <code>0xF</code> | ||
| | | Reserved | ||
|- | |- | ||
| | | <code>0x16F</code> | ||
| | | <code>0x1</code> | ||
| | | Resource limit category. (0 = <code>APPLICATION</code>, 1 = <code>SYS_APPLET</code>, 2 = <code>LIB_APPLET</code>, 3 = <code>OTHER</code> (sysmodules running under the BASE memregion)) | ||
|} | |} | ||
Line 214: | Line 215: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Bits | ||
! | ! Description | ||
|- | |- | ||
| 0-1 | | <code>0-1</code> | ||
| Ideal | | Ideal processor | ||
|- | |- | ||
| 2-3 | | <code>2-3</code> | ||
| Affinity | | Affinity mask | ||
|- | |- | ||
| 4-7 | | <code>4-7</code> | ||
| System | | System mode | ||
|} | |} | ||
In the exheader data, the | In the exheader data, the ideal processor field is a bit-index, while in the <code>AccessDesc</code> the ideal processor field is a bitmask. When the bit specified by the exheader field is not set in the <code>AccessDesc</code> field, an error is returned. | ||
<pre>if((1 << exheaderval) & accessdescval == 0) return error</pre> | |||
During a FIRM-launch when a | During a FIRM-launch when a <code>TitleInfo</code> structure was specified, the field at offset [[FIRM#FIRM_Launch_Parameters|0x400]] in the FIRM-launch parameters is set to the SystemMode of the specified title, however in some cases other values are written there. With [[8.0.0-18]] NS will now check the output of [[PTM|PTMSYSM]] command <code>0x040A0000</code>, when the output is non-zero and a certain NS state field is value-zero, the following is executed otherwise this is skipped. With that check passed on [[8.0.0-18]], NS will then check (<code>Flag2 & 0xF</code>). When that is <code>value2</code>, the output value (used for the FIRM-launcher parameter field mentioned above) is set to <code>value7</code>. Otherwise, when that value is non-zero, the output value is set to 6. | ||
==== Flag1 ==== | ==== Flag1 ==== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Bits | ||
! | ! Description | ||
|- | |- | ||
| 0 | | <code>0</code> | ||
| | | <code>EnableL2Cache</code> (Unknown what this actually does, New3DS-only presumably) | ||
|- | |- | ||
| 1 | | <code>1</code> | ||
| | | <code>cpuspeed_804MHz</code> (Default "cpuspeed" when not set) | ||
|- | |- | ||
| 2-7 | | <code>2-7</code> | ||
| Unused | | Unused | ||
|} | |} | ||
In order for the exheader to have any of the above new bits set, the | In order for the exheader to have any of the above new bits set, the <code>AccessDesc</code> must have the corresponding bit set, otherwise the invalid-exheader error is returned. | ||
Homebrew which runs under a title which has the above cpuspeed flag set, runs much faster on New3DS. It's unknown how exactly the system handles these flags. | Homebrew which runs under a title which has the above <code>cpuspeed</code> flag set, runs much faster on New3DS. It's unknown how exactly the system handles these flags. | ||
When launching titles / perhaps other things with APT, [[NS]] uses [[PTMSYSM:ConfigureNew3DSCPU]] with data which originally came from these flags | When launching titles / perhaps other things with [[APT]], [[NS]] uses [[PTMSYSM:ConfigureNew3DSCPU]] with data which originally came from these flags; NS does this regardless of what the running 3DS system is. However, due to a bug(?) in NS the value sent to that command is always either 0x0 or 0x3. When calculating that value, the code only ever uses the cpuspeed field, not the cache field: code to actually load and check the value of the cache field appears to be missing. | ||
==== Flag2 ==== | ==== Flag2 ==== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Bit | ||
! | ! Description | ||
|- | |- | ||
| 0-3 | | <code>0-3</code> | ||
| | | ''Unknown'' | ||
|- | |- | ||
| 4-7 | | <code>4-7</code> | ||
| Unused | | Unused | ||
|} | |} | ||
The exheader value for the above 4-bit value must be | The exheader value for the above 4-bit value must be ≤ to the <code>AccessDesc</code> value, otherwise the invalid-exheader error is returned. | ||
==== Storage Info ==== | ==== Storage Info ==== | ||
Line 273: | Line 276: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Offset | ||
! | ! Size | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0x0</code> | ||
| | | <code>8</code> | ||
| | | Extdata ID | ||
|- | |- | ||
| | | <code>0x8</code> | ||
| | | <code>8</code> | ||
| | | System savedata IDs | ||
|- | |- | ||
| | | <code>0x10</code> | ||
| | | <code>8</code> | ||
| | | Storage accessible unique IDs | ||
|- | |- | ||
| | | <code>0x18</code> | ||
| | | <code>7</code> | ||
| | | Filesystem access info | ||
|- | |- | ||
| | | <code>0x1F</code> | ||
| | | <code>1</code> | ||
| | | Other attributes | ||
|} | |} | ||
Line 301: | Line 304: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Bit and bitmask | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0</code>, <code>0x1</code> | ||
| | | Category system application | ||
|- | |- | ||
| | | <code>1</code>, <code>0x2</code> | ||
| | | Category hardware check | ||
|- | |- | ||
| | | <code>2</code>, <code>0x4</code> | ||
| | | Category filesystem tool | ||
|- | |- | ||
| | | <code>3</code>, <code>0x8</code> | ||
| | | Debug | ||
|- | |- | ||
| | | <code>4</code>, <code>0x10</code> | ||
| | | TWL card backup | ||
|- | |- | ||
| | | <code>5</code>, <code>0x20</code> | ||
| | | TWL NAND data | ||
|- | |- | ||
| | | <code>6</code>, <code>0x40</code> | ||
| | | BOSS | ||
|- | |- | ||
| | | <code>7</code>, <code>0x80</code> | ||
| | | [[FS:OpenArchive|<code>sdmc:/</code>]] | ||
|- | |- | ||
| | | <code>8</code>, <code>0x100</code> | ||
| | | Core | ||
|- | |- | ||
| | | <code>9</code>, <code>0x200</code> | ||
| | | [[Flash Filesystem|<code>nand:/ro/</code>]] (Read Only) | ||
|- | |- | ||
| | | <code>10</code>, <code>0x400</code> | ||
| | | [[Flash Filesystem|<code>nand:/rw/</code>]] | ||
|- | |- | ||
| | | <code>11</code>, <code>0x800</code> | ||
| | | [[Flash Filesystem|<code>nand:/ro/</code>]] (Write Access) | ||
|- | |- | ||
| | | <code>12</code>, <code>0x1000</code> | ||
| | | Category system settings | ||
|- | |- | ||
| | | <code>13</code>, <code>0x2000</code> | ||
| | | Cardboard | ||
|- | |- | ||
| | | <code>14</code>, <code>0x4000</code> | ||
| | | Export/Import IVS | ||
|- | |- | ||
| | | <code>15</code>, <code>0x8000</code> | ||
| | | [[FS:OpenArchive|<code>sdmc:/</code>]] (Write-only) | ||
|- | |- | ||
| | | <code>16</code>, <code>0x10000</code> | ||
| | | Switch cleanup (Introduced in [[3.0.0-5|3.0.0]]?) | ||
|- | |- | ||
| | | <code>17</code>, <code>0x20000</code> | ||
| | | Savedata move (Introduced in [[5.0.0-11|5.0.0]]) | ||
|- | |- | ||
| | | <code>18</code>, <code>0x40000</code> | ||
| | | Shop (Introduced in [[5.0.0-11|5.0.0]]) | ||
|- | |- | ||
| | | <code>19</code>, <code>0x80000</code> | ||
| | | Shell (Introduced in [[5.0.0-11|5.0.0]]) | ||
|- | |- | ||
| | | <code>20</code>, <code>0x100000</code> | ||
| | | Category home menu (Introduced in [[6.0.0-11|6.0.0]]) | ||
|- | |- | ||
| | | <code>21</code>, <code>0x200000</code> | ||
| | | Seed DB. Introduced in [[9.6.0-24|9.6.0-X]] [[FIRM]]. [[Home Menu]] has this bit set starting with [[9.6.0-24|9.6.0-X]]. | ||
|} | |} | ||
Other Attributes | ====Other Attributes==== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Bit | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0</code> | ||
| | | Not use ROMFS | ||
|- | |- | ||
| | | <code>1</code> | ||
| | | Use Extended savedata access. | ||
|} | |} | ||
When this is set, the "Extdata ID" and "Storage Accessable Unique IDs" regions are used to store a total of 6 "Accessible Save IDs". Introduced in [[6.0.0-11|6.0.0]]. | |||
==== Service Access Control ==== | ==== Service Access Control ==== | ||
This is the list of [[Services_API|services]] which the process is allowed to access, this is registered with the [[Services|services]] manager. Each service listed in the exheader must be listed in the | This is the list of [[Services_API|services]] which the process is allowed to access, this is registered with the [[Services|services]] manager. Each service listed in the exheader must be listed in the <code>AccessDesc</code>, otherwise the invalid exheader error is returned. The order of the services for exheader/<code>AccessDesc</code> doesn't matter. The <code>AccessDesc</code> can list services which are not in the exheader, but normally the service-access-control data for exheader/<code>AccessDesc</code> are exactly the same. | ||
This list is submitted to [[SRVPM:RegisterProcess]]. | This list is submitted to [[SRVPM:RegisterProcess]]. | ||
Line 394: | Line 400: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Offset | ||
! | ! Size | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0x0</code> | ||
| | | <code>0x70</code> (<code>28*4</code>) | ||
| | | Descriptors | ||
|- | |- | ||
| | | <code>0x70</code> | ||
| | | <code>0x10</code> | ||
| | | Reserved | ||
|} | |} | ||
There are different descriptor types, determined by the number of leading | There are different descriptor types, determined by the number of leading ones in the binary value representation of bits 20-31. The different types are laid out as follows: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Pattern of bits 20-31 | ||
! | ! Type | ||
! | ! Fields | ||
|- | |- | ||
| | | <code>0b1110xxxxxxxx</code> | ||
| | | Interrupt info | ||
| | | | ||
|- | |- | ||
| | | <code>0b11110xxxxxxx</code> | ||
| | | System call mask | ||
| | | Bits 24-26: System call mask table index; Bits 0-23: mask | ||
|- | |- | ||
| | | <code>0b1111110xxxxx</code> | ||
| | | Kernel release version | ||
| | | Bits 8-15: Major version; Bits 0-7: Minor version | ||
|- | |- | ||
| | | <code>0b11111110xxxx</code> | ||
| | | Handle table size | ||
| | | Bits 0-18: size | ||
|- | |- | ||
| | | <code>0b111111110xxx</code> | ||
| | | [[#ARM11_Kernel_Flags|Kernel flags]] | ||
| | | See below | ||
|- | |- | ||
| | | <code>0b11111111100x</code> | ||
| | | Mapping static address | ||
| | | | ||
|- | |- | ||
| | | <code>0b111111111110</code> | ||
| | | Mapping IO address | ||
| | | Bits 0-19: IO page index to map; Bit 20: Map read-only (otherwise read-write) | ||
|} | |} | ||
Line 447: | Line 453: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Bit | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0</code> | ||
| | | Allow debug | ||
|- | |- | ||
| | | <code>1</code> | ||
| | | Force debug | ||
|- | |- | ||
| | | <code>2</code> | ||
| | | Allow non-alphanum | ||
|- | |- | ||
| | | <code>3</code> | ||
| | | Shared page writing | ||
|- | |- | ||
| | | <code>4</code> | ||
| | | Privilege priority | ||
|- | |- | ||
| | | <code>5</code> | ||
| | | Allow <code>main()</code> args | ||
|- | |- | ||
| | | <code>6</code> | ||
| | | Shared device memory | ||
|- | |- | ||
| | | <code>7</code> | ||
| | | Runnable on sleep | ||
|- | |- | ||
| | | <code>8-11</code> | ||
| | | Memory type (1: application, 2: system, 3: base) | ||
|- | |- | ||
| | | <code>12</code> | ||
| | | [[Memory_layout#NATIVE_FIRM.2FSAFE_MODE_FIRM_Userland_Memory|Special memory]] | ||
|- | |- | ||
| | | <code>13</code> | ||
| | | Process has access to CPU core 2 (New3DS only) | ||
|} | |} | ||
Line 487: | Line 493: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Offset | ||
! | ! Size | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0x0</code> | ||
| | | <code>15</code> | ||
| | | Descriptors | ||
|- | |- | ||
| | | <code>0xF</code> | ||
| | | <code>1</code> | ||
| | | ARM9 Descriptor Version. Originally this value had to be ≥ 2. Starting with [[9.3.0-21|9.3.0-X]] this value has to be either value 2 or value 3. | ||
|} | |} | ||
Line 503: | Line 509: | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! Bit | ||
! | ! Description | ||
|- | |- | ||
| | | <code>0</code> | ||
| | | Mount [[Flash Filesystem|<code>nand:/</code>]] | ||
|- | |- | ||
| | | <code>1</code> | ||
| | | Mount [[Flash Filesystem|<code>nand:/ro/</code>]] (Write Access) | ||
|- | |- | ||
| | | <code>2</code> | ||
| | | Mount [[Flash Filesystem|<code>twln:/</code>]] | ||
|- | |- | ||
| | | <code>3</code> | ||
| | | Mount [[Flash Filesystem|<code>wnand:/</code>]] | ||
|- | |- | ||
| | | <code>4</code> | ||
| | | Mount card SPI | ||
|- | |- | ||
| | | <code>5</code> | ||
| | | Use SDIF3 | ||
|- | |- | ||
| | | <code>6</code> | ||
| | | Create seed | ||
|- | |- | ||
| | | <code>7</code> | ||
| | | Use card SPI | ||
|- | |- | ||
| | | <code>8</code> | ||
| | | SD application (Not checked) | ||
|- | |- | ||
| | | <code>9</code> | ||
| | | Mount [[SD Filesystem|sdmc:/]] (Write Access) | ||
|} | |} |