diff options
author | Raghuram Subramani <raghus2247@gmail.com> | 2022-06-19 19:47:51 +0530 |
---|---|---|
committer | Raghuram Subramani <raghus2247@gmail.com> | 2022-06-19 19:47:51 +0530 |
commit | 4fd287655a72b9aea14cdac715ad5b90ed082ed2 (patch) | |
tree | 65d393bc0e699dd12d05b29ba568e04cea666207 /circuitpython/supervisor/shared/filesystem.c | |
parent | 0150f70ce9c39e9e6dd878766c0620c85e47bed0 (diff) |
add circuitpython code
Diffstat (limited to 'circuitpython/supervisor/shared/filesystem.c')
-rw-r--r-- | circuitpython/supervisor/shared/filesystem.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/circuitpython/supervisor/shared/filesystem.c b/circuitpython/supervisor/shared/filesystem.c new file mode 100644 index 0000000..820dbe9 --- /dev/null +++ b/circuitpython/supervisor/shared/filesystem.c @@ -0,0 +1,203 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * 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 "supervisor/filesystem.h" + +#include "extmod/vfs_fat.h" +#include "lib/oofatfs/ff.h" +#include "lib/oofatfs/diskio.h" + +#include "py/mpstate.h" + +#include "supervisor/flash.h" + +static mp_vfs_mount_t _mp_vfs; +static fs_user_mount_t _internal_vfs; + +static volatile uint32_t filesystem_flush_interval_ms = CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS; +volatile bool filesystem_flush_requested = false; + +void filesystem_background(void) { + if (filesystem_flush_requested) { + filesystem_flush_interval_ms = CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS; + // Flush but keep caches + supervisor_flash_flush(); + filesystem_flush_requested = false; + } +} + +inline void filesystem_tick(void) { + if (filesystem_flush_interval_ms == 0) { + // 0 means not turned on. + return; + } + if (filesystem_flush_interval_ms == 1) { + filesystem_flush_requested = true; + filesystem_flush_interval_ms = CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS; + } else { + filesystem_flush_interval_ms--; + } +} + + +static void make_empty_file(FATFS *fatfs, const char *path) { + FIL fp; + f_open(fatfs, &fp, path, FA_WRITE | FA_CREATE_ALWAYS); + f_close(&fp); +} + + +static void make_sample_code_file(FATFS *fatfs) { + #if CIRCUITPY_FULL_BUILD + FIL fs; + UINT char_written = 0; + const byte buffer[] = "print(\"Hello World!\")\n"; + // Create or modify existing code.py file + f_open(fatfs, &fs, "/code.py", FA_WRITE | FA_CREATE_ALWAYS); + f_write(&fs, buffer, sizeof(buffer) - 1, &char_written); + f_close(&fs); + #else + make_empty_file(fatfs, "/code.py"); + #endif +} + +// we don't make this function static because it needs a lot of stack and we +// want it to be executed without using stack within main() function +bool filesystem_init(bool create_allowed, bool force_create) { + // init the vfs object + fs_user_mount_t *vfs_fat = &_internal_vfs; + vfs_fat->blockdev.flags = 0; + supervisor_flash_init_vfs(vfs_fat); + + // try to mount the flash + FRESULT res = f_mount(&vfs_fat->fatfs); + if ((res == FR_NO_FILESYSTEM && create_allowed) || force_create) { + // No filesystem so create a fresh one, or reformat has been requested. + uint8_t working_buf[FF_MAX_SS]; + BYTE formats = FM_FAT; + #if FF_FS_EXFAT + formats |= FM_EXFAT | FM_FAT32; + #endif + res = f_mkfs(&vfs_fat->fatfs, formats, 0, working_buf, sizeof(working_buf)); + if (res != FR_OK) { + return false; + } + // Flush the new file system to make sure it's repaired immediately. + supervisor_flash_flush(); + + // set label + #ifdef CIRCUITPY_DRIVE_LABEL + res = f_setlabel(&vfs_fat->fatfs, CIRCUITPY_DRIVE_LABEL); + #else + res = f_setlabel(&vfs_fat->fatfs, "CIRCUITPY"); + #endif + if (res != FR_OK) { + return false; + } + + // inhibit file indexing on MacOS + res = f_mkdir(&vfs_fat->fatfs, "/.fseventsd"); + if (res != FR_OK) { + return false; + } + make_empty_file(&vfs_fat->fatfs, "/.metadata_never_index"); + make_empty_file(&vfs_fat->fatfs, "/.Trashes"); + make_empty_file(&vfs_fat->fatfs, "/.fseventsd/no_log"); + // make a sample code.py file + make_sample_code_file(&vfs_fat->fatfs); + + // create empty lib directory + res = f_mkdir(&vfs_fat->fatfs, "/lib"); + if (res != FR_OK) { + return false; + } + + // and ensure everything is flushed + supervisor_flash_flush(); + } else if (res != FR_OK) { + return false; + } + mp_vfs_mount_t *vfs = &_mp_vfs; + vfs->str = "/"; + vfs->len = 1; + vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); + vfs->next = NULL; + MP_STATE_VM(vfs_mount_table) = vfs; + + // The current directory is used as the boot up directory. + // It is set to the internal flash filesystem by default. + MP_STATE_PORT(vfs_cur) = vfs; + + return true; +} + +void filesystem_flush(void) { + // Reset interval before next flush. + filesystem_flush_interval_ms = CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS; + supervisor_flash_flush(); + // Don't keep caches because this is called when starting or stopping the VM. + supervisor_flash_release_cache(); +} + +void filesystem_set_internal_writable_by_usb(bool writable) { + fs_user_mount_t *vfs = &_internal_vfs; + + filesystem_set_writable_by_usb(vfs, writable); +} + +void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable) { + if (usb_writable) { + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_USB_WRITABLE; + } else { + vfs->blockdev.flags &= ~MP_BLOCKDEV_FLAG_USB_WRITABLE; + } +} + +bool filesystem_is_writable_by_python(fs_user_mount_t *vfs) { + return (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0 || + (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) == 0; +} + +bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs) { + return (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0 || + (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) != 0; +} + +void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection) { + filesystem_set_concurrent_write_protection(&_internal_vfs, concurrent_write_protection); +} + +void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concurrent_write_protection) { + if (concurrent_write_protection) { + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED; + } else { + vfs->blockdev.flags &= ~MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED; + } +} + +bool filesystem_present(void) { + return true; +} |