|
|
@ -423,7 +423,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk |
|
|
RemoveCachedContents(); |
|
|
RemoveCachedContents(); |
|
|
|
|
|
|
|
|
// Gen keys if necessary
|
|
|
// Gen keys if necessary
|
|
|
OnReinitializeKeys(ReinitializeKeyBehavior::NoWarning); |
|
|
|
|
|
|
|
|
OnCheckFirmwareDecryption(); |
|
|
|
|
|
|
|
|
game_list->LoadCompatibilityList(); |
|
|
game_list->LoadCompatibilityList(); |
|
|
game_list->PopulateAsync(UISettings::values.game_dirs); |
|
|
game_list->PopulateAsync(UISettings::values.game_dirs); |
|
|
@ -1574,8 +1574,6 @@ void GMainWindow::ConnectMenuEvents() { |
|
|
connect(multiplayer_state, &MultiplayerState::SaveConfig, this, &GMainWindow::OnSaveConfig); |
|
|
connect(multiplayer_state, &MultiplayerState::SaveConfig, this, &GMainWindow::OnSaveConfig); |
|
|
|
|
|
|
|
|
// Tools
|
|
|
// Tools
|
|
|
connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this, |
|
|
|
|
|
ReinitializeKeyBehavior::Warning)); |
|
|
|
|
|
connect_menu(ui->action_Load_Album, &GMainWindow::OnAlbum); |
|
|
connect_menu(ui->action_Load_Album, &GMainWindow::OnAlbum); |
|
|
connect_menu(ui->action_Load_Cabinet_Nickname_Owner, |
|
|
connect_menu(ui->action_Load_Cabinet_Nickname_Owner, |
|
|
[this]() { OnCabinet(Service::NFP::CabinetMode::StartNicknameAndOwnerSettings); }); |
|
|
[this]() { OnCabinet(Service::NFP::CabinetMode::StartNicknameAndOwnerSettings); }); |
|
|
@ -4551,122 +4549,20 @@ void GMainWindow::OnMouseActivity() { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { |
|
|
|
|
|
if (behavior == ReinitializeKeyBehavior::Warning) { |
|
|
|
|
|
const auto res = QMessageBox::information( |
|
|
|
|
|
this, tr("Confirm Key Rederivation"), |
|
|
|
|
|
tr("You are about to force rederive all of your keys. \nIf you do not know what " |
|
|
|
|
|
"this " |
|
|
|
|
|
"means or what you are doing, \nthis is a potentially destructive action. " |
|
|
|
|
|
"\nPlease " |
|
|
|
|
|
"make sure this is what you want \nand optionally make backups.\n\nThis will " |
|
|
|
|
|
"delete " |
|
|
|
|
|
"your autogenerated key files and re-run the key derivation module."), |
|
|
|
|
|
QMessageBox::StandardButtons{QMessageBox::Ok, QMessageBox::Cancel}); |
|
|
|
|
|
|
|
|
|
|
|
if (res == QMessageBox::Cancel) |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
const auto keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir); |
|
|
|
|
|
|
|
|
|
|
|
Common::FS::RemoveFile(keys_dir / "prod.keys_autogenerated"); |
|
|
|
|
|
Common::FS::RemoveFile(keys_dir / "console.keys_autogenerated"); |
|
|
|
|
|
Common::FS::RemoveFile(keys_dir / "title.keys_autogenerated"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); |
|
|
|
|
|
bool all_keys_present{true}; |
|
|
|
|
|
|
|
|
|
|
|
if (keys.BaseDeriveNecessary()) { |
|
|
|
|
|
Core::Crypto::PartitionDataManager pdm{vfs->OpenDirectory("", FileSys::Mode::Read)}; |
|
|
|
|
|
|
|
|
|
|
|
const auto function = [this, &keys, &pdm] { |
|
|
|
|
|
keys.PopulateFromPartitionData(pdm); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void GMainWindow::OnCheckFirmwareDecryption() { |
|
|
system->GetFileSystemController().CreateFactories(*vfs); |
|
|
system->GetFileSystemController().CreateFactories(*vfs); |
|
|
keys.DeriveETicket(pdm, system->GetContentProvider()); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
QString errors; |
|
|
|
|
|
if (!pdm.HasFuses()) { |
|
|
|
|
|
errors += tr("Missing fuses"); |
|
|
|
|
|
} |
|
|
|
|
|
if (!pdm.HasBoot0()) { |
|
|
|
|
|
errors += tr(" - Missing BOOT0"); |
|
|
|
|
|
} |
|
|
|
|
|
if (!pdm.HasPackage2()) { |
|
|
|
|
|
errors += tr(" - Missing BCPKG2-1-Normal-Main"); |
|
|
|
|
|
} |
|
|
|
|
|
if (!pdm.HasProdInfo()) { |
|
|
|
|
|
errors += tr(" - Missing PRODINFO"); |
|
|
|
|
|
} |
|
|
|
|
|
if (!errors.isEmpty()) { |
|
|
|
|
|
all_keys_present = false; |
|
|
|
|
|
|
|
|
if (!ContentManager::AreKeysPresent()) { |
|
|
QMessageBox::warning( |
|
|
QMessageBox::warning( |
|
|
this, tr("Derivation Components Missing"), |
|
|
this, tr("Derivation Components Missing"), |
|
|
tr("Encryption keys are missing. " |
|
|
tr("Encryption keys are missing. " |
|
|
"<br>Please follow <a href='https://yuzu-emu.org/help/quickstart/'>the yuzu " |
|
|
|
|
|
"quickstart guide</a> to get all your keys, firmware and " |
|
|
|
|
|
"games.<br><br><small>(%1)</small>") |
|
|
|
|
|
.arg(errors)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
QProgressDialog prog(this); |
|
|
|
|
|
prog.setRange(0, 0); |
|
|
|
|
|
prog.setLabelText(tr("Deriving keys...\nThis may take up to a minute depending \non your " |
|
|
|
|
|
"system's performance.")); |
|
|
|
|
|
prog.setWindowTitle(tr("Deriving Keys")); |
|
|
|
|
|
|
|
|
|
|
|
prog.show(); |
|
|
|
|
|
|
|
|
|
|
|
auto future = QtConcurrent::run(function); |
|
|
|
|
|
while (!future.isFinished()) { |
|
|
|
|
|
QCoreApplication::processEvents(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
prog.close(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
system->GetFileSystemController().CreateFactories(*vfs); |
|
|
|
|
|
|
|
|
|
|
|
if (all_keys_present && !this->CheckSystemArchiveDecryption()) { |
|
|
|
|
|
LOG_WARNING(Frontend, "Mii model decryption failed"); |
|
|
|
|
|
QMessageBox::warning( |
|
|
|
|
|
this, tr("System Archive Decryption Failed"), |
|
|
|
|
|
tr("Encryption keys failed to decrypt firmware. " |
|
|
|
|
|
"<br>Please follow <a href='https://yuzu-emu.org/help/quickstart/'>the yuzu " |
|
|
"<br>Please follow <a href='https://yuzu-emu.org/help/quickstart/'>the yuzu " |
|
|
"quickstart guide</a> to get all your keys, firmware and " |
|
|
"quickstart guide</a> to get all your keys, firmware and " |
|
|
"games.")); |
|
|
"games.")); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
SetFirmwareVersion(); |
|
|
SetFirmwareVersion(); |
|
|
|
|
|
|
|
|
if (behavior == ReinitializeKeyBehavior::Warning) { |
|
|
|
|
|
game_list->PopulateAsync(UISettings::values.game_dirs); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
UpdateMenuState(); |
|
|
UpdateMenuState(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool GMainWindow::CheckSystemArchiveDecryption() { |
|
|
|
|
|
constexpr u64 MiiModelId = 0x0100000000000802; |
|
|
|
|
|
|
|
|
|
|
|
auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); |
|
|
|
|
|
if (!bis_system) { |
|
|
|
|
|
// Not having system BIS files is not an error.
|
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
auto mii_nca = bis_system->GetEntry(MiiModelId, FileSys::ContentRecordType::Data); |
|
|
|
|
|
if (!mii_nca) { |
|
|
|
|
|
// Not having the Mii model is not an error.
|
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Return whether we are able to decrypt the RomFS of the Mii model.
|
|
|
|
|
|
return mii_nca->GetRomFS().get() != nullptr; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool GMainWindow::CheckFirmwarePresence() { |
|
|
bool GMainWindow::CheckFirmwarePresence() { |
|
|
constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit); |
|
|
constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit); |
|
|
|
|
|
|
|
|
|