Skip to content

Commit

Permalink
Create BIS storage interface.
Browse files Browse the repository at this point in the history
Takes care of retrieving a FsStorage object for any FAT eMMC BIS partition, mounting it via FatFs and creating a virtual devoptab device that can be used to carry out FS operations. All write operations have been stubbed, disabled or ifdef'd out of the code.

Other changes include:

* cert: update code to use the new BIS storage interface.

* defines: remove BIS_SYSTEM_PARTITION_MOUNT_NAME macro.

* devoptab: slightly improve macros.
* devoptab: add operation table for FatFs devices.
* devoptab: add rodev_fstat().
* devoptab: add devoptabMountFatFsDevice().

* fatfs: update diskio code to use the new BIS storage interface.
* fatfs: update configuration.

* save: update code to use regular C I/O calls instead of FatFs calls.

* tik: update code to use the new BIS storage interface.

* utils: remove eMMC BIS System partition (un)mount code.
  • Loading branch information
DarkMatterCore committed Oct 28, 2024
1 parent 160236c commit 596928a
Show file tree
Hide file tree
Showing 19 changed files with 1,138 additions and 291 deletions.
54 changes: 54 additions & 0 deletions include/core/bis_storage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* bis_storage.h
*
* Copyright (c) 2020-2024, DarkMatterCore <[email protected]>.
*
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

#ifndef __BIS_STORAGE_H__
#define __BIS_STORAGE_H__

#ifdef __cplusplus
extern "C" {
#endif

/// Mounts an eMMC BIS partition using its ID and provides a pointer to a string that holds its mount name, which can be used to carry out FS operations.
/// Only eMMC BIS partition IDs `CalibrationFile` (28) through `System` (31) are supported.
bool bisStorageMountPartition(u8 bis_partition_id, const char **out_mount_name);

/// Unmounts a previously mounted eMMC BIS partition.
/// Only eMMC BIS partition IDs `CalibrationFile` (28) through `System` (31) are supported.
void bisStorageUnmountPartition(u8 bis_partition_id);

/// Unmounts all previously mounted eMMC BIS partitions.
void bisStorageUnmountAllPartitions(void);

/// Returns a pointer to a FsStorage object that matches the provided FatFs drive number, or NULL if it hasn't been mounted.
/// Only used by FatFs's diskio operations.
FsStorage *bisStorageGetFsStorageByFatFsDriveNumber(u8 drive_number);

/// (Un)locks the BIS storage mutex. Can be used to block other threads and prevent them from altering the internal status of this interface.
/// Use with caution.
void bisStorageControlMutex(bool lock);

#ifdef __cplusplus
}
#endif

#endif /* __BIS_STORAGE_H__ */
55 changes: 30 additions & 25 deletions include/core/devoptab/nxdt_devoptab.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,54 +27,56 @@
#include "../pfs.h"
#include "../hfs.h"
#include "../romfs.h"
#include "../fatfs/ff.h"

#ifdef __cplusplus
extern "C" {
#endif

#define DEVOPTAB_MOUNT_NAME_LENGTH 32 // Including NULL terminator.
#define DEVOPTAB_MOUNT_NAME_LENGTH 32 // Including NULL terminator.

#define DEVOPTAB_DECL_ERROR_STATE int _errno = 0
#define DEVOPTAB_DECL_DEV_CTX DevoptabDeviceContext *dev_ctx = (DevoptabDeviceContext*)r->deviceData
#define DEVOPTAB_DECL_FS_CTX(type) type *fs_ctx = (type*)dev_ctx->fs_ctx
#define DEVOPTAB_DECL_FILE_STATE(type) type *file = (type*)fd
#define DEVOPTAB_DECL_DIR_STATE(type) type *dir = (type*)dirState->dirStruct
#define DEVOPTAB_INIT_ERROR_STATE r->_errno = 0
#define DEVOPTAB_DECL_DEV_CTX DevoptabDeviceContext *dev_ctx = (DevoptabDeviceContext*)r->deviceData
#define DEVOPTAB_DECL_FS_CTX(type) type *fs_ctx = (type*)dev_ctx->fs_ctx
#define DEVOPTAB_DECL_FILE_STATE(type) type *file = (type*)fd
#define DEVOPTAB_DECL_DIR_STATE(type) type *dir = (type*)dirState->dirStruct

#define DEVOPTAB_SET_ERROR(x) r->_errno = _errno = (x)
#define DEVOPTAB_IS_ERROR_SET (_errno != 0)
#define DEVOPTAB_SET_ERROR(x) r->_errno = (x)
#define DEVOPTAB_IS_ERROR_SET (r->_errno != 0)

#define DEVOPTAB_EXIT goto end
#define DEVOPTAB_SET_ERROR_AND_EXIT(x) \
#define DEVOPTAB_EXIT goto end
#define DEVOPTAB_SET_ERROR_AND_EXIT(x) \
do { \
DEVOPTAB_SET_ERROR(x); \
DEVOPTAB_EXIT; \
} while(0)

#define DEVOPTAB_RETURN_INT(x) return (DEVOPTAB_IS_ERROR_SET ? -1 : (x))
#define DEVOPTAB_RETURN_PTR(x) return (DEVOPTAB_IS_ERROR_SET ? NULL : (x))
#define DEVOPTAB_RETURN_BOOL return (DEVOPTAB_IS_ERROR_SET ? false : true)
#define DEVOPTAB_RETURN_UNSUPPORTED_OP r->_errno = ENOSYS; \
return -1;
#define DEVOPTAB_RETURN_INT(x) return (DEVOPTAB_IS_ERROR_SET ? -1 : (x))
#define DEVOPTAB_RETURN_PTR(x) return (DEVOPTAB_IS_ERROR_SET ? NULL : (x))
#define DEVOPTAB_RETURN_BOOL return (DEVOPTAB_IS_ERROR_SET ? false : true)
#define DEVOPTAB_RETURN_UNSUPPORTED_OP r->_errno = ENOSYS; \
return -1

#define DEVOPTAB_INIT_VARS(type) devoptabControlMutex(true); \
DEVOPTAB_DECL_ERROR_STATE; \
DEVOPTAB_DECL_DEV_CTX; \
if (!dev_ctx->initialized) DEVOPTAB_SET_ERROR_AND_EXIT(ENODEV);
#define DEVOPTAB_INIT_VARS devoptabControlMutex(true); \
DEVOPTAB_INIT_ERROR_STATE; \
DEVOPTAB_DECL_DEV_CTX; \
if (!dev_ctx->initialized) DEVOPTAB_SET_ERROR_AND_EXIT(ENODEV)

#define DEVOPTAB_INIT_FILE_VARS(fs_type, file_type) DEVOPTAB_INIT_VARS(fs_type); \
DEVOPTAB_DECL_FILE_STATE(file_type)
#define DEVOPTAB_INIT_FILE_VARS(type) DEVOPTAB_INIT_VARS; \
DEVOPTAB_DECL_FILE_STATE(type)

#define DEVOPTAB_INIT_DIR_VARS(fs_type, dir_type) DEVOPTAB_INIT_VARS(fs_type); \
DEVOPTAB_DECL_DIR_STATE(dir_type)
#define DEVOPTAB_INIT_DIR_VARS(type) DEVOPTAB_INIT_VARS; \
if (!dirState) DEVOPTAB_SET_ERROR_AND_EXIT(EINVAL); \
DEVOPTAB_DECL_DIR_STATE(type)

#define DEVOPTAB_DEINIT_VARS devoptabControlMutex(false)
#define DEVOPTAB_DEINIT_VARS devoptabControlMutex(false)

typedef struct {
bool initialized; ///< Device initialization flag.
char name[DEVOPTAB_MOUNT_NAME_LENGTH]; ///< Mount name string, without a trailing colon (:).
time_t mount_time; ///< Mount time.
devoptab_t device; ///< Devoptab virtual device interface. Provides a way to use libcstd I/O calls on the mounted filesystem.
void *fs_ctx; ///< Pointer to actual type-specific filesystem context (PartitionFileSystemContext, HashFileSystemContext, RomFileSystemContext).
void *fs_ctx; ///< Pointer to actual type-specific filesystem context (PartitionFileSystemContext, HashFileSystemContext, RomFileSystemContext, FATFS).
} DevoptabDeviceContext;

/// Mounts a virtual Partition FS device using the provided Partition FS context and a mount name.
Expand All @@ -86,6 +88,9 @@ bool devoptabMountHashFileSystemDevice(HashFileSystemContext *hfs_ctx, const cha
/// Mounts a virtual RomFS device using the provided RomFS context and a mount name.
bool devoptabMountRomFileSystemDevice(RomFileSystemContext *romfs_ctx, const char *name);

/// Mounts a virtual FatFs device using the provided FATFS object and a mount name.
bool devoptabMountFatFsDevice(FATFS *fatfs, const char *name);

/// Unmounts a previously mounted virtual device.
void devoptabUnmountDevice(const char *name);

Expand Down
1 change: 1 addition & 0 deletions include/core/devoptab/ro_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ extern "C" {
/* We don't provide support for relative directories, so chdir is discarded as well. */

ssize_t rodev_write(struct _reent *r, void *fd, const char *ptr, size_t len);
int rodev_fstat(struct _reent *r, void *fd, struct stat *st);
int rodev_link(struct _reent *r, const char *existing, const char *newLink);
int rodev_unlink(struct _reent *r, const char *name);
int rodev_chdir(struct _reent *r, const char *name);
Expand Down
3 changes: 1 addition & 2 deletions include/core/fatfs/ffconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,11 @@
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/

#define FF_VOLUMES 1
#define FF_VOLUMES 4
/* Number of volumes (logical drives) to be used. (1-10) */


#define FF_STR_VOLUME_ID 1
#define FF_VOLUME_STRS "sys"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
Expand Down
3 changes: 0 additions & 3 deletions include/core/nxdt_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,6 @@ bool utilsIsTerraUnit(void);
/// Returns true if the application is running under applet mode.
bool utilsIsAppletMode(void);

/// Returns a pointer to the FsStorage object for the eMMC BIS System partition.
FsStorage *utilsGetEmmcBisSystemPartitionStorage(void);

/// Blocks HOME button presses, disables screen dimming and auto sleep and overclocks system CPU/MEM.
/// Must be called before starting long-running processes.
/// If state is set to false, regular system behavior is restored.
Expand Down
14 changes: 6 additions & 8 deletions include/core/save.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
#ifndef __SAVE_H__
#define __SAVE_H__

#include "fatfs/ff.h"

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -45,7 +43,7 @@ extern "C" {
#define MAGIC_RMAP 0x50414D52
#define MAGIC_IVFC 0x43465649

#define ACTION_VERIFY (1<<2)
#define ACTION_VERIFY (1 << 2)

typedef enum {
VALIDITY_UNCHECKED = 0,
Expand Down Expand Up @@ -232,7 +230,7 @@ typedef struct {
enum base_storage_type type;
u64 base_storage_offset;
duplex_storage_ctx_t *duplex;
FIL *file;
FILE *file;
} remap_storage_ctx_t;

typedef struct {
Expand Down Expand Up @@ -333,7 +331,7 @@ typedef struct {
u32 block_size;
u64 journal_data_offset;
u64 _length;
FIL *file;
FILE *file;
} journal_storage_ctx_t;

typedef struct {
Expand Down Expand Up @@ -470,9 +468,9 @@ typedef struct {

struct save_ctx_t {
save_header_t header;
FIL *file;
FILE *file;
struct {
FIL *file;
FILE *file;
u32 action;
} tool_ctx;
validity_t header_cmac_validity;
Expand Down Expand Up @@ -549,7 +547,7 @@ bool save_hierarchical_file_table_find_path_recursive(hierarchical_save_file_tab
bool save_hierarchical_file_table_get_file_entry_by_path(hierarchical_save_file_table_ctx_t *ctx, const char *path, save_fs_list_entry_t *entry);

save_ctx_t *save_open_savefile(const char *path, u32 action);
void save_close_savefile(save_ctx_t *ctx);
void save_close_savefile(save_ctx_t **ctx);
bool save_get_fat_storage_from_file_entry_by_path(save_ctx_t *ctx, const char *path, allocation_table_storage_ctx_t *out_fat_storage, u64 *out_file_entry_size);

#ifdef __cplusplus
Expand Down
2 changes: 0 additions & 2 deletions include/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@
#define LOG_BUF_SIZE 0x400000 /* 4 MiB. */
#define LOG_FORCE_FLUSH 0 /* Forces a log buffer flush each time the logfile is written to. */

#define BIS_SYSTEM_PARTITION_MOUNT_NAME "sys:"

/// Reference: https://docs.microsoft.com/en-us/windows/win32/fileio/filesystem-functionality-comparison#limits.
/// Reference: https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits.
/// Most modern filesystems use a 255-byte limit instead of 255-character/codepoint limit, so that's what we're gonna use.
Expand Down
Loading

0 comments on commit 596928a

Please sign in to comment.