2021-03-07 23:22:49 +00:00
/*
* hfs . h
*
2024-04-12 10:47:36 +01:00
* Copyright ( c ) 2020 - 2024 , DarkMatterCore < pabloacurielz @ gmail . com > .
2021-03-07 23:22:49 +00:00
*
* This file is part of nxdumptool ( https : //github.com/DarkMatterCore/nxdumptool).
*
2021-03-25 19:26:58 +00:00
* nxdumptool is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
2021-03-07 23:22:49 +00:00
*
2021-03-25 19:26:58 +00:00
* nxdumptool is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2021-03-07 23:22:49 +00:00
*
* You should have received a copy of the GNU General Public License
2021-03-25 19:26:58 +00:00
* along with this program . If not , see < https : //www.gnu.org/licenses/>.
2021-03-07 23:22:49 +00:00
*/
# pragma once
2021-03-24 17:25:19 +00:00
# ifndef __HFS_H__
# define __HFS_H__
2021-03-23 14:06:52 +00:00
# ifdef __cplusplus
extern " C " {
# endif
2021-03-07 23:22:49 +00:00
# define HFS0_MAGIC 0x48465330 /* "HFS0". */
typedef struct {
u32 magic ; ///< "HFS0".
u32 entry_count ;
u32 name_table_size ;
u8 reserved [ 0x4 ] ;
} HashFileSystemHeader ;
2021-03-24 17:25:19 +00:00
NXDT_ASSERT ( HashFileSystemHeader , 0x10 ) ;
2021-03-07 23:22:49 +00:00
typedef struct {
u64 offset ;
u64 size ;
u32 name_offset ;
u32 hash_target_size ;
u64 hash_target_offset ;
u8 hash [ SHA256_HASH_SIZE ] ;
} HashFileSystemEntry ;
2021-03-24 17:25:19 +00:00
NXDT_ASSERT ( HashFileSystemEntry , 0x40 ) ;
2023-05-24 20:05:34 +01:00
typedef enum {
HashFileSystemPartitionType_None = 0 , ///< Not a real value.
HashFileSystemPartitionType_Root = 1 ,
HashFileSystemPartitionType_Update = 2 ,
HashFileSystemPartitionType_Logo = 3 , ///< Only available in GameCardFwVersion_Since400NUP or greater gamecards.
HashFileSystemPartitionType_Normal = 4 ,
HashFileSystemPartitionType_Secure = 5 ,
HashFileSystemPartitionType_Count = 6 ///< Total values supported by this enum.
} HashFileSystemPartitionType ;
2021-03-07 23:22:49 +00:00
/// Internally used by gamecard functions.
/// Use gamecardGetHashFileSystemContext() to retrieve a Hash FS context.
typedef struct {
2023-05-24 20:05:34 +01:00
u8 type ; ///< HashFileSystemPartitionType.
2021-03-07 23:22:49 +00:00
char * name ; ///< Dynamically allocated partition name.
u64 offset ; ///< Partition offset (relative to the start of gamecard image).
u64 size ; ///< Partition size.
u64 header_size ; ///< Full header size.
u8 * header ; ///< HashFileSystemHeader + (HashFileSystemEntry * entry_count) + Name Table.
} HashFileSystemContext ;
/// Reads raw partition data using a Hash FS context.
/// Input offset must be relative to the start of the Hash FS.
bool hfsReadPartitionData ( HashFileSystemContext * ctx , void * out , u64 read_size , u64 offset ) ;
/// Reads data from a previously retrieved HashFileSystemEntry using a Hash FS context.
/// Input offset must be relative to the start of the Hash FS entry.
bool hfsReadEntryData ( HashFileSystemContext * ctx , HashFileSystemEntry * fs_entry , void * out , u64 read_size , u64 offset ) ;
/// Calculates the extracted Hash FS size.
2023-05-24 20:05:34 +01:00
/// If the target partition is empty, 'out_size' will be set to zero and true will be returned.
2021-03-07 23:22:49 +00:00
bool hfsGetTotalDataSize ( HashFileSystemContext * ctx , u64 * out_size ) ;
2023-05-24 20:05:34 +01:00
/// Retrieves a Hash FS entry index by its name.
bool hfsGetEntryIndexByName ( HashFileSystemContext * ctx , const char * name , u32 * out_idx ) ;
/// Takes a HashFileSystemPartitionType value. Returns a pointer to a string that represents the partition name that matches the provided Hash FS partition type.
/// Returns NULL if the provided value is out of range.
const char * hfsGetPartitionNameString ( u8 hfs_partition_type ) ;
2021-03-07 23:22:49 +00:00
/// Miscellaneous functions.
2021-03-10 01:12:01 +00:00
NX_INLINE void hfsFreeContext ( HashFileSystemContext * ctx )
2021-03-07 23:22:49 +00:00
{
2021-03-10 01:12:01 +00:00
if ( ! ctx ) return ;
if ( ctx - > name ) free ( ctx - > name ) ;
if ( ctx - > header ) free ( ctx - > header ) ;
memset ( ctx , 0 , sizeof ( HashFileSystemContext ) ) ;
2021-03-07 23:22:49 +00:00
}
2023-05-24 20:05:34 +01:00
NX_INLINE bool hfsIsValidContext ( HashFileSystemContext * ctx )
{
return ( ctx & & ctx - > type > HashFileSystemPartitionType_None & & ctx - > type < HashFileSystemPartitionType_Count & & ctx - > name & & ctx - > size & & ctx - > header_size & & ctx - > header ) ;
}
2021-03-07 23:22:49 +00:00
NX_INLINE u32 hfsGetEntryCount ( HashFileSystemContext * ctx )
{
2023-12-20 19:32:48 +00:00
return ( hfsIsValidContext ( ctx ) ? ( ( HashFileSystemHeader * ) ctx - > header ) - > entry_count : 0 ) ;
2021-03-07 23:22:49 +00:00
}
NX_INLINE HashFileSystemEntry * hfsGetEntryByIndex ( HashFileSystemContext * ctx , u32 idx )
{
2023-12-20 19:32:48 +00:00
return ( idx < hfsGetEntryCount ( ctx ) ? ( HashFileSystemEntry * ) ( ctx - > header + sizeof ( HashFileSystemHeader ) + ( idx * sizeof ( HashFileSystemEntry ) ) ) : NULL ) ;
2021-03-07 23:22:49 +00:00
}
NX_INLINE char * hfsGetNameTable ( HashFileSystemContext * ctx )
{
u32 entry_count = hfsGetEntryCount ( ctx ) ;
2023-12-20 19:32:48 +00:00
return ( entry_count ? ( char * ) ( ctx - > header + sizeof ( HashFileSystemHeader ) + ( entry_count * sizeof ( HashFileSystemEntry ) ) ) : NULL ) ;
2021-03-07 23:22:49 +00:00
}
NX_INLINE char * hfsGetEntryName ( HashFileSystemContext * ctx , HashFileSystemEntry * fs_entry )
{
char * name_table = hfsGetNameTable ( ctx ) ;
if ( ! name_table | | ! fs_entry | | fs_entry - > name_offset > = ( ( HashFileSystemHeader * ) ctx - > header ) - > name_table_size | | ! name_table [ fs_entry - > name_offset ] ) return NULL ;
return ( name_table + fs_entry - > name_offset ) ;
}
NX_INLINE char * hfsGetEntryNameByIndex ( HashFileSystemContext * ctx , u32 idx )
{
HashFileSystemEntry * fs_entry = hfsGetEntryByIndex ( ctx , idx ) ;
char * name_table = hfsGetNameTable ( ctx ) ;
2023-12-20 19:32:48 +00:00
return ( ( fs_entry & & name_table ) ? ( name_table + fs_entry - > name_offset ) : NULL ) ;
2021-03-07 23:22:49 +00:00
}
NX_INLINE HashFileSystemEntry * hfsGetEntryByName ( HashFileSystemContext * ctx , const char * name )
{
u32 idx = 0 ;
2023-12-20 19:32:48 +00:00
return ( hfsGetEntryIndexByName ( ctx , name , & idx ) ? hfsGetEntryByIndex ( ctx , idx ) : NULL ) ;
2021-03-07 23:22:49 +00:00
}
2021-03-23 14:06:52 +00:00
# ifdef __cplusplus
}
2021-03-24 17:25:19 +00:00
# endif
# endif /* __HFS_H__ */