This commit is contained in:
Pika 2019-05-01 16:50:21 -04:00
parent 8f3919407b
commit ae885e6531
3 changed files with 52 additions and 44 deletions

View File

@ -262,18 +262,22 @@ Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out
const bool is_sysmodule = TitleIdIsSystem(this->title_id); const bool is_sysmodule = TitleIdIsSystem(this->title_id);
const bool has_bis_write_flag = Utils::HasFlag(this->title_id, "bis_write"); const bool has_bis_write_flag = Utils::HasFlag(this->title_id, "bis_write");
const bool has_cal0_read_flag = Utils::HasFlag(this->title_id, "cal_read"); const bool has_cal0_read_flag = Utils::HasFlag(this->title_id, "cal_read");
const bool has_blank_cal0_flag = Utils::HasGlobalFlag("blank_prodinfo");
if (bis_partition_id == BisStorageId_Boot0) { if (bis_partition_id == BisStorageId_Boot0) {
storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->title_id)); storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->title_id));
} else if (bis_partition_id == BisStorageId_Prodinfo) { } else if (bis_partition_id == BisStorageId_Prodinfo) {
bool has_blank_cal0_flag = true; // See PR details if (has_blank_cal0_flag) {
FsFile file;
/* PRODINFO should *never* be writable. */ rc = Utils::OpenBlankProdinfoFile(&file);
if (is_sysmodule || has_cal0_read_flag) { if (R_FAILED(rc)) {
return rc;
}
storage = std::make_shared<IStorageInterface>(new FileStorage(new ProxyFile(&file))); /* Should we make this read-only? */
} else if (is_sysmodule || has_cal0_read_flag) {
/* PRODINFO should *never* be writable. */
storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage));
} else if (has_blank_cal0_flag) {
FsFile file = Utils::GetBlankProdinfoFileHandle();
storage = std::make_shared<IStorageInterface>(new FileStorage(std::make_shared<ProxyFile>(&file)));
} else { } else {
/* Do not allow non-sysmodules to read *or* write CAL0. */ /* Do not allow non-sysmodules to read *or* write CAL0. */
fsStorageClose(&bis_storage); fsStorageClose(&bis_storage);

View File

@ -669,59 +669,59 @@ void Utils::RebootToFatalError(AtmosphereFatalErrorContext *ctx) {
} }
void Utils::CreateBlankProdinfoIfNeeded() { void Utils::CreateBlankProdinfoIfNeeded() {
/* if (!Utils::HasGlobalFlag("blank_prodinfo")) { const bool p = Utils::GetCAL0BackupBufferToBlank();
return;
} */
Result rc; Result rc;
FsFile file;
u8* buffer = g_cal0_backup; rc = fsFsOpenFile(&g_sd_filesystem, "/atmosphere/automatic_backups/prodinfo_blank.bin", FS_OPEN_READ, &file);
if (R_SUCCEEDED(rc)) {
fsFileClose(&file);
return;
}
// big brain: modify buffer inline // big brain: modify buffer inline
const char* serial = "XAW00000000000"; // TODO: Make this configurable? const char serial[] = "XAW00000000000";
memcpy(&buffer[0x250], serial, strlen(serial)); memcpy(p ? &g_cal0_backup[0x250] : &g_cal0_storage_backup[0x250], serial, sizeof(serial) - 1);
const u64 erasePoints[14] = {0xAE0, 0x800, 0x3AE0, 0x130, 0x35E1, 0x6, 0x36E1, 0x6, 0x2B0, 0x180, 0x3D70, 0x240, 0x3FC0, 0x240}; // offset, size static constexpr u64 erase_offsets[7] = {0xAE0, 0x3AE0, 0x35E1, 0x36E1, 0x2B0, 0x3D70, 0x3FC0};
static constexpr u64 erase_sizes[7] = {0x800, 0x130, 0x6, 0x6, 0x180, 0x240, 0x240};
for (u64 i = 0; i < 14; i = i + 2) { for (size_t i = 0; i < 7; i++) {
u64 offset = erasePoints[i]; u64 offset = erase_offsets[i];
u64 size = erasePoints[i + 1]; u64 size = erase_sizes[i];
memset(&buffer[offset], 0, size); memset(p ? &g_cal0_backup[offset] : &g_cal0_storage_backup[offset], 0, size);
} }
const u64 hashPoints[6] = {0x12E0, 0xAE0, buffer[0xAD0], 0x20, 0x40, buffer[0x8]}; // hash offset, data offset, data size static constexpr u64 hash_offsets[2] = {0x12E0, 0x20};
static constexpr u64 data_offsets[2] = {0xAE0, 0x40};
u64 data_sizes[2] = {p ? g_cal0_backup[0xAD0] : g_cal0_storage_backup[0xAD0], p ? g_cal0_backup[0x8] : g_cal0_storage_backup[0x8]};
for (u64 i = 0; i < 6; i = i + 3) { for (size_t i = 0; i < 2; i++) {
u64 hashOffset = hashPoints[i]; u64 hash_offset = hash_offsets[i];
u64 dataOffset = hashPoints[i + 1]; u64 data_offset = data_offsets[i];
u64 dataSize = hashPoints[i + 2]; u64 data_size = data_sizes[i];
u8 data[dataSize]; u8 data[data_size];
memset(&data, buffer[dataOffset], dataSize); memset(&data, p ? g_cal0_backup[data_offset] : g_cal0_storage_backup[data_offset], data_size);
u8 hash[0x20]; u8 hash[0x20];
Sha256Context ctx; Sha256Context ctx;
sha256ContextCreate(&ctx); sha256ContextCreate(&ctx);
sha256ContextUpdate(&ctx, data, dataSize); sha256ContextUpdate(&ctx, data, data_size);
sha256ContextGetHash(&ctx, &hash); sha256ContextGetHash(&ctx, &hash);
memcpy(&buffer[hashOffset], hash, 0x20); memcpy(p ? &g_cal0_backup[hash_offset] : &g_cal0_storage_backup[hash_offset], hash, 0x20);
} }
rc = fsFsCreateFile(&g_sd_filesystem, "/atmosphere/automatic_backups/prodinfo_blank.bin", ProdinfoSize, 0);
if (R_FAILED(rc)) {
std::abort();
}
FsFile file;
rc = fsFsOpenFile(&g_sd_filesystem, "/atmosphere/automatic_backups/prodinfo_blank.bin", FS_OPEN_WRITE, &file); rc = fsFsOpenFile(&g_sd_filesystem, "/atmosphere/automatic_backups/prodinfo_blank.bin", FS_OPEN_WRITE, &file);
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
std::abort(); std::abort();
@ -732,7 +732,7 @@ void Utils::CreateBlankProdinfoIfNeeded() {
std::abort(); std::abort();
} }
rc = fsFileWrite(&file, 0, buffer, ProdinfoSize); rc = fsFileWrite(&file, 0, p ? g_cal0_backup : g_cal0_storage_backup, ProdinfoSize);
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
std::abort(); std::abort();
} }
@ -745,10 +745,13 @@ void Utils::CreateBlankProdinfoIfNeeded() {
fsFileClose(&file); fsFileClose(&file);
} }
FsFile Utils::GetBlankProdinfoFileHandle() { Result Utils::OpenBlankProdinfoFile(FsFile *out) {
FsFile file; return fsFsOpenFile(&g_sd_filesystem, "/atmosphere/automatic_backups/prodinfo_blank.bin", FS_OPEN_READ, out);
}
fsFsOpenFile(&g_sd_filesystem, "/atmosphere/automatic_backups/prodinfo_blank.bin", FS_OPEN_READ, &file);
bool Utils::GetCAL0BackupBufferToBlank() { // true = g_cal0_backup, false = g_cal0_storage_backup
return file; bool is_cal0_valid = true;
is_cal0_valid &= memcmp(g_cal0_backup, "CAL0", 4) == 0;
return is_cal0_valid;
} }

View File

@ -91,8 +91,9 @@ class Utils {
/* Error occurred. */ /* Error occurred. */
static void RebootToFatalError(AtmosphereFatalErrorContext *ctx); static void RebootToFatalError(AtmosphereFatalErrorContext *ctx);
static FsFile GetBlankProdinfoFileHandle(); static Result OpenBlankProdinfoFile(FsFile *out);
private: private:
static void RefreshConfiguration(); static void RefreshConfiguration();
static void CreateBlankProdinfoIfNeeded(); static void CreateBlankProdinfoIfNeeded();
static bool GetCAL0BackupBufferToBlank();
}; };