cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ssh_msgb.h (5615B)


      1/* SPDX-License-Identifier: GPL-2.0+ */
      2/*
      3 * SSH message builder functions.
      4 *
      5 * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
      6 */
      7
      8#ifndef _SURFACE_AGGREGATOR_SSH_MSGB_H
      9#define _SURFACE_AGGREGATOR_SSH_MSGB_H
     10
     11#include <asm/unaligned.h>
     12#include <linux/types.h>
     13
     14#include <linux/surface_aggregator/controller.h>
     15#include <linux/surface_aggregator/serial_hub.h>
     16
     17/**
     18 * struct msgbuf - Buffer struct to construct SSH messages.
     19 * @begin: Pointer to the beginning of the allocated buffer space.
     20 * @end:   Pointer to the end (one past last element) of the allocated buffer
     21 *         space.
     22 * @ptr:   Pointer to the first free element in the buffer.
     23 */
     24struct msgbuf {
     25	u8 *begin;
     26	u8 *end;
     27	u8 *ptr;
     28};
     29
     30/**
     31 * msgb_init() - Initialize the given message buffer struct.
     32 * @msgb: The buffer struct to initialize
     33 * @ptr:  Pointer to the underlying memory by which the buffer will be backed.
     34 * @cap:  Size of the underlying memory.
     35 *
     36 * Initialize the given message buffer struct using the provided memory as
     37 * backing.
     38 */
     39static inline void msgb_init(struct msgbuf *msgb, u8 *ptr, size_t cap)
     40{
     41	msgb->begin = ptr;
     42	msgb->end = ptr + cap;
     43	msgb->ptr = ptr;
     44}
     45
     46/**
     47 * msgb_bytes_used() - Return the current number of bytes used in the buffer.
     48 * @msgb: The message buffer.
     49 */
     50static inline size_t msgb_bytes_used(const struct msgbuf *msgb)
     51{
     52	return msgb->ptr - msgb->begin;
     53}
     54
     55static inline void __msgb_push_u8(struct msgbuf *msgb, u8 value)
     56{
     57	*msgb->ptr = value;
     58	msgb->ptr += sizeof(u8);
     59}
     60
     61static inline void __msgb_push_u16(struct msgbuf *msgb, u16 value)
     62{
     63	put_unaligned_le16(value, msgb->ptr);
     64	msgb->ptr += sizeof(u16);
     65}
     66
     67/**
     68 * msgb_push_u16() - Push a u16 value to the buffer.
     69 * @msgb:  The message buffer.
     70 * @value: The value to push to the buffer.
     71 */
     72static inline void msgb_push_u16(struct msgbuf *msgb, u16 value)
     73{
     74	if (WARN_ON(msgb->ptr + sizeof(u16) > msgb->end))
     75		return;
     76
     77	__msgb_push_u16(msgb, value);
     78}
     79
     80/**
     81 * msgb_push_syn() - Push SSH SYN bytes to the buffer.
     82 * @msgb: The message buffer.
     83 */
     84static inline void msgb_push_syn(struct msgbuf *msgb)
     85{
     86	msgb_push_u16(msgb, SSH_MSG_SYN);
     87}
     88
     89/**
     90 * msgb_push_buf() - Push raw data to the buffer.
     91 * @msgb: The message buffer.
     92 * @buf:  The data to push to the buffer.
     93 * @len:  The length of the data to push to the buffer.
     94 */
     95static inline void msgb_push_buf(struct msgbuf *msgb, const u8 *buf, size_t len)
     96{
     97	msgb->ptr = memcpy(msgb->ptr, buf, len) + len;
     98}
     99
    100/**
    101 * msgb_push_crc() - Compute CRC and push it to the buffer.
    102 * @msgb: The message buffer.
    103 * @buf:  The data for which the CRC should be computed.
    104 * @len:  The length of the data for which the CRC should be computed.
    105 */
    106static inline void msgb_push_crc(struct msgbuf *msgb, const u8 *buf, size_t len)
    107{
    108	msgb_push_u16(msgb, ssh_crc(buf, len));
    109}
    110
    111/**
    112 * msgb_push_frame() - Push a SSH message frame header to the buffer.
    113 * @msgb: The message buffer
    114 * @ty:   The type of the frame.
    115 * @len:  The length of the payload of the frame.
    116 * @seq:  The sequence ID of the frame/packet.
    117 */
    118static inline void msgb_push_frame(struct msgbuf *msgb, u8 ty, u16 len, u8 seq)
    119{
    120	u8 *const begin = msgb->ptr;
    121
    122	if (WARN_ON(msgb->ptr + sizeof(struct ssh_frame) > msgb->end))
    123		return;
    124
    125	__msgb_push_u8(msgb, ty);	/* Frame type. */
    126	__msgb_push_u16(msgb, len);	/* Frame payload length. */
    127	__msgb_push_u8(msgb, seq);	/* Frame sequence ID. */
    128
    129	msgb_push_crc(msgb, begin, msgb->ptr - begin);
    130}
    131
    132/**
    133 * msgb_push_ack() - Push a SSH ACK frame to the buffer.
    134 * @msgb: The message buffer
    135 * @seq:  The sequence ID of the frame/packet to be ACKed.
    136 */
    137static inline void msgb_push_ack(struct msgbuf *msgb, u8 seq)
    138{
    139	/* SYN. */
    140	msgb_push_syn(msgb);
    141
    142	/* ACK-type frame + CRC. */
    143	msgb_push_frame(msgb, SSH_FRAME_TYPE_ACK, 0x00, seq);
    144
    145	/* Payload CRC (ACK-type frames do not have a payload). */
    146	msgb_push_crc(msgb, msgb->ptr, 0);
    147}
    148
    149/**
    150 * msgb_push_nak() - Push a SSH NAK frame to the buffer.
    151 * @msgb: The message buffer
    152 */
    153static inline void msgb_push_nak(struct msgbuf *msgb)
    154{
    155	/* SYN. */
    156	msgb_push_syn(msgb);
    157
    158	/* NAK-type frame + CRC. */
    159	msgb_push_frame(msgb, SSH_FRAME_TYPE_NAK, 0x00, 0x00);
    160
    161	/* Payload CRC (ACK-type frames do not have a payload). */
    162	msgb_push_crc(msgb, msgb->ptr, 0);
    163}
    164
    165/**
    166 * msgb_push_cmd() - Push a SSH command frame with payload to the buffer.
    167 * @msgb: The message buffer.
    168 * @seq:  The sequence ID (SEQ) of the frame/packet.
    169 * @rqid: The request ID (RQID) of the request contained in the frame.
    170 * @rqst: The request to wrap in the frame.
    171 */
    172static inline void msgb_push_cmd(struct msgbuf *msgb, u8 seq, u16 rqid,
    173				 const struct ssam_request *rqst)
    174{
    175	const u8 type = SSH_FRAME_TYPE_DATA_SEQ;
    176	u8 *cmd;
    177
    178	/* SYN. */
    179	msgb_push_syn(msgb);
    180
    181	/* Command frame + CRC. */
    182	msgb_push_frame(msgb, type, sizeof(struct ssh_command) + rqst->length, seq);
    183
    184	/* Frame payload: Command struct + payload. */
    185	if (WARN_ON(msgb->ptr + sizeof(struct ssh_command) > msgb->end))
    186		return;
    187
    188	cmd = msgb->ptr;
    189
    190	__msgb_push_u8(msgb, SSH_PLD_TYPE_CMD);		/* Payload type. */
    191	__msgb_push_u8(msgb, rqst->target_category);	/* Target category. */
    192	__msgb_push_u8(msgb, rqst->target_id);		/* Target ID (out). */
    193	__msgb_push_u8(msgb, 0x00);			/* Target ID (in). */
    194	__msgb_push_u8(msgb, rqst->instance_id);	/* Instance ID. */
    195	__msgb_push_u16(msgb, rqid);			/* Request ID. */
    196	__msgb_push_u8(msgb, rqst->command_id);		/* Command ID. */
    197
    198	/* Command payload. */
    199	msgb_push_buf(msgb, rqst->payload, rqst->length);
    200
    201	/* CRC for command struct + payload. */
    202	msgb_push_crc(msgb, cmd, msgb->ptr - cmd);
    203}
    204
    205#endif /* _SURFACE_AGGREGATOR_SSH_MSGB_H */