Firmware 20.0.0 Initial Implementation & Android: Uninstall Firmware Button

Co-authored-by: Pavel Barabanov <pavelbarabanov94@gmail.com>
Reviewed-on: #89
Co-authored-by: crueter <crueter@noreply.localhost>
Co-committed-by: crueter <crueter@noreply.localhost>
This commit is contained in:
crueter 2025-05-07 20:15:25 +00:00 committed by edendev
parent 668bcb94db
commit 4661909f4c
18 changed files with 155 additions and 20 deletions

View file

@ -133,6 +133,11 @@ class InstallableFragment : Fragment() {
R.string.install_firmware_description,
install = { mainActivity.getFirmware.launch(arrayOf("application/zip")) }
),
Installable(
R.string.uninstall_firmware,
R.string.uninstall_firmware_description,
install = { mainActivity.uninstallFirmware() }
),
Installable(
R.string.install_prod_keys,
R.string.install_prod_keys_description,

View file

@ -376,7 +376,31 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
messageToShow
}.show(supportFragmentManager, ProgressDialogFragment.TAG)
}
fun uninstallFirmware() {
val firmwarePath = File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/")
ProgressDialogFragment.newInstance(
this,
R.string.firmware_uninstalling
) { progressCallback, _ ->
var messageToShow: Any
try {
// Ensure the firmware directory exists before attempting to delete
if (firmwarePath.exists()) {
firmwarePath.deleteRecursively()
// Optionally reinitialize the system or perform other necessary steps
NativeLibrary.initializeSystem(true)
homeViewModel.setCheckKeys(true)
messageToShow = getString(R.string.firmware_uninstalled_success)
} else {
messageToShow = getString(R.string.firmware_uninstalled_failure)
}
} catch (e: Exception) {
Log.error("[MainActivity] Firmware uninstall failed - ${e.message}")
messageToShow = getString(R.string.fatal_error)
}
messageToShow
}.show(supportFragmentManager, ProgressDialogFragment.TAG)
}
val getAmiiboKey =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result == null) {

View file

@ -143,6 +143,11 @@
<string name="firmware_installed_success">Firmware installed successfully</string>
<string name="firmware_installed_failure">Firmware installation failed</string>
<string name="firmware_installed_failure_description">Make sure the firmware nca files are at the root of the zip and try again.</string>
<string name="uninstall_firmware">Uninstall firmware</string>
<string name="uninstall_firmware_description">Uninstalling the firmware will remove it from the device and may affect game compatibility.</string>
<string name="firmware_uninstalling">Uninstalling firmware</string>
<string name="firmware_uninstalled_success">Firmware uninstalled successfully</string>
<string name="firmware_uninstalled_failure">Firmware uninstallation failed</string>
<string name="share_log">Share debug logs</string>
<string name="share_log_description">Share eden\'s log file to debug issues</string>
<string name="share_log_missing">No log file found</string>

View file

@ -60,24 +60,29 @@ std::unique_ptr<Process> CreateProcessImpl(std::unique_ptr<Loader::AppLoader>& o
} // Anonymous namespace
std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id,
u8 minimum_key_generation, u8 maximum_key_generation) {
FileSys::VirtualFile nca_raw = system.GetContentProviderUnion()
.GetEntryRaw(program_id, FileSys::ContentRecordType::Program);
u8 minimum_key_generation, u8 maximum_key_generation) {
// Attempt to load program NCA.
FileSys::VirtualFile nca_raw{};
// Get the program NCA from storage.
auto& storage = system.GetContentProviderUnion();
nca_raw = storage.GetEntryRaw(program_id, FileSys::ContentRecordType::Program);
// Ensure we retrieved a program NCA.
if (!nca_raw) {
return nullptr;
}
FileSys::NCA nca(nca_raw);
if (nca.GetStatus() != Loader::ResultStatus::Success) {
return nullptr;
}
u8 current_gen = nca.GetKeyGeneration();
if (minimum_key_generation > 0 && (current_gen < minimum_key_generation ||
current_gen > maximum_key_generation)) {
LOG_WARNING(Service_LDR, "Program {:016X} has unsupported generation {}. "
"Attempting to load anyway...", program_id, current_gen);
// Ensure we have a suitable version.
if (minimum_key_generation > 0) {
FileSys::NCA nca(nca_raw);
if (nca.GetStatus() == Loader::ResultStatus::Success &&
(nca.GetKeyGeneration() < minimum_key_generation ||
nca.GetKeyGeneration() > maximum_key_generation)) {
LOG_WARNING(Service_LDR, "Skipping program {:016X} with generation {}", program_id,
nca.GetKeyGeneration());
return nullptr;
}
}
std::unique_ptr<Loader::AppLoader> loader;
@ -101,7 +106,7 @@ std::unique_ptr<Process> CreateApplicationProcess(std::vector<u8>& out_control,
out_control = nacp.GetRawBytes();
} else {
out_control.resize(sizeof(FileSys::RawNACP));
std::fill(out_control.begin(), out_control.end(), (u8) 0);
std::fill(out_control.begin(), out_control.end(), 0);
}
auto& storage = system.GetContentProviderUnion();

View file

@ -18,6 +18,7 @@ IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& sys
// clang-format off
static const FunctionInfo functions[] = {
{100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"},
{110, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxyForDebug>, "OpenSystemAppletProxyForDebug"},
{200, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld>, "OpenLibraryAppletProxyOld"},
{201, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxy>, "OpenLibraryAppletProxy"},
{300, nullptr, "OpenOverlayAppletProxy"},
@ -25,6 +26,7 @@ IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& sys
{400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
{410, nullptr, "GetSystemAppletControllerForDebug"},
{450, D<&IAllSystemAppletProxiesService::GetSystemProcessCommonFunctions>, "GetSystemProcessCommonFunctions"}, // 19.0.0+
{460, nullptr, "Unknown460"},
{1000, nullptr, "GetDebugFunctions"},
};
// clang-format on
@ -49,6 +51,26 @@ Result IAllSystemAppletProxiesService::OpenSystemAppletProxy(
}
}
Result IAllSystemAppletProxiesService::OpenSystemAppletProxyForDebug(
Out<SharedPointer<ISystemAppletProxy>> out_proxy, ClientProcessId pid) {
LOG_DEBUG(Service_AM, "OpenSystemAppletProxyForDebug called");
auto process = system.ApplicationProcess();
if (!process) {
LOG_ERROR(Service_AM, "No application process available");
R_THROW(ResultUnknown);
}
if (const auto applet = GetAppletFromProcessId(pid)) {
*out_proxy = std::make_shared<ISystemAppletProxy>(
system, applet, process, m_window_system);
R_SUCCEED();
}
LOG_ERROR(Service_AM, "Applet not found for pid={}", pid.pid);
R_THROW(ResultUnknown);
}
Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy(
Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle,

View file

@ -27,6 +27,7 @@ private:
Result OpenSystemAppletProxy(Out<SharedPointer<ISystemAppletProxy>> out_system_applet_proxy,
ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle);
Result OpenSystemAppletProxyForDebug(Out<SharedPointer<ISystemAppletProxy>> out_proxy, ClientProcessId pid);
Result OpenLibraryAppletProxy(Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy,
ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle,

View file

@ -32,6 +32,11 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
{91, nullptr, "OpenNamedChannelAsChild"},
{100, nullptr, "SetApplicationCoreUsageMode"},
{300, D<&IAppletCommonFunctions::GetCurrentApplicationId>, "GetCurrentApplicationId"},
{310, nullptr, "IsSystemAppletHomeMenu"}, //19.0.0+
{311, nullptr, "Unknown311"},
{320, nullptr, "SetGpuTimeSliceBoost"}, //19.0.0+
{321, nullptr, "SetGpuTimeSliceBoostDueToApplication"}, //19.0.0+
{350, nullptr, "Unknown350"},
};
// clang-format on

View file

@ -111,9 +111,11 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
Firmware1500 = 15,
Firmware1600 = 16,
Firmware1700 = 17,
Firmware1800 = 18,
Firmware1900 = 19,
};
auto process = CreateProcess(system, program_id, Firmware1400, Firmware1700);
auto process = CreateProcess(system, program_id, Firmware1400, Firmware1900);
if (!process) {
// Couldn't initialize the guest process
return {};

View file

@ -15,7 +15,7 @@ IProcessWindingController::IProcessWindingController(Core::System& system_,
static const FunctionInfo functions[] = {
{0, D<&IProcessWindingController::GetLaunchReason>, "GetLaunchReason"},
{11, D<&IProcessWindingController::OpenCallingLibraryApplet>, "OpenCallingLibraryApplet"},
{21, nullptr, "PushContext"},
{21, D<&IProcessWindingController::PushContext>, "PushContext"},
{22, nullptr, "PopContext"},
{23, nullptr, "CancelWindingReservation"},
{30, nullptr, "WindAndDoReserved"},
@ -51,4 +51,9 @@ Result IProcessWindingController::OpenCallingLibraryApplet(
R_SUCCEED();
}
Result IProcessWindingController::PushContext() {
LOG_WARNING(Service_AM, "(STUBBED) called");
R_SUCCEED();
}
} // namespace Service::AM

View file

@ -21,7 +21,7 @@ private:
Result GetLaunchReason(Out<AppletProcessLaunchReason> out_launch_reason);
Result OpenCallingLibraryApplet(
Out<SharedPointer<ILibraryAppletAccessor>> out_calling_library_applet);
Result PushContext();
const std::shared_ptr<Applet> m_applet;
};

View file

@ -67,6 +67,7 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet>
{110, nullptr, "SetApplicationAlbumUserData"},
{120, D<&ISelfController::SaveCurrentScreenshot>, "SaveCurrentScreenshot"},
{130, D<&ISelfController::SetRecordVolumeMuted>, "SetRecordVolumeMuted"},
{230, D<&ISelfController::Unknown230>, "Unknown230"},
{1000, nullptr, "GetDebugStorageChannel"},
};
// clang-format on
@ -394,6 +395,10 @@ Result ISelfController::SaveCurrentScreenshot(Capture::AlbumReportOption album_r
R_SUCCEED();
}
Result ISelfController::Unknown230() {
LOG_WARNING(Service_AM, "(STUBBED) called - function 230 (0xE6)");
R_SUCCEED();
}
Result ISelfController::SetRecordVolumeMuted(bool muted) {
LOG_WARNING(Service_AM, "(STUBBED) called. muted={}", muted);

View file

@ -62,6 +62,7 @@ private:
Result GetAccumulatedSuspendedTickChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result SetAlbumImageTakenNotificationEnabled(bool enabled);
Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option);
Result Unknown230();
Result SetRecordVolumeMuted(bool muted);
Kernel::KProcess* const m_process;

View file

@ -53,6 +53,8 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
{8021, nullptr, "GetAlbumEntryFromApplicationAlbumEntryAruid"},
{10011, nullptr, "SetInternalErrorConversionEnabled"},
{50000, nullptr, "LoadMakerNoteInfoForDebug"},
{50011, C<&IAlbumAccessorService::GetAlbumAccessResultForDebug>, "GetAlbumAccessResultForDebug"},
{50012, C<&IAlbumAccessorService::SetAlbumAccessResultForDebug>, "SetAlbumAccessResultForDebug"},
{60002, nullptr, "OpenAccessorSession"},
};
// clang-format on
@ -137,6 +139,15 @@ Result IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1(
R_RETURN(TranslateResult(result));
}
Result IAlbumAccessorService::GetAlbumAccessResultForDebug() {
LOG_DEBUG(Service_Capture, "(STUBBED) called.");
R_SUCCEED();
}
Result IAlbumAccessorService::SetAlbumAccessResultForDebug() {
LOG_DEBUG(Service_Capture, "(STUBBED) called.");
R_SUCCEED();
}
Result IAlbumAccessorService::TranslateResult(Result in_result) {
if (in_result.IsSuccess()) {
return in_result;

View file

@ -50,6 +50,10 @@ private:
OutArray<u8, BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_image,
OutArray<u8, BufferAttr_HipcMapAlias> out_buffer);
Result GetAlbumAccessResultForDebug();
Result SetAlbumAccessResultForDebug();
Result TranslateResult(Result in_result);
std::shared_ptr<AlbumManager> manager = nullptr;

View file

@ -303,6 +303,9 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{3013, nullptr, "IsGameCardEnabled"},
{3014, nullptr, "IsLocalContentShareEnabled"},
{3050, nullptr, "ListAssignELicenseTaskResult"},
{4022, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4022"},
{4023, D<&IApplicationManagerInterface::Unknown4023>, "Unknown4023"},
{4088, D<&IApplicationManagerInterface::Unknown4088>, "Unknown4088"},
{9999, nullptr, "GetApplicationCertificate"},
};
// clang-format on
@ -509,6 +512,23 @@ Result IApplicationManagerInterface::CheckApplicationLaunchVersion(u64 applicati
R_SUCCEED();
}
Result IApplicationManagerInterface::Unknown4022(Out<u32> out_unknown) {
LOG_WARNING(Service_NS, "(STUBBED) Unknown4022 called");
*out_unknown = 0;
R_SUCCEED();
}
Result IApplicationManagerInterface::Unknown4023(Out<u32> out_unknown) {
LOG_WARNING(Service_NS, "(STUBBED) Unknown4022 called");
*out_unknown = 0;
R_SUCCEED();
}
Result IApplicationManagerInterface::Unknown4088() {
LOG_WARNING(Service_NS, "(STUBBED) Unknown4088 called");
R_SUCCEED();
}
Result IApplicationManagerInterface::GetApplicationTerminateResult(Out<Result> out_result,
u64 application_id) {
LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id);

View file

@ -48,6 +48,9 @@ public:
Result IsApplicationUpdateRequested(Out<bool> out_update_required, Out<u32> out_update_version,
u64 application_id);
Result CheckApplicationLaunchVersion(u64 application_id);
Result Unknown4022(Out<u32> out_unknown);
Result Unknown4023(Out<u32> out_unknown);
Result Unknown4088();
Result GetApplicationTerminateResult(Out<Result> out_result, u64 application_id);
private:

View file

@ -81,12 +81,12 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
{1451, D<&IParentalControlService::StartPlayTimer>, "StartPlayTimer"},
{1452, D<&IParentalControlService::StopPlayTimer>, "StopPlayTimer"},
{1453, D<&IParentalControlService::IsPlayTimerEnabled>, "IsPlayTimerEnabled"},
{1454, nullptr, "GetPlayTimerRemainingTime"},
{1454, D<&IParentalControlService::GetPlayTimerRemainingTime>, "GetPlayTimerRemainingTime"},
{1455, D<&IParentalControlService::IsRestrictedByPlayTimer>, "IsRestrictedByPlayTimer"},
{1456, D<&IParentalControlService::GetPlayTimerSettingsOld>, "GetPlayTimerSettingsOld"},
{1457, D<&IParentalControlService::GetPlayTimerEventToRequestSuspension>, "GetPlayTimerEventToRequestSuspension"},
{1458, D<&IParentalControlService::IsPlayTimerAlarmDisabled>, "IsPlayTimerAlarmDisabled"},
{1459, nullptr, "GetPlayTimerRemainingTimeDisplayInfo"}, // 20.0.0+
{1459, D<&IParentalControlService::GetPlayTimerRemainingTimeDisplayInfo>, "GetPlayTimerRemainingTimeDisplayInfo"}, // 20.0.0+
{1471, nullptr, "NotifyWrongPinCodeInputManyTimes"},
{1472, nullptr, "CancelNetworkRequest"},
{1473, D<&IParentalControlService::GetUnlinkedEvent>, "GetUnlinkedEvent"},
@ -388,6 +388,12 @@ Result IParentalControlService::IsPlayTimerEnabled(Out<bool> out_is_play_timer_e
R_SUCCEED();
}
Result IParentalControlService::GetPlayTimerRemainingTime(Out<s32> out_remaining_minutes) {
*out_remaining_minutes = 0;
LOG_WARNING(Service_PCTL, "(STUBBED) called, remaining_minutes={}", *out_remaining_minutes);
R_SUCCEED();
}
Result IParentalControlService::IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer) {
*out_is_restricted_by_play_timer = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, restricted={}", *out_is_restricted_by_play_timer);
@ -422,6 +428,15 @@ Result IParentalControlService::IsPlayTimerAlarmDisabled(Out<bool> out_play_time
R_SUCCEED();
}
Result IParentalControlService::GetPlayTimerRemainingTimeDisplayInfo(
Out<s32> out_remaining_minutes, Out<u32> out_unknown) {
*out_remaining_minutes = 0;
*out_unknown = 0;
LOG_WARNING(Service_PCTL, "(STUBBED) called, remaining_minutes={}, unknown={}",
*out_remaining_minutes, *out_unknown);
R_SUCCEED();
}
Result IParentalControlService::GetUnlinkedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_INFO(Service_PCTL, "called");
*out_event = unlinked_event.GetHandle();

View file

@ -45,10 +45,12 @@ private:
Result StartPlayTimer();
Result StopPlayTimer();
Result IsPlayTimerEnabled(Out<bool> out_is_play_timer_enabled);
Result GetPlayTimerRemainingTime(Out<s32> out_remaining_minutes);
Result IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer);
Result GetPlayTimerSettingsOld(Out<PlayTimerSettings> out_play_timer_settings);
Result GetPlayTimerEventToRequestSuspension(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result IsPlayTimerAlarmDisabled(Out<bool> out_play_timer_alarm_disabled);
Result GetPlayTimerRemainingTimeDisplayInfo(Out<s32> out_remaining_minutes, Out<u32> out_unknown);
Result GetUnlinkedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetStereoVisionRestriction(Out<bool> out_stereo_vision_restriction);
Result SetStereoVisionRestriction(bool stereo_vision_restriction);