diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index f94c47768..c575dc478 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -460,13 +460,28 @@ void FindDLCContentInfos(Service::Interface* self) { rb.PushMappedBuffer(content_info_out, output_buffer_size, output_buffer_perms); } -void ListContentInfos(Service::Interface* self) { +void ListDLCContentInfos(Service::Interface* self) { IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1003, 5, 2); // 0x10030142 + u32 content_count = rp.Pop(); auto media_type = static_cast(rp.Pop()); u64 title_id = rp.Pop(); u32 start_index = rp.Pop(); - VAddr content_info_out = rp.PopMappedBuffer(); + + size_t output_buffer_size; + IPC::MappedBufferPermissions output_buffer_perms; + VAddr content_info_out = rp.PopMappedBuffer(&output_buffer_size, &output_buffer_perms); + + // Validate that only DLC TIDs are passed in + u32 tid_high = static_cast(title_id >> 32); + if (tid_high != TID_HIGH_DLC) { + IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); + rb.Push(ResultCode(ErrCodes::InvalidTIDInList, ErrorModule::AM, + ErrorSummary::InvalidArgument, ErrorLevel::Usage)); + rb.Push(0); + rb.PushMappedBuffer(content_info_out, output_buffer_size, output_buffer_perms); + return; + } std::string tmd_path = GetTitleMetadataPath(media_type, title_id); @@ -494,9 +509,10 @@ void ListContentInfos(Service::Interface* self) { } } - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); rb.Push(RESULT_SUCCESS); rb.Push(copied); + rb.PushMappedBuffer(content_info_out, output_buffer_size, output_buffer_perms); } void DeleteContents(Service::Interface* self) { diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index b8f1053b6..8a2887bcd 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -110,7 +110,8 @@ void GetNumPrograms(Service::Interface* self); void FindDLCContentInfos(Service::Interface* self); /** - * AM::ListContentInfos service function + * AM::ListDLCContentInfos service function + * Explicitly checks that TID high value is 0004008C or an error is returned. * Inputs: * 1 : Content count * 2 : MediaType @@ -121,7 +122,7 @@ void FindDLCContentInfos(Service::Interface* self); * 1 : Result, 0 on success, otherwise error code * 2 : Number of content infos returned */ -void ListContentInfos(Service::Interface* self); +void ListDLCContentInfos(Service::Interface* self); /** * AM::DeleteContents service function diff --git a/src/core/hle/service/am/am_app.cpp b/src/core/hle/service/am/am_app.cpp index 6dd93497a..4007e2d1c 100644 --- a/src/core/hle/service/am/am_app.cpp +++ b/src/core/hle/service/am/am_app.cpp @@ -11,7 +11,7 @@ namespace AM { const Interface::FunctionInfo FunctionTable[] = { {0x100100C0, GetNumContentInfos, "GetNumContentInfos"}, {0x10020104, FindDLCContentInfos, "FindDLCContentInfos"}, - {0x10030142, ListContentInfos, "ListContentInfos"}, + {0x10030142, ListDLCContentInfos, "ListDLCContentInfos"}, {0x10040102, DeleteContents, "DeleteContents"}, {0x10050084, GetDLCTitleInfos, "GetDLCTitleInfos"}, {0x10060080, nullptr, "GetNumDataTitleTickets"}, diff --git a/src/core/hle/service/am/am_sys.cpp b/src/core/hle/service/am/am_sys.cpp index cb860653f..921221f39 100644 --- a/src/core/hle/service/am/am_sys.cpp +++ b/src/core/hle/service/am/am_sys.cpp @@ -56,7 +56,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x002D00C0, CheckContentRightsIgnorePlatform, "CheckContentRightsIgnorePlatform"}, {0x100100C0, GetNumContentInfos, "GetNumContentInfos"}, {0x10020104, FindDLCContentInfos, "FindDLCContentInfos"}, - {0x10030142, ListContentInfos, "ListContentInfos"}, + {0x10030142, ListDLCContentInfos, "ListDLCContentInfos"}, {0x10040102, DeleteContents, "DeleteContents"}, {0x10050084, GetDLCTitleInfos, "GetDLCTitleInfos"}, {0x10060080, nullptr, "GetNumDataTitleTickets"},