aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/vpd/vpd_decode.c
diff options
context:
space:
mode:
authorHung-Te Lin <hungte@chromium.org>2019-05-27 11:02:00 +0800
committerPatrick Georgi <pgeorgi@google.com>2019-06-03 13:22:01 +0000
commitc345570acce55a2cb13a65bf06c4e1d8069f7b36 (patch)
treec75a2e8bf0421b2554515d4c866965b14e588eb6 /src/drivers/vpd/vpd_decode.c
parent6681f05373c2ec07168e279026962d7a63539e93 (diff)
src/driver/vpd: Update lib_vpd from upstream
Update lib_vpd.c (only containing vpd_decode.c) to latest version from https://chromium.googlesource.com/chromiumos/platform/vpd The called module (vpd.c) has been also corrected for new lib_vpd types and constants. BUG=chromium:967209 TEST=select VPD config on kukui; make; boots on at least kukui boards. Change-Id: I3928e9c43cb87caf93fb44ee10434ce80f0a188a Signed-off-by: Hung-Te Lin <hungte@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/33016 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Joel Kitching <kitching@google.com>
Diffstat (limited to 'src/drivers/vpd/vpd_decode.c')
-rw-r--r--src/drivers/vpd/vpd_decode.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/drivers/vpd/vpd_decode.c b/src/drivers/vpd/vpd_decode.c
new file mode 100644
index 0000000000..0eab704ca8
--- /dev/null
+++ b/src/drivers/vpd/vpd_decode.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * This is a copy from upstream:
+ * https://chromium.googlesource.com/chromiumos/platform/vpd/+/master/lib/vpd_decode.c
+ */
+#include "vpd_decode.h"
+
+int vpd_decode_len(
+ const u32 max_len, const u8 *in, u32 *length, u32 *decoded_len)
+{
+ u8 more;
+ int i = 0;
+
+ if (!length || !decoded_len)
+ return VPD_DECODE_FAIL;
+
+ *length = 0;
+ do {
+ if (i >= max_len)
+ return VPD_DECODE_FAIL;
+
+ more = in[i] & 0x80;
+ *length <<= 7;
+ *length |= in[i] & 0x7f;
+ ++i;
+ } while (more);
+
+ *decoded_len = i;
+ return VPD_DECODE_OK;
+}
+
+int vpd_decode_string(
+ const u32 max_len, const u8 *input_buf, u32 *consumed,
+ vpd_decode_callback callback, void *callback_arg)
+{
+ int type;
+ int res;
+ u32 key_len;
+ u32 value_len;
+ u32 decoded_len;
+ const u8 *key;
+ const u8 *value;
+
+ /* type */
+ if (*consumed >= max_len)
+ return VPD_DECODE_FAIL;
+
+ type = input_buf[*consumed];
+
+ switch (type) {
+ case VPD_TYPE_INFO:
+ case VPD_TYPE_STRING:
+ (*consumed)++;
+
+ /* key */
+ res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed],
+ &key_len, &decoded_len);
+ /* key name cannot be empty, and must be followed by value. */
+ if (res != VPD_DECODE_OK || key_len < 1 ||
+ *consumed + decoded_len + key_len >= max_len)
+ return VPD_DECODE_FAIL;
+
+ *consumed += decoded_len;
+ key = &input_buf[*consumed];
+ *consumed += key_len;
+
+ /* value */
+ res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed],
+ &value_len, &decoded_len);
+ /* value can be empty (value_len = 0). */
+ if (res != VPD_DECODE_OK ||
+ *consumed + decoded_len + value_len > max_len)
+ return VPD_DECODE_FAIL;
+
+ *consumed += decoded_len;
+ value = &input_buf[*consumed];
+ *consumed += value_len;
+
+ if (type == VPD_TYPE_STRING)
+ return callback(key, key_len, value, value_len,
+ callback_arg);
+ break;
+
+ default:
+ return VPD_DECODE_FAIL;
+ }
+
+ return VPD_DECODE_OK;
+}