xref: /openbmc/libbej/src/bej_dictionary.c (revision 716c741d1f23da0dbd22e2aaf46197ffc9444071)
1d073aa1aSkasunath #include "bej_dictionary.h"
2d073aa1aSkasunath 
3d073aa1aSkasunath #include <stdbool.h>
4d073aa1aSkasunath #include <stdio.h>
5f68be959Skasunath #include <string.h>
6d073aa1aSkasunath 
7d073aa1aSkasunath /**
8d073aa1aSkasunath  * @brief Get the index for a property offset. First property will be at index
9d073aa1aSkasunath  * 0.
10d073aa1aSkasunath  *
11d073aa1aSkasunath  * @param[in] propertyOffset - a valid property offset.
12d073aa1aSkasunath  * @return index of the property.
13d073aa1aSkasunath  */
bejGetPropertyEntryIndex(uint16_t propertyOffset)14d073aa1aSkasunath static uint16_t bejGetPropertyEntryIndex(uint16_t propertyOffset)
15d073aa1aSkasunath {
16d073aa1aSkasunath     return (propertyOffset - bejDictGetPropertyHeadOffset()) /
17d073aa1aSkasunath            sizeof(struct BejDictionaryProperty);
18d073aa1aSkasunath }
19d073aa1aSkasunath 
20d073aa1aSkasunath /**
21d073aa1aSkasunath  * @brief  Validate a property offset.
22d073aa1aSkasunath  *
23f68be959Skasunath  * @param[in] dictionary - pointer to the dictionary.
24d073aa1aSkasunath  * @param[in] propertyOffset - offset needed to be validated.
25d073aa1aSkasunath  * @return true if propertyOffset is a valid offset.
26d073aa1aSkasunath  */
bejValidatePropertyOffset(const uint8_t * dictionary,uint16_t propertyOffset)27f68be959Skasunath static bool bejValidatePropertyOffset(const uint8_t* dictionary,
28f68be959Skasunath                                       uint16_t propertyOffset)
29d073aa1aSkasunath {
30d073aa1aSkasunath     // propertyOffset should be greater than or equal to first property offset.
31d073aa1aSkasunath     if (propertyOffset < bejDictGetPropertyHeadOffset())
32d073aa1aSkasunath     {
33d073aa1aSkasunath         fprintf(
34d073aa1aSkasunath             stderr,
35d073aa1aSkasunath             "Invalid property offset. Pointing to Dictionary header data\n");
36d073aa1aSkasunath         return false;
37d073aa1aSkasunath     }
38d073aa1aSkasunath 
39d073aa1aSkasunath     // propertyOffset should be a multiple of sizeof(BejDictionaryProperty)
40d073aa1aSkasunath     // starting from first property within the dictionary.
41d073aa1aSkasunath     if ((propertyOffset - bejDictGetPropertyHeadOffset()) %
42d073aa1aSkasunath         sizeof(struct BejDictionaryProperty))
43d073aa1aSkasunath     {
44d073aa1aSkasunath         fprintf(stderr, "Invalid property offset. Does not point to beginning "
45d073aa1aSkasunath                         "of property\n");
46d073aa1aSkasunath         return false;
47d073aa1aSkasunath     }
48d073aa1aSkasunath 
49f68be959Skasunath     const struct BejDictionaryHeader* header =
50f68be959Skasunath         (const struct BejDictionaryHeader*)dictionary;
51f68be959Skasunath     uint16_t propertyIndex = bejGetPropertyEntryIndex(propertyOffset);
52f68be959Skasunath     if (propertyIndex >= header->entryCount)
53f68be959Skasunath     {
54f68be959Skasunath         fprintf(stderr,
55f68be959Skasunath                 "Invalid property offset %u. It falls outside of dictionary "
56f68be959Skasunath                 "properties\n",
57f68be959Skasunath                 propertyOffset);
58f68be959Skasunath         return false;
59f68be959Skasunath     }
60f68be959Skasunath 
61d073aa1aSkasunath     return true;
62d073aa1aSkasunath }
63d073aa1aSkasunath 
bejDictGetPropertyHeadOffset(void)64*716c741dSJayanth Othayoth uint16_t bejDictGetPropertyHeadOffset(void)
65d073aa1aSkasunath {
66d073aa1aSkasunath     // First property is present soon after the dictionary header.
67d073aa1aSkasunath     return sizeof(struct BejDictionaryHeader);
68d073aa1aSkasunath }
69d073aa1aSkasunath 
bejDictGetFirstAnnotatedPropertyOffset(void)70*716c741dSJayanth Othayoth uint16_t bejDictGetFirstAnnotatedPropertyOffset(void)
71d073aa1aSkasunath {
72d073aa1aSkasunath     // The first property available is the "Annotations" set which is the parent
73d073aa1aSkasunath     // for all properties. Next immediate property is the first property we
74d073aa1aSkasunath     // need.
75d073aa1aSkasunath     return sizeof(struct BejDictionaryHeader) +
76d073aa1aSkasunath            sizeof(struct BejDictionaryProperty);
77d073aa1aSkasunath }
78d073aa1aSkasunath 
bejDictGetProperty(const uint8_t * dictionary,uint16_t startingPropertyOffset,uint16_t sequenceNumber,const struct BejDictionaryProperty ** property)79d073aa1aSkasunath int bejDictGetProperty(const uint8_t* dictionary,
80d073aa1aSkasunath                        uint16_t startingPropertyOffset, uint16_t sequenceNumber,
81d073aa1aSkasunath                        const struct BejDictionaryProperty** property)
82d073aa1aSkasunath {
83d073aa1aSkasunath     uint16_t propertyOffset = startingPropertyOffset;
84d073aa1aSkasunath     const struct BejDictionaryHeader* header =
85d073aa1aSkasunath         (const struct BejDictionaryHeader*)dictionary;
86d073aa1aSkasunath 
87f68be959Skasunath     if (!bejValidatePropertyOffset(dictionary, propertyOffset))
88d073aa1aSkasunath     {
89d073aa1aSkasunath         return bejErrorInvalidPropertyOffset;
90d073aa1aSkasunath     }
91d073aa1aSkasunath     uint16_t propertyIndex = bejGetPropertyEntryIndex(propertyOffset);
92d073aa1aSkasunath 
93d073aa1aSkasunath     for (uint16_t index = propertyIndex; index < header->entryCount; ++index)
94d073aa1aSkasunath     {
95d073aa1aSkasunath         const struct BejDictionaryProperty* p =
96d073aa1aSkasunath             (const struct BejDictionaryProperty*)(dictionary + propertyOffset);
97d073aa1aSkasunath         if (p->sequenceNumber == sequenceNumber)
98d073aa1aSkasunath         {
99d073aa1aSkasunath             *property = p;
100d073aa1aSkasunath             return 0;
101d073aa1aSkasunath         }
102d073aa1aSkasunath         propertyOffset += sizeof(struct BejDictionaryProperty);
103d073aa1aSkasunath     }
104d073aa1aSkasunath     return bejErrorUnknownProperty;
105d073aa1aSkasunath }
106d073aa1aSkasunath 
bejDictGetPropertyName(const uint8_t * dictionary,uint16_t nameOffset,uint8_t nameLength)107d073aa1aSkasunath const char* bejDictGetPropertyName(const uint8_t* dictionary,
108d073aa1aSkasunath                                    uint16_t nameOffset, uint8_t nameLength)
109d073aa1aSkasunath {
110d073aa1aSkasunath     if (nameLength == 0)
111d073aa1aSkasunath     {
112d073aa1aSkasunath         return "";
113d073aa1aSkasunath     }
114d073aa1aSkasunath     return (const char*)(dictionary + nameOffset);
115d073aa1aSkasunath }
116f68be959Skasunath 
bejDictGetPropertyByName(const uint8_t * dictionary,uint16_t startingPropertyOffset,const char * propertyName,const struct BejDictionaryProperty ** property,uint16_t * propertyOffset)117be27f2e9SPatrick Williams int bejDictGetPropertyByName(
118be27f2e9SPatrick Williams     const uint8_t* dictionary, uint16_t startingPropertyOffset,
119be27f2e9SPatrick Williams     const char* propertyName, const struct BejDictionaryProperty** property,
120f68be959Skasunath     uint16_t* propertyOffset)
121f68be959Skasunath {
122f68be959Skasunath     NULL_CHECK(property, "property in bejDictGetPropertyByName");
123f68be959Skasunath 
124f68be959Skasunath     uint16_t curPropertyOffset = startingPropertyOffset;
125f68be959Skasunath     const struct BejDictionaryHeader* header =
126f68be959Skasunath         (const struct BejDictionaryHeader*)dictionary;
127f68be959Skasunath 
128f68be959Skasunath     if (!bejValidatePropertyOffset(dictionary, curPropertyOffset))
129f68be959Skasunath     {
130f68be959Skasunath         return bejErrorInvalidPropertyOffset;
131f68be959Skasunath     }
132f68be959Skasunath     uint16_t propertyIndex = bejGetPropertyEntryIndex(curPropertyOffset);
133f68be959Skasunath 
134f68be959Skasunath     for (uint16_t index = propertyIndex; index < header->entryCount; ++index)
135f68be959Skasunath     {
136f68be959Skasunath         const struct BejDictionaryProperty* p =
137f68be959Skasunath             (const struct BejDictionaryProperty*)(dictionary +
138f68be959Skasunath                                                   curPropertyOffset);
139f68be959Skasunath         if (strcmp(propertyName,
140f68be959Skasunath                    bejDictGetPropertyName(dictionary, p->nameOffset,
141f68be959Skasunath                                           p->nameLength)) == 0)
142f68be959Skasunath         {
143f68be959Skasunath             *property = p;
144f68be959Skasunath             // propertyOffset is an optional output.
145f68be959Skasunath             if (propertyOffset != NULL)
146f68be959Skasunath             {
147f68be959Skasunath                 *propertyOffset = curPropertyOffset;
148f68be959Skasunath             }
149f68be959Skasunath             return 0;
150f68be959Skasunath         }
151f68be959Skasunath         curPropertyOffset += sizeof(struct BejDictionaryProperty);
152f68be959Skasunath     }
153f68be959Skasunath     return bejErrorUnknownProperty;
154f68be959Skasunath }
155