Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/firmware/google/vpd_decode.c
26444 views
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
12
static 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
36
static 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
60
int 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
}
99
100