xref: /openbmc/libbej/src/bej_dictionary.c (revision f68be959)
1d073aa1aSkasunath #include "bej_dictionary.h"
2d073aa1aSkasunath 
3d073aa1aSkasunath #include <stdbool.h>
4d073aa1aSkasunath #include <stdio.h>
5*f68be959Skasunath #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  *
23*f68be959Skasunath  * @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)27*f68be959Skasunath static bool bejValidatePropertyOffset(const uint8_t* dictionary,
28*f68be959Skasunath                                       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 
49*f68be959Skasunath     const struct BejDictionaryHeader* header =
50*f68be959Skasunath         (const struct BejDictionaryHeader*)dictionary;
51*f68be959Skasunath     uint16_t propertyIndex = bejGetPropertyEntryIndex(propertyOffset);
52*f68be959Skasunath     if (propertyIndex >= header->entryCount)
53*f68be959Skasunath     {
54*f68be959Skasunath         fprintf(stderr,
55*f68be959Skasunath                 "Invalid property offset %u. It falls outside of dictionary "
56*f68be959Skasunath                 "properties\n",
57*f68be959Skasunath                 propertyOffset);
58*f68be959Skasunath         return false;
59*f68be959Skasunath     }
60*f68be959Skasunath 
61d073aa1aSkasunath     return true;
62d073aa1aSkasunath }
63d073aa1aSkasunath 
bejDictGetPropertyHeadOffset()64d073aa1aSkasunath uint16_t bejDictGetPropertyHeadOffset()
65d073aa1aSkasunath {
66d073aa1aSkasunath     // First property is present soon after the dictionary header.
67d073aa1aSkasunath     return sizeof(struct BejDictionaryHeader);
68d073aa1aSkasunath }
69d073aa1aSkasunath 
bejDictGetFirstAnnotatedPropertyOffset()70d073aa1aSkasunath uint16_t bejDictGetFirstAnnotatedPropertyOffset()
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 
87*f68be959Skasunath     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 }
116*f68be959Skasunath 
bejDictGetPropertyByName(const uint8_t * dictionary,uint16_t startingPropertyOffset,const char * propertyName,const struct BejDictionaryProperty ** property,uint16_t * propertyOffset)117*f68be959Skasunath int bejDictGetPropertyByName(const uint8_t* dictionary,
118*f68be959Skasunath                              uint16_t startingPropertyOffset,
119*f68be959Skasunath                              const char* propertyName,
120*f68be959Skasunath                              const struct BejDictionaryProperty** property,
121*f68be959Skasunath                              uint16_t* propertyOffset)
122*f68be959Skasunath {
123*f68be959Skasunath     NULL_CHECK(property, "property in bejDictGetPropertyByName");
124*f68be959Skasunath 
125*f68be959Skasunath     uint16_t curPropertyOffset = startingPropertyOffset;
126*f68be959Skasunath     const struct BejDictionaryHeader* header =
127*f68be959Skasunath         (const struct BejDictionaryHeader*)dictionary;
128*f68be959Skasunath 
129*f68be959Skasunath     if (!bejValidatePropertyOffset(dictionary, curPropertyOffset))
130*f68be959Skasunath     {
131*f68be959Skasunath         return bejErrorInvalidPropertyOffset;
132*f68be959Skasunath     }
133*f68be959Skasunath     uint16_t propertyIndex = bejGetPropertyEntryIndex(curPropertyOffset);
134*f68be959Skasunath 
135*f68be959Skasunath     for (uint16_t index = propertyIndex; index < header->entryCount; ++index)
136*f68be959Skasunath     {
137*f68be959Skasunath         const struct BejDictionaryProperty* p =
138*f68be959Skasunath             (const struct BejDictionaryProperty*)(dictionary +
139*f68be959Skasunath                                                   curPropertyOffset);
140*f68be959Skasunath         if (strcmp(propertyName,
141*f68be959Skasunath                    bejDictGetPropertyName(dictionary, p->nameOffset,
142*f68be959Skasunath                                           p->nameLength)) == 0)
143*f68be959Skasunath         {
144*f68be959Skasunath             *property = p;
145*f68be959Skasunath             // propertyOffset is an optional output.
146*f68be959Skasunath             if (propertyOffset != NULL)
147*f68be959Skasunath             {
148*f68be959Skasunath                 *propertyOffset = curPropertyOffset;
149*f68be959Skasunath             }
150*f68be959Skasunath             return 0;
151*f68be959Skasunath         }
152*f68be959Skasunath         curPropertyOffset += sizeof(struct BejDictionaryProperty);
153*f68be959Skasunath     }
154*f68be959Skasunath     return bejErrorUnknownProperty;
155*f68be959Skasunath }
156