blob: 545fd8106f67fdda47bef9853d7e54c19622b2fa [file] [log] [blame]
Hung-Te Lin6eaaafa2014-02-21 16:21:00 +08001/*
2 * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 *
6 */
7#include <assert.h>
8#include "lib_vpd.h"
9
10int decodeLen(
11 const int32_t max_len,
12 const uint8_t *in,
13 int32_t *length,
14 int32_t *decoded_len) {
15 uint8_t more;
16 int i = 0;
17
18 assert(length);
19 assert(decoded_len);
20
21 *length = 0;
22 do {
23 if (i >= max_len) return VPD_FAIL;
24 more = in[i] & 0x80;
25 *length <<= 7;
26 *length |= in[i] & 0x7f;
27 ++i;
28 } while (more);
29
30 *decoded_len = i;
31
32 return VPD_OK;
33}
34
35/* Sequentially decodes type, key, and value.
36 */
37int decodeVpdString(
38 const int32_t max_len,
39 const uint8_t *input_buf,
40 int32_t *consumed,
41 VpdDecodeCallback callback,
42 void *callback_arg) {
43 int type;
44 int32_t key_len, value_len;
45 int32_t decoded_len;
46 const uint8_t *key, *value;
47
48 /* type */
49 if (*consumed >= max_len)
50 return VPD_FAIL;
51
52 type = input_buf[*consumed];
53 switch (type) {
54 case VPD_TYPE_INFO:
55 case VPD_TYPE_STRING:
56 (*consumed)++;
57
58 /* key */
59 if (VPD_OK != decodeLen(max_len - *consumed, &input_buf[*consumed],
60 &key_len, &decoded_len) ||
61 *consumed + decoded_len >= max_len) {
62 return VPD_FAIL;
63 }
64
65 *consumed += decoded_len;
66 key = &input_buf[*consumed];
67 *consumed += key_len;
68
69 /* value */
70 if (VPD_OK != decodeLen(max_len - *consumed, &input_buf[*consumed],
71 &value_len, &decoded_len) ||
72 *consumed + decoded_len > max_len) {
73 return VPD_FAIL;
74 }
75 *consumed += decoded_len;
76 value = &input_buf[*consumed];
77 *consumed += value_len;
78
79 if (type == VPD_TYPE_STRING)
80 return callback(key, key_len, value, value_len, callback_arg);
81
82 return VPD_OK;
83
84 default:
85 return VPD_FAIL;
86 break;
87 }
88 return VPD_OK;
89}