The ES (ETicket Services) is responsible for the security of Wii, making it the enemy! Along with the rest of IOS, this is generally considered a "private interface" -- game developers never call any of these functions directly. Most of these are now implemented in libogc -- see http://devkitpro.cvs.sourceforge.net/viewvc/devkitpro/libogc/libogc/es.c?view=markup. Please feel free to submit patches to implement the remaining functions.
Here are the known ES functions:
ios_ioctlv( fd, 0x01, 4, 0, vec); // ES_AddTicket(const signed_blob *stik, u32 stik_size, const signed_blob *certificates, u32 certificates_size, const signed_blob *crl, u32 crl_size)
ios_ioctlv( fd, 0x02, 4, 0, vec); // ES_AddTitleStart(const signed_blob *stmd, u32 tmd_size, const signed_blob *certificates, u32 certificates_size, const signed_blob *crl, u32 crl_size)
ios_ioctlv( fd, 0x03, 2, 0, vec); // ES_AddContentStart(u64 titleID, u32 cid)
ios_ioctlv( fd, 0x04, 2, 0, vec); // ES_AddContentData(s32 cfd, u8 *data, u32 data_size)
ios_ioctlv( fd, 0x05, 1, 0, vec); // ES_AddContentFinish(u32 cid)
ios_ioctlv( fd, 0x06, 0, 0, vec); // ES_AddTitleFinish(void)
ios_ioctlv( fd, 0x07, 0, 1, vec); // ES_GetDeviceID
ios_ioctlvReboot(fd, 8, 2, 0, vec); // ES_LaunchTitle(u64 titleID, const tikview *view)
ios_ioctlv( fd, 0x09, 1, 0, vec); // ES_OpenContent(u16 index)
ios_ioctlv( fd, 0x0A, 1, 1, vec); // ES_ReadContent(s32 cfd, u8 *data, u32 data_size)
ios_ioctlv( fd, 0x0B, 1, 0, vec); // ES_CloseContent(s32 cfd)
ios_ioctlv( fd, 0x0C, 0, 1, vec); // ES_GetOwnedTitlesCount
ios_ioctlv( fd, 0x0D, 1, 1, vec); // ES_GetOwnedTitles
ios_ioctlv( fd, 0x0E, 0, 1, vec); // ES_GetTitlesCount
ios_ioctlv( fd, 0x0F, 1, 1, vec); // ES_GetTitles
ios_ioctlv( fd, 0x10, 0, 1, vec); // ES_GetTitleContentsCount
ios_ioctlv( fd, 0x11, 2, 1, vec); // ES_GetTitleContent
ios_ioctlv( fd, 0x12, 1, 1, vec); // ES_GetNumTicketViews(u64 titleID, u32 *cnt)
ios_ioctlv( fd, 0x13, 1, 1, vec); // ES_GetTicketViews(u64 titleID, tikview *views, u32 cnt)
ios_ioctlv( fd, 0x14, 1, 1, vec); // ES_GetTmdViewSize
ios_ioctlv( fd, 0x15, 2, 1, vec); // ES_GetTmdView
ios_ioctlv( fd, 0x16, 1, 2, vec); // ES_GetConsumption
ios_ioctlv( fd, 0x17, 1, 2, vec); // ES_DeleteTitle
ios_ioctlv( fd, 0x18, 1, 2, vec); // ES_DeleteTicket
ios_ioctlv( fd, 0x19, 1, 1, vec); // ES_DiGetTmdViewCount
ios_ioctlv( fd, 0x1A, 2, 1, vec); // ES_DiGetTmdView
ios_ioctlv( fd, 0x1B, 1, 1, vec); // ES_DiGetTicketView
ios_ioctlv( fd, 0x1c, 1, 1, vec); // ES_DiVerify
ios_ioctlv( fd, 0x1d, 1, 1, vec); // ES_GetDataDir
ios_ioctlv( fd, 0x1e, 0, 1, vec); // ES_GetDeviceCert(u8 *outbuf)
ios_ioctlv( fd, 0x1f, 6, 0, vec); // ES_ImportBoot( const signed_blob *tik, u32 tik_size, const signed_blob *tik_certs, u32 tik_certs_size, const signed_blob *tmd, u32 tmd_size, const signed_blob *tmd_certs, u32 tmd_certs_size, const u8 *content, u32 content_size )
ios_ioctlv( fd, 0x20, 0, 1, vec); // ES_GetTitleId
ios_ioctlv( fd, 0x21, 1, 0, vec); // ES_SetUid
ios_ioctlv( fd, 0x22, 1, 0, vec); // ES_DeleteTitleContent(u64 titleID) - deletes all files containing 'app' in a /title/xxxxxxxx/yyyyyyyy/content
ios_ioctlv( fd, 0x23, 3, 0, vec); // ES_SeekContent
ios_ioctlv( fd, 0x24, 3, 0, vec); // ES_OpenTitleContent
ios_ioctlv( fd, 0x25, 0, 0, vec); // ES_LaunchBC(void)
ios_ioctlv( fd, 0x26, 1, 1, vec); // ES_ExportTitleInit
ios_ioctlv( fd, 0x27, 2, 0, vec); // ES_ExportContentBegin
ios_ioctlv( fd, 0x28, 1, 1, vec); // ES_ExportContentData
ios_ioctlv( fd, 0x29, 1, 0, vec); // ES_ExportContentEnd
ios_ioctlv( fd, 0x2A, 0, 0, vec); // ES_ExportTitleDone(void)
ios_ioctlv( fd, 0x2B, 1, 0, vec); // ES_AddTmd
ios_ioctlv( fd, 0x2C, 3, 2, vec); // ES_Encrypt(u32 keynum, u8 *iv, u8 *source, u32 size, u8 *dest)
ios_ioctlv( fd, 0x2D, 3, 2, vec); // ES_Decrypt(u32 keynum, u8 *iv, u8 *source, u32 size, u8 *dest)
ios_ioctlv( fd, 0x2E, 0, 1, vec); // ES_GetBoot2Version(u32 *version)
ios_ioctlv( fd, 0x2F, 0, 0, vec); // ES_AddTitleCancel(void)
ios_ioctlv( fd, 0x30, 1, 2, vec); // ES_Sign(u8 *source, u32 size, u8 *sig, u8 *certs)
ios_ioctlv( fd, 0x31, 3, 0, vec); // ES_VerifySign
ios_ioctlv( fd, 0x32, 0, 1, vec); // ES_GetStoredContentCount
ios_ioctlv( fd, 0x33, 0, 1, vec); // ES_GetStoredContent
ios_ioctlv( fd, 0x34, 0, 1, vec); // ES_GetStoredTmdSize
ios_ioctlv( fd, 0x35, 0, 1, vec); // ES_GetStoredTmd
ios_ioctlv( fd, 0x36, 0, 1, vec); // ES_GetSharedContentCount
ios_ioctlv( fd, 0x37, 0, 1, vec); // ES_GetSharedContents
ios_ioctlv( fd, 0x38, ?, ?, vec);
ios_ioctlv( fd, 0x39, 0, 1, vec); // ES_GetDiTmdSize
ios_ioctlv( fd, 0x3A, 1, 1, vec); // ES_GetDiTmd
ios_ioctlv( fd, 0x3B, 0, 1, vec); // Unknown ... calls ES_DiVerify
ios_ioctlv( fd, 0x3C, 0, 1, vec); // Unknown ... calls ES_DiVerify
ios_ioctlv( fd, 0x3D, 0, 1, vec); // wrapper for syscall 5c
/dev/es IOS_Ioctlv
number
|
name
|
in count
|
out count
|
vec entry target
|
vec entry size [bytes]
|
libogc prototype
|
Description
|
0x00
|
?
|
0
|
0
|
|
|
?
|
returns -1017
|
0x01
|
ES_AddTicket
|
3
|
0
|
?
|
0x2A4
|
ES_AddTicket(const signed_blob *stik, u32 stik_size, const signed_blob *certificates, u32 certificates_size, const signed_blob *crl, u32 crl_size)
|
?
|
?
|
?
|
?
|
?
|
0x02
|
ES_AddTitleStart
|
4
|
0
|
?
|
?
|
?
|
?
|
?
|
?
|
?
|
?
|
?
|
0x1c
|
0x03
|
ES_AddContentStart
|
2
|
0
|
?
|
0x8
|
?
|
?
|
?
|
0x4
|
0x04
|
ES_AddContentData
|
2
|
0
|
?
|
0x4
|
?
|
?
|
?
|
?
|
0x05
|
ES_AddContentFinish
|
1
|
0
|
?
|
0x4
|
?
|
?
|
0x06
|
ES_AddTitleFinish
|
0
|
0
|
|
|
?
|
?
|
0x07
|
ES_GetDeviceID
|
0
|
1
|
?
|
0x4
|
?
|
?
|
0x08
|
ES_LaunchTitle
|
2
|
0
|
?
|
0x8
|
?
|
?
|
?
|
0xd8
|
0x09
|
ES_OpenContent
|
1
|
0
|
?
|
0x4
|
?
|
?
|
0x0a
|
ES_ReadContent
|
1
|
1
|
?
|
0x4
|
?
|
?
|
?
|
?
|
0x0b
|
ES_CloseContent
|
1
|
0
|
?
|
0x4
|
?
|
?
|
0x0c
|
ES_GetOwnedTitlesCount
|
0
|
1
|
u32* count
|
0x4
|
?
|
?
|
0x0d
|
ES_GetOwnedTitles
|
1
|
1
|
u32* count
|
0x4
|
?
|
?
|
u64 titles[]
|
[count]*0x8
|
0x0e
|
ES_GetTitlesCount
|
0
|
1
|
u32* count
|
0x4
|
?
|
Sets the u32 pointed to by count to the number of titles on the system under /title.
|
0x0f
|
ES_GetTitles
|
1
|
1
|
u32* count
|
0x4
|
?
|
Fills out buffer with at most count 8 byte title ids of titles on the system under /title. It also update count for the number of title ids copied.
|
u64 buffer[]
|
[count]*0x8
|
0x10
|
ES_GetTitleContentsCount
|
1
|
1
|
u64 title_id
|
0x8
|
?
|
Gets the number of contents from the tmd. It checks that the contents are present in the title's private content directory or linked via /shared1/content.map
|
u32* count
|
0x4
|
0x11
|
ES_GetTitleContents
|
2
|
1
|
u64 title_id
|
0x8
|
?
|
Fills out content_ids with the content ids from the title's tmd. It checks if the contents are present in the title's private content directory or linked via /shared1/content.map
|
u32* count
|
0x4
|
u32 content_ids[]
|
[count]*0x4
|
0x12
|
ES_GetNumTicketViews
|
1
|
1
|
u64 title_id
|
0x8
|
?
|
?
|
u32* count
|
0x4
|
0x13
|
ES_GetTicketViews
|
2
|
1
|
u64 title_id
|
0x8
|
?
|
?
|
u32* count
|
0x4
|
tikview_t ticketviews[]
|
[count]*0xd8
|
0x14
|
ES_GetTmdViewSize
|
1
|
1
|
u64 title_id
|
0x8
|
?
|
?
|
u32* count
|
0x4
|
0x15
|
ES_GetTmdView
|
2
|
1
|
u64 title_id
|
0x8
|
?
|
?
|
u32* count
|
0x4
|
tmdiew_t tmdview
|
[count]
|
0x22
|
ES_DeleteTitleContent
|
1
|
0
|
u64 title_id
|
0x8
|
?
|
Deletes all files containing the substring "app" in a title's content directory (/title/xxxxxxxx/yyyyyyyy/content).
|
0x38
|
? (ES_DeleteSharedContent)
|
1
|
0
|
u8 sha1[]
|
0x14
|
?
|
Deletes the content file from /shared1 with the given sha1 checksum. It aborts if the tmd of an essential system title references the content. It rebuilds content.map after, removing the entry for the deleted file.
|
0x3e
|
?
|
2
|
0
|
u64 title_id
|
0x8
|
?
|
Deletes a specific content from a title's private content directory.
|
u32 content_id
|
0x4
|
0x3f
|
?
|
0
|
0
|
|
|
?
|
returns -1017
|
0x40
|
?
|
1
|
1
|
tikview_t ticketview
|
0xd8
|
?
|
Copies the ticket associated with ticketview into ticket_buffer based on some access checks [currently unknown ticket offsets +0x1e8 to +0x1ef, +0x1f0.]
|
tik_t ticket_buffer
|
0x2a4
|
/dev/es error codes
Error code
|
POSIX equivalent
|
Notes
|
-106
|
?
|
Invalid TMD when using ES_OpenContent or <marcan> HUGHLALUGH SOMETHING FUCKED UP AND I'M NOT TELLING, or access denied
|
-1009
|
EIO
|
Read failure (short read)
|
-1010
|
EIO
|
Write failure (short write)
|
-1012
|
?
|
Invalid signature type
|
-1015
|
?
|
Invalid value for byte at 0x180 in ticket (valid:0,1,2)
|
-1017
|
EFAULT?
|
Wrong IN or OUT size, wrong size for a part of the vector, vector alignment problems
|
-1022
|
?
|
Content did not match hash in TMD
|
-1024
|
ENOMEM
|
Memory allocation failure
|
-1026
|
EACCESS
|
Incorrect access rights
|
-1028
|
ENOENT
|
No ticket installed
|
-1029
|
?
|
Installed ticket is invalid
|
-1035
|
?
|
Title with a higher version is already installed
|
-2008
|
EINVAL
|
Invalid parameter(s)
|
-2011
|
?
|
Signature check failed
|
-2014
|
?
|
Bad hash length (!= 20)
|
-4100
|
?
|
Wrong Ticket-, Cert size or invalid Ticket-, Cert data
|