vpd_decode.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * vpd_decode.c
  3. *
  4. * Google VPD decoding routines.
  5. *
  6. * Copyright 2017 Google Inc.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License v2.0 as published by
  10. * the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. */
  17. #include <linux/export.h>
  18. #include "vpd_decode.h"
  19. static int vpd_decode_len(const s32 max_len, const u8 *in,
  20. s32 *length, s32 *decoded_len)
  21. {
  22. u8 more;
  23. int i = 0;
  24. if (!length || !decoded_len)
  25. return VPD_FAIL;
  26. *length = 0;
  27. do {
  28. if (i >= max_len)
  29. return VPD_FAIL;
  30. more = in[i] & 0x80;
  31. *length <<= 7;
  32. *length |= in[i] & 0x7f;
  33. ++i;
  34. } while (more);
  35. *decoded_len = i;
  36. return VPD_OK;
  37. }
  38. int vpd_decode_string(const s32 max_len, const u8 *input_buf, s32 *consumed,
  39. vpd_decode_callback callback, void *callback_arg)
  40. {
  41. int type;
  42. int res;
  43. s32 key_len;
  44. s32 value_len;
  45. s32 decoded_len;
  46. const u8 *key;
  47. const u8 *value;
  48. /* type */
  49. if (*consumed >= max_len)
  50. return VPD_FAIL;
  51. type = input_buf[*consumed];
  52. switch (type) {
  53. case VPD_TYPE_INFO:
  54. case VPD_TYPE_STRING:
  55. (*consumed)++;
  56. /* key */
  57. res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed],
  58. &key_len, &decoded_len);
  59. if (res != VPD_OK || *consumed + decoded_len >= max_len)
  60. return VPD_FAIL;
  61. *consumed += decoded_len;
  62. key = &input_buf[*consumed];
  63. *consumed += key_len;
  64. /* value */
  65. res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed],
  66. &value_len, &decoded_len);
  67. if (res != VPD_OK || *consumed + decoded_len > max_len)
  68. return VPD_FAIL;
  69. *consumed += decoded_len;
  70. value = &input_buf[*consumed];
  71. *consumed += value_len;
  72. if (type == VPD_TYPE_STRING)
  73. return callback(key, key_len, value, value_len,
  74. callback_arg);
  75. break;
  76. default:
  77. return VPD_FAIL;
  78. }
  79. return VPD_OK;
  80. }