[iot] Import ql-tipc lib for Trusty OS
authorHaoran.Wang <elven.wang@nxp.com>
Mon, 28 Aug 2017 07:21:44 +0000 (15:21 +0800)
committerJason Liu <jason.hui.liu@nxp.com>
Thu, 2 Nov 2017 18:37:25 +0000 (02:37 +0800)
The lib provided ql-tipc communication channel with
Trusty OS.
Also the AVB, Keymaster and SecureStorage service
tipc client implement in this lib.

Change-Id: I0ab1ec9ee1b6f272b960c2e944008283c2c9249a
Signed-off-by: Haoran.Wang <elven.wang@nxp.com>
27 files changed:
include/interface/avb/avb.h [new file with mode: 0644]
include/interface/keymaster/keymaster.h [new file with mode: 0644]
include/interface/storage/storage.h [new file with mode: 0644]
include/trusty/avb.h [new file with mode: 0644]
include/trusty/keymaster.h [new file with mode: 0644]
include/trusty/libtipc.h [new file with mode: 0644]
include/trusty/rpmb.h [new file with mode: 0644]
include/trusty/sysdeps.h [new file with mode: 0644]
include/trusty/trusty_dev.h [new file with mode: 0644]
include/trusty/trusty_ipc.h [new file with mode: 0644]
include/trusty/util.h [new file with mode: 0644]
lib/Makefile
lib/trusty/ql-tipc/LICENSE [new file with mode: 0644]
lib/trusty/ql-tipc/README.md [new file with mode: 0644]
lib/trusty/ql-tipc/arch/arm/sm_err.h [new file with mode: 0644]
lib/trusty/ql-tipc/arch/arm/smcall.h [new file with mode: 0644]
lib/trusty/ql-tipc/arch/arm/trusty_dev.c [new file with mode: 0644]
lib/trusty/ql-tipc/arch/arm/trusty_mem.c [new file with mode: 0644]
lib/trusty/ql-tipc/avb.c [new file with mode: 0644]
lib/trusty/ql-tipc/ipc.c [new file with mode: 0644]
lib/trusty/ql-tipc/ipc_dev.c [new file with mode: 0644]
lib/trusty/ql-tipc/keymaster.c [new file with mode: 0644]
lib/trusty/ql-tipc/libtipc.c [new file with mode: 0644]
lib/trusty/ql-tipc/rpmb_proxy.c [new file with mode: 0644]
lib/trusty/ql-tipc/sysdeps/Makefile [new file with mode: 0644]
lib/trusty/ql-tipc/sysdeps/storage_ops_uboot.c [new file with mode: 0644]
lib/trusty/ql-tipc/sysdeps/sysdeps_uboot.c [new file with mode: 0644]

diff --git a/include/interface/avb/avb.h b/include/interface/avb/avb.h
new file mode 100644 (file)
index 0000000..5ce338e
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef TRUSTY_INTERFACE_AVB_H_
+#define TRUSTY_INTERFACE_AVB_H_
+
+#include <trusty/sysdeps.h>
+
+#define AVB_PORT "com.android.trusty.avb"
+#define AVB_MAX_BUFFER_LENGTH 2048
+
+enum avb_command {
+    AVB_REQ_SHIFT = 1,
+    AVB_RESP_BIT  = 1,
+
+    READ_ROLLBACK_INDEX        = (0 << AVB_REQ_SHIFT),
+    WRITE_ROLLBACK_INDEX       = (1 << AVB_REQ_SHIFT),
+    AVB_GET_VERSION            = (2 << AVB_REQ_SHIFT),
+    READ_PERMANENT_ATTRIBUTES  = (3 << AVB_REQ_SHIFT),
+    WRITE_PERMANENT_ATTRIBUTES = (4 << AVB_REQ_SHIFT),
+    READ_LOCK_STATE            = (5 << AVB_REQ_SHIFT),
+    WRITE_LOCK_STATE           = (6 << AVB_REQ_SHIFT),
+    LOCK_BOOT_STATE            = (7 << AVB_REQ_SHIFT),
+};
+
+/**
+ * enum avb_error - error codes for AVB protocol
+ * @AVB_ERROR_NONE:         All OK
+ * @AVB_ERROR_INVALID:      Invalid input
+ * @AVB_ERROR_INTERNAL:     Error occurred during an operation in Trusty
+ */
+enum avb_error {
+    AVB_ERROR_NONE     = 0,
+    AVB_ERROR_INVALID  = 1,
+    AVB_ERROR_INTERNAL = 2,
+};
+
+/**
+ * avb_message - Serial header for communicating with AVB server
+ * @cmd:     the command. Payload must be a serialized buffer of the
+ *           corresponding request object.
+ * @result:  resulting error code for message, one of avb_error.
+ * @payload: start of the serialized command specific payload
+ */
+struct avb_message {
+    uint32_t cmd;
+    uint32_t result;
+    uint8_t payload[0];
+};
+
+/**
+ * avb_rollback_req - request format for [READ|WRITE]_ROLLBACK_INDEX
+ * @value: value to write to rollback index. Ignored for read.
+ * @slot:  slot number of rollback index to write
+ */
+struct avb_rollback_req {
+    uint64_t value;
+    uint32_t slot;
+} TRUSTY_ATTR_PACKED;
+
+/**
+ * avb_rollback_resp - response format for [READ|WRITE]_ROLLBACK_INDEX.
+ * @value: value of the requested rollback index.
+ */
+struct avb_rollback_resp {
+    uint64_t value;
+};
+
+/**
+ * avb_get_version_resp - response format for AVB_GET_VERSION.
+ * @version: version of AVB message format
+ */
+struct avb_get_version_resp {
+    uint32_t version;
+};
+
+#endif /* TRUSTY_INTERFACE_AVB_H_ */
diff --git a/include/interface/keymaster/keymaster.h b/include/interface/keymaster/keymaster.h
new file mode 100644 (file)
index 0000000..d8f7eb7
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef TRUSTY_INTERFACE_KEYMASTER_H_
+#define TRUSTY_INTERFACE_KEYMASTER_H_
+
+#include <trusty/sysdeps.h>
+
+#define KEYMASTER_PORT "com.android.trusty.keymaster"
+#define KEYMASTER_MAX_BUFFER_LENGTH 4096
+
+enum keymaster_command {
+    KEYMASTER_RESP_BIT              = 1,
+    KEYMASTER_STOP_BIT              = 2,
+    KEYMASTER_REQ_SHIFT             = 2,
+
+    KM_GENERATE_KEY                 = (0 << KEYMASTER_REQ_SHIFT),
+    KM_BEGIN_OPERATION              = (1 << KEYMASTER_REQ_SHIFT),
+    KM_UPDATE_OPERATION             = (2 << KEYMASTER_REQ_SHIFT),
+    KM_FINISH_OPERATION             = (3 << KEYMASTER_REQ_SHIFT),
+    KM_ABORT_OPERATION              = (4 << KEYMASTER_REQ_SHIFT),
+    KM_IMPORT_KEY                   = (5 << KEYMASTER_REQ_SHIFT),
+
+    KM_EXPORT_KEY                   = (6 << KEYMASTER_REQ_SHIFT),
+    KM_GET_VERSION                  = (7 << KEYMASTER_REQ_SHIFT),
+    KM_ADD_RNG_ENTROPY              = (8 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_ALGORITHMS     = (9 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_BLOCK_MODES    = (10 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_PADDING_MODES  = (11 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_DIGESTS        = (12 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_IMPORT_FORMATS = (13 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_EXPORT_FORMATS = (14 << KEYMASTER_REQ_SHIFT),
+    KM_GET_KEY_CHARACTERISTICS      = (15 << KEYMASTER_REQ_SHIFT),
+
+    KM_SET_BOOT_PARAMS                 = (0x1000 << KEYMASTER_REQ_SHIFT),
+    KM_SET_ATTESTATION_KEY             = (0x2000 << KEYMASTER_REQ_SHIFT),
+    KM_APPEND_ATTESTATION_CERT_CHAIN   = (0x3000 << KEYMASTER_REQ_SHIFT),
+};
+
+typedef enum {
+    KM_VERIFIED_BOOT_VERIFIED = 0,    /* Full chain of trust extending from the bootloader to
+                                       * verified partitions, including the bootloader, boot
+                                       * partition, and all verified partitions*/
+    KM_VERIFIED_BOOT_SELF_SIGNED = 1, /* The boot partition has been verified using the embedded
+                                       * certificate, and the signature is valid. The bootloader
+                                       * displays a warning and the fingerprint of the public
+                                       * key before allowing the boot process to continue.*/
+    KM_VERIFIED_BOOT_UNVERIFIED = 2,  /* The device may be freely modified. Device integrity is left
+                                       * to the user to verify out-of-band. The bootloader
+                                       * displays a warning to the user before allowing the boot
+                                       * process to continue */
+    KM_VERIFIED_BOOT_FAILED = 3,      /* The device failed verification. The bootloader displays a
+                                       * warning and stops the boot process, so no keymaster
+                                       * implementation should ever actually return this value,
+                                       * since it should not run.  Included here only for
+                                       * completeness. */
+} keymaster_verified_boot_t;
+
+/**
+ * Algorithms that may be provided by keymaster implementations.
+ */
+typedef enum {
+    /* Asymmetric algorithms. */
+    KM_ALGORITHM_RSA = 1,
+    // KM_ALGORITHM_DSA = 2, -- Removed, do not re-use value 2.
+    KM_ALGORITHM_EC = 3,
+
+    /* Block ciphers algorithms */
+    KM_ALGORITHM_AES = 32,
+
+    /* MAC algorithms */
+    KM_ALGORITHM_HMAC = 128,
+} keymaster_algorithm_t;
+
+typedef enum {
+    KM_ERROR_OK = 0,
+    KM_ERROR_ROOT_OF_TRUST_ALREADY_SET = -1,
+    KM_ERROR_UNSUPPORTED_PURPOSE = -2,
+    KM_ERROR_INCOMPATIBLE_PURPOSE = -3,
+    KM_ERROR_UNSUPPORTED_ALGORITHM = -4,
+    KM_ERROR_INCOMPATIBLE_ALGORITHM = -5,
+    KM_ERROR_UNSUPPORTED_KEY_SIZE = -6,
+    KM_ERROR_UNSUPPORTED_BLOCK_MODE = -7,
+    KM_ERROR_INCOMPATIBLE_BLOCK_MODE = -8,
+    KM_ERROR_UNSUPPORTED_MAC_LENGTH = -9,
+    KM_ERROR_UNSUPPORTED_PADDING_MODE = -10,
+    KM_ERROR_INCOMPATIBLE_PADDING_MODE = -11,
+    KM_ERROR_UNSUPPORTED_DIGEST = -12,
+    KM_ERROR_INCOMPATIBLE_DIGEST = -13,
+    KM_ERROR_INVALID_EXPIRATION_TIME = -14,
+    KM_ERROR_INVALID_USER_ID = -15,
+    KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT = -16,
+    KM_ERROR_UNSUPPORTED_KEY_FORMAT = -17,
+    KM_ERROR_INCOMPATIBLE_KEY_FORMAT = -18,
+    KM_ERROR_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19,   /* For PKCS8 & PKCS12 */
+    KM_ERROR_UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20, /* For PKCS8 & PKCS12 */
+    KM_ERROR_INVALID_INPUT_LENGTH = -21,
+    KM_ERROR_KEY_EXPORT_OPTIONS_INVALID = -22,
+    KM_ERROR_DELEGATION_NOT_ALLOWED = -23,
+    KM_ERROR_KEY_NOT_YET_VALID = -24,
+    KM_ERROR_KEY_EXPIRED = -25,
+    KM_ERROR_KEY_USER_NOT_AUTHENTICATED = -26,
+    KM_ERROR_OUTPUT_PARAMETER_NULL = -27,
+    KM_ERROR_INVALID_OPERATION_HANDLE = -28,
+    KM_ERROR_INSUFFICIENT_BUFFER_SPACE = -29,
+    KM_ERROR_VERIFICATION_FAILED = -30,
+    KM_ERROR_TOO_MANY_OPERATIONS = -31,
+    KM_ERROR_UNEXPECTED_NULL_POINTER = -32,
+    KM_ERROR_INVALID_KEY_BLOB = -33,
+    KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED = -34,
+    KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED = -35,
+    KM_ERROR_IMPORTED_KEY_NOT_SIGNED = -36,
+    KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED = -37,
+    KM_ERROR_INVALID_ARGUMENT = -38,
+    KM_ERROR_UNSUPPORTED_TAG = -39,
+    KM_ERROR_INVALID_TAG = -40,
+    KM_ERROR_MEMORY_ALLOCATION_FAILED = -41,
+    KM_ERROR_IMPORT_PARAMETER_MISMATCH = -44,
+    KM_ERROR_SECURE_HW_ACCESS_DENIED = -45,
+    KM_ERROR_OPERATION_CANCELLED = -46,
+    KM_ERROR_CONCURRENT_ACCESS_CONFLICT = -47,
+    KM_ERROR_SECURE_HW_BUSY = -48,
+    KM_ERROR_SECURE_HW_COMMUNICATION_FAILED = -49,
+    KM_ERROR_UNSUPPORTED_EC_FIELD = -50,
+    KM_ERROR_MISSING_NONCE = -51,
+    KM_ERROR_INVALID_NONCE = -52,
+    KM_ERROR_MISSING_MAC_LENGTH = -53,
+    KM_ERROR_KEY_RATE_LIMIT_EXCEEDED = -54,
+    KM_ERROR_CALLER_NONCE_PROHIBITED = -55,
+    KM_ERROR_KEY_MAX_OPS_EXCEEDED = -56,
+    KM_ERROR_INVALID_MAC_LENGTH = -57,
+    KM_ERROR_MISSING_MIN_MAC_LENGTH = -58,
+    KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59,
+    KM_ERROR_UNSUPPORTED_KDF = -60,
+    KM_ERROR_UNSUPPORTED_EC_CURVE = -61,
+    KM_ERROR_KEY_REQUIRES_UPGRADE = -62,
+    KM_ERROR_ATTESTATION_CHALLENGE_MISSING = -63,
+    KM_ERROR_KEYMASTER_NOT_CONFIGURED = -64,
+
+    KM_ERROR_UNIMPLEMENTED = -100,
+    KM_ERROR_VERSION_MISMATCH = -101,
+
+    KM_ERROR_UNKNOWN_ERROR = -1000,
+} keymaster_error_t;
+
+/**
+ * keymaster_message - Serial header for communicating with KM server
+ *
+ * @cmd: the command, one of keymaster_command.
+ * @payload: start of the serialized command specific payload
+ */
+struct keymaster_message {
+    uint32_t cmd;
+    uint8_t payload[0];
+};
+
+/**
+ * km_no_response -  Generic keymaster response for commands with no special
+ * response data
+ *
+ * @error: error code from command
+ */
+struct km_no_response {
+    int32_t error;
+};
+
+/**
+ * km_get_version_resp - response format for KM_GET_VERSION.
+ */
+struct km_get_version_resp {
+    int32_t error;
+    uint8_t major_ver;
+    uint8_t minor_ver;
+    uint8_t subminor_ver;
+} TRUSTY_ATTR_PACKED;
+
+/**
+ * km_boot_params - Parameters sent from the bootloader to the Keymaster TA
+ *
+ * Since verified_boot_key_hash and verified_boot_hash have variable sizes, this
+ * structure must be serialized before sending to the secure side
+ * using km_boot_params_serialize().
+ *
+ * @os_version: OS version from Android image header
+ * @os_patchlevel: OS patch level from Android image header
+ * @device_locked: nonzero if device is locked
+ * @verified_boot_state: one of keymaster_verified_boot_t
+ * @verified_boot_key_hash_size: size of verified_boot_key_hash
+ * @verified_boot_key_hash: hash of key used to verify Android image
+ * @verified_boot_hash_size: size of verified_boot_hash
+ * @verified_boot_hash: cumulative hash of all images verified thus far
+ */
+struct km_boot_params {
+    uint32_t os_version;
+    uint32_t os_patchlevel;
+    uint32_t device_locked;
+    uint32_t verified_boot_state;
+    uint32_t verified_boot_key_hash_size;
+    const uint8_t *verified_boot_key_hash;
+    uint32_t verified_boot_hash_size;
+    const uint8_t *verified_boot_hash;
+} TRUSTY_ATTR_PACKED;
+
+/**
+ * km_attestation_data - represents a DER encoded key or certificate
+ *
+ * @algorithm: one of KM_ALGORITHM_RSA or KM_ALGORITHM_EC
+ * @data_size: size of |data|
+ * @data: DER encoded key or certificate (depending on operation)
+ */
+struct km_attestation_data {
+    uint32_t algorithm;
+    uint32_t data_size;
+    const uint8_t *data;
+} TRUSTY_ATTR_PACKED;
+
+/**
+ * Serializes a km_boot_params structure. On success, allocates |*out_size|
+ * bytes to |*out| and writes the serialized |params| to |*out|. Caller takes
+ * ownership of |*out|. Returns one of trusty_err.
+ */
+int km_boot_params_serialize(const struct km_boot_params *params, uint8_t **out,
+                             uint32_t *out_size);
+
+/**
+ * Serializes a km_attestation_data structure. On success, allocates |*out_size|
+ * bytes to |*out| and writes the serialized |data| to |*out|. Caller takes
+ * ownership of |*out|. Returns one of trusty_err.
+ */
+int km_attestation_data_serialize(const struct km_attestation_data *data,
+                                  uint8_t **out, uint32_t *out_size);
+
+#endif /* TRUSTY_INTERFACE_KEYMASTER_H_ */
diff --git a/include/interface/storage/storage.h b/include/interface/storage/storage.h
new file mode 100644 (file)
index 0000000..e4f7f83
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef TRUSTY_INTERFACE_STORAGE_H_
+#define TRUSTY_INTERFACE_STORAGE_H_
+
+/*
+ * The contents of this file are copied from
+ * trusty/lib/interface/storage/include/interface/storage/storage.h.
+ * It is required to stay in sync for struct formats and enum values.
+ */
+
+#include <trusty/sysdeps.h>
+
+/*
+ * @STORAGE_DISK_PROXY_PORT: Port used by non-secure proxy server
+ */
+#define STORAGE_DISK_PROXY_PORT    "com.android.trusty.storage.proxy"
+
+enum storage_cmd {
+    STORAGE_REQ_SHIFT = 1,
+    STORAGE_RESP_BIT  = 1,
+
+    STORAGE_RESP_MSG_ERR   = STORAGE_RESP_BIT,
+
+    STORAGE_FILE_DELETE    = 1 << STORAGE_REQ_SHIFT,
+    STORAGE_FILE_OPEN      = 2 << STORAGE_REQ_SHIFT,
+    STORAGE_FILE_CLOSE     = 3 << STORAGE_REQ_SHIFT,
+    STORAGE_FILE_READ      = 4 << STORAGE_REQ_SHIFT,
+    STORAGE_FILE_WRITE     = 5 << STORAGE_REQ_SHIFT,
+    STORAGE_FILE_GET_SIZE  = 6 << STORAGE_REQ_SHIFT,
+    STORAGE_FILE_SET_SIZE  = 7 << STORAGE_REQ_SHIFT,
+
+    STORAGE_RPMB_SEND      = 8 << STORAGE_REQ_SHIFT,
+
+    /* transaction support */
+    STORAGE_END_TRANSACTION = 9 << STORAGE_REQ_SHIFT,
+};
+
+/**
+ * enum storage_err - error codes for storage protocol
+ * @STORAGE_NO_ERROR:           all OK
+ * @STORAGE_ERR_GENERIC:        unknown error. Can occur when there's an internal server
+ *                              error, e.g. the server runs out of memory or is in a bad state.
+ * @STORAGE_ERR_NOT_VALID:      input not valid. May occur if the arguments passed
+ *                              into the command are not valid, for example if the file handle
+ *                              passed in is not a valid one.
+ * @STORAGE_ERR_UNIMPLEMENTED:  the command passed in is not recognized
+ * @STORAGE_ERR_ACCESS:         the file is not accessible in the requested mode
+ * @STORAGE_ERR_NOT_FOUND:      the file was not found
+ * @STORAGE_ERR_EXIST           the file exists when it shouldn't as in with OPEN_CREATE | OPEN_EXCLUSIVE.
+ * @STORAGE_ERR_TRANSACT        returned by various operations to indicate that current transaction
+ *                              is in error state. Such state could be only cleared by sending
+ *                              STORAGE_END_TRANSACTION message.
+ */
+enum storage_err {
+    STORAGE_NO_ERROR          = 0,
+    STORAGE_ERR_GENERIC       = 1,
+    STORAGE_ERR_NOT_VALID     = 2,
+    STORAGE_ERR_UNIMPLEMENTED = 3,
+    STORAGE_ERR_ACCESS        = 4,
+    STORAGE_ERR_NOT_FOUND     = 5,
+    STORAGE_ERR_EXIST         = 6,
+    STORAGE_ERR_TRANSACT      = 7,
+};
+
+/**
+ * enum storage_msg_flag - protocol-level flags in struct storage_msg
+ * @STORAGE_MSG_FLAG_BATCH:             if set, command belongs to a batch transaction.
+ *                                      No response will be sent by the server until
+ *                                      it receives a command with this flag unset, at
+ *                                      which point a cummulative result for all messages
+ *                                      sent with STORAGE_MSG_FLAG_BATCH will be sent.
+ *                                      This is only supported by the non-secure disk proxy
+ *                                      server.
+ * @STORAGE_MSG_FLAG_PRE_COMMIT:        if set, indicates that server need to commit
+ *                                      pending changes before processing this message.
+ * @STORAGE_MSG_FLAG_POST_COMMIT:       if set, indicates that server need to commit
+ *                                      pending changes after processing this message.
+ * @STORAGE_MSG_FLAG_TRANSACT_COMPLETE: if set, indicates that server need to commit
+ *                                      current transaction after processing this message.
+ *                                      It is an alias for STORAGE_MSG_FLAG_POST_COMMIT.
+ */
+enum storage_msg_flag {
+    STORAGE_MSG_FLAG_BATCH = 0x1,
+    STORAGE_MSG_FLAG_PRE_COMMIT = 0x2,
+    STORAGE_MSG_FLAG_POST_COMMIT = 0x4,
+    STORAGE_MSG_FLAG_TRANSACT_COMPLETE = STORAGE_MSG_FLAG_POST_COMMIT,
+};
+
+/*
+ * The following declarations are the message-specific contents of
+ * the 'payload' element inside struct storage_msg.
+ */
+
+/**
+ * struct storage_rpmb_send_req - request format for STORAGE_RPMB_SEND
+ * @reliable_write_size:        size in bytes of reliable write region
+ * @write_size:                 size in bytes of write region
+ * @read_size:                  number of bytes to read for a read request
+ * @__reserved:                 unused, must be set to 0
+ * @payload:                    start of reliable write region, followed by
+ *                              write region.
+ *
+ * Only used in proxy<->server interface.
+ */
+struct storage_rpmb_send_req {
+    uint32_t reliable_write_size;
+    uint32_t write_size;
+    uint32_t read_size;
+    uint32_t __reserved;
+    uint8_t  payload[0];
+};
+
+/**
+ * struct storage_rpmb_send_resp: response type for STORAGE_RPMB_SEND
+ * @data: the data frames frames retrieved from the MMC.
+ */
+struct storage_rpmb_send_resp {
+    uint8_t data[0];
+};
+
+/**
+ * struct storage_msg - generic req/resp format for all storage commands
+ * @cmd:        one of enum storage_cmd
+ * @op_id:      client chosen operation identifier for an instance
+ *              of a command or atomic grouping of commands (transaction).
+ * @flags:      one or many of enum storage_msg_flag or'ed together.
+ * @size:       total size of the message including this header
+ * @result:     one of enum storage_err
+ * @__reserved: unused, must be set to 0.
+ * @payload:    beginning of command specific message format
+ */
+struct storage_msg {
+    uint32_t cmd;
+    uint32_t op_id;
+    uint32_t flags;
+    uint32_t size;
+    int32_t  result;
+    uint32_t __reserved;
+    uint8_t  payload[0];
+};
+
+#endif /* TRUSTY_INTERFACE_STORAGE_H_ */
diff --git a/include/trusty/avb.h b/include/trusty/avb.h
new file mode 100644 (file)
index 0000000..f54a3ff
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef TRUSTY_AVB_H_
+#define TRUSTY_AVB_H_
+
+#include <trusty/sysdeps.h>
+#include <trusty/trusty_ipc.h>
+#include <interface/avb/avb.h>
+
+/*
+ * Initialize AVB TIPC client. Returns one of trusty_err.
+ *
+ * @dev: initialized with trusty_ipc_dev_create
+ */
+int avb_tipc_init(struct trusty_ipc_dev *dev);
+/*
+ * Shutdown AVB TIPC client.
+ *
+ * @dev: initialized with trusty_ipc_dev_create
+ */
+void avb_tipc_shutdown(struct trusty_ipc_dev *dev);
+/*
+ * Send request to secure side to read rollback index.
+ * Returns one of trusty_err.
+ *
+ * @slot:    rollback index slot
+ * @value:   rollback index value stored here
+ */
+int trusty_read_rollback_index(uint32_t slot, uint64_t *value);
+/*
+ * Send request to secure side to write rollback index
+ * Returns one of trusty_err.
+ *
+ * @slot:    rollback index slot
+ * @value:   rollback index value to write
+ */
+int trusty_write_rollback_index(uint32_t slot, uint64_t value);
+/*
+ * Send request to secure side to read permanent attributes. When permanent
+ * attributes are stored in RPMB, a hash of the permanent attributes which is
+ * given to AVB during verification MUST still be backed by write-once hardware.
+ *
+ * Copies attributes received by secure side to |attributes|. If |size| does not
+ * match the size returned by the secure side, an error is returned. Returns one
+ * of trusty_err.
+ *
+ * @attributes:  caller allocated buffer
+ * @size:        size of |attributes|
+ */
+int trusty_read_permanent_attributes(uint8_t *attributes, uint32_t size);
+/*
+ * Send request to secure side to write permanent attributes. Permanent
+ * attributes can only be written to storage once.
+ *
+ * Returns one of trusty_err.
+ */
+int trusty_write_permanent_attributes(uint8_t *attributes, uint32_t size);
+/*
+ * Send request to secure side to read device lock state from RPMB.
+ *
+ * Returns one of trusty_err.
+ */
+int trusty_read_lock_state(uint8_t *lock_state);
+/*
+ * Send request to secure side to write device lock state to RPMB. If the lock
+ * state is changed, all rollback index data will be cleared.
+ *
+ * Returns one of trusty_err.
+ */
+int trusty_write_lock_state(uint8_t lock_state);
+/*
+ * Send request to secure side to lock the boot state. After this is invoked,
+ * the non-secure side will not be able to write to data managed by the AVB
+ * service until next boot.
+ *
+ * Returns one of trusty_err.
+ */
+int trusty_lock_boot_state(void);
+
+#endif /* TRUSTY_AVB_H_ */
diff --git a/include/trusty/keymaster.h b/include/trusty/keymaster.h
new file mode 100644 (file)
index 0000000..6117ae6
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef TRUSTY_KEYMASTER_H_
+#define TRUSTY_KEYMASTER_H_
+
+#include <trusty/sysdeps.h>
+#include <trusty/trusty_ipc.h>
+#include <interface/keymaster/keymaster.h>
+
+/*
+ * Initialize Keymaster TIPC client. Returns one of trusty_err.
+ *
+ * @dev: initialized with trusty_ipc_dev_create
+ */
+int km_tipc_init(struct trusty_ipc_dev *dev);
+
+/*
+ * Shutdown Keymaster TIPC client.
+ *
+ * @dev: initialized with trusty_ipc_dev_create
+ */
+void km_tipc_shutdown(struct trusty_ipc_dev *dev);
+
+/*
+ * Set Keymaster boot parameters. Returns one of trusty_err.
+ *
+ * @os_version: OS version from Android image header
+ * @os_patchlevel: OS patch level from Android image header
+ * @verified_boot_state: one of keymaster_verified_boot_t
+ * @device_locked: nonzero if device is locked
+ * @verified_boot_key_hash: hash of key used to verify Android image
+ * @verified_boot_key_hash_size: size of verified_boot_key_hash
+ * @verified_boot_hash: cumulative hash of all images verified thus far.
+ *                      May be NULL if not computed.
+ * @verified_boot_hash_size: size of verified_boot_hash
+ */
+int trusty_set_boot_params(uint32_t os_version, uint32_t os_patchlevel,
+                           keymaster_verified_boot_t verified_boot_state,
+                           bool device_locked,
+                           const uint8_t *verified_boot_key_hash,
+                           uint32_t verified_boot_key_hash_size,
+                           const uint8_t *verified_boot_hash,
+                           uint32_t verified_boot_hash_size);
+
+/*
+ * Set Keymaster attestation key. Returns one of trusty_err.
+ *
+ * @key: buffer containing key
+ * @key_size: size of key in bytes
+ * @algorithm: one of KM_ALGORITHM_RSA or KM_ALGORITHM_EC
+ */
+int trusty_set_attestation_key(const uint8_t *key, uint32_t key_size,
+                               keymaster_algorithm_t algorithm);
+
+/*
+ * Append certificate to Keymaster attestation certificate chain. Returns
+ * one of trusty_err.
+ *
+ * @cert: buffer containing certificate
+ * @cert_size: size of certificate in bytes
+ * @algorithm: one of KM_ALGORITHM_RSA or KM_ALGORITHM_EC
+ */
+int trusty_append_attestation_cert_chain(const uint8_t *cert,
+                                         uint32_t cert_size,
+                                         keymaster_algorithm_t algorithm);
+
+#endif /* TRUSTY_KEYMASTER_H_ */
diff --git a/include/trusty/libtipc.h b/include/trusty/libtipc.h
new file mode 100644 (file)
index 0000000..e37b010
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef TRUSTY_LIBTIPC_H_
+#define TRUSTY_LIBTIPC_H_
+
+#include <trusty/avb.h>
+#include <trusty/keymaster.h>
+#include <trusty/sysdeps.h>
+
+/*
+ * Initialize TIPC library
+ */
+void trusty_ipc_init(void);
+/*
+ * Shutdown TIPC library
+ */
+void trusty_ipc_shutdown(void);
+
+#endif /* TRUSTY_LIBTIPC_H_ */
diff --git a/include/trusty/rpmb.h b/include/trusty/rpmb.h
new file mode 100644 (file)
index 0000000..594f527
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef TRUSTY_RPMB_H_
+#define TRUSTY_RPMB_H_
+
+#include <trusty/sysdeps.h>
+#include <trusty/trusty_ipc.h>
+
+#define MMC_BLOCK_SIZE 512
+
+/*
+ * Initialize RPMB storage proxy. Returns one of trusty_err.
+ *
+ * @dev:      initialized with trusty_ipc_dev_create
+ * @rpmb_dev: Context of RPMB device, initialized with rpmb_storage_get_ctx
+ */
+int rpmb_storage_proxy_init(struct trusty_ipc_dev *dev, void *rpmb_dev);
+/*
+ * Poll for and handle RPMB storange events. Returns one of trusty_err.
+ */
+int rpmb_storage_proxy_poll(void);
+/*
+ * Shutdown RPMB storage proxy
+ *
+ * @dev: initialized with trusty_ipc_dev_create
+ */
+void rpmb_storage_proxy_shutdown(struct trusty_ipc_dev *dev);
+/*
+ * Execute RPMB command. Implementation is platform specific.
+ * Returns one of trusty_err.
+ *
+ * @rpmb_dev:            Context of RPMB device, initialized with
+ *                       rpmb_storage_get_ctx
+ * @reliable_write_data: Buffer containing RPMB structs for reliable write
+ * @reliable_write_size: Size of reliable_write_data
+ * @write_data:          Buffer containing RPMB structs for write
+ * @write_size:          Size of write_data
+ * @read_data:           Buffer to be filled with RPMB structs read from RPMB
+ *                       partition
+ * @read_size:           Size of read_data
+ */
+int rpmb_storage_send(void *rpmb_dev,
+                      const void *reliable_write_data,
+                      size_t reliable_write_size,
+                      const void *write_data, size_t write_size,
+                      void *read_buf, size_t read_size);
+/*
+ * Return context for RPMB device. This is called when the RPMB storage proxy is
+ * initialized, and subsequently used when issuing RPMB storage requests.
+ * Implementation is platform specific.
+ */
+void *rpmb_storage_get_ctx(void);
+
+#endif /* TRUSTY_RPMB_H_ */
diff --git a/include/trusty/sysdeps.h b/include/trusty/sysdeps.h
new file mode 100644 (file)
index 0000000..7704563
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef TRUSTY_SYSDEPS_H_
+#define TRUSTY_SYSDEPS_H_
+/*
+ * Change these includes to match your platform to bring in the equivalent
+ * types available in a normal C runtime. At least things like uint64_t,
+ * uintptr_t, and bool (with |false|, |true| keywords) must be present.
+ */
+#include <compiler.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <linux/types.h>
+/*
+ * These attribute macros may need to be adjusted if not using gcc or clang.
+ */
+#define TRUSTY_ATTR_PACKED __attribute__((packed))
+#define TRUSTY_ATTR_NO_RETURN __attribute__((noreturn))
+#define TRUSTY_ATTR_SENTINEL __attribute__((__sentinel__))
+#define TRUSTY_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+
+#define PAGE_SIZE 4096
+/*
+ * Struct containing attributes for memory to be shared with secure size.
+ */
+struct ns_mem_page_info {
+    uint64_t attr;
+};
+
+struct trusty_dev;
+
+/*
+ * Lock/unlock mutex associated with @dev. These can be safely empty in a single
+ * threaded environment.
+ *
+ * @dev: Trusty device initialized with trusty_dev_init
+ */
+void trusty_lock(struct trusty_dev *dev);
+void trusty_unlock(struct trusty_dev *dev);
+/*
+ * Disable/enable IRQ interrupts and save/restore @state
+ */
+void trusty_local_irq_disable(unsigned long *state);
+void trusty_local_irq_restore(unsigned long *state);
+/*
+ * Put in standby state waiting for interrupt.
+ *
+ * @dev: Trusty device initialized with trusty_dev_init
+ */
+void trusty_idle(struct trusty_dev *dev);
+/*
+ * Aborts the program or reboots the device.
+ */
+void trusty_abort(void) TRUSTY_ATTR_NO_RETURN;
+/*
+ * Print a formatted string. @format must point to a NULL-terminated UTF-8
+ * string, and is followed by arguments to be printed.
+ */
+void trusty_printv(const char *format, ...);
+/*
+ * Copy @n bytes from @src to @dest.
+ */
+void *trusty_memcpy(void *dest, const void *src, size_t n);
+/*
+ * Set @n bytes starting at @dest to @c. Returns @dest.
+ */
+void *trusty_memset(void *dest, const int c, size_t n);
+/*
+ * Copy string from @src to @dest, including the terminating NULL byte.
+ *
+ * The size of the array at @dest should be long enough to contain the string
+ * at @src, and should not overlap in memory with @src.
+ */
+char *trusty_strcpy(char *dest, const char *src);
+/*
+ * Returns the length of @str, excluding the terminating NULL byte.
+ */
+size_t trusty_strlen(const char *str);
+/*
+ * Allocate @n elements of size @size. Initializes memory to 0, returns pointer
+ * to it.
+ */
+void *trusty_calloc(size_t n, size_t size) TRUSTY_ATTR_WARN_UNUSED_RESULT;
+/*
+ * Free memory at @addr allocated with trusty_calloc.
+ */
+void trusty_free(void *addr);
+/*
+ * Allocate @size bytes of page aligned memory to be shared with secure side.
+ *
+ * @mem_inf:  Stores cache attributes
+ * Returns:   vaddr of allocated memory
+ */
+void *trusty_membuf_alloc(struct ns_mem_page_info *mem_inf,
+                          size_t size) TRUSTY_ATTR_WARN_UNUSED_RESULT;
+/*
+ * Frees memory at @vaddr allocated by trusty_membuf_alloc
+ */
+void trusty_membuf_free(void *vaddr);
+
+#endif /* TRUSTY_SYSDEPS_H_ */
diff --git a/include/trusty/trusty_dev.h b/include/trusty/trusty_dev.h
new file mode 100644 (file)
index 0000000..27ae8cc
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef TRUSTY_TRUSTY_DEV_H_
+#define TRUSTY_TRUSTY_DEV_H_
+
+#include <trusty/sysdeps.h>
+
+/*
+ * Architecture specific Trusty device struct.
+ *
+ * @priv_data:   system dependent data, may be unused
+ * @api_version: TIPC version
+ */
+struct trusty_dev {
+    void *priv_data;
+    uint32_t api_version;
+};
+
+/*
+ * Initializes @dev with @priv, and gets the API version by calling
+ * into Trusty. Returns negative on error.
+ */
+int trusty_dev_init(struct trusty_dev *dev, void *priv);
+
+/*
+ * Cleans up anything related to @dev. Returns negative on error.
+ */
+int trusty_dev_shutdown(struct trusty_dev *dev);
+
+/*
+ * Invokes creation of queueless Trusty IPC device on the secure side.
+ * @buf will be mapped into Trusty's address space.
+ *
+ * @dev:      trusty device, initialized with trusty_dev_init
+ * @buf:      physical address info of buffer to share with Trusty
+ * @buf_size: size of @buf
+ */
+int trusty_dev_init_ipc(struct trusty_dev *dev, struct ns_mem_page_info *buf,
+                        uint32_t buf_size);
+/*
+ * Invokes execution of command on the secure side.
+ *
+ * @dev:      trusty device, initialized with trusty_dev_init
+ * @buf:      physical address info of shared buffer containing command
+ * @buf_size: size of command data
+ */
+int trusty_dev_exec_ipc(struct trusty_dev *dev, struct ns_mem_page_info *buf,
+                        uint32_t buf_size);
+/*
+ * Invokes deletion of queueless Trusty IPC device on the secure side.
+ * @buf is unmapped, and all open channels are closed.
+ *
+ * @dev:      trusty device, initialized with trusty_dev_init
+ * @buf:      physical address info of shared buffer
+ * @buf_size: size of @buf
+ */
+int trusty_dev_shutdown_ipc(struct trusty_dev *dev,
+                            struct ns_mem_page_info *buf, uint32_t buf_size);
+
+#endif /* TRUSTY_TRUSTY_DEV_H_ */
diff --git a/include/trusty/trusty_ipc.h b/include/trusty/trusty_ipc.h
new file mode 100644 (file)
index 0000000..03ef935
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef TRUSTY_TRUSTY_IPC_H_
+#define TRUSTY_TRUSTY_IPC_H_
+
+#include <trusty/sysdeps.h>
+
+/*
+ * handle_t is an opaque 32 bit value that is used to reference an
+ * Trusty IPC channel
+ */
+typedef uint32_t handle_t;
+
+#define INVALID_IPC_HANDLE  0
+
+/*
+ * Error codes returned by Trusty IPC device function calls
+ */
+enum trusty_err {
+    TRUSTY_ERR_NONE            =  0,
+    TRUSTY_ERR_GENERIC         = -1,
+    TRUSTY_ERR_NOT_SUPPORTED   = -2,
+    TRUSTY_ERR_NO_MEMORY       = -3,
+    TRUSTY_ERR_INVALID_ARGS    = -4,
+    TRUSTY_ERR_SECOS_ERR       = -5,
+    TRUSTY_ERR_MSG_TOO_BIG     = -6,
+    TRUSTY_ERR_NO_MSG          = -7,
+    TRUSTY_ERR_CHANNEL_CLOSED  = -8,
+    TRUSTY_ERR_SEND_BLOCKED    = -9,
+};
+/*
+ * Return codes for successful Trusty IPC events (failures return trusty_err)
+ */
+enum trusty_event_result {
+    TRUSTY_EVENT_HANDLED   = 1,
+    TRUSTY_EVENT_NONE      = 2
+};
+
+/*
+ * Combination of these values are used for the event field
+ * of trusty_ipc_event structure.
+ */
+enum trusty_ipc_event_type {
+    IPC_HANDLE_POLL_NONE  = 0x0,
+    IPC_HANDLE_POLL_READY = 0x1,
+    IPC_HANDLE_POLL_ERROR = 0x2,
+    IPC_HANDLE_POLL_HUP   = 0x4,
+    IPC_HANDLE_POLL_MSG   = 0x8,
+    IPC_HANDLE_POLL_SEND_UNBLOCKED = 0x10,
+};
+
+struct trusty_dev;
+struct trusty_ipc_chan;
+
+/*
+ * Trusty IPC event
+ *
+ * @event:  event type
+ * @handle: handle this event is related to
+ * @cookie: cookie associated with handle
+ */
+struct trusty_ipc_event {
+    uint32_t event;
+    uint32_t handle;
+    uint64_t cookie;
+};
+
+struct trusty_ipc_iovec {
+    void *base;
+    size_t len;
+};
+
+/*
+ * Trusty IPC device
+ *
+ * @buf_vaddr: virtual address of shared buffer associated with device
+ * @buf_size:  size of shared buffer
+ * @buf_ns:    physical address info of shared buffer
+ * @tdev:      trusty device
+ */
+struct trusty_ipc_dev {
+    void  *buf_vaddr;
+    size_t buf_size;
+    struct ns_mem_page_info buf_ns;
+    struct trusty_dev *tdev;
+};
+
+/*
+ * Trusty IPC event handlers.
+ */
+struct trusty_ipc_ops {
+    int (*on_raw_event)(struct trusty_ipc_chan *chan,
+                        struct trusty_ipc_event *evt);
+    int (*on_connect_complete)(struct trusty_ipc_chan *chan);
+    int (*on_send_unblocked)(struct trusty_ipc_chan *chan);
+    int (*on_message)(struct trusty_ipc_chan *chan);
+    int (*on_disconnect)(struct trusty_ipc_chan *chan);
+};
+
+/*
+ * Trusty IPC channel.
+ *
+ * @ops_ctx:  refers to additional data that may be used by trusty_ipc_ops
+ * @handle:   identifier for channel
+ * @complete: completion status of last event on channel
+ * @dev:      Trusty IPC device used by channel, initialized with
+              trusty_ipc_dev_create
+ * @ops:      callbacks for Trusty events
+ */
+struct trusty_ipc_chan {
+    void *ops_ctx;
+    handle_t handle;
+    volatile int complete;
+    struct trusty_ipc_dev *dev;
+    struct trusty_ipc_ops *ops;
+};
+
+/*
+ * Creates new Trusty IPC device on @tdev. Allocates shared buffer, and calls
+ * trusty_dev_init_ipc to register with secure side. Returns a trusty_err.
+ *
+ * @ipc_dev:  new Trusty IPC device to be initialized
+ * @tdev:     associated Trusty device
+ * @buf_size: size of shared buffer to be allocated
+ */
+int trusty_ipc_dev_create(struct trusty_ipc_dev **ipc_dev,
+                          struct trusty_dev *tdev,
+                          size_t buf_size);
+/*
+ * Shutdown @dev. Frees shared buffer, and calls trusty_dev_shutdown_ipc
+ * to shutdown on the secure side.
+ */
+void trusty_ipc_dev_shutdown(struct trusty_ipc_dev *dev);
+
+/*
+ * Calls into secure OS to initiate a new connection to a Trusty IPC service.
+ * Returns handle for the new channel, a trusty_err on error.
+ *
+ * @dev:    Trusty IPC device initialized with trusty_ipc_dev_create
+ * @port:   name of port to connect to on secure side
+ * @cookie: cookie associated with new channel.
+ */
+int trusty_ipc_dev_connect(struct trusty_ipc_dev *dev, const char *port,
+                           uint64_t cookie);
+/*
+ * Calls into secure OS to close connection to Trusty IPC service.
+ * Returns a trusty_err.
+ *
+ * @dev:  Trusty IPC device
+ * @chan: handle for connection, opened with trusty_ipc_dev_connect
+ */
+int trusty_ipc_dev_close(struct trusty_ipc_dev *dev, handle_t chan);
+
+/*
+ * Calls into secure OS to receive pending event. Returns a trusty_err.
+ *
+ * @dev:   Trusty IPC device
+ * @chan:  handle for connection
+ * @event: pointer to output event struct
+ */
+int trusty_ipc_dev_get_event(struct trusty_ipc_dev *dev, handle_t chan,
+                             struct trusty_ipc_event *event);
+/*
+ * Calls into secure OS to send message to channel. Returns a trusty_err.
+ *
+ * @dev:      Trusty IPC device
+ * @chan:     handle for connection
+ * @iovs:     contains messages to be sent
+ * @iovs_cnt: number of iovecs to be sent
+ */
+int trusty_ipc_dev_send(struct trusty_ipc_dev *dev, handle_t chan,
+                        const struct trusty_ipc_iovec *iovs, size_t iovs_cnt);
+/*
+ * Calls into secure OS to receive message on channel. Returns number of bytes
+ * received on success, trusty_err on failure.
+ *
+ * @dev:      Trusty IPC device
+ * @chan:     handle for connection
+ * @iovs:     contains received messages
+ * @iovs_cnt: number of iovecs received
+ */
+int trusty_ipc_dev_recv(struct trusty_ipc_dev *dev, handle_t chan,
+                        const struct trusty_ipc_iovec *iovs, size_t iovs_cnt);
+
+void trusty_ipc_dev_idle(struct trusty_ipc_dev *dev);
+
+/*
+ * Initializes @chan with default values and @dev.
+ */
+void trusty_ipc_chan_init(struct trusty_ipc_chan *chan,
+                          struct trusty_ipc_dev *dev);
+/*
+ * Calls trusty_ipc_dev_connect to get a handle for channel.
+ * Returns a trusty_err.
+ *
+ * @chan: channel to initialize with new handle
+ * @port: name of port to connect to on secure side
+ * @wait: flag to wait for connect to complete by polling for
+ *        IPC_HANDLE_POLL_READY event
+ */
+int trusty_ipc_connect(struct trusty_ipc_chan *chan, const char *port,
+                       bool wait);
+/*
+ * Calls trusty_ipc_dev_close and invalidates @chan. Returns a trusty_err.
+ */
+int trusty_ipc_close(struct trusty_ipc_chan *chan);
+/*
+ * Calls trusty_ipc_dev_get_event to poll for an event on @chan. Handles
+ * event by calling appropriate callback. Returns nonnegative on success.
+ */
+int trusty_ipc_poll_for_event(struct trusty_ipc_chan *chan);
+/*
+ * Calls trusty_ipc_dev_send to send a message. Returns a trusty_err.
+ *
+ * @chan:     handle for connection
+ * @iovs:     contains messages to be sent
+ * @iovs_cnt: number of iovecs to be sent
+ * @wait:     flag to wait for send to complete
+ */
+int trusty_ipc_send(struct trusty_ipc_chan *chan,
+                    const struct trusty_ipc_iovec *iovs, size_t iovs_cnt,
+                    bool wait);
+/*
+ * Calls trusty_ipc_dev_recv to receive a message. Return number of bytes
+ * received on success, trusty_err on failure.
+ *
+ * @chan:     handle for connection
+ * @iovs:     contains received messages
+ * @iovs_cnt: number of iovecs received
+ * @wait:     flag to wait for a message to receive
+ */
+int trusty_ipc_recv(struct trusty_ipc_chan *chan,
+                    const struct trusty_ipc_iovec *iovs, size_t iovs_cnt,
+                    bool wait);
+
+#endif /* TRUSTY_TRUSTY_IPC_H_ */
diff --git a/include/trusty/util.h b/include/trusty/util.h
new file mode 100644 (file)
index 0000000..58cb2e7
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef TRUSTY_UTIL_H_
+#define TRUSTY_UTIL_H_
+
+#include <trusty/sysdeps.h>
+
+#define TRUSTY_STRINGIFY(x) #x
+#define TRUSTY_TO_STRING(x) TRUSTY_STRINGIFY(x)
+
+/*
+ * Aborts the program if @expr is false.
+ *
+ * This has no effect unless TIPC_ENABLE_DEBUG is defined.
+ */
+#ifdef TIPC_ENABLE_DEBUG
+#define trusty_assert(expr)                     \
+  do {                                          \
+    if (!(expr)) {                              \
+      trusty_fatal("assert fail: " #expr "\n"); \
+    }                                           \
+  } while(0)
+#else
+#define trusty_assert(expr)
+#endif
+
+/*
+ * Prints debug message.
+ *
+ * This has no effect unless TIPC_ENABLE_DEBUG and LOCAL_LOG is defined.
+ */
+#ifdef TIPC_ENABLE_DEBUG
+#define trusty_debug(message, ...)                                       \
+  do {                                                                   \
+    if (LOCAL_LOG) {                                                     \
+      trusty_printv(__FILE__ ":" TRUSTY_TO_STRING(__LINE__) ": DEBUG "); \
+      trusty_printv(message, ##__VA_ARGS__, NULL);                       \
+    }                                                                    \
+  } while(0)
+#else
+#define trusty_debug(message, ...)
+#endif
+
+/*
+ * Prints info message.
+ */
+#define trusty_info(message, ...)                \
+  do {                                           \
+    trusty_printv(__FILE__ ": INFO ");           \
+    trusty_printv(message, ##__VA_ARGS__, NULL); \
+  } while(0)
+
+/*
+ * Prints error message.
+ */
+#define trusty_error(message, ...)                                     \
+  do {                                                                 \
+    trusty_printv(__FILE__ ":" TRUSTY_TO_STRING(__LINE__) ": ERROR "); \
+    trusty_printv(message, ##__VA_ARGS__, NULL);                       \
+  } while(0)
+
+/*
+ * Prints message and calls trusty_abort.
+ */
+#define trusty_fatal(message, ...)                                     \
+  do {                                                                 \
+    trusty_printv(__FILE__ ":" TRUSTY_TO_STRING(__LINE__) ": FATAL "); \
+    trusty_printv(message, ##__VA_ARGS__, NULL);                       \
+    trusty_abort();                                                    \
+  } while(0)
+
+#endif /* TRUSTY_UTIL_H_ */
index d164689..b8bfb76 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_TIZEN) += tizen/
 obj-$(CONFIG_FIT) += libfdt/
 obj-$(CONFIG_CMD_DHRYSTONE) += dhry/
 obj-$(CONFIG_AVB_SUPPORT) += avb/
+obj-$(CONFIG_IMX_TRUSTY_OS) += trusty/ql-tipc/sysdeps/
 
 obj-$(CONFIG_AES) += aes.o
 obj-$(CONFIG_USB_TTY) += circbuf.o
diff --git a/lib/trusty/ql-tipc/LICENSE b/lib/trusty/ql-tipc/LICENSE
new file mode 100644 (file)
index 0000000..d21621a
--- /dev/null
@@ -0,0 +1,20 @@
+Copyright 2016, The Android Open Source Project
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/trusty/ql-tipc/README.md b/lib/trusty/ql-tipc/README.md
new file mode 100644 (file)
index 0000000..76e3781
--- /dev/null
@@ -0,0 +1,30 @@
+# Queueless Trusty IPC
+
+ql-tipc is a portable client library that implements Trusty queueless IPC.
+It is intended to enable Trusty IPC in bootloader environments.
+
+## Code organization
+
+### IPC components
+
+- libtipc - Functions to be called by library user
+- ipc - IPC library
+- ipc_dev - Helper functions for sending requests to the secure OS
+- rpmb_proxy - Handles RPMB requests from secure storage service
+- avb - Sends requests to the Android Verified Boot service
+
+### Misc
+
+- examples/ - Implementations of bootloader-specific code.
+- arch/$ARCH/ - Architecture dependent implementation of Trusty device
+   (see trusty_dev.h). Implements SMCs on ARM for example.
+
+## Portability Notes
+
+The suggested approach to porting ql-tipc is to copy all header and C files
+into the bootloader and integrate as needed. RPMB storage operations and
+functions defined in trusty/sysdeps.h require system dependent implementations.
+
+If the TIPC_ENABLE_DEBUG preprocessor symbol is set, the code will include
+debug information and run-time checks. Production builds should not use this.
+
diff --git a/lib/trusty/ql-tipc/arch/arm/sm_err.h b/lib/trusty/ql-tipc/arch/arm/sm_err.h
new file mode 100644 (file)
index 0000000..9401256
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef QL_TIPC_SM_ERR_H_
+#define QL_TIPC_SM_ERR_H_
+
+/* Errors from the secure monitor */
+#define SM_ERR_UNDEFINED_SMC           0xFFFFFFFF /* Unknown SMC (defined by ARM DEN 0028A(0.9.0) */
+#define SM_ERR_INVALID_PARAMETERS      -2
+#define SM_ERR_INTERRUPTED             -3      /* Got interrupted. Call back with restart SMC */
+#define SM_ERR_UNEXPECTED_RESTART      -4      /* Got an restart SMC when we didn't expect it */
+#define SM_ERR_BUSY                    -5      /* Temporarily busy. Call back with original args */
+#define SM_ERR_INTERLEAVED_SMC         -6      /* Got a trusted_service SMC when a restart SMC is required */
+#define SM_ERR_INTERNAL_FAILURE                -7      /* Unknown error */
+#define SM_ERR_NOT_SUPPORTED           -8
+#define SM_ERR_NOT_ALLOWED             -9      /* SMC call not allowed */
+#define SM_ERR_END_OF_INPUT            -10
+#define SM_ERR_PANIC                   -11     /* Secure OS crashed */
+#define SM_ERR_FIQ_INTERRUPTED         -12     /* Got interrupted by FIQ. Call back with SMC_SC_RESTART_FIQ on same CPU */
+#define SM_ERR_CPU_IDLE                        -13     /* SMC call waiting for another CPU */
+#define SM_ERR_NOP_INTERRUPTED         -14     /* Got interrupted. Call back with new SMC_SC_NOP */
+#define SM_ERR_NOP_DONE                        -15     /* Cpu idle after SMC_SC_NOP (not an error) */
+
+#endif /* QL_TIPC_SM_ERR_H_ */
diff --git a/lib/trusty/ql-tipc/arch/arm/smcall.h b/lib/trusty/ql-tipc/arch/arm/smcall.h
new file mode 100644 (file)
index 0000000..695776c
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef QL_TIPC_SMCALL_H_
+#define QL_TIPC_SMCALL_H_
+
+#define SMC_NUM_ENTITIES       64
+#define SMC_NUM_ARGS           4
+#define SMC_NUM_PARAMS         (SMC_NUM_ARGS - 1)
+
+#define SMC_IS_FASTCALL(smc_nr)        ((smc_nr) & 0x80000000)
+#define SMC_IS_SMC64(smc_nr)   ((smc_nr) & 0x40000000)
+#define SMC_ENTITY(smc_nr)     (((smc_nr) & 0x3F000000) >> 24)
+#define SMC_FUNCTION(smc_nr)   ((smc_nr) & 0x0000FFFF)
+
+#define SMC_NR(entity, fn, fastcall, smc64) ((((fastcall) & 0x1) << 31) | \
+                                            (((smc64) & 0x1) << 30) | \
+                                            (((entity) & 0x3F) << 24) | \
+                                            ((fn) & 0xFFFF) \
+                                           )
+
+#define SMC_FASTCALL_NR(entity, fn)    SMC_NR((entity), (fn), 1, 0)
+#define SMC_STDCALL_NR(entity, fn)     SMC_NR((entity), (fn), 0, 0)
+#define SMC_FASTCALL64_NR(entity, fn)  SMC_NR((entity), (fn), 1, 1)
+#define SMC_STDCALL64_NR(entity, fn)   SMC_NR((entity), (fn), 0, 1)
+
+#define        SMC_ENTITY_ARCH                 0       /* ARM Architecture calls */
+#define        SMC_ENTITY_CPU                  1       /* CPU Service calls */
+#define        SMC_ENTITY_SIP                  2       /* SIP Service calls */
+#define        SMC_ENTITY_OEM                  3       /* OEM Service calls */
+#define        SMC_ENTITY_STD                  4       /* Standard Service calls */
+#define        SMC_ENTITY_RESERVED             5       /* Reserved for future use */
+#define        SMC_ENTITY_TRUSTED_APP          48      /* Trusted Application calls */
+#define        SMC_ENTITY_TRUSTED_OS           50      /* Trusted OS calls */
+#define        SMC_ENTITY_LOGGING              51      /* Used for secure -> nonsecure logging */
+#define        SMC_ENTITY_SECURE_MONITOR       60      /* Trusted OS calls internal to secure monitor */
+
+/* FC = Fast call, SC = Standard call */
+#define SMC_SC_RESTART_LAST    SMC_STDCALL_NR  (SMC_ENTITY_SECURE_MONITOR, 0)
+#define SMC_SC_LOCKED_NOP      SMC_STDCALL_NR  (SMC_ENTITY_SECURE_MONITOR, 1)
+
+/**
+ * SMC_SC_RESTART_FIQ - Re-enter trusty after it was interrupted by an fiq
+ *
+ * No arguments, no return value.
+ *
+ * Re-enter trusty after returning to ns to process an fiq. Must be called iff
+ * trusty returns SM_ERR_FIQ_INTERRUPTED.
+ *
+ * Enable by selecting api version TRUSTY_API_VERSION_RESTART_FIQ (1) or later.
+ */
+#define SMC_SC_RESTART_FIQ     SMC_STDCALL_NR  (SMC_ENTITY_SECURE_MONITOR, 2)
+
+/**
+ * SMC_SC_NOP - Enter trusty to run pending work.
+ *
+ * No arguments.
+ *
+ * Returns SM_ERR_NOP_INTERRUPTED or SM_ERR_NOP_DONE.
+ * If SM_ERR_NOP_INTERRUPTED is returned, the call must be repeated.
+ *
+ * Enable by selecting api version TRUSTY_API_VERSION_SMP (2) or later.
+ */
+#define SMC_SC_NOP             SMC_STDCALL_NR  (SMC_ENTITY_SECURE_MONITOR, 3)
+
+/*
+ * Return from secure os to non-secure os with return value in r1
+ */
+#define SMC_SC_NS_RETURN       SMC_STDCALL_NR  (SMC_ENTITY_SECURE_MONITOR, 0)
+
+#define SMC_FC_RESERVED                SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 0)
+#define SMC_FC_FIQ_EXIT                SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 1)
+#define SMC_FC_REQUEST_FIQ     SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 2)
+#define SMC_FC_GET_NEXT_IRQ    SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 3)
+#define SMC_FC_FIQ_ENTER       SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 4)
+
+#define SMC_FC64_SET_FIQ_HANDLER SMC_FASTCALL64_NR(SMC_ENTITY_SECURE_MONITOR, 5)
+#define SMC_FC64_GET_FIQ_REGS  SMC_FASTCALL64_NR (SMC_ENTITY_SECURE_MONITOR, 6)
+
+#define SMC_FC_CPU_SUSPEND     SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 7)
+#define SMC_FC_CPU_RESUME      SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 8)
+
+#define SMC_FC_AARCH_SWITCH    SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 9)
+#define SMC_FC_GET_VERSION_STR SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 10)
+
+/**
+ * SMC_FC_API_VERSION - Find and select supported API version.
+ *
+ * @r1: Version supported by client.
+ *
+ * Returns version supported by trusty.
+ *
+ * If multiple versions are supported, the client should start by calling
+ * SMC_FC_API_VERSION with the largest version it supports. Trusty will then
+ * return a version it supports. If the client does not support the version
+ * returned by trusty and the version returned is less than the version
+ * requested, repeat the call with the largest supported version less than the
+ * last returned version.
+ *
+ * This call must be made before any calls that are affected by the api version.
+ */
+#define TRUSTY_API_VERSION_RESTART_FIQ (1)
+#define TRUSTY_API_VERSION_SMP         (2)
+#define TRUSTY_API_VERSION_SMP_NOP     (3)
+#define TRUSTY_API_VERSION_CURRENT     (3)
+#define SMC_FC_API_VERSION     SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 11)
+
+/* TRUSTED_OS entity calls */
+#define SMC_SC_VIRTIO_GET_DESCR        SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 20)
+#define SMC_SC_VIRTIO_START    SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 21)
+#define SMC_SC_VIRTIO_STOP     SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 22)
+
+#define SMC_SC_VDEV_RESET      SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 23)
+#define SMC_SC_VDEV_KICK_VQ    SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 24)
+#define SMC_NC_VDEV_KICK_VQ    SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 25)
+
+/* Queueless Trusty IPC Interface */
+#define SMC_SC_TRUSTY_IPC_CREATE_QL_DEV                SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 30)
+#define SMC_SC_TRUSTY_IPC_SHUTDOWN_QL_DEV      SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 31)
+#define SMC_SC_TRUSTY_IPC_HANDLE_QL_DEV_CMD    SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 32)
+
+#endif /* QL_TIPC_SMCALL_H_ */
diff --git a/lib/trusty/ql-tipc/arch/arm/trusty_dev.c b/lib/trusty/ql-tipc/arch/arm/trusty_dev.c
new file mode 100644 (file)
index 0000000..6407d73
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <trusty/trusty_dev.h>
+#include <trusty/util.h>
+
+#include "sm_err.h"
+#include "smcall.h"
+
+struct trusty_dev;
+
+#define LOCAL_LOG 0
+
+#ifndef __asmeq
+#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
+#endif
+
+#ifdef  NS_ARCH_ARM64
+#define SMC_ARG0                "x0"
+#define SMC_ARG1                "x1"
+#define SMC_ARG2                "x2"
+#define SMC_ARG3                "x3"
+#define SMC_ARCH_EXTENSION      ""
+#define SMC_REGISTERS_TRASHED   "x4","x5","x6","x7","x8","x9","x10","x11", \
+                                "x12","x13","x14","x15","x16","x17"
+#else
+#define SMC_ARG0                "r0"
+#define SMC_ARG1                "r1"
+#define SMC_ARG2                "r2"
+#define SMC_ARG3                "r3"
+#define SMC_ARCH_EXTENSION      ".arch_extension sec\n"
+#define SMC_REGISTERS_TRASHED   "ip"
+#endif
+
+/*
+ * Execute SMC call into trusty
+ */
+static unsigned long smc(unsigned long r0,
+                         unsigned long r1,
+                         unsigned long r2,
+                         unsigned long r3)
+{
+    register unsigned long _r0 asm(SMC_ARG0) = r0;
+    register unsigned long _r1 asm(SMC_ARG1) = r1;
+    register unsigned long _r2 asm(SMC_ARG2) = r2;
+    register unsigned long _r3 asm(SMC_ARG3) = r3;
+
+    asm volatile(
+        __asmeq("%0", SMC_ARG0)
+        __asmeq("%1", SMC_ARG1)
+        __asmeq("%2", SMC_ARG2)
+        __asmeq("%3", SMC_ARG3)
+        __asmeq("%4", SMC_ARG0)
+        __asmeq("%5", SMC_ARG1)
+        __asmeq("%6", SMC_ARG2)
+        __asmeq("%7", SMC_ARG3)
+        SMC_ARCH_EXTENSION
+        "smc    #0" /* switch to secure world */
+        : "=r" (_r0), "=r" (_r1), "=r" (_r2), "=r" (_r3)
+        : "r" (_r0), "r" (_r1), "r" (_r2), "r" (_r3)
+        : SMC_REGISTERS_TRASHED);
+    return _r0;
+}
+
+static int32_t trusty_fast_call32(struct trusty_dev *dev, uint32_t smcnr,
+                                  uint32_t a0, uint32_t a1, uint32_t a2)
+{
+    trusty_assert(dev);
+    trusty_assert(SMC_IS_FASTCALL(smcnr));
+
+    return smc(smcnr, a0, a1, a2);
+}
+
+static unsigned long trusty_std_call_inner(struct trusty_dev *dev,
+                                           unsigned long smcnr,
+                                           unsigned long a0,
+                                           unsigned long a1,
+                                           unsigned long a2)
+{
+    unsigned long ret;
+    int retry = 5;
+
+    trusty_debug("%s(0x%lx 0x%lx 0x%lx 0x%lx)\n", __func__, smcnr, a0, a1, a2);
+
+    while (true) {
+        ret = smc(smcnr, a0, a1, a2);
+        while ((int32_t)ret == SM_ERR_FIQ_INTERRUPTED)
+            ret = smc(SMC_SC_RESTART_FIQ, 0, 0, 0);
+        if ((int)ret != SM_ERR_BUSY || !retry)
+            break;
+
+        trusty_debug("%s(0x%lx 0x%lx 0x%lx 0x%lx) returned busy, retry\n",
+                     __func__, smcnr, a0, a1, a2);
+
+        retry--;
+    }
+
+    return ret;
+}
+
+static unsigned long trusty_std_call_helper(struct trusty_dev *dev,
+                                            unsigned long smcnr,
+                                            unsigned long a0,
+                                            unsigned long a1,
+                                            unsigned long a2)
+{
+    unsigned long ret;
+    unsigned long irq_state;
+
+    while (true) {
+        trusty_local_irq_disable(&irq_state);
+        ret = trusty_std_call_inner(dev, smcnr, a0, a1, a2);
+        trusty_local_irq_restore(&irq_state);
+
+        if ((int)ret != SM_ERR_BUSY)
+            break;
+
+        trusty_idle(dev);
+    }
+
+    return ret;
+}
+
+static int32_t trusty_std_call32(struct trusty_dev *dev, uint32_t smcnr,
+                                 uint32_t a0, uint32_t a1, uint32_t a2)
+{
+    int ret;
+
+    trusty_assert(dev);
+    trusty_assert(!SMC_IS_FASTCALL(smcnr));
+
+    if (smcnr != SMC_SC_NOP) {
+        trusty_lock(dev);
+    }
+
+    trusty_debug("%s(0x%x 0x%x 0x%x 0x%x) started\n", __func__,
+                 smcnr, a0, a1, a2);
+
+    ret = trusty_std_call_helper(dev, smcnr, a0, a1, a2);
+    while (ret == SM_ERR_INTERRUPTED || ret == SM_ERR_CPU_IDLE) {
+        trusty_debug("%s(0x%x 0x%x 0x%x 0x%x) interrupted\n", __func__,
+                     smcnr, a0, a1, a2);
+        if (ret == SM_ERR_CPU_IDLE) {
+            trusty_idle(dev);
+        }
+        ret = trusty_std_call_helper(dev, SMC_SC_RESTART_LAST, 0, 0, 0);
+    }
+
+    trusty_debug("%s(0x%x 0x%x 0x%x 0x%x) returned 0x%x\n",
+                 __func__, smcnr, a0, a1, a2, ret);
+
+    if (smcnr != SMC_SC_NOP) {
+        trusty_unlock(dev);
+    }
+
+    return ret;
+}
+
+static int trusty_call32_mem_buf(struct trusty_dev *dev, uint32_t smcnr,
+                                 struct ns_mem_page_info *page, uint32_t size)
+{
+    trusty_assert(dev);
+    trusty_assert(page);
+
+    if (SMC_IS_FASTCALL(smcnr)) {
+        return trusty_fast_call32(dev, smcnr,
+                                  (uint32_t)page->attr,
+                                  (uint32_t)(page->attr >> 32), size);
+    } else {
+        return trusty_std_call32(dev, smcnr,
+                                 (uint32_t)page->attr,
+                                 (uint32_t)(page->attr >> 32), size);
+    }
+}
+
+int trusty_dev_init_ipc(struct trusty_dev *dev,
+                        struct ns_mem_page_info *buf, uint32_t buf_size)
+{
+    return trusty_call32_mem_buf(dev, SMC_SC_TRUSTY_IPC_CREATE_QL_DEV,
+                                 buf, buf_size);
+}
+
+int trusty_dev_exec_ipc(struct trusty_dev *dev,
+                        struct ns_mem_page_info *buf, uint32_t buf_size)
+{
+    return trusty_call32_mem_buf(dev, SMC_SC_TRUSTY_IPC_HANDLE_QL_DEV_CMD,
+                                 buf, buf_size);
+}
+
+int trusty_dev_shutdown_ipc(struct trusty_dev *dev,
+                            struct ns_mem_page_info *buf, uint32_t buf_size)
+{
+    return trusty_call32_mem_buf(dev, SMC_SC_TRUSTY_IPC_SHUTDOWN_QL_DEV,
+                                 buf, buf_size);
+}
+
+
+static int trusty_init_api_version(struct trusty_dev *dev)
+{
+    uint32_t api_version;
+
+    api_version = trusty_fast_call32(dev, SMC_FC_API_VERSION,
+                                     TRUSTY_API_VERSION_CURRENT, 0, 0);
+    if (api_version == SM_ERR_UNDEFINED_SMC)
+        api_version = 0;
+
+    if (api_version > TRUSTY_API_VERSION_CURRENT) {
+        trusty_error("unsupported trusty api version %u > %u\n",
+                     api_version, TRUSTY_API_VERSION_CURRENT);
+        return -1;
+    }
+
+    trusty_info("selected trusty api version: %u (requested %u)\n",
+                api_version, TRUSTY_API_VERSION_CURRENT);
+
+    dev->api_version = api_version;
+
+    return 0;
+}
+
+int trusty_dev_init(struct trusty_dev *dev, void *priv_data)
+{
+    trusty_assert(dev);
+
+    dev->priv_data = priv_data;
+    return trusty_init_api_version(dev);
+}
+
+int trusty_dev_shutdown(struct trusty_dev *dev)
+{
+    trusty_assert(dev);
+
+    dev->priv_data = NULL;
+    return 0;
+}
+
diff --git a/lib/trusty/ql-tipc/arch/arm/trusty_mem.c b/lib/trusty/ql-tipc/arch/arm/trusty_mem.c
new file mode 100644 (file)
index 0000000..e980b95
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <trusty/trusty_dev.h>
+#include <trusty/util.h>
+
+/* 48-bit physical address bits 47:12 */
+
+#define NS_PTE_PHYSADDR_SHIFT      12
+#define NS_PTE_PHYSADDR(pte)       ((pte) & 0xFFFFFFFFF000ULL)
+
+/* Access permissions bits 7:6
+ *      EL0     EL1
+ * 00   None    RW
+ * 01   RW      RW
+ * 10   None    RO
+ * 11   RO      RO
+ */
+#define NS_PTE_AP_SHIFT                    6
+#define NS_PTE_AP_MASK                     (0x3 << NS_PTE_AP_SHIFT)
+
+/* Memory type and cache attributes bits 55:48 */
+#define NS_PTE_MAIR_SHIFT                  48
+#define NS_PTE_MAIR_MASK                   (0x00FFULL << NS_PTE_MAIR_SHIFT)
+
+#define NS_PTE_MAIR_INNER_SHIFT            48
+#define NS_PTE_MAIR_INNER_MASK             (0x000FULL << NS_PTE_MAIR_INNER_SHIFT)
+
+#define NS_PTE_MAIR_OUTER_SHIFT            52
+#define NS_PTE_MAIR_OUTER_MASK             (0x000FULL << NS_PTE_MAIR_OUTER_SHIFT)
+
+/* Normal memory */
+#define NS_MAIR_NORMAL_CACHED_WB_RWA       0xFF /* inner and outer write back read/write allocate */
+#define NS_MAIR_NORMAL_CACHED_WT_RA        0xAA /* inner and outer write through read allocate */
+#define NS_MAIR_NORMAL_CACHED_WB_RA        0xEE /* inner and outer write back, read allocate */
+#define NS_MAIR_NORMAL_UNCACHED            0x44 /* uncached */
+
+/* Device memory */
+#define NS_MAIR_DEVICE_STRONGLY_ORDERED    0x00 /* nGnRnE (strongly ordered) */
+#define NS_MAIR_DEVICE                     0x04 /* nGnRE  (device) */
+#define NS_MAIR_DEVICE_GRE                 0x0C /* GRE */
+
+/* shareable attributes bits 9:8 */
+#define NS_PTE_SHAREABLE_SHIFT             8
+
+#define NS_NON_SHAREABLE                   0x0
+#define NS_OUTER_SHAREABLE                 0x2
+#define NS_INNER_SHAREABLE                 0x3
+
+typedef uintptr_t addr_t;
+typedef uintptr_t vaddr_t;
+typedef uintptr_t paddr_t;
+
+#if NS_ARCH_ARM64
+
+#define  PAR_F  (0x1 <<  0)
+
+/*
+ * ARM64
+ */
+static void arm64_write_ATS1E1W(uint64_t vaddr)
+{
+    __asm__ volatile("at S1E1W, %0" :: "r" (vaddr));
+    __asm__ volatile("isb" ::: "memory");
+}
+
+static uint64_t arm64_read_par64(void)
+{
+    uint64_t _val;
+    __asm__ volatile("mrs %0, par_el1" : "=r" (_val));
+    return _val;
+}
+
+
+static uint64_t va2par(vaddr_t va)
+{
+    uint64_t par;
+    unsigned long irq_state;
+
+    trusty_local_irq_disable(&irq_state);
+    arm64_write_ATS1E1W(va);
+    par = arm64_read_par64();
+    trusty_local_irq_restore(&irq_state);
+
+    return par;
+}
+
+static uint64_t par2attr(uint64_t par)
+{
+    uint64_t attr;
+
+    /* set phys address */
+    attr = NS_PTE_PHYSADDR(par);
+
+    /* cache attributes */
+    attr |= ((par >> 56) & 0xFF) << NS_PTE_MAIR_SHIFT;
+
+    /* shareable attributes */
+    attr |= ((par >> 7) & 0x03) << NS_PTE_SHAREABLE_SHIFT;
+
+    /* the memory is writable and accessible so leave AP field 0 */
+    attr |= 0x0 << NS_PTE_AP_SHIFT;
+
+    return attr;
+}
+
+#else
+
+#define  PAR_F     (0x1 <<  0)
+#define  PAR_SS    (0x1 <<  1)
+#define  PAR_SH    (0x1 <<  7)
+#define  PAR_NOS   (0x1 << 10)
+#define  PAR_LPAE  (0x1 << 11)
+
+/*
+ * ARM32
+ */
+static void arm_write_ATS1CPW(uint64_t vaddr)
+{
+    __asm__ volatile(
+        "mcr    p15, 0, %0, c7, c8, 1   \n"
+        : : "r"(vaddr)
+    );
+}
+
+static void arm_write_ATS1HW(uint64_t vaddr)
+{
+    __asm__ volatile(
+        "mcr    p15, 4, %0, c7, c8, 1   \n"
+        : : "r"(vaddr)
+    );
+}
+
+static uint64_t arm_read_par64(void)
+{
+    uint32_t lower, higher;
+
+    __asm__ volatile(
+        "mrc    p15, 0, %0, c7, c4, 0   \n"
+        "tst    %0, #(1 << 11)      @ LPAE / long desc format\n"
+        "moveq  %1, #0          \n"
+        "mrrcne p15, 0, %0, %1, c7  \n"
+         :"=r"(lower), "=r"(higher) : :
+    );
+
+    return ((uint64_t)higher << 32) | lower;
+}
+
+
+static uint8_t ish_to_mair[8] = {
+    0x04, /* 0b000 Non cacheble */
+    0x00, /* 0b001 Strongly ordered */
+    0xF0, /* 0b010 reserved */
+    0x04, /* 0b011 device */
+    0xF0, /* 0b100 reserved */
+    0x0F, /* 0b101 write back - write allocate */
+    0x0A, /* 0b110 write through */
+    0x0E, /* 0b111 write back - no write allocate */
+};
+
+static uint8_t osh_to_mair[4] = {
+    0x00, /* 0b00   Non-cacheable */
+    0x0F, /* 0b01   Write-back, Write-allocate */
+    0x0A, /* 0b10   Write-through, no Write-allocate */
+    0x0E, /* 0b11   Write-back, no Write-allocate */
+};
+
+static uint64_t par2attr(uint64_t par)
+{
+    uint64_t attr;
+
+    if (par & PAR_LPAE) {
+        /* set phys address */
+        attr = NS_PTE_PHYSADDR(par);
+
+        /* cache attributes */
+        attr |= ((par >> 56) & 0xFF) << NS_PTE_MAIR_SHIFT;
+
+        /* shareable attributes */
+        attr |= ((par >> 7) & 0x03) << NS_PTE_SHAREABLE_SHIFT;
+
+    } else {
+
+        /* set phys address */
+        trusty_assert((par & PAR_SS) == 0); /* super section not supported */
+        attr = NS_PTE_PHYSADDR(par);
+
+        /* cache attributes */
+        uint64_t inner = ((uint64_t)ish_to_mair[(par >> 4) & 0x7]) << NS_PTE_MAIR_INNER_SHIFT;
+        uint64_t outer = ((uint64_t)osh_to_mair[(par >> 2) & 0x3]) << NS_PTE_MAIR_OUTER_SHIFT;
+        uint64_t cache_attributes = (outer << 4) | inner;
+
+        /* Trusty does not support any kind of device memory, so we will force
+         * cache attributes to be NORMAL UNCACHED on the Trusty side.
+         */
+        if (cache_attributes == NS_MAIR_DEVICE_STRONGLY_ORDERED) {
+            attr |= ((uint64_t)NS_MAIR_NORMAL_UNCACHED << NS_PTE_MAIR_SHIFT);
+        } else {
+            attr |= inner;
+            attr |= outer;
+        }
+
+        /* shareable attributes */
+        if (par & PAR_SH) {
+            /* how to handle NOS bit ? */
+            attr |= ((uint64_t)NS_INNER_SHAREABLE) << NS_PTE_SHAREABLE_SHIFT;
+        } else {
+            attr |= ((uint64_t)NS_NON_SHAREABLE) << NS_PTE_SHAREABLE_SHIFT;
+        }
+    }
+
+    /* the memory is writable and accessible so leave AP field 0 */
+    attr |= 0x0 << NS_PTE_AP_SHIFT;
+
+    return attr;
+}
+
+static uint64_t va2par(vaddr_t va)
+{
+    uint64_t par;
+    unsigned long irq_state;
+
+    trusty_local_irq_disable(&irq_state);
+    arm_write_ATS1CPW(va); /* need to call the right one */
+    par = arm_read_par64();
+    trusty_local_irq_restore(&irq_state);
+
+    return par;
+}
+
+#endif /* ARM64 */
+
+
+int trusty_encode_page_info(struct ns_mem_page_info *inf, void *va)
+{
+    uint64_t par = va2par((vaddr_t)va);
+
+    if (par & PAR_F) {
+        return -1;
+    }
+
+    inf->attr = par2attr(par);
+
+    return 0;
+}
+
diff --git a/lib/trusty/ql-tipc/avb.c b/lib/trusty/ql-tipc/avb.c
new file mode 100644 (file)
index 0000000..ebbb38f
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <trusty/avb.h>
+#include <trusty/rpmb.h>
+#include <trusty/trusty_ipc.h>
+#include <trusty/util.h>
+
+#define LOCAL_LOG 0
+
+static bool initialized;
+static int avb_tipc_version = 1;
+static struct trusty_ipc_chan avb_chan;
+
+static int avb_send_request(struct avb_message *msg, void *req, size_t req_len)
+{
+    struct trusty_ipc_iovec req_iovs[2] = {
+        { .base = msg, .len = sizeof(*msg) },
+        { .base = req, .len = req_len },
+    };
+
+    return trusty_ipc_send(&avb_chan, req_iovs, req ? 2 : 1, true);
+}
+
+static int avb_read_response(struct avb_message *msg, uint32_t cmd, void *resp,
+                             size_t resp_len)
+{
+    int rc;
+    struct trusty_ipc_iovec resp_iovs[2] = {
+        { .base = msg, .len = sizeof(*msg) },
+        { .base = resp, .len = resp_len },
+    };
+
+    rc = trusty_ipc_recv(&avb_chan, resp_iovs, resp ? 2 : 1, true);
+    if (rc < 0) {
+        trusty_error("failed (%d) to recv response\n", rc);
+        return rc;
+    }
+    if (msg->cmd != (cmd | AVB_RESP_BIT)) {
+        trusty_error("malformed response\n");
+        return TRUSTY_ERR_GENERIC;
+    }
+    /* return payload size */
+    return rc - sizeof(*msg);
+}
+
+/*
+ * Convenience function to send a request to the AVB service and read the
+ * response.
+ *
+ * @cmd: the command
+ * @req: the request buffer
+ * @req_size: size of the request buffer
+ * @resp: the response buffer
+ * @resp_size_p: pointer to the size of the response buffer. changed to the
+                 actual size of the response read from the secure side
+ * @handle_rpmb: true if the request is expected to invoke RPMB callbacks
+ */
+static int avb_do_tipc(uint32_t cmd, void *req, uint32_t req_size, void *resp,
+                       uint32_t *resp_size_p, bool handle_rpmb)
+{
+    int rc;
+    struct avb_message msg = { .cmd = cmd };
+
+    if (!initialized && cmd != AVB_GET_VERSION) {
+        trusty_error("%s: AVB TIPC client not initialized\n", __func__);
+        return TRUSTY_ERR_GENERIC;
+    }
+
+    rc = avb_send_request(&msg, req, req_size);
+    if (rc < 0) {
+        trusty_error("%s: failed (%d) to send AVB request\n", __func__, rc);
+        return rc;
+    }
+
+    if (handle_rpmb) {
+        /* handle any incoming RPMB requests */
+        rc = rpmb_storage_proxy_poll();
+        if (rc < 0) {
+            trusty_error("%s: failed (%d) to get RPMB requests\n", __func__,
+                         rc);
+            return rc;
+        }
+    }
+
+    uint32_t resp_size = resp_size_p ? *resp_size_p : 0;
+    rc = avb_read_response(&msg, cmd, resp, resp_size);
+    if (rc < 0) {
+        trusty_error("%s: failed (%d) to read AVB response\n", __func__, rc);
+        return rc;
+    }
+    /* change response size to actual response size */
+    if (resp_size_p && rc != *resp_size_p) {
+        *resp_size_p = rc;
+    }
+    if (msg.result != AVB_ERROR_NONE) {
+        trusty_error("%s: AVB service returned error (%d)\n", __func__,
+                     msg.result);
+        return TRUSTY_ERR_GENERIC;
+    }
+    return TRUSTY_ERR_NONE;
+}
+
+static int avb_get_version(uint32_t *version)
+{
+    int rc;
+    struct avb_get_version_resp resp;
+    uint32_t resp_size = sizeof(resp);
+
+    rc = avb_do_tipc(AVB_GET_VERSION, NULL, 0, &resp, &resp_size, false);
+
+    *version = resp.version;
+    return rc;
+}
+
+
+int avb_tipc_init(struct trusty_ipc_dev *dev)
+{
+    int rc;
+    uint32_t version = 0;
+
+    trusty_assert(dev);
+    trusty_assert(!initialized);
+
+    trusty_ipc_chan_init(&avb_chan, dev);
+    trusty_debug("Connecting to AVB service\n");
+
+    /* connect to AVB service and wait for connect to complete */
+    rc = trusty_ipc_connect(&avb_chan, AVB_PORT, true);
+    if (rc < 0) {
+        trusty_error("failed (%d) to connect to '%s'\n", rc, AVB_PORT);
+        return rc;
+    }
+
+    /* check for version mismatch */
+    rc = avb_get_version(&version);
+    if (rc != 0) {
+        trusty_error("Error getting version");
+        return TRUSTY_ERR_GENERIC;
+    }
+    if (version != avb_tipc_version) {
+        trusty_error("AVB TIPC version mismatch. Expected %u, received %u\n",
+                     avb_tipc_version, version);
+        return TRUSTY_ERR_GENERIC;
+    }
+
+    /* mark as initialized */
+    initialized = true;
+
+    return TRUSTY_ERR_NONE;
+}
+
+void avb_tipc_shutdown(struct trusty_ipc_dev *dev)
+{
+    if (!initialized)
+        return; /* nothing to do */
+
+    /* close channel */
+    trusty_ipc_close(&avb_chan);
+
+    initialized = false;
+}
+
+int trusty_read_rollback_index(uint32_t slot, uint64_t *value)
+{
+    int rc;
+    struct avb_rollback_req req = { .slot = slot, .value = 0 };
+    struct avb_rollback_resp resp;
+    uint32_t resp_size = sizeof(resp);
+
+    rc = avb_do_tipc(READ_ROLLBACK_INDEX, &req, sizeof(req), &resp,
+                     &resp_size, true);
+
+    *value = resp.value;
+    return rc;
+}
+
+int trusty_write_rollback_index(uint32_t slot, uint64_t value)
+{
+    int rc;
+    struct avb_rollback_req req = { .slot = slot, .value = value };
+    struct avb_rollback_resp resp;
+    uint32_t resp_size = sizeof(resp);
+
+    rc = avb_do_tipc(WRITE_ROLLBACK_INDEX, &req, sizeof(req), &resp,
+                     &resp_size, true);
+    return rc;
+}
+
+int trusty_read_permanent_attributes(uint8_t *attributes, uint32_t size)
+{
+    uint8_t resp_buf[AVB_MAX_BUFFER_LENGTH];
+    uint32_t resp_size = AVB_MAX_BUFFER_LENGTH;
+    int rc = avb_do_tipc(READ_PERMANENT_ATTRIBUTES, NULL, 0, resp_buf,
+                         &resp_size, true);
+    if (rc != 0) {
+        return rc;
+    }
+    /* ensure caller passed size matches size returned by Trusty */
+    if (size != resp_size) {
+        return TRUSTY_ERR_INVALID_ARGS;
+    }
+    trusty_memcpy(attributes, resp_buf, resp_size);
+    return rc;
+}
+
+int trusty_write_permanent_attributes(uint8_t *attributes, uint32_t size)
+{
+    return avb_do_tipc(WRITE_PERMANENT_ATTRIBUTES, attributes, size, NULL, NULL,
+                       true);
+}
+
+int trusty_read_lock_state(uint8_t *lock_state)
+{
+    uint32_t resp_size = sizeof(*lock_state);
+    return avb_do_tipc(READ_LOCK_STATE, NULL, 0, lock_state,
+                       &resp_size, true);
+}
+
+int trusty_write_lock_state(uint8_t lock_state)
+{
+    return avb_do_tipc(WRITE_LOCK_STATE, &lock_state, sizeof(lock_state), NULL,
+                       NULL, true);
+}
+
+int trusty_lock_boot_state(void)
+{
+    return avb_do_tipc(LOCK_BOOT_STATE, NULL, 0, NULL, NULL, false);
+}
diff --git a/lib/trusty/ql-tipc/ipc.c b/lib/trusty/ql-tipc/ipc.c
new file mode 100644 (file)
index 0000000..95c0ee6
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <trusty/trusty_ipc.h>
+#include <trusty/util.h>
+
+#define LOCAL_LOG 0
+
+static int sync_ipc_on_connect_complete(struct trusty_ipc_chan *chan)
+{
+    trusty_assert(chan);
+
+    chan->complete = 1;
+    return TRUSTY_EVENT_HANDLED;
+}
+
+static int sync_ipc_on_message(struct trusty_ipc_chan *chan)
+{
+    trusty_assert(chan);
+
+    chan->complete = 1;
+    return TRUSTY_EVENT_HANDLED;
+}
+
+static int sync_ipc_on_disconnect(struct trusty_ipc_chan *chan)
+{
+    trusty_assert(chan);
+
+    chan->complete = TRUSTY_ERR_CHANNEL_CLOSED;
+    return TRUSTY_EVENT_HANDLED;
+}
+
+static int wait_for_complete(struct trusty_ipc_chan *chan)
+{
+    int rc;
+
+    chan->complete = 0;
+    for (;;) {
+        rc = trusty_ipc_poll_for_event(chan);
+        if (rc < 0)
+            return rc;
+
+        if (chan->complete)
+            break;
+
+        trusty_ipc_dev_idle(chan->dev);
+    }
+
+    return chan->complete;
+}
+
+static int wait_for_connect(struct trusty_ipc_chan *chan)
+{
+    trusty_debug("%s: chan %x: waiting for connect\n", __func__,
+                 (int)chan->handle);
+    return wait_for_complete(chan);
+}
+
+static int wait_for_send(struct trusty_ipc_chan *chan)
+{
+    trusty_debug("%s: chan %d: waiting for send\n", __func__, chan->handle);
+    return wait_for_complete(chan);
+}
+
+static int wait_for_reply(struct trusty_ipc_chan *chan)
+{
+    trusty_debug("%s: chan %d: waiting for reply\n", __func__, chan->handle);
+    return wait_for_complete(chan);
+}
+
+static struct trusty_ipc_ops sync_ipc_ops = {
+    .on_connect_complete = sync_ipc_on_connect_complete,
+    .on_message = sync_ipc_on_message,
+    .on_disconnect = sync_ipc_on_disconnect,
+};
+
+void trusty_ipc_chan_init(struct trusty_ipc_chan *chan,
+                          struct trusty_ipc_dev *dev)
+{
+    trusty_assert(chan);
+    trusty_assert(dev);
+
+    trusty_memset(chan, 0, sizeof(*chan));
+
+    chan->handle = INVALID_IPC_HANDLE;
+    chan->dev = dev;
+    chan->ops = &sync_ipc_ops;
+    chan->ops_ctx = chan;
+}
+
+int trusty_ipc_connect(struct trusty_ipc_chan *chan, const char *port,
+                       bool wait)
+{
+    int rc;
+
+    trusty_assert(chan);
+    trusty_assert(chan->dev);
+    trusty_assert(chan->handle == INVALID_IPC_HANDLE);
+    trusty_assert(port);
+
+    rc = trusty_ipc_dev_connect(chan->dev, port, (uint64_t)(uintptr_t)chan);
+    if (rc < 0) {
+        trusty_error("%s: init connection failed (%d)\n", __func__, rc);
+        return rc;
+    }
+    chan->handle = (handle_t)rc;
+    trusty_debug("chan->handle: %x\n", (int)chan->handle);
+
+    /* got valid channel */
+    if (wait) {
+        rc = wait_for_connect(chan);
+        if (rc < 0) {
+            trusty_error("%s: wait for connect failed (%d)\n", __func__, rc);
+            trusty_ipc_close(chan);
+        }
+    }
+
+    return rc;
+}
+
+int trusty_ipc_close(struct trusty_ipc_chan *chan)
+{
+    int rc;
+
+    trusty_assert(chan);
+
+    rc = trusty_ipc_dev_close(chan->dev, chan->handle);
+    chan->handle = INVALID_IPC_HANDLE;
+
+    return rc;
+}
+
+int trusty_ipc_send(struct trusty_ipc_chan *chan,
+                    const struct trusty_ipc_iovec *iovs, size_t iovs_cnt,
+                    bool wait)
+{
+    int rc;
+
+    trusty_assert(chan);
+    trusty_assert(chan->dev);
+    trusty_assert(chan->handle);
+
+Again:
+    rc = trusty_ipc_dev_send(chan->dev, chan->handle, iovs, iovs_cnt);
+    if (rc == TRUSTY_ERR_SEND_BLOCKED) {
+        if (wait) {
+            rc = wait_for_send(chan);
+            if (rc < 0) {
+                trusty_error("%s: wait to send failed (%d)\n", __func__, rc);
+                return rc;
+            }
+            goto Again;
+        }
+    }
+    return rc;
+}
+
+int trusty_ipc_recv(struct trusty_ipc_chan *chan,
+                    const struct trusty_ipc_iovec *iovs, size_t iovs_cnt,
+                    bool wait)
+{
+    int rc;
+    trusty_assert(chan);
+    trusty_assert(chan->dev);
+    trusty_assert(chan->handle);
+
+Again:
+    rc = trusty_ipc_dev_recv(chan->dev, chan->handle, iovs, iovs_cnt);
+    if (rc == TRUSTY_ERR_NO_MSG) {
+        if (wait) {
+            rc = wait_for_reply(chan);
+            if (rc < 0) {
+                trusty_error("%s: wait to reply failed (%d)\n", __func__, rc);
+                return rc;
+            }
+            goto Again;
+        }
+    }
+
+    return rc;
+}
+
+int trusty_ipc_poll_for_event(struct trusty_ipc_chan *chan)
+{
+    int rc;
+    struct trusty_ipc_event evt;
+    trusty_assert(chan && chan->ops);
+
+    rc = trusty_ipc_dev_get_event(chan->dev, chan->handle, &evt);
+    if (rc) {
+        trusty_error("%s: get event failed (%d)\n", __func__, rc);
+        return rc;
+    }
+
+    /* check if we have an event */
+    if (!evt.event) {
+        trusty_debug("%s: no event\n", __func__);
+        return TRUSTY_EVENT_NONE;
+    }
+
+    /* check if we have raw event handler */
+    if (chan->ops->on_raw_event) {
+        /* invoke it first */
+        rc = chan->ops->on_raw_event(chan, &evt);
+        if (rc < 0) {
+            trusty_error("%s: chan %d: raw event cb returned (%d)\n", __func__,
+                         chan->handle, rc);
+            return rc;
+        }
+        if (rc > 0)
+            return rc; /* handled */
+    }
+
+    if (evt.event & IPC_HANDLE_POLL_ERROR) {
+        /* something is very wrong */
+        trusty_error("%s: chan %d: chan in error state\n", __func__,
+                     chan->handle);
+        return TRUSTY_ERR_GENERIC;
+    }
+
+    /* send unblocked should be handled first as it is edge truggered event */
+    if (evt.event & IPC_HANDLE_POLL_SEND_UNBLOCKED) {
+        if (chan->ops->on_send_unblocked) {
+            rc = chan->ops->on_send_unblocked(chan);
+            if (rc < 0) {
+                trusty_error("%s: chan %d: send unblocked cb returned (%d)\n",
+                             __func__, chan->handle, rc);
+                return rc;
+            }
+            if (rc > 0)
+                return rc; /* handled */
+        }
+    }
+
+    /* check for connection complete */
+    if (evt.event & IPC_HANDLE_POLL_READY) {
+        if (chan->ops->on_connect_complete) {
+            rc = chan->ops->on_connect_complete(chan);
+            if (rc < 0) {
+                trusty_error("%s: chan %d: ready cb returned (%d)\n", __func__,
+                             chan->handle, rc);
+                return rc;
+            }
+            if (rc > 0)
+                return rc; /* handled */
+        }
+    }
+
+    /* check for incomming messages */
+    if (evt.event & IPC_HANDLE_POLL_MSG) {
+        if (chan->ops->on_message) {
+            rc = chan->ops->on_message(chan);
+            if (rc < 0) {
+                trusty_error("%s: chan %d: msg cb returned (%d)\n", __func__,
+                             chan->handle, rc);
+                return rc;
+            }
+            if (rc > 0)
+                return rc;
+        }
+    }
+
+    /* check for hangups */
+    if (evt.event & IPC_HANDLE_POLL_HUP) {
+        if (chan->ops->on_disconnect) {
+            rc = chan->ops->on_disconnect(chan);
+            if (rc < 0) {
+                trusty_error("%s: chan %d: hup cb returned (%d)\n", __func__,
+                             chan->handle, rc);
+                return rc;
+            }
+            if (rc > 0)
+                return rc;
+        }
+    }
+
+    return TRUSTY_ERR_NONE;
+}
diff --git a/lib/trusty/ql-tipc/ipc_dev.c b/lib/trusty/ql-tipc/ipc_dev.c
new file mode 100644 (file)
index 0000000..5924d44
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <trusty/trusty_dev.h>
+#include <trusty/trusty_ipc.h>
+#include <trusty/util.h>
+
+#define NS_PTE_PHYSADDR(pte)       ((pte) & 0xFFFFFFFFF000ULL)
+
+#define QL_TIPC_DEV_RESP     0x8000
+#define QL_TIPC_DEV_CONNECT     0x1
+#define QL_TIPC_DEV_GET_EVENT   0x2
+#define QL_TIPC_DEV_SEND        0x3
+#define QL_TIPC_DEV_RECV        0x4
+#define QL_TIPC_DEV_DISCONNECT  0x5
+
+#define LOCAL_LOG 0
+
+struct trusty_ipc_cmd_hdr {
+    uint16_t opcode;
+    uint16_t flags;
+    uint32_t status;
+    uint32_t handle;
+    uint32_t payload_len;
+    uint8_t  payload[0];
+};
+
+struct trusty_ipc_wait_req {
+    uint64_t reserved;
+};
+
+struct trusty_ipc_connect_req {
+    uint64_t cookie;
+    uint64_t reserved;
+    uint8_t  name[0];
+};
+
+static size_t iovec_size(const struct trusty_ipc_iovec *iovs, size_t iovs_cnt)
+{
+    size_t i;
+    size_t cb = 0;
+
+    trusty_assert(iovs);
+
+    for (i = 0; i < iovs_cnt; i++) {
+        cb += iovs[i].len;
+    }
+
+    return cb;
+}
+
+static size_t iovec_to_buf(void *buf, size_t buf_len,
+                           const struct trusty_ipc_iovec *iovs, size_t iovs_cnt)
+{
+    size_t i;
+    size_t buf_pos = 0;
+
+    trusty_assert(iovs);
+
+    for (i = 0; i < iovs_cnt; i++) {
+        size_t to_copy = (size_t)iovs[i].len;
+
+        if (!to_copy)
+            continue;
+
+        if (to_copy > buf_len)
+            to_copy = buf_len;
+
+        trusty_memcpy((uint8_t *)buf + buf_pos, iovs[i].base, to_copy);
+
+        buf_pos += to_copy;
+        buf_len -= to_copy;
+
+        if (buf_len == 0)
+            break;
+    }
+
+    return buf_pos;
+}
+
+static size_t buf_to_iovec(const struct trusty_ipc_iovec *iovs, size_t iovs_cnt,
+                           const void *buf, size_t buf_len)
+{
+    size_t i;
+    size_t copied = 0;
+    const uint8_t *buf_ptr = buf;
+
+    trusty_assert(buf_ptr);
+    trusty_assert(iovs);
+
+    if (iovs_cnt == 0 || buf_len == 0)
+        return 0;
+
+    for (i = 0; i < iovs_cnt; i++) {
+        size_t to_copy = buf_len;
+
+        if (to_copy > iovs[i].len)
+            to_copy = iovs[i].len;
+
+        if (!to_copy)
+            continue;
+
+        trusty_memcpy(iovs[i].base, buf_ptr, to_copy);
+
+        copied  += to_copy;
+        buf_ptr += to_copy;
+        buf_len -= to_copy;
+
+        if (buf_len == 0)
+            break;
+    }
+
+    return copied;
+}
+
+static int check_response(struct trusty_ipc_dev *dev,
+                          volatile struct trusty_ipc_cmd_hdr *hdr, uint16_t cmd)
+{
+    if (hdr->opcode != (cmd | QL_TIPC_DEV_RESP)) {
+        /* malformed response */
+        trusty_error("%s: malformed response cmd: 0x%x\n",
+                     __func__, hdr->opcode);
+        return TRUSTY_ERR_SECOS_ERR;
+    }
+
+    if (hdr->status) {
+        /* secure OS responded with error: TODO need error code */
+        trusty_error("%s: cmd 0x%x: status = %d\n",
+                     __func__, hdr->opcode, hdr->status);
+        return TRUSTY_ERR_SECOS_ERR;
+    }
+
+    return TRUSTY_ERR_NONE;
+}
+
+int trusty_ipc_dev_create(struct trusty_ipc_dev **idev,
+                          struct trusty_dev *tdev,
+                          size_t buf_size)
+{
+    int rc;
+    struct trusty_ipc_dev *dev;
+
+    trusty_assert(idev);
+
+    trusty_debug("%s: Create new Trusty IPC device (%zu)\n", __func__, buf_size);
+
+    /* allocate device context */
+    dev = trusty_calloc(1, sizeof(*dev));
+    if (!dev) {
+        trusty_error("%s: failed to allocate Trusty IPC device\n", __func__);
+        return TRUSTY_ERR_NO_MEMORY;
+    }
+    dev->tdev = tdev;
+
+    /* allocate shared buffer */
+    dev->buf_size = buf_size;
+    dev->buf_vaddr = trusty_membuf_alloc(&dev->buf_ns, buf_size);
+    if (!dev->buf_vaddr) {
+        trusty_error("%s: failed to allocate shared memory\n", __func__);
+        rc = TRUSTY_ERR_NO_MEMORY;
+        goto err_alloc_membuf;
+    }
+
+    /* call secure OS to register shared buffer */
+    rc = trusty_dev_init_ipc(dev->tdev, &dev->buf_ns, dev->buf_size);
+    if (rc != 0) {
+        trusty_error("%s: failed (%d) to create Trusty IPC device\n",
+                     __func__, rc);
+        rc = TRUSTY_ERR_SECOS_ERR;
+        goto err_create_sec_dev;
+    }
+
+    trusty_debug("%s: new Trusty IPC device (%p)\n", __func__, dev);
+
+    *idev = dev;
+    return TRUSTY_ERR_NONE;
+
+err_create_sec_dev:
+err_alloc_membuf:
+    trusty_membuf_free(dev->buf_vaddr);
+    trusty_free(dev);
+    return rc;
+}
+
+void trusty_ipc_dev_shutdown(struct trusty_ipc_dev *dev)
+{
+    int rc;
+    trusty_assert(dev);
+
+    trusty_debug("%s: shutting down Trusty IPC device (%p)\n", __func__, dev);
+
+    /* shutdown Trusty IPC device */
+    rc = trusty_dev_shutdown_ipc(dev->tdev, &dev->buf_ns, dev->buf_size);
+    trusty_assert(!rc);
+    if (rc != 0) {
+        trusty_error("%s: failed (%d) to shutdown Trusty IPC device\n",
+                     __func__, rc);
+    }
+    trusty_membuf_free(dev->buf_vaddr);
+    trusty_free(dev);
+}
+
+int trusty_ipc_dev_connect(struct trusty_ipc_dev *dev, const char *port,
+                           uint64_t cookie)
+{
+    int rc;
+    size_t port_len;
+    volatile struct trusty_ipc_cmd_hdr *cmd;
+    struct trusty_ipc_connect_req *req;
+
+    trusty_assert(dev);
+    trusty_assert(port);
+
+    trusty_debug("%s: connecting to '%s'\n", __func__, port);
+
+    /* check port name length */
+    port_len = trusty_strlen(port) + 1;
+    if (port_len > (dev->buf_size - sizeof(*cmd) + sizeof(*req))) {
+        /* it would not fit into buffer */
+        trusty_error("%s: port name is too long (%zu)\n", __func__, port_len);
+        return TRUSTY_ERR_INVALID_ARGS;
+    }
+
+    /* prepare command */
+    cmd = dev->buf_vaddr;
+    trusty_memset((void *)cmd, 0, sizeof(*cmd));
+    cmd->opcode = QL_TIPC_DEV_CONNECT;
+
+    /* prepare payload  */
+    req = (struct trusty_ipc_connect_req *)cmd->payload;
+    trusty_memset((void *)req, 0, sizeof(*req));
+    req->cookie = cookie;
+    trusty_strcpy((char *)req->name, port);
+    cmd->payload_len = sizeof(*req) + port_len;
+
+    /* call secure os */
+    rc = trusty_dev_exec_ipc(dev->tdev,
+                             &dev->buf_ns, sizeof(*cmd) + cmd->payload_len);
+    if (rc) {
+        /* secure OS returned an error */
+        trusty_error("%s: secure OS returned (%d)\n", __func__, rc);
+        return TRUSTY_ERR_SECOS_ERR;
+    }
+
+    rc = check_response(dev, cmd, QL_TIPC_DEV_CONNECT);
+    if (rc) {
+        trusty_error("%s: connect cmd failed (%d)\n", __func__, rc);
+        return rc;
+    }
+
+    /* success */
+    return cmd->handle;
+}
+
+int trusty_ipc_dev_close(struct trusty_ipc_dev *dev, handle_t handle)
+{
+    int rc;
+    volatile struct trusty_ipc_cmd_hdr *cmd;
+
+    trusty_assert(dev);
+
+    trusty_debug("%s: chan %d: closing\n", __func__, handle);
+
+    /* prepare command */
+    cmd = dev->buf_vaddr;
+    trusty_memset((void *)cmd, 0, sizeof(*cmd));
+    cmd->opcode = QL_TIPC_DEV_DISCONNECT;
+    cmd->handle = handle;
+    /* no payload */
+
+    /* call into secure os */
+    rc = trusty_dev_exec_ipc(dev->tdev,
+                             &dev->buf_ns, sizeof(*cmd) + cmd->payload_len);
+    if (rc) {
+        trusty_error("%s: secure OS returned (%d)\n", __func__, rc);
+        return TRUSTY_ERR_SECOS_ERR;
+    }
+
+    rc = check_response(dev, cmd, QL_TIPC_DEV_DISCONNECT);
+    if (rc) {
+        trusty_error("%s: disconnect cmd failed (%d)\n", __func__, rc);
+        return rc;
+    }
+
+    trusty_debug("%s: chan %d: closed\n", __func__, handle);
+
+    return TRUSTY_ERR_NONE;
+}
+
+int trusty_ipc_dev_get_event(struct trusty_ipc_dev *dev, handle_t chan,
+                             struct trusty_ipc_event *event)
+{
+    int rc;
+    volatile struct trusty_ipc_cmd_hdr *cmd;
+
+    trusty_assert(dev);
+    trusty_assert(event);
+
+    /* prepare command */
+    cmd = dev->buf_vaddr;
+    trusty_memset((void *)cmd, 0, sizeof(*cmd));
+    cmd->opcode = QL_TIPC_DEV_GET_EVENT;
+    cmd->handle = chan;
+
+    /* prepare payload  */
+    trusty_memset((void *)cmd->payload, 0, sizeof(struct trusty_ipc_wait_req));
+    cmd->payload_len = sizeof(struct trusty_ipc_wait_req);
+
+    /* call into secure os */
+    rc = trusty_dev_exec_ipc(dev->tdev,
+                             &dev->buf_ns, sizeof(*cmd) + cmd->payload_len);
+    if (rc) {
+        trusty_error("%s: secure OS returned (%d)\n", __func__, rc);
+        return TRUSTY_ERR_SECOS_ERR;
+    }
+
+    rc = check_response(dev, cmd, QL_TIPC_DEV_GET_EVENT);
+    if (rc) {
+        trusty_error("%s: get event cmd failed (%d)\n", __func__, rc);
+        return rc;
+    }
+
+    if ((size_t)cmd->payload_len < sizeof(*event)) {
+        trusty_error("%s: invalid response length (%zd)\n",
+                     __func__, (size_t)cmd->payload_len);
+        return TRUSTY_ERR_SECOS_ERR;
+    }
+
+    /* copy out event */
+    trusty_memcpy(event, (const void *)cmd->payload, sizeof(*event));
+    return TRUSTY_ERR_NONE;
+}
+
+int trusty_ipc_dev_send(struct trusty_ipc_dev *dev, handle_t chan,
+                        const struct trusty_ipc_iovec *iovs, size_t iovs_cnt)
+{
+    int rc;
+    size_t msg_size;
+    volatile struct trusty_ipc_cmd_hdr *cmd;
+
+    trusty_assert(dev);
+    /* calc message length */
+    msg_size = iovec_size(iovs, iovs_cnt);
+    if (msg_size > dev->buf_size - sizeof(*cmd)) {
+        /* msg is too big to fit provided buffer */
+        trusty_error("%s: chan %d: msg is too long (%zu)\n", __func__,
+                     chan, msg_size);
+        return TRUSTY_ERR_MSG_TOO_BIG;
+    }
+
+    /* prepare command */
+    cmd = dev->buf_vaddr;
+    trusty_memset((void *)cmd, 0, sizeof(*cmd));
+    cmd->opcode = QL_TIPC_DEV_SEND;
+    cmd->handle = chan;
+
+    /* copy in message data */
+    cmd->payload_len = (uint32_t)msg_size;
+    msg_size = iovec_to_buf(dev->buf_vaddr + sizeof(*cmd), dev->buf_size - sizeof(*cmd),
+                          iovs,  iovs_cnt);
+    trusty_assert(msg_size == (size_t)cmd->payload_len);
+
+    /* call into secure os */
+    rc = trusty_dev_exec_ipc(dev->tdev,
+                             &dev->buf_ns, sizeof(*cmd) + cmd->payload_len);
+    if (rc < 0) {
+        trusty_error("%s: secure OS returned (%d)\n", __func__, rc);
+        return TRUSTY_ERR_SECOS_ERR;
+    }
+
+    rc = check_response(dev, cmd, QL_TIPC_DEV_SEND);
+    if (rc) {
+        trusty_error("%s: send msg failed (%d)\n", __func__, rc);
+    }
+
+    return rc;
+}
+
+
+int trusty_ipc_dev_recv(struct trusty_ipc_dev *dev, handle_t chan,
+                        const struct trusty_ipc_iovec *iovs, size_t iovs_cnt)
+{
+    int rc;
+    size_t copied;
+    volatile struct trusty_ipc_cmd_hdr *cmd;
+
+    trusty_assert(dev);
+
+    /* prepare command */
+    cmd = dev->buf_vaddr;
+    trusty_memset((void *)cmd, 0, sizeof(*cmd));
+    cmd->opcode = QL_TIPC_DEV_RECV;
+    cmd->handle = chan;
+    /* no payload */
+
+    /* call into secure os */
+    rc = trusty_dev_exec_ipc(dev->tdev,
+                             &dev->buf_ns, sizeof(*cmd) + cmd->payload_len);
+    if (rc < 0) {
+        trusty_error("%s: secure OS returned (%d)\n", __func__, rc);
+        return TRUSTY_ERR_SECOS_ERR;
+    }
+
+    rc = check_response(dev, cmd, QL_TIPC_DEV_RECV);
+    if (rc) {
+        trusty_error("%s: recv cmd failed (%d)\n", __func__, rc);
+        return rc;
+    }
+
+    /* copy data out to proper destination */
+    copied = buf_to_iovec(iovs, iovs_cnt,
+                          (const void *)cmd->payload, cmd->payload_len);
+    if (copied != (size_t)cmd->payload_len) {
+        /* msg is too big to fit provided buffer */
+        trusty_error("%s: chan %d: buffer too small (%zu vs. %zu)\n",
+                     __func__, chan, copied, (size_t)cmd->payload_len);
+        return TRUSTY_ERR_MSG_TOO_BIG;
+    }
+
+    return (int)copied;
+}
+
+void trusty_ipc_dev_idle(struct trusty_ipc_dev *dev)
+{
+    trusty_idle(dev->tdev);
+}
+
diff --git a/lib/trusty/ql-tipc/keymaster.c b/lib/trusty/ql-tipc/keymaster.c
new file mode 100644 (file)
index 0000000..d3c0be4
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <trusty/keymaster.h>
+#include <trusty/rpmb.h>
+#include <trusty/trusty_ipc.h>
+#include <trusty/util.h>
+
+#define LOCAL_LOG 0
+
+static struct trusty_ipc_chan km_chan;
+static bool initialized;
+static int trusty_km_version = 2;
+
+static int km_send_request(struct keymaster_message *msg, void *req,
+                           size_t req_len)
+{
+    int num_iovecs = req ? 2 : 1;
+
+    struct trusty_ipc_iovec req_iovs[2] = {
+        { .base = msg, .len = sizeof(*msg) },
+        { .base = req, .len = req_len },
+    };
+
+    return trusty_ipc_send(&km_chan, req_iovs, num_iovecs, true);
+}
+
+static int km_read_response(struct keymaster_message *msg, uint32_t cmd,
+                            void *resp, size_t resp_len)
+{
+    int rc = TRUSTY_ERR_GENERIC;
+    struct trusty_ipc_iovec resp_iovs[2] = {
+        { .base = msg, .len = sizeof(*msg) },
+        { .base = resp, .len = resp_len },
+    };
+
+    rc = trusty_ipc_recv(&km_chan, resp_iovs, resp ? 2 : 1, true);
+    if (rc < 0) {
+        trusty_error("failed (%d) to recv response\n", rc);
+        return rc;
+    }
+    if ((msg->cmd & ~(KEYMASTER_STOP_BIT)) != (cmd | KEYMASTER_RESP_BIT)) {
+        trusty_error("malformed response\n");
+        return TRUSTY_ERR_GENERIC;
+    }
+
+    return rc;
+}
+
+static int km_do_tipc(uint32_t cmd, void *req, uint32_t req_len,
+                      bool handle_rpmb)
+{
+    int rc = TRUSTY_ERR_GENERIC;
+    struct keymaster_message msg = { .cmd = cmd };
+    struct km_no_response resp;
+
+    rc = km_send_request(&msg, req, req_len);
+    if (rc < 0) {
+        trusty_error("%s: failed (%d) to send km request\n", __func__, rc);
+        return rc;
+    }
+
+    if (handle_rpmb) {
+        /* handle any incoming RPMB requests */
+        rc = rpmb_storage_proxy_poll();
+        if (rc < 0) {
+            trusty_error("%s: failed (%d) to get RPMB requests\n", __func__,
+                         rc);
+            return rc;
+        }
+    }
+
+    rc = km_read_response(&msg, cmd, &resp, sizeof(resp));
+    if (rc < 0) {
+        trusty_error("%s: failed (%d) to read km response\n", __func__, rc);
+        return rc;
+    }
+    return resp.error;
+}
+
+static int32_t MessageVersion(uint8_t major_ver, uint8_t minor_ver,
+                              uint8_t subminor_ver) {
+    int32_t message_version = -1;
+    switch (major_ver) {
+    case 0:
+        message_version = 0;
+        break;
+    case 1:
+        switch (minor_ver) {
+        case 0:
+            message_version = 1;
+            break;
+        case 1:
+            message_version = 2;
+            break;
+        }
+        break;
+    case 2:
+        message_version = 3;
+        break;
+    }
+    return message_version;
+}
+
+static int km_get_version(int32_t *version)
+{
+    int rc = TRUSTY_ERR_GENERIC;
+    struct keymaster_message msg = { .cmd = KM_GET_VERSION };
+    struct km_get_version_resp resp;
+
+    rc = km_send_request(&msg, NULL, 0);
+    if (rc < 0) {
+        trusty_error("failed to send km version request", rc);
+        return rc;
+    }
+
+    rc = km_read_response(&msg, KM_GET_VERSION, &resp, sizeof(resp));
+    if (rc < 0) {
+        trusty_error("%s: failed (%d) to read km response\n", __func__, rc);
+        return rc;
+    }
+
+    *version = MessageVersion(resp.major_ver, resp.minor_ver,
+                              resp.subminor_ver);
+    return rc;
+}
+
+int km_tipc_init(struct trusty_ipc_dev *dev)
+{
+    int rc = TRUSTY_ERR_GENERIC;
+
+    trusty_assert(dev);
+
+    trusty_ipc_chan_init(&km_chan, dev);
+    trusty_debug("Connecting to Keymaster service\n");
+
+    /* connect to km service and wait for connect to complete */
+    rc = trusty_ipc_connect(&km_chan, KEYMASTER_PORT, true);
+    if (rc < 0) {
+        trusty_error("failed (%d) to connect to '%s'\n", rc, KEYMASTER_PORT);
+        return rc;
+    }
+
+    int32_t version = -1;
+    rc = km_get_version(&version);
+    if (rc < 0) {
+        trusty_error("failed (%d) to get keymaster version\n", rc);
+        return rc;
+    }
+    if (version < trusty_km_version) {
+        trusty_error("keymaster version mismatch. Expected %d, received %d\n",
+                     trusty_km_version, version);
+        return TRUSTY_ERR_GENERIC;
+    }
+
+    return TRUSTY_ERR_NONE;
+}
+
+void km_tipc_shutdown(struct trusty_ipc_dev *dev)
+{
+    if (!initialized)
+        return;
+    /* close channel */
+    trusty_ipc_close(&km_chan);
+
+    initialized = false;
+}
+
+/**
+ * Appends |data_len| bytes at |data| to |buf|. Performs no bounds checking,
+ * assumes sufficient memory allocated at |buf|. Returns |buf| + |data_len|.
+ */
+static uint8_t *append_to_buf(uint8_t *buf, const void *data, size_t data_len)
+{
+    if (data && data_len) {
+        trusty_memcpy(buf, data, data_len);
+    }
+    return buf + data_len;
+}
+
+/**
+ * Appends |val| to |buf|. Performs no bounds checking. Returns |buf| +
+ * sizeof(uint32_t).
+ */
+static uint8_t *append_uint32_to_buf(uint8_t *buf, uint32_t val)
+{
+    return append_to_buf(buf, &val, sizeof(val));
+}
+
+/**
+ * Appends a sized buffer to |buf|. First appends |data_len| to |buf|, then
+ * appends |data_len| bytes at |data| to |buf|. Performs no bounds checking.
+ * Returns |buf| + sizeof(uint32_t) + |data_len|.
+ */
+static uint8_t *append_sized_buf_to_buf(uint8_t *buf, const uint8_t *data,
+                                        uint32_t data_len)
+{
+    buf = append_uint32_to_buf(buf, data_len);
+    return append_to_buf(buf, data, data_len);
+}
+
+int km_boot_params_serialize(const struct km_boot_params *params, uint8_t** out,
+                             uint32_t *out_size)
+{
+    uint8_t *tmp;
+
+    if (!out || !params || !out_size) {
+        return TRUSTY_ERR_INVALID_ARGS;
+    }
+    *out_size = (sizeof(params->os_version) + sizeof(params->os_patchlevel) +
+                 sizeof(params->device_locked) +
+                 sizeof(params->verified_boot_state) +
+                 sizeof(params->verified_boot_key_hash_size) +
+                 sizeof(params->verified_boot_hash_size) +
+                 params->verified_boot_key_hash_size +
+                 params->verified_boot_hash_size);
+    *out = trusty_calloc(*out_size, 1);
+    if (!*out) {
+        return TRUSTY_ERR_NO_MEMORY;
+    }
+
+    tmp = append_uint32_to_buf(*out, params->os_version);
+    tmp = append_uint32_to_buf(tmp, params->os_patchlevel);
+    tmp = append_uint32_to_buf(tmp, params->device_locked);
+    tmp = append_uint32_to_buf(tmp, params->verified_boot_state);
+    tmp = append_sized_buf_to_buf(tmp, params->verified_boot_key_hash,
+                                  params->verified_boot_key_hash_size);
+    tmp = append_sized_buf_to_buf(tmp, params->verified_boot_hash,
+                                  params->verified_boot_hash_size);
+
+    return TRUSTY_ERR_NONE;
+}
+
+int km_attestation_data_serialize(const struct km_attestation_data *data,
+                                 uint8_t** out, uint32_t *out_size)
+{
+    uint8_t *tmp;
+
+    if (!out || !data || !out_size) {
+        return TRUSTY_ERR_INVALID_ARGS;
+    }
+    *out_size = (sizeof(data->algorithm) + sizeof(data->data_size) +
+                 data->data_size);
+    *out = trusty_calloc(*out_size, 1);
+    if (!*out) {
+        return TRUSTY_ERR_NO_MEMORY;
+    }
+
+    tmp = append_uint32_to_buf(*out, data->algorithm);
+    tmp = append_sized_buf_to_buf(tmp, data->data, data->data_size);
+
+    return TRUSTY_ERR_NONE;
+}
+
+int trusty_set_boot_params(uint32_t os_version, uint32_t os_patchlevel,
+                           keymaster_verified_boot_t verified_boot_state,
+                           bool device_locked,
+                           const uint8_t *verified_boot_key_hash,
+                           uint32_t verified_boot_key_hash_size,
+                           const uint8_t *verified_boot_hash,
+                           uint32_t verified_boot_hash_size)
+{
+    struct km_boot_params params = {
+        .os_version = os_version,
+        .os_patchlevel = os_patchlevel,
+        .device_locked = (uint32_t)device_locked,
+        .verified_boot_state = (uint32_t)verified_boot_state,
+        .verified_boot_key_hash_size = verified_boot_key_hash_size,
+        .verified_boot_key_hash = verified_boot_key_hash,
+        .verified_boot_hash_size = verified_boot_hash_size,
+        .verified_boot_hash = verified_boot_hash
+    };
+    uint8_t *req = NULL;
+    uint32_t req_size = 0;
+    int rc = km_boot_params_serialize(&params, &req, &req_size);
+
+    if (rc < 0) {
+        trusty_error("failed (%d) to serialize request\n", rc);
+        goto end;
+    }
+    rc = km_do_tipc(KM_SET_BOOT_PARAMS, req, req_size, false);
+
+end:
+    if (req) {
+        trusty_free(req);
+    }
+    return rc;
+}
+
+static int trusty_send_attestation_data(uint32_t cmd, const uint8_t *data,
+                                        uint32_t data_size,
+                                        keymaster_algorithm_t algorithm)
+{
+    struct km_attestation_data attestation_data = {
+        .algorithm = (uint32_t)algorithm,
+        .data_size = data_size,
+        .data = data,
+    };
+    uint8_t *req = NULL;
+    uint32_t req_size = 0;
+    int rc = km_attestation_data_serialize(&attestation_data, &req, &req_size);
+
+    if (rc < 0) {
+        trusty_error("failed (%d) to serialize request\n", rc);
+        goto end;
+    }
+    rc = km_do_tipc(cmd, req, req_size, true);
+
+end:
+    if (req) {
+        trusty_free(req);
+    }
+    return rc;
+}
+
+int trusty_set_attestation_key(const uint8_t *key, uint32_t key_size,
+                               keymaster_algorithm_t algorithm)
+{
+    return trusty_send_attestation_data(KM_SET_ATTESTATION_KEY, key, key_size,
+                                        algorithm);
+}
+
+int trusty_append_attestation_cert_chain(const uint8_t *cert,
+                                         uint32_t cert_size,
+                                         keymaster_algorithm_t algorithm)
+{
+    return trusty_send_attestation_data(KM_APPEND_ATTESTATION_CERT_CHAIN,
+                                        cert, cert_size, algorithm);
+}
diff --git a/lib/trusty/ql-tipc/libtipc.c b/lib/trusty/ql-tipc/libtipc.c
new file mode 100644 (file)
index 0000000..1f3fa66
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <trusty/avb.h>
+#include <trusty/keymaster.h>
+#include <trusty/rpmb.h>
+#include <trusty/trusty_dev.h>
+#include <trusty/trusty_ipc.h>
+#include <trusty/util.h>
+
+#define LOCAL_LOG 0
+
+typedef uintptr_t vaddr_t;
+
+static struct trusty_ipc_dev *_ipc_dev;
+static struct trusty_dev _tdev; /* There should only be one trusty device */
+static void *rpmb_ctx;
+
+void trusty_ipc_shutdown(void)
+{
+    (void)rpmb_storage_proxy_shutdown(_ipc_dev);
+    (void)rpmb_storage_put_ctx(rpmb_ctx);
+
+    (void)avb_tipc_shutdown(_ipc_dev);
+    (void)km_tipc_shutdown(_ipc_dev);
+
+    /* shutdown Trusty IPC device */
+    (void)trusty_ipc_dev_shutdown(_ipc_dev);
+
+    /* shutdown Trusty device */
+    (void)trusty_dev_shutdown(&_tdev);
+}
+
+int trusty_ipc_init(void)
+{
+    int rc;
+    /* init Trusty device */
+    trusty_info("Initializing Trusty device\n");
+    rc = trusty_dev_init(&_tdev, NULL);
+    if (rc != 0) {
+        trusty_error("Initializing Trusty device failed (%d)\n", rc);
+        return rc;
+    }
+
+    /* create Trusty IPC device */
+    trusty_info("Initializing Trusty IPC device\n");
+    rc = trusty_ipc_dev_create(&_ipc_dev, &_tdev, PAGE_SIZE);
+    if (rc != 0) {
+        trusty_error("Initializing Trusty IPC device failed (%d)\n", rc);
+        return rc;
+    }
+
+    /* get storage rpmb */
+    rpmb_ctx = rpmb_storage_get_ctx();
+
+    /* start secure storage proxy service */
+    trusty_info("Initializing RPMB storage proxy service\n");
+    rc = rpmb_storage_proxy_init(_ipc_dev, rpmb_ctx);
+    if (rc != 0) {
+        trusty_error("Initlializing RPMB storage proxy service failed (%d)\n",
+                     rc);
+        return rc;
+    }
+
+    trusty_info("Initializing Trusty AVB client\n");
+    rc = avb_tipc_init(_ipc_dev);
+    if (rc != 0) {
+        trusty_error("Initlializing Trusty AVB client failed (%d)\n", rc);
+        return rc;
+    }
+
+    trusty_info("Initializing Trusty Keymaster client\n");
+    rc = km_tipc_init(_ipc_dev);
+    if (rc != 0) {
+        trusty_error("Initlializing Trusty Keymaster client failed (%d)\n", rc);
+        return rc;
+    }
+
+    return TRUSTY_ERR_NONE;
+}
diff --git a/lib/trusty/ql-tipc/rpmb_proxy.c b/lib/trusty/ql-tipc/rpmb_proxy.c
new file mode 100644 (file)
index 0000000..e4a684f
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <trusty/rpmb.h>
+#include <trusty/trusty_ipc.h>
+#include <trusty/util.h>
+#include <interface/storage/storage.h>
+
+#define LOCAL_LOG 1
+
+static bool initialized;
+/* Address of rpmb device */
+static void *proxy_rpmb;
+struct trusty_ipc_chan proxy_chan;
+
+struct storage_msg req_msg;
+static uint8_t req_buf[4096];
+static uint8_t read_buf[4096];
+
+/*
+ * Read RPMB request from storage service. Writes message to @msg
+ * and @req.
+ *
+ * @chan:    proxy ipc channel
+ * @msg:     address of storage message header
+ * @req:     address of storage message request
+ * @req_len: length of req in bytes
+ */
+static int proxy_read_request(struct trusty_ipc_chan *chan,
+                              struct storage_msg *msg, void *req,
+                              size_t req_len)
+{
+    int rc;
+
+    struct trusty_ipc_iovec req_iovs[2] = {
+        { .base = msg, .len = sizeof(*msg) },
+        { .base = req, .len = req_len },
+    };
+    rc = trusty_ipc_recv(chan, req_iovs, 2, false);
+    if (rc < 0) {
+        /* recv message failed */
+        trusty_error("%s: failed (%d) to recv request\n", __func__, rc);
+        return rc;
+    }
+
+    if ((size_t)rc < sizeof(*msg)) {
+        /* malformed message */
+        trusty_error("%s: malformed request (%zu)\n", __func__, (size_t)rc);
+        return TRUSTY_ERR_GENERIC;
+    }
+
+    return rc - sizeof(*msg); /* return payload size */
+}
+
+/*
+ * Send RPMB response to storage service
+ *
+ * @chan:     proxy ipc channel
+ * @msg:      address of storage message header
+ * @resp:     address of storage message response
+ * @resp_len: length of resp in bytes
+ */
+static int proxy_send_response(struct trusty_ipc_chan *chan,
+                               struct storage_msg *msg, void *resp,
+                               size_t resp_len)
+{
+    struct trusty_ipc_iovec resp_iovs[2] = {
+        { .base = msg, .len = sizeof(*msg) },
+        { .base = resp, .len = resp_len }
+    };
+
+    msg->cmd |= STORAGE_RESP_BIT;
+    return trusty_ipc_send(chan, resp_iovs, resp ? 2 : 1, false);
+}
+
+/*
+ * Executes the RPMB request at @r, sends response to storage service.
+ *
+ * @chan:    proxy ipc channel
+ * @msg:     address of storage message header
+ * @r:       address of storage message request
+ * @req_len: length of resp in bytes
+ */
+static int proxy_handle_rpmb(struct trusty_ipc_chan *chan,
+                             struct storage_msg *msg, const void *r,
+                             size_t req_len)
+{
+    int rc;
+    size_t exp_len;
+    const void *write_data = NULL;
+    const void *rel_write_data = NULL;
+    const struct storage_rpmb_send_req *req = r;
+
+    if (req_len < sizeof(req)) {
+        msg->result = STORAGE_ERR_NOT_VALID;
+        goto err_response;
+    }
+
+    exp_len = sizeof(*req) + req->reliable_write_size + req->write_size;
+    if (req_len != exp_len) {
+        trusty_error(
+            "%s: malformed rpmb request: invalid length (%zu != %zu)\n",
+            __func__, req_len, exp_len);
+        msg->result = STORAGE_ERR_NOT_VALID;
+        goto err_response;
+    }
+
+    if (req->reliable_write_size) {
+        if ((req->reliable_write_size % MMC_BLOCK_SIZE) != 0) {
+            trusty_error("%s: invalid reliable write size %u\n", __func__,
+                         req->reliable_write_size);
+            msg->result = STORAGE_ERR_NOT_VALID;
+            goto err_response;
+        }
+        rel_write_data = req->payload;
+    }
+
+    if (req->write_size) {
+        if ((req->write_size % MMC_BLOCK_SIZE) != 0) {
+            trusty_error("%: invalid write size %u\n", __func__,
+                         req->write_size);
+            msg->result = STORAGE_ERR_NOT_VALID;
+            goto err_response;
+        }
+        write_data = req->payload + req->reliable_write_size;
+    }
+
+    if (req->read_size) {
+        if (req->read_size % MMC_BLOCK_SIZE != 0 ||
+            req->read_size > sizeof(read_buf)) {
+            trusty_error("%s: invalid read size %u\n", __func__,
+                         req->read_size);
+            msg->result = STORAGE_ERR_NOT_VALID;
+            goto err_response;
+        }
+    }
+
+    /* execute rpmb command */
+    rc = rpmb_storage_send(proxy_rpmb,
+                           rel_write_data, req->reliable_write_size,
+                           write_data, req->write_size,
+                           read_buf, req->read_size);
+    if (rc) {
+        trusty_error("%s: rpmb_storage_send failed: %d\n", __func__, rc);
+        msg->result = STORAGE_ERR_GENERIC;
+        goto err_response;
+    }
+
+    if (msg->flags & STORAGE_MSG_FLAG_POST_COMMIT) {
+        /*
+         * Nothing todo for post msg commit request as MMC_IOC_MULTI_CMD
+         * is fully synchronous in this implementation.
+         */
+    }
+
+    msg->result = STORAGE_NO_ERROR;
+    return proxy_send_response(chan, msg, read_buf, req->read_size);
+
+err_response:
+    return proxy_send_response(chan, msg, NULL, 0);
+}
+
+/*
+ * Handles storage request.
+ *
+ * @chan:    proxy ipc channel
+ * @msg:     address of storage message header
+ * @req:     address of storage message request
+ * @req_len: length of resp in bytes
+ */
+static int proxy_handle_req(struct trusty_ipc_chan *chan,
+                            struct storage_msg *msg, const void *req,
+                            size_t req_len)
+{
+    int rc;
+
+    if (msg->flags & STORAGE_MSG_FLAG_PRE_COMMIT) {
+        /* nothing to do */
+    }
+
+    switch (msg->cmd) {
+    case STORAGE_RPMB_SEND:
+        rc = proxy_handle_rpmb(chan, msg, req, req_len);
+        break;
+
+    case STORAGE_FILE_DELETE:
+    case STORAGE_FILE_OPEN:
+    case STORAGE_FILE_CLOSE:
+    case STORAGE_FILE_WRITE:
+    case STORAGE_FILE_READ:
+    case STORAGE_FILE_GET_SIZE:
+    case STORAGE_FILE_SET_SIZE:
+        /* Bulk filesystem is not supported */
+        msg->result = STORAGE_ERR_UNIMPLEMENTED;
+        rc = proxy_send_response(chan, msg, NULL, 0);
+        break;
+
+    default:
+        msg->result = STORAGE_ERR_UNIMPLEMENTED;
+        rc = proxy_send_response(chan, msg, NULL, 0);
+    }
+
+    return rc;
+}
+
+/*
+ * Invalidates @chan on hangup event
+ *
+ * @chan:    proxy ipc channel
+ */
+static int proxy_on_disconnect(struct trusty_ipc_chan *chan)
+{
+    trusty_assert(chan);
+
+    trusty_debug("%s: closed by peer\n", __func__);
+    chan->handle = INVALID_IPC_HANDLE;
+    return TRUSTY_EVENT_HANDLED;
+}
+
+/*
+ * Handles received storage message on message event
+ *
+ * @chan:    proxy ipc channel
+ */
+static int proxy_on_message(struct trusty_ipc_chan *chan)
+{
+    int rc;
+
+    trusty_assert(chan);
+
+    /* read request */
+    rc = proxy_read_request(chan, &req_msg, req_buf, sizeof(req_buf));
+    if (rc < 0) {
+        trusty_error("%s: failed (%d) to read request\n", __func__, rc);
+        trusty_ipc_close(chan);
+        return rc;
+    }
+
+    /* handle it and send reply */
+    rc = proxy_handle_req(chan, &req_msg, req_buf, rc);
+    if (rc < 0) {
+        trusty_error("%s: failed (%d) to handle request\n", __func__, rc);
+        trusty_ipc_close(chan);
+        return rc;
+    }
+
+    return TRUSTY_EVENT_HANDLED;
+}
+
+static struct trusty_ipc_ops proxy_ops = {
+    .on_message = proxy_on_message,
+    .on_disconnect = proxy_on_disconnect,
+};
+
+/*
+ * Initialize RPMB storage proxy
+ */
+int rpmb_storage_proxy_init(struct trusty_ipc_dev *dev, void *rpmb_dev)
+{
+    int rc;
+
+    trusty_assert(dev);
+    trusty_assert(!initialized);
+
+    /* attach rpmb device  */
+    proxy_rpmb = rpmb_dev;
+
+    /* init ipc channel */
+    trusty_ipc_chan_init(&proxy_chan, dev);
+
+    /* connect to proxy service and wait for connect to complete */
+    rc = trusty_ipc_connect(&proxy_chan, STORAGE_DISK_PROXY_PORT, true);
+    if (rc < 0) {
+        trusty_error("%s: failed (%d) to connect to '%s'\n", __func__, rc,
+                     STORAGE_DISK_PROXY_PORT);
+        return rc;
+    }
+
+    /* override default ops */
+    proxy_chan.ops = &proxy_ops;
+
+    rc = rpmb_storage_proxy_poll();
+    if (rc < 0) {
+        return rc;
+    }
+
+    /* mark as initialized */
+    initialized = true;
+
+    return TRUSTY_ERR_NONE;
+}
+
+int rpmb_storage_proxy_poll(void)
+{
+    int rc = 0;
+    while (rc != TRUSTY_EVENT_NONE) {
+        /* Check for RPMB events */
+        rc = trusty_ipc_poll_for_event(&proxy_chan);
+        if (rc < 0) {
+            trusty_error("%s: failed (%d) to get rpmb event\n", __func__, rc);
+            return rc;
+        }
+    }
+    return TRUSTY_ERR_NONE;
+}
+
+void rpmb_storage_proxy_shutdown(struct trusty_ipc_dev *dev)
+{
+    if (!initialized)
+        return; /* nothing to do */
+
+    /* close channel */
+    trusty_ipc_close(&proxy_chan);
+
+    initialized = false;
+}
diff --git a/lib/trusty/ql-tipc/sysdeps/Makefile b/lib/trusty/ql-tipc/sysdeps/Makefile
new file mode 100644 (file)
index 0000000..f9b19d0
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+
+# Sample Makefile for U-boot
+
+#ccflags-y += -DTIPC_ENABLE_DEBUG
+
+TRUSTY_DIR = lib/trusty
+#ccflags-y += -I$(TRUSTY_DIR)/ql-tipc/include
+ccflags-y += -I$(TRUSTY_DIR)/interface/include
+
+QL_TIPC = ../
+obj-y += \
+    $(QL_TIPC)/avb.o \
+    $(QL_TIPC)/keymaster.o \
+    $(QL_TIPC)/ipc.o \
+    $(QL_TIPC)/ipc_dev.o \
+    $(QL_TIPC)/libtipc.o \
+    $(QL_TIPC)/rpmb_proxy.o \
+    sysdeps_uboot.o \
+    storage_ops_uboot.o
+
+obj-$(CONFIG_ARM) += \
+    $(QL_TIPC)/arch/arm/trusty_mem.o \
+    $(QL_TIPC)/arch/arm/trusty_dev.o
diff --git a/lib/trusty/ql-tipc/sysdeps/storage_ops_uboot.c b/lib/trusty/ql-tipc/sysdeps/storage_ops_uboot.c
new file mode 100644 (file)
index 0000000..de12174
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <trusty/rpmb.h>
+#include <trusty/trusty_dev.h>
+#include <trusty/util.h>
+
+#include <common.h>
+#include <memalign.h>
+#include <mmc.h>
+
+void *rpmb_storage_get_ctx(void)
+{
+    /* Unused for U-boot */
+    return NULL;
+}
+
+void rpmb_storage_put_ctx(void *dev)
+{
+}
+
+int rpmb_storage_send(void *rpmb_dev, const void *rel_write_data,
+                      size_t rel_write_size, const void *write_data,
+                      size_t write_size, void *read_buf, size_t read_size)
+{
+    ALLOC_CACHE_ALIGN_BUFFER(uint8_t, rpmb_rel_write_data, rel_write_size);
+    ALLOC_CACHE_ALIGN_BUFFER(uint8_t, rpmb_write_data, write_size);
+    ALLOC_CACHE_ALIGN_BUFFER(uint8_t, rpmb_read_data, read_size);
+    int ret = TRUSTY_ERR_NONE;
+    struct mmc *mmc = find_mmc_device(mmc_get_env_dev());
+    char original_part = mmc->block_dev.hwpart;
+
+    /* Switch to RPMB partition */
+    if (mmc->block_dev.hwpart != MMC_PART_RPMB) {
+        ret = mmc_switch_part(mmc, MMC_PART_RPMB);
+        if (ret) {
+            trusty_error("failed to switch to RPMB partition\n");
+            ret = TRUSTY_ERR_GENERIC;
+            goto end;
+        }
+        mmc->block_dev.hwpart = MMC_PART_RPMB;
+    }
+
+    if (rel_write_size) {
+        if (rel_write_size % MMC_BLOCK_SIZE) {
+            trusty_error(
+                "rel_write_size is not a multiple of MMC_BLOCK_SIZE: %d\n",
+                 rel_write_size);
+            ret = TRUSTY_ERR_INVALID_ARGS;
+            goto end;
+        }
+        trusty_memcpy(rpmb_rel_write_data, rel_write_data, rel_write_size);
+        ret = mmc_rpmb_request(mmc,
+                               (const struct s_rpmb *)rpmb_rel_write_data,
+                               rel_write_size / MMC_BLOCK_SIZE, true);
+        if (ret) {
+            trusty_error("failed to execute rpmb reliable write\n");
+            goto end;
+        }
+    }
+    if (write_size) {
+        if (write_size % MMC_BLOCK_SIZE) {
+            trusty_error("write_size is not a multiple of MMC_BLOCK_SIZE: %d\n",
+                         write_size);
+            ret = TRUSTY_ERR_INVALID_ARGS;
+            goto end;
+        }
+        trusty_memcpy(rpmb_write_data, write_data, write_size);
+        ret = mmc_rpmb_request(mmc, (const struct s_rpmb *)rpmb_write_data,
+                               write_size / MMC_BLOCK_SIZE, false);
+        if (ret) {
+            trusty_error("failed to execute rpmb write\n");
+            goto end;
+        }
+    }
+    if (read_size) {
+        if (read_size % MMC_BLOCK_SIZE) {
+            trusty_error("read_size is not a multiple of MMC_BLOCK_SIZE: %d\n",
+                         read_size);
+            ret = TRUSTY_ERR_INVALID_ARGS;
+            goto end;
+        }
+        ret = mmc_rpmb_response(mmc, (struct s_rpmb *)rpmb_read_data,
+                                read_size / MMC_BLOCK_SIZE, 0);
+        trusty_memcpy((void *)read_buf, rpmb_read_data, read_size);
+        if (ret < 0) {
+            trusty_error("failed to execute rpmb read\n");
+        }
+    }
+
+end:
+    /* Return to original partition */
+    if (mmc->block_dev.hwpart != original_part) {
+        if (mmc_switch_part(mmc, original_part) != 0) {
+            trusty_error("failed to switch back to original partition\n");
+            return TRUSTY_ERR_GENERIC;
+        }
+        mmc->block_dev.hwpart = original_part;
+    }
+    return ret;
+}
diff --git a/lib/trusty/ql-tipc/sysdeps/sysdeps_uboot.c b/lib/trusty/ql-tipc/sysdeps/sysdeps_uboot.c
new file mode 100644 (file)
index 0000000..a452689
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <trusty/sysdeps.h>
+
+#include <common.h>
+#include <linux/string.h>
+#include <malloc.h>
+
+extern int trusty_encode_page_info(struct ns_mem_page_info *page_info,
+                                   void *vaddr);
+
+void trusty_lock(struct trusty_dev *dev)
+{
+}
+void trusty_unlock(struct trusty_dev *dev)
+{
+}
+
+void trusty_local_irq_disable(unsigned long *state)
+{
+    disable_interrupts();
+}
+
+void trusty_local_irq_restore(unsigned long *state)
+{
+    enable_interrupts();
+}
+
+void trusty_idle(struct trusty_dev *dev)
+{
+    wfi();
+}
+
+void trusty_abort(void)
+{
+    do_reset(NULL, 0, 0, NULL);
+    __builtin_unreachable();
+}
+
+void trusty_printv(const char *message, ...)
+{
+    va_list ap;
+
+    va_start(ap, message);
+    vprintf(message, ap);
+    va_end(ap);
+}
+
+void *trusty_memcpy(void *dest, const void *src, size_t n)
+{
+    return memcpy(dest, src, n);
+}
+
+void *trusty_memset(void *dest, const int c, size_t n)
+{
+    return memset(dest, c, n);
+}
+
+char *trusty_strcpy(char *dest, const char *src)
+{
+    return strcpy(dest, src);
+}
+
+size_t trusty_strlen(const char *str)
+{
+    return strlen(str);
+}
+
+void *trusty_calloc(size_t n, size_t size)
+{
+    return calloc(n, size);
+}
+
+void trusty_free(void *addr)
+{
+    if (addr)
+        free(addr);
+}
+
+void *trusty_membuf_alloc(struct ns_mem_page_info *page_info, size_t size)
+{
+    void *va = NULL;
+    int res;
+
+    va = memalign(4096, size);
+    if (!va)
+        return NULL;
+
+    /* get memory attibutes */
+    res = trusty_encode_page_info(page_info, va);
+    if (res) {
+        trusty_membuf_free(va);
+        return NULL;
+    }
+    return va;
+}
+
+void trusty_membuf_free(void *va)
+{
+    if (va)
+        free(va);
+}