From 932630764f04ee2b6f510fe69bb8db1249f1f541 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 6 Feb 2016 23:34:51 -0800 Subject: [PATCH] Clean up and update AM service functions. --- libctru/include/3ds/services/am.h | 192 +++++++++++++++++++++++------ libctru/source/services/am.c | 198 +++++++++++++++++++++++++++--- 2 files changed, 331 insertions(+), 59 deletions(-) diff --git a/libctru/include/3ds/services/am.h b/libctru/include/3ds/services/am.h index 9f0ef8b..9a7b8b1 100644 --- a/libctru/include/3ds/services/am.h +++ b/libctru/include/3ds/services/am.h @@ -4,9 +4,9 @@ */ #pragma once -/** - * @brief Contains basic information about a title. - */ +#include <3ds/services/fs.h> + +/// Contains basic information about a title. typedef struct { u64 titleID; ///< The title's ID. @@ -15,6 +15,39 @@ typedef struct u8 unk[6]; ///< Unknown title data. } AM_TitleEntry; +/// Pending title status mask values. +enum +{ + AM_STATUS_MASK_INSTALLING = BIT(0), ///< Titles currently installing. + AM_STATUS_MASK_AWAITING_FINALIZATION = BIT(1) ///< Titles awaiting finalization. +}; + +/// Pending title status values. +typedef enum +{ + AM_STATUS_ABORTED = 0x0002, ///< Install aborted. + AM_STATUS_SAVED = 0x0003, ///< Title saved, but not installed. + AM_STATUS_INSTALL_IN_PROGRESS = 0x0802, ///< Install in progress. + AM_STATUS_AWAITING_FINALIZATION = 0x0803 ///< Awaiting finalization. +} AM_InstallStatus; + +// Contains basic information about a pending title. +typedef struct +{ + u64 titleId; ///< Title ID + u16 version; ///< Version + u16 status; ///< @ref AM_InstallStatus + u32 titleType; ///< Title Type + u8 unk[0x8]; ///< Unknown +} AM_PendingTitleEntry; + +/// Pending title deletion flags. +enum +{ + AM_DELETE_PENDING_NON_SYSTEM = BIT(0), ///< Non-system titles. + AM_DELETE_PENDING_SYSTEM = BIT(1) ///< System titles. +}; + /// Initializes AM. Result amInit(void); @@ -25,19 +58,71 @@ void amExit(void); Handle *amGetSessionHandle(void); /** - * @brief Gets the number of titles for a given mediatype. - * @param mediatype Mediatype to get titles from. - * @param count Pointer to write the title count to. + * @brief Gets the number of titles for a given media type. + * @param mediatype Media type to get titles from. + * @param[out] count Pointer to write the title count to. */ -Result AM_GetTitleCount(u8 mediatype, u32 *count); +Result AM_GetTitleCount(FS_MediaType mediatype, u32 *count); /** * @brief Gets a list of title IDs present in a mediatype. - * @param mediatype Mediatype to get titles from. - * @param count Number of title IDs to get. - * @param titleIDs Buffer to write retrieved title IDs to. + * @param[out] titlesRead Pointer to output the number of read titles to. + * @param mediatype Media type to get titles from. + * @param titleCount Number of title IDs to get. + * @param titleIds Buffer to output the retrieved title IDs to. */ -Result AM_GetTitleIdList(u8 mediatype, u32 count, u64 *titleIDs); +Result AM_GetTitleList(u32* titlesRead, FS_MediaType mediatype, u32 titleCount, u64 *titleIds); + +/** + * @brief Gets a list of details about installed titles. + * @param mediatype Media type to get titles from. + * @param titleCount Number of titles to list. + * @param titleIds List of title IDs to retrieve details for. + * @param titleInfo Buffer to write AM_TitleEntry's to. + */ +Result AM_GetTitleInfo(FS_MediaType mediatype, u32 titleCount, u64 *titleIds, AM_TitleEntry *titleInfo); + +/** + * @brief Gets the number of tickets installed on the system. + * @param[out] count Pointer to output the ticket count to. + */ +Result AM_GetTicketCount(u32 *count); + +/** + * @brief Gets a list of tickets installed on the system. + * @param[out] ticketsRead Pointer to output the number of read tickets to. + * @param ticketCount Number of tickets to read. + * @param skip Number of tickets to skip. + * @param ticketIds Buffer to output the retrieved ticket IDs to. + */ +Result AM_GetTicketList(u32 *ticketsRead, u32 ticketCount, u32 skip, u64 *ticketIds); + +/** + * @brief Gets the number of pending titles on this system. + * @param[out] count Pointer to output the pending title count to. + * @param mediatype Media type of pending titles to count. + * @param statusMask Bit mask of status values to include. + */ +Result AM_GetPendingTitleCount(u32 *count, FS_MediaType mediatype, u32 statusMask); + +/** + * @brief Gets a list of pending titles on this system. + * @param[out] titlesRead Pointer to output the number of read pending titles to. + * @param titleCount Number of pending titles to read. + * @param mediatype Media type of pending titles to list. + * @param statusMask Bit mask of status values to include. + * @param titleIds Buffer to output the retrieved pending title IDs to. + */ +Result AM_GetPendingTitleList(u32 *titlesRead, u32 titleCount, FS_MediaType mediatype, u32 statusMask, u64 *titleIds); + +/** + * @brief Gets information about pending titles on this system. + * @param titleCount Number of pending titles to read. + * @param mediatype Media type of pending titles to get information on. + * @param titleIds IDs of the titles to get information about. + * @param titleInfo Buffer to output the retrieved pending title info to. + */ +Result AM_GetPendingTitleInfo(u32 titleCount, FS_MediaType mediatype, u64 *titleIds, AM_PendingTitleEntry *titleInfo); /** * @brief Gets a 32-bit device-specific ID. @@ -45,76 +130,103 @@ Result AM_GetTitleIdList(u8 mediatype, u32 count, u64 *titleIDs); */ Result AM_GetDeviceId(u32 *deviceID); -/** - * @brief Gets a list of details about installed titles. - * @param mediatype Mediatype to get titles from. - * @param titleCount Number of titles to list. - * @param titleIdList List of title IDs to retrieve details for. - * @param titleList Buffer to write AM_TitleEntry's to. - */ -Result AM_ListTitles(u8 mediatype, u32 titleCount, u64 *titleIdList, AM_TitleEntry *titleList); - /** * @brief Initializes the CIA install process, returning a handle to write CIA data to. - * @param mediatype Mediatype to install the CIA to. - * @param ciaHandle Pointer to write the CIA handle to. + * @param mediatype Media type to install the CIA to. + * @param[out] ciaHandle Pointer to write the CIA handle to. */ -Result AM_StartCiaInstall(u8 mediatype, Handle *ciaHandle); +Result AM_StartCiaInstall(FS_MediaType mediatype, Handle *ciaHandle); /** * @brief Initializes the CIA install process for Download Play CIAs, returning a handle to write CIA data to. - * @param ciaHandle Pointer to write the CIA handle to. + * @param[out] ciaHandle Pointer to write the CIA handle to. */ Result AM_StartDlpChildCiaInstall(Handle *ciaHandle); /** * @brief Aborts the CIA install process. - * @param ciaHandle Pointer to the CIA handle to cancel. + * @param ciaHandle CIA handle to cancel. */ -Result AM_CancelCIAInstall(Handle *ciaHandle); +Result AM_CancelCIAInstall(Handle ciaHandle); /** * @brief Finalizes the CIA install process. - * @param mediatype Mediatype to install the CIA to. - * @param ciaHandle Pointer to the CIA handle to finalize. + * @param ciaHandle CIA handle to finalize. */ -Result AM_FinishCiaInstall(u8 mediatype, Handle *ciaHandle); +Result AM_FinishCiaInstall(Handle ciaHandle); /** * @brief Deletes a title. - * @param mediatype Mediatype to delete from. + * @param mediatype Media type to delete from. * @param titleID ID of the title to delete. */ -Result AM_DeleteTitle(u8 mediatype, u64 titleID); +Result AM_DeleteTitle(FS_MediaType mediatype, u64 titleID); /** * @brief Deletes a title, provided that it is not a system title. - * @param mediatype Mediatype to delete from. + * @param mediatype Media type to delete from. * @param titleID ID of the title to delete. */ -Result AM_DeleteAppTitle(u8 mediatype, u64 titleID); +Result AM_DeleteAppTitle(FS_MediaType mediatype, u64 titleID); + +/** + * @brief Deletes a ticket. + * @param titleID ID of the ticket to delete. + */ +Result AM_DeleteTicket(u64 ticketId); + +/** + * @brief Deletes a pending title. + * @param mediatype Media type to delete from. + * @param titleId ID of the pending title to delete. + */ +Result AM_DeletePendingTitle(FS_MediaType mediatype, u64 titleId); + +/** + * @brief Deletes pending titles. + * @param mediatype Media type to delete from. + * @param flags Flags used to select pending titles. + */ +Result AM_DeletePendingTitles(FS_MediaType mediatype, u32 flags); + +/** + * @brief Deletes all pending titles. + * @param mediatype Media type to delete from. + */ +Result AM_DeleteAllPendingTitles(FS_MediaType mediatype); /// Installs the current NATIVE_FIRM title to NAND (firm0:/ & firm1:/) Result AM_InstallNativeFirm(void); -/// Similar to InstallNativeFirm, but doesn't use AMPXI_GetTitleList (NATIVE_FIRM: 0004013800000002 or 0004013820000002 (N3DS)) +/** + * @brief Installs a NATIVE_FIRM title to NAND. Accepts 0004013800000002 or 0004013820000002 (N3DS). + * @param titleID Title ID of the NATIVE_FIRM to install. + */ Result AM_InstallFirm(u64 titleID); /** * @brief Gets the product code of a title. - * @param mediatype Mediatype of the title. + * @param mediatype Media type of the title. * @param titleID ID of the title. - * @param productCode Buffer to output the product code to. (length = 16) + * @param[out] productCode Pointer to output the product code to. (length = 16) */ -Result AM_GetTitleProductCode(u8 mediatype, u64 titleID, char* productCode); +Result AM_GetTitleProductCode(FS_MediaType mediatype, u64 titleId, char *productCode); + +/** + * @brief Gets the ext data ID of a title. + * @param[out] extDataId Pointer to output the ext data ID to. + * @param mediatype Media type of the title. + * @param titleID ID of the title. + */ +Result AM_GetTitleExtDataId(u64 *extDataId, FS_MediaType mediatype, u64 titleId); /** * @brief Gets an AM_TitleEntry instance for a CIA file. - * @param mediatype Mediatype that this CIA would be installed to. - * @param titleEntry Pointer to write the AM_TitleEntry instance to. + * @param mediatype Media type that this CIA would be installed to. + * @param[out] titleEntry Pointer to write the AM_TitleEntry instance to. * @param fileHandle Handle of the CIA file to read. */ -Result AM_GetCiaFileInfo(u8 mediatype, AM_TitleEntry *titleEntry, Handle fileHandle); +Result AM_GetCiaFileInfo(FS_MediaType mediatype, AM_TitleEntry *titleEntry, Handle fileHandle); /** * @brief Initializes the external (SD) title database. diff --git a/libctru/source/services/am.c b/libctru/source/services/am.c index 1de3605..cdcf0b2 100644 --- a/libctru/source/services/am.c +++ b/libctru/source/services/am.c @@ -37,7 +37,7 @@ Handle *amGetSessionHandle(void) return &amHandle; } -Result AM_GetTitleCount(u8 mediatype, u32 *count) +Result AM_GetTitleCount(FS_MediaType mediatype, u32 *count) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -52,23 +52,25 @@ Result AM_GetTitleCount(u8 mediatype, u32 *count) return (Result)cmdbuf[1]; } -Result AM_GetTitleIdList(u8 mediatype, u32 count, u64 *titleIDs) +Result AM_GetTitleList(u32* titlesRead, FS_MediaType mediatype, u32 titleCount, u64 *titleIds) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x2,2,2); // 0x00020082 - cmdbuf[1] = count; + cmdbuf[1] = titleCount; cmdbuf[2] = mediatype; - cmdbuf[3] = IPC_Desc_Buffer(count*sizeof(u64),IPC_BUFFER_W); - cmdbuf[4] = (u32)titleIDs; + cmdbuf[3] = IPC_Desc_Buffer(titleCount*sizeof(u64),IPC_BUFFER_W); + cmdbuf[4] = (u32)titleIds; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + if(titlesRead) *titlesRead = cmdbuf[2]; + return (Result)cmdbuf[1]; } -Result AM_ListTitles(u8 mediatype, u32 titleCount, u64 *titleIdList, AM_TitleEntry *titleList) +Result AM_GetTitleInfo(FS_MediaType mediatype, u32 titleCount, u64 *titleIds, AM_TitleEntry *titleInfo) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -77,9 +79,94 @@ Result AM_ListTitles(u8 mediatype, u32 titleCount, u64 *titleIdList, AM_TitleEnt cmdbuf[1] = mediatype; cmdbuf[2] = titleCount; cmdbuf[3] = IPC_Desc_Buffer(titleCount*sizeof(u64),IPC_BUFFER_R); - cmdbuf[4] = (u32)titleIdList; + cmdbuf[4] = (u32)titleIds; cmdbuf[5] = IPC_Desc_Buffer(titleCount*sizeof(AM_TitleEntry),IPC_BUFFER_W); - cmdbuf[6] = (u32)titleList; + cmdbuf[6] = (u32)titleInfo; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_GetTicketCount(u32 *count) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x8,0,0); // 0x00080000 + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + *count = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result AM_GetTicketList(u32 *ticketsRead, u32 ticketCount, u32 skip, u64 *ticketIds) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x9,2,2); // 0x00090082 + cmdbuf[1] = ticketCount; + cmdbuf[2] = skip; + cmdbuf[3] = IPC_Desc_Buffer(ticketCount*sizeof(u64),IPC_BUFFER_W); + cmdbuf[4] = (u32)ticketIds; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + if(ticketsRead) *ticketsRead = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result AM_GetPendingTitleCount(u32 *count, FS_MediaType mediatype, u32 statusMask) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x23,2,0); // 0x00230080 + cmdbuf[1] = mediatype; + cmdbuf[2] = statusMask; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + *count = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result AM_GetPendingTitleList(u32 *titlesRead, u32 titleCount, FS_MediaType mediatype, u32 statusMask, u64 *titleIds) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x24,3,2); // 0x002400C2 + cmdbuf[1] = titleCount; + cmdbuf[2] = mediatype; + cmdbuf[3] = statusMask; + cmdbuf[4] = IPC_Desc_Buffer(titleCount*sizeof(u64),IPC_BUFFER_W); + cmdbuf[5] = (u32)titleIds; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + if(titlesRead) *titlesRead = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result AM_GetPendingTitleInfo(u32 titleCount, FS_MediaType mediatype, u64 *titleIds, AM_PendingTitleEntry *titleInfo) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0xD,2,4); // 0x000D0084 + cmdbuf[1] = titleCount; + cmdbuf[2] = mediatype; + cmdbuf[3] = IPC_Desc_Buffer(titleCount*sizeof(u64),IPC_BUFFER_R); + cmdbuf[4] = (u32)titleIds; + cmdbuf[5] = IPC_Desc_Buffer(titleCount*sizeof(AM_TitleEntry),IPC_BUFFER_W); + cmdbuf[6] = (u32)titleInfo; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; @@ -100,7 +187,7 @@ Result AM_GetDeviceId(u32 *deviceID) return (Result)cmdbuf[1]; } -Result AM_StartCiaInstall(u8 mediatype, Handle *ciaHandle) +Result AM_StartCiaInstall(FS_MediaType mediatype, Handle *ciaHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -129,35 +216,35 @@ Result AM_StartDlpChildCiaInstall(Handle *ciaHandle) return (Result)cmdbuf[1]; } -Result AM_CancelCIAInstall(Handle *ciaHandle) +Result AM_CancelCIAInstall(Handle ciaHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x404,0,2); // 0x04040002 cmdbuf[1] = IPC_Desc_MoveHandles(1); - cmdbuf[2] = *ciaHandle; + cmdbuf[2] = ciaHandle; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; return (Result)cmdbuf[1]; } -Result AM_FinishCiaInstall(u8 mediatype, Handle *ciaHandle) +Result AM_FinishCiaInstall(Handle ciaHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x405,0,2); // 0x04050002 cmdbuf[1] = IPC_Desc_MoveHandles(1); - cmdbuf[2] = *ciaHandle; + cmdbuf[2] = ciaHandle; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; return (Result)cmdbuf[1]; } -Result AM_DeleteTitle(u8 mediatype, u64 titleID) +Result AM_DeleteTitle(FS_MediaType mediatype, u64 titleID) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -172,7 +259,7 @@ Result AM_DeleteTitle(u8 mediatype, u64 titleID) return (Result)cmdbuf[1]; } -Result AM_DeleteAppTitle(u8 mediatype, u64 titleID) +Result AM_DeleteAppTitle(FS_MediaType mediatype, u64 titleID) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -187,6 +274,62 @@ Result AM_DeleteAppTitle(u8 mediatype, u64 titleID) return (Result)cmdbuf[1]; } +Result AM_DeleteTicket(u64 ticketId) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x7,2,0); // 0x00070080 + cmdbuf[1] = ticketId & 0xffffffff; + cmdbuf[2] = (u32)(ticketId >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_DeletePendingTitle(FS_MediaType mediatype, u64 titleId) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0xE,3,0); // 0x000E00C0 + cmdbuf[1] = mediatype; + cmdbuf[2] = titleId & 0xffffffff; + cmdbuf[3] = (u32)(titleId >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_DeletePendingTitles(FS_MediaType mediatype, u32 flags) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x22,2,0); // 0x00220080 + cmdbuf[1] = mediatype; + cmdbuf[2] = flags; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_DeleteAllPendingTitles(FS_MediaType mediatype) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x15,1,0); // 0x00150040 + cmdbuf[1] = mediatype; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + Result AM_InstallNativeFirm(void) { Result ret = 0; @@ -212,15 +355,15 @@ Result AM_InstallFirm(u64 titleID){ return (Result)cmdbuf[1]; } -Result AM_GetTitleProductCode(u8 mediatype, u64 titleID, char* productCode) +Result AM_GetTitleProductCode(FS_MediaType mediatype, u64 titleId, char *productCode) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x5,3,0); // 0x000500C0 cmdbuf[1] = mediatype; - cmdbuf[2] = titleID & 0xffffffff; - cmdbuf[3] = (u32)(titleID >> 32); + cmdbuf[2] = titleId & 0xffffffff; + cmdbuf[3] = (u32)(titleId >> 32); if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; @@ -230,7 +373,24 @@ Result AM_GetTitleProductCode(u8 mediatype, u64 titleID, char* productCode) return (Result)cmdbuf[1]; } -Result AM_GetCiaFileInfo(u8 mediatype, AM_TitleEntry *titleEntry, Handle fileHandle) +Result AM_GetTitleExtDataId(u64 *extDataId, FS_MediaType mediatype, u64 titleId) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x6,3,0); // 0x000600C0 + cmdbuf[1] = mediatype; + cmdbuf[2] = titleId & 0xffffffff; + cmdbuf[3] = (u32)(titleId >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + if(extDataId) *extDataId = (u64) cmdbuf[2] | ((u64) cmdbuf[3] << 32); + + return (Result)cmdbuf[1]; +} + +Result AM_GetCiaFileInfo(FS_MediaType mediatype, AM_TitleEntry *titleEntry, Handle fileHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer();