17a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev/* 27a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * Copyright (C) 2016 The Android Open Source Project 37a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * 47a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * Licensed under the Apache License, Version 2.0 (the "License"); 57a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * you may not use this file except in compliance with the License. 67a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * You may obtain a copy of the License at 77a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * 87a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * http://www.apache.org/licenses/LICENSE-2.0 97a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * 107a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * Unless required by applicable law or agreed to in writing, software 117a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * distributed under the License is distributed on an "AS IS" BASIS, 127a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * See the License for the specific language governing permissions and 147a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * limitations under the License. 157a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev */ 167a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 177a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <errno.h> 187a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <fcntl.h> 197a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <stdint.h> 207a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <stdio.h> 217a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <stdlib.h> 227a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <string.h> 237a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <sys/ioctl.h> 24cfd5b080af8de527d768f0ff7902c26af8d49307Mark Salyzyn#include <unistd.h> 257a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 267a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <linux/major.h> 277a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include <linux/mmc/ioctl.h> 287a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 297a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include "ipc.h" 307a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include "log.h" 317a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include "rpmb.h" 327a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#include "storage.h" 337a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 347a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_READ_MULTIPLE_BLOCK 18 357a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_WRITE_MULTIPLE_BLOCK 25 367a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_RELIABLE_WRITE_FLAG (1 << 31) 377a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 387a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_RSP_PRESENT (1 << 0) 397a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_RSP_CRC (1 << 2) 407a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_RSP_OPCODE (1 << 4) 417a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_CMD_ADTC (1 << 5) 427a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_RSP_SPI_S1 (1 << 7) 437a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_RSP_R1 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) 447a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_RSP_SPI_R1 (MMC_RSP_SPI_S1) 457a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 467a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_WRITE_FLAG_R 0 477a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_WRITE_FLAG_W 1 487a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_WRITE_FLAG_RELW (MMC_WRITE_FLAG_W | MMC_RELIABLE_WRITE_FLAG) 497a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 507a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#define MMC_BLOCK_SIZE 512 517a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 527a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic int rpmb_fd = -1; 537a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic uint8_t read_buf[4096]; 547a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 557a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#ifdef RPMB_DEBUG 567a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 577a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevstatic void print_buf(const char *prefix, const uint8_t *buf, size_t size) 587a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 597a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev size_t i; 607a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 617a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev printf("%s @%p [%zu]", prefix, buf, size); 627a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev for (i = 0; i < size; i++) { 637a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (i && i % 32 == 0) 647a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev printf("\n%*s", (int) strlen(prefix), ""); 657a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev printf(" %02x", buf[i]); 667a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 677a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev printf("\n"); 687a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev fflush(stdout); 697a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 707a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 717a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#endif 727a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 737a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 747a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevint rpmb_send(struct storage_msg *msg, const void *r, size_t req_len) 757a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 767a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int rc; 777a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev struct { 787a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev struct mmc_ioc_multi_cmd multi; 797a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev struct mmc_ioc_cmd cmd_buf[3]; 807a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } mmc = {}; 817a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev struct mmc_ioc_cmd *cmd = mmc.multi.cmds; 827a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const struct storage_rpmb_send_req *req = r; 837a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 847a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req_len < sizeof(*req)) { 857a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGW("malformed rpmb request: invalid length (%zu < %zu)\n", 867a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev req_len, sizeof(*req)); 877a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 887a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 897a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 907a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 917a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev size_t expected_len = 927a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev sizeof(*req) + req->reliable_write_size + req->write_size; 937a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req_len != expected_len) { 947a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGW("malformed rpmb request: invalid length (%zu != %zu)\n", 957a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev req_len, expected_len); 967a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 977a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 987a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 997a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1007a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev const uint8_t *write_buf = req->payload; 1017a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req->reliable_write_size) { 1027a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if ((req->reliable_write_size % MMC_BLOCK_SIZE) != 0) { 1037a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGW("invalid reliable write size %u\n", req->reliable_write_size); 1047a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 1057a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 1067a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1077a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1087a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->write_flag = MMC_WRITE_FLAG_RELW; 1097a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->opcode = MMC_WRITE_MULTIPLE_BLOCK; 1107a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 1117a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->blksz = MMC_BLOCK_SIZE; 1127a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->blocks = req->reliable_write_size / MMC_BLOCK_SIZE; 1137a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev mmc_ioc_cmd_set_data((*cmd), write_buf); 1147a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#ifdef RPMB_DEBUG 1157a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGI("opcode: 0x%x, write_flag: 0x%x\n", cmd->opcode, cmd->write_flag); 1167a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev print_buf("request: ", write_buf, req->reliable_write_size); 1177a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#endif 1187a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev write_buf += req->reliable_write_size; 1197a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev mmc.multi.num_of_cmds++; 1207a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd++; 1217a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1227a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1237a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req->write_size) { 1247a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if ((req->write_size % MMC_BLOCK_SIZE) != 0) { 1257a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGW("invalid write size %u\n", req->write_size); 1267a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 1277a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 1287a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1297a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1307a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->write_flag = MMC_WRITE_FLAG_W; 1317a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->opcode = MMC_WRITE_MULTIPLE_BLOCK; 1327a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 1337a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->blksz = MMC_BLOCK_SIZE; 1347a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->blocks = req->write_size / MMC_BLOCK_SIZE; 1357a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev mmc_ioc_cmd_set_data((*cmd), write_buf); 1367a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#ifdef RPMB_DEBUG 1377a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGI("opcode: 0x%x, write_flag: 0x%x\n", cmd->opcode, cmd->write_flag); 1387a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev print_buf("request: ", write_buf, req->write_size); 1397a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#endif 1407a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev write_buf += req->write_size; 1417a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev mmc.multi.num_of_cmds++; 1427a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd++; 1437a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1447a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1457a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req->read_size) { 1467a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req->read_size % MMC_BLOCK_SIZE != 0 || 1477a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev req->read_size > sizeof(read_buf)) { 1487a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: invalid read size %u\n", __func__, req->read_size); 1497a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_NOT_VALID; 1507a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 1517a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1527a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1537a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->write_flag = MMC_WRITE_FLAG_R; 1547a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->opcode = MMC_READ_MULTIPLE_BLOCK; 1557a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC, 1567a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->blksz = MMC_BLOCK_SIZE; 1577a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd->blocks = req->read_size / MMC_BLOCK_SIZE; 1587a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev mmc_ioc_cmd_set_data((*cmd), read_buf); 1597a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#ifdef RPMB_DEBUG 1607a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGI("opcode: 0x%x, write_flag: 0x%x\n", cmd->opcode, cmd->write_flag); 1617a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#endif 1627a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev mmc.multi.num_of_cmds++; 1637a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev cmd++; 1647a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1657a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1667a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = ioctl(rpmb_fd, MMC_IOC_MULTI_CMD, &mmc.multi); 1677a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 1687a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("%s: mmc ioctl failed: %d, %s\n", __func__, rc, strerror(errno)); 1697a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_ERR_GENERIC; 1707a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev goto err_response; 1717a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1727a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#ifdef RPMB_DEBUG 1737a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (req->read_size) 1747a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev print_buf("response: ", read_buf, req->read_size); 1757a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev#endif 1767a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1777a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (msg->flags & STORAGE_MSG_FLAG_POST_COMMIT) { 1787a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev /* 1797a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * Nothing todo for post msg commit request as MMC_IOC_MULTI_CMD 1807a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev * is fully synchronous in this implementation. 1817a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev */ 1827a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 1837a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1847a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev msg->result = STORAGE_NO_ERROR; 1857a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, read_buf, req->read_size); 1867a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1877a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleeverr_response: 1887a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return ipc_respond(msg, NULL, 0); 1897a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 1907a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1917a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1927a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevint rpmb_open(const char *rpmb_devname) 1937a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 1947a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev int rc; 1957a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 1967a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rc = open(rpmb_devname, O_RDWR, 0); 1977a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev if (rc < 0) { 1987a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev ALOGE("unable (%d) to open rpmb device '%s': %s\n", 1997a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev errno, rpmb_devname, strerror(errno)); 2007a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return rc; 2017a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev } 2027a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rpmb_fd = rc; 2037a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev return 0; 2047a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 2057a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 2067a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleevvoid rpmb_close(void) 2077a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev{ 2087a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev close(rpmb_fd); 2097a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev rpmb_fd = -1; 2107a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev} 2117a2bc37af59a0d9a931347316ac5c86435a1dccbMichael Ryleev 212