root/drivers/firmware/google/vpd_decode.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vpd_decode_len
  2. vpd_decode_entry
  3. vpd_decode_string

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * vpd_decode.c
   4  *
   5  * Google VPD decoding routines.
   6  *
   7  * Copyright 2017 Google Inc.
   8  */
   9 
  10 #include "vpd_decode.h"
  11 
  12 static 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 
  36 static 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 
  60 int 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 }

/* [<][>][^][v][top][bottom][index][help] */