Implement support for parsing/interacting with NCAs. (#942)

* fs: implement support for interacting with ncas.

* spl: extend to use virtual keyslots
This commit is contained in:
SciresM 2020-05-11 15:04:51 -07:00 committed by GitHub
parent 3a1ccdd919
commit 81f91803ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
118 changed files with 13301 additions and 405 deletions

View file

@ -29,4 +29,6 @@
#include <vapours/crypto/crypto_rsa_oaep_sha256_decoder.hpp>
#include <vapours/crypto/crypto_rsa_oaep_sha256_decryptor.hpp>
#include <vapours/crypto/crypto_rsa_oaep_sha256_encryptor.hpp>
#include <vapours/crypto/crypto_hmac_sha1_generator.hpp>
#include <vapours/crypto/crypto_hmac_sha256_generator.hpp>
#include <vapours/crypto/crypto_csrng.hpp>

View file

@ -0,0 +1,51 @@
/*
* 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/>.
*/
#pragma once
#include <vapours/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util.hpp>
#include <vapours/crypto/impl/crypto_hmac_impl.hpp>
namespace ams::crypto {
template<typename Hash> /* requires HashFunction<Hash> */
class HmacGenerator {
NON_COPYABLE(HmacGenerator);
NON_MOVEABLE(HmacGenerator);
private:
using Impl = impl::HmacImpl<Hash>;
public:
static constexpr size_t HashSize = Impl::HashSize;
static constexpr size_t BlockSize = Impl::BlockSize;
private:
Impl impl;
public:
HmacGenerator() { /* ... */ }
void Initialize(const void *key, size_t key_size) {
return this->impl.Initialize(key, key_size);
}
void Update(const void *data, size_t size) {
return this->impl.Update(data, size);
}
void GetMac(void *dst, size_t dst_size) {
return this->impl.GetMac(dst, dst_size);
}
};
}

View file

@ -0,0 +1,27 @@
/*
* 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/>.
*/
#pragma once
#include <vapours/crypto/crypto_sha1_generator.hpp>
#include <vapours/crypto/crypto_hmac_generator.hpp>
namespace ams::crypto {
using HmacSha1Generator = HmacGenerator<Sha1Generator>;
void GenerateHmacSha1Mac(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size);
}

View file

@ -0,0 +1,27 @@
/*
* 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/>.
*/
#pragma once
#include <vapours/crypto/crypto_sha256_generator.hpp>
#include <vapours/crypto/crypto_hmac_generator.hpp>
namespace ams::crypto {
using HmacSha256Generator = HmacGenerator<Sha256Generator>;
void GenerateHmacSha256Mac(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size);
}

View file

@ -0,0 +1,126 @@
/*
* 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/>.
*/
#pragma once
#include <vapours/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util.hpp>
#include <vapours/crypto/impl/crypto_hash_function.hpp>
#include <vapours/crypto/crypto_memory_clear.hpp>
namespace ams::crypto::impl {
template<typename Hash> /* requires HashFunction<Hash> */
class HmacImpl {
NON_COPYABLE(HmacImpl);
NON_MOVEABLE(HmacImpl);
public:
static constexpr size_t MacSize = Hash::HashSize;
static constexpr size_t BlockSize = Hash::BlockSize;
private:
static constexpr u32 IpadMagic = 0x36363636;
static constexpr u32 OpadMagic = 0x5c5c5c5c;
static constexpr u32 IpadMagicXorOpadMagic = IpadMagic ^ OpadMagic;
static_assert(IpadMagicXorOpadMagic == 0x6a6a6a6a);
private:
enum State {
State_None = 0,
State_Initialized = 1,
State_Done = 2,
};
private:
Hash hash_function;
u32 key[BlockSize / sizeof(u32)];
u32 mac[MacSize / sizeof(u32)];
State state;
public:
HmacImpl() : state(State_None) { /* ... */ }
~HmacImpl() {
static_assert(offsetof(HmacImpl, hash_function) == 0);
/* Clear everything except for the hash function. */
ClearMemory(reinterpret_cast<u8 *>(this) + sizeof(this->hash_function), sizeof(*this) - sizeof(this->hash_function));
}
void Initialize(const void *key, size_t key_size);
void Update(const void *data, size_t data_size);
void GetMac(void *dst, size_t dst_size);
};
template<typename Hash>
inline void HmacImpl<Hash>::Initialize(const void *key, size_t key_size) {
/* Clear the key storage. */
std::memset(this->key, 0, sizeof(this->key));
/* Set the key storage. */
if (key_size > BlockSize) {
this->hash_function.Initialize();
this->hash_function.Update(key, key_size);
this->hash_function.GetHash(this->key, this->hash_function.HashSize);
} else {
std::memcpy(this->key, key, key_size);
}
/* Xor the key with the ipad. */
for (size_t i = 0; i < util::size(this->key); i++) {
this->key[i] ^= IpadMagic;
}
/* Update the hash function with the xor'd key. */
this->hash_function.Initialize();
this->hash_function.Update(this->key, BlockSize);
/* Mark initialized. */
this->state = State_Initialized;
}
template<typename Hash>
inline void HmacImpl<Hash>::Update(const void *data, size_t data_size) {
AMS_ASSERT(this->state == State_Initialized);
this->hash_function.Update(data, data_size);
}
template<typename Hash>
inline void HmacImpl<Hash>::GetMac(void *dst, size_t dst_size) {
AMS_ASSERT(this->state == State_Initialized || this->state == State_Done);
AMS_ASSERT(dst_size >= MacSize);
/* If we're not already finalized, get the final mac. */
if (this->state == State_Initialized) {
/* Get the hash of ((key ^ ipad) || data). */
this->hash_function.GetHash(this->mac, MacSize);
/* Xor the key with the opad. */
for (size_t i = 0; i < util::size(this->key); i++) {
this->key[i] ^= IpadMagicXorOpadMagic;
}
/* Calculate the final mac as hash of ((key ^ opad) || hash((key ^ ipad) || data)) */
this->hash_function.Initialize();
this->hash_function.Update(this->key, BlockSize);
this->hash_function.Update(this->mac, MacSize);
this->hash_function.GetHash(this->mac, MacSize);
/* Set our state as done. */
this->state = State_Done;
}
std::memcpy(dst, this->mac, MacSize);
}
}

View file

@ -35,9 +35,12 @@ namespace ams::fs {
R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceBisSystem, 38);
R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceSdCard, 39);
R_DEFINE_ERROR_RESULT(UnsupportedSdkVersion, 50);
R_DEFINE_ERROR_RESULT(MountNameAlreadyExists, 60);
R_DEFINE_ERROR_RESULT(TargetNotFound, 1002);
R_DEFINE_ERROR_RESULT(PartitionNotFound, 1001);
R_DEFINE_ERROR_RESULT(TargetNotFound, 1002);
R_DEFINE_ERROR_RANGE(SdCardAccessFailed, 2000, 2499);
R_DEFINE_ERROR_RESULT(SdCardNotPresent, 2001);
@ -51,48 +54,65 @@ namespace ams::fs {
R_DEFINE_ERROR_RESULT(SystemPartitionNotReady, 3100);
R_DEFINE_ERROR_RANGE(AllocationFailure, 3200, 3499);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorA, 3211);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorB, 3212);
R_DEFINE_ERROR_RESULT(AllocationFailureInApplicationA, 3213);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisA, 3215);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisB, 3216);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisC, 3217);
R_DEFINE_ERROR_RESULT(AllocationFailureInCodeA, 3218);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentA, 3219);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageA, 3220);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageB, 3221);
R_DEFINE_ERROR_RESULT(AllocationFailureInDataA, 3222);
R_DEFINE_ERROR_RESULT(AllocationFailureInDataB, 3223);
R_DEFINE_ERROR_RESULT(AllocationFailureInDeviceSaveDataA, 3224);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardA, 3225);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardB, 3226);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardC, 3227);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardD, 3228);
R_DEFINE_ERROR_RESULT(AllocationFailureInImageDirectoryA, 3232);
R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardA, 3244);
R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardB, 3245);
R_DEFINE_ERROR_RESULT(AllocationFailureInSystemSaveDataA, 3246);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemA, 3247);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemB, 3248);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemC, 3249);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemCreatorA, 3280);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemBuddyHeapA, 3294);
R_DEFINE_ERROR_RESULT(AllocationFailureInDirectorySaveDataFileSystem, 3321);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemA, 3347);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemB, 3348);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemC, 3349);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaA, 3350);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaB, 3351);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemD, 3352);
R_DEFINE_ERROR_RESULT(AllocationFailureInSubDirectoryFileSystem, 3355);
R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterA, 3365);
R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterB, 3366);
R_DEFINE_ERROR_RESULT(AllocationFailureInPathNormalizer, 3367);
R_DEFINE_ERROR_RESULT(AllocationFailureInDbmRomKeyValueStorage, 3375);
R_DEFINE_ERROR_RESULT(AllocationFailureInReadOnlyFileSystemA, 3386);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemE, 3377);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemInterfaceAdapter, 3407);
R_DEFINE_ERROR_RESULT(AllocationFailureInNew, 3420);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorA, 3211);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorB, 3212);
R_DEFINE_ERROR_RESULT(AllocationFailureInApplicationA, 3213);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisA, 3215);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisB, 3216);
R_DEFINE_ERROR_RESULT(AllocationFailureInBisC, 3217);
R_DEFINE_ERROR_RESULT(AllocationFailureInCodeA, 3218);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentA, 3219);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageA, 3220);
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageB, 3221);
R_DEFINE_ERROR_RESULT(AllocationFailureInDataA, 3222);
R_DEFINE_ERROR_RESULT(AllocationFailureInDataB, 3223);
R_DEFINE_ERROR_RESULT(AllocationFailureInDeviceSaveDataA, 3224);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardA, 3225);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardB, 3226);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardC, 3227);
R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardD, 3228);
R_DEFINE_ERROR_RESULT(AllocationFailureInImageDirectoryA, 3232);
R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardA, 3244);
R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardB, 3245);
R_DEFINE_ERROR_RESULT(AllocationFailureInSystemSaveDataA, 3246);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemA, 3247);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemB, 3248);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemC, 3249);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemCreatorA, 3280);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFileSystemCreatorA, 3281);
R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorA, 3288);
R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorB, 3289);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemBuddyHeapA, 3294);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemBufferManagerA, 3295);
R_DEFINE_ERROR_RESULT(AllocationFailureInBlockCacheBufferedStorageA, 3296);
R_DEFINE_ERROR_RESULT(AllocationFailureInBlockCacheBufferedStorageB, 3297);
R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityVerificationStorageA, 3304);
R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityVerificationStorageB, 3305);
R_DEFINE_ERROR_RESULT(AllocationFailureInDirectorySaveDataFileSystem, 3321);
R_DEFINE_ERROR_RESULT(AllocationFailureInNcaFileSystemDriverI, 3341);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemA, 3347);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemB, 3348);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemC, 3349);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaA, 3350);
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaB, 3351);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemD, 3352);
R_DEFINE_ERROR_RESULT(AllocationFailureInSubDirectoryFileSystem, 3355);
R_DEFINE_ERROR_RESULT(AllocationFailureInNcaReaderA, 3363);
R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterA, 3365);
R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterB, 3366);
R_DEFINE_ERROR_RESULT(AllocationFailureInPathNormalizer, 3367);
R_DEFINE_ERROR_RESULT(AllocationFailureInDbmRomKeyValueStorage, 3375);
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemE, 3377);
R_DEFINE_ERROR_RESULT(AllocationFailureInReadOnlyFileSystemA, 3386);
R_DEFINE_ERROR_RESULT(AllocationFailureInAesCtrCounterExtendedStorageA, 3399);
R_DEFINE_ERROR_RESULT(AllocationFailureInAesCtrCounterExtendedStorageB, 3400);
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemInterfaceAdapter, 3407);
R_DEFINE_ERROR_RESULT(AllocationFailureInBufferedStorageA, 3411);
R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityRomFsStorageA, 3412);
R_DEFINE_ERROR_RESULT(AllocationFailureInNew, 3420);
R_DEFINE_ERROR_RESULT(AllocationFailureInMakeUnique, 3422);
R_DEFINE_ERROR_RESULT(AllocationFailureInAllocateShared, 3423);
R_DEFINE_ERROR_RESULT(AllocationFailurePooledBufferNotEnoughSize, 3424);
R_DEFINE_ERROR_RANGE(MmcAccessFailed, 3500, 3999);
@ -100,6 +120,28 @@ namespace ams::fs {
R_DEFINE_ERROR_RANGE(RomCorrupted, 4001, 4299);
R_DEFINE_ERROR_RESULT(UnsupportedRomVersion, 4002);
R_DEFINE_ERROR_RANGE(AesCtrCounterExtendedStorageCorrupted, 4011, 4019);
R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedEntryOffset, 4012);
R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedTableSize, 4013);
R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedGeneration, 4014);
R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedOffset, 4015);
R_DEFINE_ERROR_RANGE(IndirectStorageCorrupted, 4021, 4029);
R_DEFINE_ERROR_RESULT(InvalidIndirectEntryOffset, 4022);
R_DEFINE_ERROR_RESULT(InvalidIndirectEntryStorageIndex, 4023);
R_DEFINE_ERROR_RESULT(InvalidIndirectStorageSize, 4024);
R_DEFINE_ERROR_RESULT(InvalidIndirectVirtualOffset, 4025);
R_DEFINE_ERROR_RESULT(InvalidIndirectPhysicalOffset, 4026);
R_DEFINE_ERROR_RESULT(InvalidIndirectStorageIndex, 4027);
R_DEFINE_ERROR_RANGE(BucketTreeCorrupted, 4031, 4039);
R_DEFINE_ERROR_RESULT(InvalidBucketTreeSignature, 4032);
R_DEFINE_ERROR_RESULT(InvalidBucketTreeEntryCount, 4033);
R_DEFINE_ERROR_RESULT(InvalidBucketTreeNodeEntryCount, 4034);
R_DEFINE_ERROR_RESULT(InvalidBucketTreeNodeOffset, 4035);
R_DEFINE_ERROR_RESULT(InvalidBucketTreeEntryOffset, 4036);
R_DEFINE_ERROR_RESULT(InvalidBucketTreeEntrySetOffset, 4037);
R_DEFINE_ERROR_RANGE(RomNcaCorrupted, 4041, 4139);
R_DEFINE_ERROR_RANGE(RomNcaFileSystemCorrupted, 4051, 4069);
R_DEFINE_ERROR_RESULT(InvalidRomNcaFileSystemType, 4052);
@ -154,6 +196,9 @@ namespace ams::fs {
R_DEFINE_ERROR_RANGE(SaveDataCorrupted, 4301, 4499);
R_DEFINE_ERROR_RANGE(NcaCorrupted, 4501, 4599);
R_DEFINE_ERROR_RESULT(NcaBaseStorageOutOfRangeA, 4508);
R_DEFINE_ERROR_RESULT(NcaBaseStorageOutOfRangeB, 4509);
R_DEFINE_ERROR_RANGE(NcaFileSystemCorrupted, 4511, 4529);
R_DEFINE_ERROR_RESULT(InvalidNcaFileSystemType, 4512);
R_DEFINE_ERROR_RESULT(InvalidAcidFileSize, 4513);
@ -167,6 +212,12 @@ namespace ams::fs {
R_DEFINE_ERROR_RESULT(InvalidNcaKeyIndex, 4521);
R_DEFINE_ERROR_RESULT(InvalidNcaFsHeaderHashType, 4522);
R_DEFINE_ERROR_RESULT(InvalidNcaFsHeaderEncryptionType, 4523);
R_DEFINE_ERROR_RESULT(InvalidNcaPatchInfoIndirectSize, 4524);
R_DEFINE_ERROR_RESULT(InvalidNcaPatchInfoAesCtrExSize, 4525);
R_DEFINE_ERROR_RESULT(InvalidNcaPatchInfoAesCtrExOffset, 4526);
R_DEFINE_ERROR_RESULT(InvalidNcaId, 4527);
R_DEFINE_ERROR_RESULT(InvalidNcaHeader, 4528);
R_DEFINE_ERROR_RESULT(InvalidNcaFsHeader, 4529);
R_DEFINE_ERROR_RANGE(NcaHierarchicalSha256StorageCorrupted, 4531, 4539);
R_DEFINE_ERROR_RESULT(InvalidHierarchicalSha256BlockSize, 4532);
@ -174,6 +225,9 @@ namespace ams::fs {
R_DEFINE_ERROR_RESULT(HierarchicalSha256BaseStorageTooLarge, 4534);
R_DEFINE_ERROR_RESULT(HierarchicalSha256HashVerificationFailed, 4535);
/* TODO: Range? */
R_DEFINE_ERROR_RESULT(InvalidNcaHeader1SignatureKeyGeneration, 4543);
R_DEFINE_ERROR_RANGE(IntegrityVerificationStorageCorrupted, 4601, 4639);
R_DEFINE_ERROR_RESULT(IncorrectIntegrityVerificationMagic, 4602);
R_DEFINE_ERROR_RESULT(InvalidZeroHash, 4603);
@ -254,28 +308,51 @@ namespace ams::fs {
R_DEFINE_ERROR_RESULT(WriteNotPermitted, 6203);
R_DEFINE_ERROR_RANGE(UnsupportedOperation, 6300, 6399);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInSubStorageA, 6302);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInSubStorageB, 6303);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInMemoryStorageA, 6304);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInMemoryStorageB, 6305);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileStorageA, 6306);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileStorageB, 6307);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrStorageA, 6315);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileServiceObjectAdapterA, 6362);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemA, 6364);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemB, 6365);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemC, 6366);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileA, 6367);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileB, 6368);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateA, 6369);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateB, 6370);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateC, 6371);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileA, 6372);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileB, 6373);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileSystemA, 6374);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileSystemB, 6375);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileA, 6376);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileB, 6377);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInSubStorageA, 6302);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInSubStorageB, 6303);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInMemoryStorageA, 6304);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInMemoryStorageB, 6305);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileStorageA, 6306);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileStorageB, 6307);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInSwitchStorageA, 6308);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageA, 6310);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageB, 6311);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageC, 6312);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrStorageExternalA, 6313);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrStorageExternalB, 6314);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrStorageA, 6315);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInHierarchicalIntegrityVerificationStorageA, 6316);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInHierarchicalIntegrityVerificationStorageB, 6317);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityVerificationStorageA, 6318);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityVerificationStorageB, 6319);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityVerificationStorageC, 6320);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInBlockCacheBufferedStorageA, 6321);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInBlockCacheBufferedStorageB, 6322);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInBlockCacheBufferedStorageC, 6323);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInIndirectStorageA, 6324);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInIndirectStorageB, 6325);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInIndirectStorageC, 6326);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInZeroStorageA, 6327);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInZeroStorageB, 6328);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInHierarchicalSha256StorageA, 6329);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyBlockCacheStorageA, 6330);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyBlockCacheStorageB, 6331);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityRomFsStorageA , 6332);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileServiceObjectAdapterA, 6362);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemA, 6364);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemB, 6365);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemC, 6366);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileA, 6367);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileB, 6368);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateA, 6369);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateB, 6370);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateC, 6371);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileA, 6372);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileB, 6373);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileSystemA, 6374);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileSystemB, 6375);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileA, 6376);
R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileB, 6377);
R_DEFINE_ERROR_RANGE(PermissionDenied, 6400, 6449);

View file

@ -36,3 +36,4 @@
#include <vapours/util/util_uuid.hpp>
#include <vapours/util/util_bounded_map.hpp>
#include <vapours/util/util_string_util.hpp>
#include <vapours/util/util_variadic.hpp>

View file

@ -208,4 +208,11 @@ namespace ams::util {
return T(1) << (BITSIZEOF(T) - CountLeadingZeros(x) - 1);
}
template<typename T, typename U>
constexpr ALWAYS_INLINE T DivideUp(T v, U d) {
using Unsigned = typename std::make_unsigned<U>::type;
const Unsigned add = static_cast<Unsigned>(d) - 1;
return static_cast<T>((v + add) / d);
}
}

View file

@ -0,0 +1,84 @@
/*
* 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/>.
*/
#pragma once
#include <vapours/common.hpp>
#include <vapours/assert.hpp>
#define AMS_UTIL_VARIADIC_INVOKE_MACRO(__HANDLER__) \
__HANDLER__(_01_) \
__HANDLER__(_02_) \
__HANDLER__(_03_) \
__HANDLER__(_04_) \
__HANDLER__(_05_) \
__HANDLER__(_06_) \
__HANDLER__(_07_) \
__HANDLER__(_08_) \
__HANDLER__(_09_) \
__HANDLER__(_0A_) \
__HANDLER__(_0B_) \
__HANDLER__(_0C_) \
__HANDLER__(_0D_) \
__HANDLER__(_0E_) \
__HANDLER__(_0F_)
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_01_(_T_) typename _T_##_01_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_02_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_01_(_T_), typename _T_##_02_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_03_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_02_(_T_), typename _T_##_03_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_04_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_03_(_T_), typename _T_##_04_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_05_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_04_(_T_), typename _T_##_05_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_06_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_05_(_T_), typename _T_##_06_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_07_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_06_(_T_), typename _T_##_07_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_08_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_07_(_T_), typename _T_##_08_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_09_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_08_(_T_), typename _T_##_09_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_0A_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_09_(_T_), typename _T_##_0A_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_0B_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_0A_(_T_), typename _T_##_0B_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_0C_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_0B_(_T_), typename _T_##_0C_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_0D_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_0C_(_T_), typename _T_##_0D_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_0E_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_0D_(_T_), typename _T_##_0E_
#define AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_0F_(_T_) AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS_0E_(_T_), typename _T_##_0F_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_01_(_T_, _N_) _T_##_01_ &&_N_##_01_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_02_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_01_(_T_, _N_), _T_##_02_ &&_N_##_02_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_03_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_02_(_T_, _N_), _T_##_03_ &&_N_##_03_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_04_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_03_(_T_, _N_), _T_##_04_ &&_N_##_04_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_05_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_04_(_T_, _N_), _T_##_05_ &&_N_##_05_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_06_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_05_(_T_, _N_), _T_##_06_ &&_N_##_06_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_07_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_06_(_T_, _N_), _T_##_07_ &&_N_##_07_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_08_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_07_(_T_, _N_), _T_##_08_ &&_N_##_08_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_09_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_08_(_T_, _N_), _T_##_09_ &&_N_##_09_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_0A_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_09_(_T_, _N_), _T_##_0A_ &&_N_##_0A_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_0B_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_0A_(_T_, _N_), _T_##_0B_ &&_N_##_0B_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_0C_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_0B_(_T_, _N_), _T_##_0C_ &&_N_##_0C_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_0D_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_0C_(_T_, _N_), _T_##_0D_ &&_N_##_0D_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_0E_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_0D_(_T_, _N_), _T_##_0E_ &&_N_##_0E_
#define AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_0F_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS_0E_(_T_, _N_), _T_##_0F_ &&_N_##_0F_
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_01_(_T_, _N_) ::std::forward<_T_##_01_>(_N_##_01_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_02_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_01_(_T_, _N_), ::std::forward<_T_##_02_>(_N_##_02_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_03_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_02_(_T_, _N_), ::std::forward<_T_##_03_>(_N_##_03_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_04_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_03_(_T_, _N_), ::std::forward<_T_##_04_>(_N_##_04_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_05_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_04_(_T_, _N_), ::std::forward<_T_##_05_>(_N_##_05_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_06_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_05_(_T_, _N_), ::std::forward<_T_##_06_>(_N_##_06_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_07_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_06_(_T_, _N_), ::std::forward<_T_##_07_>(_N_##_07_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_08_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_07_(_T_, _N_), ::std::forward<_T_##_08_>(_N_##_08_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_09_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_08_(_T_, _N_), ::std::forward<_T_##_09_>(_N_##_09_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_0A_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_09_(_T_, _N_), ::std::forward<_T_##_0A_>(_N_##_0A_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_0B_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_0A_(_T_, _N_), ::std::forward<_T_##_0B_>(_N_##_0B_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_0C_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_0B_(_T_, _N_), ::std::forward<_T_##_0C_>(_N_##_0C_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_0D_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_0C_(_T_, _N_), ::std::forward<_T_##_0D_>(_N_##_0D_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_0E_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_0D_(_T_, _N_), ::std::forward<_T_##_0E_>(_N_##_0E_)
#define AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_0F_(_T_, _N_) AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS_0E_(_T_, _N_), ::std::forward<_T_##_0F_>(_N_##_0F_)