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

nal-rbsp.c (5876B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2019-2020 Pengutronix, Michael Tretter <kernel@pengutronix.de>
      4 *
      5 * Helper functions to generate a raw byte sequence payload from values.
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/types.h>
     10#include <linux/string.h>
     11#include <linux/v4l2-controls.h>
     12
     13#include <linux/device.h>
     14#include <linux/export.h>
     15#include <linux/log2.h>
     16
     17#include "nal-rbsp.h"
     18
     19void rbsp_init(struct rbsp *rbsp, void *addr, size_t size,
     20	       struct nal_rbsp_ops *ops)
     21{
     22	if (!rbsp)
     23		return;
     24
     25	rbsp->data = addr;
     26	rbsp->size = size;
     27	rbsp->pos = 0;
     28	rbsp->ops = ops;
     29	rbsp->error = 0;
     30}
     31
     32void rbsp_unsupported(struct rbsp *rbsp)
     33{
     34	rbsp->error = -EINVAL;
     35}
     36
     37static int rbsp_read_bits(struct rbsp *rbsp, int n, unsigned int *value);
     38static int rbsp_write_bits(struct rbsp *rbsp, int n, unsigned int value);
     39
     40/*
     41 * When reading or writing, the emulation_prevention_three_byte is detected
     42 * only when the 2 one bits need to be inserted. Therefore, we are not
     43 * actually adding the 0x3 byte, but the 2 one bits and the six 0 bits of the
     44 * next byte.
     45 */
     46#define EMULATION_PREVENTION_THREE_BYTE (0x3 << 6)
     47
     48static int add_emulation_prevention_three_byte(struct rbsp *rbsp)
     49{
     50	rbsp->num_consecutive_zeros = 0;
     51	rbsp_write_bits(rbsp, 8, EMULATION_PREVENTION_THREE_BYTE);
     52
     53	return 0;
     54}
     55
     56static int discard_emulation_prevention_three_byte(struct rbsp *rbsp)
     57{
     58	unsigned int tmp = 0;
     59
     60	rbsp->num_consecutive_zeros = 0;
     61	rbsp_read_bits(rbsp, 8, &tmp);
     62	if (tmp != EMULATION_PREVENTION_THREE_BYTE)
     63		return -EINVAL;
     64
     65	return 0;
     66}
     67
     68static inline int rbsp_read_bit(struct rbsp *rbsp)
     69{
     70	int shift;
     71	int ofs;
     72	int bit;
     73	int err;
     74
     75	if (rbsp->num_consecutive_zeros == 22) {
     76		err = discard_emulation_prevention_three_byte(rbsp);
     77		if (err)
     78			return err;
     79	}
     80
     81	shift = 7 - (rbsp->pos % 8);
     82	ofs = rbsp->pos / 8;
     83	if (ofs >= rbsp->size)
     84		return -EINVAL;
     85
     86	bit = (rbsp->data[ofs] >> shift) & 1;
     87
     88	rbsp->pos++;
     89
     90	if (bit == 1 ||
     91	    (rbsp->num_consecutive_zeros < 7 && (rbsp->pos % 8 == 0)))
     92		rbsp->num_consecutive_zeros = 0;
     93	else
     94		rbsp->num_consecutive_zeros++;
     95
     96	return bit;
     97}
     98
     99static inline int rbsp_write_bit(struct rbsp *rbsp, bool value)
    100{
    101	int shift;
    102	int ofs;
    103
    104	if (rbsp->num_consecutive_zeros == 22)
    105		add_emulation_prevention_three_byte(rbsp);
    106
    107	shift = 7 - (rbsp->pos % 8);
    108	ofs = rbsp->pos / 8;
    109	if (ofs >= rbsp->size)
    110		return -EINVAL;
    111
    112	rbsp->data[ofs] &= ~(1 << shift);
    113	rbsp->data[ofs] |= value << shift;
    114
    115	rbsp->pos++;
    116
    117	if (value ||
    118	    (rbsp->num_consecutive_zeros < 7 && (rbsp->pos % 8 == 0))) {
    119		rbsp->num_consecutive_zeros = 0;
    120	} else {
    121		rbsp->num_consecutive_zeros++;
    122	}
    123
    124	return 0;
    125}
    126
    127static inline int rbsp_read_bits(struct rbsp *rbsp, int n, unsigned int *value)
    128{
    129	int i;
    130	int bit;
    131	unsigned int tmp = 0;
    132
    133	if (n > 8 * sizeof(*value))
    134		return -EINVAL;
    135
    136	for (i = n; i > 0; i--) {
    137		bit = rbsp_read_bit(rbsp);
    138		if (bit < 0)
    139			return bit;
    140		tmp |= bit << (i - 1);
    141	}
    142
    143	if (value)
    144		*value = tmp;
    145
    146	return 0;
    147}
    148
    149static int rbsp_write_bits(struct rbsp *rbsp, int n, unsigned int value)
    150{
    151	int ret;
    152
    153	if (n > 8 * sizeof(value))
    154		return -EINVAL;
    155
    156	while (n--) {
    157		ret = rbsp_write_bit(rbsp, (value >> n) & 1);
    158		if (ret)
    159			return ret;
    160	}
    161
    162	return 0;
    163}
    164
    165static int rbsp_read_uev(struct rbsp *rbsp, unsigned int *value)
    166{
    167	int leading_zero_bits = 0;
    168	unsigned int tmp = 0;
    169	int ret;
    170
    171	while ((ret = rbsp_read_bit(rbsp)) == 0)
    172		leading_zero_bits++;
    173	if (ret < 0)
    174		return ret;
    175
    176	if (leading_zero_bits > 0) {
    177		ret = rbsp_read_bits(rbsp, leading_zero_bits, &tmp);
    178		if (ret)
    179			return ret;
    180	}
    181
    182	if (value)
    183		*value = (1 << leading_zero_bits) - 1 + tmp;
    184
    185	return 0;
    186}
    187
    188static int rbsp_write_uev(struct rbsp *rbsp, unsigned int *value)
    189{
    190	int ret;
    191	int leading_zero_bits;
    192
    193	if (!value)
    194		return -EINVAL;
    195
    196	leading_zero_bits = ilog2(*value + 1);
    197
    198	ret = rbsp_write_bits(rbsp, leading_zero_bits, 0);
    199	if (ret)
    200		return ret;
    201
    202	return rbsp_write_bits(rbsp, leading_zero_bits + 1, *value + 1);
    203}
    204
    205static int rbsp_read_sev(struct rbsp *rbsp, int *value)
    206{
    207	int ret;
    208	unsigned int tmp;
    209
    210	ret = rbsp_read_uev(rbsp, &tmp);
    211	if (ret)
    212		return ret;
    213
    214	if (value) {
    215		if (tmp & 1)
    216			*value = (tmp + 1) / 2;
    217		else
    218			*value = -(tmp / 2);
    219	}
    220
    221	return 0;
    222}
    223
    224static int rbsp_write_sev(struct rbsp *rbsp, int *value)
    225{
    226	unsigned int tmp;
    227
    228	if (!value)
    229		return -EINVAL;
    230
    231	if (*value > 0)
    232		tmp = (2 * (*value)) | 1;
    233	else
    234		tmp = -2 * (*value);
    235
    236	return rbsp_write_uev(rbsp, &tmp);
    237}
    238
    239static int __rbsp_write_bit(struct rbsp *rbsp, int *value)
    240{
    241	return rbsp_write_bit(rbsp, *value);
    242}
    243
    244static int __rbsp_write_bits(struct rbsp *rbsp, int n, unsigned int *value)
    245{
    246	return rbsp_write_bits(rbsp, n, *value);
    247}
    248
    249struct nal_rbsp_ops write = {
    250	.rbsp_bit = __rbsp_write_bit,
    251	.rbsp_bits = __rbsp_write_bits,
    252	.rbsp_uev = rbsp_write_uev,
    253	.rbsp_sev = rbsp_write_sev,
    254};
    255
    256static int __rbsp_read_bit(struct rbsp *rbsp, int *value)
    257{
    258	int tmp = rbsp_read_bit(rbsp);
    259
    260	if (tmp < 0)
    261		return tmp;
    262	*value = tmp;
    263
    264	return 0;
    265}
    266
    267struct nal_rbsp_ops read = {
    268	.rbsp_bit = __rbsp_read_bit,
    269	.rbsp_bits = rbsp_read_bits,
    270	.rbsp_uev = rbsp_read_uev,
    271	.rbsp_sev = rbsp_read_sev,
    272};
    273
    274void rbsp_bit(struct rbsp *rbsp, int *value)
    275{
    276	if (rbsp->error)
    277		return;
    278	rbsp->error = rbsp->ops->rbsp_bit(rbsp, value);
    279}
    280
    281void rbsp_bits(struct rbsp *rbsp, int n, int *value)
    282{
    283	if (rbsp->error)
    284		return;
    285	rbsp->error = rbsp->ops->rbsp_bits(rbsp, n, value);
    286}
    287
    288void rbsp_uev(struct rbsp *rbsp, unsigned int *value)
    289{
    290	if (rbsp->error)
    291		return;
    292	rbsp->error = rbsp->ops->rbsp_uev(rbsp, value);
    293}
    294
    295void rbsp_sev(struct rbsp *rbsp, int *value)
    296{
    297	if (rbsp->error)
    298		return;
    299	rbsp->error = rbsp->ops->rbsp_sev(rbsp, value);
    300}
    301
    302void rbsp_trailing_bits(struct rbsp *rbsp)
    303{
    304	unsigned int rbsp_stop_one_bit = 1;
    305	unsigned int rbsp_alignment_zero_bit = 0;
    306
    307	rbsp_bit(rbsp, &rbsp_stop_one_bit);
    308	rbsp_bits(rbsp, round_up(rbsp->pos, 8) - rbsp->pos,
    309		  &rbsp_alignment_zero_bit);
    310}