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

vpd_decode.c (1892B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * vpd_decode.c
      4 *
      5 * Google VPD decoding routines.
      6 *
      7 * Copyright 2017 Google Inc.
      8 */
      9
     10#include "vpd_decode.h"
     11
     12static int vpd_decode_len(const u32 max_len, const u8 *in,
     13			  u32 *length, u32 *decoded_len)
     14{
     15	u8 more;
     16	int i = 0;
     17
     18	if (!length || !decoded_len)
     19		return VPD_FAIL;
     20
     21	*length = 0;
     22	do {
     23		if (i >= max_len)
     24			return VPD_FAIL;
     25
     26		more = in[i] & 0x80;
     27		*length <<= 7;
     28		*length |= in[i] & 0x7f;
     29		++i;
     30	} while (more);
     31
     32	*decoded_len = i;
     33	return VPD_OK;
     34}
     35
     36static int vpd_decode_entry(const u32 max_len, const u8 *input_buf,
     37			    u32 *_consumed, const u8 **entry, u32 *entry_len)
     38{
     39	u32 decoded_len;
     40	u32 consumed = *_consumed;
     41
     42	if (vpd_decode_len(max_len - consumed, &input_buf[consumed],
     43			   entry_len, &decoded_len) != VPD_OK)
     44		return VPD_FAIL;
     45	if (max_len - consumed < decoded_len)
     46		return VPD_FAIL;
     47
     48	consumed += decoded_len;
     49	*entry = input_buf + consumed;
     50
     51	/* entry_len is untrusted data and must be checked again. */
     52	if (max_len - consumed < *entry_len)
     53		return VPD_FAIL;
     54
     55	consumed += *entry_len;
     56	*_consumed = consumed;
     57	return VPD_OK;
     58}
     59
     60int vpd_decode_string(const u32 max_len, const u8 *input_buf, u32 *consumed,
     61		      vpd_decode_callback callback, void *callback_arg)
     62{
     63	int type;
     64	u32 key_len;
     65	u32 value_len;
     66	const u8 *key;
     67	const u8 *value;
     68
     69	/* type */
     70	if (*consumed >= max_len)
     71		return VPD_FAIL;
     72
     73	type = input_buf[*consumed];
     74
     75	switch (type) {
     76	case VPD_TYPE_INFO:
     77	case VPD_TYPE_STRING:
     78		(*consumed)++;
     79
     80		if (vpd_decode_entry(max_len, input_buf, consumed, &key,
     81				     &key_len) != VPD_OK)
     82			return VPD_FAIL;
     83
     84		if (vpd_decode_entry(max_len, input_buf, consumed, &value,
     85				     &value_len) != VPD_OK)
     86			return VPD_FAIL;
     87
     88		if (type == VPD_TYPE_STRING)
     89			return callback(key, key_len, value, value_len,
     90					callback_arg);
     91		break;
     92
     93	default:
     94		return VPD_FAIL;
     95	}
     96
     97	return VPD_OK;
     98}