Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f065e3bac | ||
|
|
9296a56303 | ||
|
|
481b209ae8 | ||
|
|
17ca463c3f | ||
|
|
f175802136 | ||
|
|
fe79bc253a | ||
|
|
81bf8c577a | ||
|
|
aee89db748 | ||
|
|
f5704d25f8 | ||
|
|
73afa042f1 | ||
|
|
2da31b122f | ||
|
|
43bbfd29bb | ||
|
|
4cb4707f34 | ||
|
|
389c3b6baa | ||
|
|
0c596e682f | ||
|
|
4d430a4c61 | ||
|
|
0c41489f01 | ||
|
|
bd6155bcb4 | ||
|
|
3bedf56512 | ||
|
|
1be74ea6e2 | ||
|
|
14d458522d | ||
|
|
12bf9612cb | ||
|
|
ea7b6e14f9 | ||
|
|
5e3339e866 | ||
|
|
a7c14e03b9 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -79,9 +79,8 @@ dkms.conf
|
||||
*.nam
|
||||
*.til
|
||||
|
||||
# KEYS file for sept-secondary.
|
||||
# Compiled python files.
|
||||
*.pyc
|
||||
sept/sept-secondary/KEYS.py
|
||||
|
||||
.**/
|
||||
|
||||
|
||||
17
Makefile
17
Makefile
@@ -32,10 +32,7 @@ mesosphere: exosphere libraries
|
||||
troposphere: stratosphere
|
||||
$(MAKE) -C troposphere all
|
||||
|
||||
sept: exosphere
|
||||
$(MAKE) -C sept all
|
||||
|
||||
fusee: exosphere mesosphere stratosphere sept
|
||||
fusee: exosphere mesosphere stratosphere
|
||||
$(MAKE) -C $@ all
|
||||
|
||||
libraries:
|
||||
@@ -61,7 +58,6 @@ dist-no-debug: all
|
||||
rm -rf out
|
||||
mkdir atmosphere-$(AMSVER)
|
||||
mkdir atmosphere-$(AMSVER)/atmosphere
|
||||
mkdir atmosphere-$(AMSVER)/sept
|
||||
mkdir atmosphere-$(AMSVER)/switch
|
||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/fatal_errors
|
||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/config_templates
|
||||
@@ -71,13 +67,6 @@ dist-no-debug: all
|
||||
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
|
||||
cp fusee/fusee-mtc/fusee-mtc.bin atmosphere-$(AMSVER)/atmosphere/fusee-mtc.bin
|
||||
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
||||
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/sept/payload.bin
|
||||
cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.bin
|
||||
cp sept/sept-secondary/sept-secondary.bin atmosphere-$(AMSVER)/sept/sept-secondary.bin
|
||||
cp sept/sept-secondary/sept-secondary_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_00.enc
|
||||
cp sept/sept-secondary/sept-secondary_01.enc atmosphere-$(AMSVER)/sept/sept-secondary_01.enc
|
||||
cp sept/sept-secondary/sept-secondary_dev_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_dev_00.enc
|
||||
cp sept/sept-secondary/sept-secondary_dev_01.enc atmosphere-$(AMSVER)/sept/sept-secondary_dev_01.enc
|
||||
cp config_templates/BCT.ini atmosphere-$(AMSVER)/atmosphere/config_templates/BCT.ini
|
||||
cp config_templates/override_config.ini atmosphere-$(AMSVER)/atmosphere/config_templates/override_config.ini
|
||||
cp config_templates/system_settings.ini atmosphere-$(AMSVER)/atmosphere/config_templates/system_settings.ini
|
||||
@@ -109,7 +98,6 @@ dist-no-debug: all
|
||||
cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro
|
||||
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../;
|
||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
|
||||
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER)-WITHOUT_MESOSPHERE.zip ./*; cd ../;
|
||||
rm -r atmosphere-$(AMSVER)
|
||||
mkdir out
|
||||
@@ -133,9 +121,6 @@ dist: dist-no-debug
|
||||
cp fusee/fusee-primary/fusee-primary.elf atmosphere-$(AMSVER)-debug/fusee-primary.elf
|
||||
cp fusee/fusee-mtc/fusee-mtc.elf atmosphere-$(AMSVER)-debug/fusee-mtc.elf
|
||||
cp fusee/fusee-secondary/fusee-secondary-experimental.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
|
||||
cp sept/sept-primary/sept-primary.elf atmosphere-$(AMSVER)-debug/sept-primary.elf
|
||||
cp sept/sept-secondary/sept-secondary.elf atmosphere-$(AMSVER)-debug/sept-secondary.elf
|
||||
cp sept/sept-secondary/key_derivation/key_derivation.elf atmosphere-$(AMSVER)-debug/sept-secondary-key-derivation.elf
|
||||
cp exosphere/loader_stub/loader_stub.elf atmosphere-$(AMSVER)-debug/exosphere-loader-stub.elf
|
||||
cp exosphere/program/program.elf atmosphere-$(AMSVER)-debug/exosphere-program.elf
|
||||
cp exosphere/warmboot/warmboot.elf atmosphere-$(AMSVER)-debug/exosphere-warmboot.elf
|
||||
|
||||
@@ -9,7 +9,7 @@ Building Atmosphère is a very straightforward process that relies almost exclus
|
||||
+ [PyCryptodome](https://pypi.org/project/pycryptodome) (optional)
|
||||
|
||||
## Instructions
|
||||
1. Follow the guide located [here](https://devkitpro.org/wiki/Getting_Started) to install and configure all the tools necessary for the build process.
|
||||
1. Follow the guide located [here](https://devkitpro.org/wiki/Getting_Started) to install and configure all the tools necessary for the build process.
|
||||
|
||||
2. Install the following packages via (dkp-)pacman:
|
||||
+ `switch-dev`
|
||||
@@ -21,12 +21,4 @@ Building Atmosphère is a very straightforward process that relies almost exclus
|
||||
3. Install the following library via python's package manager `pip`, required by [exosphere](components/exosphere.md):
|
||||
+ `lz4`
|
||||
|
||||
4. (Optional) In order to build [sept](components/sept.md) the pycryptodome PyPi package is required, which can be installed by running `pip install pycryptodome` under the installed Python environment of your choice or by installing the complete zip package to support the `make dist` recipe. This is an optional step included for advanced users who have the ability to provide the necessary encryption/signing keys themselves.
|
||||
|
||||
5. It is, instead, possible to build [sept](components/sept.md) by providing previously encrypted/signed binaries distributed by official Atmosphère release packages. In order to do so, export the following variables in your current environment:
|
||||
+ `SEPT_00_ENC_PATH` (must point to the `sept-secondary_00.enc` file)
|
||||
+ `SEPT_01_ENC_PATH` (must point to the `sept-secondary_01.enc` file)
|
||||
+ `SEPT_DEV_00_ENC_PATH` (must point to the `sept-secondary_dev_00.enc` file)
|
||||
+ `SEPT_DEV_01_ENC_PATH` (must point to the `sept-secondary_dev_01.enc` file)
|
||||
|
||||
6. Finally, clone the Atmosphère repository and run `make` under its root directory.
|
||||
4. Finally, clone the Atmosphère repository and run `make` under its root directory.
|
||||
|
||||
@@ -1,4 +1,31 @@
|
||||
# Changelog
|
||||
## 0.20.0
|
||||
+ DRAM training (MTC) was implemented for Mariko hardware, increasing RAM speed from 204MHz to 1600MHz.
|
||||
+ This significantly optimizes Mariko boot speed, cutting boot time roughly in half.
|
||||
+ Typical boot time reductions (measured as "select fusee" to "home menu visible"):
|
||||
+ Normal (Iowa): ~35 seconds -> ~18 seconds.
|
||||
+ Lite (Hoag): ~65 seconds -> ~30 seconds.
|
||||
+ NOTE: Work is being started on a re-written `fusee` component, with an eye specifically towards ensuring a good boot speed.
|
||||
+ With any luck, boot will be much much faster on all units (Mariko and Erista) in an upcoming release.
|
||||
+ Sept was replaced, and deleted from the repository.
|
||||
+ Erista units now use a custom TSEC firmware to manage key derivation.
|
||||
+ For more details, contact SciresM#0524 on discord.
|
||||
+ This has a number of benefits, including:
|
||||
+ This greatly simplifies key derivation logic by making it consistent on all firmwares.
|
||||
+ Fusee no longer accesses/uses keyblobs at all, so units which have accidentally destroyed/lost keyblobs can boot without them.
|
||||
+ This greatly increases stability (sept was the biggest source of boot failures).
|
||||
+ This improves boot speed (sept rebooted multiple times, performed hardware init multiple times, and was generally very slow).
|
||||
+ Atmosphère build process is now much saner.
|
||||
+ A number of improvements were made to the dmnt cheat engine.
|
||||
+ Cheats which take in a memory region operand may now use types "2" or "3" to perform accesses relative to the alias/aslr regions, respectively.
|
||||
+ Support was added for an "else" opcode in the cheat engine, to make writing certain conditional logic more natural.
|
||||
+ Support was added for a cheat orchestrator homebrew (like edizon) to detach from a cheat process/set the master cheat programmatically.
|
||||
+ Daybreak now provides a warning when attempting to install a firmware newer than the highest version atmosphère knows it supports.
|
||||
+ To facilitate this, exosphere now exposes the supported HOS version via an extension ConfigItem.
|
||||
+ A number of minor issues were fixed, including:
|
||||
+ Several mesosphere debug SVC implementations were updated to reflect the semantics of the latest kernel.
|
||||
+ Support was fixed for deriving BIS encryption keys on certain prototype hardware.
|
||||
+ General system stability improvements to enhance the user's experience.
|
||||
## 0.19.5
|
||||
+ Support was added for 12.1.0.
|
||||
+ LayeredFS support was added for OpenDataStorageWithProgramIndex commands.
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# sept
|
||||
Sept is a payload that facilitates booting Atmosphère when targeting firmware version 7.0.0+.
|
||||
|
||||
It consists of a primary and a secondary payload.
|
||||
|
||||
## sept-primary
|
||||
sept-primary is essentially a stand-in for Nintendo's package1ldr, on 7.0.0+. To use it, the caller (normally fusée-secondary) loads the sept-primary binary to `0x4003F000`, loads the 7.0.0+ TSEC firmware to `0x40010F00`, and loads a signed, encrypted payload to `0x40016FE0`.
|
||||
|
||||
This signed, encrypted payload is normally sept-secondary.
|
||||
|
||||
## sept-secondary
|
||||
sept-secondary is a payload that performs 7.0.0+ key derivation, and then chainloads to `sept/payload.bin`.
|
||||
|
||||
It is normally stored encrypted/signed. Therefore, if one wishes to build sept-secondary instead of using release builds, one must bring their own keys.
|
||||
@@ -19,6 +19,8 @@ This behavior ensures that cheat codes are only loaded when the user would want
|
||||
|
||||
In cases where `dmnt` has not activated the cheat manager, but the user wants to make it do so anyway, the cheat manager's service API provides a `ForceOpenCheatProcess` command that homebrew can use. This command will cause the cheat manager to try to force itself to attach to the process.
|
||||
|
||||
In cases where `dmnt` has activated the cheat manager, but the user wants to use an alternate debugger, the cheat manager's service API provides a `ForceCloseCheatProcess` command that homebrew can use. This command will cause the cheat manager to detach itself from the process.
|
||||
|
||||
By default, all cheat codes listed in the loaded .txt file will be toggled on. This is configurable by the user by editing the `atmosphere!dmnt_cheats_enabled_by_default` [system setting](configurations.md).
|
||||
|
||||
Users may use homebrew programs to toggle cheats on and off at runtime via the cheat manager's service API.
|
||||
@@ -40,30 +42,30 @@ The following provides documentation of the instruction format for the virtual m
|
||||
|
||||
Typically, instruction type is encoded in the upper nybble of the first instruction u32.
|
||||
|
||||
### Code Type 0: Store Static Value to Memory
|
||||
Code type 0 allows writing a static value to a memory address.
|
||||
### Code Type 0x0: Store Static Value to Memory
|
||||
Code type 0x0 allows writing a static value to a memory address.
|
||||
|
||||
#### Encoding
|
||||
`0TMR00AA AAAAAAAA VVVVVVVV (VVVVVVVV)`
|
||||
|
||||
+ T: Width of memory write (1, 2, 4, or 8 bytes).
|
||||
+ M: Memory region to write to (0 = Main NSO, 1 = Heap).
|
||||
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr).
|
||||
+ R: Register to use as an offset from memory region base.
|
||||
+ A: Immediate offset to use from memory region base.
|
||||
+ V: Value to write.
|
||||
|
||||
---
|
||||
|
||||
### Code Type 1: Begin Conditional Block
|
||||
Code type 1 performs a comparison of the contents of memory to a static value.
|
||||
### Code Type 0x1: Begin Conditional Block
|
||||
Code type 0x1 performs a comparison of the contents of memory to a static value.
|
||||
|
||||
If the condition is not met, all instructions until the appropriate conditional block terminator are skipped.
|
||||
If the condition is not met, all instructions until the appropriate End or Else conditional block terminator are skipped.
|
||||
|
||||
#### Encoding
|
||||
`1TMC00AA AAAAAAAA VVVVVVVV (VVVVVVVV)`
|
||||
|
||||
+ T: Width of memory write (1, 2, 4, or 8 bytes).
|
||||
+ M: Memory region to write to (0 = Main NSO, 1 = Heap).
|
||||
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr).
|
||||
+ C: Condition to use, see below.
|
||||
+ A: Immediate offset to use from memory region base.
|
||||
+ V: Value to compare to.
|
||||
@@ -78,16 +80,20 @@ If the condition is not met, all instructions until the appropriate conditional
|
||||
|
||||
---
|
||||
|
||||
### Code Type 2: End Conditional Block
|
||||
Code type 2 marks the end of a conditional block (started by Code Type 1 or Code Type 8).
|
||||
### Code Type 0x2: End Conditional Block
|
||||
Code type 0x2 marks the end of a conditional block (started by Code Type 0x1 or Code Type 0x8).
|
||||
|
||||
When an Else is executed, all instructions until the appropriate End conditional block terminator are skipped.
|
||||
|
||||
#### Encoding
|
||||
`20000000`
|
||||
`2X000000`
|
||||
|
||||
+ X: End type (0 = End, 1 = Else).
|
||||
|
||||
---
|
||||
|
||||
### Code Type 3: Start/End Loop
|
||||
Code type 3 allows for iterating in a loop a fixed number of times.
|
||||
### Code Type 0x3: Start/End Loop
|
||||
Code type 0x3 allows for iterating in a loop a fixed number of times.
|
||||
|
||||
#### Start Loop Encoding
|
||||
`300R0000 VVVVVVVV`
|
||||
@@ -102,8 +108,8 @@ Code type 3 allows for iterating in a loop a fixed number of times.
|
||||
|
||||
---
|
||||
|
||||
### Code Type 4: Load Register with Static Value
|
||||
Code type 4 allows setting a register to a constant value.
|
||||
### Code Type 0x4: Load Register with Static Value
|
||||
Code type 0x4 allows setting a register to a constant value.
|
||||
|
||||
#### Encoding
|
||||
`400R0000 VVVVVVVV VVVVVVVV`
|
||||
@@ -113,29 +119,28 @@ Code type 4 allows setting a register to a constant value.
|
||||
|
||||
---
|
||||
|
||||
### Code Type 5: Load Register with Memory Value
|
||||
Code type 5 allows loading a value from memory into a register, either using a fixed address or by dereferencing the destination register.
|
||||
### Code Type 0x5: Load Register with Memory Value
|
||||
Code type 0x5 allows loading a value from memory into a register, either using a fixed address or by dereferencing the destination register.
|
||||
|
||||
#### Load From Fixed Address Encoding
|
||||
`5TMR00AA AAAAAAAA`
|
||||
|
||||
+ T: Width of memory read (1, 2, 4, or 8 bytes).
|
||||
+ M: Memory region to write to (0 = Main NSO, 1 = Heap).
|
||||
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr).
|
||||
+ R: Register to load value into.
|
||||
+ A: Immediate offset to use from memory region base.
|
||||
|
||||
#### Load from Register Address Encoding
|
||||
`5TMR10AA AAAAAAAA`
|
||||
`5T0R10AA AAAAAAAA`
|
||||
|
||||
+ T: Width of memory read (1, 2, 4, or 8 bytes).
|
||||
+ M: Memory region to write to (0 = Main NSO, 1 = Heap).
|
||||
+ R: Register to load value into.
|
||||
+ R: Register to load value into. (This register is also used as the base memory address).
|
||||
+ A: Immediate offset to use from register R.
|
||||
|
||||
---
|
||||
|
||||
### Code Type 6: Store Static Value to Register Memory Address
|
||||
Code type 6 allows writing a fixed value to a memory address specified by a register.
|
||||
### Code Type 0x6: Store Static Value to Register Memory Address
|
||||
Code type 0x6 allows writing a fixed value to a memory address specified by a register.
|
||||
|
||||
#### Encoding
|
||||
`6T0RIor0 VVVVVVVV VVVVVVVV`
|
||||
@@ -149,10 +154,10 @@ Code type 6 allows writing a fixed value to a memory address specified by a regi
|
||||
|
||||
---
|
||||
|
||||
### Code Type 7: Legacy Arithmetic
|
||||
Code type 7 allows performing arithmetic on registers.
|
||||
### Code Type 0x7: Legacy Arithmetic
|
||||
Code type 0x7 allows performing arithmetic on registers.
|
||||
|
||||
However, it has been deprecated by Code type 9, and is only kept for backwards compatibility.
|
||||
However, it has been deprecated by Code type 0x9, and is only kept for backwards compatibility.
|
||||
|
||||
#### Encoding
|
||||
`7T0RC000 VVVVVVVV`
|
||||
@@ -171,8 +176,8 @@ However, it has been deprecated by Code type 9, and is only kept for backwards c
|
||||
|
||||
---
|
||||
|
||||
### Code Type 8: Begin Keypress Conditional Block
|
||||
Code type 8 enters or skips a conditional block based on whether a key combination is pressed.
|
||||
### Code Type 0x8: Begin Keypress Conditional Block
|
||||
Code type 0x8 enters or skips a conditional block based on whether a key combination is pressed.
|
||||
|
||||
#### Encoding
|
||||
`8kkkkkkk`
|
||||
@@ -213,8 +218,8 @@ Note: This is the direct output of `hidKeysDown()`.
|
||||
|
||||
---
|
||||
|
||||
### Code Type 9: Perform Arithmetic
|
||||
Code type 9 allows performing arithmetic on registers.
|
||||
### Code Type 0x9: Perform Arithmetic
|
||||
Code type 0x9 allows performing arithmetic on registers.
|
||||
|
||||
#### Register Arithmetic Encoding
|
||||
`9TCRS0s0`
|
||||
@@ -248,8 +253,8 @@ Code type 9 allows performing arithmetic on registers.
|
||||
|
||||
---
|
||||
|
||||
### Code Type 10: Store Register to Memory Address
|
||||
Code type 10 allows writing a register to memory.
|
||||
### Code Type 0xA: Store Register to Memory Address
|
||||
Code type 0xA allows writing a register to memory.
|
||||
|
||||
#### Encoding
|
||||
`ATSRIOxa (aaaaaaaa)`
|
||||
@@ -272,13 +277,13 @@ Code type 10 allows writing a register to memory.
|
||||
|
||||
---
|
||||
|
||||
### Code Type 11: Reserved
|
||||
Code Type 11 is currently reserved for future use.
|
||||
### Code Type 0xB: Reserved
|
||||
Code Type 0xB is currently reserved for future use.
|
||||
|
||||
---
|
||||
|
||||
### Code Type 12-15: Extended-Width Instruction
|
||||
Code Types 12-15 signal to the VM to treat the upper two nybbles of the first dword as instruction type, instead of just the upper nybble.
|
||||
### Code Type 0xC-0xF: Extended-Width Instruction
|
||||
Code Types 0xC-0xF signal to the VM to treat the upper two nybbles of the first dword as instruction type, instead of just the upper nybble.
|
||||
|
||||
This reserves an additional 64 opcodes for future use.
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ Atmosphère provides six core components, mimicking to some degree the various l
|
||||
|
||||
Additionally, Atmosphère also provides the following secondary components:
|
||||
+ [emummc](components/emummc.md)
|
||||
+ [sept](components/sept.md)
|
||||
+ [libraries](components/libraries.md)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
|
||||
namespace ams::secmon::loader {
|
||||
|
||||
NORETURN void UncompressAndExecute() {
|
||||
NORETURN void UncompressAndExecute(const void *program, const void *boot_code) {
|
||||
/* Uncompress the program image. */
|
||||
Uncompress(secmon::MemoryRegionPhysicalTzramFullProgramImage.GetPointer(), secmon::MemoryRegionPhysicalTzramFullProgramImage.GetSize(), program_lz4, program_lz4_size);
|
||||
Uncompress(secmon::MemoryRegionPhysicalTzramFullProgramImage.GetPointer(), secmon::MemoryRegionPhysicalTzramFullProgramImage.GetSize(), program, program_lz4_size);
|
||||
|
||||
/* Copy the boot image to the end of IRAM */
|
||||
u8 *relocated_boot_code = secmon::MemoryRegionPhysicalIramBootCodeImage.GetEndPointer<u8>() - boot_code_lz4_size;
|
||||
std::memcpy(relocated_boot_code, boot_code_lz4, boot_code_lz4_size);
|
||||
std::memcpy(relocated_boot_code, boot_code, boot_code_lz4_size);
|
||||
|
||||
/* Uncompress the boot image. */
|
||||
Uncompress(secmon::MemoryRegionPhysicalIramBootCodeImage.GetPointer(), secmon::MemoryRegionPhysicalIramBootCodeImage.GetSize(), relocated_boot_code, boot_code_lz4_size);
|
||||
|
||||
@@ -98,8 +98,8 @@ _start:
|
||||
ldr x20, =0x7C020000
|
||||
mov sp, x20
|
||||
|
||||
/* Call our init array functions. */
|
||||
bl __libc_init_array
|
||||
adr x0, program_lz4
|
||||
adr x1, boot_code_lz4
|
||||
|
||||
/* Uncompress the program and iram boot code images. */
|
||||
b _ZN3ams6secmon6loader20UncompressAndExecuteEv
|
||||
b _ZN3ams6secmon6loader20UncompressAndExecuteEPKvS3_
|
||||
|
||||
@@ -272,7 +272,19 @@ namespace ams::secmon::smc {
|
||||
|
||||
void GetSecureDataImpl(u8 *dst, SecureData which, bool tweak) {
|
||||
/* Compute the appropriate AES-CTR. */
|
||||
se::ComputeAes128Ctr(dst, AesKeySize, pkg1::AesKeySlot_Device, SecureDataSource, AesKeySize, GetSecureDataCounter(which), AesKeySize);
|
||||
{
|
||||
/* Ensure that the SE sees consistent data. */
|
||||
hw::FlushDataCache(dst, AesKeySize);
|
||||
hw::DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
/* Perform the appropriate AES operation. */
|
||||
se::ComputeAes128Ctr(dst, AesKeySize, pkg1::AesKeySlot_Device, SecureDataSource, AesKeySize, GetSecureDataCounter(which), AesKeySize);
|
||||
hw::DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
/* Ensure the CPU sees consistent data. */
|
||||
hw::FlushDataCache(dst, AesKeySize);
|
||||
hw::DataSynchronizationBarrierInnerShareable();
|
||||
}
|
||||
|
||||
/* Tweak, if we should. */
|
||||
if (tweak) {
|
||||
|
||||
@@ -243,7 +243,7 @@ namespace ams::secmon::smc {
|
||||
(static_cast<u64>(ATMOSPHERE_RELEASE_VERSION_MINOR & 0xFF) << 48) |
|
||||
(static_cast<u64>(ATMOSPHERE_RELEASE_VERSION_MICRO & 0xFF) << 40) |
|
||||
(static_cast<u64>(GetKeyGeneration()) << 32) |
|
||||
(static_cast<u64>(GetTargetFirmware()) << 00);
|
||||
(static_cast<u64>(GetTargetFirmware()) << 0);
|
||||
break;
|
||||
case ConfigItem::ExosphereNeedsReboot:
|
||||
/* We are executing, so we aren't in the process of rebooting. */
|
||||
@@ -290,6 +290,12 @@ namespace ams::secmon::smc {
|
||||
/* Get whether usb 3.0 should be force-enabled. */
|
||||
args.r[1] = GetSecmonConfiguration().IsUsb30ForceEnabled();
|
||||
break;
|
||||
case ConfigItem::ExosphereSupportedHosVersion:
|
||||
/* Get information about the supported hos version. */
|
||||
args.r[1] = (static_cast<u64>(ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR & 0xFF) << 24) |
|
||||
(static_cast<u64>(ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR & 0xFF) << 16) |
|
||||
(static_cast<u64>(ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO & 0xFF) << 8);
|
||||
break;
|
||||
default:
|
||||
return SmcResult::InvalidArgument;
|
||||
}
|
||||
|
||||
@@ -40,17 +40,18 @@ namespace ams::secmon::smc {
|
||||
Package2Hash = 17,
|
||||
|
||||
/* Extension config items for exosphere. */
|
||||
ExosphereApiVersion = 65000,
|
||||
ExosphereNeedsReboot = 65001,
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
ExosphereLogConfiguration = 65009,
|
||||
ExosphereForceEnableUsb30 = 65010,
|
||||
ExosphereApiVersion = 65000,
|
||||
ExosphereNeedsReboot = 65001,
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
ExosphereLogConfiguration = 65009,
|
||||
ExosphereForceEnableUsb30 = 65010,
|
||||
ExosphereSupportedHosVersion = 65011,
|
||||
};
|
||||
|
||||
SmcResult SmcGetConfigUser(SmcArguments &args);
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
#include "../../../fusee/fusee-primary/fusee-primary-main/src/fs_utils.h"
|
||||
#elif defined(FUSEE_STAGE2_SRC)
|
||||
#include "../../../fusee/fusee-secondary/src/device_partition.h"
|
||||
#elif defined(SEPT_STAGE2_SRC)
|
||||
#include "../../../sept/sept-secondary/src/fs_utils.h"
|
||||
#endif
|
||||
|
||||
#ifdef FUSEE_STAGE2_SRC
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
#include "../../../fusee/fusee-primary/fusee-primary-main/src/timers.h"
|
||||
#elif defined(FUSEE_STAGE2_SRC)
|
||||
#include "../../../fusee/fusee-secondary/src/timers.h"
|
||||
#elif defined(SEPT_STAGE2_SRC)
|
||||
#include "../../../sept/sept-secondary/src/timers.h"
|
||||
#endif
|
||||
|
||||
#define UNSTUFF_BITS(resp,start,size) \
|
||||
@@ -102,7 +100,7 @@ static int sdmmc_device_send_r1_cmd(sdmmc_device_t *device, uint32_t opcode, uin
|
||||
if (resp_mask) {
|
||||
resp &= ~(resp_mask);
|
||||
}
|
||||
|
||||
|
||||
/* We got an error state. */
|
||||
if (is_sdmmc_device_r1_error(resp)) {
|
||||
return 0;
|
||||
@@ -355,7 +353,7 @@ static int sdmmc_sd_decode_scr(sdmmc_device_t *device, uint8_t *scr) {
|
||||
if (device->scr.sda_spec3) {
|
||||
device->scr.cmds = UNSTUFF_BITS(resp, 32, 2);
|
||||
}
|
||||
|
||||
|
||||
/* Unknown SCR structure version. */
|
||||
if (UNSTUFF_BITS(resp, 60, 4)) {
|
||||
return 0;
|
||||
@@ -465,7 +463,7 @@ static int sdmmc_sd_send_op_cond(sdmmc_device_t *device, bool is_sd_ver2, bool i
|
||||
if (is_uhs_en) {
|
||||
arg |= SD_OCR_S18R;
|
||||
}
|
||||
|
||||
|
||||
cmd.opcode = SD_APP_OP_COND;
|
||||
cmd.arg = arg;
|
||||
cmd.flags = SDMMC_RSP_R3;
|
||||
@@ -916,7 +914,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||
if (!sdmmc_sd_decode_csd(device, csd)) {
|
||||
sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure);
|
||||
}
|
||||
|
||||
|
||||
/* If we never switched to 1.8V, change the bus speed mode. */
|
||||
if (!device->is_180v) {
|
||||
/* Reconfigure the internal clock. */
|
||||
@@ -1155,7 +1153,7 @@ static int sdmmc_mmc_send_op_cond(sdmmc_device_t *device, SdmmcBusVoltage bus_vo
|
||||
if (resp & SD_OCR_CCS) {
|
||||
device->is_block_sdhc = true;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1439,7 +1437,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
||||
if (!sdmmc_mmc_decode_csd(device, csd)) {
|
||||
sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure);
|
||||
}
|
||||
|
||||
|
||||
/* Reconfigure the internal clock. */
|
||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_LEGACY)) {
|
||||
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
||||
@@ -1498,7 +1496,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
||||
} else {
|
||||
sdmmc_info(sdmmc, "BKOPS is disabled!");
|
||||
}
|
||||
|
||||
|
||||
/* Switch to high speed mode. */
|
||||
if (!sdmmc_mmc_select_timing(device, bus_speed)) {
|
||||
sdmmc_error(sdmmc, "Failed to switch to high speed mode!");
|
||||
|
||||
@@ -41,15 +41,6 @@
|
||||
#include "../../../fusee/fusee-secondary/src/gpio.h"
|
||||
#include "../../../fusee/fusee-secondary/src/pmc.h"
|
||||
#include "../../../fusee/fusee-secondary/src/max7762x.h"
|
||||
#elif defined(SEPT_STAGE2_SRC)
|
||||
#include "../../../sept/sept-secondary/src/car.h"
|
||||
#include "../../../sept/sept-secondary/src/fuse.h"
|
||||
#include "../../../sept/sept-secondary/src/pinmux.h"
|
||||
#include "../../../sept/sept-secondary/src/timers.h"
|
||||
#include "../../../sept/sept-secondary/src/apb_misc.h"
|
||||
#include "../../../sept/sept-secondary/src/gpio.h"
|
||||
#include "../../../sept/sept-secondary/src/pmc.h"
|
||||
#include "../../../sept/sept-secondary/src/max7762x.h"
|
||||
#endif
|
||||
#include "../log.h"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FUSEE_CAR_H
|
||||
#define FUSEE_CAR_H
|
||||
|
||||
@@ -489,7 +489,16 @@ typedef struct {
|
||||
uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */
|
||||
uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */
|
||||
uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */
|
||||
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
|
||||
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
|
||||
|
||||
uint32_t _0x748[(0x774-0x748) / sizeof(uint32_t)]; // TODO
|
||||
|
||||
uint32_t pllm_ss_cfg; /* _PLLM_SS_CFG_0, 0x744 */
|
||||
uint32_t pllm_ss_ctrl1; /* _PLLM_SS_CTRL1_0, 0x778 */
|
||||
uint32_t pllm_ss_ctrl2; /* _PLLM_SS_CTRL2_0, 0x77C */
|
||||
uint32_t pllmb_ss_cfg; /* _PLLMB_SS_CFG_0, 0x780 */
|
||||
uint32_t pllmb_ss_ctrl1; /* _PLLMB_SS_CTRL1_0, 0x784 */
|
||||
uint32_t pllmb_ss_ctrl2; /* _PLLMB_SS_CTRL2_0, 0x788 */
|
||||
} tegra_car_t;
|
||||
|
||||
static inline volatile tegra_car_t *car_get_regs(void) {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FUSEE_EMC_H_
|
||||
#define FUSEE_EMC_H_
|
||||
|
||||
@@ -393,6 +393,7 @@
|
||||
#define EMC_CFG_DIG_DLL_PERIOD 0x2c0
|
||||
#define EMC_DIG_DLL_STATUS 0x2c4
|
||||
#define EMC_DIG_DLL_STATUS_DLL_LOCK (1 << 15)
|
||||
#define EMC_DIG_DLL_STATUS_DLL_LOCK_B01 (1 << 2)
|
||||
#define EMC_DIG_DLL_STATUS_DLL_PRIV_UPDATED (1 << 17)
|
||||
#define EMC_DIG_DLL_STATUS_DLL_OUT_SHIFT 0
|
||||
#define EMC_DIG_DLL_STATUS_DLL_OUT_MASK \
|
||||
@@ -1065,6 +1066,10 @@
|
||||
#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSN_TX_E_DCC (1 << 16)
|
||||
#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_CMD_TX_E_DCC (1 << 24)
|
||||
|
||||
#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQS_E_IVREF_B01 (1 << 10)
|
||||
|
||||
|
||||
|
||||
#define EMC_PMACRO_COMMON_PAD_TX_CTRL 0xc68
|
||||
#define EMC_PMACRO_BRICK_MAPPING_0 0xc80
|
||||
#define EMC_PMACRO_BRICK_MAPPING_1 0xc84
|
||||
@@ -1126,4 +1131,8 @@
|
||||
|
||||
#define EMC_PMACRO_DSR_VTTGEN_CTRL_0 0xc6c
|
||||
|
||||
// B01
|
||||
#define EMC_PMACRO_DLL_CFG_0 0x5E4
|
||||
#define EMC_PMACRO_DLL_CFG_1 0x5E8
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,28 +28,28 @@ static stage2_mtc_args_t *g_mtc_args;
|
||||
|
||||
int main(int argc, void **argv) {
|
||||
ScreenLogLevel log_level = SCREEN_LOG_LEVEL_NONE;
|
||||
|
||||
|
||||
/* Check argc. */
|
||||
if (argc != MTC_ARGC) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Extract arguments from argv. */
|
||||
g_mtc_args = &g_mtc_args_store;
|
||||
memcpy(g_mtc_args, (stage2_mtc_args_t *)argv[MTC_ARGV_ARGUMENT_STRUCT], sizeof(*g_mtc_args));
|
||||
log_level = g_mtc_args->log_level;
|
||||
|
||||
|
||||
/* Override the global logging level. */
|
||||
log_set_log_level(log_level);
|
||||
|
||||
|
||||
if (log_level != SCREEN_LOG_LEVEL_NONE) {
|
||||
/* Set framebuffer address. */
|
||||
g_framebuffer = (void *)0xC0000000;
|
||||
|
||||
|
||||
/* Zero-fill the framebuffer and register it as printk provider. */
|
||||
video_init(g_framebuffer);
|
||||
}
|
||||
|
||||
|
||||
/* Train DRAM. */
|
||||
train_dram();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,7 @@
|
||||
#define TEGRA21_MAX_TABLE_ID_LEN 50
|
||||
#define TEGRA_EMC_ISO_USE_FREQ_MAX_NUM 12
|
||||
#define PLL_C_DIRECT_FLOOR 333500000
|
||||
#define EMC_STATUS_UPDATE_TIMEOUT 1000
|
||||
#define EMC_STATUS_UPDATE_TIMEOUT 2000
|
||||
#define TEGRA_EMC_DEFAULT_CLK_LATENCY_US 2000
|
||||
|
||||
#define TEGRA_EMC_MODE_REG_17 0x00110000
|
||||
|
||||
4180
fusee/fusee-mtc/src/mtc_b01.c
Normal file
4180
fusee/fusee-mtc/src/mtc_b01.c
Normal file
File diff suppressed because it is too large
Load Diff
689
fusee/fusee-mtc/src/mtc_b01.h
Normal file
689
fusee/fusee-mtc/src/mtc_b01.h
Normal file
@@ -0,0 +1,689 @@
|
||||
/*
|
||||
* Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2018 CTCaer <ctcaer@gmail.com>
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FUSEE_MTC_B01_H_
|
||||
#define FUSEE_MTC_B01_H_
|
||||
|
||||
#include "mtc.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t ptfv_dqsosc_movavg_c0d0u0;
|
||||
uint32_t ptfv_dqsosc_movavg_c0d0u1;
|
||||
uint32_t ptfv_dqsosc_movavg_c0d1u0;
|
||||
uint32_t ptfv_dqsosc_movavg_c0d1u1;
|
||||
uint32_t ptfv_dqsosc_movavg_c1d0u0;
|
||||
uint32_t ptfv_dqsosc_movavg_c1d0u1;
|
||||
uint32_t ptfv_dqsosc_movavg_c1d1u0;
|
||||
uint32_t ptfv_dqsosc_movavg_c1d1u1;
|
||||
uint32_t ptfv_write_samples;
|
||||
uint32_t ptfv_dvfs_samples;
|
||||
uint32_t ptfv_movavg_weight;
|
||||
uint32_t ptfv_config_ctrl;
|
||||
} t210_emc_ptfv_list_table;
|
||||
|
||||
typedef struct {
|
||||
uint32_t emc_rc;
|
||||
uint32_t emc_rfc;
|
||||
uint32_t emc_rfcpb;
|
||||
uint32_t emc_refctrl2;
|
||||
uint32_t emc_rfc_slr;
|
||||
uint32_t emc_ras;
|
||||
uint32_t emc_rp;
|
||||
uint32_t emc_r2w;
|
||||
uint32_t emc_w2r;
|
||||
uint32_t emc_r2p;
|
||||
uint32_t emc_w2p;
|
||||
uint32_t emc_r2r;
|
||||
uint32_t emc_tppd;
|
||||
uint32_t emc_trtm;
|
||||
uint32_t emc_twtm;
|
||||
uint32_t emc_tratm;
|
||||
uint32_t emc_twatm;
|
||||
uint32_t emc_tr2ref;
|
||||
uint32_t emc_ccdmw;
|
||||
uint32_t emc_rd_rcd;
|
||||
uint32_t emc_wr_rcd;
|
||||
uint32_t emc_rrd;
|
||||
uint32_t emc_rext;
|
||||
uint32_t emc_wext;
|
||||
uint32_t emc_wdv_chk;
|
||||
uint32_t emc_wdv;
|
||||
uint32_t emc_wsv;
|
||||
uint32_t emc_wev;
|
||||
uint32_t emc_wdv_mask;
|
||||
uint32_t emc_ws_duration;
|
||||
uint32_t emc_we_duration;
|
||||
uint32_t emc_quse;
|
||||
uint32_t emc_quse_width;
|
||||
uint32_t emc_ibdly;
|
||||
uint32_t emc_obdly;
|
||||
uint32_t emc_einput;
|
||||
uint32_t emc_mrw6;
|
||||
uint32_t emc_einput_duration;
|
||||
uint32_t emc_puterm_extra;
|
||||
uint32_t emc_puterm_width;
|
||||
uint32_t emc_qrst;
|
||||
uint32_t emc_qsafe;
|
||||
uint32_t emc_rdv;
|
||||
uint32_t emc_rdv_mask;
|
||||
uint32_t emc_rdv_early;
|
||||
uint32_t emc_rdv_early_mask;
|
||||
uint32_t emc_refresh;
|
||||
uint32_t emc_burst_refresh_num;
|
||||
uint32_t emc_pre_refresh_req_cnt;
|
||||
uint32_t emc_pdex2wr;
|
||||
uint32_t emc_pdex2rd;
|
||||
uint32_t emc_pchg2pden;
|
||||
uint32_t emc_act2pden;
|
||||
uint32_t emc_ar2pden;
|
||||
uint32_t emc_rw2pden;
|
||||
uint32_t emc_cke2pden;
|
||||
uint32_t emc_pdex2cke;
|
||||
uint32_t emc_pdex2mrr;
|
||||
uint32_t emc_txsr;
|
||||
uint32_t emc_txsrdll;
|
||||
uint32_t emc_tcke;
|
||||
uint32_t emc_tckesr;
|
||||
uint32_t emc_tpd;
|
||||
uint32_t emc_tfaw;
|
||||
uint32_t emc_trpab;
|
||||
uint32_t emc_tclkstable;
|
||||
uint32_t emc_tclkstop;
|
||||
uint32_t emc_mrw7;
|
||||
uint32_t emc_trefbw;
|
||||
uint32_t emc_odt_write;
|
||||
uint32_t emc_fbio_cfg5;
|
||||
uint32_t emc_fbio_cfg7;
|
||||
uint32_t emc_cfg_dig_dll;
|
||||
uint32_t emc_cfg_dig_dll_period;
|
||||
uint32_t emc_pmacro_ib_rxrt;
|
||||
uint32_t emc_cfg_pipe_1;
|
||||
uint32_t emc_cfg_pipe_2;
|
||||
uint32_t emc_pmacro_quse_ddll_rank0_4;
|
||||
uint32_t emc_pmacro_quse_ddll_rank0_5;
|
||||
uint32_t emc_pmacro_quse_ddll_rank1_4;
|
||||
uint32_t emc_pmacro_quse_ddll_rank1_5;
|
||||
uint32_t emc_mrw8;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank1_4;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank1_5;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_0;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_1;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_2;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_3;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_4;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_5;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_0;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_1;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_2;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_3;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_4;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_5;
|
||||
uint32_t emc_pmacro_ddll_long_cmd_0;
|
||||
uint32_t emc_pmacro_ddll_long_cmd_1;
|
||||
uint32_t emc_pmacro_ddll_long_cmd_2;
|
||||
uint32_t emc_pmacro_ddll_long_cmd_3;
|
||||
uint32_t emc_pmacro_ddll_long_cmd_4;
|
||||
uint32_t emc_pmacro_ddll_short_cmd_0;
|
||||
uint32_t emc_pmacro_ddll_short_cmd_1;
|
||||
uint32_t emc_pmacro_ddll_short_cmd_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte0_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte1_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte2_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte3_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte4_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte5_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte6_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte7_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd0_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd1_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd2_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd3_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte0_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte1_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte2_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte3_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte4_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte5_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte6_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte7_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd0_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd0_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd0_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd0_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd1_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd1_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd1_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd1_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd2_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd2_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd2_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd2_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd3_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd3_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd3_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_cmd3_3;
|
||||
uint32_t emc_txdsrvttgen;
|
||||
uint32_t emc_fdpd_ctrl_dq;
|
||||
uint32_t emc_fdpd_ctrl_cmd;
|
||||
uint32_t emc_fbio_spare;
|
||||
uint32_t emc_zcal_interval;
|
||||
uint32_t emc_zcal_wait_cnt;
|
||||
uint32_t emc_mrs_wait_cnt;
|
||||
uint32_t emc_mrs_wait_cnt2;
|
||||
uint32_t emc_auto_cal_channel;
|
||||
uint32_t emc_pmacro_dll_cfg_0;
|
||||
uint32_t emc_pmacro_dll_cfg_1;
|
||||
uint32_t emc_pmacro_dll_cfg_2;
|
||||
uint32_t emc_pmacro_autocal_cfg_common;
|
||||
uint32_t emc_pmacro_zctrl;
|
||||
uint32_t emc_cfg;
|
||||
uint32_t emc_cfg_pipe;
|
||||
uint32_t emc_dyn_self_ref_control;
|
||||
uint32_t emc_qpop;
|
||||
uint32_t emc_dqs_brlshft_0;
|
||||
uint32_t emc_dqs_brlshft_1;
|
||||
uint32_t emc_cmd_brlshft_2;
|
||||
uint32_t emc_cmd_brlshft_3;
|
||||
uint32_t emc_pmacro_pad_cfg_ctrl;
|
||||
uint32_t emc_pmacro_data_pad_rx_ctrl;
|
||||
uint32_t emc_pmacro_cmd_pad_rx_ctrl;
|
||||
uint32_t emc_pmacro_data_rx_term_mode;
|
||||
uint32_t emc_pmacro_cmd_rx_term_mode;
|
||||
uint32_t emc_pmacro_cmd_pad_tx_ctrl;
|
||||
uint32_t emc_pmacro_data_pad_tx_ctrl;
|
||||
uint32_t emc_pmacro_vttgen_ctrl_0;
|
||||
uint32_t emc_pmacro_vttgen_ctrl_1;
|
||||
uint32_t emc_pmacro_vttgen_ctrl_2;
|
||||
uint32_t emc_pmacro_brick_ctrl_rfu1;
|
||||
uint32_t emc_pmacro_cmd_brick_ctrl_fdpd;
|
||||
uint32_t emc_pmacro_brick_ctrl_rfu2;
|
||||
uint32_t emc_pmacro_data_brick_ctrl_fdpd;
|
||||
uint32_t emc_pmacro_bg_bias_ctrl_0;
|
||||
uint32_t emc_cfg_3;
|
||||
uint32_t emc_pmacro_tx_pwrd_0;
|
||||
uint32_t emc_pmacro_tx_pwrd_1;
|
||||
uint32_t emc_pmacro_tx_pwrd_2;
|
||||
uint32_t emc_pmacro_tx_pwrd_3;
|
||||
uint32_t emc_pmacro_tx_pwrd_4;
|
||||
uint32_t emc_pmacro_tx_pwrd_5;
|
||||
uint32_t emc_config_sample_delay;
|
||||
uint32_t emc_pmacro_tx_sel_clk_src_0;
|
||||
uint32_t emc_pmacro_tx_sel_clk_src_1;
|
||||
uint32_t emc_pmacro_tx_sel_clk_src_2;
|
||||
uint32_t emc_pmacro_tx_sel_clk_src_3;
|
||||
uint32_t emc_pmacro_tx_sel_clk_src_4;
|
||||
uint32_t emc_pmacro_tx_sel_clk_src_5;
|
||||
uint32_t emc_pmacro_ddll_bypass;
|
||||
uint32_t emc_pmacro_ddll_pwrd_0;
|
||||
uint32_t emc_pmacro_ddll_pwrd_1;
|
||||
uint32_t emc_pmacro_ddll_pwrd_2;
|
||||
uint32_t emc_pmacro_cmd_ctrl_0;
|
||||
uint32_t emc_pmacro_cmd_ctrl_1;
|
||||
uint32_t emc_pmacro_cmd_ctrl_2;
|
||||
uint32_t emc_pmacro_data_pi_ctrl;
|
||||
uint32_t emc_pmacro_cmd_pi_ctrl;
|
||||
uint32_t emc_tr_timing_0;
|
||||
uint32_t emc_tr_dvfs;
|
||||
uint32_t emc_tr_ctrl_1;
|
||||
uint32_t emc_tr_rdv;
|
||||
uint32_t emc_tr_qpop;
|
||||
uint32_t emc_tr_rdv_mask;
|
||||
uint32_t emc_mrw14;
|
||||
uint32_t emc_tr_qsafe;
|
||||
uint32_t emc_tr_qrst;
|
||||
uint32_t emc_training_ctrl;
|
||||
uint32_t emc_training_settle;
|
||||
uint32_t emc_training_vref_settle;
|
||||
uint32_t emc_training_ca_fine_ctrl;
|
||||
uint32_t emc_training_ca_ctrl_misc;
|
||||
uint32_t emc_training_ca_ctrl_misc1;
|
||||
uint32_t emc_training_ca_vref_ctrl;
|
||||
uint32_t emc_training_quse_cors_ctrl;
|
||||
uint32_t emc_training_quse_fine_ctrl;
|
||||
uint32_t emc_training_quse_ctrl_misc;
|
||||
uint32_t emc_training_quse_vref_ctrl;
|
||||
uint32_t emc_training_read_fine_ctrl;
|
||||
uint32_t emc_training_read_ctrl_misc;
|
||||
uint32_t emc_training_read_vref_ctrl;
|
||||
uint32_t emc_training_write_fine_ctrl;
|
||||
uint32_t emc_training_write_ctrl_misc;
|
||||
uint32_t emc_training_write_vref_ctrl;
|
||||
uint32_t emc_training_mpc;
|
||||
uint32_t emc_mrw15;
|
||||
} t210b01_emc_burst_regs;
|
||||
|
||||
typedef struct {
|
||||
uint32_t emc0_mrw10;
|
||||
uint32_t emc1_mrw10;
|
||||
uint32_t emc0_mrw11;
|
||||
uint32_t emc1_mrw11;
|
||||
uint32_t emc0_mrw12;
|
||||
uint32_t emc1_mrw12;
|
||||
uint32_t emc0_mrw13;
|
||||
uint32_t emc1_mrw13;
|
||||
} t210_emc_burst_reg_per_ch;
|
||||
|
||||
typedef struct {
|
||||
uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_0;
|
||||
uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_1;
|
||||
uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_2;
|
||||
uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_3;
|
||||
uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_0;
|
||||
uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_1;
|
||||
uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_2;
|
||||
uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_3;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte0_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte0_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte0_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte1_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte1_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte1_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte2_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte2_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte2_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte3_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte3_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte3_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte4_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte4_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte4_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte5_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte5_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte5_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte6_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte6_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte6_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte7_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte7_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank0_byte7_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte0_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte0_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte0_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte1_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte1_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte1_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte2_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte2_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte2_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte3_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte3_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte3_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte4_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte4_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte4_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte5_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte5_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte5_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte6_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte6_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte6_2;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte7_0;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte7_1;
|
||||
uint32_t emc_pmacro_ib_ddll_short_dq_rank1_byte7_2;
|
||||
uint32_t emc_pmacro_ib_vref_dqs_0;
|
||||
uint32_t emc_pmacro_ib_vref_dqs_1;
|
||||
uint32_t emc_pmacro_ib_vref_dq_0;
|
||||
uint32_t emc_pmacro_ib_vref_dq_1;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank0_0;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank0_1;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank0_2;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank0_3;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank0_4;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank0_5;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank1_0;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank1_1;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank1_2;
|
||||
uint32_t emc_pmacro_ob_ddll_long_dq_rank1_3;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte0_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte0_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte0_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte1_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte1_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte1_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte2_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte2_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte2_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte3_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte3_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte3_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte4_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte4_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte4_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte5_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte5_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte5_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte6_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte6_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte6_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte7_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte7_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_byte7_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd0_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd0_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd0_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd1_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd1_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd1_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd2_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd2_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd2_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd3_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd3_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank0_cmd3_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte0_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte0_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte0_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte1_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte1_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte1_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte2_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte2_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte2_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte3_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte3_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte3_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte4_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte4_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte4_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte5_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte5_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte5_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte6_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte6_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte6_2;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte7_0;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte7_1;
|
||||
uint32_t emc_pmacro_ob_ddll_short_dq_rank1_byte7_2;
|
||||
uint32_t emc_pmacro_quse_ddll_rank0_0;
|
||||
uint32_t emc_pmacro_quse_ddll_rank0_1;
|
||||
uint32_t emc_pmacro_quse_ddll_rank0_2;
|
||||
uint32_t emc_pmacro_quse_ddll_rank0_3;
|
||||
uint32_t emc_pmacro_quse_ddll_rank1_0;
|
||||
uint32_t emc_pmacro_quse_ddll_rank1_1;
|
||||
uint32_t emc_pmacro_quse_ddll_rank1_2;
|
||||
uint32_t emc_pmacro_quse_ddll_rank1_3;
|
||||
} t210_emc_trim_regs;
|
||||
|
||||
typedef struct {
|
||||
uint32_t emc_cmd_brlshft_0;
|
||||
uint32_t emc_cmd_brlshft_1;
|
||||
uint32_t emc0_data_brlshft_0;
|
||||
uint32_t emc1_data_brlshft_0;
|
||||
uint32_t emc0_data_brlshft_1;
|
||||
uint32_t emc1_data_brlshft_1;
|
||||
uint32_t emc_quse_brlshft_0;
|
||||
uint32_t emc_quse_brlshft_1;
|
||||
uint32_t emc_quse_brlshft_2;
|
||||
uint32_t emc_quse_brlshft_3;
|
||||
} t210_emc_trim_perch_regs;
|
||||
|
||||
typedef struct {
|
||||
uint32_t emc0_training_opt_dqs_ib_vref_rank0;
|
||||
uint32_t emc1_training_opt_dqs_ib_vref_rank0;
|
||||
uint32_t emc0_training_opt_dqs_ib_vref_rank1;
|
||||
uint32_t emc1_training_opt_dqs_ib_vref_rank1;
|
||||
} t210_emc_vref_perch_regs;
|
||||
|
||||
typedef struct {
|
||||
uint32_t t_rp;
|
||||
uint32_t t_fc_lpddr4;
|
||||
uint32_t t_rfc;
|
||||
uint32_t t_pdex;
|
||||
uint32_t rl;
|
||||
} t210_emc_dram_timings;
|
||||
|
||||
typedef struct {
|
||||
uint32_t emc0_training_rw_offset_ib_byte0;
|
||||
uint32_t emc1_training_rw_offset_ib_byte0;
|
||||
uint32_t emc0_training_rw_offset_ib_byte1;
|
||||
uint32_t emc1_training_rw_offset_ib_byte1;
|
||||
uint32_t emc0_training_rw_offset_ib_byte2;
|
||||
uint32_t emc1_training_rw_offset_ib_byte2;
|
||||
uint32_t emc0_training_rw_offset_ib_byte3;
|
||||
uint32_t emc1_training_rw_offset_ib_byte3;
|
||||
uint32_t emc0_training_rw_offset_ib_misc;
|
||||
uint32_t emc1_training_rw_offset_ib_misc;
|
||||
uint32_t emc0_training_rw_offset_ob_byte0;
|
||||
uint32_t emc1_training_rw_offset_ob_byte0;
|
||||
uint32_t emc0_training_rw_offset_ob_byte1;
|
||||
uint32_t emc1_training_rw_offset_ob_byte1;
|
||||
uint32_t emc0_training_rw_offset_ob_byte2;
|
||||
uint32_t emc1_training_rw_offset_ob_byte2;
|
||||
uint32_t emc0_training_rw_offset_ob_byte3;
|
||||
uint32_t emc1_training_rw_offset_ob_byte3;
|
||||
uint32_t emc0_training_rw_offset_ob_misc;
|
||||
uint32_t emc1_training_rw_offset_ob_misc;
|
||||
} t210_emc_training_mod_regs;
|
||||
|
||||
typedef struct {
|
||||
uint32_t mc_emem_arb_cfg;
|
||||
uint32_t mc_emem_arb_outstanding_req;
|
||||
uint32_t mc_emem_arb_refpb_hp_ctrl;
|
||||
uint32_t mc_emem_arb_refpb_bank_ctrl;
|
||||
uint32_t mc_emem_arb_timing_rcd;
|
||||
uint32_t mc_emem_arb_timing_rp;
|
||||
uint32_t mc_emem_arb_timing_rc;
|
||||
uint32_t mc_emem_arb_timing_ras;
|
||||
uint32_t mc_emem_arb_timing_faw;
|
||||
uint32_t mc_emem_arb_timing_rrd;
|
||||
uint32_t mc_emem_arb_timing_rap2pre;
|
||||
uint32_t mc_emem_arb_timing_wap2pre;
|
||||
uint32_t mc_emem_arb_timing_r2r;
|
||||
uint32_t mc_emem_arb_timing_w2w;
|
||||
uint32_t mc_emem_arb_timing_r2w;
|
||||
uint32_t mc_emem_arb_timing_ccdmw;
|
||||
uint32_t mc_emem_arb_timing_w2r;
|
||||
uint32_t mc_emem_arb_timing_rfcpb;
|
||||
uint32_t mc_emem_arb_da_turns;
|
||||
uint32_t mc_emem_arb_da_covers;
|
||||
uint32_t mc_emem_arb_misc0;
|
||||
uint32_t mc_emem_arb_misc1;
|
||||
uint32_t mc_emem_arb_misc2;
|
||||
uint32_t mc_emem_arb_ring1_throttle;
|
||||
uint32_t mc_emem_arb_dhyst_ctrl;
|
||||
uint32_t mc_emem_arb_dhyst_timeout_util_0;
|
||||
uint32_t mc_emem_arb_dhyst_timeout_util_1;
|
||||
uint32_t mc_emem_arb_dhyst_timeout_util_2;
|
||||
uint32_t mc_emem_arb_dhyst_timeout_util_3;
|
||||
uint32_t mc_emem_arb_dhyst_timeout_util_4;
|
||||
uint32_t mc_emem_arb_dhyst_timeout_util_5;
|
||||
uint32_t mc_emem_arb_dhyst_timeout_util_6;
|
||||
uint32_t mc_emem_arb_dhyst_timeout_util_7;
|
||||
} t210_emc_burst_mc_regs;
|
||||
|
||||
typedef struct {
|
||||
uint32_t mc_mll_mpcorer_ptsa_rate;
|
||||
uint32_t mc_ftop_ptsa_rate;
|
||||
uint32_t mc_ptsa_grant_decrement;
|
||||
uint32_t mc_latency_allowance_xusb_0;
|
||||
uint32_t mc_latency_allowance_xusb_1;
|
||||
uint32_t mc_latency_allowance_tsec_0;
|
||||
uint32_t mc_latency_allowance_sdmmca_0;
|
||||
uint32_t mc_latency_allowance_sdmmcaa_0;
|
||||
uint32_t mc_latency_allowance_sdmmc_0;
|
||||
uint32_t mc_latency_allowance_sdmmcab_0;
|
||||
uint32_t mc_latency_allowance_ppcs_0;
|
||||
uint32_t mc_latency_allowance_ppcs_1;
|
||||
uint32_t mc_latency_allowance_mpcore_0;
|
||||
uint32_t mc_latency_allowance_hc_0;
|
||||
uint32_t mc_latency_allowance_hc_1;
|
||||
uint32_t mc_latency_allowance_avpc_0;
|
||||
uint32_t mc_latency_allowance_gpu_0;
|
||||
uint32_t mc_latency_allowance_gpu2_0;
|
||||
uint32_t mc_latency_allowance_nvenc_0;
|
||||
uint32_t mc_latency_allowance_nvdec_0;
|
||||
uint32_t mc_latency_allowance_vic_0;
|
||||
uint32_t mc_latency_allowance_vi2_0;
|
||||
uint32_t mc_latency_allowance_isp2_0;
|
||||
uint32_t mc_latency_allowance_isp2_1;
|
||||
} t210_emc_la_scale_regs;
|
||||
|
||||
typedef struct {
|
||||
uint32_t rev;
|
||||
char dvfs_ver[60];
|
||||
uint32_t rate_khz;
|
||||
uint32_t min_volt;
|
||||
uint32_t gpu_min_volt;
|
||||
char clock_src[32];
|
||||
uint32_t clk_src_emc;
|
||||
uint32_t pll_en_ssc;
|
||||
uint32_t needs_training;
|
||||
uint32_t training_pattern;
|
||||
uint32_t trained;
|
||||
uint32_t periodic_training;
|
||||
uint32_t trained_dram_clktree_c0d0u0;
|
||||
uint32_t trained_dram_clktree_c0d0u1;
|
||||
uint32_t trained_dram_clktree_c0d1u0;
|
||||
uint32_t trained_dram_clktree_c0d1u1;
|
||||
uint32_t trained_dram_clktree_c1d0u0;
|
||||
uint32_t trained_dram_clktree_c1d0u1;
|
||||
uint32_t trained_dram_clktree_c1d1u0;
|
||||
uint32_t trained_dram_clktree_c1d1u1;
|
||||
uint32_t current_dram_clktree_c0d0u0;
|
||||
uint32_t current_dram_clktree_c0d0u1;
|
||||
uint32_t current_dram_clktree_c0d1u0;
|
||||
uint32_t current_dram_clktree_c0d1u1;
|
||||
uint32_t current_dram_clktree_c1d0u0;
|
||||
uint32_t current_dram_clktree_c1d0u1;
|
||||
uint32_t current_dram_clktree_c1d1u0;
|
||||
uint32_t current_dram_clktree_c1d1u1;
|
||||
uint32_t emc_fbio_cfg7;
|
||||
uint32_t run_clocks;
|
||||
uint32_t tree_margin;
|
||||
uint32_t num_burst;
|
||||
uint32_t num_burst_per_ch;
|
||||
uint32_t num_trim;
|
||||
uint32_t num_trim_per_ch;
|
||||
uint32_t num_mc_regs;
|
||||
uint32_t num_up_down;
|
||||
uint32_t vref_num;
|
||||
uint32_t training_mod_num;
|
||||
uint32_t dram_timing_num;
|
||||
t210_emc_ptfv_list_table ptfv_list;
|
||||
union {
|
||||
t210b01_emc_burst_regs burst_regs;
|
||||
uint32_t burst_regs_arr[sizeof(t210b01_emc_burst_regs) / sizeof(uint32_t)];
|
||||
};
|
||||
union {
|
||||
t210_emc_burst_reg_per_ch burst_reg_per_ch;
|
||||
uint32_t burst_reg_per_ch_arr[sizeof(t210_emc_burst_reg_per_ch) / sizeof(uint32_t)];
|
||||
};
|
||||
union {
|
||||
t210b01_emc_burst_regs shadow_regs_ca_train;
|
||||
uint32_t shadow_regs_ca_train_arr[sizeof(t210b01_emc_burst_regs) / sizeof(uint32_t)];
|
||||
};
|
||||
union {
|
||||
t210b01_emc_burst_regs shadow_regs_rdwr_train;
|
||||
uint32_t shadow_regs_rdwr_train_arr[sizeof(t210b01_emc_burst_regs) / sizeof(uint32_t)];
|
||||
};
|
||||
union {
|
||||
t210_emc_trim_regs trim_regs;
|
||||
uint32_t trim_regs_arr[sizeof(t210_emc_trim_regs) / sizeof(uint32_t)];
|
||||
};
|
||||
union {
|
||||
t210_emc_trim_perch_regs trim_perch_regs;
|
||||
uint32_t trim_perch_regs_arr[sizeof(t210_emc_trim_perch_regs) / sizeof(uint32_t)];
|
||||
};
|
||||
union {
|
||||
t210_emc_vref_perch_regs vref_perch_regs;
|
||||
uint32_t vref_perch_regs_arr[sizeof(t210_emc_vref_perch_regs) / sizeof(uint32_t)];
|
||||
};
|
||||
t210_emc_dram_timings dram_timings;
|
||||
uint32_t zq_op_cc_long_zcal;
|
||||
uint32_t zq_op_cc_short_zcal;
|
||||
uint32_t zcal_wait_time_ps_cc_long_zcal;
|
||||
uint32_t zcal_wait_time_ps_cc_short_zcal;
|
||||
uint32_t tZQCAL_lpddr4;
|
||||
uint32_t zqcal_before_cc_cutoff;
|
||||
uint32_t opt_cc_short_zcal;
|
||||
uint32_t opt_short_zcal;
|
||||
uint32_t opt_do_sw_qrst;
|
||||
uint32_t save_restore_clkstop_pd;
|
||||
uint32_t opt_E90;
|
||||
uint32_t cya_allow_ref_cc;
|
||||
uint32_t ref_b4_sref_en;
|
||||
uint32_t cya_issue_pc_ref;
|
||||
union {
|
||||
t210_emc_training_mod_regs training_mod_regs;
|
||||
uint32_t training_mod_regs_arr[sizeof(t210_emc_training_mod_regs) / sizeof(uint32_t)];
|
||||
};
|
||||
uint32_t save_restore_mod_regs[12];
|
||||
union {
|
||||
t210_emc_burst_mc_regs burst_mc_regs;
|
||||
uint32_t burst_mc_regs_arr[sizeof(t210_emc_burst_mc_regs) / sizeof(uint32_t)];
|
||||
};
|
||||
union {
|
||||
t210_emc_la_scale_regs la_scale_regs;
|
||||
uint32_t la_scale_regs_arr[sizeof(t210_emc_la_scale_regs) / sizeof(uint32_t)];
|
||||
};
|
||||
uint32_t unk_0;
|
||||
uint32_t vtt_vdda_ctrl_0;
|
||||
uint32_t src_clock_div;
|
||||
uint32_t vtt_vdda_dual_channel;
|
||||
uint32_t vtt_vdda_ctrl_1;
|
||||
uint32_t vtt_vdda_ctrl_2;
|
||||
uint32_t vtt_vdda_ctrl_3;
|
||||
uint32_t vtt_vdda_ctrl_4;
|
||||
uint32_t misc_cfg_0;
|
||||
uint32_t misc_cfg_1;
|
||||
uint32_t misc_cfg_2;
|
||||
uint32_t unk_1;
|
||||
uint32_t unk_2;
|
||||
uint32_t pipe_clk_delay;
|
||||
uint32_t clkchange_delay;
|
||||
uint32_t pllm_ss_cfg;
|
||||
uint32_t pllm_ss_ctrl1;
|
||||
uint32_t pllm_ss_ctrl2;
|
||||
uint32_t pllmb_ss_cfg;
|
||||
uint32_t pllmb_ss_ctrl1;
|
||||
uint32_t pllmb_ss_ctrl2;
|
||||
uint32_t pllmb_divm;
|
||||
uint32_t pllmb_divn;
|
||||
uint32_t pllmb_divp;
|
||||
uint32_t min_mrs_wait;
|
||||
uint32_t ramp_wait;
|
||||
uint32_t emc_mrw;
|
||||
uint32_t emc_mrw2;
|
||||
uint32_t emc_mrw3;
|
||||
uint32_t emc_mrw4;
|
||||
uint32_t emc_mrw9;
|
||||
uint32_t emc_mrs;
|
||||
uint32_t emc_emrs;
|
||||
uint32_t emc_emrs2;
|
||||
uint32_t emc_auto_cal_config;
|
||||
uint32_t emc_auto_cal_config2;
|
||||
uint32_t emc_auto_cal_config3;
|
||||
uint32_t emc_auto_cal_config4;
|
||||
uint32_t emc_auto_cal_config5;
|
||||
uint32_t emc_auto_cal_config6;
|
||||
uint32_t emc_auto_cal_config7;
|
||||
uint32_t emc_auto_cal_config8;
|
||||
uint32_t emc_cfg_2;
|
||||
uint32_t emc_sel_dpd_ctrl;
|
||||
uint32_t emc_fdpd_ctrl_cmd_no_ramp;
|
||||
uint32_t emc_tr_ctrl_0;
|
||||
uint32_t dll_clk_src;
|
||||
uint32_t clk_out_enb_x_0_clk_enb_emc_dll;
|
||||
uint32_t latency;
|
||||
uint32_t pllm_misc1_0_pllm_clamp_ph90;
|
||||
} tegra_b01_emc_timing_t;
|
||||
_Static_assert(sizeof(tegra_b01_emc_timing_t) == 0x10CC);
|
||||
|
||||
void train_dram_mariko(void);
|
||||
|
||||
#endif
|
||||
10551
fusee/fusee-mtc/src/mtc_tables_b01.h
Normal file
10551
fusee/fusee-mtc/src/mtc_tables_b01.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include "utils.h"
|
||||
@@ -31,18 +31,18 @@ __attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
|
||||
if (log_get_log_level() == SCREEN_LOG_LEVEL_NONE) {
|
||||
/* Zero-fill the framebuffer and register it as printk provider. */
|
||||
video_init((void *)0xC0000000);
|
||||
|
||||
|
||||
/* Override the global logging level. */
|
||||
log_set_log_level(SCREEN_LOG_LEVEL_ERROR);
|
||||
}
|
||||
|
||||
|
||||
/* Display fatal error. */
|
||||
va_list args;
|
||||
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
|
||||
va_start(args, fmt);
|
||||
vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
|
||||
while (true) {
|
||||
/* Lock. */
|
||||
}
|
||||
|
||||
@@ -158,7 +158,12 @@ static void config_se_brom(void) {
|
||||
|
||||
/* Bootrom part we skipped. */
|
||||
uint32_t sbk[4] = {fuse_chip->FUSE_PRIVATE_KEY[0], fuse_chip->FUSE_PRIVATE_KEY[1], fuse_chip->FUSE_PRIVATE_KEY[2], fuse_chip->FUSE_PRIVATE_KEY[3]};
|
||||
set_aes_keyslot(0xE, sbk, 0x10);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (sbk[i] != 0xFFFFFFFF) {
|
||||
set_aes_keyslot(0xE, sbk, 0x10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock SBK from being read. */
|
||||
se->SE_CRYPTO_KEYTABLE_ACCESS[0xE] = 0x7E;
|
||||
@@ -247,7 +252,7 @@ void nx_hwinit(bool enable_log) {
|
||||
} else {
|
||||
uint8_t val = 0x40;
|
||||
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGBBC, &val, 1);
|
||||
val = 0x60;
|
||||
val = 0x58;
|
||||
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1);
|
||||
val = 0x38;
|
||||
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG0, &val, 1);
|
||||
|
||||
@@ -92,8 +92,8 @@ export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/ncm $(AMS)/stra
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||
$(AMS)/exosphere $(AMS)/exosphere/warmboot $(AMS)/exosphere/program/rebootstub \
|
||||
$(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/sept/sept-primary \
|
||||
$(AMS)/sept/sept-secondary $(AMS)/emummc $(AMS)/mesosphere $(AMS)/mesosphere/kernel_ldr $(KIPDIRS)
|
||||
$(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/emummc $(AMS)/mesosphere \
|
||||
$(KIPDIRS)
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
@@ -103,9 +103,7 @@ SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
KIPFILES := loader.kip ncm.kip pm.kip sm.kip ams_mitm.kip spl.kip boot.kip
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \
|
||||
exosphere.bin warmboot.bin rebootstub.bin thermosphere.bin splash_screen.bin \
|
||||
sept-primary.bin sept-secondary_00.enc sept-secondary_01.enc emummc.kip \
|
||||
sept-secondary_dev_00.enc sept-secondary_dev_01.enc mesosphere.bin kernel_ldr.bin \
|
||||
mariko_fatal.bin $(KIPFILES)
|
||||
emummc.kip mesosphere.bin mariko_fatal.bin $(KIPFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
@@ -133,7 +131,7 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
.PHONY: check_fusee_primary check_exosphere check_sept check_emummc check_thermosphere check_stratosphere check_libraries
|
||||
.PHONY: check_fusee_primary check_exosphere check_emummc check_thermosphere check_stratosphere check_libraries
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
@@ -144,9 +142,6 @@ check_fusee_primary:
|
||||
check_exosphere:
|
||||
@$(MAKE) -C $(AMS)/exosphere all
|
||||
|
||||
check_sept:
|
||||
@$(MAKE) -C $(AMS)/sept all
|
||||
|
||||
check_emummc:
|
||||
@$(MAKE) -C $(AMS)/emummc EMUMMCDIR=$(AMS)/emummc all
|
||||
|
||||
@@ -163,7 +158,7 @@ check_libraries:
|
||||
@$(MAKE) -C $(AMS)/libraries all
|
||||
|
||||
|
||||
$(BUILD): check_fusee_primary check_exosphere check_sept check_emummc check_thermosphere check_libraries check_stratosphere check_mesosphere
|
||||
$(BUILD): check_fusee_primary check_exosphere check_emummc check_thermosphere check_libraries check_stratosphere check_mesosphere
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
@@ -176,7 +171,6 @@ clean:
|
||||
@$(MAKE) -C $(AMS)/libraries clean
|
||||
@$(MAKE) -C $(AMS)/mesosphere clean
|
||||
@$(MAKE) -C $(AMS)/stratosphere clean
|
||||
@$(MAKE) -C $(AMS)/sept clean
|
||||
@$(MAKE) -C $(AMS)/emummc clean
|
||||
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
|
||||
|
||||
@@ -216,31 +210,6 @@ fusee_primary.bin.o fusee_primary_bin.h: fusee-primary.bin
|
||||
@echo $(notdir $<)
|
||||
@$(_bin2o)
|
||||
|
||||
sept_primary.bin.o sept_primary_bin.h: sept-primary.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(_bin2o)
|
||||
|
||||
sept_secondary_00.enc.o sept_secondary_00_enc.h: sept-secondary_00.enc
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(_bin2o)
|
||||
|
||||
sept_secondary_01.enc.o sept_secondary_01_enc.h: sept-secondary_01.enc
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(_bin2o)
|
||||
|
||||
sept_secondary_dev_00.enc.o sept_secondary_dev_00_enc.h: sept-secondary_dev_00.enc
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(_bin2o)
|
||||
|
||||
sept_secondary_dev_01.enc.o sept_secondary_dev_01_enc.h: sept-secondary_dev_01.enc
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(_bin2o)
|
||||
|
||||
%.bin.o %_bin.h: %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
|
||||
BIN
fusee/fusee-secondary/data/tsec_keygen.bin
Normal file
BIN
fusee/fusee-secondary/data/tsec_keygen.bin
Normal file
Binary file not shown.
@@ -244,12 +244,6 @@ SECTIONS
|
||||
PROVIDE(__pm_kip_size__ = pm_kip_end - pm_kip);
|
||||
PROVIDE(__rebootstub_bin_start__ = rebootstub_bin - __start__);
|
||||
PROVIDE(__rebootstub_bin_size__ = rebootstub_bin_end - rebootstub_bin);
|
||||
PROVIDE(__sept_primary_bin_start__ = sept_primary_bin - __start__);
|
||||
PROVIDE(__sept_primary_bin_size__ = sept_primary_bin_end - sept_primary_bin);
|
||||
PROVIDE(__sept_secondary_00_enc_start__ = sept_secondary_00_enc - __start__);
|
||||
PROVIDE(__sept_secondary_00_enc_size__ = sept_secondary_00_enc_end - sept_secondary_00_enc);
|
||||
PROVIDE(__sept_secondary_01_enc_start__ = sept_secondary_01_enc - __start__);
|
||||
PROVIDE(__sept_secondary_01_enc_size__ = sept_secondary_01_enc_end - sept_secondary_01_enc);
|
||||
PROVIDE(__sm_kip_start__ = sm_kip - __start__);
|
||||
PROVIDE(__sm_kip_size__ = sm_kip_end - sm_kip);
|
||||
PROVIDE(__spl_kip_start__ = spl_kip - __start__);
|
||||
@@ -266,4 +260,6 @@ SECTIONS
|
||||
PROVIDE(__mesosphere_bin_size__ = mesosphere_bin_end - mesosphere_bin);
|
||||
PROVIDE(__mariko_fatal_bin_start__ = mariko_fatal_bin - __start__);
|
||||
PROVIDE(__mariko_fatal_bin_size__ = mariko_fatal_bin_end - mariko_fatal_bin);
|
||||
PROVIDE(__tsec_keygen_bin_start__ = tsec_keygen_bin - __start__);
|
||||
PROVIDE(__tsec_keygen_bin_size__ = tsec_keygen_bin_end - tsec_keygen_bin);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FUSEE_CAR_H
|
||||
#define FUSEE_CAR_H
|
||||
|
||||
@@ -51,7 +51,7 @@ typedef enum {
|
||||
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
||||
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||
CARDEVICE_MSELECT = ((3 << 5) | 0x8),
|
||||
CARDEVICE_MSELECT = ((3 << 5) | 0x3),
|
||||
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
||||
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||
@@ -489,7 +489,7 @@ typedef struct {
|
||||
uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */
|
||||
uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */
|
||||
uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */
|
||||
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
|
||||
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
|
||||
} tegra_car_t;
|
||||
|
||||
static inline volatile tegra_car_t *car_get_regs(void) {
|
||||
|
||||
@@ -21,12 +21,6 @@
|
||||
#include "kernel_patches.h"
|
||||
#include "ips.h"
|
||||
|
||||
#define u8 uint8_t
|
||||
#define u32 uint32_t
|
||||
#include "kernel_ldr_bin.h"
|
||||
#undef u8
|
||||
#undef u32
|
||||
|
||||
#define MAKE_BRANCH(a, o) 0x14000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF)
|
||||
#define MAKE_NOP 0xD503201F
|
||||
|
||||
|
||||
@@ -26,19 +26,6 @@
|
||||
|
||||
#define AL16 ALIGN(16)
|
||||
|
||||
static const uint8_t AL16 keyblob_seeds[MASTERKEY_REVISION_MAX][0x10] = {
|
||||
{0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3}, /* Keyblob seed 00. */
|
||||
{0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC}, /* Keyblob seed 01. */
|
||||
{0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B}, /* Keyblob seed 02. */
|
||||
{0x2D, 0x1F, 0x48, 0x80, 0xED, 0xEC, 0xED, 0x3E, 0x3C, 0xF2, 0x48, 0xB5, 0x65, 0x7D, 0xF7, 0xBE}, /* Keyblob seed 03. */
|
||||
{0xBB, 0x5A, 0x01, 0xF9, 0x88, 0xAF, 0xF5, 0xFC, 0x6C, 0xFF, 0x07, 0x9E, 0x13, 0x3C, 0x39, 0x80}, /* Keyblob seed 04. */
|
||||
{0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0} /* Keyblob seed 05. */
|
||||
};
|
||||
|
||||
static const uint8_t AL16 keyblob_mac_seed[0x10] = {
|
||||
0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5
|
||||
};
|
||||
|
||||
static const uint8_t AL16 masterkey_seed[0x10] = {
|
||||
0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C
|
||||
};
|
||||
@@ -55,164 +42,51 @@ static const uint8_t AL16 masterkey_4x_seed[0x10] = {
|
||||
0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66
|
||||
};
|
||||
|
||||
/* TODO: Bother adding 8.1.0 here? We'll never call into here... */
|
||||
static const uint8_t AL16 new_master_kek_seeds[MASTERKEY_REVISION_700_800 - MASTERKEY_REVISION_600_610][0x10] = {
|
||||
{0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, /* MasterKek seed 06. */
|
||||
{0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, /* MasterKek seed 07. */
|
||||
static const uint8_t AL16 keyblob_seed_00[0x10] = {
|
||||
0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3
|
||||
};
|
||||
|
||||
static const uint8_t AL16 master_kek_seed_erista[0x10] = { /* TODO: Update on next change of keys. */
|
||||
0x84, 0x67, 0xB6, 0x7F, 0x13, 0x11, 0xAE, 0xE6, 0x58, 0x9B, 0x19, 0xAF, 0x13, 0x6C, 0x80, 0x7A /* Erista MasterKek seed 0B. */
|
||||
};
|
||||
|
||||
static const uint8_t AL16 master_devkey_seed_erista[0x10] = {
|
||||
0xAA, 0xFD, 0xBC, 0xBB, 0x25, 0xC3, 0xA4, 0xEF, 0xE3, 0xEE, 0x58, 0x53, 0xB7, 0xF8, 0xDD, 0xD6
|
||||
};
|
||||
|
||||
static const uint8_t AL16 master_kek_seed_mariko[0x10] = { /* TODO: Update on next change of keys. */
|
||||
0xE5, 0x41, 0xAC, 0xEC, 0xD1, 0xA7, 0xD1, 0xAB, 0xED, 0x03, 0x77, 0xF1, 0x27, 0xCA, 0xF8, 0xF1, /* Mariko MasterKek seed 0B. */
|
||||
};
|
||||
|
||||
static nx_dec_keyblob_t AL16 g_dec_keyblobs[32];
|
||||
|
||||
static int get_keyblob(nx_keyblob_t *dst, uint32_t revision, const nx_keyblob_t *keyblobs, uint32_t available_revision) {
|
||||
if (revision >= 0x20) {
|
||||
return -1;
|
||||
/* TODO: what should we do? */
|
||||
}
|
||||
|
||||
if (keyblobs != NULL) {
|
||||
*dst = keyblobs[revision];
|
||||
} else {
|
||||
return -1;
|
||||
/* TODO: what should we do? */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool safe_memcmp(uint8_t *a, uint8_t *b, size_t sz) {
|
||||
uint8_t different = 0;
|
||||
for (unsigned int i = 0; i < sz; i++) {
|
||||
different |= a[i] ^ b[i];
|
||||
}
|
||||
return different != 0;
|
||||
}
|
||||
|
||||
static int decrypt_keyblob(const nx_keyblob_t *keyblobs, uint32_t revision, uint32_t available_revision) {
|
||||
nx_keyblob_t AL16 keyblob;
|
||||
uint8_t AL16 work_buffer[0x10];
|
||||
unsigned int keyslot = revision == MASTERKEY_REVISION_100_230 ? 0xF : KEYSLOT_SWITCH_TEMPKEY;
|
||||
|
||||
if (get_keyblob(&keyblob, revision, keyblobs, available_revision) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
se_aes_ecb_decrypt_block(0xD, work_buffer, 0x10, keyblob_seeds[revision], 0x10);
|
||||
decrypt_data_into_keyslot(keyslot, 0xE, work_buffer, 0x10);
|
||||
decrypt_data_into_keyslot(0xB, keyslot, keyblob_mac_seed, 0x10);
|
||||
|
||||
/* Validate keyblob. */
|
||||
se_compute_aes_128_cmac(0xB, work_buffer, 0x10, keyblob.mac + sizeof(keyblob.mac), sizeof(keyblob) - sizeof(keyblob.mac));
|
||||
if (safe_memcmp(keyblob.mac, work_buffer, 0x10)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Decrypt keyblob. */
|
||||
se_aes_ctr_crypt(keyslot, &g_dec_keyblobs[revision], sizeof(g_dec_keyblobs[revision]), keyblob.data, sizeof(keyblob.data), keyblob.ctr, sizeof(keyblob.ctr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_package1_key(uint32_t revision) {
|
||||
if (revision > MASTERKEY_REVISION_600_610) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_aes_keyslot(0xB, g_dec_keyblobs[revision].package1_key, 0x10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Derive all Switch keys. */
|
||||
int derive_nx_keydata_erista(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_keys, unsigned int *out_keygen_type) {
|
||||
int derive_nx_keydata_erista(uint32_t target_firmware) {
|
||||
uint8_t AL16 work_buffer[0x10];
|
||||
uint8_t AL16 zeroes[0x10] = {0};
|
||||
|
||||
/* Initialize keygen type. */
|
||||
*out_keygen_type = 0;
|
||||
/* Get whether we're using dev keys. */
|
||||
const bool is_retail = fuse_get_hardware_state() != 0;
|
||||
|
||||
/* TODO: Set keyslot flags properly in preparation of derivation. */
|
||||
set_aes_keyslot_flags(0xE, 0x15);
|
||||
set_aes_keyslot_flags(0xD, 0x15);
|
||||
/* Derive Keyblob Key 00. */
|
||||
se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, keyblob_seed_00, 0x10);
|
||||
decrypt_data_into_keyslot(0xF, 0xE, work_buffer, 0x10);
|
||||
|
||||
/* Set the TSEC key. */
|
||||
set_aes_keyslot(0xD, tsec_key, 0x10);
|
||||
/* Derive master kek. */
|
||||
decrypt_data_into_keyslot(0xE, is_retail ? 0xD : 0xB, master_kek_seed_erista, 0x10);
|
||||
|
||||
/* Decrypt all keyblobs, setting keyslot 0xF correctly. */
|
||||
for (unsigned int rev = 0; rev <= MASTERKEY_REVISION_600_610; rev++) {
|
||||
int ret = decrypt_keyblob(keyblobs, rev, available_revision);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/* Derive master key, device master key. */
|
||||
decrypt_data_into_keyslot(0xD, 0xE, masterkey_seed, 0x10);
|
||||
decrypt_data_into_keyslot(0xE, 0xE, masterkey_4x_seed, 0x10);
|
||||
|
||||
/* Do 6.2.0+ keygen. */
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
|
||||
uint32_t desired_keyblob;
|
||||
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
|
||||
/* NOTE: We load in the current key for all >= 8.1.0 firmwares to reduce sept binaries. */
|
||||
desired_keyblob = MASTERKEY_REVISION_C10_CURRENT;
|
||||
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
|
||||
desired_keyblob = MASTERKEY_REVISION_700_800;
|
||||
} else {
|
||||
desired_keyblob = MASTERKEY_REVISION_620;
|
||||
}
|
||||
|
||||
/* Try emulation result. */
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
void *tsec_root_key = (void *)((uintptr_t)tsec_root_keys + 0x10 * (rev - MASTERKEY_REVISION_620));
|
||||
if (memcmp(tsec_root_key, zeroes, 0x10) != 0) {
|
||||
/* We got a valid key from emulation. */
|
||||
set_aes_keyslot(0xD, tsec_root_key, 0x10);
|
||||
se_aes_ecb_decrypt_block(0xD, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620], 0x10);
|
||||
memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(g_dec_keyblobs[desired_keyblob].master_kek, zeroes, 0x10) == 0) {
|
||||
/* Try reading the keys from a file. */
|
||||
const char *keyfile = fuse_get_hardware_state() != 0 ? "atmosphere/prod.keys" : "atmosphere/dev.keys";
|
||||
FILE *extkey_file = fopen(keyfile, "r");
|
||||
AL16 fusee_extkeys_t extkeys = {0};
|
||||
if (extkey_file == NULL) {
|
||||
fatal_error("Error: failed to read %s, needed for 6.2.0+ key derivation!", keyfile);
|
||||
}
|
||||
extkeys_initialize_keyset(&extkeys, extkey_file);
|
||||
fclose(extkey_file);
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
if (memcmp(extkeys.tsec_root_keys[rev - MASTERKEY_REVISION_620], zeroes, 0x10) != 0) {
|
||||
set_aes_keyslot(0xD, extkeys.tsec_root_keys[rev - MASTERKEY_REVISION_620], 0x10);
|
||||
se_aes_ecb_decrypt_block(0xD, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620], 0x10);
|
||||
memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10);
|
||||
} else {
|
||||
memcpy(g_dec_keyblobs[rev].master_kek, extkeys.master_keks[rev], 0x10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(g_dec_keyblobs[available_revision].master_kek, zeroes, 0x10) == 0) {
|
||||
fatal_error("Error: failed to derive master_kek_%02x!", available_revision);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the SBK. */
|
||||
clear_aes_keyslot(0xE);
|
||||
|
||||
/* Get needed data. */
|
||||
set_aes_keyslot(0xD, g_dec_keyblobs[available_revision].master_kek, 0x10);
|
||||
|
||||
/* Also set the Package1 key for the revision that is stored on the eMMC boot0 partition. */
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
|
||||
load_package1_key(available_revision);
|
||||
}
|
||||
|
||||
/* Derive keys for Exosphere, lock critical keyslots. */
|
||||
/* Derive device keys. */
|
||||
decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10);
|
||||
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
|
||||
decrypt_data_into_keyslot(0xC, 0xD, masterkey_4x_seed, 0x10);
|
||||
decrypt_data_into_keyslot(0xD, 0xD, masterkey_seed, 0x10);
|
||||
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
|
||||
|
||||
/* Derive firmware specific device key. */
|
||||
se_aes_ecb_decrypt_block(0xA, work_buffer, 0x10, master_devkey_seed_erista, 0x10);
|
||||
decrypt_data_into_keyslot(0xC, 0xE, work_buffer, 0x10);
|
||||
|
||||
/* Clear keyslots 0xB/0xE. */
|
||||
clear_aes_keyslot(0xB);
|
||||
clear_aes_keyslot(0xE);
|
||||
|
||||
/* Setup master key revision, derive older master keys for use. */
|
||||
return mkey_detect_revision(fuse_get_hardware_state() != 0);
|
||||
|
||||
@@ -27,29 +27,8 @@ typedef enum BisPartition {
|
||||
BisPartition_UserSystem = 2,
|
||||
} BisPartition;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
uint8_t keys[9][0x10];
|
||||
struct {
|
||||
uint8_t master_kek[0x10];
|
||||
uint8_t _keys[7][0x10];
|
||||
uint8_t package1_key[0x10];
|
||||
};
|
||||
};
|
||||
} nx_dec_keyblob_t;
|
||||
|
||||
typedef struct nx_keyblob_t {
|
||||
uint8_t mac[0x10];
|
||||
uint8_t ctr[0x10];
|
||||
union {
|
||||
uint8_t data[0x90];
|
||||
nx_dec_keyblob_t dec_blob;
|
||||
};
|
||||
} nx_keyblob_t;
|
||||
|
||||
int derive_nx_keydata_erista(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_key, unsigned int *out_keygen_type);
|
||||
int derive_nx_keydata_erista(uint32_t target_firmware);
|
||||
int derive_nx_keydata_mariko(uint32_t target_firmware);
|
||||
int load_package1_key(uint32_t revision);
|
||||
void derive_bis_key(void *dst, BisPartition partition_id, uint32_t target_firmware);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -185,8 +185,8 @@ void derive_new_device_keys(bool is_retail, unsigned int keygen_keyslot, unsigne
|
||||
if (relative_revision > mkey_get_revision()) {
|
||||
break;
|
||||
} else if (relative_revision == mkey_get_revision()) {
|
||||
/* On 7.0.0 erista, sept will have derived this key for us already. */
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0 || is_mariko) {
|
||||
/* On Erista, this will already be derived. */
|
||||
if (is_mariko) {
|
||||
decrypt_data_into_keyslot(is_mariko ? KEYSLOT_SWITCH_DEVICEKEY_MARIKO : KEYSLOT_SWITCH_DEVICEKEY, KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
#include "masterkey.h"
|
||||
#include "package1.h"
|
||||
#include "package2.h"
|
||||
#include "smmu.h"
|
||||
#include "tsec.h"
|
||||
#include "lp0.h"
|
||||
#include "loader.h"
|
||||
@@ -59,11 +58,8 @@
|
||||
#include "exosphere_bin.h"
|
||||
#include "mariko_fatal_bin.h"
|
||||
#include "mesosphere_bin.h"
|
||||
#include "sept_secondary_00_enc.h"
|
||||
#include "sept_secondary_01_enc.h"
|
||||
#include "sept_secondary_dev_00_enc.h"
|
||||
#include "sept_secondary_dev_01_enc.h"
|
||||
#include "warmboot_bin.h"
|
||||
#include "tsec_keygen_bin.h"
|
||||
#include "emummc_kip.h"
|
||||
#undef u8
|
||||
#undef u32
|
||||
@@ -724,18 +720,11 @@ static void nxboot_move_bootconfig() {
|
||||
free(bootconfig);
|
||||
}
|
||||
|
||||
static bool get_and_clear_has_run_sept(void) {
|
||||
bool has_run_sept = (MAKE_EMC_REG(EMC_SCRATCH0) & 0x80000000) != 0;
|
||||
MAKE_EMC_REG(EMC_SCRATCH0) &= ~0x80000000;
|
||||
return has_run_sept;
|
||||
}
|
||||
|
||||
static void get_mariko_warmboot_path(char *dst, size_t dst_size, uint32_t version) {
|
||||
snprintf(dst, dst_size, "warmboot_mariko/wb_%02" PRIx32 ".bin", version);
|
||||
}
|
||||
|
||||
/* This is the main function responsible for booting Horizon. */
|
||||
static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
|
||||
uint32_t nxboot_main(void) {
|
||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||
loader_ctx_t *loader_ctx = get_loader_ctx();
|
||||
@@ -745,8 +734,6 @@ uint32_t nxboot_main(void) {
|
||||
size_t package2_size;
|
||||
void *tsec_fw;
|
||||
size_t tsec_fw_size;
|
||||
const void *sept_secondary_enc = NULL;
|
||||
size_t sept_secondary_enc_size = 0;
|
||||
void *warmboot_fw;
|
||||
size_t warmboot_fw_size;
|
||||
void *warmboot_memaddr;
|
||||
@@ -756,7 +743,6 @@ uint32_t nxboot_main(void) {
|
||||
size_t mesosphere_size;
|
||||
void *emummc;
|
||||
size_t emummc_size;
|
||||
uint32_t available_revision;
|
||||
FILE *boot0, *pk2file;
|
||||
void *exosphere_memaddr;
|
||||
exo_emummc_config_t exo_emummc_cfg;
|
||||
@@ -844,7 +830,7 @@ uint32_t nxboot_main(void) {
|
||||
fatal_error("[NXBOOT] Couldn't parse boot0: %s!\n", strerror(errno));
|
||||
}
|
||||
} else {
|
||||
if (package1_read_and_parse_boot0_erista(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1) {
|
||||
if (package1_read_and_parse_boot0_erista(&package1loader, &package1loader_size, boot0) == -1) {
|
||||
fatal_error("[NXBOOT] Couldn't parse boot0: %s!\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
@@ -860,103 +846,26 @@ uint32_t nxboot_main(void) {
|
||||
}
|
||||
|
||||
/* Handle TSEC and Sept (Erista only). */
|
||||
uint8_t tsec_key[0x10] = {0};
|
||||
uint8_t tsec_root_keys[0x20][0x10] = {0};
|
||||
if (!is_mariko) {
|
||||
/* Read the TSEC firmware from a file, otherwise from PK1L. */
|
||||
if (loader_ctx->tsecfw_path[0] != '\0') {
|
||||
tsec_fw_size = get_file_size(loader_ctx->tsecfw_path);
|
||||
if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900 && tsec_fw_size != 0x3000 && tsec_fw_size != 0x3300)) {
|
||||
fatal_error("[NXBOOT] TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path);
|
||||
} else if (tsec_fw_size == 0) {
|
||||
fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path);
|
||||
}
|
||||
/* Use Atmosphere's tsec_keygen implementation. */
|
||||
tsec_fw_size = tsec_keygen_bin_size;
|
||||
tsec_fw = memalign(0x100, tsec_fw_size);
|
||||
|
||||
/* Allocate memory for the TSEC firmware. */
|
||||
tsec_fw = memalign(0x100, tsec_fw_size);
|
||||
|
||||
if (tsec_fw == NULL) {
|
||||
fatal_error("[NXBOOT] Out of memory!\n");
|
||||
}
|
||||
if (read_from_file(tsec_fw, tsec_fw_size, loader_ctx->tsecfw_path) != tsec_fw_size) {
|
||||
fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path);
|
||||
}
|
||||
|
||||
if (tsec_fw_size == 0x3000) {
|
||||
if (fuse_get_hardware_state() != 0) {
|
||||
sept_secondary_enc = sept_secondary_00_enc;
|
||||
sept_secondary_enc_size = sept_secondary_00_enc_size;
|
||||
} else {
|
||||
sept_secondary_enc = sept_secondary_dev_00_enc;
|
||||
sept_secondary_enc_size = sept_secondary_dev_00_enc_size;
|
||||
}
|
||||
} else if (tsec_fw_size == 0x3300) {
|
||||
if (fuse_get_hardware_state() != 0) {
|
||||
sept_secondary_enc = sept_secondary_01_enc;
|
||||
sept_secondary_enc_size = sept_secondary_01_enc_size;
|
||||
} else {
|
||||
sept_secondary_enc = sept_secondary_dev_01_enc;
|
||||
sept_secondary_enc_size = sept_secondary_dev_01_enc_size;
|
||||
}
|
||||
} else {
|
||||
fatal_error("[NXBOOT] Unable to identify sept revision to run.");
|
||||
}
|
||||
} else {
|
||||
if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) {
|
||||
fatal_error("[NXBOOT] Failed to read the TSEC firmware from Package1loader!\n");
|
||||
}
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
|
||||
if (fuse_get_hardware_state() != 0) {
|
||||
sept_secondary_enc = sept_secondary_01_enc;
|
||||
sept_secondary_enc_size = sept_secondary_01_enc_size;
|
||||
} else {
|
||||
sept_secondary_enc = sept_secondary_dev_01_enc;
|
||||
sept_secondary_enc_size = sept_secondary_dev_01_enc_size;
|
||||
}
|
||||
tsec_fw_size = 0x3300;
|
||||
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
|
||||
if (fuse_get_hardware_state() != 0) {
|
||||
sept_secondary_enc = sept_secondary_00_enc;
|
||||
sept_secondary_enc_size = sept_secondary_00_enc_size;
|
||||
} else {
|
||||
sept_secondary_enc = sept_secondary_dev_00_enc;
|
||||
sept_secondary_enc_size = sept_secondary_dev_00_enc_size;
|
||||
}
|
||||
tsec_fw_size = 0x3000;
|
||||
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
|
||||
tsec_fw_size = 0x2900;
|
||||
} else {
|
||||
tsec_fw_size = 0xF00;
|
||||
}
|
||||
if (tsec_fw == NULL) {
|
||||
fatal_error("[NXBOOT] Out of memory!\n");
|
||||
}
|
||||
|
||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Loaded firmware from eMMC...\n");
|
||||
memcpy(tsec_fw, tsec_keygen_bin, tsec_fw_size);
|
||||
|
||||
/* Get the TSEC keys. */
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
|
||||
/* Detect whether we need to run sept-secondary in order to derive keys. */
|
||||
if (!get_and_clear_has_run_sept()) {
|
||||
reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size);
|
||||
} else {
|
||||
if (mkey_detect_revision(fuse_get_hardware_state() != 0) != 0) {
|
||||
fatal_error("[NXBOOT] Sept derived incorrect keys!\n");
|
||||
}
|
||||
}
|
||||
get_and_clear_has_run_sept();
|
||||
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
|
||||
uint8_t tsec_keys[0x20] = {0};
|
||||
if (tsec_fw_size == 0) {
|
||||
fatal_error("[NXBOOT] Could not read the warmboot firmware from Package1!\n");
|
||||
}
|
||||
|
||||
/* Emulate the TSEC payload on 6.2.0+. */
|
||||
smmu_emulate_tsec((void *)tsec_keys, package1loader, package1loader_size, package1loader);
|
||||
|
||||
/* Copy back the keys. */
|
||||
memcpy((void *)tsec_key, (void *)tsec_keys, 0x10);
|
||||
memcpy((void *)tsec_root_keys, (void *)tsec_keys + 0x10, 0x10);
|
||||
} else {
|
||||
/* Run the TSEC payload and get the key. */
|
||||
if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) {
|
||||
fatal_error("[NXBOOT] Failed to get TSEC key!\n");
|
||||
}
|
||||
/* Get the TSEC keys into the security engine. */
|
||||
int tsec_res = tsec_run_fw(tsec_fw, tsec_fw_size);
|
||||
if (tsec_res != 0) {
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
fatal_error("[NXBOOT] Failed to run TSEC firmware %d %08x %08x!\n", tsec_res, tsec->TSEC_FALCON_MAILBOX0, tsec->TSEC_FALCON_MAILBOX1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -969,8 +878,8 @@ uint32_t nxboot_main(void) {
|
||||
if (derive_nx_keydata_mariko(target_firmware) != 0) {
|
||||
fatal_error("[NXBOOT] Mariko key derivation failed!\n");
|
||||
}
|
||||
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { /* If on 7.0.0+, sept has already derived keys for us (Erista only). */
|
||||
if (derive_nx_keydata_erista(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_keys, &keygen_type) != 0) {
|
||||
} else {
|
||||
if (derive_nx_keydata_erista(target_firmware) != 0) {
|
||||
fatal_error("[NXBOOT] Erista key derivation failed!\n");
|
||||
}
|
||||
}
|
||||
@@ -1230,9 +1139,6 @@ uint32_t nxboot_main(void) {
|
||||
|
||||
/* Clean up. */
|
||||
free(package1loader);
|
||||
if (loader_ctx->tsecfw_path[0] != '\0') {
|
||||
free(tsec_fw);
|
||||
}
|
||||
if (loader_ctx->warmboot_path[0] != '\0') {
|
||||
free(warmboot_fw);
|
||||
}
|
||||
|
||||
@@ -24,18 +24,10 @@
|
||||
#include "mc.h"
|
||||
#include "nxboot.h"
|
||||
#include "se.h"
|
||||
#include "smmu.h"
|
||||
#include "timers.h"
|
||||
#include "sysreg.h"
|
||||
|
||||
/* Determine the current SoC for Mariko specific code. */
|
||||
static bool is_soc_mariko() {
|
||||
return (fuse_get_soc_type() == 1);
|
||||
}
|
||||
|
||||
void nxboot_finish(uint32_t boot_memaddr) {
|
||||
bool is_mariko = is_soc_mariko();
|
||||
|
||||
/* Boot up Exosphère. */
|
||||
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0;
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X;
|
||||
@@ -43,26 +35,8 @@ void nxboot_finish(uint32_t boot_memaddr) {
|
||||
/* Terminate the display. */
|
||||
display_end();
|
||||
|
||||
if (is_mariko) {
|
||||
/* Boot CPU0. */
|
||||
cluster_boot_cpu0(boot_memaddr);
|
||||
} else {
|
||||
/* Check if SMMU emulation has been used. */
|
||||
uint32_t smmu_magic = *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC);
|
||||
if (smmu_magic == 0xDEADC0DE) {
|
||||
/* Clear the magic. */
|
||||
*(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC) = 0;
|
||||
|
||||
/* Pass the boot address to the already running payload. */
|
||||
*(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xF0) = boot_memaddr;
|
||||
|
||||
/* Wait a while. */
|
||||
mdelay(500);
|
||||
} else {
|
||||
/* Boot CPU0. */
|
||||
cluster_boot_cpu0(boot_memaddr);
|
||||
}
|
||||
}
|
||||
/* Boot CPU0. */
|
||||
cluster_boot_cpu0(boot_memaddr);
|
||||
|
||||
/* Wait for Exosphère to wake up. */
|
||||
while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) {
|
||||
|
||||
@@ -58,16 +58,12 @@ bool package1_is_custom_public_key(const void *bct, bool mariko) {
|
||||
}
|
||||
}
|
||||
|
||||
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0) {
|
||||
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, FILE *boot0) {
|
||||
nvboot_config_table *bct; /* Normal firmware BCT, primary. TODO: check? */
|
||||
nv_bootloader_info *pk1l_info; /* TODO: check? */
|
||||
size_t fpos, pk1l_offset;
|
||||
union {
|
||||
nx_keyblob_t keyblob;
|
||||
uint8_t sector[0x200];
|
||||
} d;
|
||||
|
||||
if (package1loader == NULL || package1loader_size == NULL || keyblobs == NULL || revision == NULL || boot0 == NULL) {
|
||||
if (package1loader == NULL || package1loader_size == NULL || boot0 == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@@ -105,7 +101,6 @@ int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1
|
||||
return -1;
|
||||
}
|
||||
|
||||
*revision = pk1l_info->version - 1;
|
||||
*package1loader_size = pk1l_info->length;
|
||||
|
||||
pk1l_offset = 0x4000 * pk1l_info->start_blk + 0x200 * pk1l_info->start_page;
|
||||
@@ -128,14 +123,6 @@ int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read the full keyblob area.*/
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
if (!fread(d.sector, 0x200, 1, boot0)) {
|
||||
return -1;
|
||||
}
|
||||
keyblobs[i] = d.keyblob;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -211,24 +198,6 @@ bool package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t pac
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size) {
|
||||
const uint8_t *crypt_hdr = (const uint8_t *)package1loader + 0x4000 - 0x20;
|
||||
if (package1loader_size < 0x4000) {
|
||||
return 0; /* Shouldn't happen, ever. */
|
||||
}
|
||||
|
||||
memcpy(ctr, crypt_hdr + 0x10, 0x10);
|
||||
(*package1) = (package1_header_t *)(crypt_hdr + 0x20);
|
||||
return *(uint32_t *)crypt_hdr;
|
||||
}
|
||||
|
||||
bool package1_decrypt(package1_header_t *package1, size_t package1_size, const uint8_t *ctr) {
|
||||
uint8_t __attribute__((aligned(16))) ctrbuf[16];
|
||||
memcpy(ctrbuf, ctr, 16);
|
||||
se_aes_ctr_crypt(0xB, package1, package1_size, package1, package1_size, ctrbuf, 16);
|
||||
return memcmp(package1->magic, "PK11", 4) == 0;
|
||||
}
|
||||
|
||||
void *package1_get_warmboot_fw(const package1_header_t *package1) {
|
||||
/*
|
||||
The layout of pk1 changes between versions.
|
||||
|
||||
@@ -59,14 +59,10 @@ typedef struct {
|
||||
|
||||
bool package1_is_custom_public_key(const void *bct, bool mariko);
|
||||
|
||||
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0);
|
||||
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, FILE *boot0);
|
||||
int package1_read_and_parse_boot0_mariko(void **package1loader, size_t *package1loader_size, FILE *boot0);
|
||||
|
||||
bool package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size);
|
||||
size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size);
|
||||
|
||||
/* Must be aligned to 16 bytes. */
|
||||
bool package1_decrypt(package1_header_t *package1, size_t package1_size, const uint8_t *ctr);
|
||||
void *package1_get_warmboot_fw(const package1_header_t *package1);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "smmu.h"
|
||||
#include "cluster.h"
|
||||
#include "mc.h"
|
||||
#include "timers.h"
|
||||
#include "tsec.h"
|
||||
|
||||
#define TSEC_KEYGEN_MAX_RETRIES 25
|
||||
|
||||
void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR;
|
||||
|
||||
static void safe_memcpy(void *dst, void *src, uint32_t sz) {
|
||||
/* Aligned memcpy to read MMIO correctly. */
|
||||
for (size_t i = 0; i < (sz/4); i++) {
|
||||
((volatile uint32_t *)dst)[i] = ((volatile uint32_t *)src)[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void smmu_flush_ppsb() {
|
||||
/* Read-back barrier for interactions between the PPSB and the APB/AHB. */
|
||||
(void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG);
|
||||
}
|
||||
|
||||
static void smmu_flush_regs() {
|
||||
/* Flush all TLB and PTC entries. */
|
||||
MAKE_MC_REG(MC_SMMU_PTC_FLUSH) = 0;
|
||||
smmu_flush_ppsb();
|
||||
MAKE_MC_REG(MC_SMMU_TLB_FLUSH) = 0;
|
||||
smmu_flush_ppsb();
|
||||
}
|
||||
|
||||
static void *smmu_alloc_page(uint32_t page_count) {
|
||||
void *cur_page = smmu_heap;
|
||||
smmu_heap += (page_count * SMMU_PAGE_SIZE);
|
||||
memset(cur_page, 0, (page_count * SMMU_PAGE_SIZE));
|
||||
return cur_page;
|
||||
}
|
||||
|
||||
static uint32_t *smmu_alloc_pdir() {
|
||||
uint32_t *pdir = (uint32_t *)smmu_alloc_page(1);
|
||||
for (int pdn = 0; pdn < SMMU_PDIR_COUNT; pdn++) {
|
||||
pdir[pdn] = _PDE_VACANT(pdn);
|
||||
}
|
||||
return pdir;
|
||||
}
|
||||
|
||||
static uint32_t *smmu_locate_pte(uint32_t *pdir_page, uint32_t iova) {
|
||||
uint32_t ptn = SMMU_ADDR_TO_PFN(iova);
|
||||
uint32_t pdn = SMMU_ADDR_TO_PDN(iova);
|
||||
uint32_t *pdir = pdir_page;
|
||||
uint32_t *ptbl;
|
||||
|
||||
if (pdir[pdn] != _PDE_VACANT(pdn)) {
|
||||
/* Mapped entry table already exists. */
|
||||
ptbl = (uint32_t *)SMMU_EX_PTBL_PAGE(pdir[pdn]);
|
||||
} else {
|
||||
/* Allocate page table. */
|
||||
ptbl = (uint32_t *)smmu_alloc_page(1);
|
||||
uint32_t addr = SMMU_PDN_TO_ADDR(pdn);
|
||||
for (int pn = 0; pn < SMMU_PTBL_COUNT; pn++, addr += SMMU_PAGE_SIZE) {
|
||||
ptbl[pn] = _PTE_VACANT(addr);
|
||||
}
|
||||
pdir[pdn] = SMMU_MK_PDE((uint32_t)ptbl, _PDE_ATTR | _PDE_NEXT);
|
||||
smmu_flush_regs();
|
||||
}
|
||||
|
||||
return &ptbl[ptn % SMMU_PTBL_COUNT];
|
||||
}
|
||||
|
||||
static void smmu_map(uint32_t *pdir, uint32_t addr, uint32_t ptpage, int pcount, uint32_t pte_attr) {
|
||||
for (int i = 0; i < pcount; i++) {
|
||||
uint32_t *pte = smmu_locate_pte(pdir, addr);
|
||||
*pte = SMMU_PFN_TO_PTE(SMMU_ADDR_TO_PFN(ptpage), pte_attr);
|
||||
addr += SMMU_PAGE_SIZE;
|
||||
ptpage += SMMU_PAGE_SIZE;
|
||||
}
|
||||
smmu_flush_regs();
|
||||
}
|
||||
|
||||
static uint32_t *smmu_setup_tsec_as(uint32_t asid) {
|
||||
/* Allocate the page directory. */
|
||||
uint32_t *pdir_page = smmu_alloc_pdir();
|
||||
|
||||
/* Set the PTB ASID and point it to the PDIR. */
|
||||
MAKE_MC_REG(MC_SMMU_PTB_ASID) = asid;
|
||||
MAKE_MC_REG(MC_SMMU_PTB_DATA) = SMMU_MK_PDIR((uint32_t)pdir_page, _PDIR_ATTR);
|
||||
smmu_flush_ppsb();
|
||||
|
||||
/* Assign the ASID to TSEC. */
|
||||
MAKE_MC_REG(MC_SMMU_TSEC_ASID) = SMMU_ASID_ENABLE((asid << 24) | (asid << 16) | (asid << 8) | asid);
|
||||
smmu_flush_ppsb();
|
||||
|
||||
return pdir_page;
|
||||
}
|
||||
|
||||
static void smmu_clear_tsec_as(uint32_t asid) {
|
||||
/* Set the PTB ASID and clear it's data. */
|
||||
MAKE_MC_REG(MC_SMMU_PTB_ASID) = asid;
|
||||
MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0;
|
||||
|
||||
/* Clear the ASID from TSEC. */
|
||||
MAKE_MC_REG(MC_SMMU_TSEC_ASID) = SMMU_ASID_DISABLE;
|
||||
smmu_flush_ppsb();
|
||||
}
|
||||
|
||||
static void smmu_enable() {
|
||||
/* AARCH64 payload for enabling the SMMU. */
|
||||
/* Write 1 to MC_SMMU_CONFIG, read back and write the result to 0x40003F80. */
|
||||
/* This will leave the CPU waiting until 0x40003FF0 is set to Exosphère's address. */
|
||||
static const uint32_t aarch64_payload[20] = {
|
||||
0x52800020, 0x58000162, 0x58000183, 0xB9000040,
|
||||
0xB9400041, 0xB9000061, 0x58000142, 0xF9400040,
|
||||
0xF100001F, 0x54FFFFA0, 0xD61F0000, 0x00000000,
|
||||
0x70019010, 0x00000000, 0x40003F80, 0x00000000,
|
||||
0x40003FF0, 0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
/* Reset Translation Enable Registers. */
|
||||
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_0) = 0xFFFFFFFF;
|
||||
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_1) = 0xFFFFFFFF;
|
||||
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_2) = 0xFFFFFFFF;
|
||||
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_3) = 0xFFFFFFFF;
|
||||
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_4) = 0xFFFFFFFF;
|
||||
|
||||
/* Setup initial TLB and PTC configuration. */
|
||||
MAKE_MC_REG(MC_SMMU_PTB_ASID) = 0;
|
||||
MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0;
|
||||
MAKE_MC_REG(MC_SMMU_TLB_CONFIG) = 0x30000030;
|
||||
MAKE_MC_REG(MC_SMMU_PTC_CONFIG) = 0x2800003F;
|
||||
smmu_flush_regs();
|
||||
|
||||
/* Power on the CCPLEX to enable the SMMU globally (requires a secure write). */
|
||||
volatile uint32_t *aarch64_payload_res = (volatile uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0x80);
|
||||
memset((void *)SMMU_AARCH64_PAYLOAD_ADDR, 0, 0x100);
|
||||
memcpy((void *)SMMU_AARCH64_PAYLOAD_ADDR, aarch64_payload, 20 * 4);
|
||||
cluster_boot_cpu0(SMMU_AARCH64_PAYLOAD_ADDR);
|
||||
mdelay(500);
|
||||
if (*aarch64_payload_res != 1) {
|
||||
fatal_error("[SMMU]: Failed to enable SMMU!\n");
|
||||
}
|
||||
|
||||
/* Write magic for nxboot. */
|
||||
*(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC) = 0xDEADC0DE;
|
||||
|
||||
/* Flush TLB and PTC entries. */
|
||||
smmu_flush_regs();
|
||||
}
|
||||
|
||||
void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_size, void *package1_dec) {
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
|
||||
/* Backup IRAM to DRAM. */
|
||||
memcpy((void *)SMMU_IRAM_BACKUP_ADDR, (void *)0x40010000, 0x30000);
|
||||
|
||||
/* Copy package1 into IRAM. */
|
||||
memcpy((void *)0x40010000, package1, package1_size);
|
||||
|
||||
/* Setup TSEC's address space. */
|
||||
uint32_t *pdir = smmu_setup_tsec_as(1);
|
||||
|
||||
/* Allocate pages for MMIO and IRAM. */
|
||||
volatile uint32_t *car_page = smmu_alloc_page(1);
|
||||
volatile uint32_t *fuse_page = smmu_alloc_page(1);
|
||||
volatile uint32_t *pmc_page = smmu_alloc_page(1);
|
||||
volatile uint32_t *flow_page = smmu_alloc_page(1);
|
||||
volatile uint32_t *se_page = smmu_alloc_page(1);
|
||||
volatile uint32_t *mc_page = smmu_alloc_page(1);
|
||||
volatile uint32_t *iram_pages = smmu_alloc_page(48);
|
||||
volatile uint32_t *expv_page = smmu_alloc_page(1);
|
||||
|
||||
/* Map all necessary pages. */
|
||||
smmu_map(pdir, 0x60006000, (uint32_t)car_page, 1, _READABLE | _WRITABLE | _NONSECURE);
|
||||
smmu_map(pdir, 0x7000F000, (uint32_t)fuse_page, 1, _READABLE | _NONSECURE);
|
||||
smmu_map(pdir, 0x7000E000, (uint32_t)pmc_page, 1, _READABLE | _NONSECURE);
|
||||
smmu_map(pdir, 0x60007000, (uint32_t)flow_page, 1, _WRITABLE | _NONSECURE);
|
||||
smmu_map(pdir, 0x70012000, (uint32_t)se_page, 1, _READABLE | _WRITABLE | _NONSECURE);
|
||||
smmu_map(pdir, 0x70019000, (uint32_t)mc_page, 1, _READABLE | _NONSECURE);
|
||||
smmu_map(pdir, 0x40010000, (uint32_t)iram_pages, 48, _READABLE | _WRITABLE | _NONSECURE);
|
||||
smmu_map(pdir, 0x6000F000, (uint32_t)expv_page, 1, _READABLE | _WRITABLE | _NONSECURE);
|
||||
|
||||
/* Enable the SMMU. */
|
||||
smmu_enable();
|
||||
|
||||
/* Loop retrying TSEC firmware execution, in case we lose the SE keydata race. */
|
||||
uint32_t key_buf[0x20/4] = {0};
|
||||
unsigned int retries = 0;
|
||||
while (true) {
|
||||
if (retries++ > TSEC_KEYGEN_MAX_RETRIES) {
|
||||
fatal_error("[SMMU] TSEC key generation race was lost too many times!");
|
||||
}
|
||||
|
||||
/* Load the TSEC firmware from IRAM. */
|
||||
if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) {
|
||||
fatal_error("[SMMU]: Failed to load TSEC firmware!\n");
|
||||
}
|
||||
|
||||
/* Disable the aperture since it has precedence over the SMMU. */
|
||||
mc_disable_ahb_redirect();
|
||||
|
||||
/* Clear all pages. */
|
||||
memset((void *)car_page, 0, SMMU_PAGE_SIZE);
|
||||
memset((void *)fuse_page, 0, SMMU_PAGE_SIZE);
|
||||
memset((void *)pmc_page, 0, SMMU_PAGE_SIZE);
|
||||
memset((void *)flow_page, 0, SMMU_PAGE_SIZE);
|
||||
memset((void *)se_page, 0, SMMU_PAGE_SIZE);
|
||||
memset((void *)mc_page, 0, SMMU_PAGE_SIZE);
|
||||
memset((void *)iram_pages, 0, 48 * SMMU_PAGE_SIZE);
|
||||
memset((void *)expv_page, 0, SMMU_PAGE_SIZE);
|
||||
|
||||
/* Copy CAR, MC and FUSE. */
|
||||
safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000);
|
||||
safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000);
|
||||
safe_memcpy((void *)&fuse_page[0x800/4], (void *)0x7000F800, 0x400);
|
||||
|
||||
/* Copy IRAM. */
|
||||
memcpy((void *)iram_pages, (void *)0x40010000, 0x30000);
|
||||
|
||||
/* TSEC wants CLK_RST_CONTROLLER_CLK_SOURCE_TSEC_0 to be equal to 2. */
|
||||
car_page[0x1F4/4] = 2;
|
||||
|
||||
/* TSEC wants the aperture fully open. */
|
||||
mc_page[0x65C/4] = 0;
|
||||
mc_page[0x660/4] = 0x80000000;
|
||||
|
||||
/* Run the TSEC firmware. */
|
||||
tsec_run_fw();
|
||||
|
||||
/* Extract the keys from SE. */
|
||||
volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320);
|
||||
uint32_t old_key_data = *key_data;
|
||||
uint32_t buf_counter = 0;
|
||||
while (!(tsec->TSEC_FALCON_CPUCTL & 0x10)) {
|
||||
const uint32_t new_key_data = *key_data;
|
||||
if (new_key_data != old_key_data) {
|
||||
old_key_data = new_key_data;
|
||||
key_buf[buf_counter] = new_key_data;
|
||||
buf_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable back the aperture. */
|
||||
mc_enable_ahb_redirect();
|
||||
|
||||
if (buf_counter == 8) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the TSEC firmware wrote over the exception vectors. */
|
||||
volatile uint32_t *tsec_done_check = (volatile uint32_t *)((void *)expv_page + 0x200);
|
||||
if (!(*tsec_done_check)) {
|
||||
fatal_error("[SMMU]: Failed to emulate the TSEC firmware!\n");
|
||||
}
|
||||
|
||||
/* Copy back the extracted keys. */
|
||||
memcpy((void *)tsec_keys, (void *)key_buf, 0x20);
|
||||
|
||||
/* Manually disable TSEC clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
/* Clear TSEC's address space. */
|
||||
smmu_clear_tsec_as(1);
|
||||
|
||||
/* Return the decrypted package1 from emulated IRAM. */
|
||||
memcpy(package1_dec, (void *)iram_pages, package1_size);
|
||||
|
||||
/* Restore IRAM from DRAM. */
|
||||
memcpy((void *)0x40010000, (void *)SMMU_IRAM_BACKUP_ADDR, 0x30000);
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FUSEE_SMMU_H_
|
||||
#define FUSEE_SMMU_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define SMMU_HEAP_BASE_ADDR 0x81000000
|
||||
#define SMMU_IRAM_BACKUP_ADDR 0x82000000
|
||||
#define SMMU_AARCH64_PAYLOAD_ADDR 0x40003F00
|
||||
|
||||
#define SMMU_PAGE_SHIFT 12
|
||||
#define SMMU_PAGE_SIZE (1 << SMMU_PAGE_SHIFT)
|
||||
#define SMMU_PDIR_COUNT 1024
|
||||
#define SMMU_PDIR_SIZE (sizeof(uint32_t) * SMMU_PDIR_COUNT)
|
||||
#define SMMU_PTBL_COUNT 1024
|
||||
#define SMMU_PTBL_SIZE (sizeof(uint32_t) * SMMU_PTBL_COUNT)
|
||||
#define SMMU_PDIR_SHIFT 12
|
||||
#define SMMU_PDE_SHIFT 12
|
||||
#define SMMU_PTE_SHIFT 12
|
||||
#define SMMU_PFN_MASK 0x000fffff
|
||||
#define SMMU_PDE_NEXT_SHIFT 28
|
||||
#define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
|
||||
#define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
|
||||
#define SMMU_PDN_TO_ADDR(pdn) ((pdn) << 22)
|
||||
#define _READABLE (1 << 31)
|
||||
#define _WRITABLE (1 << 30)
|
||||
#define _NONSECURE (1 << 29)
|
||||
#define _PDE_NEXT (1 << SMMU_PDE_NEXT_SHIFT)
|
||||
#define _MASK_ATTR (_READABLE | _WRITABLE | _NONSECURE)
|
||||
#define _PDIR_ATTR (_READABLE | _WRITABLE | _NONSECURE)
|
||||
#define _PDE_ATTR (_READABLE | _WRITABLE | _NONSECURE)
|
||||
#define _PDE_ATTR_N (_PDE_ATTR | _PDE_NEXT)
|
||||
#define _PDE_VACANT(pdn) (((pdn) << 10) | _PDE_ATTR)
|
||||
#define _PTE_ATTR (_READABLE | _WRITABLE | _NONSECURE)
|
||||
#define _PTE_VACANT(addr) (((addr) >> SMMU_PAGE_SHIFT) | _PTE_ATTR)
|
||||
#define SMMU_MK_PDIR(page, attr) (((page) >> SMMU_PDIR_SHIFT) | (attr))
|
||||
#define SMMU_MK_PDE(page, attr) (((page) >> SMMU_PDE_SHIFT) | (attr))
|
||||
#define SMMU_EX_PTBL_PAGE(pde) (((pde) & SMMU_PFN_MASK) << SMMU_PDIR_SHIFT)
|
||||
#define SMMU_PFN_TO_PTE(pfn, attr) ((pfn) | (attr))
|
||||
#define SMMU_ASID_ENABLE(asid) ((asid) | (1 << 31))
|
||||
#define SMMU_ASID_DISABLE 0
|
||||
#define SMMU_ASID_ASID(n) ((n) & ~SMMU_ASID_ENABLE(0))
|
||||
|
||||
void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_size, void *package1_dec);
|
||||
|
||||
#endif
|
||||
@@ -108,6 +108,7 @@ _metadata:
|
||||
#define CONTENT_TYPE_KLD 9
|
||||
#define CONTENT_TYPE_KRN 10
|
||||
#define CONTENT_TYPE_EXF 11
|
||||
#define CONTENT_TYPE_TKG 12
|
||||
|
||||
#define CONTENT_FLAG_NONE (0 << 0)
|
||||
|
||||
@@ -213,39 +214,6 @@ _content_headers:
|
||||
.asciz "rebootstub"
|
||||
.align 5
|
||||
|
||||
/* sept_primary content header */
|
||||
.word __sept_primary_bin_start__
|
||||
.word __sept_primary_bin_size__
|
||||
.byte CONTENT_TYPE_SP1
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.word 0xCCCCCCCC
|
||||
.asciz "sept_primary"
|
||||
.align 5
|
||||
|
||||
/* sept_secondary 00 content header */
|
||||
.word __sept_secondary_00_enc_start__
|
||||
.word __sept_secondary_00_enc_size__
|
||||
.byte CONTENT_TYPE_SP2
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.word 0xCCCCCCCC
|
||||
.asciz "septsecondary00"
|
||||
.align 5
|
||||
|
||||
/* sept_secondary 01 content header */
|
||||
.word __sept_secondary_01_enc_start__
|
||||
.word __sept_secondary_01_enc_size__
|
||||
.byte CONTENT_TYPE_SP2
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.word 0xCCCCCCCC
|
||||
.asciz "septsecondary01"
|
||||
.align 5
|
||||
|
||||
/* sm content header */
|
||||
.word __sm_kip_start__
|
||||
.word __sm_kip_size__
|
||||
@@ -301,6 +269,17 @@ _content_headers:
|
||||
.asciz "exosphere_fatal"
|
||||
.align 5
|
||||
|
||||
/* tsec_keygen content header */
|
||||
.word __tsec_keygen_bin_start__
|
||||
.word __tsec_keygen_bin_size__
|
||||
.byte CONTENT_TYPE_TKG
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.byte CONTENT_FLAG_NONE
|
||||
.word 0xCCCCCCCC
|
||||
.asciz "tsec_keygen"
|
||||
.align 5
|
||||
|
||||
_content_headers_end:
|
||||
|
||||
/* No need to include this in normal programs: */
|
||||
|
||||
@@ -14,15 +14,16 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "tsec.h"
|
||||
#include "di.h"
|
||||
#include "timers.h"
|
||||
#include "car.h"
|
||||
#include "mc.h"
|
||||
|
||||
static int tsec_dma_wait_idle()
|
||||
{
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
uint32_t timeout = (get_time_ms() + 10000);
|
||||
|
||||
while (!(tsec->TSEC_FALCON_DMATRFCMD & 2))
|
||||
@@ -30,13 +31,13 @@ static int tsec_dma_wait_idle()
|
||||
if (get_time_ms() > timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tsec_dma_phys_to_flcn(bool is_imem, uint32_t flcn_offset, uint32_t phys_offset)
|
||||
{
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
uint32_t cmd = 0;
|
||||
|
||||
if (!is_imem)
|
||||
@@ -52,16 +53,16 @@ static int tsec_dma_phys_to_flcn(bool is_imem, uint32_t flcn_offset, uint32_t ph
|
||||
}
|
||||
|
||||
static int tsec_kfuse_wait_ready()
|
||||
{
|
||||
{
|
||||
uint32_t timeout = (get_time_ms() + 10000);
|
||||
|
||||
|
||||
/* Wait for STATE_DONE. */
|
||||
while (!(KFUSE_STATE & 0x10000))
|
||||
{
|
||||
if (get_time_ms() > timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check for STATE_CRCPASS. */
|
||||
if (!(KFUSE_STATE & 0x20000))
|
||||
return 0;
|
||||
@@ -91,19 +92,19 @@ void tsec_disable_clkrst()
|
||||
clkrst_disable(CARDEVICE_HOST1X);
|
||||
}
|
||||
|
||||
int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size)
|
||||
static int tsec_run_fw_impl(const void *tsec_fw, size_t tsec_fw_size)
|
||||
{
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
|
||||
/* Enable clocks. */
|
||||
tsec_enable_clkrst();
|
||||
|
||||
|
||||
/* Make sure KFUSE is ready. */
|
||||
if (!tsec_kfuse_wait_ready())
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -112,16 +113,16 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw
|
||||
tsec->TSEC_FALCON_IRQMSET = 0xFFF2;
|
||||
tsec->TSEC_FALCON_IRQDEST = 0xFFF0;
|
||||
tsec->TSEC_FALCON_ITFEN = 3;
|
||||
|
||||
|
||||
/* Make sure the DMA block is idle. */
|
||||
if (!tsec_dma_wait_idle())
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
/* Load firmware. */
|
||||
tsec->TSEC_FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8;
|
||||
for (uint32_t addr = 0; addr < tsec_fw_size; addr += 0x100)
|
||||
@@ -130,128 +131,71 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Write magic value to HOST1X scratch register. */
|
||||
MAKE_HOST1X_REG(0x3300) = 0x34C2E1DA;
|
||||
|
||||
|
||||
/* Execute firmware. */
|
||||
tsec->TSEC_FALCON_MAILBOX1 = 0;
|
||||
tsec->TSEC_FALCON_MAILBOX0 = rev;
|
||||
tsec->TSEC_FALCON_MAILBOX0 = 1;
|
||||
tsec->TSEC_FALCON_BOOTVEC = 0;
|
||||
tsec->TSEC_FALCON_CPUCTL = 2;
|
||||
|
||||
|
||||
/* Make sure the DMA block is idle. */
|
||||
if (!tsec_dma_wait_idle())
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
|
||||
return -4;
|
||||
}
|
||||
|
||||
uint32_t timeout = (get_time_ms() + 2000);
|
||||
while (!tsec->TSEC_FALCON_MAILBOX1)
|
||||
{
|
||||
if (get_time_ms() > timeout)
|
||||
{
|
||||
|
||||
uint32_t timeout = (get_time_ms() + 4000);
|
||||
while (!(tsec->TSEC_FALCON_CPUCTL & 0x10)) {
|
||||
if (get_time_ms() > timeout) {
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
|
||||
return -5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (tsec->TSEC_FALCON_MAILBOX1 != 0xB0B0B0B0)
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
|
||||
return -6;
|
||||
}
|
||||
|
||||
/* Clear magic value from HOST1X scratch register. */
|
||||
MAKE_HOST1X_REG(0x3300) = 0;
|
||||
|
||||
/* Fetch result from SOR1. */
|
||||
uint32_t tmp[0x4] = {0};
|
||||
tmp[0] = SOR1_DP_HDCP_BKSV_LSB;
|
||||
tmp[1] = SOR1_TMDS_HDCP_BKSV_LSB;
|
||||
tmp[2] = SOR1_TMDS_HDCP_CN_MSB;
|
||||
tmp[3] = SOR1_TMDS_HDCP_CN_LSB;
|
||||
|
||||
/* Clear SOR1 registers. */
|
||||
SOR1_DP_HDCP_BKSV_LSB = 0;
|
||||
SOR1_TMDS_HDCP_BKSV_LSB = 0;
|
||||
SOR1_TMDS_HDCP_CN_MSB = 0;
|
||||
SOR1_TMDS_HDCP_CN_LSB = 0;
|
||||
|
||||
/* Copy back the key. */
|
||||
memcpy(key, &tmp, 0x10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tsec_load_fw(const void *tsec_fw, size_t tsec_fw_size)
|
||||
{
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
int tsec_run_fw(const void *tsec_fw, size_t tsec_fw_size) {
|
||||
/* Ensure that the ahb redirect is enabled. */
|
||||
mc_enable_ahb_redirect();
|
||||
|
||||
/* Enable clocks. */
|
||||
tsec_enable_clkrst();
|
||||
|
||||
/* Make sure KFUSE is ready. */
|
||||
if (!tsec_kfuse_wait_ready())
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -1;
|
||||
}
|
||||
/* Get bom/tom */
|
||||
uint32_t bom = MAKE_MC_REG(MC_IRAM_BOM);
|
||||
uint32_t tom = MAKE_MC_REG(MC_IRAM_TOM);
|
||||
|
||||
/* Configure Falcon. */
|
||||
tsec->TSEC_FALCON_DMACTL = 0;
|
||||
tsec->TSEC_FALCON_IRQMSET = 0xFFF2;
|
||||
tsec->TSEC_FALCON_IRQDEST = 0xFFF0;
|
||||
tsec->TSEC_FALCON_ITFEN = 3;
|
||||
|
||||
/* Make sure the DMA block is idle. */
|
||||
if (!tsec_dma_wait_idle())
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Load firmware. */
|
||||
tsec->TSEC_FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8;
|
||||
for (uint32_t addr = 0; addr < tsec_fw_size; addr += 0x100)
|
||||
{
|
||||
if (!tsec_dma_phys_to_flcn(true, addr, addr))
|
||||
{
|
||||
/* Disable clocks. */
|
||||
tsec_disable_clkrst();
|
||||
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
/* Override the ahb redirect extents. */
|
||||
MAKE_MC_REG(MC_IRAM_BOM) = 0x40000000;
|
||||
MAKE_MC_REG(MC_IRAM_TOM) = 0x80000000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Run the fw. */
|
||||
int res = tsec_run_fw_impl(tsec_fw, tsec_fw_size);
|
||||
|
||||
void tsec_run_fw()
|
||||
{
|
||||
volatile tegra_tsec_t *tsec = tsec_get_regs();
|
||||
|
||||
/* Write magic value to HOST1X scratch register. */
|
||||
MAKE_HOST1X_REG(0x3300) = 0x34C2E1DA;
|
||||
|
||||
/* Execute firmware. */
|
||||
tsec->TSEC_FALCON_MAILBOX1 = 0;
|
||||
tsec->TSEC_FALCON_MAILBOX0 = 1;
|
||||
tsec->TSEC_FALCON_BOOTVEC = 0;
|
||||
tsec->TSEC_FALCON_CPUCTL = 2;
|
||||
/* Reset the ahb redirect extents. */
|
||||
MAKE_MC_REG(MC_IRAM_BOM) = bom;
|
||||
MAKE_MC_REG(MC_IRAM_TOM) = tom;
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FUSEE_TSEC_H_
|
||||
#define FUSEE_TSEC_H_
|
||||
|
||||
@@ -306,8 +306,7 @@ static inline volatile tegra_tsec_t *tsec_get_regs(void)
|
||||
|
||||
void tsec_enable_clkrst();
|
||||
void tsec_disable_clkrst();
|
||||
int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size);
|
||||
int tsec_load_fw(const void *tsec_fw, size_t tsec_fw_size);
|
||||
void tsec_run_fw();
|
||||
|
||||
int tsec_run_fw(const void *tsec_fw, size_t tsec_fw_size);
|
||||
|
||||
#endif
|
||||
@@ -34,7 +34,6 @@
|
||||
#define u8 uint8_t
|
||||
#define u32 uint32_t
|
||||
#include "fusee_primary_bin.h"
|
||||
#include "sept_primary_bin.h"
|
||||
#include "rebootstub_bin.h"
|
||||
#undef u8
|
||||
#undef u32
|
||||
@@ -131,42 +130,8 @@ __attribute__((noreturn)) void reboot_to_fusee_primary(void) {
|
||||
reboot_to_payload();
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void reboot_to_sept(const void *tsec_fw, size_t tsec_fw_length, const void *stage2, size_t stage2_size) {
|
||||
if (is_soc_mariko()) {
|
||||
/* Reboot to sept isn't possible on mariko, so just do normal reboot. */
|
||||
shutdown_system(true);
|
||||
} else {
|
||||
/* Copy tsec firmware. */
|
||||
for (size_t i = 0; i < tsec_fw_length; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x40010F00, i, read32le(tsec_fw, i));
|
||||
}
|
||||
MAKE_REG32(0x40010EFC) = tsec_fw_length;
|
||||
|
||||
/* Copy stage 2. */
|
||||
for (size_t i = 0; i < stage2_size; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x40016FE0, i, read32le(stage2, i));
|
||||
}
|
||||
|
||||
/* Copy sept into IRAM low. */
|
||||
for (size_t i = 0; i < sept_primary_bin_size; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x4003F000, i, read32le(sept_primary_bin, i));
|
||||
}
|
||||
|
||||
/* Patch SDRAM init to perform an SVC immediately after second write */
|
||||
APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF;
|
||||
APBDEV_PMC_SCRATCH46_0 = 0x6001DC28;
|
||||
/* Set SVC handler to jump to reboot stub in IRAM. */
|
||||
APBDEV_PMC_SCRATCH33_0 = 0x4003F000;
|
||||
APBDEV_PMC_SCRATCH40_0 = 0x6000F208;
|
||||
|
||||
/* Trigger warm reboot. */
|
||||
pmc_reboot(1 << 0);
|
||||
while (true) { }
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void reboot_to_iram_payload(void *payload, size_t payload_size) {
|
||||
/* Copy sept into IRAM low. */
|
||||
/* Copy payload into IRAM low. */
|
||||
for (size_t i = 0; i < payload_size; i += sizeof(uint32_t)) {
|
||||
write32le((void *)0x40010000, i, read32le(payload, i));
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FUSEE_UTILS_H
|
||||
#define FUSEE_UTILS_H
|
||||
|
||||
@@ -121,7 +121,6 @@ static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t s
|
||||
__attribute__((noreturn)) void watchdog_reboot(void);
|
||||
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
|
||||
__attribute__((noreturn)) void reboot_to_fusee_primary(void);
|
||||
__attribute__((noreturn)) void reboot_to_sept(const void *tsec_fw, size_t tsec_fw_length, const void *stage2, size_t stage2_size);
|
||||
__attribute__((noreturn)) void reboot_to_iram_payload(void *payload, size_t payload_size);
|
||||
__attribute__((noreturn)) void wait_for_button_and_reboot(void);
|
||||
void wait_for_button(void);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||
branch = master
|
||||
commit = eb667fea5142fd35caf539289603748dd6f4f87e
|
||||
parent = 283736878ddf2cf1cad731b4bf21f916c7e87054
|
||||
commit = 87a1de0b1d489c25a85e187a5bf059f6872465d1
|
||||
parent = 9296a563036ef20664a2752c03a9695597d4c2b4
|
||||
method = merge
|
||||
cmdver = 0.4.0
|
||||
cmdver = 0.4.1
|
||||
|
||||
@@ -96,6 +96,8 @@ clean-$(strip $1):
|
||||
@rm -fr $$(foreach hdr,$$(GCH_DIRS),$$(hdr)/$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1))
|
||||
@for i in $$(GCH_DIRS) $$(ATMOSPHERE_BUILD_DIR) $$(ATMOSPHERE_LIBRARY_DIR); do [ -d $$$$i ] && rmdir --ignore-fail-on-non-empty $$$$i || true; done
|
||||
|
||||
.PHONY: $(strip $1) clean-$(strip $1) $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call ATMOSPHERE_ADD_TARGET, release, $(TARGET).a, \
|
||||
@@ -117,7 +119,7 @@ $(eval $(call ATMOSPHERE_ADD_TARGET, audit, $(TARGET)_audit.a, \
|
||||
ALL_GCH_IDENTIFIERS := $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(config))
|
||||
ALL_GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(foreach id,$(ALL_GCH_IDENTIFIERS),$(hdr)/$(id)))
|
||||
|
||||
.PHONY: clean all $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
|
||||
.PHONY: clean all
|
||||
|
||||
$(ATMOSPHERE_LIBRARY_DIR) $(GCH_DIRS):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
@@ -96,6 +96,8 @@ clean-$(strip $1):
|
||||
@rm -fr $$(foreach hdr,$$(GCH_DIRS),$$(hdr)/$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1))
|
||||
@for i in $$(GCH_DIRS) $$(ATMOSPHERE_BUILD_DIR) $$(ATMOSPHERE_LIBRARY_DIR); do [ -d $$$$i ] && rmdir --ignore-fail-on-non-empty $$$$i || true; done
|
||||
|
||||
.PHONY: $(strip $1) clean-$(strip $1) $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call ATMOSPHERE_ADD_TARGET, release, $(TARGET).a, \
|
||||
@@ -117,7 +119,7 @@ $(eval $(call ATMOSPHERE_ADD_TARGET, audit, $(TARGET)_audit.a, \
|
||||
ALL_GCH_IDENTIFIERS := $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(config))
|
||||
ALL_GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(foreach id,$(ALL_GCH_IDENTIFIERS),$(hdr)/$(id)))
|
||||
|
||||
.PHONY: clean all $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
|
||||
.PHONY: clean all
|
||||
|
||||
$(ATMOSPHERE_LIBRARY_DIR) $(GCH_DIRS):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
@@ -88,6 +88,8 @@ clean-$(strip $1):
|
||||
@rm -fr $$(foreach hdr,$$(GCH_DIRS),$$(hdr)/$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1))
|
||||
@for i in $$(GCH_DIRS) $$(ATMOSPHERE_BUILD_DIR) $$(ATMOSPHERE_LIBRARY_DIR); do [ -d $$$$i ] && rmdir --ignore-fail-on-non-empty $$$$i || true; done
|
||||
|
||||
.PHONY: $(strip $1) clean-$(strip $1) $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call ATMOSPHERE_ADD_TARGET, release, $(TARGET).a, \
|
||||
@@ -109,7 +111,7 @@ $(eval $(call ATMOSPHERE_ADD_TARGET, audit, $(TARGET)_audit.a, \
|
||||
ALL_GCH_IDENTIFIERS := $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(config))
|
||||
ALL_GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(foreach id,$(ALL_GCH_IDENTIFIERS),$(hdr)/$(id)))
|
||||
|
||||
.PHONY: clean all $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
|
||||
.PHONY: clean all
|
||||
|
||||
$(ATMOSPHERE_LIBRARY_DIR) $(GCH_DIRS):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
|
||||
@@ -172,10 +172,8 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
|
||||
/* Cache management helpers. */
|
||||
void ClearPageToZeroImpl(void *);
|
||||
void FlushEntireDataCacheSharedForInit();
|
||||
void FlushEntireDataCacheLocalForInit();
|
||||
void InvalidateEntireInstructionCacheForInit();
|
||||
void StoreEntireCacheForInit();
|
||||
void FlushEntireCacheForInit();
|
||||
|
||||
void FlushEntireDataCache();
|
||||
|
||||
|
||||
@@ -262,27 +262,6 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
__asm__ __volatile__("dc csw, %[v]" :: [v]"r"(sw_value) : "memory");
|
||||
}
|
||||
|
||||
template<bool Init, typename F>
|
||||
ALWAYS_INLINE void PerformCacheOperationBySetWayShared(F f) {
|
||||
CacheLineIdRegisterAccessor clidr_el1;
|
||||
const int levels_of_coherency = clidr_el1.GetLevelsOfCoherency();
|
||||
const int levels_of_unification = clidr_el1.GetLevelsOfUnification();
|
||||
|
||||
for (int level = levels_of_coherency; level >= levels_of_unification; level--) {
|
||||
PerformCacheOperationBySetWayImpl<Init>(level, f);
|
||||
}
|
||||
}
|
||||
|
||||
template<bool Init, typename F>
|
||||
ALWAYS_INLINE void PerformCacheOperationBySetWayLocal(F f) {
|
||||
CacheLineIdRegisterAccessor clidr_el1;
|
||||
const int levels_of_unification = clidr_el1.GetLevelsOfUnification();
|
||||
|
||||
for (int level = levels_of_unification - 1; level >= 0; level--) {
|
||||
PerformCacheOperationBySetWayImpl<Init>(level, f);
|
||||
}
|
||||
}
|
||||
|
||||
void StoreDataCacheBySetWay(int level) {
|
||||
PerformCacheOperationBySetWayImpl<false>(level, StoreDataCacheLineBySetWayImpl);
|
||||
cpu::DataSynchronizationBarrier();
|
||||
@@ -361,24 +340,63 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
|
||||
}
|
||||
|
||||
void FlushEntireDataCacheSharedForInit() {
|
||||
return PerformCacheOperationBySetWayShared<true>(FlushDataCacheLineBySetWayImpl);
|
||||
void StoreEntireCacheForInit() {
|
||||
/* Store local. */
|
||||
{
|
||||
CacheLineIdRegisterAccessor clidr_el1;
|
||||
const int levels_of_unification = clidr_el1.GetLevelsOfUnification();
|
||||
|
||||
for (int level = 0; level != levels_of_unification; ++level) {
|
||||
PerformCacheOperationBySetWayImpl<true>(level, StoreDataCacheLineBySetWayImpl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store shared. */
|
||||
{
|
||||
CacheLineIdRegisterAccessor clidr_el1;
|
||||
const int levels_of_coherency = clidr_el1.GetLevelsOfCoherency();
|
||||
const int levels_of_unification = clidr_el1.GetLevelsOfUnification();
|
||||
|
||||
for (int level = levels_of_unification; level <= levels_of_coherency; ++level) {
|
||||
PerformCacheOperationBySetWayImpl<true>(level, StoreDataCacheLineBySetWayImpl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Data synchronization barrier. */
|
||||
DataSynchronizationBarrierInnerShareable();
|
||||
|
||||
/* Invalidate instruction cache. */
|
||||
InvalidateEntireInstructionCacheLocalImpl();
|
||||
|
||||
/* Ensure local instruction consistency. */
|
||||
DataSynchronizationBarrierInnerShareable();
|
||||
InstructionMemoryBarrier();
|
||||
}
|
||||
|
||||
void FlushEntireDataCacheLocalForInit() {
|
||||
return PerformCacheOperationBySetWayLocal<true>(FlushDataCacheLineBySetWayImpl);
|
||||
}
|
||||
void FlushEntireCacheForInit() {
|
||||
/* Flush data cache. */
|
||||
{
|
||||
/* Get levels of coherence/unificaiton. */
|
||||
CacheLineIdRegisterAccessor clidr_el1;
|
||||
const int levels_of_coherency = clidr_el1.GetLevelsOfCoherency();
|
||||
|
||||
void InvalidateEntireInstructionCacheForInit() {
|
||||
/* Store cache from L1 up to (level of coherence - 1). */
|
||||
for (int level = 0; level < levels_of_coherency - 1; ++level) {
|
||||
PerformCacheOperationBySetWayImpl<true>(level, StoreDataCacheLineBySetWayImpl);
|
||||
}
|
||||
|
||||
/* Flush cache from (level of coherence - 1) down to L0. */
|
||||
for (int level = levels_of_coherency; level > 0; --level) {
|
||||
PerformCacheOperationBySetWayImpl<true>(level - 1, FlushDataCacheLineBySetWayImpl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalidate instruction cache. */
|
||||
InvalidateEntireInstructionCacheLocalImpl();
|
||||
EnsureInstructionConsistency();
|
||||
}
|
||||
|
||||
void StoreEntireCacheForInit() {
|
||||
PerformCacheOperationBySetWayLocal<true>(StoreDataCacheLineBySetWayImpl);
|
||||
PerformCacheOperationBySetWayShared<true>(StoreDataCacheLineBySetWayImpl);
|
||||
DataSynchronizationBarrierInnerShareable();
|
||||
InvalidateEntireInstructionCacheForInit();
|
||||
/* Invalidate entire TLB. */
|
||||
InvalidateEntireTlb();
|
||||
}
|
||||
|
||||
void FlushEntireDataCache() {
|
||||
|
||||
@@ -258,7 +258,7 @@ namespace ams::kern::arch::arm64 {
|
||||
{
|
||||
exception = ams::svc::DebugException_BreakPoint;
|
||||
param2 = far;
|
||||
param3 = ams::svc::BreakPointType_HardwareInstruction;
|
||||
param3 = ams::svc::BreakPointType_HardwareData;
|
||||
}
|
||||
break;
|
||||
case EsrEc_SErrorInterrupt:
|
||||
@@ -293,6 +293,13 @@ namespace ams::kern::arch::arm64 {
|
||||
/* Print that an exception occurred. */
|
||||
MESOSPHERE_RELEASE_LOG("Exception occurred. %016lx\n", GetCurrentProcess().GetProgramId());
|
||||
|
||||
{
|
||||
/* Print the current thread's registers. */
|
||||
KDebug::PrintRegister();
|
||||
|
||||
/* Print a backtrace. */
|
||||
KDebug::PrintBacktrace();
|
||||
}
|
||||
|
||||
/* If the SVC is handled, handle it. */
|
||||
if (!svc::ResultNotHandled::Includes(result)) {
|
||||
|
||||
@@ -74,26 +74,32 @@ namespace ams::kern::arch::arm64 {
|
||||
/* Get the exception context. */
|
||||
const KExceptionContext *e_ctx = GetExceptionContext(thread);
|
||||
|
||||
/* Get whether we're 64-bit. */
|
||||
const bool is_64_bit = this->Is64Bit();
|
||||
|
||||
/* If general registers are requested, get them. */
|
||||
if ((context_flags & ams::svc::ThreadContextFlag_General) != 0) {
|
||||
/* We can always get X0-X7/R0-R7. */
|
||||
auto register_count = 8;
|
||||
if (!thread->IsCallingSvc() || thread->GetSvcId() == svc::SvcId_ReturnFromException) {
|
||||
if (this->Is64Bit()) {
|
||||
/* Get X0-X28. */
|
||||
for (auto i = 0; i <= 28; ++i) {
|
||||
out->r[i] = e_ctx->x[i];
|
||||
}
|
||||
if (is_64_bit) {
|
||||
/* We're not in an SVC, so we can get X0-X29. */
|
||||
register_count = 29;
|
||||
} else {
|
||||
/* Get R0-R12. */
|
||||
for (auto i = 0; i <= 12; ++i) {
|
||||
out->r[i] = static_cast<u32>(e_ctx->x[i]);
|
||||
}
|
||||
/* We're 32-bit, so we should get R0-R12. */
|
||||
register_count = 13;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the registers. */
|
||||
for (auto i = 0; i < register_count; ++i) {
|
||||
out->r[i] = is_64_bit ? e_ctx->x[i] : static_cast<u32>(e_ctx->x[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* If control flags are requested, get them. */
|
||||
if ((context_flags & ams::svc::ThreadContextFlag_Control) != 0) {
|
||||
if (this->Is64Bit()) {
|
||||
if (is_64_bit) {
|
||||
out->fp = e_ctx->x[29];
|
||||
out->lr = e_ctx->x[30];
|
||||
out->sp = e_ctx->sp;
|
||||
@@ -291,7 +297,7 @@ namespace ams::kern::arch::arm64 {
|
||||
/* If the breakpoint matches context id, we need to get the context id. */
|
||||
if ((flags & (1ul << 21)) != 0) {
|
||||
/* Ensure that the breakpoint is context-aware. */
|
||||
R_UNLESS((name - ams::svc::HardwareBreakPointRegisterName_I0) <= (num_bp - num_ctx), svc::ResultNotSupported());
|
||||
R_UNLESS((name - ams::svc::HardwareBreakPointRegisterName_I0) >= (num_bp - num_ctx), svc::ResultNotSupported());
|
||||
|
||||
/* Check that the breakpoint does not have the mismatch bit. */
|
||||
R_UNLESS((flags & (1ul << 22)) == 0, svc::ResultInvalidCombination());
|
||||
|
||||
@@ -55,16 +55,18 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||
Package2Hash = 17,
|
||||
|
||||
/* Extension config items for exosphere. */
|
||||
ExosphereApiVersion = 65000,
|
||||
ExosphereNeedsReboot = 65001,
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
ExosphereLogConfiguration = 65009,
|
||||
ExosphereApiVersion = 65000,
|
||||
ExosphereNeedsReboot = 65001,
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
ExosphereLogConfiguration = 65009,
|
||||
ExosphereForceEnableUsb30 = 65010,
|
||||
ExosphereSupportedHosVersion = 65011,
|
||||
};
|
||||
|
||||
enum class SmcResult {
|
||||
|
||||
@@ -103,54 +103,29 @@ namespace ams::kern {
|
||||
auto it = m_tree.nfind_key({ addr, -1 });
|
||||
/* Determine the updated value. */
|
||||
s32 new_value;
|
||||
if (GetTargetFirmware() >= TargetFirmware_7_0_0) {
|
||||
if (count <= 0) {
|
||||
if ((it != m_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
new_value = value - 2;
|
||||
} else {
|
||||
new_value = value + 1;
|
||||
}
|
||||
if (count <= 0) {
|
||||
if ((it != m_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
new_value = value - 2;
|
||||
} else {
|
||||
if ((it != m_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
auto tmp_it = it;
|
||||
s32 tmp_num_waiters = 0;
|
||||
while ((++tmp_it != m_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr)) {
|
||||
if ((tmp_num_waiters++) >= count) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_num_waiters < count) {
|
||||
new_value = value - 1;
|
||||
} else {
|
||||
new_value = value;
|
||||
}
|
||||
} else {
|
||||
new_value = value + 1;
|
||||
}
|
||||
new_value = value + 1;
|
||||
}
|
||||
} else {
|
||||
if (count <= 0) {
|
||||
if ((it != m_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
new_value = value - 1;
|
||||
} else {
|
||||
new_value = value + 1;
|
||||
}
|
||||
} else {
|
||||
if ((it != m_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
auto tmp_it = it;
|
||||
s32 tmp_num_waiters = 0;
|
||||
while ((tmp_it != m_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && (tmp_num_waiters < count + 1)) {
|
||||
++tmp_num_waiters;
|
||||
++tmp_it;
|
||||
while ((++tmp_it != m_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr)) {
|
||||
if ((tmp_num_waiters++) >= count) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_num_waiters == 0) {
|
||||
new_value = value + 1;
|
||||
} else if (tmp_num_waiters <= count) {
|
||||
if (tmp_num_waiters < count) {
|
||||
new_value = value - 1;
|
||||
} else {
|
||||
new_value = value;
|
||||
}
|
||||
} else {
|
||||
new_value = value + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace ams::kern {
|
||||
|
||||
can_access = cpu::CanAccessAtomic(address);
|
||||
if (AMS_LIKELY(can_access)) {
|
||||
UpdateLockAtomic(std::addressof(prev_tag), address, own_tag, ams::svc::HandleWaitMask);
|
||||
can_access = UpdateLockAtomic(std::addressof(prev_tag), address, own_tag, ams::svc::HandleWaitMask);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -422,8 +422,8 @@ namespace ams::kern {
|
||||
for (auto i = 0; i < static_cast<s32>(cpu::NumCores); ++i) {
|
||||
if (thread == Kernel::GetScheduler(i).GetSchedulerCurrentThread()) {
|
||||
current = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the thread is current, retry until it isn't. */
|
||||
@@ -469,8 +469,8 @@ namespace ams::kern {
|
||||
for (auto i = 0; i < static_cast<s32>(cpu::NumCores); ++i) {
|
||||
if (thread == Kernel::GetScheduler(i).GetSchedulerCurrentThread()) {
|
||||
current = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the thread is current, retry until it isn't. */
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace ams::kern {
|
||||
|
||||
/* If we fail to unmap, we want to do a partial unlock. */
|
||||
{
|
||||
auto unlock_guard = SCOPE_GUARD { page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size, size); };
|
||||
auto unlock_guard = SCOPE_GUARD { MESOSPHERE_R_ABORT_UNLESS(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size, size)); };
|
||||
|
||||
/* Unmap. */
|
||||
R_TRY(m_table.Unmap(page_table, process_address, size, device_address));
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace ams::kern::KDumpObject {
|
||||
|
||||
const auto end = accessor.end();
|
||||
const auto &handle_table = process->GetHandleTable();
|
||||
const size_t max_handles = handle_table.GetMaxCount();
|
||||
const size_t max_handles = handle_table.GetTableSize();
|
||||
for (size_t i = 0; i < max_handles; ++i) {
|
||||
/* Get the object + handle. */
|
||||
ams::svc::Handle handle = ams::svc::InvalidHandle;
|
||||
@@ -181,7 +181,7 @@ namespace ams::kern::KDumpObject {
|
||||
|
||||
const auto end = accessor.end();
|
||||
const auto &handle_table = process->GetHandleTable();
|
||||
const size_t max_handles = handle_table.GetMaxCount();
|
||||
const size_t max_handles = handle_table.GetTableSize();
|
||||
for (size_t i = 0; i < max_handles; ++i) {
|
||||
/* Get the object + handle. */
|
||||
ams::svc::Handle handle = ams::svc::InvalidHandle;
|
||||
@@ -203,7 +203,7 @@ namespace ams::kern::KDumpObject {
|
||||
{
|
||||
for (auto it = accessor.begin(); it != end && client_port_process.IsNull(); ++it) {
|
||||
KProcess *cur = static_cast<KProcess *>(std::addressof(*it));
|
||||
for (size_t j = 0; j < cur->GetHandleTable().GetMaxCount(); ++j) {
|
||||
for (size_t j = 0; j < cur->GetHandleTable().GetTableSize(); ++j) {
|
||||
ams::svc::Handle cur_h = ams::svc::InvalidHandle;
|
||||
KScopedAutoObject cur_o = cur->GetHandleTable().GetObjectByIndex(std::addressof(cur_h), j);
|
||||
if (cur_o.IsNotNull()) {
|
||||
@@ -236,7 +236,7 @@ namespace ams::kern::KDumpObject {
|
||||
{
|
||||
for (auto it = accessor.begin(); it != end; ++it) {
|
||||
KProcess *cur = static_cast<KProcess *>(std::addressof(*it));
|
||||
for (size_t j = 0; j < cur->GetHandleTable().GetMaxCount(); ++j) {
|
||||
for (size_t j = 0; j < cur->GetHandleTable().GetTableSize(); ++j) {
|
||||
ams::svc::Handle cur_h = ams::svc::InvalidHandle;
|
||||
KScopedAutoObject cur_o = cur->GetHandleTable().GetObjectByIndex(std::addressof(cur_h), j);
|
||||
if (cur_o.IsNull()) {
|
||||
|
||||
@@ -804,7 +804,7 @@ namespace ams::kern {
|
||||
|
||||
/* Remove waiter thread. */
|
||||
s32 num_waiters;
|
||||
if (KThread *next = thread->RemoveWaiterByKey(std::addressof(num_waiters), reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread))); next != nullptr) {
|
||||
if (KThread *next = thread->RemoveWaiterByKey(std::addressof(num_waiters), reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread)) | 1); next != nullptr) {
|
||||
next->SetState(KThread::ThreadState_Runnable);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I.
|
||||
|
||||
.PHONY: clean all
|
||||
.PHONY: clean all lib/$(TARGET).a
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: lib/$(TARGET).a
|
||||
|
||||
@@ -164,6 +164,6 @@ namespace ams::fs {
|
||||
static_assert(util::is_pod<HashSalt>::value);
|
||||
static_assert(sizeof(HashSalt) == HashSalt::Size);
|
||||
|
||||
using SaveDataHashSalt = std::optional<HashSalt>;
|
||||
using SaveDataHashSalt = util::optional<HashSalt>;
|
||||
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace ams::fssrv::impl {
|
||||
return m_list.size();
|
||||
}
|
||||
|
||||
std::optional<fs::ProgramIndexMapInfo> Get(const ncm::ProgramId &program_id) const {
|
||||
util::optional<fs::ProgramIndexMapInfo> Get(const ncm::ProgramId &program_id) const {
|
||||
/* Acquire exclusive access to the map. */
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
@@ -134,9 +134,9 @@ namespace ams::fssrv::impl {
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
std::optional<fs::ProgramIndexMapInfo> GetImpl(F f) const {
|
||||
util::optional<fs::ProgramIndexMapInfo> GetImpl(F f) const {
|
||||
/* Try to find an entry matching the predicate. */
|
||||
std::optional<fs::ProgramIndexMapInfo> match = std::nullopt;
|
||||
util::optional<fs::ProgramIndexMapInfo> match = util::nullopt;
|
||||
|
||||
for (const auto &entry : m_list) {
|
||||
/* If the predicate matches, we want to return the relevant info. */
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace ams::fssrv::impl {
|
||||
public:
|
||||
bool IsDeepRetryEnabled() const;
|
||||
bool IsAccessFailureDetectionObserved() const;
|
||||
std::optional<std::shared_lock<os::ReadWriteLock>> AcquireCacheInvalidationReadLock();
|
||||
util::optional<std::shared_lock<os::ReadWriteLock>> AcquireCacheInvalidationReadLock();
|
||||
os::ReadWriteLock &GetReadWriteLockForCacheInvalidation();
|
||||
public:
|
||||
/* Command API. */
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace ams::fssrv::impl {
|
||||
|
||||
~StorageInterfaceAdapter();
|
||||
private:
|
||||
std::optional<std::shared_lock<os::ReadWriteLock>> AcquireCacheInvalidationReadLock();
|
||||
util::optional<std::shared_lock<os::ReadWriteLock>> AcquireCacheInvalidationReadLock();
|
||||
public:
|
||||
/* Command API. */
|
||||
Result Read(s64 offset, const ams::sf::OutNonSecureBuffer &buffer, s64 size);
|
||||
|
||||
@@ -34,9 +34,9 @@ namespace ams::fssystem {
|
||||
|
||||
virtual ~DirectoryRedirectionFileSystem();
|
||||
protected:
|
||||
inline std::optional<std::scoped_lock<os::Mutex>> GetAccessorLock() const {
|
||||
inline util::optional<std::scoped_lock<os::Mutex>> GetAccessorLock() const {
|
||||
/* No accessor lock is needed. */
|
||||
return std::nullopt;
|
||||
return util::nullopt;
|
||||
}
|
||||
private:
|
||||
Result GetNormalizedDirectoryPath(char **out, size_t *out_size, const char *dir);
|
||||
|
||||
@@ -33,9 +33,9 @@ namespace ams::fssystem {
|
||||
|
||||
virtual ~DirectorySaveDataFileSystem();
|
||||
protected:
|
||||
inline std::optional<std::scoped_lock<os::Mutex>> GetAccessorLock() {
|
||||
inline util::optional<std::scoped_lock<os::Mutex>> GetAccessorLock() {
|
||||
/* We have a real accessor lock that we want to use. */
|
||||
return std::make_optional<std::scoped_lock<os::Mutex>>(this->accessor_mutex);
|
||||
return util::make_optional<std::scoped_lock<os::Mutex>>(this->accessor_mutex);
|
||||
}
|
||||
private:
|
||||
Result AllocateWorkBuffer(std::unique_ptr<u8[]> *out, size_t *out_size, size_t ideal_size);
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace ams::fssystem {
|
||||
class Sha256PartitionFileSystemMeta : public PartitionFileSystemMetaCore<impl::Sha256PartitionFileSystemFormat> {
|
||||
public:
|
||||
using PartitionFileSystemMetaCore<impl::Sha256PartitionFileSystemFormat>::Initialize;
|
||||
Result Initialize(fs::IStorage *base_storage, MemoryResource *allocator, const void *hash, size_t hash_size, std::optional<u8> suffix = std::nullopt);
|
||||
Result Initialize(fs::IStorage *base_storage, MemoryResource *allocator, const void *hash, size_t hash_size, util::optional<u8> suffix = util::nullopt);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ namespace ams::fssystem {
|
||||
|
||||
virtual ~SubDirectoryFileSystem();
|
||||
protected:
|
||||
inline std::optional<std::scoped_lock<os::Mutex>> GetAccessorLock() const {
|
||||
inline util::optional<std::scoped_lock<os::Mutex>> GetAccessorLock() const {
|
||||
/* No accessor lock is needed. */
|
||||
return std::nullopt;
|
||||
return util::nullopt;
|
||||
}
|
||||
private:
|
||||
Result Initialize(const char *bp);
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->CreateFile(full_path, size, option);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->DeleteFile(full_path);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->CreateDirectory(full_path);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->DeleteDirectory(full_path);
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->DeleteDirectoryRecursively(full_path);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace ams::fssystem::impl {
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(old_full_path, sizeof(old_full_path), old_path));
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(new_full_path, sizeof(new_full_path), new_path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->RenameFile(old_full_path, new_full_path);
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace ams::fssystem::impl {
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(old_full_path, sizeof(old_full_path), old_path));
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(new_full_path, sizeof(new_full_path), new_path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->RenameDirectory(old_full_path, new_full_path);
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->GetEntryType(out, full_path);
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->OpenFile(out_file, full_path, mode);
|
||||
}
|
||||
|
||||
@@ -126,12 +126,12 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->OpenDirectory(out_dir, full_path, mode);
|
||||
}
|
||||
|
||||
virtual Result DoCommit() override {
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->Commit();
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->GetFreeSpaceSize(out, full_path);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->GetTotalSpaceSize(out, full_path);
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->CleanDirectoryRecursively(full_path);
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->GetFileTimeStampRaw(out, full_path);
|
||||
}
|
||||
|
||||
@@ -171,23 +171,23 @@ namespace ams::fssystem::impl {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(static_cast<Impl*>(this)->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->QueryEntry(dst, dst_size, src, src_size, query, full_path);
|
||||
}
|
||||
|
||||
/* These aren't accessible as commands. */
|
||||
virtual Result DoCommitProvisionally(s64 counter) override {
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->CommitProvisionally(counter);
|
||||
}
|
||||
|
||||
virtual Result DoRollback() override {
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->Rollback();
|
||||
}
|
||||
|
||||
virtual Result DoFlush() override {
|
||||
std::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
util::optional optional_lock = static_cast<Impl*>(this)->GetAccessorLock();
|
||||
return this->base_fs->Flush();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -57,8 +57,8 @@ namespace ams::kvdb {
|
||||
public:
|
||||
Result Initialize(void *buffer, size_t buffer_size, size_t capacity);
|
||||
void Invalidate();
|
||||
std::optional<size_t> TryGet(void *out_value, size_t max_out_size, const void *key, size_t key_size);
|
||||
std::optional<size_t> TryGetSize(const void *key, size_t key_size);
|
||||
util::optional<size_t> TryGet(void *out_value, size_t max_out_size, const void *key, size_t key_size);
|
||||
util::optional<size_t> TryGetSize(const void *key, size_t key_size);
|
||||
void Set(const void *key, size_t key_size, const void *value, size_t value_size);
|
||||
bool Contains(const void *key, size_t key_size);
|
||||
};
|
||||
|
||||
@@ -37,6 +37,6 @@ namespace ams::ncm {
|
||||
void GetTicketFileStringFromRightsId(char *dst, size_t dst_size, fs::RightsId id);
|
||||
void GetCertificateFileStringFromRightsId(char *dst, size_t dst_size, fs::RightsId id);
|
||||
|
||||
std::optional<ContentId> GetContentIdFromString(const char *str, size_t len);
|
||||
util::optional<ContentId> GetContentIdFromString(const char *str, size_t len);
|
||||
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace ams::ncm {
|
||||
StorageId storage_id;
|
||||
SystemSaveDataInfo info;
|
||||
sf::SharedPointer<IContentMetaDatabase> content_meta_database;
|
||||
std::optional<kvdb::MemoryKeyValueStore<ContentMetaKey>> kvs;
|
||||
util::optional<kvdb::MemoryKeyValueStore<ContentMetaKey>> kvs;
|
||||
ContentMetaMemoryResource *memory_resource;
|
||||
u32 max_content_metas;
|
||||
|
||||
|
||||
@@ -303,17 +303,17 @@ namespace ams::ncm {
|
||||
return static_cast<StorageId>(this->GetHeader()->storage_id);
|
||||
}
|
||||
|
||||
std::optional<ApplicationId> GetApplicationId(const ContentMetaKey &key) const {
|
||||
util::optional<ApplicationId> GetApplicationId(const ContentMetaKey &key) const {
|
||||
switch (key.type) {
|
||||
case ContentMetaType::Application: return ApplicationId{ key.id };
|
||||
case ContentMetaType::Patch: return this->GetExtendedHeader<PatchMetaExtendedHeader>()->application_id;
|
||||
case ContentMetaType::AddOnContent: return this->GetExtendedHeader<AddOnContentMetaExtendedHeader>()->application_id;
|
||||
case ContentMetaType::Delta: return this->GetExtendedHeader<DeltaMetaExtendedHeader>()->application_id;
|
||||
default: return std::nullopt;
|
||||
default: return util::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<ApplicationId> GetApplicationId() const {
|
||||
util::optional<ApplicationId> GetApplicationId() const {
|
||||
return this->GetApplicationId(this->GetKey());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace ams::ncm {
|
||||
protected:
|
||||
Result Initialize(StorageId install_storage, InstallTaskDataBase *data, u32 config);
|
||||
|
||||
Result PrepareContentMeta(const InstallContentMetaInfo &meta_info, std::optional<ContentMetaKey> key, std::optional<u32> source_version);
|
||||
Result PrepareContentMeta(const InstallContentMetaInfo &meta_info, util::optional<ContentMetaKey> key, util::optional<u32> source_version);
|
||||
Result PrepareContentMeta(ContentId content_id, s64 size, ContentMetaType meta_type, AutoBuffer *buffer);
|
||||
Result WritePlaceHolderBuffer(InstallContentInfo *content_info, const void *data, size_t data_size);
|
||||
void PrepareAgain();
|
||||
@@ -145,7 +145,7 @@ namespace ams::ncm {
|
||||
Result PrepareSystemUpdateDependency();
|
||||
virtual Result PrepareContentMetaIfLatest(const ContentMetaKey &key); /* NOTE: This is not virtual in Nintendo's code. We do so to facilitate downgrades. */
|
||||
u32 GetConfig() const { return this->config; }
|
||||
Result WriteContentMetaToPlaceHolder(InstallContentInfo *out_install_content_info, ContentStorage *storage, const InstallContentMetaInfo &meta_info, std::optional<bool> is_temporary);
|
||||
Result WriteContentMetaToPlaceHolder(InstallContentInfo *out_install_content_info, ContentStorage *storage, const InstallContentMetaInfo &meta_info, util::optional<bool> is_temporary);
|
||||
|
||||
StorageId GetInstallStorage() const { return this->install_storage; }
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace ams::ncm {
|
||||
Result VerifyAllNotCommitted(const StorageContentMetaKey *keys, s32 num_keys);
|
||||
|
||||
virtual Result PrepareInstallContentMetaData() = 0;
|
||||
virtual Result GetLatestVersion(std::optional<u32> *out_version, u64 id) { return ncm::ResultContentMetaNotFound(); }
|
||||
virtual Result GetLatestVersion(util::optional<u32> *out_version, u64 id) { return ncm::ResultContentMetaNotFound(); }
|
||||
|
||||
virtual Result OnExecuteComplete() { return ResultSuccess(); }
|
||||
|
||||
@@ -187,9 +187,9 @@ namespace ams::ncm {
|
||||
void StartThroughputMeasurement();
|
||||
void UpdateThroughputMeasurement(s64 throughput);
|
||||
|
||||
Result GetInstallContentMetaDataFromPath(AutoBuffer *out, const Path &path, const InstallContentInfo &content_info, std::optional<u32> source_version);
|
||||
Result GetInstallContentMetaDataFromPath(AutoBuffer *out, const Path &path, const InstallContentInfo &content_info, util::optional<u32> source_version);
|
||||
|
||||
InstallContentInfo MakeInstallContentInfoFrom(const InstallContentMetaInfo &info, const PlaceHolderId &placeholder_id, std::optional<bool> is_temporary);
|
||||
InstallContentInfo MakeInstallContentInfoFrom(const InstallContentMetaInfo &info, const PlaceHolderId &placeholder_id, util::optional<bool> is_temporary);
|
||||
|
||||
Result ReadContentMetaInfoList(s32 *out_count, std::unique_ptr<ContentMetaInfo[]> *out_meta_infos, const ContentMetaKey &key);
|
||||
Result ListRightsIdsByInstallContentMeta(s32 *out_count, Span<RightsId> out_span, const InstallContentMeta &content_meta, s32 offset);
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace ams::ncm {
|
||||
|
||||
void Inactivate();
|
||||
Result Initialize(const char *package_root, const char *context_path, void *buffer, size_t buffer_size, bool requires_exfat_driver, FirmwareVariationId firmware_variation_id);
|
||||
std::optional<ContentMetaKey> GetSystemUpdateMetaKey();
|
||||
util::optional<ContentMetaKey> GetSystemUpdateMetaKey();
|
||||
protected:
|
||||
virtual Result PrepareInstallContentMetaData() override;
|
||||
virtual Result GetInstallContentMetaInfo(InstallContentMetaInfo *out, const ContentMetaKey &key) override;
|
||||
|
||||
@@ -223,17 +223,18 @@ namespace ams::spl {
|
||||
Package2Hash = 17,
|
||||
|
||||
/* Extension config items for exosphere. */
|
||||
ExosphereApiVersion = 65000,
|
||||
ExosphereNeedsReboot = 65001,
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
ExosphereLogConfiguration = 65009,
|
||||
ExosphereForceEnableUsb30 = 65010,
|
||||
ExosphereApiVersion = 65000,
|
||||
ExosphereNeedsReboot = 65001,
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
ExosphereLogConfiguration = 65009,
|
||||
ExosphereForceEnableUsb30 = 65010,
|
||||
ExosphereSupportedHosVersion = 65011,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ namespace ams::capsrv::server {
|
||||
|
||||
/* Destroy the server. */
|
||||
os::FinalizeEvent(std::addressof(this->idle_event));
|
||||
this->server_manager_holder = std::nullopt;
|
||||
this->service_holder = std::nullopt;
|
||||
this->server_manager_holder = util::nullopt;
|
||||
this->service_holder = util::nullopt;
|
||||
}
|
||||
|
||||
void DecoderControlServerManager::StartServer() {
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace ams::capsrv::server {
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
using ServerManager = sf::hipc::ServerManager<NumServers, ServerOptions, MaxSessions>;
|
||||
private:
|
||||
std::optional<ServiceHolderType> service_holder;
|
||||
std::optional<ServerManager> server_manager_holder;
|
||||
util::optional<ServiceHolderType> service_holder;
|
||||
util::optional<ServerManager> server_manager_holder;
|
||||
os::EventType idle_event;
|
||||
public:
|
||||
constexpr DecoderControlServerManager() : service_holder(), server_manager_holder(), idle_event{} { /* ... */ }
|
||||
|
||||
@@ -74,6 +74,10 @@ Result dmntchtResumeCheatProcess(void) {
|
||||
return _dmntchtCmdVoid(&g_dmntchtSrv, 65005);
|
||||
}
|
||||
|
||||
Result dmntchtForceCloseCheatProcess(void) {
|
||||
return _dmntchtCmdVoid(&g_dmntchtSrv, 65006);
|
||||
}
|
||||
|
||||
static Result _dmntchtGetCount(u64 *out_count, u32 cmd_id) {
|
||||
return serviceDispatchOut(&g_dmntchtSrv, cmd_id, *out_count);
|
||||
}
|
||||
@@ -171,6 +175,13 @@ Result dmntchtResetStaticRegisters() {
|
||||
return _dmntchtCmdVoid(&g_dmntchtSrv, 65208);
|
||||
}
|
||||
|
||||
Result dmntchtSetMasterCheat(DmntCheatDefinition *cheat_def) {
|
||||
return serviceDispatch(&g_dmntchtSrv, 65209,
|
||||
.buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias | SfBufferAttr_FixedSize },
|
||||
.buffers = { { cheat_def, sizeof(*cheat_def) } },
|
||||
);
|
||||
}
|
||||
|
||||
Result dmntchtGetFrozenAddressCount(u64 *out_count) {
|
||||
return _dmntchtGetCount(out_count, 65300);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ Result dmntchtHasCheatProcess(bool *out);
|
||||
Result dmntchtGetCheatProcessEvent(Event *event);
|
||||
Result dmntchtGetCheatProcessMetadata(DmntCheatProcessMetadata *out_metadata);
|
||||
Result dmntchtForceOpenCheatProcess(void);
|
||||
Result dmntchtForceCloseCheatProcess(void);
|
||||
|
||||
Result dmntchtGetCheatProcessMappingCount(u64 *out_count);
|
||||
Result dmntchtGetCheatProcessMappings(MemoryInfo *buffer, u64 max_count, u64 offset, u64 *out_count);
|
||||
@@ -84,6 +85,7 @@ Result dmntchtRemoveCheat(u32 cheat_id);
|
||||
Result dmntchtReadStaticRegister(u64 *out, u8 which);
|
||||
Result dmntchtWriteStaticRegister(u8 which, u64 value);
|
||||
Result dmntchtResetStaticRegisters();
|
||||
Result dmntchtSetMasterCheat(DmntCheatDefinition *cheat);
|
||||
|
||||
Result dmntchtGetFrozenAddressCount(u64 *out_count);
|
||||
Result dmntchtGetFrozenAddresses(DmntFrozenAddressEntry *buffer, u64 max_count, u64 offset, u64 *out_count);
|
||||
|
||||
@@ -26,10 +26,10 @@ namespace ams::erpt::srv {
|
||||
constinit char Reporter::s_serial_number[24] = "Unknown";
|
||||
constinit char Reporter::s_os_version[24] = "Unknown";
|
||||
constinit char Reporter::s_private_os_version[96] = "Unknown";
|
||||
constinit std::optional<os::Tick> Reporter::s_application_launch_time;
|
||||
constinit std::optional<os::Tick> Reporter::s_awake_time;
|
||||
constinit std::optional<os::Tick> Reporter::s_power_on_time;
|
||||
constinit std::optional<time::SteadyClockTimePoint> Reporter::s_initial_launch_settings_completion_time;
|
||||
constinit util::optional<os::Tick> Reporter::s_application_launch_time;
|
||||
constinit util::optional<os::Tick> Reporter::s_awake_time;
|
||||
constinit util::optional<os::Tick> Reporter::s_power_on_time;
|
||||
constinit util::optional<time::SteadyClockTimePoint> Reporter::s_initial_launch_settings_completion_time;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -78,13 +78,13 @@ namespace ams::erpt::srv {
|
||||
entry->suspended_duration = suspended_duration;
|
||||
}
|
||||
|
||||
std::optional<TimeSpan> GetActiveDuration(ncm::ProgramId program_id) const {
|
||||
util::optional<TimeSpan> GetActiveDuration(ncm::ProgramId program_id) const {
|
||||
/* Try to find a matching entry. */
|
||||
const auto entry = util::range::find_if(m_list, [&](const AppletActiveTimeInfo &info) { return info.program_id == program_id; });
|
||||
if (entry != m_list.end()) {
|
||||
return (os::GetSystemTick() - entry->register_tick).ToTimeSpan() - entry->suspended_duration;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
return util::nullopt;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -25,13 +25,13 @@ namespace ams::erpt::srv {
|
||||
static char s_serial_number[24];
|
||||
static char s_os_version[24];
|
||||
static char s_private_os_version[96];
|
||||
static std::optional<os::Tick> s_application_launch_time;
|
||||
static std::optional<os::Tick> s_awake_time;
|
||||
static std::optional<os::Tick> s_power_on_time;
|
||||
static std::optional<time::SteadyClockTimePoint> s_initial_launch_settings_completion_time;
|
||||
static util::optional<os::Tick> s_application_launch_time;
|
||||
static util::optional<os::Tick> s_awake_time;
|
||||
static util::optional<os::Tick> s_power_on_time;
|
||||
static util::optional<time::SteadyClockTimePoint> s_initial_launch_settings_completion_time;
|
||||
public:
|
||||
static void ClearApplicationLaunchTime() { s_application_launch_time = std::nullopt; }
|
||||
static void ClearInitialLaunchSettingsCompletionTime() { s_initial_launch_settings_completion_time = std::nullopt; }
|
||||
static void ClearApplicationLaunchTime() { s_application_launch_time = util::nullopt; }
|
||||
static void ClearInitialLaunchSettingsCompletionTime() { s_initial_launch_settings_completion_time = util::nullopt; }
|
||||
|
||||
static void SetInitialLaunchSettingsCompletionTime(const time::SteadyClockTimePoint &time) { s_initial_launch_settings_completion_time = time; }
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ namespace ams::fs {
|
||||
|
||||
class SdCardRedirectionCodeFileSystem : public OpenFileOnlyFileSystem {
|
||||
private:
|
||||
std::optional<ReadOnlyFileSystem> sd_content_fs;
|
||||
util::optional<ReadOnlyFileSystem> sd_content_fs;
|
||||
ReadOnlyFileSystem code_fs;
|
||||
bool is_redirect;
|
||||
public:
|
||||
@@ -303,8 +303,8 @@ namespace ams::fs {
|
||||
|
||||
class AtmosphereCodeFileSystem : public OpenFileOnlyFileSystem {
|
||||
private:
|
||||
std::optional<SdCardRedirectionCodeFileSystem> code_fs;
|
||||
std::optional<ReadOnlyFileSystem> hbl_fs;
|
||||
util::optional<SdCardRedirectionCodeFileSystem> code_fs;
|
||||
util::optional<ReadOnlyFileSystem> hbl_fs;
|
||||
ncm::ProgramId program_id;
|
||||
bool initialized;
|
||||
public:
|
||||
|
||||
@@ -154,8 +154,8 @@ namespace ams::fssrv::impl {
|
||||
AMS_ABORT_UNLESS(false);
|
||||
}
|
||||
|
||||
std::optional<std::shared_lock<os::ReadWriteLock>> FileSystemInterfaceAdapter::AcquireCacheInvalidationReadLock() {
|
||||
std::optional<std::shared_lock<os::ReadWriteLock>> lock;
|
||||
util::optional<std::shared_lock<os::ReadWriteLock>> FileSystemInterfaceAdapter::AcquireCacheInvalidationReadLock() {
|
||||
util::optional<std::shared_lock<os::ReadWriteLock>> lock;
|
||||
if (this->deep_retry_enabled) {
|
||||
lock.emplace(this->invalidation_lock);
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ namespace ams::fssrv::impl {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
std::optional<std::shared_lock<os::ReadWriteLock>> StorageInterfaceAdapter::AcquireCacheInvalidationReadLock() {
|
||||
std::optional<std::shared_lock<os::ReadWriteLock>> lock;
|
||||
util::optional<std::shared_lock<os::ReadWriteLock>> StorageInterfaceAdapter::AcquireCacheInvalidationReadLock() {
|
||||
util::optional<std::shared_lock<os::ReadWriteLock>> lock;
|
||||
if (this->deep_retry_enabled) {
|
||||
lock.emplace(this->invalidation_lock);
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace ams::fssystem {
|
||||
|
||||
constexpr inline s32 KeySlotCacheEntryCount = 3;
|
||||
KeySlotCache g_key_slot_cache;
|
||||
std::optional<KeySlotCacheEntry> g_key_slot_cache_entry[KeySlotCacheEntryCount];
|
||||
util::optional<KeySlotCacheEntry> g_key_slot_cache_entry[KeySlotCacheEntryCount];
|
||||
|
||||
spl::AccessKey &GetNcaKekAccessKey(s32 key_type) {
|
||||
static spl::AccessKey s_nca_kek_access_key_array[KeyAreaEncryptionKeyCount] = {};
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace ams::fssystem {
|
||||
template class PartitionFileSystemMetaCore<impl::PartitionFileSystemFormat>;
|
||||
template class PartitionFileSystemMetaCore<impl::Sha256PartitionFileSystemFormat>;
|
||||
|
||||
Result Sha256PartitionFileSystemMeta::Initialize(fs::IStorage *base_storage, MemoryResource *allocator, const void *hash, size_t hash_size, std::optional<u8> suffix) {
|
||||
Result Sha256PartitionFileSystemMeta::Initialize(fs::IStorage *base_storage, MemoryResource *allocator, const void *hash, size_t hash_size, util::optional<u8> suffix) {
|
||||
/* Ensure preconditions. */
|
||||
R_UNLESS(hash_size == crypto::Sha256Generator::HashSize, fs::ResultPreconditionViolation());
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace ams::htclow::driver {
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
/* Clear our driver type. */
|
||||
m_driver_type = std::nullopt;
|
||||
m_driver_type = util::nullopt;
|
||||
|
||||
/* Close our driver. */
|
||||
if (m_open_driver != nullptr) {
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace ams::htclow::driver {
|
||||
|
||||
class DriverManager {
|
||||
private:
|
||||
std::optional<htclow::impl::DriverType> m_driver_type{};
|
||||
util::optional<htclow::impl::DriverType> m_driver_type{};
|
||||
IDriver *m_debug_driver{};
|
||||
SocketDriver m_socket_driver;
|
||||
UsbDriver m_usb_driver{};
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace ams::htclow::mux {
|
||||
u64 m_total_send_size;
|
||||
u64 m_cur_max_data;
|
||||
u64 m_prev_max_data;
|
||||
std::optional<u64> m_share;
|
||||
util::optional<u64> m_share;
|
||||
os::Event m_state_change_event;
|
||||
ChannelState m_state;
|
||||
public:
|
||||
|
||||
@@ -55,9 +55,9 @@ namespace ams::kvdb {
|
||||
AMS_ABORT_UNLESS(this->entries != nullptr);
|
||||
}
|
||||
|
||||
std::optional<size_t> FileKeyValueStore::Cache::TryGet(void *out_value, size_t max_out_size, const void *key, size_t key_size) {
|
||||
util::optional<size_t> FileKeyValueStore::Cache::TryGet(void *out_value, size_t max_out_size, const void *key, size_t key_size) {
|
||||
if (!this->HasEntries()) {
|
||||
return std::nullopt;
|
||||
return util::nullopt;
|
||||
}
|
||||
|
||||
/* Try to find the entry. */
|
||||
@@ -66,7 +66,7 @@ namespace ams::kvdb {
|
||||
if (entry.key_size == key_size && std::memcmp(entry.key, key, key_size) == 0) {
|
||||
/* If we don't have enough space, fail to read from cache. */
|
||||
if (max_out_size < entry.value_size) {
|
||||
return std::nullopt;
|
||||
return util::nullopt;
|
||||
}
|
||||
|
||||
std::memcpy(out_value, entry.value, entry.value_size);
|
||||
@@ -74,12 +74,12 @@ namespace ams::kvdb {
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return util::nullopt;
|
||||
}
|
||||
|
||||
std::optional<size_t> FileKeyValueStore::Cache::TryGetSize(const void *key, size_t key_size) {
|
||||
util::optional<size_t> FileKeyValueStore::Cache::TryGetSize(const void *key, size_t key_size) {
|
||||
if (!this->HasEntries()) {
|
||||
return std::nullopt;
|
||||
return util::nullopt;
|
||||
}
|
||||
|
||||
/* Try to find the entry. */
|
||||
@@ -90,7 +90,7 @@ namespace ams::kvdb {
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return util::nullopt;
|
||||
}
|
||||
|
||||
void FileKeyValueStore::Cache::Set(const void *key, size_t key_size, const void *value, size_t value_size) {
|
||||
|
||||
@@ -78,13 +78,13 @@ namespace ams::ncm {
|
||||
util::SNPrintf(dst, dst_size, "%s.cert", str.data);
|
||||
}
|
||||
|
||||
std::optional<ContentId> GetContentIdFromString(const char *str, size_t len) {
|
||||
util::optional<ContentId> GetContentIdFromString(const char *str, size_t len) {
|
||||
if (len < ContentIdStringLength) {
|
||||
return std::nullopt;
|
||||
return util::nullopt;
|
||||
}
|
||||
|
||||
ContentId content_id;
|
||||
return GetBytesFromString(std::addressof(content_id), sizeof(content_id), str, ContentIdStringLength) ? std::optional<ContentId>(content_id) : std::nullopt;
|
||||
return GetBytesFromString(std::addressof(content_id), sizeof(content_id), str, ContentIdStringLength) ? util::optional<ContentId>(content_id) : util::nullopt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace ams::ncm {
|
||||
out->max_content_metas = max_content_metas;
|
||||
out->memory_resource = memory_resource;
|
||||
out->content_meta_database = nullptr;
|
||||
out->kvs = std::nullopt;
|
||||
out->kvs = util::nullopt;
|
||||
|
||||
/* Create a new mount name and copy it to out. */
|
||||
std::strcpy(out->mount_name, impl::CreateUniqueMountName().str);
|
||||
@@ -240,7 +240,7 @@ namespace ams::ncm {
|
||||
out->max_content_metas = max_content_metas;
|
||||
out->memory_resource = memory_resource;
|
||||
out->content_meta_database = nullptr;
|
||||
out->kvs = std::nullopt;
|
||||
out->kvs = util::nullopt;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -649,7 +649,7 @@ namespace ams::ncm {
|
||||
/* N doesn't bother checking the result of this */
|
||||
root->content_meta_database->DisableForcibly();
|
||||
root->content_meta_database = nullptr;
|
||||
root->kvs = std::nullopt;
|
||||
root->kvs = util::nullopt;
|
||||
|
||||
/* Also unmount, except in the case of game cards. */
|
||||
if (storage_id != StorageId::GameCard) {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
Result ContentMetaDatabaseImpl::GetContentIdImpl(ContentId *out, const ContentMetaKey &key, ContentType type, std::optional<u8> id_offset) const {
|
||||
Result ContentMetaDatabaseImpl::GetContentIdImpl(ContentId *out, const ContentMetaKey &key, ContentType type, util::optional<u8> id_offset) const {
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
||||
/* Find the meta key. */
|
||||
@@ -78,7 +78,7 @@ namespace ams::ncm {
|
||||
}
|
||||
|
||||
Result ContentMetaDatabaseImpl::GetContentIdByType(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type) {
|
||||
return this->GetContentIdImpl(out_content_id.GetPointer(), key, type, std::nullopt);
|
||||
return this->GetContentIdImpl(out_content_id.GetPointer(), key, type, util::nullopt);
|
||||
}
|
||||
|
||||
Result ContentMetaDatabaseImpl::ListContentInfo(sf::Out<s32> out_count, const sf::OutArray<ContentInfo> &out_info, const ContentMetaKey &key, s32 offset) {
|
||||
@@ -149,7 +149,7 @@ namespace ams::ncm {
|
||||
Result ContentMetaDatabaseImpl::GetLatestContentMetaKey(sf::Out<ContentMetaKey> out_key, u64 id) {
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
||||
std::optional<ContentMetaKey> found_key = std::nullopt;
|
||||
util::optional<ContentMetaKey> found_key = util::nullopt;
|
||||
|
||||
/* Find the last key with the desired program id. */
|
||||
for (auto entry = this->kvs->lower_bound(ContentMetaKey::MakeUnknownType(id, 0)); entry != this->kvs->end(); entry++) {
|
||||
@@ -308,15 +308,15 @@ namespace ams::ncm {
|
||||
out_orphaned[i] = true;
|
||||
}
|
||||
|
||||
auto IsOrphanedContent = [] ALWAYS_INLINE_LAMBDA (const sf::InArray<ContentId> &list, const ncm::ContentId &id) -> std::optional<size_t> {
|
||||
auto IsOrphanedContent = [] ALWAYS_INLINE_LAMBDA (const sf::InArray<ContentId> &list, const ncm::ContentId &id) -> util::optional<size_t> {
|
||||
/* Check if any input content ids match our found content id. */
|
||||
for (size_t i = 0; i < list.GetSize(); i++) {
|
||||
if (list[i] == id) {
|
||||
return std::make_optional(i);
|
||||
return util::make_optional(i);
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return util::nullopt;
|
||||
};
|
||||
|
||||
/* Iterate over all entries. */
|
||||
@@ -435,7 +435,7 @@ namespace ams::ncm {
|
||||
}
|
||||
|
||||
Result ContentMetaDatabaseImpl::GetContentIdByTypeAndIdOffset(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type, u8 id_offset) {
|
||||
return this->GetContentIdImpl(out_content_id.GetPointer(), key, type, std::make_optional(id_offset));
|
||||
return this->GetContentIdImpl(out_content_id.GetPointer(), key, type, util::make_optional(id_offset));
|
||||
}
|
||||
|
||||
Result ContentMetaDatabaseImpl::GetCount(sf::Out<u32> out_count) {
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace ams::ncm {
|
||||
ContentMetaDatabaseImpl(ContentMetaKeyValueStore *kvs) : ContentMetaDatabaseImplBase(kvs) { /* ... */ }
|
||||
private:
|
||||
/* Helpers. */
|
||||
Result GetContentIdImpl(ContentId *out, const ContentMetaKey &key, ContentType type, std::optional<u8> id_offset) const;
|
||||
Result GetContentIdImpl(ContentId *out, const ContentMetaKey &key, ContentType type, util::optional<u8> id_offset) const;
|
||||
public:
|
||||
/* Actual commands. */
|
||||
virtual Result Set(const ContentMetaKey &key, const sf::InBuffer &value) override;
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace ams::ncm {
|
||||
R_UNLESS(reader.GetExtendedDataSize() != 0, ReadMetaInfoListFromBase());
|
||||
|
||||
SystemUpdateMetaExtendedDataReader extended_data_reader(reader.GetExtendedData(), reader.GetExtendedDataSize());
|
||||
std::optional<s32> firmware_variation_index = std::nullopt;
|
||||
util::optional<s32> firmware_variation_index = util::nullopt;
|
||||
|
||||
/* NOTE: Atmosphere extension to support downgrading. */
|
||||
/* If all firmware variations refer to base, don't require the current variation be present. */
|
||||
|
||||
@@ -208,7 +208,7 @@ namespace ams::ncm {
|
||||
return this->OpenCurrentDirectory();
|
||||
}
|
||||
|
||||
Result ContentStorageImpl::ContentIterator::GetNext(std::optional<fs::DirectoryEntry> *out) {
|
||||
Result ContentStorageImpl::ContentIterator::GetNext(util::optional<fs::DirectoryEntry> *out) {
|
||||
/* Iterate until we get the next entry. */
|
||||
while (true) {
|
||||
/* Ensure that we have entries loaded. */
|
||||
@@ -216,7 +216,7 @@ namespace ams::ncm {
|
||||
|
||||
/* If we failed to load any entries, there's nothing to get. */
|
||||
if (this->entry_count <= 0) {
|
||||
*out = std::nullopt;
|
||||
*out = util::nullopt;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ namespace ams::ncm {
|
||||
fs::CloseFile(this->cached_file_handle);
|
||||
this->cached_content_id = InvalidContentId;
|
||||
}
|
||||
this->content_iterator = std::nullopt;
|
||||
this->content_iterator = util::nullopt;
|
||||
}
|
||||
|
||||
Result ContentStorageImpl::OpenContentIdFile(ContentId content_id) {
|
||||
@@ -586,7 +586,7 @@ namespace ams::ncm {
|
||||
/* Advance to the desired offset. */
|
||||
for (auto current_offset = 0; current_offset < offset; /* ... */) {
|
||||
/* Get the next directory entry. */
|
||||
std::optional<fs::DirectoryEntry> dir_entry;
|
||||
util::optional<fs::DirectoryEntry> dir_entry;
|
||||
R_TRY(this->content_iterator->GetNext(std::addressof(dir_entry)));
|
||||
|
||||
/* If we run out of entries before reaching the desired offset, we're done. */
|
||||
@@ -606,7 +606,7 @@ namespace ams::ncm {
|
||||
s32 count = 0;
|
||||
while (count < static_cast<s32>(out.GetSize())) {
|
||||
/* Get the next directory entry. */
|
||||
std::optional<fs::DirectoryEntry> dir_entry;
|
||||
util::optional<fs::DirectoryEntry> dir_entry;
|
||||
R_TRY(this->content_iterator->GetNext(std::addressof(dir_entry)));
|
||||
|
||||
/* Don't continue if the directory entry is absent. */
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace ams::ncm {
|
||||
~ContentIterator();
|
||||
|
||||
Result Initialize(const char *root_path, size_t max_depth);
|
||||
Result GetNext(std::optional<fs::DirectoryEntry> *out);
|
||||
Result GetNext(util::optional<fs::DirectoryEntry> *out);
|
||||
private:
|
||||
Result OpenCurrentDirectory();
|
||||
Result OpenDirectory(const char *dir);
|
||||
@@ -53,14 +53,14 @@ namespace ams::ncm {
|
||||
ContentId cached_content_id;
|
||||
fs::FileHandle cached_file_handle;
|
||||
RightsIdCache *rights_id_cache;
|
||||
std::optional<ContentIterator> content_iterator;
|
||||
std::optional<s32> last_content_offset;
|
||||
util::optional<ContentIterator> content_iterator;
|
||||
util::optional<s32> last_content_offset;
|
||||
public:
|
||||
static Result InitializeBase(const char *root_path);
|
||||
static Result CleanupBase(const char *root_path);
|
||||
static Result VerifyBase(const char *root_path);
|
||||
public:
|
||||
ContentStorageImpl() : placeholder_accessor(), cached_content_id(InvalidContentId), cached_file_handle(), rights_id_cache(nullptr), content_iterator(std::nullopt), last_content_offset(std::nullopt) { /* ... */ }
|
||||
ContentStorageImpl() : placeholder_accessor(), cached_content_id(InvalidContentId), cached_file_handle(), rights_id_cache(nullptr), content_iterator(util::nullopt), last_content_offset(util::nullopt) { /* ... */ }
|
||||
~ContentStorageImpl();
|
||||
|
||||
Result Initialize(const char *root_path, MakeContentPathFunction content_path_func, MakePlaceHolderPathFunction placeholder_path_func, bool delay_flush, RightsIdCache *rights_id_cache);
|
||||
|
||||
@@ -87,8 +87,8 @@ namespace ams::ncm {
|
||||
R_TRY(this->CountInstallContentMetaData(std::addressof(count)));
|
||||
|
||||
/* Iterate over content meta. */
|
||||
std::optional<PlaceHolderId> placeholder_id;
|
||||
std::optional<StorageId> storage_id;
|
||||
util::optional<PlaceHolderId> placeholder_id;
|
||||
util::optional<StorageId> storage_id;
|
||||
for (s32 i = 0; i < count; i++) {
|
||||
/* Obtain the content meta. */
|
||||
InstallContentMeta content_meta;
|
||||
@@ -716,7 +716,7 @@ namespace ams::ncm {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result InstallTaskBase::WriteContentMetaToPlaceHolder(InstallContentInfo *out_install_content_info, ContentStorage *storage, const InstallContentMetaInfo &meta_info, std::optional<bool> is_temporary) {
|
||||
Result InstallTaskBase::WriteContentMetaToPlaceHolder(InstallContentInfo *out_install_content_info, ContentStorage *storage, const InstallContentMetaInfo &meta_info, util::optional<bool> is_temporary) {
|
||||
/* Generate a placeholder id. */
|
||||
auto placeholder_id = storage->GeneratePlaceHolderId();
|
||||
|
||||
@@ -736,14 +736,14 @@ namespace ams::ncm {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result InstallTaskBase::PrepareContentMeta(const InstallContentMetaInfo &meta_info, std::optional<ContentMetaKey> expected_key, std::optional<u32> source_version) {
|
||||
Result InstallTaskBase::PrepareContentMeta(const InstallContentMetaInfo &meta_info, util::optional<ContentMetaKey> expected_key, util::optional<u32> source_version) {
|
||||
/* Open the BuiltInSystem content storage. */
|
||||
ContentStorage content_storage;
|
||||
R_TRY(OpenContentStorage(&content_storage, StorageId::BuiltInSystem));
|
||||
|
||||
/* Write content meta to a placeholder. */
|
||||
InstallContentInfo content_info;
|
||||
R_TRY(this->WriteContentMetaToPlaceHolder(std::addressof(content_info), std::addressof(content_storage), meta_info, std::nullopt));
|
||||
R_TRY(this->WriteContentMetaToPlaceHolder(std::addressof(content_info), std::addressof(content_storage), meta_info, util::nullopt));
|
||||
|
||||
/* Get the path of the placeholder. */
|
||||
Path path;
|
||||
@@ -929,7 +929,7 @@ namespace ams::ncm {
|
||||
/* Get and prepare install content meta info. */
|
||||
InstallContentMetaInfo install_content_meta_info;
|
||||
R_TRY(this->GetInstallContentMetaInfo(std::addressof(install_content_meta_info), key));
|
||||
R_TRY(this->PrepareContentMeta(install_content_meta_info, key, std::nullopt));
|
||||
R_TRY(this->PrepareContentMeta(install_content_meta_info, key, util::nullopt));
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -997,7 +997,7 @@ namespace ams::ncm {
|
||||
return this->data->Delete(keys, num_keys);
|
||||
}
|
||||
|
||||
Result InstallTaskBase::GetInstallContentMetaDataFromPath(AutoBuffer *out, const Path &path, const InstallContentInfo &content_info, std::optional<u32> source_version) {
|
||||
Result InstallTaskBase::GetInstallContentMetaDataFromPath(AutoBuffer *out, const Path &path, const InstallContentInfo &content_info, util::optional<u32> source_version) {
|
||||
AutoBuffer meta;
|
||||
{
|
||||
fs::ScopedAutoAbortDisabler aad;
|
||||
@@ -1027,7 +1027,7 @@ namespace ams::ncm {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
InstallContentInfo InstallTaskBase::MakeInstallContentInfoFrom(const InstallContentMetaInfo &info, const PlaceHolderId &placeholder_id, std::optional<bool> is_tmp) {
|
||||
InstallContentInfo InstallTaskBase::MakeInstallContentInfoFrom(const InstallContentMetaInfo &info, const PlaceHolderId &placeholder_id, util::optional<bool> is_tmp) {
|
||||
return {
|
||||
.digest = info.digest,
|
||||
.info = ContentInfo::Make(info.content_id, info.content_size, ContentType::Meta, 0),
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace ams::ncm {
|
||||
Result OnMemoryContentMetaDatabaseImpl::GetLatestContentMetaKey(sf::Out<ContentMetaKey> out_key, u64 id) {
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
||||
std::optional<ContentMetaKey> found_key = std::nullopt;
|
||||
util::optional<ContentMetaKey> found_key = util::nullopt;
|
||||
|
||||
/* Find the last key with the desired program id. */
|
||||
for (auto entry = this->kvs->lower_bound(ContentMetaKey::MakeUnknownType(id, 0)); entry != this->kvs->end(); entry++) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user