diff options
author | Olivier Deprez <olivier.deprez@arm.com> | 2019-12-23 14:42:49 +0000 |
---|---|---|
committer | TrustedFirmware Code Review <review@review.trustedfirmware.org> | 2019-12-23 14:42:49 +0000 |
commit | 584b3cb3aba5423c31496a4f46ea6a58e44dd7d9 (patch) | |
tree | 713cdf78866ab6ccce8e00d177ce047290425978 | |
parent | e00ab6c5018a3be8b9837b126784c850a38a906f (diff) | |
parent | 81042e36ea7603a1c31e8f8984757029bad5db1e (diff) | |
download | tf-a-tests-584b3cb3aba5423c31496a4f46ea6a58e44dd7d9.tar.gz |
Merge "debugfs: add debug filesystem tests"
-rw-r--r-- | tftf/tests/runtime_services/sip_service/debugfs.h | 59 | ||||
-rw-r--r-- | tftf/tests/runtime_services/sip_service/test_debugfs.c | 356 | ||||
-rw-r--r-- | tftf/tests/tests-debugfs.mk | 10 | ||||
-rw-r--r-- | tftf/tests/tests-debugfs.xml | 17 | ||||
-rw-r--r-- | tftf/tests/tests-standard.mk | 1 | ||||
-rw-r--r-- | tftf/tests/tests-standard.xml | 2 |
6 files changed, 445 insertions, 0 deletions
diff --git a/tftf/tests/runtime_services/sip_service/debugfs.h b/tftf/tests/runtime_services/sip_service/debugfs.h new file mode 100644 index 000000000..cf09e0b08 --- /dev/null +++ b/tftf/tests/runtime_services/sip_service/debugfs.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEBUGFS_H +#define DEBUGFS_H + +#define NAMELEN 13 /* Maximum length of a file name */ +#define PATHLEN 41 /* Maximum length of a path */ +#define STATLEN 41 /* Size of static part of dir format */ +#define ROOTLEN (2 + 4) /* Size needed to encode root string */ +#define FILNAMLEN (2 + NAMELEN) /* Size needed to encode filename */ +#define DIRLEN (STATLEN + FILNAMLEN + 3*ROOTLEN) /* Size of dir entry */ + +#define KSEEK_SET 0 +#define KSEEK_CUR 1 +#define KSEEK_END 2 + +#define NELEM(tab) (sizeof(tab) / sizeof((tab)[0])) + +typedef unsigned short qid_t; + +/******************************************************************************* + * This structure contains the necessary information to represent a 9p + * directory. + ******************************************************************************/ +typedef struct { + char name[NAMELEN]; + long length; + unsigned char mode; + unsigned char type; + unsigned char dev; + qid_t qid; +} dir_t; + +enum devflags { + O_READ = 1 << 0, + O_WRITE = 1 << 1, + O_RDWR = 1 << 2, + O_BIND = 1 << 3, + O_DIR = 1 << 4, + O_STAT = 1 << 5 +}; + +#define MOUNT 0 +#define CREATE 1 +#define OPEN 2 +#define CLOSE 3 +#define READ 4 +#define WRITE 5 +#define SEEK 6 +#define BIND 7 +#define STAT 8 +#define INIT 10 +#define VERSION 11 + +#endif /* DEBUGFS_H */ diff --git a/tftf/tests/runtime_services/sip_service/test_debugfs.c b/tftf/tests/runtime_services/sip_service/test_debugfs.c new file mode 100644 index 000000000..6c626e9b2 --- /dev/null +++ b/tftf/tests/runtime_services/sip_service/test_debugfs.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> +#include <tftf_lib.h> +#include <xlat_tables_v2.h> + +#include "debugfs.h" + +#define SMC_OK (0) + +#define DEBUGFS_VERSION (0x00000001) +#define DEBUGFS_SMC_64 (0xC2000030) +#define MAX_PATH_LEN (256) + +/* DebugFS shared buffer area */ +#ifndef PLAT_ARM_DEBUGFS_BASE +#define PLAT_ARM_DEBUGFS_BASE (0x81000000) +#define PLAT_ARM_DEBUGFS_SIZE (0x1000) +#endif /* PLAT_ARM_DEBUGFS_BASE */ + +union debugfs_parms { + struct { + char fname[MAX_PATH_LEN]; + } open; + + struct mount { + char srv[MAX_PATH_LEN]; + char where[MAX_PATH_LEN]; + char spec[MAX_PATH_LEN]; + } mount; + + struct { + char path[MAX_PATH_LEN]; + dir_t dir; + } stat; + + struct { + char oldpath[MAX_PATH_LEN]; + char newpath[MAX_PATH_LEN]; + } bind; +}; + +typedef struct { + char *name; + qid_t qid; +} dir_expected_t; + +static const dir_expected_t root_dir_expected[] = { + { "dev", 0x8001 }, + { "blobs", 0x8003 }, + { "fip", 0x8002 } +}; + +static unsigned int read_buffer[4096 / sizeof(unsigned int)]; + +static void *const payload = (void *) PLAT_ARM_DEBUGFS_BASE; + +static int init(unsigned long long phys_addr) +{ + smc_ret_values ret; + smc_args args; + + args.fid = DEBUGFS_SMC_64; + args.arg1 = INIT; + args.arg2 = phys_addr; + ret = tftf_smc(&args); + + return (ret.ret0 == SMC_OK) ? 0 : -1; +} + +static int version(void) +{ + smc_ret_values ret; + smc_args args; + + args.fid = DEBUGFS_SMC_64; + args.arg1 = VERSION; + ret = tftf_smc(&args); + + return (ret.ret0 == SMC_OK) ? ret.ret1 : -1; +} + +static int open(const char *name, int flags) +{ + union debugfs_parms *parms = payload; + smc_ret_values ret; + smc_args args; + + strlcpy(parms->open.fname, name, MAX_PATH_LEN); + + args.fid = DEBUGFS_SMC_64; + args.arg1 = OPEN; + args.arg2 = (u_register_t) flags; + ret = tftf_smc(&args); + + return (ret.ret0 == SMC_OK) ? ret.ret1 : -1; +} + +static int read(int fd, void *buf, size_t size) +{ + smc_ret_values ret; + smc_args args; + + args.fid = DEBUGFS_SMC_64; + args.arg1 = READ; + args.arg2 = (u_register_t) fd; + args.arg3 = (u_register_t) size; + + ret = tftf_smc(&args); + + if (ret.ret0 == SMC_OK) { + memcpy(buf, payload, size); + return ret.ret1; + } + + return -1; +} + +static int close(int fd) +{ + smc_ret_values ret; + smc_args args; + + args.fid = DEBUGFS_SMC_64; + args.arg1 = CLOSE; + args.arg2 = (u_register_t) fd; + + ret = tftf_smc(&args); + + return (ret.ret0 == SMC_OK) ? 0 : -1; +} + +static int mount(char *srv, char *where, char *spec) +{ + union debugfs_parms *parms = payload; + smc_ret_values ret; + smc_args args; + + strlcpy(parms->mount.srv, srv, MAX_PATH_LEN); + strlcpy(parms->mount.where, where, MAX_PATH_LEN); + strlcpy(parms->mount.spec, spec, MAX_PATH_LEN); + + args.fid = DEBUGFS_SMC_64; + args.arg1 = MOUNT; + + ret = tftf_smc(&args); + + return (ret.ret0 == SMC_OK) ? 0 : -1; +} + +static int stat(const char *name, dir_t *dir) +{ + union debugfs_parms *parms = payload; + smc_ret_values ret; + smc_args args; + + strlcpy(parms->stat.path, name, MAX_PATH_LEN); + + args.fid = DEBUGFS_SMC_64; + args.arg1 = STAT; + + ret = tftf_smc(&args); + + if (ret.ret0 == SMC_OK) { + memcpy(dir, &parms->stat.dir, sizeof(dir_t)); + return 0; + } + + return -1; +} + +static int seek(int fd, long offset, int whence) +{ + smc_ret_values ret; + smc_args args; + + args.fid = DEBUGFS_SMC_64; + args.arg1 = SEEK; + args.arg2 = (u_register_t) fd; + args.arg3 = (u_register_t) offset; + args.arg4 = (u_register_t) whence; + + ret = tftf_smc(&args); + + return (ret.ret0 == SMC_OK) ? 0 : -1; +} + +static bool compare_dir(const dir_expected_t *dir_expected, + unsigned int iteration, dir_t *dir) +{ + return ((memcmp(dir->name, dir_expected[iteration].name, + strlen(dir_expected[iteration].name)) == 0) && + (dir->qid == dir_expected[iteration].qid)); +} + +static void dir_print(dir_t *dir) +{ + tftf_testcase_printf("name: %s, length: %ld, mode: %d, type: %d, " + "dev: %d, qid: 0x%x\n", + dir->name, + dir->length, + dir->mode, + dir->type, + dir->dev, + dir->qid); +} + +/* + * @Test_Aim@ Issue SMCs to TF-A calling debugfs functions in order to test + * the exposure of the filesystem. + * The result is displayed on the console, something that should look like: + * > ls / + * dev + * fip + * blobs + */ +test_result_t test_debugfs(void) +{ + int fd, ret, iteration; + dir_t dir; + + /* Get debugfs interface version (if implemented)*/ + ret = version(); + if (ret != DEBUGFS_VERSION) { + /* Likely debugfs feature is not implemented */ + return TEST_RESULT_SKIPPED; + } + + /* Initialize debugfs feature, this maps the NS shared buffer in SWd */ + ret = init(PLAT_ARM_DEBUGFS_BASE); + if (ret != 0) { + return TEST_RESULT_FAIL; + } + + /* Calling init a second time should fail */ + ret = init(PLAT_ARM_DEBUGFS_BASE); + if (ret == 0) { + tftf_testcase_printf("init succeeded ret=%d\n", ret); + return TEST_RESULT_FAIL; + } + + /* open non-existing directory */ + fd = open("/dummy", O_READ); + if (fd >= 0) { + tftf_testcase_printf("open succeeded fd=%d\n", fd); + return TEST_RESULT_FAIL; + } + + /* stat non-existent file from root */ + ret = stat("/unknown", &dir); + if (ret == 0) { + tftf_testcase_printf("stat succeeded ret=%d\n", ret); + return TEST_RESULT_FAIL; + } + + /***************** Root directory listing **************/ + /* open root directory */ + fd = open("/", O_READ); + if (fd < 0) { + tftf_testcase_printf("open failed fd=%d\n", fd); + return TEST_RESULT_FAIL; + } + + /* read directory entries */ + iteration = 0; + ret = read(fd, &dir, sizeof(dir)); + while (ret > 0) { + if (compare_dir(root_dir_expected, iteration++, + &dir) == false) { + dir_print(&dir); + return TEST_RESULT_FAIL; + } + + ret = read(fd, &dir, sizeof(dir)); + } + + /* close root directory handle */ + ret = close(fd); + if (ret < 0) { + tftf_testcase_printf("close failed ret=%d\n", ret); + return TEST_RESULT_FAIL; + } + + /***************** FIP operations **************/ + /* mount fip */ + ret = mount("#F", "/fip", "/blobs/fip.bin"); + if (ret < 0) { + tftf_testcase_printf("mount failed ret=%d\n", ret); + return TEST_RESULT_FAIL; + } + + /* stat a non-existent file from fip */ + ret = stat("/fip/unknown", &dir); + if (ret == 0) { + tftf_testcase_printf("stat succeeded ret=%d\n", ret); + return TEST_RESULT_FAIL; + } + + /* detect bl2 image presence */ + ret = stat("/fip/bl2.bin", &dir); + if (ret != 0) { + tftf_testcase_printf("stat failed ret=%d\n", ret); + return TEST_RESULT_FAIL; + } + + /* open bl2 */ + fd = open("/fip/bl2.bin", O_READ); + if (fd < 0) { + tftf_testcase_printf("open failed fd=%d\n", fd); + return TEST_RESULT_FAIL; + } + + /* read first 128 bytes */ + ret = read(fd, read_buffer, 128); + if (ret != 128) { + tftf_testcase_printf("read failed(%d) ret=%d\n", __LINE__, ret); + return TEST_RESULT_FAIL; + } + + /* Compare first word of bl2 binary */ + if (read_buffer[0] != 0xaa0003f4) { + tftf_testcase_printf("read ret %d, buf[0]: 0x%x\n", + ret, read_buffer[0]); + return TEST_RESULT_FAIL; + } + + /* rewind to file start */ + ret = seek(fd, 0, KSEEK_SET); + if (ret != 0) { + tftf_testcase_printf("seek failed ret=%d\n", ret); + return TEST_RESULT_FAIL; + } + + size_t read_size = 0; + do { + ret = read(fd, read_buffer, sizeof(read_buffer)); + if (ret < 0) { + tftf_testcase_printf("read failed(%d) ret=%d\n", + __LINE__, ret); + return TEST_RESULT_FAIL; + } + read_size += ret; + } while (ret); + + if (read_size != dir.length) { + tftf_testcase_printf("read size mismatch read_size=%zu " + "dir.length=%ld\n", read_size, dir.length); + return TEST_RESULT_FAIL; + } + + return TEST_RESULT_SUCCESS; +} diff --git a/tftf/tests/tests-debugfs.mk b/tftf/tests/tests-debugfs.mk new file mode 100644 index 000000000..77fafd7be --- /dev/null +++ b/tftf/tests/tests-debugfs.mk @@ -0,0 +1,10 @@ +# +# Copyright (c) 2019, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +TESTS_SOURCES += \ + $(addprefix tftf/tests/runtime_services/sip_service/, \ + test_debugfs.c \ + ) diff --git a/tftf/tests/tests-debugfs.xml b/tftf/tests/tests-debugfs.xml new file mode 100644 index 000000000..4da315241 --- /dev/null +++ b/tftf/tests/tests-debugfs.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + Copyright (c) 2019, Arm Limited. All rights reserved. + + SPDX-License-Identifier: BSD-3-Clause +--> + +<testsuites> + <!-- + Test suite exercising execution state switch SiP service. + --> + <testsuite name="DebugFS" description="Test ARM SiP DebugFS service"> + <testcase name="Expose filesystem" function="test_debugfs" /> + </testsuite> + +</testsuites> diff --git a/tftf/tests/tests-standard.mk b/tftf/tests/tests-standard.mk index 9ef75bb94..97d530fdf 100644 --- a/tftf/tests/tests-standard.mk +++ b/tftf/tests/tests-standard.mk @@ -21,6 +21,7 @@ TESTS_MAKEFILE := $(addprefix tftf/tests/, \ tests-tftf-validation.mk \ tests-tsp.mk \ tests-uncontainable.mk \ + tests-debugfs.mk \ ) include ${TESTS_MAKEFILE} diff --git a/tftf/tests/tests-standard.xml b/tftf/tests/tests-standard.xml index fa5762173..a865981db 100644 --- a/tftf/tests/tests-standard.xml +++ b/tftf/tests/tests-standard.xml @@ -21,6 +21,7 @@ <!ENTITY tests-performance SYSTEM "tests-performance.xml"> <!ENTITY tests-smc SYSTEM "tests-smc.xml"> <!ENTITY tests-pmu-leakage SYSTEM "tests-pmu-leakage.xml"> + <!ENTITY tests-debugfs SYSTEM "tests-debugfs.xml"> ]> <testsuites> @@ -37,5 +38,6 @@ &tests-performance; &tests-smc; &tests-pmu-leakage; + &tests-debugfs; </testsuites> |