diff options
author | isiora <none@example.com> | 2018-05-11 10:09:11 +0000 |
---|---|---|
committer | isiora <none@example.com> | 2018-05-11 10:09:11 +0000 |
commit | d7921befb0703ba5bd304c4441fae1c783e2f5dc (patch) | |
tree | ede8ab01a3c21ba40a56ef9da5211d1e36823059 | |
parent | dd882e357ea36c7ed28511d81b41680623ae216b (diff) | |
download | ChibiOS-d7921befb0703ba5bd304c4441fae1c783e2f5dc.tar.gz ChibiOS-d7921befb0703ba5bd304c4441fae1c783e2f5dc.tar.bz2 ChibiOS-d7921befb0703ba5bd304c4441fae1c783e2f5dc.zip |
Refactoring of the proxy stubs code.
Added the IOBlks proxystub.
Included reliance edge test.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12021 110e8d01-0319-4d1e-a829-52ad28d1bb01
-rw-r--r-- | demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/.project | 5 | ||||
-rwxr-xr-x | demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/Makefile | 5 | ||||
-rw-r--r-- | demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/ch_sec_nsec.cmm | 61 | ||||
-rwxr-xr-x | demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/chconf.h | 2 | ||||
-rwxr-xr-x | demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/main.c | 86 | ||||
-rw-r--r-- | demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/mcuconf.h | 11 | ||||
-rw-r--r-- | demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/redconf.h | 114 | ||||
-rw-r--r-- | demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/reliance.mk | 38 | ||||
-rw-r--r-- | demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/tservices.c | 11 |
9 files changed, 316 insertions, 17 deletions
diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/.project b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/.project index 2610966b7..dc40bc8a9 100644 --- a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/.project +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/.project @@ -87,6 +87,11 @@ <locationURI>CHIBIOS/os</locationURI> </link> <link> + <name>reliance-edge</name> + <type>2</type> + <locationURI>CHIBIOS/ext/reliance-edge</locationURI> + </link> + <link> <name>test</name> <type>2</type> <locationURI>CHIBIOS/test</locationURI> diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/Makefile b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/Makefile index 4f210dc2a..02febb392 100755 --- a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/Makefile +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/Makefile @@ -5,7 +5,7 @@ # Compiler options here.
ifeq ($(USE_OPT),)
- USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16
+ USE_OPT = -Og -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
@@ -131,6 +131,7 @@ include $(CHIBIOS)/test/lib/test.mk include $(CHIBIOS)/test/rt/rt_test.mk
include $(CHIBIOS)/test/oslib/oslib_test.mk
include $(CHIBIOS)/os/hal/lib/streams/streams.mk
+include reliance.mk
# Define linker script file here
LDSCRIPT= $(STARTUPLD)/SAMA5D2ddr.ld
@@ -140,7 +141,9 @@ LDSCRIPT= $(STARTUPLD)/SAMA5D2ddr.ld CSRC = $(ALLCSRC) \
$(TESTSRC) \
tservices.c \
+ proxies/tsproxystubs.c \
proxies/tssockstub.c \
+ proxies/tsioblksstub.c \
main.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/ch_sec_nsec.cmm b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/ch_sec_nsec.cmm new file mode 100644 index 000000000..98213cc81 --- /dev/null +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/ch_sec_nsec.cmm @@ -0,0 +1,61 @@ +; -------------------------------------------------------------------------------- +; @Title: SEC/NSEC demo script for ATSAMA5D28 on ATSAMA5D2B-XULT +; @Description: +; Test the TSSI api, the socket proxy and the Trusted Execution Environment +; @Keywords: ARM, Cortex-A5 +; @Author: Orabona +; @Board: ATSAMA5D2B-XULT +; @Chip: ATSAMA5D28 +; -------------------------------------------------------------------------------- + + +; -------------------------------------------------------------------------------- +; initialize and start the debugger +RESet +SYStem.RESet +SYStem.Config SWDP ON +SYStem.CPU ATSAMA5D28 +IF VERSION.BUILD()<84227. +( + SYStem.CONFIG L2CACHE Type L2C-310 + SYStem.CONFIG L2CACHE Base ANC:0xA00000 +) +SYStem.Option ResBreak OFF +SYStem.Option EnReset OFF +SYStem.Option WaitReset 30.ms +SYStem.Option ZoneSPACES ON +SYStem.JtagClock CTCK 10MHz +Trace.DISable +SYStem.Up + +GOSUB DisableWatchdog + +; -------------------------------------------------------------------------------- +; load demo program (uses internal RAM only) +;Data.LOAD.Elf "~/bootstrap_bv1000.elf" Z: +Data.LOAD.Elf "~/bootstrap.elf" Z: +Register.Set PC 0x200000 +Go +PRINT "Wait!" +WAIT !STATE.RUN() + +Data.LOAD.Elf "~/Chibilogic/GBC/ChibiOS/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-NSEC/build/ch.elf" N: + +Data.LOAD.Elf "~/Chibilogic/GBC/ChibiOS/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/build/ch.elf" Z: /NAME ch_sec /NoClear + +; -------------------------------------------------------------------------------- +; start program execution +Register.Set PC 0x27000000 +Go Boot_Handler +WAIT !STATE.RUN() + +b.s main + +ENDDO + +DisableWatchdog: +( + ; disable the Watchdog + Data.Set AD:0xF8048044 %Long Data.Long(AD:0xF8048044)|0x8000 + RETURN +) diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/chconf.h b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/chconf.h index 6db52ba06..b4155a3b5 100755 --- a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/chconf.h +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/chconf.h @@ -72,7 +72,7 @@ * The value one is not valid, timeouts are rounded up to
* this value.
*/
-#define CH_CFG_ST_TIMEDELTA 2
+#define CH_CFG_ST_TIMEDELTA 6
/** @} */
diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/main.c b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/main.c index 479b7c513..ca7838920 100755 --- a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/main.c +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/main.c @@ -17,15 +17,21 @@ #include "ch.h"
#include "hal.h"
#include "chtssi.h"
+#include "proxies/tsproxystubs.h"
#include "proxies/tssockstub.h"
#include "rt_test_root.h"
#include "oslib_test_root.h"
#include "chprintf.h"
-#include <string.h>
+#include "redfs.h"
+#include "redposix.h"
+#include "redfse.h"
+#include "redconf.h"
+#include "string.h"
-#define SERVER_PORT_NUM 8080
#define SERVER_IP_ADDRESS "192.168.1.104"
+#define BSS ((BaseSequentialStream *)&SD1)
+
void tcpexample(int port) {
int socket_fd;
struct sockaddr_in ra;
@@ -42,7 +48,7 @@ void tcpexample(int port) { socket_fd = socket(PF_INET, SOCK_STREAM, 0);
if ( socket_fd < 0 ) {
- chprintf((BaseSequentialStream *)&SD1, "socket call failed.\r\n");
+ chprintf(BSS, "socket call failed.\r\n");
return;
}
@@ -57,7 +63,7 @@ void tcpexample(int port) { if (connect(socket_fd, (struct sockaddr *)&ra,
sizeof (struct sockaddr_in)) < 0) {
- chprintf((BaseSequentialStream *)&SD1, "Connect failed.\r\n");
+ chprintf(BSS, "Connect failed.\r\n");
close(socket_fd);
return;
}
@@ -65,7 +71,7 @@ void tcpexample(int port) { chsnprintf(data_buffer, sizeof data_buffer,
"Sending this message on port %d.\r\n", port);
if (send(socket_fd, data_buffer, strlen(data_buffer), 0) < 0) {
- chprintf((BaseSequentialStream *)&SD1, "Send failed.\r\n");
+ chprintf(BSS, "Send failed.\r\n");
close(socket_fd);
return;
}
@@ -73,19 +79,19 @@ void tcpexample(int port) { FD_SET(socket_fd, &rset);
recv_data = select(socket_fd+1, &rset, 0, 0, &tm);
if (recv_data < 0) {
- chprintf((BaseSequentialStream *)&SD1, "Select failed.\r\n");
+ chprintf(BSS, "Select failed.\r\n");
close(socket_fd);
return;
}
} while (recv_data == 0);
recv_data = recv(socket_fd, data_buffer, sizeof data_buffer, 0);
if (recv_data < 0) {
- chprintf((BaseSequentialStream *)&SD1, "Recv failed.\r\n");
+ chprintf(BSS, "Recv failed.\r\n");
close(socket_fd);
return;
}
data_buffer[recv_data] = '\0';
- chprintf((BaseSequentialStream *)&SD1, "Received data: %s.\r\n", data_buffer);
+ chprintf(BSS, "Received data: %s\r\n", data_buffer);
}
close(socket_fd);
}
@@ -94,13 +100,71 @@ void tcpexample(int port) { * Two threads that run the same tcp example on two
* different ports.
*/
-static THD_WORKING_AREA(waThreadTcp1, 512);
-static THD_WORKING_AREA(waThreadTcp2, 512);
+static THD_WORKING_AREA(waThreadTcp1, 8192);
+static THD_WORKING_AREA(waThreadTcp2, 8192);
static THD_FUNCTION(ThreadTcp, arg) {
int port = (int)arg;
+ static int once = 0;
+ static const char wb[] = "Baba', dolce baba'.\r\n";
- tsWaitStubSkelReady();
+ tsWaitStubSkelReady(EVT_F_SOCK_NEW_OP|EVT_F_IOBLK_NEW_OP);
chThdSleepMilliseconds(5000);
+
+ /* one among the threads runs Reliance Edge test on remote partition.*/
+ if (!once) {
+ int32_t fd, n;
+ static char buf[128];
+ static const char *filename = "Test.txt";
+
+ once = 1;
+ red_init();
+ if (red_mount("") == -1) {
+ chprintf(BSS, "Formatting the partition.\r\n");
+ red_format("");
+ red_mount("");
+ }
+ if ((fd = red_open(filename, RED_O_RDWR)) == -1) {
+ int i;
+ chprintf(BSS, "Creating a file.\r\n");
+ fd = red_open(filename, RED_O_RDWR|RED_O_CREAT);
+ if (fd == -1) {
+ chprintf(BSS, "Cannot create the file. Aborting.\r\n");
+ goto re_abort;
+ }
+ chprintf(BSS, "Writing it.\r\n");
+ for (i = 0; i < 10; ++i)
+ if (red_write(fd, wb, sizeof wb - 1) == -1) {
+ chprintf(BSS, "Cannot write into the file. Aborting.\r\n");
+ goto re_abort;
+ }
+ chprintf(BSS, "Closing it.\r\n");
+ red_close(fd);
+ chprintf(BSS, "Reopening it.\r\n");
+ fd = red_open(filename, RED_O_RDWR);
+ if (fd == -1) {
+ chprintf(BSS, "Cannot open the file. Aborting.\r\n");
+ goto re_abort;
+ }
+ }
+ chprintf(BSS, "Reading:\r\n");
+ do {
+ n = red_read(fd, buf, sizeof buf - 1);
+ if (n == -1) {
+ chprintf(BSS, "Cannot read the file. Aborting.\r\n");
+ goto re_abort;
+ }
+ buf[n] = '\0';
+ if (n)
+ chprintf(BSS, "%s", buf);
+ } while (n);
+ chprintf(BSS, "\r\nClosing.\r\n");
+ red_close(fd);
+ chprintf(BSS, "\r\nDeleting the file.\r\n");
+ red_unlink(filename);
+re_abort:
+ red_uninit();
+ }
+
while (true) {
tcpexample(port);
chThdSleepMilliseconds(250);
diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/mcuconf.h b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/mcuconf.h index 4af515d48..9cfe0ba97 100644 --- a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/mcuconf.h +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/mcuconf.h @@ -106,6 +106,11 @@ #define SAMA_TC1_IRQ_PRIORITY 2
/*
+ * TRNG driver system settings
+ */
+#define HAL_USE_TRNG FALSE
+
+/*
* UART driver system settings.
*/
#define SAMA_UART_USE_UART0 FALSE
@@ -140,4 +145,10 @@ #define SAMA_UART_FLEXCOM4_DMA_IRQ_PRIORITY 4
#define SAMA_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+/*
+ * L2CC related defines.
+ */
+#define SAMA_L2CC_ASSUME_ENABLED 0
+#define SAMA_L2CC_ENABLE 0
+
#endif /* MCUCONF_H */
diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/redconf.h b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/redconf.h new file mode 100644 index 000000000..e2b80d2d2 --- /dev/null +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/redconf.h @@ -0,0 +1,114 @@ +/* THIS FILE WAS GENERATED BY THE DATALIGHT RELIANCE EDGE CONFIGURATION + UTILITY. DO NOT MODIFY. + + Generated by configuration utility version 2.02 +*/ +/** @file +*/ +#ifndef REDCONF_H +#define REDCONF_H + + +#include <string.h> + +#define REDCONF_READ_ONLY 0 + +#define REDCONF_API_POSIX 1 + +#define REDCONF_API_FSE 0 + +#define REDCONF_API_POSIX_FORMAT 1 + +#define REDCONF_API_POSIX_LINK 1 + +#define REDCONF_API_POSIX_UNLINK 1 + +#define REDCONF_API_POSIX_MKDIR 1 + +#define REDCONF_API_POSIX_RMDIR 1 + +#define REDCONF_API_POSIX_RENAME 1 + +#define REDCONF_RENAME_ATOMIC 1 + +#define REDCONF_API_POSIX_FTRUNCATE 1 + +#define REDCONF_API_POSIX_READDIR 1 + +#define REDCONF_API_POSIX_CWD 0 + +#define REDCONF_NAME_MAX 12U + +#define REDCONF_PATH_SEPARATOR '/' + +#define REDCONF_TASK_COUNT 10U + +#define REDCONF_HANDLE_COUNT 10U + +#define REDCONF_API_FSE_FORMAT 0 + +#define REDCONF_API_FSE_TRUNCATE 0 + +#define REDCONF_API_FSE_TRANSMASKGET 0 + +#define REDCONF_API_FSE_TRANSMASKSET 0 + +#define REDCONF_OUTPUT 0 + +#define REDCONF_ASSERTS 1 + +#define REDCONF_BLOCK_SIZE 512U + +#define REDCONF_VOLUME_COUNT 1U + +#define REDCONF_ENDIAN_BIG 0 + +#define REDCONF_ALIGNMENT_SIZE 4U + +#define REDCONF_CRC_ALGORITHM CRC_SLICEBY8 + +#define REDCONF_INODE_BLOCKS 1 + +#define REDCONF_INODE_TIMESTAMPS 1 + +#define REDCONF_ATIME 0 + +#define REDCONF_DIRECT_POINTERS 4U + +#define REDCONF_INDIRECT_POINTERS 32U + +#define REDCONF_BUFFER_COUNT 12U + +#define RedMemCpyUnchecked memcpy + +#define RedMemMoveUnchecked memmove + +#define RedMemSetUnchecked memset + +#define RedMemCmpUnchecked memcmp + +#define RedStrLenUnchecked strlen + +#define RedStrCmpUnchecked strcmp + +#define RedStrNCmpUnchecked strncmp + +#define RedStrNCpyUnchecked strncpy + +#define REDCONF_TRANSACT_DEFAULT (( RED_TRANSACT_CREAT | RED_TRANSACT_MKDIR | RED_TRANSACT_RENAME | RED_TRANSACT_LINK | RED_TRANSACT_UNLINK | RED_TRANSACT_FSYNC | RED_TRANSACT_CLOSE | RED_TRANSACT_VOLFULL | RED_TRANSACT_UMOUNT ) & RED_TRANSACT_MASK) + +#define REDCONF_IMAP_INLINE 0 + +#define REDCONF_IMAP_EXTERNAL 1 + +#define REDCONF_DISCARDS 0 + +#define REDCONF_IMAGE_BUILDER 0 + +#define REDCONF_CHECKER 0 + +#define RED_CONFIG_UTILITY_VERSION 0x2000200U + +#define RED_CONFIG_MINCOMPAT_VER 0x1000200U + +#endif diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/reliance.mk b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/reliance.mk new file mode 100644 index 000000000..4bbb0a1a6 --- /dev/null +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/reliance.mk @@ -0,0 +1,38 @@ +# List of the required Reliance Edge files.
+RELEDGESRC= \
+ $(CHIBIOS)/ext/reliance-edge/core/driver/blockio.c \
+ $(CHIBIOS)/ext/reliance-edge/core/driver/buffer.c \
+ $(CHIBIOS)/ext/reliance-edge/core/driver/core.c \
+ $(CHIBIOS)/ext/reliance-edge/core/driver/dir.c \
+ $(CHIBIOS)/ext/reliance-edge/core/driver/format.c \
+ $(CHIBIOS)/ext/reliance-edge/core/driver/imap.c \
+ $(CHIBIOS)/ext/reliance-edge/core/driver/imapextern.c \
+ $(CHIBIOS)/ext/reliance-edge/core/driver/imapinline.c \
+ $(CHIBIOS)/ext/reliance-edge/core/driver/inode.c \
+ $(CHIBIOS)/ext/reliance-edge/core/driver/inodedata.c \
+ $(CHIBIOS)/ext/reliance-edge/core/driver/volume.c \
+ $(CHIBIOS)/ext/reliance-edge/fse/fse.c \
+ $(CHIBIOS)/ext/reliance-edge/posix/path.c \
+ $(CHIBIOS)/ext/reliance-edge/posix/posix.c \
+ $(CHIBIOS)/ext/reliance-edge/util/bitmap.c \
+ $(CHIBIOS)/ext/reliance-edge/util/crc.c \
+ $(CHIBIOS)/ext/reliance-edge/util/memory.c \
+ $(CHIBIOS)/ext/reliance-edge/util/namelen.c \
+ $(CHIBIOS)/ext/reliance-edge/util/sign.c \
+ $(CHIBIOS)/ext/reliance-edge/util/string.c
+
+RELEDGEINC = $(CHIBIOS)/ext/reliance-edge/include \
+ $(CHIBIOS)/ext/reliance-edge/core/include
+
+RELEDGEBINDINC = $(CHIBIOS)/ext/reliance-edge/os/chibios/include
+
+RELEDGEBINDSRC = \
+ $(CHIBIOS)/ext/reliance-edge/os/chibios/services/osassert.c \
+ $(CHIBIOS)/ext/reliance-edge/os/chibios/services/osclock.c \
+ $(CHIBIOS)/ext/reliance-edge/os/chibios/services/osmutex.c \
+ $(CHIBIOS)/ext/reliance-edge/os/chibios/services/osoutput.c \
+ $(CHIBIOS)/ext/reliance-edge/os/chibios/services/ostask.c
+
+# Shared variables
+ALLCSRC += $(RELEDGESRC) $(RELEDGEBINDSRC)
+ALLINC += $(RELEDGEINC) $(RELEDGEBINDINC)
diff --git a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/tservices.c b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/tservices.c index 4b822246e..c4d54ff9e 100644 --- a/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/tservices.c +++ b/demos/ATSAMA5D2/RT-SAMA5D2-XPLAINED-SEC/tservices.c @@ -25,7 +25,9 @@ #include "ch.h"
#include "hal.h"
#include "tservices.h"
+#include "proxies/tscommon.h"
#include "proxies/tssockstub.h"
+#include "proxies/tsioblksstub.h"
#include "chprintf.h"
/*===========================================================================*/
@@ -49,17 +51,17 @@ /*===========================================================================*/
static THD_WORKING_AREA(waTsSimpleService, 1024);
-static THD_FUNCTION(TsSimpleService, tsstate) {
+static THD_FUNCTION(TsSimpleService, tsstatep) {
BaseSequentialStream *ssp = (BaseSequentialStream*)&SD1;
- ts_state_t *svcp = tsstate;
+ ts_state_t *svcp = tsstatep;
/* Start the 'wait request / process / response' cycle.*/
for (;/* ever */;) {
int i;
/* Wait a service request.*/
- msg_t r = tssiWaitRequest(tsstate);
+ msg_t r = tssiWaitRequest(svcp);
/* Check if status is ko. It could not happen.*/
if (r != SMC_SVC_OK) {
@@ -97,7 +99,8 @@ static THD_FUNCTION(TsSimpleService, tsstate) { TS_STATE_TABLE
TS_CONF_TABLE_BEGIN
TS_CONF_TABLE_ENTRY("TsSimpleService", waTsSimpleService, TS_BASE_PRIO, TsSimpleService, TS_STATE(0))
- TS_CONF_TABLE_ENTRY("TsStubsService", waTsStubsService, TS_BASE_PRIO+1, TsStubsService, TS_STATE(1))
+ TS_CONF_TABLE_ENTRY(SOCKS_SVC_NAME, waTsSocksStubsService, TS_BASE_PRIO+1, TsSocksStubsService, TS_STATE(1))
+ TS_CONF_TABLE_ENTRY(IOBLKS_SVC_NAME, waTsIOBlksStubsService, TS_BASE_PRIO+1, TsIOBlksStubsService, TS_STATE(2))
TS_CONF_TABLE_END
/** @} */
|