^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * vpd_decode.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Google VPD decoding routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2017 Google Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "vpd_decode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static int vpd_decode_len(const u32 max_len, const u8 *in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) u32 *length, u32 *decoded_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) u8 more;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) if (!length || !decoded_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) return VPD_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (i >= max_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return VPD_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) more = in[i] & 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *length <<= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *length |= in[i] & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ++i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) } while (more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *decoded_len = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return VPD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static int vpd_decode_entry(const u32 max_len, const u8 *input_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u32 *_consumed, const u8 **entry, u32 *entry_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 decoded_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u32 consumed = *_consumed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (vpd_decode_len(max_len - consumed, &input_buf[consumed],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) entry_len, &decoded_len) != VPD_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return VPD_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (max_len - consumed < decoded_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return VPD_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) consumed += decoded_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *entry = input_buf + consumed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* entry_len is untrusted data and must be checked again. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (max_len - consumed < *entry_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return VPD_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) consumed += *entry_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *_consumed = consumed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return VPD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int vpd_decode_string(const u32 max_len, const u8 *input_buf, u32 *consumed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) vpd_decode_callback callback, void *callback_arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u32 key_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u32 value_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) const u8 *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) const u8 *value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (*consumed >= max_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return VPD_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) type = input_buf[*consumed];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) case VPD_TYPE_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) case VPD_TYPE_STRING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) (*consumed)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (vpd_decode_entry(max_len, input_buf, consumed, &key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) &key_len) != VPD_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return VPD_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (vpd_decode_entry(max_len, input_buf, consumed, &value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) &value_len) != VPD_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return VPD_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (type == VPD_TYPE_STRING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return callback(key, key_len, value, value_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) callback_arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return VPD_FAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return VPD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }