/* * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include "hvb_ops.h" #include "hvb.h" static struct struct hvb_ops *g_hvb_ops; static enum hvb_io_errno hvb_read_partition(struct hvb_ops *ops, const char *partition, int64_t offset, uint64_t num_bytes, void *buffer, uint64_t *out_num_read) { int fd; off_t where; suint64_t num_read; enum hvb_io_errno ret = HVB_IO_OK; fd = open(partition, O_RDONLY); if (fd == -1) { printf("Error open %s partition.\n", partition); ret = HVB_IO_ERROR_NO_SUCH_PARTITION; goto out; } if (offset < 0) { uint64_t partition_size; if (ioctl(fd, BLKGETSIZE64, &partition_size) != 0) { printf("Error getting size of %s partition.\n", partition); ret = HVB_IO_ERROR_IO; goto out; } offset = partition_size - (-offset); } where = lseek(fd, offset, SEEK_SET); if (where == -1) { printf("Error seeking to offset.\n"); ret = HVB_IO_ERROR_IO; goto out; } else if (where != offset) { printf("Error seeking to offset.\n"); ret = HVB_IO_ERROR_RANGE_OUTSIDE_PARTITION; goto out; } num_read = read(fd, buffer, num_bytes); if (num_read == -1) { printf("Error reading data.\n"); ret = HVB_IO_ERROR_IO; goto out; } if (out_num_read != NULL) { *out_num_read = num_read; } out: if (fd != -1) { if (close(fd) != 0) { printf("Error closing file descriptor.\n"); } } return ret; } static enum hvb_io_errno hvb_write_partition(struct hvb_ops *ops, const char *partition, int64_t offset, uint64_t num_bytes, const void *buffer) { int fd; off_t where; suint64_t num_written; enum hvb_io_errno ret = HVB_IO_OK; fd = open(partition, O_WRONLY); if (fd == -1) { printf("Error opening %s partition.\n", partition); ret = HVB_IO_ERROR_IO; goto out; } where = lseek(fd, offset, SEEK_SET); if (where == -1) { printf("Error seeking to offset.\n"); ret = HVB_IO_ERROR_IO; goto out; } else if (where != offset) { printf("Error seeking to offset.\n"); ret = HVB_IO_ERROR_RANGE_OUTSIDE_PARTITION; goto out; } /* On Linux, we never get partial writes on block devices. */ num_written = write(fd, buffer, num_bytes); if (num_written == -1) { printf("Error writing data.\n"); ret = HVB_IO_ERROR_IO; goto out; } out: if (fd != -1) { if (close(fd) != 0) { printf("Error closing file descriptor.\n"); } } return ret; } static enum hvb_io_errno hvb_read_rollback(struct hvb_ops *ops, uint64_t rollback_index_location, uint64_t *out_rollback_index) { if (out_rollback_index != NULL) { *out_rollback_index = 0; } return HVB_IO_OK; } static enum hvb_io_errno hvb_write_rollback(struct hvb_ops *ops, uint64_t rollback_index_location, uint64_t rollback_index) { return HVB_IO_OK; } static enum hvb_io_errno hvb_get_partiton_uuid(struct hvb_ops *ops, const char *partition, char *uuid_buf, uint64_t uuid_buf_size) { if (uuid_buf != NULL && uuid_buf_size > 0) { uuid_buf[0] = '\0'; } return HVB_IO_OK; } static enum hvb_io_errno hvb_get_partiton_size(struct hvb_ops *ops, const char *partition, uint64_t *out_size_in_bytes) { int fd; enum hvb_io_errno ret = HVB_IO_OK; fd = open(partition, O_WRONLY); if (fd == -1) { printf("Error opening %s partition.\n", partition); ret = HVB_IO_ERROR_IO; goto out; } if (out_size_in_bytes != NULL) { if (ioctl(fd, BLKGETSIZE64, out_size_in_bytes) != 0) { printf("Error getting size of %s partition.\n", partition); ret = HVB_IO_ERROR_IO; goto out; } } out: if (fd != -1) { if (close(fd) != 0) { printf("Error closing file descriptor.\n"); } } return ret; } static struct hvb_ops *hvb_ops_user(void) { struct hvb_ops *hvb_ops; hvb_ops = (struct hvb_ops *)hvb_malloc(sizeof(struct hvb_ops)); if (!hvb_ops) { printf("Error malloc for hvb_ops.\n"); return NULL; } hvb_ops->user_data = hvb_ops; hvb_ops->read_partition = hvb_read_partition; hvb_ops->write_partition = hvb_write_partition; hvb_ops->read_rollback = hvb_read_rollback; hvb_ops->write_rollback = hvb_write_rollback; hvb_ops->get_partiton_uuid = hvb_get_partiton_uuid; hvb_ops->get_partiton_size = hvb_get_partiton_size; return hvb_ops; } int main(void) { int ret = -1; enum hvb_errno sub_ret = HVB_OK; struct hvb_verified_data *verified_data = NULL; printf("hvb main function start.\n"); g_hvb_ops = hvb_ops_user(); if (!g_hvb_ops) { printf("failed to get hvb_ops_user.\n"); goto out; } sub_ret = hvb_chain_verify(g_hvb_ops, "rvt", &verified_data); if (sub_ret != HVB_OK) { printf("hvb verity error.\n"); goto out; } printf("hvb main end.\n"); out: if (g_hvb_ops != NULL) { hvb_free(g_hvb_ops); } return ret; }