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