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), _uiBitPos(0), _uiBitSize(0), _uiMax(uint64_t(-1))
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 += CUtility::toString(_uiBitPos);
60     strResult += "\n";
61 
62     // Bit size
63     strResult += "Bit size: ";
64     strResult += CUtility::toString(_uiBitSize);
65     strResult += "\n";
66 
67     // Max
68     strResult += "Max: ";
69     strResult += CUtility::toString(_uiMax);
70     strResult += "\n";
71 }
72 
73 // From IXmlSink
fromXml(const CXmlElement & xmlElement,CXmlSerializingContext & serializingContext)74 bool CBitParameterType::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
75 {
76     // Pos
77     _uiBitPos = xmlElement.getAttributeInteger("Pos");
78 
79     // Size
80     _uiBitSize = xmlElement.getAttributeInteger("Size");
81 
82     // Validate bit pos and size still fit into parent type
83     const CBitParameterBlockType* pBitParameterBlockType = static_cast<const CBitParameterBlockType*>(getParent());
84 
85     uint32_t uiParentBlockBitSize = pBitParameterBlockType->getSize() * 8;
86 
87     if (_uiBitPos + _uiBitSize > uiParentBlockBitSize) {
88 
89         // Range exceeded
90 	std::ostringstream strStream;
91 
92         strStream << "Pos and Size attributes inconsistent with maximum container element size (" << uiParentBlockBitSize << " bits) for " + getKind();
93 
94         serializingContext.setError(strStream.str());
95 
96         return false;
97     }
98 
99     // Max
100     if (xmlElement.hasAttribute("Max")) {
101 
102         _uiMax = xmlElement.getAttributeInteger("Max");
103 
104         if (_uiMax > getMaxEncodableValue()) {
105 
106             // Max value exceeded
107 	    std::ostringstream strStream;
108 
109             strStream << "Max attribute inconsistent with maximum encodable size (" << getMaxEncodableValue() << ") for " + getKind();
110 
111             serializingContext.setError(strStream.str());
112 
113             return false;
114         }
115     } else {
116 
117         _uiMax = getMaxEncodableValue();
118     }
119 
120     // Base
121     return base::fromXml(xmlElement, serializingContext);
122 }
123 
124 // Conversion
toBlackboard(const string & strValue,uint64_t & uiValue,CParameterAccessContext & parameterAccessContext) const125 bool CBitParameterType::toBlackboard(const string& strValue, uint64_t& uiValue, CParameterAccessContext& parameterAccessContext) const
126 {
127     // Hexa
128     bool bValueProvidedAsHexa = !strValue.compare(0, 2, "0x");
129 
130     // Get value
131     uint64_t uiConvertedValue = strtoull(strValue.c_str(), NULL, 0);
132 
133     if (uiConvertedValue > _uiMax) {
134 
135         // Range exceeded
136 	std::ostringstream strStream;
137 
138         strStream << "Value " << strValue << " standing out of admitted range [";
139 
140         if (bValueProvidedAsHexa) {
141 
142             strStream << "0x0, " << "0x" << std::hex << std::uppercase;
143         } else {
144 
145             strStream << "0, ";
146         }
147         strStream << _uiMax << "] for " + getKind();
148 
149         parameterAccessContext.setError(strStream.str());
150 
151         return false;
152     }
153 
154     // Do bitwise RMW operation
155     uiValue = (uiValue & ~getMask()) | (uiConvertedValue << _uiBitPos);
156 
157     return true;
158 }
159 
fromBlackboard(string & strValue,const uint64_t & uiValue,CParameterAccessContext & parameterAccessContext) const160 void CBitParameterType::fromBlackboard(string& strValue, const uint64_t& uiValue, CParameterAccessContext& parameterAccessContext) const
161 {
162     uint64_t uiConvertedValue = (uiValue & getMask()) >> _uiBitPos;
163 
164     // Format
165     std::ostringstream strStream;
166 
167     // Take care of format
168     if (parameterAccessContext.valueSpaceIsRaw() && parameterAccessContext.outputRawFormatIsHex()) {
169 
170         strStream << "0x" << std::hex << std::uppercase;
171     }
172 
173     strStream << uiConvertedValue;
174 
175     strValue = strStream.str();
176 }
177 
178 // Value access
179 // Integer
toBlackboard(uint64_t uiUserValue,uint64_t & uiValue,CParameterAccessContext & parameterAccessContext) const180 bool CBitParameterType::toBlackboard(uint64_t uiUserValue, uint64_t& uiValue, CParameterAccessContext& parameterAccessContext) const
181 {
182     if (uiUserValue > _uiMax) {
183 
184         parameterAccessContext.setError("Value out of range");
185 
186         return false;
187     }
188 
189     // Do bitwise RMW operation
190     uiValue = (uiValue & ~getMask()) | (uiUserValue << _uiBitPos);
191 
192     return true;
193 }
194 
fromBlackboard(uint32_t & uiUserValue,uint64_t uiValue,CParameterAccessContext & parameterAccessContext) const195 void CBitParameterType::fromBlackboard(uint32_t& uiUserValue, uint64_t uiValue, CParameterAccessContext& parameterAccessContext) const
196 {
197     (void)parameterAccessContext;
198 
199     uiUserValue = (uiValue & getMask()) >> _uiBitPos;
200 }
201 
202 // Access from area configuration
merge(uint64_t uiOriginData,uint64_t uiNewData) const203 uint64_t CBitParameterType::merge(uint64_t uiOriginData, uint64_t uiNewData) const
204 {
205     return (uiOriginData & ~getMask()) | (uiNewData & getMask());
206 }
207 
208 // Bit Size
getBitSize() const209 uint32_t CBitParameterType::getBitSize() const
210 {
211     return _uiBitSize;
212 }
213 
doInstantiate() const214 CInstanceConfigurableElement* CBitParameterType::doInstantiate() const
215 {
216     return new CBitParameter(getName(), this);
217 }
218 
219 // Max value
getMaxEncodableValue() const220 uint64_t CBitParameterType::getMaxEncodableValue() const
221 {
222     return (uint64_t)-1L >> (8 * sizeof(uint64_t) - _uiBitSize);
223 }
224 
225 // Biwise mask
getMask() const226 uint64_t CBitParameterType::getMask() const
227 {
228     return getMaxEncodableValue() << _uiBitPos;
229 }
230 
231 // Check data has no bit set outside available range
isEncodable(uint64_t uiData) const232 bool CBitParameterType::isEncodable(uint64_t uiData) const
233 {
234     uint32_t uiShift = 8 * sizeof(uiData) - _uiBitSize;
235 
236     if (uiShift) {
237 
238         // Check high bits are clean
239         return !(uiData >> uiShift);
240     }
241 
242     return true;
243 }
244 
245 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const246 void CBitParameterType::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
247 {
248     // Position
249     xmlElement.setAttributeString("Pos", CUtility::toString(_uiBitPos));
250 
251     // Size
252     xmlElement.setAttributeString("Size", CUtility::toString(_uiBitSize));
253 
254     // Maximum
255     xmlElement.setAttributeString("Max", CUtility::toString(_uiMax));
256 
257     base::toXml(xmlElement, serializingContext);
258 
259 }
260