Пример custom_vfs

Пример собственной реализации виртуальной файловой системы (далее VFS).

Для вывода в stdout используется пример реализации VFS – сущность CustomVfs.

EDL-описания сущностей

Client.edl

entity client.Client

CustomVfs.edl

entity custom_vfs.CustomVfs

components {

vfs: kl.Vfs

}

Init-описание

Для использования потока stdout сущность Client должна иметь доступ к сущности VFS (CustomVfs).

Этот пример содержит два файла init-описаний:

init_qemu.yaml.in

entities:

- name: client.Client

path: client

connections:

- target: custom_vfs.CustomVfs

id: {var: _VFS_CONNECTION_ID, include: vfs/defs.h}

@INIT_client_ENTITY_CONNECTIONS+@

- name: custom_vfs.CustomVfs

path: custom_vfs_hw

@INIT_custom_vfs_hw_ENTITY_CONNECTIONS@

@INIT_EXTERNAL_ENTITIES@

init_hw.yaml.in

entities:

- name: client.Client

path: client

connections:

- target: custom_vfs.CustomVfs

id: {var: _VFS_CONNECTION_ID, include: vfs/defs.h}

@INIT_client_ENTITY_CONNECTIONS+@

- name: custom_vfs.CustomVfs

path: custom_vfs_qemu

@INIT_custom_vfs_qemu_ENTITY_CONNECTIONS@

@INIT_EXTERNAL_ENTITIES@

Конфигурация безопасности

Конфигурация безопасности в этом примере разрешает запуск всех сущностей и позволяет любой сущности обращаться к сущностям Core и CustomVfs.

security.psl

/* Конфигурация безопасности для примера "custom_vfs". */

/* Определение execute-интерфейса. */

execute: kl.core.Execute

/* Импорт файла с объявлением псевдонимов базовых политик безопасности. */

use nk.base._

/* Объявление сущностей. */

use EDL kl.VfsEntity

use EDL Einit

use EDL kl.core.Core

use EDL client.Client

use EDL custom_vfs.CustomVfs

/* Запуск сущностей разрешен. */

execute {

grant ()

}

/* Сообщения типа request разрешены. */

request {

grant ()

}

/* Сообщения типа response разрешены. */

response {

grant ()

}

/* Вызовы к security interface игнорируются. */

security {

grant ()

}

Реализация сущности Client

Сущность Client выводит в stdout фразу "Hello, world!".

client.c

#include <stdio.h>

#include <stdlib.h>

int main(int argc, const char *argv[])

{

printf("Hello, World!\n");

return EXIT_SUCCESS;

}

Реализация сущности CustomVfs

Сущность CustomVfs предоставляет собственную реализацию метода write из интерфейса IFilesystem.

custom_vfs.c

#include <assert.h>

#include <stdlib.h>

#include <errno.h>

#define _VFS_SERVER_INTERFACE

#include <vfs/basic.h>

#include <uart/uart.h>

/* Первый порт UART. */

static UartHandle uartH = 0;

/* Подготовить vfs к выводу в UART. */

static int uart_init(UartHandle *uartH)

{

/* Инициализировать драйвер UART. */

int rc = UartInit();

if (rc != UART_OK)

return -1;

/* Открыть порт. */

rc = UartOpenPort(PORT_NAME, uartH);

if (rc != UART_OK)

return -1;

return 0;

}

/* Обязательные действия для подготовки виртуальной файловой системы. */

/* Реализация инициализирующей функции. */

bool _vfs_implementation_init(Handle self_id, int *error)

{

(void)self_id;

(void)error;

/* Возвращает FALSE, если инициализация UART прошла неуспешно. */

if (uart_init(&uartH) == -1)

return false;

/* Возвращает TRUE. */

return true;

}

/* Реализация завершающей функции. */

void _vfs_implementation_free(void)

{

/* Не выполняет никаких действий. */

}

/* Реализация метода "write" из интерфейса IFilesystem. */

ssize_t _vfs_write(Handle client_id, Handle fd, const void *buf, size_t count, int *error)

{

/* Работаем только потоками stdout и stderr, т.к. в примере отсутствует файловая система. */

if (fd == 1 || fd == 2)

{

static const char msg[] = "Custom vfs uses UART to print this message...\n";

int i;

/* Вывести сообщение в порт UART. */

for (i = 0; i < sizeof(msg) - 1; ++i)

UartWriteByte(uartH, (uint8_t)msg[i]);

/* Вывести переданную строку в порт UART. */

for (i = 0; i < count; ++i)

UartWriteByte(uartH, (uint8_t)(*((const char *)buf + i)));

/* Ошибки нет. */

*error = 0;

/* Возвращаем размер буфера, который был записан. */

return count;

}

/* Для иных файловых дескрипторов возвращаем ошибку. */

*error = EROFS;

return -1;

}

/* Выполнять диспетчеризацию в основном потоке. */

#define WE_DONT_NEED_THE_MAIN_THREAD 1

#if WE_DONT_NEED_THE_MAIN_THREAD

static _vfs_server_thread_routine_t thread_routine;

static void *thread_routine_arg;

/* Определение этой функции необходимо для выполнения диспетчеризации методов интерфейса IFilesystem

в основном потоке. */

void _vfs_server_set_main_thread_routine(_vfs_server_thread_routine_t func, void *arg)

{

thread_routine = func;

thread_routine_arg = arg;

}

int main(void)

{

assert(thread_routine != NULL);

/* Запуск диспетчеризации. */

(*thread_routine)(thread_routine_arg);

return EXIT_SUCCESS;

}

#else

/* Диспетчеризация выполняется в отдельном потоке, т.к. функция _vfs_server_set_main_thread_routine

не определена. */

int main(void)

{

while (1) continue;

return EXIT_SUCCESS;

}

#endif

Инструкции сборки решения

В этом примере используется система автоматизации сборки CMake.

Для обработки EDL-описаний сущности Client используется функция nk_build_edl_files, которую предоставляет NK.

Инструкции сборки сущности Client

./client/CMakeLists.txt

project (client)

# Инструментарий для работы с парсером NK.

include (platform/nk)

# Установка флагов компиляции.

project_header_default ("STANDARD_GNU_11:YES" "STRICT_WARNINGS:NO")

nk_build_edl_files (client_edl_files NK_MODULE "client" EDL "${CMAKE_SOURCE_DIR}/resources/edl/Client.edl")

add_executable (client "src/client.c")

target_link_libraries (client ${vfs_CLIENT_LIB})

#set_target_properties (client PROPERTIES LINK_FLAGS "-Ttext 0x00800000")

# We do not need default VFS entity here, which comes from ${vfs_CLIENT_LIB}

set_target_properties (client PROPERTIES ${vfs_ENTITY}_REPLACEMENT "")

add_dependencies (client client_edl_files)

Инструкции сборки сущности CustomVfs

./custom_vfs/CMakeLists.txt

project (custom_vfs)

# Инструментарий для работы с парсером NK.

include (platform/nk)

# Установка флагов компиляции.

project_header_default ("STANDARD_GNU_11:YES" "STRICT_WARNINGS:NO")

nk_build_edl_files (custom_vfs_edl_files NK_MODULE "custom_vfs" EDL "${CMAKE_SOURCE_DIR}/resources/edl/CustomVfs.edl")

if (uart_HW_LIB)

add_executable (custom_vfs_hw "src/custom_vfs.c")

target_compile_definitions (custom_vfs_hw PRIVATE "-DPORT_NAME=\"${PORT_HW}\"")

target_link_libraries (custom_vfs_hw ${vfs_SERVER_LIB} ${uart_HW_LIB})

add_dependencies (custom_vfs_hw custom_vfs_edl_files)

endif ()

add_executable (custom_vfs_qemu "src/custom_vfs.c")

target_compile_definitions (custom_vfs_qemu PRIVATE "-DPORT_NAME=\"uart0\"")

target_link_libraries (custom_vfs_qemu ${vfs_SERVER_LIB} ${uart_QEMU_LIB})

#set_target_properties (custom_vfs_qemu PROPERTIES LINK_FLAGS "-Ttext 0x00800000")

add_dependencies (custom_vfs_qemu custom_vfs_edl_files)

Инструкции сборки сущности einit и образа системы

./einit/CMakeLists.txt

project (einit)

# Инструментарий для работы с парсером NK.

include (platform/image)

# Установка флагов компиляции.

project_header_default ("STANDARD_GNU_11:YES" "STRICT_WARNINGS:NO")

# Блочные устройства в этом примере не требуются.

set_target_properties (${vfs_DEFAULT_ENTITY} PROPERTIES

${blkdev_ENTITY}_REPLACEMENT ""

${pcie_ENTITY}_REPLACEMENT "")

# Определение переменной ENTITIES_QEMU со списком сущностей.

set (ENTITIES_QEMU client custom_vfs_qemu)

# Определение переменной ENTITIES_HW со списком сущностей.

if (TARGET custom_vfs_hw)

set (ENTITIES_HW client custom_vfs_hw)

set (CONNECTIONS_CFG_HW "src/init_hw.yaml.in")

else ()

set (ENTITIES_HW ${ENTITIES_QEMU})

set (CONNECTIONS_CFG_HW "src/init_qemu.yaml.in")

endif ()

set (SECURITY_PSL "src/security.psl")

set (QEMU_FLAGS "-nographic -monitor none")

# Образ KasperskyOS для аппаратной платформы.

build_kos_hw_image (kos-image

EINIT_ENTITY EinitHw

CONNECTIONS_CFG "${CONNECTIONS_CFG_HW}"

SECURITY_PSL "${SECURITY_PSL}"

IMAGE_FILES ${ENTITIES_HW})

# Образ KasperskyOS для QEMU с целями эмуляции (sim, gdbsim, gdb).

build_kos_qemu_image (kos-qemu-image

EINIT_ENTITY EinitQemu

CONNECTIONS_CFG "src/init_qemu.yaml.in"

SECURITY_PSL "${SECURITY_PSL}"

QEMU_FLAGS "${QEMU_FLAGS}"

IMAGE_FILES ${ENTITIES_QEMU})

#set_target_properties (EinitQemu PROPERTIES LINK_FLAGS "-Ttext 0x00200000")

Инструкции сборки решения

./CMakeLists.txt

cmake_minimum_required (VERSION 3.12)

# Инициализация библиотеки CMake

include (platform)

initialize_platform ()

# Добавление документации в формате Doxygen

include (platform/doxygen)

add_project_documentation_main_target ()

# Подключение функций установки артефактов.

include (platform/install)

# Эта команда найдет все компоненты пакета uart.

find_package (uart REQUIRED)

include_directories (${uart_INCLUDE})

# Подключение пакета, импортирующего компоненты для работы с

# виртуальной файловой системой.

find_package (vfs REQUIRED)

include_directories (${vfs_INCLUDE})

add_subdirectory (client)

add_subdirectory (custom_vfs)

add_subdirectory (einit)

Сборка с помощью CMake

Для сборки и запуска примера необходимо выполнить следующий скрипт:

/opt/KasperskyOS-Community-Edition-<version>/examples/custom_vfs/cross-build.sh

В начало