Skip to content

Commit 60d3652

Browse files
authored
Merge pull request #478 from atar13/isolated-nvm-driver
isolated nonvolatile storage capsule with test
2 parents c6b0546 + 958b923 commit 60d3652

File tree

15 files changed

+960
-0
lines changed

15 files changed

+960
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Makefile for user application
2+
3+
# Specify this directory relative to the current application.
4+
TOCK_USERLAND_BASE_DIR = ../../../..
5+
6+
# Which files to compile.
7+
C_SRCS := $(wildcard *.c)
8+
9+
# Set the SHA256 hash for the credential checker on the `nrf52840dk-test-invs`
10+
# board. Also set the write_id to 0 meaning no storage permissions.
11+
ELF2TAB_ARGS += --sha256 --write_id 0
12+
13+
# Include userland master makefile. Contains rules and flags for actually
14+
# building the application.
15+
include $(TOCK_USERLAND_BASE_DIR)/AppMakefile.mk
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Isolated Nonvolatile Storage Test App With No Permissions
2+
=========================================================
3+
4+
This app tries to use the isolated nonvolatile storage capsule but is granted no
5+
storage access permissions (its `write_id` in the TBF header is 0). This
6+
verifies that the read and write calls return `ENOSUPPORT`.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#include <stdint.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
5+
#include <libtock-sync/storage/isolated_nonvolatile_storage.h>
6+
7+
8+
static bool test_exists(void) {
9+
bool exists = libtock_isolated_nonvolatile_storage_exists();
10+
11+
if (exists) {
12+
return true;
13+
}
14+
return false;
15+
}
16+
17+
static bool test_size(void) {
18+
uint64_t num_bytes;
19+
returncode_t ret;
20+
21+
ret = libtocksync_isolated_nonvolatile_storage_get_number_bytes(&num_bytes);
22+
23+
if (ret == RETURNCODE_ENOSUPPORT) {
24+
return true;
25+
}
26+
return false;
27+
}
28+
29+
static bool test_read(void) {
30+
returncode_t ret;
31+
32+
uint8_t readbuf[512];
33+
34+
uint32_t offset = 0;
35+
uint32_t length = 10;
36+
37+
ret = libtocksync_isolated_nonvolatile_storage_read(offset, readbuf, length);
38+
if (ret == RETURNCODE_ENOSUPPORT) {
39+
return true;
40+
}
41+
return false;
42+
}
43+
44+
45+
static bool test_write(void) {
46+
returncode_t ret;
47+
48+
uint8_t writebuf[512] = {0x3f};
49+
50+
uint32_t offset = 0;
51+
uint32_t length = 10;
52+
53+
ret = libtocksync_isolated_nonvolatile_storage_write(offset, writebuf, length);
54+
if (ret == RETURNCODE_ENOSUPPORT) {
55+
return true;
56+
}
57+
return false;
58+
}
59+
60+
61+
int main(void) {
62+
printf("[TEST] Isolated Nonvolatile Storage - No Permissions\n");
63+
64+
printf("[INVS TEST] Exists: ");
65+
if (test_exists()) {
66+
printf("Success\n");
67+
} else {
68+
printf("Fail\n");
69+
}
70+
71+
printf("[INVS TEST] Size: ");
72+
if (test_size()) {
73+
printf("Success\n");
74+
} else {
75+
printf("Fail\n");
76+
}
77+
78+
printf("[INVS TEST] Read: ");
79+
if (test_read()) {
80+
printf("Success\n");
81+
} else {
82+
printf("Fail\n");
83+
}
84+
85+
printf("[INVS TEST] Write: ");
86+
if (test_write()) {
87+
printf("Success\n");
88+
} else {
89+
printf("Fail\n");
90+
}
91+
92+
return 0;
93+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Makefile for user application
2+
3+
# Specify this directory relative to the current application.
4+
TOCK_USERLAND_BASE_DIR = ../../../..
5+
6+
# Which files to compile.
7+
C_SRCS := $(wildcard *.c)
8+
9+
# Set the SHA256 hash for the credential checker on the `nrf52840dk-test-invs`
10+
# board.
11+
ELF2TAB_ARGS += --sha256
12+
13+
# Include userland master makefile. Contains rules and flags for actually
14+
# building the application.
15+
include $(TOCK_USERLAND_BASE_DIR)/AppMakefile.mk
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Isolated Nonvolatile Storage Test App
2+
=====================================
3+
4+
This app writes to flash storage and reads it back to test that isolated storage
5+
is working.
6+
7+
Example Output
8+
--------------
9+
10+
```
11+
[TEST] Isolated Nonvolatile Storage
12+
Have 4096 bytes of nonvolatile storage
13+
Test with read size 14 and write size 256 ...
14+
Test with read size 14 and write size 256 ...
15+
Test with read size 512 and write size 512 ...
16+
Write to end of region (offset 3584)
17+
Test with read size 512 and write size 500 ...
18+
Write beyond end region, should fail (offset 4096)
19+
Test with read size 512 and write size 501 ...
20+
ERROR calling write. returncode: -6
21+
Write starts beyond end region, should fail (offset 4097)
22+
Test with read size 512 and write size 1 ...
23+
ERROR calling write. returncode: -6
24+
Write starts before start region, should fail (offset -1)
25+
Test with read size 512 and write size 512 ...
26+
ERROR calling write. returncode: -6
27+
All tests succeeded
28+
```
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#include <stdint.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
5+
#include <libtock-sync/storage/isolated_nonvolatile_storage.h>
6+
7+
static int test_all(void);
8+
static int test(uint8_t* readbuf, size_t readsize, uint8_t* writebuf, size_t writesize, size_t offset);
9+
10+
static size_t min(size_t a, size_t b) {
11+
if (a < b) return a;
12+
return b;
13+
}
14+
15+
int main(void) {
16+
printf("[TEST] Isolated Nonvolatile Storage\n");
17+
18+
int r = test_all();
19+
if (r == 0) {
20+
printf("All tests succeeded\n");
21+
} else {
22+
printf("Failed with code %d\n", r);
23+
}
24+
25+
return r;
26+
}
27+
28+
static int test_all(void) {
29+
uint64_t num_bytes_total;
30+
libtocksync_isolated_nonvolatile_storage_get_number_bytes(&num_bytes_total);
31+
int num_bytes = num_bytes_total;
32+
printf("Have %i bytes of nonvolatile storage\n", num_bytes);
33+
34+
int r;
35+
uint8_t readbuf[512];
36+
uint8_t writebuf[512];
37+
38+
if ((r = test(readbuf, 14, writebuf, 256, 0)) != 0) return r;
39+
if ((r = test(readbuf, 14, writebuf, 256, 20)) != 0) return r;
40+
if ((r = test(readbuf, 512, writebuf, 512, 0)) != 0) return r;
41+
42+
printf("Write to end of region (offset %d)\n", num_bytes - 512);
43+
if ((r = test(readbuf, 512, writebuf, 500, num_bytes - 512)) != 0) return r;
44+
45+
printf("Write beyond end region, should fail (offset %d)\n", num_bytes);
46+
if ((r = test(readbuf, 512, writebuf, 501, num_bytes)) == 0) return -1;
47+
48+
printf("Write starts beyond end region, should fail (offset %d)\n", num_bytes + 1);
49+
if ((r = test(readbuf, 512, writebuf, 1, num_bytes + 1)) == 0) return -1;
50+
51+
printf("Write starts before start region, should fail (offset %d)\n", -1);
52+
if ((r = test(readbuf, 512, writebuf, 512, -1)) == 0) return -1;
53+
54+
return 0;
55+
}
56+
57+
static int test(uint8_t* readbuf, size_t readsize, uint8_t* writebuf, size_t writesize, size_t offset) {
58+
int ret;
59+
60+
printf("\tTest with read size %d and write size %d ...\n", readsize, writesize);
61+
62+
for (size_t i = 0; i < writesize; i++) {
63+
writebuf[i] = i;
64+
}
65+
66+
ret = libtocksync_isolated_nonvolatile_storage_write(offset, writebuf, writesize);
67+
if (ret != RETURNCODE_SUCCESS) {
68+
printf("\tERROR calling write. returncode: %d\n", ret);
69+
return ret;
70+
}
71+
72+
ret = libtocksync_isolated_nonvolatile_storage_read(offset, readbuf, readsize);
73+
if (ret != RETURNCODE_SUCCESS) {
74+
printf("\tERROR calling read. returncode: %d\n", ret);
75+
return ret;
76+
}
77+
78+
for (size_t i = 0; i < min(readsize, writesize); i++) {
79+
if (readbuf[i] != writebuf[i]) {
80+
printf("\tInconsistency between data written and read at index %u\n", i);
81+
return -1;
82+
}
83+
}
84+
85+
return 0;
86+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Makefile for user application
2+
3+
# Specify this directory relative to the current application.
4+
TOCK_USERLAND_BASE_DIR = ../../../..
5+
6+
# Which files to compile.
7+
C_SRCS := $(wildcard *.c)
8+
9+
# Set the SHA256 hash for the credential checker on the `nrf52840dk-test-invs`
10+
# board.
11+
ELF2TAB_ARGS += --sha256
12+
13+
# Include userland master makefile. Contains rules and flags for actually
14+
# building the application.
15+
include $(TOCK_USERLAND_BASE_DIR)/AppMakefile.mk
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
Nonvolatile Storage Test App
2+
============================
3+
4+
This app writes to flash storage and reads it back to test that flash storage
5+
is working. It requires that a
6+
`capsules::nonvolatile_storage_driver::NonvolatileStorage` interface be provided
7+
to userland.
8+
9+
10+
11+
Example Hail Setup
12+
------------------
13+
14+
One way to provide the Driver interface with Hail looks like:
15+
16+
```diff
17+
--- a/boards/hail/src/main.rs
18+
+++ b/boards/hail/src/main.rs
19+
@@ -74,6 +74,7 @@ struct Hail {
20+
ipc: kernel::ipc::IPC,
21+
crc: &'static capsules::crc::Crc<'static, sam4l::crccu::Crccu<'static>>,
22+
dac: &'static capsules::dac::Dac<'static>,
23+
+ nv: &'static capsules::nonvolatile_storage_driver::NonvolatileStorage<'static>,
24+
}
25+
26+
/// Mapping of integer syscalls to objects that implement syscalls.
27+
@@ -104,6 +105,8 @@ impl Platform for Hail {
28+
capsules::dac::DRIVER_NUM => f(Some(self.dac)),
29+
30+
kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
31+
+
32+
+ 27 => f(Some(self.nv)),
33+
_ => f(None),
34+
}
35+
}
36+
@@ -443,6 +446,38 @@ pub unsafe fn reset_handler() {
37+
capsules::dac::Dac::new(&mut sam4l::dac::DAC)
38+
);
39+
40+
+ // Flash
41+
+ let mux_flash = static_init!(
42+
+ capsules::virtual_flash::MuxFlash<'static, sam4l::flashcalw::FLASHCALW>,
43+
+ capsules::virtual_flash::MuxFlash::new(&sam4l::flashcalw::FLASH_CONTROLLER));
44+
+ hil::flash::HasClient::set_client(&sam4l::flashcalw::FLASH_CONTROLLER, mux_flash);
45+
+
46+
+ // Nonvolatile Storage
47+
+ let virtual_flash_nv = static_init!(
48+
+ capsules::virtual_flash::FlashUser<'static, sam4l::flashcalw::FLASHCALW>,
49+
+ capsules::virtual_flash::FlashUser::new(mux_flash));
50+
+ pub static mut NV_PAGEBUFFER: sam4l::flashcalw::Sam4lPage = sam4l::flashcalw::Sam4lPage::new();
51+
+
52+
+ let nv_nv_to_page = static_init!(
53+
+ capsules::nonvolatile_to_pages::NonvolatileToPages<'static,
54+
+ capsules::virtual_flash::FlashUser<'static, sam4l::flashcalw::FLASHCALW>>,
55+
+ capsules::nonvolatile_to_pages::NonvolatileToPages::new(
56+
+ virtual_flash_nv,
57+
+ &mut NV_PAGEBUFFER));
58+
+ hil::flash::HasClient::set_client(virtual_flash_nv, nv_nv_to_page);
59+
+
60+
+ pub static mut NV_BUFFER: [u8; 512] = [0; 512];
61+
+ let nv = static_init!(
62+
+ capsules::nonvolatile_storage_driver::NonvolatileStorage<'static>,
63+
+ capsules::nonvolatile_storage_driver::NonvolatileStorage::new(
64+
+ nv_nv_to_page, kernel::Grant::create(),
65+
+ 0x60000, // Start address for userspace accessible region
66+
+ 0x20000, // Length of userspace accessible region
67+
+ 0, // Start address of kernel accessible region
68+
+ 0, // Length of kernel accessible region
69+
+ &mut NV_BUFFER));
70+
+ hil::nonvolatile_storage::NonvolatileStorage::set_client(nv_nv_to_page, nv);
71+
+
72+
let hail = Hail {
73+
console: console,
74+
gpio: gpio,
75+
@@ -460,6 +495,7 @@ pub unsafe fn reset_handler() {
76+
ipc: kernel::ipc::IPC::new(),
77+
crc: crc,
78+
dac: dac,
79+
+ nv: nv,
80+
};
81+
82+
// Need to reset the nRF on boot
83+
```

0 commit comments

Comments
 (0)