99 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * vpd_decode.c4 *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}99