mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 17:44:19 +00:00
debugfs: add SMC channel
Provide an SMC interface to the 9p filesystem. This permits accessing firmware drivers through a common interface, using standardized read/write/control operations. Signed-off-by: Ambroise Vincent <ambroise.vincent@arm.com> Signed-off-by: Olivier Deprez <olivier.deprez@arm.com> Change-Id: I9314662314bb060f6bc02714476574da158b2a7d
This commit is contained in:
parent
d310239d77
commit
992f091b5d
12 changed files with 759 additions and 5 deletions
|
@ -17,6 +17,7 @@ The Arm SiP implementation offers the following services:
|
|||
|
||||
- Performance Measurement Framework (PMF)
|
||||
- Execution State Switching service
|
||||
- DebugFS interface
|
||||
|
||||
Source definitions for Arm SiP service are located in the ``arm_sip_svc.h`` header
|
||||
file.
|
||||
|
@ -87,6 +88,346 @@ Instead, execution starts at the supplied entry point, with the CPU registers 0
|
|||
and 1 populated with the supplied *Cookie hi* and *Cookie lo* values,
|
||||
respectively.
|
||||
|
||||
DebugFS interface
|
||||
-----------------
|
||||
|
||||
The optional DebugFS interface is accessed through an SMC SiP service. Refer
|
||||
to the component documentation for details.
|
||||
|
||||
String parameters are passed through a shared buffer using a specific union:
|
||||
|
||||
.. code:: c
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
Format of the dir_t structure as such:
|
||||
|
||||
.. code:: c
|
||||
|
||||
typedef struct {
|
||||
char name[NAMELEN];
|
||||
long length;
|
||||
unsigned char mode;
|
||||
unsigned char index;
|
||||
unsigned char dev;
|
||||
qid_t qid;
|
||||
} dir_t;
|
||||
|
||||
|
||||
* Identifiers
|
||||
|
||||
======================== =============================================
|
||||
SMC_OK 0
|
||||
SMC_UNK -1
|
||||
DEBUGFS_E_INVALID_PARAMS -2
|
||||
======================== =============================================
|
||||
|
||||
======================== =============================================
|
||||
MOUNT 0
|
||||
CREATE 1
|
||||
OPEN 2
|
||||
CLOSE 3
|
||||
READ 4
|
||||
WRITE 5
|
||||
SEEK 6
|
||||
BIND 7
|
||||
STAT 8
|
||||
INIT 10
|
||||
VERSION 11
|
||||
======================== =============================================
|
||||
|
||||
MOUNT
|
||||
~~~~~
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
This operation mounts a blob of data pointed to by path stored in `src`, at
|
||||
filesystem location pointed to by path stored in `where`, using driver pointed
|
||||
to by path in `spec`.
|
||||
|
||||
Parameters
|
||||
^^^^^^^^^^
|
||||
======== ============================================================
|
||||
uint32_t FunctionID (0x82000030 / 0xC2000030)
|
||||
uint32_t ``MOUNT``
|
||||
======== ============================================================
|
||||
|
||||
Return values
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
=============== ==========================================================
|
||||
int32_t w0 == SMC_OK on success
|
||||
|
||||
w0 == DEBUGFS_E_INVALID_PARAMS if mount operation failed
|
||||
=============== ==========================================================
|
||||
|
||||
OPEN
|
||||
~~~~
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
This operation opens the file path pointed to by `fname`.
|
||||
|
||||
Parameters
|
||||
^^^^^^^^^^
|
||||
|
||||
======== ============================================================
|
||||
uint32_t FunctionID (0x82000030 / 0xC2000030)
|
||||
uint32_t ``OPEN``
|
||||
uint32_t mode
|
||||
======== ============================================================
|
||||
|
||||
mode can be one of:
|
||||
|
||||
.. code:: c
|
||||
|
||||
enum mode {
|
||||
O_READ = 1 << 0,
|
||||
O_WRITE = 1 << 1,
|
||||
O_RDWR = 1 << 2,
|
||||
O_BIND = 1 << 3,
|
||||
O_DIR = 1 << 4,
|
||||
O_STAT = 1 << 5
|
||||
};
|
||||
|
||||
Return values
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
=============== ==========================================================
|
||||
int32_t w0 == SMC_OK on success
|
||||
|
||||
w0 == DEBUGFS_E_INVALID_PARAMS if open operation failed
|
||||
|
||||
uint32_t w1: file descriptor id on success.
|
||||
=============== ==========================================================
|
||||
|
||||
CLOSE
|
||||
~~~~~
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
|
||||
This operation closes a file described by a file descriptor obtained by a
|
||||
previous call to OPEN.
|
||||
|
||||
Parameters
|
||||
^^^^^^^^^^
|
||||
|
||||
======== ============================================================
|
||||
uint32_t FunctionID (0x82000030 / 0xC2000030)
|
||||
uint32_t ``CLOSE``
|
||||
uint32_t File descriptor id returned by OPEN
|
||||
======== ============================================================
|
||||
|
||||
Return values
|
||||
^^^^^^^^^^^^^
|
||||
=============== ==========================================================
|
||||
int32_t w0 == SMC_OK on success
|
||||
|
||||
w0 == DEBUGFS_E_INVALID_PARAMS if close operation failed
|
||||
=============== ==========================================================
|
||||
|
||||
READ
|
||||
~~~~
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
|
||||
This operation reads a number of bytes from a file descriptor obtained by
|
||||
a previous call to OPEN.
|
||||
|
||||
Parameters
|
||||
^^^^^^^^^^
|
||||
|
||||
======== ============================================================
|
||||
uint32_t FunctionID (0x82000030 / 0xC2000030)
|
||||
uint32_t ``READ``
|
||||
uint32_t File descriptor id returned by OPEN
|
||||
uint32_t Number of bytes to read
|
||||
======== ============================================================
|
||||
|
||||
Return values
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
On success, the read data is retrieved from the shared buffer after the
|
||||
operation.
|
||||
|
||||
=============== ==========================================================
|
||||
int32_t w0 == SMC_OK on success
|
||||
|
||||
w0 == DEBUGFS_E_INVALID_PARAMS if read operation failed
|
||||
|
||||
uint32_t w1: number of bytes read on success.
|
||||
=============== ==========================================================
|
||||
|
||||
SEEK
|
||||
~~~~
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
|
||||
Move file pointer for file described by given `file descriptor` of given
|
||||
`offset` related to `whence`.
|
||||
|
||||
Parameters
|
||||
^^^^^^^^^^
|
||||
|
||||
======== ============================================================
|
||||
uint32_t FunctionID (0x82000030 / 0xC2000030)
|
||||
uint32_t ``SEEK``
|
||||
uint32_t File descriptor id returned by OPEN
|
||||
sint32_t offset in the file relative to whence
|
||||
uint32_t whence
|
||||
======== ============================================================
|
||||
|
||||
whence can be one of:
|
||||
|
||||
========= ============================================================
|
||||
KSEEK_SET 0
|
||||
KSEEK_CUR 1
|
||||
KSEEK_END 2
|
||||
========= ============================================================
|
||||
|
||||
Return values
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
=============== ==========================================================
|
||||
int32_t w0 == SMC_OK on success
|
||||
|
||||
w0 == DEBUGFS_E_INVALID_PARAMS if seek operation failed
|
||||
=============== ==========================================================
|
||||
|
||||
BIND
|
||||
~~~~
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
|
||||
Create a link from `oldpath` to `newpath`.
|
||||
|
||||
Parameters
|
||||
^^^^^^^^^^
|
||||
|
||||
======== ============================================================
|
||||
uint32_t FunctionID (0x82000030 / 0xC2000030)
|
||||
uint32_t ``BIND``
|
||||
======== ============================================================
|
||||
|
||||
Return values
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
=============== ==========================================================
|
||||
int32_t w0 == SMC_OK on success
|
||||
|
||||
w0 == DEBUGFS_E_INVALID_PARAMS if bind operation failed
|
||||
=============== ==========================================================
|
||||
|
||||
STAT
|
||||
~~~~
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
|
||||
Perform a stat operation on provided file `name` and returns the directory
|
||||
entry statistics into `dir`.
|
||||
|
||||
Parameters
|
||||
^^^^^^^^^^
|
||||
|
||||
======== ============================================================
|
||||
uint32_t FunctionID (0x82000030 / 0xC2000030)
|
||||
uint32_t ``STAT``
|
||||
======== ============================================================
|
||||
|
||||
Return values
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
=============== ==========================================================
|
||||
int32_t w0 == SMC_OK on success
|
||||
|
||||
w0 == DEBUGFS_E_INVALID_PARAMS if stat operation failed
|
||||
=============== ==========================================================
|
||||
|
||||
INIT
|
||||
~~~~
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
Initial call to setup the shared exchange buffer. Notice if successful once,
|
||||
subsequent calls fail after a first initialization. The caller maps the same
|
||||
page frame in its virtual space and uses this buffer to exchange string
|
||||
parameters with filesystem primitives.
|
||||
|
||||
Parameters
|
||||
^^^^^^^^^^
|
||||
|
||||
======== ============================================================
|
||||
uint32_t FunctionID (0x82000030 / 0xC2000030)
|
||||
uint32_t ``INIT``
|
||||
uint64_t Physical address of the shared buffer.
|
||||
======== ============================================================
|
||||
|
||||
Return values
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
=============== ======================================================
|
||||
int32_t w0 == SMC_OK on success
|
||||
|
||||
w0 == DEBUGFS_E_INVALID_PARAMS if already initialized,
|
||||
or internal error occurred.
|
||||
=============== ======================================================
|
||||
|
||||
VERSION
|
||||
~~~~~~~
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
Returns the debugfs interface version if implemented in TF-A.
|
||||
|
||||
Parameters
|
||||
^^^^^^^^^^
|
||||
|
||||
======== ============================================================
|
||||
uint32_t FunctionID (0x82000030 / 0xC2000030)
|
||||
uint32_t ``VERSION``
|
||||
======== ============================================================
|
||||
|
||||
Return values
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
=============== ======================================================
|
||||
int32_t w0 == SMC_OK on success
|
||||
|
||||
w0 == SMC_UNK if interface is not implemented
|
||||
|
||||
uint32_t w1: On success, debugfs interface version, 32 bits
|
||||
value with major version number in upper 16 bits and
|
||||
minor version in lower 16 bits.
|
||||
=============== ======================================================
|
||||
|
||||
* CREATE(1) and WRITE (5) command identifiers are unimplemented and
|
||||
return `SMC_UNK`.
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.*
|
||||
|
|
132
docs/components/debugfs-design.rst
Normal file
132
docs/components/debugfs-design.rst
Normal file
|
@ -0,0 +1,132 @@
|
|||
========
|
||||
Debug FS
|
||||
========
|
||||
|
||||
.. contents::
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The *DebugFS* feature is primarily aimed at exposing firmware debug data to
|
||||
higher SW layers such as a non-secure component. Such component can be the
|
||||
TFTF test payload or a Linux kernel module.
|
||||
|
||||
Virtual filesystem
|
||||
------------------
|
||||
|
||||
The core functionality lies in a virtual file system based on a 9p file server
|
||||
interface (`Notes on the Plan 9 Kernel Source`_). The implementation permits
|
||||
exposing virtual files, firmware drivers, and file blobs.
|
||||
|
||||
Namespace
|
||||
~~~~~~~~~
|
||||
|
||||
Two namespaces are exposed:
|
||||
|
||||
- # is used as root for drivers (e.g. #t0 is the first uart)
|
||||
- / is used as root for virtual "files" (e.g. /fip, or /dev/uart)
|
||||
|
||||
9p interface
|
||||
~~~~~~~~~~~~
|
||||
|
||||
The associated primitives are:
|
||||
|
||||
- Unix-like:
|
||||
|
||||
- open(): create a file descriptor that acts as a handle to the file passed as
|
||||
an argument.
|
||||
- close(): close the file descriptor created by open().
|
||||
- read(): read from a file to a buffer.
|
||||
- write(): write from a buffer to a file.
|
||||
- seek(): set the file position indicator of a file descriptor either to a
|
||||
relative or an absolute offset.
|
||||
- stat(): get information about a file (type, mode, size, ...).
|
||||
|
||||
.. code:: c
|
||||
|
||||
int open(const char *name, int flags);
|
||||
int close(int fd);
|
||||
int read(int fd, void *buf, int n);
|
||||
int write(int fd, void *buf, int n);
|
||||
int seek(int fd, long off, int whence);
|
||||
int stat(char *path, dir_t *dir);
|
||||
|
||||
- Specific primitives :
|
||||
|
||||
- mount(): create a link between a driver and spec.
|
||||
- create(): create a file in a specific location.
|
||||
- bind(): expose the content of a directory to another directory.
|
||||
|
||||
.. code:: c
|
||||
|
||||
int mount(char *srv, char *mnt, char *spec);
|
||||
int create(const char *name, int flags);
|
||||
int bind(char *path, char *where);
|
||||
|
||||
This interface is embedded into the BL31 run-time payload when selected by build
|
||||
options. The interface multiplexes drivers or emulated "files":
|
||||
|
||||
- Debug data can be partitioned into different virtual files e.g. expose PMF
|
||||
measurements through a file, and internal firmware state counters through
|
||||
another file.
|
||||
- This permits direct access to a firmware driver, mainly for test purposes
|
||||
(e.g. a hardware device that may not be accessible to non-privileged/
|
||||
non-secure layers, or for which no support exists in the NS side).
|
||||
|
||||
SMC interface
|
||||
-------------
|
||||
|
||||
The communication with the 9p layer in BL31 is made through an SMC conduit
|
||||
(`SMC Calling Convention PDD`_), using a specific SiP Function Id. An NS shared
|
||||
buffer is used to pass path string parameters, or e.g. to exchange data on a
|
||||
read operation. Refer to `ARM SiP Services`_ for a description of the SMC
|
||||
interface.
|
||||
|
||||
Security considerations
|
||||
-----------------------
|
||||
|
||||
- Due to the nature of the exposed data, the feature is considered experimental
|
||||
and importantly **shall only be used in debug builds**.
|
||||
- Several primitive imply string manipulations and usage of string formats.
|
||||
- Special care is taken with the shared buffer to avoid TOCTOU attacks.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
- In order to setup the shared buffer, the component consuming the interface
|
||||
needs to allocate a physical page frame and transmit its address.
|
||||
- In order to map the shared buffer, BL31 requires enabling the dynamic xlat
|
||||
table option.
|
||||
- Data exchange is limited by the shared buffer length. A large read operation
|
||||
might be split into multiple read operations of smaller chunks.
|
||||
- On concurrent access, a spinlock is implemented in the BL31 service to protect
|
||||
the internal work buffer, and re-entrancy into the filesystem layers.
|
||||
- Notice, a physical device driver if exposed by the firmware may conflict with
|
||||
the higher level OS if the latter implements its own driver for the same
|
||||
physical device.
|
||||
|
||||
Applications
|
||||
------------
|
||||
|
||||
The SMC interface is accessible from an NS environment, that is:
|
||||
|
||||
- a test payload, bootloader or hypervisor running at NS-EL2
|
||||
- a Linux kernel driver running at NS-EL1
|
||||
- a Linux userspace application through the kernel driver
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
.. [#] `SMC Calling Convention PDD`_
|
||||
.. [#] `Notes on the Plan 9 Kernel Source`_
|
||||
.. [#] `Linux 9p remote filesystem protocol`_
|
||||
.. [#] `ARM SiP Services`_
|
||||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.*
|
||||
|
||||
.. _SMC Calling Convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/
|
||||
.. _Notes on the Plan 9 Kernel Source: http://lsub.org/who/nemo/9.pdf
|
||||
.. _Linux 9p remote filesystem protocol: https://www.kernel.org/doc/Documentation/filesystems/9p.txt
|
||||
.. _ARM SiP Services: arm-sip-service.rst
|
|
@ -544,6 +544,10 @@ Common build options
|
|||
(Coherent memory region is included) or 0 (Coherent memory region is
|
||||
excluded). Default is 1.
|
||||
|
||||
- ``USE_DEBUGFS``: When set to 1 this option activates an EXPERIMENTAL feature
|
||||
exposing a virtual filesystem interface through BL31 as a SiP SMC function.
|
||||
Default is 0.
|
||||
|
||||
- ``USE_ROMLIB``: This flag determines whether library at ROM will be used.
|
||||
This feature creates a library of functions to be placed in ROM and thus
|
||||
reduces SRAM usage. Refer to :ref:`Library at ROM` for further details. Default
|
||||
|
|
|
@ -56,5 +56,28 @@ int stat(const char *path, dir_t *dir);
|
|||
|
||||
/* DebugFS initialization */
|
||||
void debugfs_init(void);
|
||||
int debugfs_smc_setup(void);
|
||||
|
||||
/* Debugfs version returned through SMC interface */
|
||||
#define DEBUGFS_VERSION (0x000000001U)
|
||||
|
||||
/* Function ID for accessing the debugfs interface */
|
||||
#define DEBUGFS_FID_VALUE (0x30U)
|
||||
|
||||
#define is_debugfs_fid(_fid) \
|
||||
(((_fid) & FUNCID_NUM_MASK) == DEBUGFS_FID_VALUE)
|
||||
|
||||
/* Error code for debugfs SMC interface failures */
|
||||
#define DEBUGFS_E_INVALID_PARAMS (-2)
|
||||
#define DEBUGFS_E_DENIED (-3)
|
||||
|
||||
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,
|
||||
uintptr_t flags);
|
||||
|
||||
#endif /* DEBUGFS_H */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -16,9 +16,15 @@
|
|||
/* U(0x8200ff02) is reserved */
|
||||
#define ARM_SIP_SVC_VERSION U(0x8200ff03)
|
||||
|
||||
/* PMF_SMC_GET_TIMESTAMP_32 0x82000010 */
|
||||
/* PMF_SMC_GET_TIMESTAMP_64 0xC2000010 */
|
||||
|
||||
/* Function ID for requesting state switch of lower EL */
|
||||
#define ARM_SIP_SVC_EXE_STATE_SWITCH U(0x82000020)
|
||||
|
||||
/* DEBUGFS_SMC_32 0x82000030U */
|
||||
/* DEBUGFS_SMC_64 0xC2000030U */
|
||||
|
||||
/* ARM SiP Service Calls version numbers */
|
||||
#define ARM_SIP_SVC_VERSION_MAJOR U(0x0)
|
||||
#define ARM_SIP_SVC_VERSION_MINOR U(0x2)
|
||||
|
|
|
@ -9,3 +9,5 @@ DEBUGFS_SRCS := $(addprefix lib/debugfs/, \
|
|||
devc.c \
|
||||
devroot.c \
|
||||
devfip.c)
|
||||
|
||||
DEBUGFS_SRCS += lib/debugfs/debugfs_smc.c
|
||||
|
|
209
lib/debugfs/debugfs_smc.c
Normal file
209
lib/debugfs/debugfs_smc.c
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* 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 acccesses. */
|
||||
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;
|
||||
}
|
|
@ -122,6 +122,10 @@ const mmap_region_t plat_arm_mmap[] = {
|
|||
#ifdef IMAGE_BL31
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
#if USE_DEBUGFS
|
||||
/* Required by devfip, can be removed if devfip is not used */
|
||||
V2M_MAP_FLASH0_RW,
|
||||
#endif /* USE_DEBUGFS */
|
||||
ARM_MAP_EL3_TZC_DRAM,
|
||||
V2M_MAP_IOFPGA,
|
||||
MAP_DEVICE0,
|
||||
|
|
|
@ -68,7 +68,11 @@
|
|||
# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10
|
||||
# else
|
||||
# define PLAT_ARM_MMAP_ENTRIES 8
|
||||
# define MAX_XLAT_TABLES 5
|
||||
# if USE_DEBUGFS
|
||||
# define MAX_XLAT_TABLES 6
|
||||
# else
|
||||
# define MAX_XLAT_TABLES 5
|
||||
# endif
|
||||
# endif
|
||||
#elif defined(IMAGE_BL32)
|
||||
# define PLAT_ARM_MMAP_ENTRIES 8
|
||||
|
|
|
@ -291,6 +291,10 @@ else # if AArch64
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq (${USE_DEBUGFS},1)
|
||||
BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1
|
||||
endif
|
||||
|
||||
# Add support for platform supplied linker script for BL31 build
|
||||
$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -11,6 +11,7 @@
|
|||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/console.h>
|
||||
#include <lib/debugfs.h>
|
||||
#include <lib/extensions/ras.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils.h>
|
||||
|
@ -231,6 +232,10 @@ void arm_bl31_platform_setup(void)
|
|||
#if RAS_EXTENSION
|
||||
ras_init();
|
||||
#endif
|
||||
|
||||
#if USE_DEBUGFS
|
||||
debugfs_init();
|
||||
#endif /* USE_DEBUGFS */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <common/debug.h>
|
||||
#include <common/runtime_svc.h>
|
||||
#include <lib/debugfs.h>
|
||||
#include <lib/pmf/pmf.h>
|
||||
#include <plat/arm/common/arm_sip_svc.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
@ -20,8 +21,18 @@ DEFINE_SVC_UUID2(arm_sip_svc_uid,
|
|||
|
||||
static int arm_sip_setup(void)
|
||||
{
|
||||
if (pmf_setup() != 0)
|
||||
if (pmf_setup() != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if USE_DEBUGFS
|
||||
|
||||
if (debugfs_smc_setup() != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* USE_DEBUGFS */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -48,6 +59,15 @@ static uintptr_t arm_sip_handler(unsigned int smc_fid,
|
|||
handle, flags);
|
||||
}
|
||||
|
||||
#if USE_DEBUGFS
|
||||
|
||||
if (is_debugfs_fid(smc_fid)) {
|
||||
return debugfs_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
|
||||
handle, flags);
|
||||
}
|
||||
|
||||
#endif /* USE_DEBUGFS */
|
||||
|
||||
switch (smc_fid) {
|
||||
case ARM_SIP_SVC_EXE_STATE_SWITCH: {
|
||||
u_register_t pc;
|
||||
|
|
Loading…
Add table
Reference in a new issue