platform: msm_shared: Add support for rpmb
Add support for rpmb listener, rpmb driver for emmc & ufs.
Change-Id: Iacfb2bd34d6ddc309f2c7f5422576fa253322f82
diff --git a/platform/msm_shared/rpmb/rpmb_listener.c b/platform/msm_shared/rpmb/rpmb_listener.c
new file mode 100644
index 0000000..7cf0b79
--- /dev/null
+++ b/platform/msm_shared/rpmb/rpmb_listener.c
@@ -0,0 +1,199 @@
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <debug.h>
+#include <rpmb.h>
+#include <rpmb_listener.h>
+#include <qseecom_lk_api.h>
+
+#define RPMB_LSTNR_VERSION_2 0x2
+
+typedef enum
+{
+ TZ_CM_CMD_RPMB_INIT = 0x101, //257
+ TZ_CM_CMD_RPMB_READ, //258
+ TZ_CM_CMD_RPMB_WRITE, //259
+ TZ_CM_CMD_RPMB_PARTITION, //260
+} tz_rpmb_cmd_type;
+
+struct tz_device_init_req
+{
+ uint32_t cmd_id;
+ uint32_t version;
+}__PACKED;
+
+/* RPMB Init response message */
+struct tz_device_init_resp
+{
+ uint32_t cmd_id; /* Command ID */
+ uint32_t version; /* Messaging version from RPMB listener */
+ uint32_t status; /* RPMB init status */
+ uint32_t num_sectors; /* Size of RPMB (in sectors) */
+ uint32_t rel_wr_count; /* Reliable write count for the RPMB */
+ uint32_t dev_type; /* Storage device type (like eMMC or UFS) */
+ uint32_t reserved1; /* Reserved 1 */
+ uint32_t reserved2; /* Reserved 2 */
+ uint32_t reserved3; /* Reserved 3 */
+ uint32_t reserved4; /* Reserved 4 */
+}__PACKED;
+
+struct tz_rpmb_rw_req
+{
+ uint32_t cmd_id;
+ uint32_t num_sectors;
+ uint32_t req_buff_len;
+ uint32_t req_buff_offset;
+}__PACKED;
+
+struct tz_rpmb_rw_resp
+{
+ uint32_t cmd_id;
+ int32_t status;
+ uint32_t res_buff_len;
+ uint32_t res_buff_offset;
+}__PACKED;
+
+typedef int (*ListenerCallback)(void*, uint32_t);
+
+static void handle_init_request(void *buf, uint32_t sz)
+{
+ struct tz_device_init_req *init_req_p = NULL;
+ struct tz_device_init_resp *init_resp = (struct tz_device_init_resp*) buf;
+ struct rpmb_init_info *rpmb_info = NULL;
+
+ init_req_p = (struct tz_device_init_req *) buf;
+
+ rpmb_info = rpmb_get_init_info();
+
+ if (rpmb_info)
+ init_resp->status = 0;
+
+ init_resp->cmd_id = init_req_p->cmd_id;
+ init_resp->version = RPMB_LSTNR_VERSION_2;
+ init_resp->num_sectors = rpmb_info->size / RPMB_SECTOR_SIZE;
+ init_resp->rel_wr_count = rpmb_info->rel_wr_count;
+ init_resp->dev_type = rpmb_info->dev_type;
+}
+
+static void handle_rw_request(void *buf, uint32_t sz)
+{
+ struct tz_rpmb_rw_req *req_p = (struct tz_rpmb_rw_req *)buf;
+ struct tz_rpmb_rw_resp *resp_p = NULL;
+ uint32_t *req_buf = buf + req_p->req_buff_offset;
+ uint32_t *resp_buf = buf + sizeof(struct tz_rpmb_rw_resp);
+
+ resp_p = (struct tz_rpmb_rw_resp *) buf;
+
+ switch (req_p->cmd_id)
+ {
+ case TZ_CM_CMD_RPMB_READ:
+#if DEBUG_RPMB
+ dprintf(INFO, "Read Request received\n");
+#endif
+ resp_p->status = rpmb_read(req_buf, req_p->num_sectors, resp_buf, &resp_p->res_buff_len);
+ break;
+ case TZ_CM_CMD_RPMB_WRITE:
+#if DEBUG_RPMB
+ dprintf(INFO, "Write Request received\n");
+#endif
+ resp_p->status = rpmb_write(req_buf, req_p->num_sectors, resp_buf, &resp_p->res_buff_len);
+ break;
+ default:
+ dprintf(CRITICAL, "Unsupported request command request: %u\n", req_p->cmd_id);
+ ASSERT(0);
+ };
+
+ resp_p->res_buff_offset = sizeof(struct tz_rpmb_rw_resp);
+ resp_p->cmd_id = req_p->cmd_id;
+}
+
+int rpmb_cmd_handler(void *buf, uint32_t sz)
+{
+ int ret = 0;
+ uint32_t cmd_id;
+
+ ASSERT(buf);
+
+ cmd_id = (uint32_t) *((uint32_t *)buf);
+
+ switch(cmd_id)
+ {
+ case TZ_CM_CMD_RPMB_READ:
+ case TZ_CM_CMD_RPMB_WRITE:
+ handle_rw_request(buf, sz);
+ break;
+ case TZ_CM_CMD_RPMB_INIT:
+#if DEBUG_RPMB
+ dprintf(INFO, "RPMB init received\n");
+#endif
+ handle_init_request(buf, sz);
+ break;
+ case TZ_CM_CMD_RPMB_PARTITION:
+#if DEBUG_RPMB
+ dprintf(INFO, "Partition init received\n");
+#endif
+ ret = -1;
+ break;
+ default:
+ /* Does qseecom need a response here? */
+ dprintf(CRITICAL, "Unsupported Request from qseecom: %d\n", cmd_id);
+ ASSERT(0);
+ };
+
+ return ret;
+}
+
+int rpmb_listener_start()
+{
+ int ret;
+ struct qseecom_listener_services rpmb_listener;
+
+ rpmb_listener.service_name = "RPMB system services";
+ rpmb_listener.id = RPMB_LSTNR_ID;
+ rpmb_listener.sb_size = 20 * 1024;
+ rpmb_listener.service_cmd_handler = rpmb_cmd_handler;
+
+ ret = qseecom_register_listener(&rpmb_listener);
+
+ if (ret < 0)
+ dprintf(CRITICAL, "Failed to register rpmb listener\n");
+
+ return ret;
+}
+
+int rpmb_listener_stop(int id)
+{
+ int ret;
+
+ ret = qseecom_deregister_listener(id);
+
+ if (ret < 0)
+ dprintf(CRITICAL, "Failed to unregister rpmb listener\n");
+
+ return ret;
+}
+