cc3200: Convert to use new VFS sub-system and new ooFatFs library.

crypto-aes
Damien George 6 years ago
parent 6eafa54486
commit 56506fd64a

@ -23,6 +23,7 @@ CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -march=armv7e-m -mabi=aapcs -mcpu=co
CFLAGS = -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os
CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno-unaligned-access
CFLAGS += -Iboards/$(BOARD)
CFLAGS += $(CFLAGS_MOD)
LDFLAGS = -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map

@ -18,7 +18,6 @@ APP_INC += -Iutil
APP_INC += -Ibootmgr
APP_INC += -I$(BUILD)
APP_INC += -I$(BUILD)/genhdr
APP_INC += -I../lib/fatfs
APP_INC += -I../lib/mp-readline
APP_INC += -I../lib/netutils
APP_INC += -I../lib/timeutils
@ -29,9 +28,6 @@ APP_CPPDEFINES = -Dgcc -DTARGET_IS_CC3200 -DSL_FULL -DUSE_FREERTOS
APP_FATFS_SRC_C = $(addprefix fatfs/src/,\
drivers/sflash_diskio.c \
drivers/sd_diskio.c \
option/syscall.c \
diskio.c \
ffconf.c \
)
APP_RTOS_SRC_C = $(addprefix FreeRTOS/Source/,\
@ -98,6 +94,7 @@ APP_MODS_SRC_C = $(addprefix mods/,\
pybpin.c \
pybi2c.c \
pybrtc.c \
pybflash.c \
pybsd.c \
pybsleep.c \
pybspi.c \
@ -143,11 +140,12 @@ APP_MAIN_SRC_C = \
main.c \
mptask.c \
mpthreadport.c \
serverstask.c
serverstask.c \
fatfs_port.c \
APP_LIB_SRC_C = $(addprefix lib/,\
fatfs/ff.c \
fatfs/option/ccsbcs.c \
oofatfs/ff.c \
oofatfs/option/unicode.c \
libc/string0.c \
mp-readline/readline.c \
netutils/netutils.c \

@ -1,209 +0,0 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2014 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include "py/mpconfig.h"
#include "py/runtime.h"
#include "py/obj.h"
#include "lib/fatfs/ff.h"
#include "lib/fatfs/diskio.h" /* FatFs lower layer API */
#include "sflash_diskio.h" /* Serial flash disk IO API */
#include "sd_diskio.h" /* SDCARD disk IO API */
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "rom_map.h"
#include "prcm.h"
#include "pybrtc.h"
#include "timeutils.h"
#include "pybsd.h"
#include "moduos.h"
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
if (pdrv == PD_FLASH) {
return sflash_disk_status();
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(pdrv))) {
if (mount_obj->writeblocks[0] == MP_OBJ_NULL) {
return STA_PROTECT;
}
return 0;
}
}
return STA_NODISK;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
if (pdrv == PD_FLASH) {
if (RES_OK != sflash_disk_init()) {
return STA_NOINIT;
}
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(pdrv))) {
if (mount_obj->writeblocks[0] == MP_OBJ_NULL) {
return STA_PROTECT;
}
return 0;
}
}
return STA_NODISK;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
)
{
if (pdrv == PD_FLASH) {
return sflash_disk_read(buff, sector, count);
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(pdrv))) {
// optimization for the built-in sd card device
if (mount_obj->device == (mp_obj_t)&pybsd_obj) {
return sd_disk_read(buff, sector, count);
}
mount_obj->readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
mount_obj->readblocks[3] = mp_obj_new_bytearray_by_ref(count * 512, buff);
return mp_obj_get_int(mp_call_method_n_kw(2, 0, mount_obj->readblocks));
}
// nothing mounted
return RES_ERROR;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if _USE_WRITE
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
{
if (pdrv == PD_FLASH) {
return sflash_disk_write(buff, sector, count);
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(pdrv))) {
// optimization for the built-in sd card device
if (mount_obj->device == (mp_obj_t)&pybsd_obj) {
return sd_disk_write(buff, sector, count);
}
mount_obj->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
mount_obj->writeblocks[3] = mp_obj_new_bytearray_by_ref(count * 512, (void *)buff);
return mp_obj_get_int(mp_call_method_n_kw(2, 0, mount_obj->writeblocks));
}
// nothing mounted
return RES_ERROR;
}
return RES_PARERR;
}
#endif
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
#if _USE_IOCTL
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
if (pdrv == PD_FLASH) {
switch (cmd) {
case CTRL_SYNC:
return sflash_disk_flush();
case GET_SECTOR_COUNT:
*((DWORD*)buff) = SFLASH_SECTOR_COUNT;
return RES_OK;
case GET_SECTOR_SIZE:
*((DWORD*)buff) = SFLASH_SECTOR_SIZE;
return RES_OK;
case GET_BLOCK_SIZE:
*((DWORD*)buff) = 1; // high-level sector erase size in units of the block size
return RES_OK;
}
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(pdrv))) {
switch (cmd) {
case CTRL_SYNC:
if (mount_obj->sync[0] != MP_OBJ_NULL) {
mp_call_method_n_kw(0, 0, mount_obj->sync);
}
return RES_OK;
case GET_SECTOR_COUNT:
// optimization for the built-in sd card device
if (mount_obj->device == (mp_obj_t)&pybsd_obj) {
*((DWORD*)buff) = sd_disk_info.ulNofBlock * (sd_disk_info.ulBlockSize / 512);
} else {
*((DWORD*)buff) = mp_obj_get_int(mp_call_method_n_kw(0, 0, mount_obj->count));
}
return RES_OK;
case GET_SECTOR_SIZE:
*((DWORD*)buff) = SD_SECTOR_SIZE; // Sector size is fixed to 512 bytes, as with SD cards
return RES_OK;
case GET_BLOCK_SIZE:
*((DWORD*)buff) = 1; // high-level sector erase size in units of the block size
return RES_OK;
}
}
// nothing mounted
return RES_ERROR;
}
return RES_PARERR;
}
#endif
#if !_FS_READONLY && !_FS_NORTC
DWORD get_fattime (
void
)
{
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(pyb_rtc_get_seconds(), &tm);
return ((tm.tm_year - 1980) << 25) | ((tm.tm_mon) << 21) |
((tm.tm_mday) << 16) | ((tm.tm_hour) << 11) |
((tm.tm_min) << 5) | (tm.tm_sec >> 1);
}
#endif

@ -39,11 +39,12 @@
#include "py/mpconfig.h"
#include "py/mphal.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
#include "hw_types.h"
#include "hw_memmap.h"
#include "hw_ints.h"
#include "rom_map.h"
#include "diskio.h"
#include "sd_diskio.h"
#include "sdhost.h"
#include "pin.h"

@ -4,8 +4,9 @@
#include "py/mpconfig.h"
#include "py/obj.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
#include "simplelink.h"
#include "diskio.h"
#include "sflash_diskio.h"
#include "debug.h"
#include "modnetwork.h"

@ -1,93 +0,0 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "py/mpstate.h"
#include "lib/fatfs/ff.h"
#include "lib/fatfs/ffconf.h"
#include "lib/fatfs/diskio.h"
#include "moduos.h"
#if _FS_RPATH
extern BYTE ff_CurrVol;
#endif
STATIC bool check_path(const TCHAR **path, const char *mount_point_str, mp_uint_t mount_point_len) {
if (strncmp(*path, mount_point_str, mount_point_len) == 0) {
if ((*path)[mount_point_len] == '/') {
*path += mount_point_len;
return true;
} else if ((*path)[mount_point_len] == '\0') {
*path = "/";
return true;
}
}
return false;
}
// "path" is the path to lookup; will advance this pointer beyond the volume name.
// Returns logical drive number (-1 means invalid path).
int ff_get_ldnumber (const TCHAR **path) {
if (!(*path)) {
return -1;
}
if (**path != '/') {
#if _FS_RPATH
return ff_CurrVol;
#else
return -1;
#endif
}
if (check_path(path, "/flash", 6)) {
return PD_FLASH;
}
else {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
if (check_path(path, mount_obj->path, mount_obj->pathlen)) {
return mount_obj->vol;
}
}
}
return -1;
}
void ff_get_volname(BYTE vol, TCHAR **dest) {
if (vol == PD_FLASH) {
memcpy(*dest, "/flash", 6);
*dest += 6;
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(vol))) {
memcpy(*dest, mount_obj->path, mount_obj->pathlen);
*dest += mount_obj->pathlen;
}
}
}

@ -1,150 +0,0 @@
/*------------------------------------------------------------------------*/
/* Sample code of OS dependent controls for FatFs */
/* (C)ChaN, 2014 */
/*------------------------------------------------------------------------*/
#include "ff.h"
#if _FS_REENTRANT
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object, such as semaphore and mutex. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_cre_syncobj ( /* !=0:Function succeeded, ==0:Could not create due to any error */
BYTE vol, /* Corresponding logical drive being processed */
_SYNC_t *sobj /* Pointer to return the created sync object */
)
{
int ret;
//
// *sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */
// ret = (int)(*sobj != INVALID_HANDLE_VALUE);
// *sobj = SyncObjects[vol]; /* uITRON (give a static created sync object) */
// ret = 1; /* The initial value of the semaphore must be 1. */
// *sobj = OSMutexCreate(0, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
vSemaphoreCreateBinary( (*sobj) ); /* FreeRTOS */
ret = (int)(*sobj != NULL);
return ret;
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* !=0:Function succeeded, ==0:Could not delete due to any error */
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
int ret;
// ret = CloseHandle(sobj); /* Win32 */
// ret = 1; /* uITRON (nothing to do) */
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
vSemaphoreDelete(sobj); /* FreeRTOS */
ret = 1;
return ret;
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
_SYNC_t sobj /* Sync object to wait */
)
{
int ret;
// ret = (int)(WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0); /* Win32 */
// ret = (int)(wai_sem(sobj) == E_OK); /* uITRON */
// OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
ret = (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE); /* FreeRTOS */
return ret;
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
_SYNC_t sobj /* Sync object to be signaled */
)
{
// ReleaseMutex(sobj); /* Win32 */
// sig_sem(sobj); /* uITRON */
// OSMutexPost(sobj); /* uC/OS-II */
xSemaphoreGive(sobj); /* FreeRTOS */
}
#endif
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
*/
void* ff_memalloc ( /* Returns pointer to the allocated memory block */
UINT msize /* Number of bytes to allocate */
)
{
return pvPortMalloc(msize); /* Allocate a new memory block with POSIX API */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free */
)
{
vPortFree(mblock); /* Discard the memory block with POSIX API */
}
#endif

@ -0,0 +1,74 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2017 Damien P. George
* Parts of this file are (C)ChaN, 2014, from FatFs option/syscall.c
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "lib/oofatfs/ff.h"
#include "lib/timeutils/timeutils.h"
#include "mods/pybrtc.h"
#if _FS_REENTRANT
// Create a Synchronization Object
// This function is called in f_mount() function to create a new
// synchronization object, such as semaphore and mutex.
// A return of 0 indicates failure, and then f_mount() fails with FR_INT_ERR.
int ff_cre_syncobj(FATFS *fatfs, _SYNC_t *sobj) {
vSemaphoreCreateBinary((*sobj));
return (int)(*sobj != NULL);
}
// Delete a Synchronization Object
// This function is called in f_mount() function to delete a synchronization
// object that created with ff_cre_syncobj function.
// A return of 0 indicates failure, and then f_mount() fails with FR_INT_ERR.
int ff_del_syncobj(_SYNC_t sobj) {
vSemaphoreDelete(sobj);
return 1;
}
// Request Grant to Access the Volume
// This function is called on entering file functions to lock the volume.
// When a 0 is returned, the file function fails with FR_TIMEOUT.
int ff_req_grant(_SYNC_t sobj) {
return (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE);
}
// Release Grant to Access the Volume
// This function is called on leaving file functions to unlock the volume.
void ff_rel_grant(_SYNC_t sobj) {
xSemaphoreGive(sobj);
}
#endif
DWORD get_fattime(void) {
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(pyb_rtc_get_seconds(), &tm);
return ((tm.tm_year - 1980) << 25) | ((tm.tm_mon) << 21) |
((tm.tm_mday) << 16) | ((tm.tm_hour) << 11) |
((tm.tm_min) << 5) | (tm.tm_sec >> 1);
}

@ -30,6 +30,9 @@
#include "py/mpstate.h"
#include "py/obj.h"
#include "lib/oofatfs/ff.h"
#include "extmod/vfs.h"
#include "extmod/fsusermount.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
@ -43,7 +46,6 @@
#include "modusocket.h"
#include "debug.h"
#include "serverstask.h"
#include "ff.h"
#include "fifo.h"
#include "socketfifo.h"
#include "updater.h"
@ -115,7 +117,7 @@ typedef struct {
uint8_t *dBuffer;
uint32_t ctimeout;
union {
DIR dp;
FF_DIR dp;
FIL fp;
};
int16_t lc_sd;
@ -192,6 +194,80 @@ static const ftp_month_t ftp_month[] = { { "Jan" }, { "Feb" }, { "Mar" }, { "Apr
static SocketFifoElement_t ftp_fifoelements[FTP_SOCKETFIFO_ELEMENTS_MAX];
static FIFO_t ftp_socketfifo;
/******************************************************************************
DEFINE VFS WRAPPER FUNCTIONS
******************************************************************************/
// These wrapper functions are used so that the FTP server can access the
// mounted FATFS devices directly without going through the costly mp_vfs_XXX
// functions. The latter may raise exceptions and we would then need to wrap
// all calls in an nlr handler. The wrapper functions below assume that there
// are only FATFS filesystems mounted.
STATIC FATFS *lookup_path(const TCHAR **path) {
mp_vfs_mount_t *fs = mp_vfs_lookup_path(*path, path);
if (fs == MP_VFS_NONE || fs == MP_VFS_ROOT) {
return NULL;
}
// here we assume that the mounted device is FATFS
return &((fs_user_mount_t*)MP_OBJ_TO_PTR(fs->obj))->fatfs;
}
STATIC FRESULT f_open_helper(FIL *fp, const TCHAR *path, BYTE mode) {
FATFS *fs = lookup_path(&path);
if (fs == NULL) {
return FR_NO_PATH;
}
return f_open(fs, fp, path, mode);
}
STATIC FRESULT f_opendir_helper(FF_DIR *dp, const TCHAR *path) {
FATFS *fs = lookup_path(&path);
if (fs == NULL) {
return FR_NO_PATH;
}
return f_opendir(fs, dp, path);
}
STATIC FRESULT f_stat_helper(const TCHAR *path, FILINFO *fno) {
FATFS *fs = lookup_path(&path);
if (fs == NULL) {
return FR_NO_PATH;
}
return f_stat(fs, path, fno);
}
STATIC FRESULT f_mkdir_helper(const TCHAR *path) {
FATFS *fs = lookup_path(&path);
if (fs == NULL) {
return FR_NO_PATH;
}
return f_mkdir(fs, path);
}
STATIC FRESULT f_unlink_helper(const TCHAR *path) {
FATFS *fs = lookup_path(&path);
if (fs == NULL) {
return FR_NO_PATH;
}
return f_unlink(fs, path);
}
STATIC FRESULT f_rename_helper(const TCHAR *path_old, const TCHAR *path_new) {
FATFS *fs_old = lookup_path(&path_old);
if (fs_old == NULL) {
return FR_NO_PATH;
}
FATFS *fs_new = lookup_path(&path_new);
if (fs_new == NULL) {
return FR_NO_PATH;
}
if (fs_old != fs_new) {
return FR_NO_PATH;
}
return f_rename(fs_new, path_old, path_new);
}
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
@ -210,7 +286,7 @@ static void ftp_close_cmd_data (void);
static ftp_cmd_index_t ftp_pop_command (char **str);
static void ftp_pop_param (char **str, char *param);
static int ftp_print_eplf_item (char *dest, uint32_t destsize, FILINFO *fno);
static int ftp_print_eplf_drive (char *dest, uint32_t destsize, char *name);
static int ftp_print_eplf_drive (char *dest, uint32_t destsize, const char *name);
static bool ftp_open_file (const char *path, int mode);
static ftp_result_t ftp_read_file (char *filebuf, uint32_t desiredsize, uint32_t *actualsize);
static ftp_result_t ftp_write_file (char *filebuf, uint32_t size);
@ -604,10 +680,6 @@ static void ftp_process_cmd (void) {
ftp_result_t result;
FRESULT fres;
FILINFO fno;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
ftp_data.closechild = false;
// also use the reply buffer to receive new commands
@ -634,7 +706,7 @@ static void ftp_process_cmd (void) {
fres = FR_NO_PATH;
ftp_pop_param (&bufptr, ftp_scratch_buffer);
ftp_open_child (ftp_path, ftp_scratch_buffer);
if ((ftp_path[0] == '/' && ftp_path[1] == '\0') || ((fres = f_opendir (&ftp_data.dp, ftp_path)) == FR_OK)) {
if ((ftp_path[0] == '/' && ftp_path[1] == '\0') || ((fres = f_opendir_helper (&ftp_data.dp, ftp_path)) == FR_OK)) {
if (fres == FR_OK) {
f_closedir(&ftp_data.dp);
}
@ -653,7 +725,7 @@ static void ftp_process_cmd (void) {
case E_FTP_CMD_SIZE:
{
ftp_get_param_and_open_child (&bufptr);
if (FR_OK == f_stat (ftp_path, &fno)) {
if (FR_OK == f_stat_helper(ftp_path, &fno)) {
// send the size
snprintf((char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, "%u", (_u32)fno.fsize);
ftp_send_reply(213, (char *)ftp_data.dBuffer);
@ -665,7 +737,7 @@ static void ftp_process_cmd (void) {
break;
case E_FTP_CMD_MDTM:
ftp_get_param_and_open_child (&bufptr);
if (FR_OK == f_stat (ftp_path, &fno)) {
if (FR_OK == f_stat_helper(ftp_path, &fno)) {
// send the last modified time
snprintf((char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, "%u%02u%02u%02u%02u%02u",
1980 + ((fno.fdate >> 9) & 0x7f), (fno.fdate >> 5) & 0x0f,
@ -773,7 +845,7 @@ static void ftp_process_cmd (void) {
case E_FTP_CMD_DELE:
case E_FTP_CMD_RMD:
ftp_get_param_and_open_child (&bufptr);
if (FR_OK == f_unlink(ftp_path)) {
if (FR_OK == f_unlink_helper(ftp_path)) {
ftp_send_reply(250, NULL);
}
else {
@ -782,7 +854,7 @@ static void ftp_process_cmd (void) {
break;
case E_FTP_CMD_MKD:
ftp_get_param_and_open_child (&bufptr);
if (FR_OK == f_mkdir(ftp_path)) {
if (FR_OK == f_mkdir_helper(ftp_path)) {
ftp_send_reply(250, NULL);
}
else {
@ -791,7 +863,7 @@ static void ftp_process_cmd (void) {
break;
case E_FTP_CMD_RNFR:
ftp_get_param_and_open_child (&bufptr);
if (FR_OK == f_stat (ftp_path, &fno)) {
if (FR_OK == f_stat_helper(ftp_path, &fno)) {
ftp_send_reply(350, NULL);
// save the current path
strcpy ((char *)ftp_data.dBuffer, ftp_path);
@ -803,7 +875,7 @@ static void ftp_process_cmd (void) {
case E_FTP_CMD_RNTO:
ftp_get_param_and_open_child (&bufptr);
// old path was saved in the data buffer
if (FR_OK == (fres = f_rename ((char *)ftp_data.dBuffer, ftp_path))) {
if (FR_OK == (fres = f_rename_helper((char *)ftp_data.dBuffer, ftp_path))) {
ftp_send_reply(250, NULL);
}
else {
@ -898,24 +970,16 @@ static int ftp_print_eplf_item (char *dest, uint32_t destsize, FILINFO *fno) {
if (FTP_UNIX_SECONDS_180_DAYS < tseconds - fseconds) {
return snprintf(dest, destsize, "%srw-rw-r-- 1 root root %9u %s %2u %5u %s\r\n",
type, (_u32)fno->fsize, ftp_month[mindex].month, day,
#if _USE_LFN
1980 + ((fno->fdate >> 9) & 0x7f), *fno->lfname ? fno->lfname : fno->fname);
#else
1980 + ((fno->fdate >> 9) & 0x7f), fno->fname);
#endif
}
else {
return snprintf(dest, destsize, "%srw-rw-r-- 1 root root %9u %s %2u %02u:%02u %s\r\n",
type, (_u32)fno->fsize, ftp_month[mindex].month, day,
#if _USE_LFN
(fno->ftime >> 11) & 0x1f, (fno->ftime >> 5) & 0x3f, *fno->lfname ? fno->lfname : fno->fname);
#else
(fno->ftime >> 11) & 0x1f, (fno->ftime >> 5) & 0x3f, fno->fname);
#endif
}
}
static int ftp_print_eplf_drive (char *dest, uint32_t destsize, char *name) {
static int ftp_print_eplf_drive (char *dest, uint32_t destsize, const char *name) {
timeutils_struct_time_t tm;
uint32_t tseconds;
char *type = "d";
@ -934,7 +998,7 @@ static int ftp_print_eplf_drive (char *dest, uint32_t destsize, char *name) {
}
static bool ftp_open_file (const char *path, int mode) {
FRESULT res = f_open(&ftp_data.fp, path, mode);
FRESULT res = f_open_helper(&ftp_data.fp, path, mode);
if (res != FR_OK) {
return false;
}
@ -976,7 +1040,7 @@ static ftp_result_t ftp_open_dir_for_listing (const char *path) {
ftp_data.listroot = true;
} else {
FRESULT res;
res = f_opendir(&ftp_data.dp, path); /* Open the directory */
res = f_opendir_helper(&ftp_data.dp, path); /* Open the directory */
if (res != FR_OK) {
return E_FTP_RESULT_FAILED;
}
@ -993,9 +1057,6 @@ static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *li
ftp_result_t result = E_FTP_RESULT_CONTINUE;
FILINFO fno;
#if _USE_LFN
fno.lfname = mem_Malloc(_MAX_LFN);
fno.lfsize = _MAX_LFN;
// read up to 2 directory items
while (listcount < 2) {
#else
@ -1004,17 +1065,20 @@ static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *li
#endif
if (ftp_data.listroot) {
// root directory "hack"
if (0 == ftp_data.volcount) {
next += ftp_print_eplf_drive((list + next), (maxlistsize - next), "flash");
} else if (ftp_data.volcount <= MP_STATE_PORT(mount_obj_list).len) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[(ftp_data.volcount - 1)]));
next += ftp_print_eplf_drive((list + next), (maxlistsize - next), (char *)&mount_obj->path[1]);
} else {
mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table);
int i = ftp_data.volcount;
while (vfs != NULL && i != 0) {
vfs = vfs->next;
i -= 1;
}
if (vfs == NULL) {
if (!next) {
// no volume found this time, we are done
ftp_data.volcount = 0;
}
break;
} else {
next += ftp_print_eplf_drive((list + next), (maxlistsize - next), vfs->str + 1);
}
ftp_data.volcount++;
} else {
@ -1036,9 +1100,6 @@ static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *li
ftp_close_files();
}
*listsize = next;
#if _USE_LFN
mem_Free(fno.lfname);
#endif
return result;
}

@ -113,14 +113,3 @@ void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
// the following is temporay, until cc3200 converts to oofatfs
#include "py/lexer.h"
#include "extmod/vfs_fat.h"
mp_import_stat_t mp_import_stat(const char *path) {
return fat_vfs_import_stat(NULL, path);
}
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, fatfs_builtin_open);

@ -33,10 +33,12 @@
#include "py/objtuple.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
#include "genhdr/mpversion.h"
#include "moduos.h"
#include "diskio.h"
#include "sflash_diskio.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "random.h"
#include "mpexception.h"
@ -59,155 +61,20 @@
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC uint32_t os_num_mounted_devices;
STATIC os_term_dup_obj_t os_term_dup_obj;
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC void unmount (os_fs_mount_t *mount_obj);
STATIC bool path_equal(const char *path, const char *path_canonical);
STATIC void append_dir_item (mp_obj_t dirlist, const char *item, bool string);
STATIC void mount (mp_obj_t device, const char *path, uint pathlen, bool readonly);
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void moduos_init0 (void) {
// initialize the mount objects list
mp_obj_list_init(&MP_STATE_PORT(mount_obj_list), 0);
os_num_mounted_devices = 0;
}
os_fs_mount_t *osmount_find_by_path (const char *path) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
if (!strcmp(path, mount_obj->path)) {
return mount_obj;
}
}
return NULL;
}
os_fs_mount_t *osmount_find_by_volume (uint8_t vol) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
if (vol == mount_obj->vol) {
return mount_obj;
}
}
return NULL;
}
os_fs_mount_t *osmount_find_by_device (mp_obj_t device) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
if (device == mount_obj->device) {
return mount_obj;
}
}
return NULL;
}
void osmount_unmount_all (void) {
//TODO
/*
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
unmount(mount_obj);
}
}
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
// Checks for path equality, ignoring trailing slashes:
// path_equal(/, /) -> true
// path_equal(/flash//, /flash) -> true
// second argument must be in canonical form (meaning no trailing slash, unless it's just /)
STATIC bool path_equal(const char *path, const char *path_canonical) {
for (; *path_canonical != '\0' && *path == *path_canonical; ++path, ++path_canonical) {
}
if (*path_canonical != '\0') {
return false;
}
for (; *path == '/'; ++path) {
}
return *path == '\0';
}
STATIC void append_dir_item (mp_obj_t dirlist, const char *item, bool string) {
// make a string object for this entry
mp_obj_t entry_o;
if (string) {
entry_o = mp_obj_new_str(item, strlen(item), false);
} else {
entry_o = mp_obj_new_bytes((const byte*)item, strlen(item));
}
// add the entry to the list
mp_obj_list_append(dirlist, entry_o);
}
STATIC void mount (mp_obj_t device, const char *path, uint pathlen, bool readonly) {
// is the mount point already in use?
FILINFO fno;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
// cannot mount twice or on existing paths
if (f_stat(path, &fno) == FR_OK || osmount_find_by_device(device)) {
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
}
// create a new object
os_fs_mount_t *self = m_new_obj(os_fs_mount_t);
self->device = device;
self->path = path;
self->pathlen = pathlen;
self->vol = os_num_mounted_devices + 1; // '/flash' is volume 0
if (device == (mp_obj_t)&pybsd_obj) {
// need to make it different to NULL, otherwise it's read only by default
self->writeblocks[0] = mp_const_none;
self->sync[0] = MP_OBJ_NULL; // no need to sync the SD card
self->count[0] = MP_OBJ_NULL;
} else {
// load block protocol methods
mp_load_method(device, MP_QSTR_readblocks, self->readblocks);
mp_load_method_maybe(device, MP_QSTR_writeblocks, self->writeblocks);
mp_load_method_maybe(device, MP_QSTR_sync, self->sync);
mp_load_method(device, MP_QSTR_count, self->count);
}
// Read-only device indicated by writeblocks[0] == MP_OBJ_NULL.
// User can specify read-only device by:
// 1. readonly=True keyword argument
// 2. nonexistent writeblocks method (then writeblocks[0] == MP_OBJ_NULL already)
if (readonly) {
self->writeblocks[0] = MP_OBJ_NULL;
}
// we need to add it before doing the actual mount, so that the volume can be found
mp_obj_list_append(&MP_STATE_PORT(mount_obj_list), self);
// actually mount it
if (f_mount(&self->fatfs, self->path, 1) != FR_OK) {
// remove it and raise
mp_obj_list_remove(&MP_STATE_PORT(mount_obj_list), self);
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
}
// mount succeeded, increment the count
os_num_mounted_devices++;
}
STATIC void unmount (os_fs_mount_t *mount_obj) {
// remove it from the list and then call FatFs
f_mount (NULL, mount_obj->path, 1);
mp_obj_list_remove(&MP_STATE_PORT(mount_obj_list), mount_obj);
os_num_mounted_devices--;
*/
}
/******************************************************************************/
@ -239,193 +106,6 @@ STATIC mp_obj_t os_uname(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
/// \function chdir(path)
/// Change current directory.
STATIC mp_obj_t os_chdir(mp_obj_t path_in) {
const char *path;
path = mp_obj_str_get_str(path_in);
FRESULT res = f_chdrive(path);
if (res == FR_OK) {
res = f_chdir(path);
}
if (res != FR_OK) {
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir);
STATIC mp_obj_t os_getcwd(void) {
char buf[MICROPY_ALLOC_PATH_MAX + 1];
FRESULT res = f_getcwd(buf, sizeof buf);
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
}
return mp_obj_new_str(buf, strlen(buf), false);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd);
STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) {
bool is_str_type = true;
const char *path;
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
if (n_args == 1) {
if (mp_obj_get_type(args[0]) == &mp_type_bytes) {
is_str_type = false;
}
path = mp_obj_str_get_str(args[0]);
} else {
path = "";
}
// "hack" to list the root directory
if (path[0] == '/' && path[1] == '\0') {
// add 'flash' to the list
append_dir_item (dir_list, "flash", is_str_type);
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
append_dir_item (dir_list, &mount_obj->path[1], is_str_type);
}
} else {
FRESULT res;
DIR dir;
FILINFO fno;
#if _USE_LFN
char lfn_buf[_MAX_LFN + 1];
fno.lfname = lfn_buf;
fno.lfsize = sizeof(lfn_buf);
#endif
res = f_opendir(&dir, path); /* Open the directory */
if (res != FR_OK) {
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
}
for ( ; ; ) {
res = f_readdir(&dir, &fno); /* Read a directory item */
if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */
if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */
#if _USE_LFN
char *fn = *fno.lfname ? fno.lfname : fno.fname;
#else
char *fn = fno.fname;
#endif
// add the entry to the list
append_dir_item (dir_list, fn, is_str_type);
}
f_closedir(&dir);
}
return dir_list;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_listdir_obj, 0, 1, os_listdir);
STATIC mp_obj_t os_mkdir(mp_obj_t path_o) {
const char *path = mp_obj_str_get_str(path_o);
FRESULT res = f_mkdir(path);
switch (res) {
case FR_OK:
return mp_const_none;
case FR_EXIST:
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
break;
default:
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir);
STATIC mp_obj_t os_rename(mp_obj_t path_in, mp_obj_t path_out) {
const char *old_path = mp_obj_str_get_str(path_in);
const char *new_path = mp_obj_str_get_str(path_out);
FRESULT res = f_rename(old_path, new_path);
switch (res) {
case FR_OK:
return mp_const_none;
default:
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename);
STATIC mp_obj_t os_remove(mp_obj_t path_o) {
const char *path = mp_obj_str_get_str(path_o);
FRESULT res = f_unlink(path);
switch (res) {
case FR_OK:
return mp_const_none;
default:
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove);
STATIC mp_obj_t os_stat(mp_obj_t path_in) {
const char *path = mp_obj_str_get_str(path_in);
bool isbuilt_in = false;
FILINFO fno;
FRESULT res;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
// check on the user mounted devices
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
if (path_equal(path, mount_obj->path)) {
isbuilt_in = true;
break;
}
}
if (path_equal(path, "/") || path_equal(path, "/flash") || isbuilt_in) {
// stat built-in directory
fno.fsize = 0;
fno.fdate = 0;
fno.ftime = 0;
fno.fattrib = AM_DIR;
} else if ((res = f_stat(path, &fno)) != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
}
mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL);
mp_int_t mode = 0;
if (fno.fattrib & AM_DIR) {
mode |= 0x4000; // stat.S_IFDIR
} else {
mode |= 0x8000; // stat.S_IFREG
}
mp_int_t seconds = timeutils_seconds_since_2000(
1980 + ((fno.fdate >> 9) & 0x7f),
(fno.fdate >> 5) & 0x0f,
fno.fdate & 0x1f,
(fno.ftime >> 11) & 0x1f,
(fno.ftime >> 5) & 0x3f,
2 * (fno.ftime & 0x1f)
);
t->items[0] = mp_obj_new_int(mode); // st_mode
t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino
t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev
t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink
t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid
t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid
t->items[6] = mp_obj_new_int(fno.fsize); // st_size
t->items[7] = mp_obj_new_int(seconds); // st_atime
t->items[8] = t->items[7]; // st_mtime
t->items[9] = t->items[7]; // st_ctime
return t;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_stat_obj, os_stat);
STATIC mp_obj_t os_sync(void) {
sflash_disk_flush();
return mp_const_none;
@ -443,110 +123,6 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
STATIC mp_obj_t os_mount(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t mount_args[] = {
{ MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
// parse args
mp_obj_t device = pos_args[0];
mp_obj_t mount_point = pos_args[1];
mp_arg_val_t args[MP_ARRAY_SIZE(mount_args)];
mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(mount_args), mount_args, args);
// get the mount point
mp_uint_t pathlen;
const char *path_in = mp_obj_str_get_data(mount_point, &pathlen);
if (pathlen == 0) {
goto invalid_args;
}
char *path = m_new(char, pathlen + 1);
memcpy(path, path_in, pathlen);
path[pathlen] = '\0';
// "remove" any extra slahes at the end
while (path[(pathlen - 1)] == '/') {
path[--pathlen] = '\0';
}
// is the mount point valid?
if (pathlen < 2 || path[0] !='/' || strchr(&path[1], '/')) {
goto invalid_args;
}
// now mount it
mount(device, path, pathlen, args[0].u_bool);
return mp_const_none;
invalid_args:
mp_raise_msg(&mp_type_OSError, mpexception_value_invalid_arguments);
}
MP_DEFINE_CONST_FUN_OBJ_KW(os_mount_obj, 2, os_mount);
STATIC mp_obj_t os_unmount(mp_obj_t path_o) {
const char *path = mp_obj_str_get_str(path_o);
// '/flash' cannot be unmounted, also not the current working directory
if (path_equal(path, "/flash")) {
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
}
// now unmount it
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_path(path))) {
unmount (mount_obj);
} else {
mp_raise_msg(&mp_type_ValueError, mpexception_value_invalid_arguments);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_unmount_obj, os_unmount);
STATIC mp_obj_t os_mkfs(mp_obj_t device) {
const char *path = "/__mkfs__mnt__";
os_fs_mount_t *mount_obj = NULL;
bool unmt = false;
FRESULT res;
if (MP_OBJ_IS_STR_OR_BYTES(device)) {
path = mp_obj_str_get_str(device);
// otherwise the relative path check will pass...
if (path[0] != '/') {
mp_raise_msg(&mp_type_OSError, mpexception_value_invalid_arguments);
}
} else {
// mount it briefly
mount(device, path, strlen(path), false);
unmt = true;
}
byte sfd = 0;
if (!memcmp(path, "/flash", strlen("/flash"))) {
sfd = 1;
} else if ((mount_obj = osmount_find_by_path(path))) {
if (mount_obj->device != (mp_obj_t)&pybsd_obj &&
mp_obj_get_int(mp_call_method_n_kw(0, 0, mount_obj->count)) < 2048) {
sfd = 1;
}
}
// now format the device
res = f_mkfs(path, sfd, 0);
if (unmt && mount_obj) {
unmount (mount_obj);
}
if (res != FR_OK) {
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkfs_obj, os_mkfs);
STATIC mp_obj_t os_dupterm(uint n_args,