123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- /*
- * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <stdint.h>
- #include <stdbool.h>
- #include <string.h>
- #include <lib/debugfs.h>
- #include <lib/smccc.h>
- #include <lib/spinlock.h>
- #include <lib/xlat_tables/xlat_tables_v2.h>
- #include <smccc_helpers.h>
- #define MAX_PATH_LEN 256
- #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
- /* This is the virtual address to which we map the NS shared buffer */
- #define DEBUGFS_SHARED_BUF_VIRT ((void *)0x81000000U)
- static union debugfs_parms {
- struct {
- char fname[MAX_PATH_LEN];
- } open;
- struct {
- 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;
- } parms;
- /* debugfs_access_lock protects shared buffer and internal */
- /* FS functions from concurrent accesses. */
- static spinlock_t debugfs_access_lock;
- static bool debugfs_initialized;
- uintptr_t debugfs_smc_handler(unsigned int smc_fid,
- u_register_t cmd,
- u_register_t arg2,
- u_register_t arg3,
- u_register_t arg4,
- void *cookie,
- void *handle,
- u_register_t flags)
- {
- int64_t smc_ret = DEBUGFS_E_INVALID_PARAMS, smc_resp = 0;
- int ret;
- /* Allow calls from non-secure only */
- if (is_caller_secure(flags)) {
- SMC_RET1(handle, DEBUGFS_E_DENIED);
- }
- /* Expect a SiP service fast call */
- if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
- (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
- SMC_RET1(handle, SMC_UNK);
- }
- /* Truncate parameters if 32b SMC convention call */
- if (GET_SMC_CC(smc_fid) == SMC_32) {
- arg2 &= 0xffffffff;
- arg3 &= 0xffffffff;
- arg4 &= 0xffffffff;
- }
- spin_lock(&debugfs_access_lock);
- if (debugfs_initialized == true) {
- /* Copy NS shared buffer to internal secure location */
- memcpy(&parms, (void *)DEBUGFS_SHARED_BUF_VIRT,
- sizeof(union debugfs_parms));
- }
- switch (cmd) {
- case INIT:
- if (debugfs_initialized == false) {
- /* TODO: check PA validity e.g. whether */
- /* it is an NS region. */
- ret = mmap_add_dynamic_region(arg2,
- (uintptr_t)DEBUGFS_SHARED_BUF_VIRT,
- PAGE_SIZE_4KB,
- MT_MEMORY | MT_RW | MT_NS);
- if (ret == 0) {
- debugfs_initialized = true;
- smc_ret = SMC_OK;
- smc_resp = 0;
- }
- }
- break;
- case VERSION:
- smc_ret = SMC_OK;
- smc_resp = DEBUGFS_VERSION;
- break;
- case MOUNT:
- ret = mount(parms.mount.srv,
- parms.mount.where,
- parms.mount.spec);
- if (ret == 0) {
- smc_ret = SMC_OK;
- smc_resp = 0;
- }
- break;
- case OPEN:
- ret = open(parms.open.fname, arg2);
- if (ret >= 0) {
- smc_ret = SMC_OK;
- smc_resp = ret;
- }
- break;
- case CLOSE:
- ret = close(arg2);
- if (ret == 0) {
- smc_ret = SMC_OK;
- smc_resp = 0;
- }
- break;
- case READ:
- ret = read(arg2, DEBUGFS_SHARED_BUF_VIRT, arg3);
- if (ret >= 0) {
- smc_ret = SMC_OK;
- smc_resp = ret;
- }
- break;
- case SEEK:
- ret = seek(arg2, arg3, arg4);
- if (ret == 0) {
- smc_ret = SMC_OK;
- smc_resp = 0;
- }
- break;
- case BIND:
- ret = bind(parms.bind.oldpath, parms.bind.newpath);
- if (ret == 0) {
- smc_ret = SMC_OK;
- smc_resp = 0;
- }
- break;
- case STAT:
- ret = stat(parms.stat.path, &parms.stat.dir);
- if (ret == 0) {
- memcpy((void *)DEBUGFS_SHARED_BUF_VIRT, &parms,
- sizeof(union debugfs_parms));
- smc_ret = SMC_OK;
- smc_resp = 0;
- }
- break;
- /* Not implemented */
- case CREATE:
- /* Intentional fall-through */
- /* Not implemented */
- case WRITE:
- /* Intentional fall-through */
- default:
- smc_ret = SMC_UNK;
- smc_resp = 0;
- }
- spin_unlock(&debugfs_access_lock);
- SMC_RET2(handle, smc_ret, smc_resp);
- /* Not reached */
- return smc_ret;
- }
- int debugfs_smc_setup(void)
- {
- debugfs_initialized = false;
- debugfs_access_lock.lock = 0;
- return 0;
- }
|