Пример embedded_vfs

Пример показывает, как встроить виртуальную файловую систему (далее VFS), поставляемую в составе KasperskyOS Community Edition, в разрабатываемую сущность.

В этом примере сущность Client полностью инкапсулирует реализацию VFS из KasperskyOS Community Edition. Это позволяет избавиться от использования IPC для всех стандартных функций ввода-вывода (stdio.h, socket.h и так далее), например, для отладки или повышения производительности.

Сущность Client тестирует следующие операции:

Поставляемые ресурсы

В пример входит образ жесткого диска с файловой системой FAT32 – hdd.img.

Этот пример не содержит реализации драйверов блочных устройств, с которыми работает Client. Эти драйверы (сущности ATA и SDCard) поставляются в составе KasperskyOS Community Edition и добавляются в файле сборки ./CMakeLists.txt.

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

Client.edl

entity client.Client

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

main.c

#include <errno.h>

#include <fcntl.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/mount.h>

#define TEST_MESSAGE "test_message"

#define TEST_MESSAGE_LEN 12

int main(void)

{

char buffer[TEST_MESSAGE_LEN + 1];

int ret;

int fd;

memset(buffer, 0, TEST_MESSAGE_LEN);

if (mkdir("/c", S_IRWXU | S_IRWXG | S_IRWXO)) {

printf("Failed to create \"/c\" dir (error %d: \"%s\")\n",

errno,

strerror(errno));

return EXIT_FAILURE;

}

#ifdef __arm__

if (mount("mmc0,0", "/c", "fat32", 0, "")) {

printf("Failed to mount sdcard,0,0, /c, fat32 (error %d: \"%s\")\n",

errno,

strerror(errno));

return EXIT_FAILURE;

}

#else

if (mount("Ahci0Port0,0", "/c", "fat32", 0, "")) {

printf("Failed to mount Ahci0Port0,0, /c, fat32 (error %d: \"%s\")\n",

errno,

strerror(errno));

return EXIT_FAILURE;

}

#endif

fd = open("/c/new_file", O_RDWR | O_CREAT);

if (fd == -1) {

printf("Failed to create new file /c/new_file (error %d: \"%s\")\n",

errno,

strerror(errno));

return -1;

}

ret = write(fd, TEST_MESSAGE, TEST_MESSAGE_LEN);

if (ret != TEST_MESSAGE_LEN) {

printf("Failed to write message to /c/new_file. write() returned %d\n",

ret);

return -1;

}

if (close(fd)) {

printf("Failed to close /c/new_file (error %d: \"%s\")\n",

errno,

strerror(errno));

return -1;

}

fd = open("/c/new_file", O_RDONLY);

if (fd == -1) {

printf("Failed to open existing file /c/new_file (error %d: \"%s\")\n",

errno,

strerror(errno));

return -1;

}

ret = read(fd, buffer, TEST_MESSAGE_LEN);

if (ret != TEST_MESSAGE_LEN) {

printf("Failed to read message from /c/new_file. read() returned %d\n",

ret);

return -1;

}

buffer[TEST_MESSAGE_LEN] = '\0';

printf("Read message: %s\n", buffer);

if (close(fd)) {

printf("Failed to finally close /c/new_file (error %d: \"%s\")\n",

errno,

strerror(errno));

return -1;

}

if (unlink("/c/new_file")) {

printf("Failed to finally unlink /c/new_file (error %d: \"%s\")\n",

errno,

strerror(errno));

return -1;

}

if (umount("/c")) {

printf("Failed to umount /c. error %d: \"%s\"\n",

errno,

strerror(errno));

return EXIT_FAILURE;

}

printf("All devices successfully unmounted\n");

return EXIT_SUCCESS;

}

Init-описание

Сущность Client работает с блочным устройством напрямую.

init.yaml.in

entities:

- name: client.Client

@INIT_Client_ENTITY_CONNECTIONS@

@INIT_EXTERNAL_ENTITIES@

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

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

security.psl

use common._

use EDL kl.drivers.PCIE

use EDL kl.drivers.ATA

security_arm.psl

use common._

use EDL kl.drivers.SDCard

use EDL kl.drivers.BSP

common.psl

/* Конфигурация безопасности для примера "embedded_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

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

execute {

grant ()

}

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

request {

grant ()

}

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

response {

grant ()

}

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

security {

grant ()

}

Конфигурация сборки

В этом примере используется система автоматизации сборки 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/main.c")

add_dependencies (Client client_edl_files)

# vfs_LOCAL_LIB - необходимо для поддержки встроенной файловой системы.

# vfs_IMPLEMENTATION_LIB - реализация файловой системы.

target_link_libraries (Client ${vfs_LOCAL_LIB} ${vfs_IMPLEMENTATION_LIB} ${VFAT_LIB})

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

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

./einit/CMakeLists.txt

project (einit)

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

include (platform/image)

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

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

if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm|aarch64")

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

find_package (sdcard REQUIRED)

include_directories (${sdcard_INCLUDE})

# We need SDCARD driver to be connected with our implementation of VFS

set_target_properties (Client PROPERTIES ${blkdev_ENTITY}_REPLACEMENT ${sdcard_ENTITY})

# Добавляем цель с копированием образа диска в директорию сборки примера.

add_custom_target (hdd.img

COMMAND ${CMAKE_COMMAND} -E make_directory

${CMAKE_BINARY_DIR}/hdd

COMMAND ${CMAKE_COMMAND} -E copy_directory

${KL_SDK_ROOT_PATH}/common/hdd ${CMAKE_BINARY_DIR}/hdd

COMMAND ${KL_SDK_ROOT_PATH}/common/prepare_hdd_img.sh -d ${CMAKE_BINARY_DIR}/hdd -img hdd.img -f fat32 -s 128)

# Для архитектуры Arm поддерживается работа только с одной SD-картой.

set (QEMU_FLAGS "-nographic -monitor none -sd hdd.img")

else ()

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

find_package (ata REQUIRED)

include_directories (${ata_INCLUDE})

# We need ATA driver to be connected with our implementation of VFS

set_target_properties (Client PROPERTIES ${blkdev_ENTITY}_REPLACEMENT ${ata_ENTITY})

# Добавляем цели с копированием образов дисков в директорию сборки примера.

add_custom_target (hdd.img

COMMAND ${CMAKE_COMMAND} -E make_directory

${CMAKE_BINARY_DIR}/hdd

COMMAND ${CMAKE_COMMAND} -E copy_directory

${KL_SDK_ROOT_PATH}/common/hdd ${CMAKE_BINARY_DIR}/hdd

COMMAND ${KL_SDK_ROOT_PATH}/common/prepare_hdd_img.sh -d ${CMAKE_BINARY_DIR}/hdd -img hdd.img -f fat32 -s 128)

set (QEMU_FLAGS "-nographic -monitor none \

-device ahci,id=ahci \

-drive id=disk,file=hdd.img,if=none \

-device ide-drive,drive=disk,bus=ahci.0")

endif ()

if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm")

set (SECURITY_PSL_FILE "src/security.arm.psl")

else ()

set (SECURITY_PSL_FILE "src/security.psl")

endif ()

set (QEMU_DEPENDENCIES hdd.img)

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

build_kos_hw_image (kos-image

EINIT_ENTITY EinitHw

CONNECTIONS_CFG "src/init.yaml.in"

SECURITY_PSL ${SECURITY_PSL_FILE}

IMAGE_FILES Client)

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

build_kos_qemu_image (kos-qemu-image

EINIT_ENTITY EinitQemu

CONNECTIONS_CFG "src/init.yaml.in"

SECURITY_PSL ${SECURITY_PSL_FILE}

QEMU_FLAGS "${QEMU_FLAGS}"

QEMU_DEPENDENCIES "${QEMU_DEPENDENCIES}"

IMAGE_FILES Client)

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

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

./CMakeLists.txt

cmake_minimum_required (VERSION 3.12)

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

include (platform)

initialize_platform ()

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

include (platform/install)

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

include (platform/doxygen)

add_project_documentation_main_target ()

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

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

find_package (vfs REQUIRED)

include_directories (${vfs_INCLUDE})

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

# VFAT

find_package (VFAT REQUIRED)

include_directories (${VFAT_INCLUDE})

add_subdirectory (client)

add_subdirectory (einit)

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

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

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

В начало