1/* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include <stdlib.h> 16#include <string.h> 17#include <sys/ioctl.h> 18#include <sys/stat.h> 19#include <sys/types.h> 20#include <unistd.h> 21#include <stdio.h> 22#include <linux/fs.h> 23 24#include <errno.h> 25#include <fcntl.h> 26 27#include "hvb_ops.h" 28#include "hvb.h" 29 30static struct struct hvb_ops *g_hvb_ops; 31 32static enum hvb_io_errno hvb_read_partition(struct hvb_ops *ops, 33 const char *partition, 34 int64_t offset, 35 uint64_t num_bytes, 36 void *buffer, 37 uint64_t *out_num_read) 38{ 39 int fd; 40 off_t where; 41 suint64_t num_read; 42 enum hvb_io_errno ret = HVB_IO_OK; 43 44 fd = open(partition, O_RDONLY); 45 if (fd == -1) { 46 printf("Error open %s partition.\n", partition); 47 ret = HVB_IO_ERROR_NO_SUCH_PARTITION; 48 goto out; 49 } 50 51 if (offset < 0) { 52 uint64_t partition_size; 53 if (ioctl(fd, BLKGETSIZE64, &partition_size) != 0) { 54 printf("Error getting size of %s partition.\n", partition); 55 ret = HVB_IO_ERROR_IO; 56 goto out; 57 } 58 offset = partition_size - (-offset); 59 } 60 61 where = lseek(fd, offset, SEEK_SET); 62 if (where == -1) { 63 printf("Error seeking to offset.\n"); 64 ret = HVB_IO_ERROR_IO; 65 goto out; 66 } else if (where != offset) { 67 printf("Error seeking to offset.\n"); 68 ret = HVB_IO_ERROR_RANGE_OUTSIDE_PARTITION; 69 goto out; 70 } 71 72 num_read = read(fd, buffer, num_bytes); 73 if (num_read == -1) { 74 printf("Error reading data.\n"); 75 ret = HVB_IO_ERROR_IO; 76 goto out; 77 } 78 79 if (out_num_read != NULL) { 80 *out_num_read = num_read; 81 } 82 83out: 84 if (fd != -1) { 85 if (close(fd) != 0) { 86 printf("Error closing file descriptor.\n"); 87 } 88 } 89 90 return ret; 91} 92 93static enum hvb_io_errno hvb_write_partition(struct hvb_ops *ops, 94 const char *partition, 95 int64_t offset, 96 uint64_t num_bytes, 97 const void *buffer) 98{ 99 int fd; 100 off_t where; 101 suint64_t num_written; 102 enum hvb_io_errno ret = HVB_IO_OK; 103 104 fd = open(partition, O_WRONLY); 105 if (fd == -1) { 106 printf("Error opening %s partition.\n", partition); 107 ret = HVB_IO_ERROR_IO; 108 goto out; 109 } 110 111 where = lseek(fd, offset, SEEK_SET); 112 if (where == -1) { 113 printf("Error seeking to offset.\n"); 114 ret = HVB_IO_ERROR_IO; 115 goto out; 116 } else if (where != offset) { 117 printf("Error seeking to offset.\n"); 118 ret = HVB_IO_ERROR_RANGE_OUTSIDE_PARTITION; 119 goto out; 120 } 121 122 /* On Linux, we never get partial writes on block devices. */ 123 num_written = write(fd, buffer, num_bytes); 124 if (num_written == -1) { 125 printf("Error writing data.\n"); 126 ret = HVB_IO_ERROR_IO; 127 goto out; 128 } 129 130out: 131 if (fd != -1) { 132 if (close(fd) != 0) { 133 printf("Error closing file descriptor.\n"); 134 } 135 } 136 137 return ret; 138} 139 140static enum hvb_io_errno hvb_read_rollback(struct hvb_ops *ops, 141 uint64_t rollback_index_location, 142 uint64_t *out_rollback_index) 143{ 144 if (out_rollback_index != NULL) { 145 *out_rollback_index = 0; 146 } 147 148 return HVB_IO_OK; 149} 150 151static enum hvb_io_errno hvb_write_rollback(struct hvb_ops *ops, 152 uint64_t rollback_index_location, 153 uint64_t rollback_index) 154{ 155 return HVB_IO_OK; 156} 157 158static enum hvb_io_errno hvb_get_partiton_uuid(struct hvb_ops *ops, 159 const char *partition, 160 char *uuid_buf, 161 uint64_t uuid_buf_size) 162{ 163 if (uuid_buf != NULL && uuid_buf_size > 0) { 164 uuid_buf[0] = '\0'; 165 } 166 167 return HVB_IO_OK; 168} 169 170static enum hvb_io_errno hvb_get_partiton_size(struct hvb_ops *ops, 171 const char *partition, 172 uint64_t *out_size_in_bytes) 173{ 174 int fd; 175 enum hvb_io_errno ret = HVB_IO_OK; 176 177 fd = open(partition, O_WRONLY); 178 if (fd == -1) { 179 printf("Error opening %s partition.\n", partition); 180 ret = HVB_IO_ERROR_IO; 181 goto out; 182 } 183 184 if (out_size_in_bytes != NULL) { 185 if (ioctl(fd, BLKGETSIZE64, out_size_in_bytes) != 0) { 186 printf("Error getting size of %s partition.\n", partition); 187 ret = HVB_IO_ERROR_IO; 188 goto out; 189 } 190 } 191 192out: 193 if (fd != -1) { 194 if (close(fd) != 0) { 195 printf("Error closing file descriptor.\n"); 196 } 197 } 198 199 return ret; 200} 201 202static struct hvb_ops *hvb_ops_user(void) 203{ 204 struct hvb_ops *hvb_ops; 205 206 hvb_ops = (struct hvb_ops *)hvb_malloc(sizeof(struct hvb_ops)); 207 if (!hvb_ops) { 208 printf("Error malloc for hvb_ops.\n"); 209 return NULL; 210 } 211 212 hvb_ops->user_data = hvb_ops; 213 hvb_ops->read_partition = hvb_read_partition; 214 hvb_ops->write_partition = hvb_write_partition; 215 hvb_ops->read_rollback = hvb_read_rollback; 216 hvb_ops->write_rollback = hvb_write_rollback; 217 hvb_ops->get_partiton_uuid = hvb_get_partiton_uuid; 218 hvb_ops->get_partiton_size = hvb_get_partiton_size; 219 220 return hvb_ops; 221} 222 223int main(void) 224{ 225 int ret = -1; 226 enum hvb_errno sub_ret = HVB_OK; 227 struct hvb_verified_data *verified_data = NULL; 228 229 printf("hvb main function start.\n"); 230 g_hvb_ops = hvb_ops_user(); 231 if (!g_hvb_ops) { 232 printf("failed to get hvb_ops_user.\n"); 233 goto out; 234 } 235 236 sub_ret = hvb_chain_verify(g_hvb_ops, "rvt", &verified_data); 237 if (sub_ret != HVB_OK) { 238 printf("hvb verity error.\n"); 239 goto out; 240 } 241 printf("hvb main end.\n"); 242 243out: 244 if (g_hvb_ops != NULL) { 245 hvb_free(g_hvb_ops); 246 } 247 248 return ret; 249} 250