summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaoran.Wang <elven.wang@nxp.com>2017-10-10 22:59:37 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-10-10 22:59:37 +0000
commit97e082ad2888fb0491220c356b19a63c2269b703 (patch)
treedad8c73e086ea8f03fd05f2ec9d2125d528eee5e
parent0aab3b6a2526af0274a500d9658d45dc9032252b (diff)
parent577828e5daec0b57b1748ec194c567c0d55a947c (diff)
downloaduboot-imx-97e082ad2888fb0491220c356b19a63c2269b703.tar.gz
[iot] Import ql-tipc lib for Trusty OS am: 93cda03d79
am: 577828e5da Change-Id: Iaec5f6f3399b1b901341d9dbe8b9ebe45f112735
-rw-r--r--include/interface/avb/avb.h98
-rw-r--r--include/interface/keymaster/keymaster.h254
-rw-r--r--include/interface/storage/storage.h165
-rw-r--r--include/trusty/avb.h102
-rw-r--r--include/trusty/keymaster.h89
-rw-r--r--include/trusty/libtipc.h40
-rw-r--r--include/trusty/rpmb.h76
-rw-r--r--include/trusty/sysdeps.h123
-rw-r--r--include/trusty/trusty_dev.h82
-rw-r--r--include/trusty/trusty_ipc.h258
-rw-r--r--include/trusty/util.h94
-rw-r--r--lib/Makefile1
-rw-r--r--lib/trusty/ql-tipc/LICENSE20
-rw-r--r--lib/trusty/ql-tipc/README.md30
-rw-r--r--lib/trusty/ql-tipc/arch/arm/sm_err.h45
-rw-r--r--lib/trusty/ql-tipc/arch/arm/smcall.h143
-rw-r--r--lib/trusty/ql-tipc/arch/arm/trusty_dev.c257
-rw-r--r--lib/trusty/ql-tipc/arch/arm/trusty_mem.c267
-rw-r--r--lib/trusty/ql-tipc/avb.c250
-rw-r--r--lib/trusty/ql-tipc/ipc.c299
-rw-r--r--lib/trusty/ql-tipc/ipc_dev.c448
-rw-r--r--lib/trusty/ql-tipc/keymaster.c350
-rw-r--r--lib/trusty/ql-tipc/libtipc.c101
-rw-r--r--lib/trusty/ql-tipc/rpmb_proxy.c337
-rw-r--r--lib/trusty/ql-tipc/sysdeps/Makefile46
-rw-r--r--lib/trusty/ql-tipc/sysdeps/storage_ops_uboot.c122
-rw-r--r--lib/trusty/ql-tipc/sysdeps/sysdeps_uboot.c124
27 files changed, 4221 insertions, 0 deletions
diff --git a/include/interface/avb/avb.h b/include/interface/avb/avb.h
new file mode 100644
index 0000000000..5ce338ea78
--- /dev/null
+++ b/include/interface/avb/avb.h
@@ -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
index 0000000000..d8f7eb7f1a
--- /dev/null
+++ b/include/interface/keymaster/keymaster.h
@@ -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
index 0000000000..e4f7f83656
--- /dev/null
+++ b/include/interface/storage/storage.h
@@ -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
index 0000000000..f54a3ffe8c
--- /dev/null
+++ b/include/trusty/avb.h
@@ -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
index 0000000000..6117ae6a9d
--- /dev/null
+++ b/include/trusty/keymaster.h
@@ -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
index 0000000000..e37b010770
--- /dev/null
+++ b/include/trusty/libtipc.h
@@ -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
index 0000000000..594f527a35
--- /dev/null
+++ b/include/trusty/rpmb.h
@@ -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
index 0000000000..7704563196
--- /dev/null
+++ b/include/trusty/sysdeps.h
@@ -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
index 0000000000..27ae8cca83
--- /dev/null
+++ b/include/trusty/trusty_dev.h
@@ -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
index 0000000000..03ef93507d
--- /dev/null
+++ b/include/trusty/trusty_ipc.h
@@ -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
index 0000000000..58cb2e76a4
--- /dev/null
+++ b/include/trusty/util.h
@@ -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_ */
diff --git a/lib/Makefile b/lib/Makefile
index d164689e75..b8bfb76c08 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -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
index 0000000000..d21621abc4
--- /dev/null
+++ b/lib/trusty/ql-tipc/LICENSE
@@ -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
index 0000000000..76e3781756
--- /dev/null
+++ b/lib/trusty/ql-tipc/README.md
@@ -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
index 0000000000..940125611c
--- /dev/null
+++ b/lib/trusty/ql-tipc/arch/arm/sm_err.h
@@ -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
index 0000000000..695776c93e
--- /dev/null
+++ b/lib/trusty/ql-tipc/arch/arm/smcall.h
@@ -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
index 0000000000..6407d738da
--- /dev/null
+++ b/lib/trusty/ql-tipc/arch/arm/trusty_dev.c
@@ -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
index 0000000000..e980b958ee
--- /dev/null
+++ b/lib/trusty/ql-tipc/arch/arm/trusty_mem.c
@@ -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
index 0000000000..ebbb38ff20
--- /dev/null
+++ b/lib/trusty/ql-tipc/avb.c
@@ -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
index 0000000000..95c0ee605c
--- /dev/null
+++ b/lib/trusty/ql-tipc/ipc.c
@@ -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
index 0000000000..5924d44891
--- /dev/null
+++ b/lib/trusty/ql-tipc/ipc_dev.c
@@ -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
index 0000000000..d3c0be4a8e
--- /dev/null
+++ b/lib/trusty/ql-tipc/keymaster.c
@@ -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
index 0000000000..1f3fa66973
--- /dev/null
+++ b/lib/trusty/ql-tipc/libtipc.c
@@ -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
index 0000000000..e4a684f5f3
--- /dev/null
+++ b/lib/trusty/ql-tipc/rpmb_proxy.c
@@ -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
index 0000000000..f9b19d05cc
--- /dev/null
+++ b/lib/trusty/ql-tipc/sysdeps/Makefile
@@ -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
index 0000000000..de1217427c
--- /dev/null
+++ b/lib/trusty/ql-tipc/sysdeps/storage_ops_uboot.c
@@ -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
index 0000000000..a452689b2d
--- /dev/null
+++ b/lib/trusty/ql-tipc/sysdeps/sysdeps_uboot.c
@@ -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);
+}