From fcb370a8c142806443895f597a9185d14f3e0335 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sat, 7 Nov 2015 17:35:54 -0500 Subject: [PATCH 1/3] Implemented FSUSER_GetProductInfo. --- libctru/include/3ds/services/fs.h | 9 ++++++ libctru/source/services/fs.c | 48 +++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/libctru/include/3ds/services/fs.h b/libctru/include/3ds/services/fs.h index acac55a..eadff3c 100644 --- a/libctru/include/3ds/services/fs.h +++ b/libctru/include/3ds/services/fs.h @@ -127,6 +127,14 @@ typedef struct u64 fileSize; //!< file size } FS_dirent; +/*! ProductInfo. These strings are not NULL-terminated. */ +typedef struct +{ + char product_code[0x10]; + char company_code[0x2]; + u16 remaster_version; +} FS_ProductInfo; + Result fsInit(void); Result fsExit(void); Handle *fsGetSessionHandle(); @@ -150,6 +158,7 @@ Result FSUSER_GetSdmcArchiveResource(Handle *handle, u32 *sectorSize, u32 *clust Result FSUSER_GetNandArchiveResource(Handle *handle, u32 *sectorSize, u32 *clusterSize, u32 *numClusters, u32 *freeClusters); Result FSUSER_IsSdmcDetected(Handle *handle, u8 *detected); Result FSUSER_IsSdmcWritable(Handle *handle, u8 *writable); +Result FSUSER_GetProductInfo(Handle *handle, u32 processid, FS_ProductInfo *out); Result FSUSER_GetMediaType(Handle *handle, u8* mediatype); Result FSFILE_Close(Handle handle); diff --git a/libctru/source/services/fs.c b/libctru/source/services/fs.c index 04f93ad..d66eb17 100644 --- a/libctru/source/services/fs.c +++ b/libctru/source/services/fs.c @@ -1051,6 +1051,54 @@ FSUSER_IsSdmcDetected(Handle *handle, return cmdbuf[1]; } +/*! Get the ProductInfo for the specified process. + * + * @param[in] handle fs:USER handle + * @param[in] processid ProcessID + * @param[out] out Output ProductInfo + * + * @returns error + * + * @internal + * + * #### Request + * + * Index Word | Description + * -----------|------------------------- + * 0 | Header code [0x082E0040] + * 1 | u32 processID + * + * #### Response + * + * Index Word | Description + * -----------|------------------------- + * 0 | Header code + * 1 | Result code + * 2-6 | Output ProductInfo + */ +Result +FSUSER_GetProductInfo(Handle *handle, + u32 processid, + FS_ProductInfo *out) +{ + if(!handle) + handle = &fsuHandle; + + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = 0x082E0040; + cmdbuf[1] = processid; + + Result ret = 0; + if((ret = svcSendSyncRequest(*handle))) + return ret; + + if(out) + memcpy(out, &cmdbuf[2], sizeof(FS_ProductInfo)); + + return cmdbuf[1]; +} + /*! Get curent process mediatype * * @param[in] handle fs:USER handle From e87ad0ad6c0dcfb52504da5a486c708d1c3bf1d8 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sun, 8 Nov 2015 21:28:39 -0500 Subject: [PATCH 2/3] Implemented code for getting the system-version from NAND NVer/CVer. --- libctru/include/3ds/os.h | 31 +++++++++++ libctru/source/os.c | 115 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) diff --git a/libctru/include/3ds/os.h b/libctru/include/3ds/os.h index f36fb91..cc8b16c 100644 --- a/libctru/include/3ds/os.h +++ b/libctru/include/3ds/os.h @@ -12,6 +12,17 @@ #define GET_VERSION_MINOR(version) (((version)>>16)&0xFF) #define GET_VERSION_REVISION(version) (((version)>> 8)&0xFF) +/*! OS_VersionBin. Format of the system version: "..-" */ +typedef struct +{ + u8 build; + u8 minor; + u8 mainver;//"major" in CVER, NUP version in NVer. + u8 reserved_x3; + char region;//"ASCII character for the system version region" + u8 reserved_x5[0x3]; +} OS_VersionBin; + /** * Converts an address from virtual (process) memory to physical memory. * It is sometimes required by services or when using the GPU command buffer. @@ -79,3 +90,23 @@ u8 osGetWifiStrength(); * @param enable Specifies whether to enable or disable the speedup. */ void osSetSpeedupEnable(bool enable); + +/** + * @brief Gets the NAND system-version stored in NVer/CVer. + * The romfs device must not be already initialized(via romfsInit*()) at the time this function is called, since this code uses the romfs device. + * @param nver_versionbin Output OS_VersionBin structure for the data read from NVer. + * @param cver_versionbin Output OS_VersionBin structure for the data read from CVer. + * @return The result-code. This value can be positive if opening "romfs:/version.bin" fails with stdio, since errno would be returned in that case. In some cases the error can be special negative values as well. + */ +Result osGetSystemVersionData(OS_VersionBin *nver_versionbin, OS_VersionBin *cver_versionbin); + +/** + * @brief This is a wrapper for osGetSystemVersionData. + * @param nver_versionbin Optional output OS_VersionBin structure for the data read from NVer, can be NULL. + * @param cver_versionbin Optional output OS_VersionBin structure for the data read from CVer, can be NULL. + * @param sysverstr Output string where the printed system-version will be written, in the same format displayed by the System Settings title. + * @param sysverstr_maxsize Max size of the above string buffer, *including* NULL-terminator. + * @return See osGetSystemVersionData. + */ +Result osGetSystemVersionDataString(OS_VersionBin *nver_versionbin, OS_VersionBin *cver_versionbin, char *sysverstr, u32 sysverstr_maxsize); + diff --git a/libctru/source/os.c b/libctru/source/os.c index 3e21df4..bd12681 100644 --- a/libctru/source/os.c +++ b/libctru/source/os.c @@ -1,10 +1,16 @@ #include <3ds/types.h> #include <3ds/os.h> #include <3ds/svc.h> +#include <3ds/romfs.h> #include <3ds/services/ptm.h> +#include <3ds/services/fs.h> +#include <3ds/services/cfgu.h> #include #include +#include +#include +#include #define TICKS_PER_USEC 268.123480 #define TICKS_PER_MSEC 268123.480 @@ -29,6 +35,26 @@ static volatile datetime_t* __datetime1 = __attribute__((weak)) bool __ctru_speedup = false; +static u32 __NVer_tidlow_regionarray[7] = {//See here regarding regions: http://3dbrew.org/wiki/Nandrw/sys/SecureInfo_A +0x00016202, //JPN +0x00016302, //USA +0x00016102, //EUR +0x00016202, //"AUS" +0x00016402, //CHN +0x00016502, //KOR +0x00016602, //TWN +}; + +static u32 __CVer_tidlow_regionarray[7] = { +0x00017202, //JPN +0x00017302, //USA +0x00017102, //EUR +0x00017202, //"AUS" +0x00017402, //CHN +0x00017502, //KOR +0x00017602 //TWN +}; + //--------------------------------------------------------------------------------- u32 osConvertVirtToPhys(u32 vaddr) { //--------------------------------------------------------------------------------- @@ -172,3 +198,92 @@ void osSetSpeedupEnable(bool enable) __ctru_speedup = enable; __ctru_speedup_config(); } + +static Result __read_versionbin(FS_archive archive, FS_path fileLowPath, OS_VersionBin *versionbin) +{ + Result ret = 0; + Handle filehandle = 0; + FILE *f = NULL; + + ret = FSUSER_OpenFileDirectly(NULL, &filehandle, archive, fileLowPath, FS_OPEN_READ, 0x0); + if(ret<0)return ret; + + ret = romfsInitFromFile(filehandle, 0x0); + if(ret<0)return ret; + + f = fopen("romfs:/version.bin", "r"); + if(f==NULL) + { + ret = errno; + } + else + { + if(fread(versionbin, 1, sizeof(OS_VersionBin), f) != sizeof(OS_VersionBin))ret = -10; + fclose(f); + } + + romfsExit(); + + return ret; +} + +Result osGetSystemVersionData(OS_VersionBin *nver_versionbin, OS_VersionBin *cver_versionbin) +{ + Result ret=0; + u8 region=0; + + u32 archive_lowpath_data[0x10>>2]; + u32 file_lowpath_data[0x14>>2]; + + FS_archive archive; + FS_path fileLowPath; + + memset(archive_lowpath_data, 0, sizeof(file_lowpath_data)); + memset(file_lowpath_data, 0, sizeof(file_lowpath_data)); + + archive.id = 0x2345678a; + archive.lowPath.type = PATH_BINARY; + archive.lowPath.size = 0x10; + archive.lowPath.data = (u8*)archive_lowpath_data; + + fileLowPath.type = PATH_BINARY; + fileLowPath.size = 0x14; + fileLowPath.data = (u8*)file_lowpath_data; + + archive_lowpath_data[1] = 0x000400DB; + + ret = initCfgu(); + if(ret<0)return ret; + + ret = CFGU_SecureInfoGetRegion(®ion); + if(ret<0)return ret; + + if(region>=7)return -9; + + exitCfgu(); + + archive_lowpath_data[0] = __NVer_tidlow_regionarray[region]; + ret = __read_versionbin(archive, fileLowPath, nver_versionbin); + if(ret<0)return ret; + + archive_lowpath_data[0] = __CVer_tidlow_regionarray[region]; + ret = __read_versionbin(archive, fileLowPath, cver_versionbin); + return ret; +} + +Result osGetSystemVersionDataString(OS_VersionBin *nver_versionbin, OS_VersionBin *cver_versionbin, char *sysverstr, u32 sysverstr_maxsize) +{ + Result ret=0; + OS_VersionBin nver_versionbin_tmp, cver_versionbin_tmp; + + if(nver_versionbin==NULL)nver_versionbin = &nver_versionbin_tmp; + if(cver_versionbin==NULL)cver_versionbin = &cver_versionbin_tmp; + + ret = osGetSystemVersionData(nver_versionbin, cver_versionbin); + if(ret!=0)return ret; + + snprintf(sysverstr, sysverstr_maxsize, "%u.%u.%u-%u%c\n", cver_versionbin->mainver, cver_versionbin->minor, cver_versionbin->build, nver_versionbin->mainver, nver_versionbin->region); + + return 0; +} + From 6a7f13654da6024c97a5f5792350f1181c173fa1 Mon Sep 17 00:00:00 2001 From: fincs Date: Fri, 6 Nov 2015 20:39:41 +0100 Subject: [PATCH 3/3] Fix #204 --- libctru/source/romfs_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libctru/source/romfs_dev.c b/libctru/source/romfs_dev.c index 31e1263..27f5ef7 100644 --- a/libctru/source/romfs_dev.c +++ b/libctru/source/romfs_dev.c @@ -137,7 +137,7 @@ Result romfsInit(void) __utf16path[units] = 0; FS_archive arch = { ARCH_SDMC, { PATH_EMPTY, 1, (u8*)"" }, 0, 0 }; - FS_path path = { PATH_WCHAR, units+1, (u8*)__utf16path }; + FS_path path = { PATH_WCHAR, (units+1)*2, (u8*)__utf16path }; Result rc = FSUSER_OpenFileDirectly(NULL, &romFS_file, arch, path, FS_OPEN_READ, FS_ATTRIBUTE_NONE); if (rc) return rc;