-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pkg/xipfs: add XIPFS as vfs module #21197
Open
GGuche-2XS-Univ-Lille
wants to merge
16
commits into
RIOT-OS:2025.01-branch
Choose a base branch
from
GGuche-2XS-Univ-Lille:2024.10-xipfs-pull-request
base: 2025.01-branch
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+3,892
−15
Open
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
7c4d756
pkg/xipfs : RIOT integration of xipfs
ae474dc
examples/xipfs-tests: add xipfs tests
ad27dd4
examples/xipfs : Fixes bugs and adds executable example
GGuche-2XS-Univ-Lille 9f2e029
sys/shell : Adds two XIPFS shell commands
GGuche-2XS-Univ-Lille c588492
examples/xipfs-tests: fix xipfs tests
GGuche-2XS-Univ-Lille 9f6d030
static-tests : Fixed missing doc, invalid USEMODULE, example README.md
GGuche-2XS-Univ-Lille 4cd4f58
fixup! examples/xipfs-tests: fix xipfs tests
GGuche-2XS-Univ-Lille 2f9eb4d
fixup! pkg/xipfs : RIOT integration of xipfs
GGuche-2XS-Univ-Lille c83561b
fixup! pkg/xipfs : RIOT integration of xipfs
GGuche-2XS-Univ-Lille ea20850
fixup! examples/xipfs : Fixes bugs and adds executable example
GGuche-2XS-Univ-Lille 7201b37
fixup! fixup! examples/xipfs-tests: fix xipfs tests
GGuche-2XS-Univ-Lille ce4143f
fixup! fixup! pkg/xipfs : RIOT integration of xipfs
GGuche-2XS-Univ-Lille d0d00b1
fixup! static-tests : Fixed missing doc, invalid USEMODULE, example R…
GGuche-2XS-Univ-Lille c71f0af
fixup! fixup! fixup! pkg/xipfs : RIOT integration of xipfs
GGuche-2XS-Univ-Lille 36d1763
fixup! fixup! fixup! examples/xipfs-tests: fix xipfs tests
GGuche-2XS-Univ-Lille 82b9271
fixup! fixup! fixup! fixup! pkg/xipfs : RIOT integration of xipfs
GGuche-2XS-Univ-Lille File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# name of your application | ||
APPLICATION = xipfs | ||
|
||
# If no BOARD is found in the environment, use this default: | ||
BOARD ?= dwm1001 | ||
|
||
# This has to be the absolute path to the RIOT base directory: | ||
RIOTBASE ?= $(CURDIR)/../.. | ||
|
||
# Comment this out to disable code in RIOT that does safety checking | ||
# which is not needed in a production environment but helps in the | ||
# development process: | ||
DEVELHELP ?= 1 | ||
|
||
# Change this to 0 show compiler invocation lines by default: | ||
QUIET ?= 1 | ||
|
||
BLOBS += hello-world.fae | ||
|
||
# Modules to include: | ||
USEMODULE += shell | ||
USEMODULE += shell_cmds_default | ||
USEMODULE += ps | ||
|
||
# Use xipfs file system | ||
USEMODULE += xipfs | ||
|
||
CFLAGS +=-DRIOT_OS | ||
|
||
include $(RIOTBASE)/Makefile.include |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# The eXecute In-Place File System | ||
|
||
## Description | ||
|
||
`xipfs` is a file system designed to streamline post-issuance software | ||
deployment. `xipfs` allows direct execution of programs from flash | ||
memory, eliminating the need for prior copying to RAM. This approach | ||
conserves memory space and accelerates boot times, as the | ||
microcontroller can run code directly from storage memory without | ||
preloading into RAM. | ||
|
||
The `xipfs` structure is based on a linked list, where each file | ||
occupies at least one flash memory page. To prevent fragmentation, when | ||
a file is deleted, subsequent files are shifted to fill the vacant | ||
space. | ||
|
||
`xipfs` is compatible with all microcontrollers featuring addressable | ||
flash memory and most operating systems, provided they implement the | ||
necessary functions to interact with the flash controller. | ||
|
||
## Limitations | ||
|
||
`xipfs` has the following limitations: | ||
|
||
- No journaling: `xipfs` doesn't provide journaling. Without journaling, | ||
the file system cannot keep track of changes in a way that allows for | ||
recovery in the event of a crash or power failure. This can lead to | ||
data corruption and loss. | ||
|
||
- No checksums: `xipfs` doesn't provide checksums. The lack of checksums | ||
means that the file system cannot verify the integrity of files. This | ||
increases the risk of undetected data corruption, as there is no | ||
mechanism to ensure that files have not been altered or damaged. | ||
|
||
- Global file system lock: `xipfs` needs a global file system lock. A | ||
global file system lock can lead to performance bottlenecks, as it | ||
prevents multiple threads from accessing the file system | ||
simultaneously. | ||
|
||
- Fixed file size: `xipfs` provide fixed file size. By default, a file | ||
created using `vfs_open(2)` has a fixed space reserved in flash that | ||
is the size of a flash page. This size cannot be extended later. To | ||
create a file larger than the fixed size of one flash page, the | ||
`mk(1)` command or the `xipfs_new_file(3)` function must be used. | ||
|
||
- Limited character set: `xipfs` supports only a subset of 7-bit ASCII | ||
characters, specifically `[0-9A-Za-z\/\.\-_]`. | ||
|
||
- Limited path length: `xipfs` maximum path length is 64 characters. | ||
|
||
## Tested cards | ||
|
||
`xipfs` is expected to be compatible with all boards that feature | ||
addressable NVM. However, only the `DWM1001` board has been tested and | ||
is confirmed to function correctly. | ||
|
||
## Funding | ||
|
||
The `xipfs` project is part of the TinyPART project funded by the | ||
MESRI-BMBF German-French cybersecurity program under grant agreements | ||
n°ANR-20-CYAL-0005 and 16KIS1395K. |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
/* | ||
* Copyright (C) 2024 Université de Lille | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup examples | ||
* @{ | ||
* | ||
* @file | ||
* @brief An application demonstrating xipfs | ||
* | ||
* @author Damien Amara <damien.amara@univ-lille.fr> | ||
* @author Gregory Guche <gregory.guche@univ-lille.fr> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include <fcntl.h> | ||
#include <stdlib.h> | ||
|
||
#include "fs/xipfs_fs.h" | ||
#include "periph/flashpage.h" | ||
#include "shell.h" | ||
#include "vfs.h" | ||
|
||
/** | ||
* @def PANIC | ||
* | ||
* @brief This macro handles fatal errors | ||
*/ | ||
#define PANIC() for (;;); | ||
|
||
/** | ||
* @def NVME0P0_PAGE_NUM | ||
* | ||
* @brief The number of flash page for the nvme0p0 file system | ||
*/ | ||
#define NVME0P0_PAGE_NUM 10 | ||
|
||
/** | ||
* @def NVME0P1_PAGE_NUM | ||
* | ||
* @brief The number of flash page for the nvme0p1 file system | ||
*/ | ||
#define NVME0P1_PAGE_NUM 15 | ||
|
||
/* | ||
* Allocate a new contiguous space for the nvme0p0 file system | ||
*/ | ||
XIPFS_NEW_PARTITION(nvme0p0, "/dev/nvme0p0", NVME0P0_PAGE_NUM); | ||
|
||
/* | ||
* Allocate a new contiguous space for the nvme0p1 file system | ||
*/ | ||
XIPFS_NEW_PARTITION(nvme0p1, "/dev/nvme0p1", NVME0P1_PAGE_NUM); | ||
|
||
#ifdef BOARD_DWM1001 | ||
|
||
/** | ||
* @brief hello-world.fae data blob. | ||
* | ||
* To create a *.fae file, you will need to clone the master branch of | ||
* xipfs_format, that can be found at https://github.com/2xs/XiPFS_Format . | ||
* | ||
* Then modify the Makefile to suit your needs/sources and call make. | ||
* You should end up with a *.bin file ready to be uploaded. | ||
*/ | ||
#include "blob/hello-world.fae.h" | ||
|
||
#define FILENAME_OF_HELLO_WORLD_FAE "/dev/nvme0p0/hello-world.fae" | ||
#define SIZEOF_HELLO_WORLD_BIN (sizeof(hello_world_fae) / sizeof(hello_world_fae[0])) | ||
|
||
/** | ||
* @brief Execution in-place demonstrator. | ||
* | ||
* This shell command handler will create a file hello-world.fae on /dev/nvme0p0, | ||
* if none exists yet from the data blob above. | ||
* Then, it will execute this file. | ||
* | ||
* Once the file has been created, execute command can be used to rerun | ||
* the executable file as many times as wanted. | ||
* | ||
* ```bash | ||
* 2025-01-14 09:48:36,303 # main(): This is RIOT! (Version: 2024.10) | ||
* 2025-01-14 09:48:36,307 # vfs_mount: "/dev/nvme0p0": OK | ||
* 2025-01-14 09:48:36,313 # vfs_mount: "/dev/nvme0p1": OK | ||
* > help | ||
* 2025-01-14 09:48:42,300 # help | ||
* 2025-01-14 09:48:42,302 # Command Description | ||
* 2025-01-14 09:48:42,305 # --------------------------------------- | ||
* 2025-01-14 09:48:42,309 # exec Execute Hello World | ||
* 2025-01-14 09:48:42,314 # create_executable Create an XIPFS executable file | ||
* 2025-01-14 09:48:42,317 # execute Execute an XIPFS file | ||
* 2025-01-14 09:48:42,320 # ls list files | ||
* 2025-01-14 09:48:42,325 # pm interact with layered PM subsystem | ||
* 2025-01-14 09:48:42,331 # ps Prints information about running threads. | ||
* 2025-01-14 09:48:42,334 # reboot Reboot the node | ||
* 2025-01-14 09:48:42,338 # version Prints current RIOT_VERSION | ||
* 2025-01-14 09:48:42,343 # vfs virtual file system operations | ||
* > exec | ||
* 2025-01-14 09:48:49,572 # exec | ||
* 2025-01-14 09:48:49,573 # Hello World! | ||
* > ls /dev/nvme0p0 | ||
* 2025-01-14 09:48:59,997 # ls /dev/nvme0p0 | ||
* 2025-01-14 09:48:59,999 # hello-world.fae 896 B | ||
* 2025-01-14 09:49:00,000 # total 1 files | ||
* > vfs df | ||
* 2025-01-14 09:49:04,957 # vfs df | ||
* 2025-01-14 09:49:04,962 # Mountpoint Total Used Available Use% | ||
* 2025-01-14 09:49:04,968 # /dev/nvme0p0 40 KiB 4 KiB 36 KiB 10% | ||
* 2025-01-14 09:49:04,974 # /dev/nvme0p1 60 KiB 0 B 60 KiB 0% | ||
* execute /dev/nvme0p0/hello-world.fae ipsum dolores it | ||
* 2025-01-14 09:49:14,223 # execute /dev/nvme0p0/hello-world.fae Lorem ipsum dolor sit amet | ||
* 2025-01-14 09:49:14,225 # Hello World! | ||
* 2025-01-14 09:49:14,225 # Lorem | ||
* 2025-01-14 09:49:14,226 # ipsum | ||
* 2025-01-14 09:49:14,226 # dolor | ||
* 2025-01-14 09:49:14,227 # sit | ||
* 2025-01-14 09:49:14,227 # amet | ||
* ``` | ||
*/ | ||
int execution_handler(int argc, char **argv) { | ||
|
||
(void)argc; | ||
(void)argv; | ||
|
||
int file_handle = vfs_open(FILENAME_OF_HELLO_WORLD_FAE, O_RDONLY, 0); | ||
if (file_handle < 0) { | ||
|
||
/** There's no executable file yet, let's drop one */ | ||
int ret = xipfs_extended_driver_new_file( | ||
FILENAME_OF_HELLO_WORLD_FAE, SIZEOF_HELLO_WORLD_BIN, 1 | ||
); | ||
if (ret < 0) { | ||
printf("xipfs_extended_driver_new_file : failed to create '%s' : error=%d\n", | ||
FILENAME_OF_HELLO_WORLD_FAE, ret); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
/** | ||
* Fill it with blob data | ||
* Take care : vfs does not support O_APPEND with vfs_write, only O_WRONLY or O_RDWR | ||
*/ | ||
file_handle = vfs_open(FILENAME_OF_HELLO_WORLD_FAE, O_WRONLY, 0); | ||
if (file_handle < 0) { | ||
printf("vfs_open : failed to open '%s' : error =%d\n", | ||
FILENAME_OF_HELLO_WORLD_FAE, file_handle); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
ssize_t write_ret = vfs_write(file_handle, hello_world_fae, SIZEOF_HELLO_WORLD_BIN); | ||
if (write_ret < 0) { | ||
printf("vfs_write : failed to fill '%s' : error=%d\n", | ||
FILENAME_OF_HELLO_WORLD_FAE, write_ret); | ||
vfs_close(file_handle); | ||
return EXIT_FAILURE; | ||
} | ||
} | ||
|
||
vfs_close(file_handle); | ||
|
||
char *exec_argv[] = { | ||
FILENAME_OF_HELLO_WORLD_FAE, | ||
NULL | ||
}; | ||
int ret = xipfs_extended_driver_execv(FILENAME_OF_HELLO_WORLD_FAE, exec_argv); | ||
if (ret < 0) { | ||
printf("Failed to execute '%s' : error=%d\n", FILENAME_OF_HELLO_WORLD_FAE, ret); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
return EXIT_SUCCESS; | ||
} | ||
|
||
static shell_command_t shell_commands[] = { | ||
{"exec", "Execute Hello World", execution_handler}, | ||
{NULL, NULL, NULL}, | ||
}; | ||
|
||
#else // BOARD_DWM1001 | ||
|
||
#define shell_commands NULL | ||
|
||
#endif // BOARD_DWM1001 | ||
|
||
|
||
/** | ||
* @internal | ||
* | ||
* @brief Mount a partition, or if it is corrupted, format and | ||
* remount it | ||
* | ||
* @param xipfs_mp A pointer to a memory region containing an | ||
* xipfs mount point structure | ||
*/ | ||
|
||
static void mount_or_format(vfs_xipfs_mount_t *xipfs_mp) | ||
{ | ||
if (vfs_mount(&xipfs_mp->vfs_mp) < 0) { | ||
printf("vfs_mount: \"%s\": file system has not been " | ||
"initialized or is corrupted\n", xipfs_mp->vfs_mp.mount_point); | ||
printf("vfs_format: \"%s\": try initializing it\n", | ||
xipfs_mp->vfs_mp.mount_point); | ||
vfs_format(&xipfs_mp->vfs_mp); | ||
printf("vfs_format: \"%s\": OK\n", xipfs_mp->vfs_mp.mount_point); | ||
if (vfs_mount(&xipfs_mp->vfs_mp) < 0) { | ||
printf("vfs_mount: \"%s\": file system is corrupted!\n", | ||
xipfs_mp->vfs_mp.mount_point); | ||
PANIC(); | ||
} | ||
} | ||
printf("vfs_mount: \"%s\": OK\n", xipfs_mp->vfs_mp.mount_point); | ||
} | ||
|
||
|
||
int main(void) | ||
{ | ||
char line_buf[SHELL_DEFAULT_BUFSIZE]; | ||
|
||
mount_or_format(&nvme0p0); | ||
mount_or_format(&nvme0p1); | ||
|
||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
PKG_NAME=xipfs | ||
PKG_URL=https://github.com/2xs/xipfs.git | ||
PKG_VERSION=23f61316430d6cdbc6162e816ab32257a724492d | ||
PKG_LICENSE=CeCILL-2.1 | ||
|
||
include $(RIOTBASE)/pkg/pkg.mk | ||
|
||
export RIOT_INCLUDES=$(INCLUDES) | ||
export RIOT_CFLAGS=$(CFLAGS) | ||
|
||
all: $(BINDIR)/xipfs.a | ||
|
||
$(BINDIR)/xipfs.a: | ||
$(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR) | ||
@cp $(PKG_SOURCE_DIR)/xipfs.a $@ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
DEFAULT_MODULE += xipfs_fs | ||
|
||
# require xipfs_fs dependencies if this module isn't disabled | ||
ifeq (,$(filter xipfs_fs,$(DISABLE_MODULE))) | ||
# xipfs only makes sense if the flash memory is addressable | ||
FEATURES_REQUIRED += periph_flashpage_in_address_space | ||
FEATURES_OPTIONAL += periph_flashpage_aux | ||
USEMODULE += periph_flashpage | ||
USEMODULE += mtd_flashpage | ||
USEMODULE += vfs | ||
USEMODULE += shell_cmd_xipfs | ||
endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
INCLUDES += -I$(PKGDIRBASE)/xipfs | ||
|
||
ifneq (,$(filter xipfs_fs,$(USEMODULE))) | ||
DIRS += $(RIOTBASE)/pkg/xipfs/fs | ||
endif | ||
|
||
# include archive | ||
ARCHIVES += $(BINDIR)/xipfs.a |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This comment was marked as resolved.
Sorry, something went wrong.