bool CBoot::BootNANDTitle(const u64 title_id) { UpdateStateFlags([](StateFlags* state) { state->type = 0x04; // TYPE_NANDBOOT }); auto es = IOS::HLE::GetIOS()->GetES(); const IOS::ES::TicketReader ticket = es->FindSignedTicket(title_id); auto console_type = IOS::HLE::IOSC::ConsoleType::Retail; if (ticket.IsValid()) console_type = ticket.GetConsoleType(); else ERROR_LOG(BOOT, "No ticket was found for %016" PRIx64, title_id); SetupWiiMemory(console_type); return es->LaunchTitle(title_id); }
ReturnCode ES::ImportTitleInit(Context& context, const std::vector<u8>& tmd_bytes, const std::vector<u8>& cert_chain) { INFO_LOG(IOS_ES, "ImportTitleInit"); ResetTitleImportContext(&context, m_ios.GetIOSC()); context.title_import_export.tmd.SetBytes(tmd_bytes); if (!context.title_import_export.tmd.IsValid()) { ERROR_LOG(IOS_ES, "Invalid TMD while adding title (size = %zd)", tmd_bytes.size()); return ES_EINVAL; } // Finish a previous import (if it exists). FinishStaleImport(context.title_import_export.tmd.GetTitleId()); ReturnCode ret = VerifyContainer(VerifyContainerType::TMD, VerifyMode::UpdateCertStore, context.title_import_export.tmd, cert_chain); if (ret != IPC_SUCCESS) return ret; const auto ticket = FindSignedTicket(context.title_import_export.tmd.GetTitleId()); if (!ticket.IsValid()) return ES_NO_TICKET; std::vector<u8> cert_store; ret = ReadCertStore(&cert_store); if (ret != IPC_SUCCESS) return ret; ret = VerifyContainer(VerifyContainerType::Ticket, VerifyMode::DoNotUpdateCertStore, ticket, cert_store); if (ret != IPC_SUCCESS) return ret; ret = InitTitleImportKey(ticket.GetBytes(), m_ios.GetIOSC(), &context.title_import_export.key_handle); if (ret != IPC_SUCCESS) return ret; if (!InitImport(context.title_import_export.tmd)) return ES_EIO; context.title_import_export.valid = true; return IPC_SUCCESS; }
ReturnCode ES::DeleteTicket(const u8* ticket_view) { const auto fs = m_ios.GetFS(); const u64 title_id = Common::swap64(ticket_view + offsetof(IOS::ES::TicketView, title_id)); if (!CanDeleteTitle(title_id)) return ES_EINVAL; auto ticket = FindSignedTicket(title_id); if (!ticket.IsValid()) return FS_ENOENT; const u64 ticket_id = Common::swap64(ticket_view + offsetof(IOS::ES::TicketView, ticket_id)); ticket.DeleteTicket(ticket_id); const std::vector<u8>& new_ticket = ticket.GetBytes(); const std::string ticket_path = Common::GetTicketFileName(title_id); if (!new_ticket.empty()) { const auto file = fs->OpenFile(PID_KERNEL, PID_KERNEL, ticket_path, FS::Mode::ReadWrite); if (!file || !file->Write(new_ticket.data(), new_ticket.size())) return ES_EIO; } else { // Delete the ticket file if it is now empty. fs->Delete(PID_KERNEL, PID_KERNEL, ticket_path); } // Delete the ticket directory if it is now empty. const std::string ticket_parent_dir = StringFromFormat("/ticket/%08x", static_cast<u32>(title_id >> 32)); const auto ticket_parent_dir_entries = fs->ReadDirectory(PID_KERNEL, PID_KERNEL, ticket_parent_dir); if (ticket_parent_dir_entries && ticket_parent_dir_entries->empty()) fs->Delete(PID_KERNEL, PID_KERNEL, ticket_parent_dir); return IPC_SUCCESS; }