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