service: nfc: Validate mii data

This commit is contained in:
german77 2023-11-25 22:19:46 -06:00
parent 090ea0281c
commit 281eb020ea
4 changed files with 40 additions and 35 deletions

View File

@ -130,7 +130,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name)
nfp_device->DeleteApplicationArea(); nfp_device->DeleteApplicationArea();
break; break;
case Service::NFP::CabinetMode::StartRestorer: case Service::NFP::CabinetMode::StartRestorer:
nfp_device->RestoreAmiibo(); nfp_device->Restore();
break; break;
case Service::NFP::CabinetMode::StartFormatter: case Service::NFP::CabinetMode::StartFormatter:
nfp_device->Format(); nfp_device->Format();

View File

@ -98,7 +98,7 @@ void Ver3StoreData::BuildToStoreData(StoreData& out_store_data) const {
} }
void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) { void Ver3StoreData::BuildFromStoreData(const StoreData& store_data) {
version = 1; version = 3;
mii_information.gender.Assign(static_cast<u8>(store_data.GetGender())); mii_information.gender.Assign(static_cast<u8>(store_data.GetGender()));
mii_information.favorite_color.Assign(static_cast<u8>(store_data.GetFavoriteColor())); mii_information.favorite_color.Assign(static_cast<u8>(store_data.GetFavoriteColor()));
height = store_data.GetHeight(); height = store_data.GetHeight();

View File

@ -401,6 +401,12 @@ Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& time
} }
Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target_) { Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target_) {
bool is_corrupted = false;
if (model_type != NFP::ModelType::Amiibo) {
return ResultInvalidArgument;
}
if (device_state != DeviceState::TagFound) { if (device_state != DeviceState::TagFound) {
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
return ResultWrongDeviceState; return ResultWrongDeviceState;
@ -420,26 +426,32 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target
if (is_plain_amiibo) { if (is_plain_amiibo) {
std::vector<u8> data(sizeof(NFP::NTAG215File)); std::vector<u8> data(sizeof(NFP::NTAG215File));
memcpy(data.data(), &tag_data, sizeof(tag_data)); memcpy(data.data(), &tag_data, sizeof(tag_data));
WriteBackupData(tag_data.uid, data);
device_state = DeviceState::TagMounted;
mount_target = mount_target_;
return ResultSuccess;
} }
if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { if (!is_plain_amiibo && !NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) {
bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess(); LOG_ERROR(Service_NFP, "Can't decode amiibo");
LOG_ERROR(Service_NFP, "Can't decode amiibo, has_backup= {}", has_backup); is_corrupted = true;
return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData;
} }
std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); if (tag_data.settings.settings.amiibo_initialized && !tag_data.owner_mii.IsValid()) {
memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); LOG_ERROR(Service_NFP, "Invalid mii data");
WriteBackupData(encrypted_tag_data.uuid, data); is_corrupted = true;
}
if (!is_corrupted) {
std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File));
memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data));
WriteBackupData(encrypted_tag_data.uuid, data);
}
device_state = DeviceState::TagMounted; device_state = DeviceState::TagMounted;
mount_target = mount_target_; mount_target = mount_target_;
if (is_corrupted) {
bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess();
return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData;
}
return ResultSuccess; return ResultSuccess;
} }
@ -606,6 +618,17 @@ Result NfcDevice::Restore() {
} }
} }
// Restore mii data in case is corrupted by previous instances of yuzu
if (tag_data.settings.settings.amiibo_initialized && !tag_data.owner_mii.IsValid()) {
LOG_ERROR(Service_NFP, "Regenerating mii data");
Mii::StoreData new_mii{};
new_mii.BuildRandom(Mii::Age::All, Mii::Gender::All, Mii::Race::All);
new_mii.SetNickname({u'y', u'u', u'z', u'u', u'\0'});
tag_data.owner_mii.BuildFromStoreData(new_mii);
tag_data.mii_extension.SetFromStoreData(new_mii);
}
// Overwrite tag contents with backup and mount the tag // Overwrite tag contents with backup and mount the tag
tag_data = temporary_tag_data; tag_data = temporary_tag_data;
encrypted_tag_data = temporary_encrypted_tag_data; encrypted_tag_data = temporary_encrypted_tag_data;
@ -851,25 +874,6 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe
return Flush(); return Flush();
} }
Result NfcDevice::RestoreAmiibo() {
if (device_state != DeviceState::TagMounted) {
LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
if (device_state == DeviceState::TagRemoved) {
return ResultTagRemoved;
}
return ResultWrongDeviceState;
}
if (mount_target == NFP::MountTarget::None || mount_target == NFP::MountTarget::Rom) {
LOG_ERROR(Service_NFP, "Amiibo is read only", device_state);
return ResultWrongDeviceState;
}
// TODO: Load amiibo from backup on system
LOG_ERROR(Service_NFP, "Not Implemented");
return ResultSuccess;
}
Result NfcDevice::Format() { Result NfcDevice::Format() {
Result result = ResultSuccess; Result result = ResultSuccess;
@ -877,7 +881,9 @@ Result NfcDevice::Format() {
result = Mount(NFP::ModelType::Amiibo, NFP::MountTarget::All); result = Mount(NFP::ModelType::Amiibo, NFP::MountTarget::All);
} }
if (result.IsError()) { // We are formatting all data. Corruption is not an issue.
if (result.IsError() &&
(result != ResultCorruptedData && result != ResultCorruptedDataWithBackup)) {
return result; return result;
} }

View File

@ -68,7 +68,6 @@ public:
Result DeleteRegisterInfo(); Result DeleteRegisterInfo();
Result SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& register_info); Result SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& register_info);
Result RestoreAmiibo();
Result Format(); Result Format();
Result OpenApplicationArea(u32 access_id); Result OpenApplicationArea(u32 access_id);