1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <assert.h>
26 #include <test-runner-arch.h>
27 #include <trusty/rpmb.h>
28 #include <trusty/trusty_dev.h>
29 #include <trusty/util.h>
30 #include <virtio-rpmb.h>
31 #include <virtio.h>
32
33 static const char* rpmb_devname = "rpmb0";
34
35 static struct virtq input;
36 static struct virtq_raw input_raw;
37 static struct virtq output;
38 static struct virtq_raw output_raw;
39
rpmb_scan(struct virtio_console * console)40 static int rpmb_scan(struct virtio_console* console) {
41 /* Scan for RPMB */
42 for (size_t i = 0; i < MAX_PORTS; i++) {
43 if (!trusty_strcmp(rpmb_devname, console->ports[i].name)) {
44 assert(console->ports[i].host_connected);
45 return i;
46 }
47 }
48
49 /* RPMB not found */
50 return -1;
51 }
52
init_virtio_rpmb(struct virtio_console * console)53 int init_virtio_rpmb(struct virtio_console* console) {
54 int rpmb_id = rpmb_scan(console);
55 if (rpmb_id < 0) {
56 return rpmb_id;
57 }
58
59 vq_init(&input, &input_raw, console->vio, true);
60 vq_init(&output, &output_raw, console->vio, false);
61
62 virtio_console_connect_port(console, rpmb_id, &input, &output);
63 return 0;
64 }
65
send_virtio_rpmb(const void * data,size_t len)66 static ssize_t send_virtio_rpmb(const void* data, size_t len) {
67 return send_vq(&output, data, len);
68 }
69
recv_virtio_rpmb(void * data,size_t len)70 static ssize_t recv_virtio_rpmb(void* data, size_t len) {
71 return recv_vq(&input, data, len);
72 }
73
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)74 int rpmb_storage_send(void* rpmb_dev,
75 const void* rel_write_data,
76 size_t rel_write_size,
77 const void* write_data,
78 size_t write_size,
79 void* read_buf,
80 size_t read_size) {
81 int ret;
82 uint16_t read_count = read_size / MMC_BLOCK_SIZE;
83 uint16_t cmd_count = (rel_write_size + write_size) / MMC_BLOCK_SIZE;
84
85 assert(rel_write_size % MMC_BLOCK_SIZE == 0);
86 assert(write_size % MMC_BLOCK_SIZE == 0);
87
88 ret = send_virtio_rpmb(&read_count, sizeof(read_count));
89 if (ret < 0) {
90 goto err;
91 }
92 assert((size_t)ret == sizeof(read_count));
93
94 ret = send_virtio_rpmb(&cmd_count, sizeof(cmd_count));
95 if (ret < 0) {
96 goto err;
97 }
98 assert((size_t)ret == sizeof(cmd_count));
99
100 ret = send_virtio_rpmb(rel_write_data, rel_write_size);
101 if (ret < 0) {
102 goto err;
103 }
104 assert((size_t)ret == rel_write_size);
105
106 ret = send_virtio_rpmb(write_data, write_size);
107 if (ret < 0) {
108 goto err;
109 }
110 assert((size_t)ret == write_size);
111
112 ret = recv_virtio_rpmb(read_buf, read_size);
113 if (ret < 0) {
114 goto err;
115 }
116 assert((size_t)ret == read_size);
117
118 return 0;
119
120 err:
121 return TRUSTY_ERR_GENERIC;
122 }
123