1 /*
2  * Copyright (c) 2011-2015, Intel Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation and/or
13  * other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software without
17  * specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 #include "BitParameterType.h"
31 #include "BitParameter.h"
32 #include <stdlib.h>
33 #include <sstream>
34 #include "ParameterAccessContext.h"
35 #include "BitParameterBlockType.h"
36 #include "Utility.h"
37 
38 #define base CTypeElement
39 
40 using std::string;
41 
CBitParameterType(const string & strName)42 CBitParameterType::CBitParameterType(const string &strName) : base(strName)
43 {
44 }
45 
46 // CElement
getKind() const47 string CBitParameterType::getKind() const
48 {
49     return "BitParameter";
50 }
51 
52 // Element properties
showProperties(string & strResult) const53 void CBitParameterType::showProperties(string &strResult) const
54 {
55     base::showProperties(strResult);
56 
57     // Bit Pos
58     strResult += "Bit pos: ";
59     strResult += std::to_string(_bitPos);
60     strResult += "\n";
61 
62     // Bit size
63     strResult += "Bit size: ";
64     strResult += std::to_string(_uiBitSize);
65     strResult += "\n";
66 
67     // Max
68     strResult += "Max: ";
69     strResult += std::to_string(_uiMax);
70     strResult += "\n";
71 }
72 
73 // From IXmlSink
fromXml(const CXmlElement & xmlElement,CXmlSerializingContext & serializingContext)74 bool CBitParameterType::fromXml(const CXmlElement &xmlElement,
75                                 CXmlSerializingContext &serializingContext)
76 {
77     // Pos
78     xmlElement.getAttribute("Pos", _bitPos);
79 
80     // Size
81     xmlElement.getAttribute("Size", _uiBitSize);
82 
83     // Validate bit pos and size still fit into parent type
84     const CBitParameterBlockType *pBitParameterBlockType =
85         static_cast<const CBitParameterBlockType *>(getParent());
86 
87     size_t uiParentBlockBitSize = pBitParameterBlockType->getSize() * 8;
88 
89     if (_bitPos + _uiBitSize > uiParentBlockBitSize) {
90 
91         // Range exceeded
92         std::ostringstream strStream;
93 
94         strStream << "Pos and Size attributes inconsistent with maximum container element size ("
95                   << uiParentBlockBitSize << " bits) for " + getKind();
96 
97         serializingContext.setError(strStream.str());
98 
99         return false;
100     }
101 
102     // Max
103     _uiMax = getMaxEncodableValue();
104     if (xmlElement.getAttribute("Max", _uiMax) && (_uiMax > getMaxEncodableValue())) {
105 
106         // Max value exceeded
107         std::ostringstream strStream;
108 
109         strStream << "Max attribute inconsistent with maximum encodable size ("
110                   << getMaxEncodableValue() << ") for " + getKind();
111 
112         serializingContext.setError(strStream.str());
113 
114         return false;
115     }
116 
117     // Base
118     return base::fromXml(xmlElement, serializingContext);
119 }
120 
121 // Conversion
toBlackboard(const string & strValue,uint64_t & uiValue,CParameterAccessContext & parameterAccessContext) const122 bool CBitParameterType::toBlackboard(const string &strValue, uint64_t &uiValue,
123                                      CParameterAccessContext &parameterAccessContext) const
124 {
125     // Get value
126     uint64_t uiConvertedValue = strtoull(strValue.c_str(), NULL, 0);
127 
128     if (uiConvertedValue > _uiMax) {
129 
130         // Range exceeded
131         std::ostringstream strStream;
132 
133         strStream << "Value " << strValue << " standing out of admitted range [";
134 
135         if (utility::isHexadecimal(strValue)) {
136 
137             strStream << "0x0, "
138                       << "0x" << std::hex << std::uppercase;
139         } else {
140 
141             strStream << "0, ";
142         }
143         strStream << _uiMax << "] for " + getKind();
144 
145         parameterAccessContext.setError(strStream.str());
146 
147         return false;
148     }
149 
150     // Do bitwise RMW operation
151     uiValue = (uiValue & ~getMask()) | (uiConvertedValue << _bitPos);
152 
153     return true;
154 }
155 
fromBlackboard(string & strValue,const uint64_t & uiValue,CParameterAccessContext & parameterAccessContext) const156 void CBitParameterType::fromBlackboard(string &strValue, const uint64_t &uiValue,
157                                        CParameterAccessContext &parameterAccessContext) const
158 {
159     uint64_t uiConvertedValue = (uiValue & getMask()) >> _bitPos;
160 
161     // Format
162     std::ostringstream strStream;
163 
164     // Take care of format
165     if (parameterAccessContext.valueSpaceIsRaw() && parameterAccessContext.outputRawFormatIsHex()) {
166 
167         strStream << "0x" << std::hex << std::uppercase;
168     }
169 
170     strStream << uiConvertedValue;
171 
172     strValue = strStream.str();
173 }
174 
175 // Value access
176 // Integer
toBlackboard(uint64_t uiUserValue,uint64_t & uiValue,CParameterAccessContext & parameterAccessContext) const177 bool CBitParameterType::toBlackboard(uint64_t uiUserValue, uint64_t &uiValue,
178                                      CParameterAccessContext &parameterAccessContext) const
179 {
180     if (uiUserValue > _uiMax) {
181 
182         parameterAccessContext.setError("Value out of range");
183 
184         return false;
185     }
186 
187     // Do bitwise RMW operation
188     uiValue = (uiValue & ~getMask()) | (uiUserValue << _bitPos);
189 
190     return true;
191 }
192 
fromBlackboard(uint32_t & userValue,uint64_t value,CParameterAccessContext &) const193 void CBitParameterType::fromBlackboard(uint32_t &userValue, uint64_t value,
194                                        CParameterAccessContext & /*ctx*/) const
195 {
196     userValue = static_cast<uint32_t>((value & getMask()) >> _bitPos);
197 }
198 
199 // Access from area configuration
merge(uint64_t uiOriginData,uint64_t uiNewData) const200 uint64_t CBitParameterType::merge(uint64_t uiOriginData, uint64_t uiNewData) const
201 {
202     return (uiOriginData & ~getMask()) | (uiNewData & getMask());
203 }
204 
205 // Bit Size
getBitSize() const206 size_t CBitParameterType::getBitSize() const
207 {
208     return _uiBitSize;
209 }
210 
doInstantiate() const211 CInstanceConfigurableElement *CBitParameterType::doInstantiate() const
212 {
213     return new CBitParameter(getName(), this);
214 }
215 
216 // Max value
getMaxEncodableValue() const217 uint64_t CBitParameterType::getMaxEncodableValue() const
218 {
219     return (uint64_t)-1L >> (8 * sizeof(uint64_t) - _uiBitSize);
220 }
221 
222 // Biwise mask
getMask() const223 uint64_t CBitParameterType::getMask() const
224 {
225     return getMaxEncodableValue() << _bitPos;
226 }
227 
228 // Check data has no bit set outside available range
isEncodable(uint64_t uiData) const229 bool CBitParameterType::isEncodable(uint64_t uiData) const
230 {
231     size_t uiShift = 8 * sizeof(uiData) - _uiBitSize;
232 
233     if (uiShift) {
234 
235         // Check high bits are clean
236         return !(uiData >> uiShift);
237     }
238 
239     return true;
240 }
241 
242 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const243 void CBitParameterType::toXml(CXmlElement &xmlElement,
244                               CXmlSerializingContext &serializingContext) const
245 {
246     // Position
247     xmlElement.setAttribute("Pos", _bitPos);
248 
249     // Size
250     xmlElement.setAttribute("Size", _uiBitSize);
251 
252     // Maximum
253     xmlElement.setAttribute("Max", _uiMax);
254 
255     base::toXml(xmlElement, serializingContext);
256 }
257