mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
Pass screen status and mmc struct from stage1 to 2
This commit is contained in:
parent
116eb6c67c
commit
b2139ed182
13 changed files with 139 additions and 30 deletions
|
@ -15,15 +15,8 @@
|
||||||
|
|
||||||
static bool g_ahb_redirect_enabled = false;
|
static bool g_ahb_redirect_enabled = false;
|
||||||
|
|
||||||
// Only use voltage switching in stage2 and later.
|
|
||||||
#ifdef FUSEE_STAGE1_SRC
|
|
||||||
#define MMC_VOLTAGE_SWITCHING_ALLOWED false
|
|
||||||
#else
|
|
||||||
#define MMC_VOLTAGE_SWITCHING_ALLOWED true
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Global sd struct. */
|
/* Global sd struct. */
|
||||||
static struct mmc g_sd_mmc = {0};
|
struct mmc g_sd_mmc = {0};
|
||||||
static bool g_sd_initialized = false;
|
static bool g_sd_initialized = false;
|
||||||
|
|
||||||
int initialize_sd_mmc(void) {
|
int initialize_sd_mmc(void) {
|
||||||
|
@ -33,7 +26,7 @@ int initialize_sd_mmc(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_sd_initialized) {
|
if (!g_sd_initialized) {
|
||||||
int rc = sdmmc_init(&g_sd_mmc, SWITCH_MICROSD, MMC_VOLTAGE_SWITCHING_ALLOWED);
|
int rc = sdmmc_init(&g_sd_mmc, SWITCH_MICROSD, false);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
g_sd_initialized = true;
|
g_sd_initialized = true;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -108,7 +108,9 @@ int main(void) {
|
||||||
const char *stage2_path;
|
const char *stage2_path;
|
||||||
stage2_args_t *stage2_args;
|
stage2_args_t *stage2_args;
|
||||||
uint32_t stage2_version = 0;
|
uint32_t stage2_version = 0;
|
||||||
|
extern struct mmc g_sd_mmc;
|
||||||
|
|
||||||
|
sdmmc_set_loglevel(2);
|
||||||
/* Initialize the display, console, etc. */
|
/* Initialize the display, console, etc. */
|
||||||
setup_env();
|
setup_env();
|
||||||
|
|
||||||
|
@ -134,6 +136,8 @@ int main(void) {
|
||||||
strcpy(g_chainloader_arg_data, stage2_path);
|
strcpy(g_chainloader_arg_data, stage2_path);
|
||||||
stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */
|
stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */
|
||||||
memcpy(&stage2_args->version, &stage2_version, 4);
|
memcpy(&stage2_args->version, &stage2_version, 4);
|
||||||
|
stage2_args->display_initialized = false;
|
||||||
|
memcpy(&stage2_args->sd_mmc, &g_sd_mmc, sizeof(g_sd_mmc));
|
||||||
strcpy(stage2_args->bct0, bct0);
|
strcpy(stage2_args->bct0, bct0);
|
||||||
g_chainloader_argc = 2;
|
g_chainloader_argc = 2;
|
||||||
|
|
||||||
|
|
|
@ -2259,7 +2259,7 @@ static int sdmmc_send_app_command(struct mmc *mmc, enum sdmmc_command command,
|
||||||
}
|
}
|
||||||
|
|
||||||
// And issue the body of the command.
|
// And issue the body of the command.
|
||||||
return sdmmc_send_command(mmc, command, response_type, checks, argument, response_buffer,
|
return sdmmc_send_command(mmc, command, response_type, checks, argument, response_buffer,
|
||||||
blocks_to_transfer, false, auto_terminate, data_buffer);
|
blocks_to_transfer, false, auto_terminate, data_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3382,8 +3382,8 @@ static int sdmmc_initialize_defaults(struct mmc *mmc)
|
||||||
* @param controler The controller description to be used; usually SWITCH_EMMC
|
* @param controler The controller description to be used; usually SWITCH_EMMC
|
||||||
* or SWITCH_MICROSD.
|
* or SWITCH_MICROSD.
|
||||||
* @param allow_voltage_switching True if we should allow voltage switching,
|
* @param allow_voltage_switching True if we should allow voltage switching,
|
||||||
* which may not make sense if we're about to chainload to another component,
|
* which may not make sense if we're about to chainload to another component without
|
||||||
* a la fusee stage1.
|
* preseving the overall structure.
|
||||||
*/
|
*/
|
||||||
int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching)
|
int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching)
|
||||||
{
|
{
|
||||||
|
@ -3445,6 +3445,29 @@ int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_vol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports a SDMMC driver struct from another program. This mainly intended for stage2,
|
||||||
|
* so that it can reuse stage1's SDMMC struct instance(s).
|
||||||
|
*
|
||||||
|
* @param mmc The SDMMC structure to be imported.
|
||||||
|
*/
|
||||||
|
int sdmmc_import_struct(struct mmc *mmc)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
bool uses_block_addressing = mmc->uses_block_addressing;
|
||||||
|
mmc->regs = sdmmc_get_regs(mmc->controller);
|
||||||
|
|
||||||
|
rc = sdmmc_initialize_defaults(mmc);
|
||||||
|
if (rc) {
|
||||||
|
printk("ERROR: controller SDMMC%d not currently supported!\n", mmc->controller + 1);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
mmc->uses_block_addressing = uses_block_addressing;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the active MMC partition. Can be used to select
|
* Selects the active MMC partition. Can be used to select
|
||||||
* boot partitions for access. Affects all operations going forward.
|
* boot partitions for access. Affects all operations going forward.
|
||||||
|
|
|
@ -234,12 +234,21 @@ int sdmmc_set_loglevel(int loglevel);
|
||||||
* @param controler The controller description to be used; usually SWITCH_EMMC
|
* @param controler The controller description to be used; usually SWITCH_EMMC
|
||||||
* or SWITCH_MICROSD.
|
* or SWITCH_MICROSD.
|
||||||
* @param allow_voltage_switching True if we should allow voltage switching,
|
* @param allow_voltage_switching True if we should allow voltage switching,
|
||||||
* which may not make sense if we're about to chainload to another component,
|
* which may not make sense if we're about to chainload to another component without
|
||||||
* a la fusee stage1.
|
* preseving the overall structure.
|
||||||
*/
|
*/
|
||||||
int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching);
|
int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports a SDMMC driver struct from another program. This mainly intended for stage2,
|
||||||
|
* so that it can reuse stage1's SDMMC struct instance(s).
|
||||||
|
*
|
||||||
|
* @param mmc The SDMMC structure to be imported.
|
||||||
|
*/
|
||||||
|
int sdmmc_import_struct(struct mmc *mmc);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the active MMC partition. Can be used to select
|
* Selects the active MMC partition. Can be used to select
|
||||||
* boot partitions for access. Affects all operations going forward.
|
* boot partitions for access. Affects all operations going forward.
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define FUSEE_STAGE2_H
|
#define FUSEE_STAGE2_H
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "sdmmc.h"
|
||||||
|
|
||||||
/* TODO: Is there a more concise way to do this? */
|
/* TODO: Is there a more concise way to do this? */
|
||||||
#define STAGE2_ARGV_PROGRAM_PATH 0
|
#define STAGE2_ARGV_PROGRAM_PATH 0
|
||||||
|
@ -11,7 +12,7 @@
|
||||||
#define STAGE2_NAME_KEY "stage2_path"
|
#define STAGE2_NAME_KEY "stage2_path"
|
||||||
#define STAGE2_ADDRESS_KEY "stage2_addr"
|
#define STAGE2_ADDRESS_KEY "stage2_addr"
|
||||||
#define STAGE2_ENTRYPOINT_KEY "stage2_entrypoint"
|
#define STAGE2_ENTRYPOINT_KEY "stage2_entrypoint"
|
||||||
#define BCTO_MAX_SIZE 0x6000
|
#define BCTO_MAX_SIZE 0x5800
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char path[0x100];
|
char path[0x100];
|
||||||
|
@ -21,6 +22,8 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
struct mmc sd_mmc;
|
||||||
|
bool display_initialized;
|
||||||
char bct0[BCTO_MAX_SIZE];
|
char bct0[BCTO_MAX_SIZE];
|
||||||
} stage2_args_t;
|
} stage2_args_t;
|
||||||
|
|
||||||
|
|
|
@ -87,15 +87,19 @@ static ssize_t decode_utf8(uint32_t *out, const uint8_t *in) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void console_init_display(void) {
|
static void console_init_display(void) {
|
||||||
/* Initialize the display. */
|
if (!g_display_initialized) {
|
||||||
display_init();
|
/* Initialize the display. */
|
||||||
|
display_init();
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the framebuffer. */
|
/* Set the framebuffer. */
|
||||||
display_init_framebuffer(g_framebuffer);
|
display_init_framebuffer(g_framebuffer);
|
||||||
|
|
||||||
/* Turn on the backlight after initializing the lfb */
|
/* Turn on the backlight after initializing the lfb */
|
||||||
/* to avoid flickering. */
|
/* to avoid flickering. */
|
||||||
display_enable_backlight(true);
|
if (!g_display_initialized) {
|
||||||
|
display_enable_backlight(true);
|
||||||
|
}
|
||||||
|
|
||||||
g_display_initialized = true;
|
g_display_initialized = true;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +144,10 @@ static int console_create(void) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int console_init(void) {
|
|
||||||
|
int console_init(bool display_initialized) {
|
||||||
|
g_display_initialized = display_initialized;
|
||||||
|
|
||||||
if (console_create() == -1) {
|
if (console_create() == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef FUSEE_CONSOLE_H
|
#ifndef FUSEE_CONSOLE_H
|
||||||
#define FUSEE_CONSOLE_H
|
#define FUSEE_CONSOLE_H
|
||||||
|
|
||||||
int console_init(void);
|
int console_init(bool display_initialized);
|
||||||
void *console_get_framebuffer(bool enable_display);
|
void *console_get_framebuffer(bool enable_display);
|
||||||
int console_display(const void *framebuffer); /* Must be page-aligned */
|
int console_display(const void *framebuffer); /* Must be page-aligned */
|
||||||
int console_resume(void);
|
int console_resume(void);
|
||||||
|
|
|
@ -23,14 +23,14 @@ static bool g_do_nxboot;
|
||||||
|
|
||||||
static void setup_env(void) {
|
static void setup_env(void) {
|
||||||
/* Set the console up. */
|
/* Set the console up. */
|
||||||
if (console_init() == -1) {
|
if (console_init(g_stage2_args->display_initialized) == -1) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up exception handlers. */
|
/* Set up exception handlers. */
|
||||||
setup_exception_handlers();
|
setup_exception_handlers();
|
||||||
|
|
||||||
if(switchfs_mount_all() == -1) {
|
if(switchfs_import_mmc_structs(&g_stage2_args->sd_mmc, NULL) == -1 || switchfs_mount_all() == -1) {
|
||||||
fatal_error("Failed to mount at least one parition: %s\n", strerror(errno));
|
fatal_error("Failed to mount at least one parition: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2259,7 +2259,7 @@ static int sdmmc_send_app_command(struct mmc *mmc, enum sdmmc_command command,
|
||||||
}
|
}
|
||||||
|
|
||||||
// And issue the body of the command.
|
// And issue the body of the command.
|
||||||
return sdmmc_send_command(mmc, command, response_type, checks, argument, response_buffer,
|
return sdmmc_send_command(mmc, command, response_type, checks, argument, response_buffer,
|
||||||
blocks_to_transfer, false, auto_terminate, data_buffer);
|
blocks_to_transfer, false, auto_terminate, data_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3382,8 +3382,8 @@ static int sdmmc_initialize_defaults(struct mmc *mmc)
|
||||||
* @param controler The controller description to be used; usually SWITCH_EMMC
|
* @param controler The controller description to be used; usually SWITCH_EMMC
|
||||||
* or SWITCH_MICROSD.
|
* or SWITCH_MICROSD.
|
||||||
* @param allow_voltage_switching True if we should allow voltage switching,
|
* @param allow_voltage_switching True if we should allow voltage switching,
|
||||||
* which may not make sense if we're about to chainload to another component,
|
* which may not make sense if we're about to chainload to another component without
|
||||||
* a la fusee stage1.
|
* preseving the overall structure.
|
||||||
*/
|
*/
|
||||||
int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching)
|
int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching)
|
||||||
{
|
{
|
||||||
|
@ -3445,6 +3445,29 @@ int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_vol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports a SDMMC driver struct from another program. This mainly intended for stage2,
|
||||||
|
* so that it can reuse stage1's SDMMC struct instance(s).
|
||||||
|
*
|
||||||
|
* @param mmc The SDMMC structure to be imported.
|
||||||
|
*/
|
||||||
|
int sdmmc_import_struct(struct mmc *mmc)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
bool uses_block_addressing = mmc->uses_block_addressing;
|
||||||
|
mmc->regs = sdmmc_get_regs(mmc->controller);
|
||||||
|
|
||||||
|
rc = sdmmc_initialize_defaults(mmc);
|
||||||
|
if (rc) {
|
||||||
|
printk("ERROR: controller SDMMC%d not currently supported!\n", mmc->controller + 1);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
mmc->uses_block_addressing = uses_block_addressing;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the active MMC partition. Can be used to select
|
* Selects the active MMC partition. Can be used to select
|
||||||
* boot partitions for access. Affects all operations going forward.
|
* boot partitions for access. Affects all operations going forward.
|
||||||
|
|
|
@ -234,12 +234,21 @@ int sdmmc_set_loglevel(int loglevel);
|
||||||
* @param controler The controller description to be used; usually SWITCH_EMMC
|
* @param controler The controller description to be used; usually SWITCH_EMMC
|
||||||
* or SWITCH_MICROSD.
|
* or SWITCH_MICROSD.
|
||||||
* @param allow_voltage_switching True if we should allow voltage switching,
|
* @param allow_voltage_switching True if we should allow voltage switching,
|
||||||
* which may not make sense if we're about to chainload to another component,
|
* which may not make sense if we're about to chainload to another component without
|
||||||
* a la fusee stage1.
|
* preseving the overall structure.
|
||||||
*/
|
*/
|
||||||
int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching);
|
int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports a SDMMC driver struct from another program. This mainly intended for stage2,
|
||||||
|
* so that it can reuse stage1's SDMMC struct instance(s).
|
||||||
|
*
|
||||||
|
* @param mmc The SDMMC structure to be imported.
|
||||||
|
*/
|
||||||
|
int sdmmc_import_struct(struct mmc *mmc);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the active MMC partition. Can be used to select
|
* Selects the active MMC partition. Can be used to select
|
||||||
* boot partitions for access. Affects all operations going forward.
|
* boot partitions for access. Affects all operations going forward.
|
||||||
|
|
|
@ -2,16 +2,19 @@
|
||||||
#define FUSEE_STAGE2_H
|
#define FUSEE_STAGE2_H
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "sdmmc.h"
|
||||||
|
|
||||||
/* TODO: Is there a more concise way to do this? */
|
/* TODO: Is there a more concise way to do this? */
|
||||||
#define STAGE2_ARGV_PROGRAM_PATH 0
|
#define STAGE2_ARGV_PROGRAM_PATH 0
|
||||||
#define STAGE2_ARGV_ARGUMENT_STRUCT 1
|
#define STAGE2_ARGV_ARGUMENT_STRUCT 1
|
||||||
#define STAGE2_ARGC 2
|
#define STAGE2_ARGC 2
|
||||||
|
|
||||||
#define BCTO_MAX_SIZE 0x6000
|
#define BCTO_MAX_SIZE 0x5800
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
struct mmc sd_mmc;
|
||||||
|
bool display_initialized;
|
||||||
char bct0[BCTO_MAX_SIZE];
|
char bct0[BCTO_MAX_SIZE];
|
||||||
} stage2_args_t;
|
} stage2_args_t;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,9 @@ static bool g_ahb_redirect_enabled = false;
|
||||||
static bool g_sd_mmc_initialized = false;
|
static bool g_sd_mmc_initialized = false;
|
||||||
static bool g_nand_mmc_initialized = false;
|
static bool g_nand_mmc_initialized = false;
|
||||||
|
|
||||||
|
static bool g_sd_mmc_imported = false;
|
||||||
|
static bool g_nand_mmc_imported = false;
|
||||||
|
|
||||||
static struct mmc g_sd_mmc = {0};
|
static struct mmc g_sd_mmc = {0};
|
||||||
static struct mmc g_nand_mmc = {0};
|
static struct mmc g_nand_mmc = {0};
|
||||||
|
|
||||||
|
@ -43,7 +46,7 @@ static int mmc_partition_initialize(device_partition_t *devpart) {
|
||||||
|
|
||||||
if (mmcpart->mmc == &g_sd_mmc) {
|
if (mmcpart->mmc == &g_sd_mmc) {
|
||||||
if (!g_sd_mmc_initialized) {
|
if (!g_sd_mmc_initialized) {
|
||||||
int rc = sdmmc_init(mmcpart->mmc, mmcpart->controller, true);
|
int rc = g_sd_mmc_imported ? 0 : sdmmc_init(mmcpart->mmc, mmcpart->controller, true);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
sdmmc_set_write_enable(mmcpart->mmc, SDMMC_WRITE_ENABLED);
|
sdmmc_set_write_enable(mmcpart->mmc, SDMMC_WRITE_ENABLED);
|
||||||
g_sd_mmc_initialized = true;
|
g_sd_mmc_initialized = true;
|
||||||
|
@ -56,7 +59,7 @@ static int mmc_partition_initialize(device_partition_t *devpart) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (mmcpart->mmc == &g_nand_mmc) {
|
} else if (mmcpart->mmc == &g_nand_mmc) {
|
||||||
if (!g_nand_mmc_initialized) {
|
if (!g_nand_mmc_initialized) {
|
||||||
int rc = sdmmc_init(mmcpart->mmc, mmcpart->controller, true);
|
int rc = g_nand_mmc_imported ? 0 : sdmmc_init(mmcpart->mmc, mmcpart->controller, true);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
g_nand_mmc_initialized = true;
|
g_nand_mmc_initialized = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -235,6 +238,36 @@ static int switchfs_mount_partition_gpt_callback(const efi_entry_t *entry, void
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int switchfs_import_mmc_structs(void *sd, void *nand) {
|
||||||
|
if (sd != NULL) {
|
||||||
|
int rc = 0;
|
||||||
|
memcpy(&g_sd_mmc, sd, sizeof(g_sd_mmc));
|
||||||
|
rc = sdmmc_import_struct(&g_sd_mmc);
|
||||||
|
if (rc != 0) {
|
||||||
|
memset(&g_sd_mmc, 0, sizeof(g_sd_mmc));
|
||||||
|
errno = rc;
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
g_sd_mmc_imported = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nand != NULL) {
|
||||||
|
int rc = 0;
|
||||||
|
memcpy(&g_nand_mmc, nand, sizeof(g_nand_mmc));
|
||||||
|
rc = sdmmc_import_struct(&g_nand_mmc);
|
||||||
|
if (rc != 0) {
|
||||||
|
memset(&g_nand_mmc, 0, sizeof(g_nand_mmc));
|
||||||
|
errno = rc;
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
g_nand_mmc_imported = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int switchfs_mount_all(void) {
|
int switchfs_mount_all(void) {
|
||||||
device_partition_t model;
|
device_partition_t model;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "fs_dev.h"
|
#include "fs_dev.h"
|
||||||
#include "raw_dev.h"
|
#include "raw_dev.h"
|
||||||
|
|
||||||
|
int switchfs_import_mmc_structs(void *sd, void *nand);
|
||||||
|
|
||||||
int switchfs_mount_all(void);
|
int switchfs_mount_all(void);
|
||||||
int switchfs_unmount_all(void);
|
int switchfs_unmount_all(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue