Services/AM: Implemented BeginImportProgramTemporarily, EndImportProgramWithoutCommit and CommitImportPrograms.

These functions are pretty much identical to BeginImportProgram and EndImportProgram.

We don't need to do anything special in EndImportProgramWithoutCommit and CommitImportPrograms because we don't need to implement the two-phase title installation that the 3DS uses to prevent corruption of the title.db.
This commit is contained in:
Subv 2018-10-03 14:48:39 -05:00
parent 3790ccc7b2
commit 0f6f7cfd95
3 changed files with 96 additions and 3 deletions

View file

@ -1038,6 +1038,33 @@ void Module::Interface::BeginImportProgram(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) media_type={}", static_cast<u32>(media_type));
}
void Module::Interface::BeginImportProgramTemporarily(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x0403, 0, 0); // 0x04030000
if (am->cia_installing) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ResultCode(ErrCodes::CIACurrentlyInstalling, ErrorModule::AM,
ErrorSummary::InvalidState, ErrorLevel::Permanent));
return;
}
// Note: This function should register the title in the temp_i.db database, but we can get away
// with not doing that because we traverse the file system to detect installed titles.
// Create our CIAFile handle for the app to write to, and while the app writes Citra will store
// contents out to sdmc/nand
const FileSys::Path cia_path = {};
auto file = std::make_shared<Service::FS::File>(std::make_unique<CIAFile>(FS::MediaType::NAND),
cia_path);
am->cia_installing = true;
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(RESULT_SUCCESS); // No error
rb.PushCopyObjects(file->Connect());
LOG_WARNING(Service_AM, "(STUBBED)");
}
void Module::Interface::EndImportProgram(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x0405, 0, 2); // 0x04050002
auto cia = rp.PopObject<Kernel::ClientSession>();
@ -1049,6 +1076,35 @@ void Module::Interface::EndImportProgram(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
}
void Module::Interface::EndImportProgramWithoutCommit(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x0406, 0, 2); // 0x04060002
auto cia = rp.PopObject<Kernel::ClientSession>();
// Note: This function is basically a no-op for us since we don't use title.db or ticket.db
// files to keep track of installed titles.
am->ScanForAllTitles();
am->cia_installing = false;
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(RESULT_SUCCESS);
}
void Module::Interface::CommitImportPrograms(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x0407, 3, 2); // 0x040700C2
auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>());
u32 title_count = rp.Pop<u32>();
u8 database = rp.Pop<u8>();
auto buffer = rp.PopMappedBuffer();
// Note: This function is basically a no-op for us since we don't use title.db or ticket.db
// files to keep track of installed titles.
am->ScanForAllTitles();
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(RESULT_SUCCESS);
rb.PushMappedBuffer(buffer);
}
/// Wraps all File operations to allow adding an offset to them.
class AMFileWrapper : public FileSys::FileBackend {
public:

View file

@ -384,6 +384,17 @@ public:
*/
void BeginImportProgram(Kernel::HLERequestContext& ctx);
/**
* AM::BeginImportProgramTemporarily service function
* Begin importing from a CTR Installable Archive into the temporary title database
* Inputs:
* 0 : Command header (0x04030000)
* Outputs:
* 1 : Result, 0 on success, otherwise error code
* 2-3 : CIAFile handle for application to write to
*/
void BeginImportProgramTemporarily(Kernel::HLERequestContext& ctx);
/**
* AM::EndImportProgram service function
* Finish importing from a CTR Installable Archive
@ -395,6 +406,32 @@ public:
*/
void EndImportProgram(Kernel::HLERequestContext& ctx);
/**
* AM::EndImportProgramWithoutCommit service function
* Finish importing from a CTR Installable Archive
* Inputs:
* 0 : Command header (0x04060002)
* 1-2 : CIAFile handle application wrote to
* Outputs:
* 1 : Result, 0 on success, otherwise error code
*/
void EndImportProgramWithoutCommit(Kernel::HLERequestContext& ctx);
/**
* AM::CommitImportPrograms service function
* Commits changes from the temporary title database to the real title database (title.db).
* This is a no-op for us, we don't use title.db
* Inputs:
* 0 : Command header (0x040700C2)
* 1 : Media type
* 2 : Title count
* 3 : Database type
* 4-5 : Title list buffer
* Outputs:
* 1 : Result, 0 on success, otherwise error code
*/
void CommitImportPrograms(Kernel::HLERequestContext& ctx);
/**
* AM::GetProgramInfoFromCia service function
* Get TitleInfo from a CIA file handle

View file

@ -55,11 +55,11 @@ AM_U::AM_U(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "am:u"
{0x002D00C0, nullptr, "CheckContentRightsIgnorePlatform"},
{0x04010080, nullptr, "UpdateFirmwareTo"},
{0x04020040, &AM_U::BeginImportProgram, "BeginImportProgram"},
{0x04030000, nullptr, "BeginImportProgramTemporarily"},
{0x04030000, &AM_U::BeginImportProgramTemporarily, "BeginImportProgramTemporarily"},
{0x04040002, nullptr, "CancelImportProgram"},
{0x04050002, &AM_U::EndImportProgram, "EndImportProgram"},
{0x04060002, nullptr, "EndImportProgramWithoutCommit"},
{0x040700C2, nullptr, "CommitImportPrograms"},
{0x04060002, &AM_U::EndImportProgramWithoutCommit, "EndImportProgramWithoutCommit"},
{0x040700C2, &AM_U::CommitImportPrograms, "CommitImportPrograms"},
{0x04080042, &AM_U::GetProgramInfoFromCia, "GetProgramInfoFromCia"},
{0x04090004, &AM_U::GetSystemMenuDataFromCia, "GetSystemMenuDataFromCia"},
{0x040A0002, &AM_U::GetDependencyListFromCia, "GetDependencyListFromCia"},