168 lines
5.2 KiB
C
168 lines
5.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
||
/*
|
||
* Copyright (C) 2015-2019 Intel Corp. All rights reserved
|
||
* Copyright (C) 2021-2022 Linaro Ltd
|
||
*/
|
||
#ifndef __RPMB_H__
|
||
#define __RPMB_H__
|
||
|
||
#include <linux/device.h>
|
||
#include <linux/types.h>
|
||
|
||
/**
|
||
* enum rpmb_type - type of underlying storage technology
|
||
*
|
||
* @RPMB_TYPE_EMMC : emmc (JESD84-B50.1)
|
||
* @RPMB_TYPE_UFS : UFS (JESD220)
|
||
* @RPMB_TYPE_NVME : NVM Express
|
||
*/
|
||
enum rpmb_type {
|
||
RPMB_TYPE_EMMC,
|
||
RPMB_TYPE_UFS,
|
||
RPMB_TYPE_NVME,
|
||
};
|
||
|
||
/**
|
||
* struct rpmb_descr - RPMB description provided by the underlying block device
|
||
*
|
||
* @type : block device type
|
||
* @route_frames : routes frames to and from the RPMB device
|
||
* @dev_id : unique device identifier read from the hardware
|
||
* @dev_id_len : length of unique device identifier
|
||
* @reliable_wr_count: number of sectors that can be written in one access
|
||
* @capacity : capacity of the device in units of 128K
|
||
*
|
||
* @dev_id is intended to be used as input when deriving the authenticaion key.
|
||
*/
|
||
struct rpmb_descr {
|
||
enum rpmb_type type;
|
||
int (*route_frames)(struct device *dev, u8 *req, unsigned int req_len,
|
||
u8 *resp, unsigned int resp_len);
|
||
u8 *dev_id;
|
||
size_t dev_id_len;
|
||
u16 reliable_wr_count;
|
||
u16 capacity;
|
||
};
|
||
|
||
/**
|
||
* struct rpmb_dev - device which can support RPMB partition
|
||
*
|
||
* @dev : device
|
||
* @id : device_id
|
||
* @list_node : linked list node
|
||
* @descr : RPMB description
|
||
*/
|
||
struct rpmb_dev {
|
||
struct device dev;
|
||
int id;
|
||
struct list_head list_node;
|
||
struct rpmb_descr descr;
|
||
};
|
||
|
||
#define to_rpmb_dev(x) container_of((x), struct rpmb_dev, dev)
|
||
|
||
/**
|
||
* struct rpmb_frame - RPMB frame structure for authenticated access
|
||
*
|
||
* @stuff : stuff bytes, a padding/reserved area of 196 bytes at the
|
||
* beginning of the RPMB frame. They don’t carry meaningful
|
||
* data but are required to make the frame exactly 512 bytes.
|
||
* @key_mac : The authentication key or the message authentication
|
||
* code (MAC) depending on the request/response type.
|
||
* The MAC will be delivered in the last (or the only)
|
||
* block of data.
|
||
* @data : Data to be written or read by signed access.
|
||
* @nonce : Random number generated by the host for the requests
|
||
* and copied to the response by the RPMB engine.
|
||
* @write_counter: Counter value for the total amount of the successful
|
||
* authenticated data write requests made by the host.
|
||
* @addr : Address of the data to be programmed to or read
|
||
* from the RPMB. Address is the serial number of
|
||
* the accessed block (half sector 256B).
|
||
* @block_count : Number of blocks (half sectors, 256B) requested to be
|
||
* read/programmed.
|
||
* @result : Includes information about the status of the write counter
|
||
* (valid, expired) and result of the access made to the RPMB.
|
||
* @req_resp : Defines the type of request and response to/from the memory.
|
||
*
|
||
* The stuff bytes and big-endian properties are modeled to fit to the spec.
|
||
*/
|
||
struct rpmb_frame {
|
||
u8 stuff[196];
|
||
u8 key_mac[32];
|
||
u8 data[256];
|
||
u8 nonce[16];
|
||
__be32 write_counter;
|
||
__be16 addr;
|
||
__be16 block_count;
|
||
__be16 result;
|
||
__be16 req_resp;
|
||
};
|
||
|
||
#define RPMB_PROGRAM_KEY 0x1 /* Program RPMB Authentication Key */
|
||
#define RPMB_GET_WRITE_COUNTER 0x2 /* Read RPMB write counter */
|
||
#define RPMB_WRITE_DATA 0x3 /* Write data to RPMB partition */
|
||
#define RPMB_READ_DATA 0x4 /* Read data from RPMB partition */
|
||
#define RPMB_RESULT_READ 0x5 /* Read result request (Internal) */
|
||
|
||
#if IS_ENABLED(CONFIG_RPMB)
|
||
struct rpmb_dev *rpmb_dev_get(struct rpmb_dev *rdev);
|
||
void rpmb_dev_put(struct rpmb_dev *rdev);
|
||
struct rpmb_dev *rpmb_dev_find_device(const void *data,
|
||
const struct rpmb_dev *start,
|
||
int (*match)(struct device *dev,
|
||
const void *data));
|
||
int rpmb_interface_register(struct class_interface *intf);
|
||
void rpmb_interface_unregister(struct class_interface *intf);
|
||
struct rpmb_dev *rpmb_dev_register(struct device *dev,
|
||
struct rpmb_descr *descr);
|
||
int rpmb_dev_unregister(struct rpmb_dev *rdev);
|
||
|
||
int rpmb_route_frames(struct rpmb_dev *rdev, u8 *req,
|
||
unsigned int req_len, u8 *resp, unsigned int resp_len);
|
||
|
||
#else
|
||
static inline struct rpmb_dev *rpmb_dev_get(struct rpmb_dev *rdev)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
static inline void rpmb_dev_put(struct rpmb_dev *rdev) { }
|
||
|
||
static inline struct rpmb_dev *
|
||
rpmb_dev_find_device(const void *data, const struct rpmb_dev *start,
|
||
int (*match)(struct device *dev, const void *data))
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
static inline int rpmb_interface_register(struct class_interface *intf)
|
||
{
|
||
return -EOPNOTSUPP;
|
||
}
|
||
|
||
static inline void rpmb_interface_unregister(struct class_interface *intf)
|
||
{
|
||
}
|
||
|
||
static inline struct rpmb_dev *
|
||
rpmb_dev_register(struct device *dev, struct rpmb_descr *descr)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
static inline int rpmb_dev_unregister(struct rpmb_dev *dev)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
static inline int rpmb_route_frames(struct rpmb_dev *rdev, u8 *req,
|
||
unsigned int req_len, u8 *resp,
|
||
unsigned int resp_len)
|
||
{
|
||
return -EOPNOTSUPP;
|
||
}
|
||
#endif /* CONFIG_RPMB */
|
||
|
||
#endif /* __RPMB_H__ */
|