• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "startup_cfg_gen.h"
10 #include <algorithm>
11 #include <string>
12 #include "ast.h"
13 #include "file.h"
14 #include "logger.h"
15 
16 using namespace OHOS::Hardware;
17 
18 static constexpr const char *BOOT_CONFIG_TOP =
19     "{\n"
20     "    \"jobs\" : [{\n"
21     "            \"name\" : \"post-fs-data\",\n"
22     "            \"cmds\" : [\n"
23     "                \"start hdf_devhost\"\n"
24     "            ]\n"
25     "        }\n"
26     "    ],\n"
27     "    \"services\" : [\n";
28 static constexpr const char *BOOT_CONFIG_BOTTOM =
29     "    ]\n"
30     "}\n";
31 static constexpr const char *SERVICE_TOP =
32     "        {\n"
33     "            \"name\" : ";
34 static constexpr const char *PATH_INFO     = "            \"path\" : [\"/vendor/bin/hdf_devhost\", ";
35 static constexpr const char *UID_INFO      = "            \"uid\" : ";
36 static constexpr const char *GID_INFO      = "            \"gid\" : [";
37 static constexpr const char *CAPS_INFO     = "            \"caps\" : [";
38 static constexpr const char *DYNAMIC_INFO  = "            \"ondemand\" : true,\n";
39 static constexpr const char *SECON_INFO    = "            \"secon\" : \"u:r:";
40 static constexpr const char *CRITICAL_INFO = "            \"critical\" : [";
41 
StartupCfgGen(const std::shared_ptr<Ast> & ast)42 StartupCfgGen::StartupCfgGen(const std::shared_ptr<Ast> &ast) : Generator(ast)
43 {
44 }
45 
HeaderTopOutput()46 void StartupCfgGen::HeaderTopOutput()
47 {
48     ofs_ << BOOT_CONFIG_TOP;
49 }
50 
HeaderBottomOutput()51 void StartupCfgGen::HeaderBottomOutput()
52 {
53     ofs_ << BOOT_CONFIG_BOTTOM;
54     ofs_.close();
55 }
56 
Output()57 bool StartupCfgGen::Output()
58 {
59     if (!Initialize()) {
60         return false;
61     }
62     if (!TemplateNodeSeparate()) {
63         return false;
64     }
65     HeaderTopOutput();
66 
67     if (!GetHostInfo()) {
68         return false;
69     }
70     HostInfosOutput();
71 
72     HeaderBottomOutput();
73 
74     return true;
75 }
76 
Initialize()77 bool StartupCfgGen::Initialize()
78 {
79     std::string outFileName = Option::Instance().GetOutputName();
80     if (outFileName.empty()) {
81         outFileName = Option::Instance().GetSourceNameBase();
82     }
83     outFileName = Util::File::StripSuffix(outFileName).append(".cfg");
84     outFileName_ = Util::File::FileNameBase(outFileName);
85 
86     ofs_.open(outFileName, std::ofstream::out | std::ofstream::binary);
87     if (!ofs_.is_open()) {
88         Logger().Error() << "failed to open output file: " << outFileName;
89         return false;
90     }
91 
92     Logger().Debug() << "output: " << outFileName << outFileName_ << '\n';
93 
94     return true;
95 }
96 
HostInfoOutput(const std::string & name,bool end)97 void StartupCfgGen::HostInfoOutput(const std::string &name, bool end)
98 {
99     ofs_ << SERVICE_TOP << "\"" << name << "\",\n";
100 
101     if (hostInfoMap_[name].dynamicLoad) {
102         ofs_ << DYNAMIC_INFO;
103     }
104 
105     ofs_ << PATH_INFO << "\"" << hostInfoMap_[name].hostId << "\", \"" << name <<"\"],\n";
106     ofs_ << UID_INFO << "\"" << hostInfoMap_[name].hostUID <<"\",\n";
107     ofs_ << GID_INFO << hostInfoMap_[name].hostGID <<"],\n";
108 
109     if (!hostInfoMap_[name].hostCaps.empty()) {
110         ofs_ << CAPS_INFO << hostInfoMap_[name].hostCaps <<"],\n";
111     }
112 
113     if (!hostInfoMap_[name].hostCritical.empty()) {
114         ofs_ << CRITICAL_INFO << hostInfoMap_[name].hostCritical <<"],\n";
115     }
116 
117     ofs_ << SECON_INFO << name << ":s0\"\n";
118 
119     ofs_ << TAB TAB << "}";
120 
121     if (!end) {
122         ofs_<< ",";
123     }
124     ofs_ << '\n';
125 }
126 
InitHostInfo(HostInfo & hostData)127 void StartupCfgGen::InitHostInfo(HostInfo &hostData)
128 {
129     hostData.dynamicLoad = true;
130     hostData.hostCaps = "";
131     hostData.hostUID = "";
132     hostData.hostGID = "";
133     hostData.hostPriority = 0;
134     hostData.hostId = 0;
135     hostData.hostCritical = "";
136 }
137 
TemplateNodeSeparate()138 bool StartupCfgGen::TemplateNodeSeparate()
139 {
140     return ast_->WalkBackward([this](std::shared_ptr<AstObject> &object, int32_t depth) {
141         (void)depth;
142         if (object->IsNode() && ConfigNode::CastFrom(object)->GetNodeType() == NODE_TEMPLATE) {
143             object->Separate();
144             return NOERR;
145         }
146         return NOERR;
147     });
148 }
149 
HostInfosOutput()150 void StartupCfgGen::HostInfosOutput()
151 {
152     bool end = false;
153     uint32_t cnt = 1;
154     const uint32_t size = hostInfoMap_.size();
155 
156     std::vector<std::pair<std::string, HostInfo>> vect(hostInfoMap_.begin(), hostInfoMap_.end());
157 
158     using ElementType = std::pair<std::string, HostInfo>;
159     sort(vect.begin(), vect.end(), [] (const ElementType &p1, const ElementType &p2) -> bool {
160         return (p1.second.hostPriority == p2.second.hostPriority) ?
161             (p1.second.hostId < p2.second.hostId) : (p1.second.hostPriority < p2.second.hostPriority);
162     });
163 
164     std::vector<std::pair<std::string, HostInfo>>::iterator it = vect.begin();
165     for (; it != vect.end(); ++it, ++cnt) {
166         if (cnt == size) {
167             end = true;
168         }
169         HostInfoOutput(it->first, end);
170     }
171 }
172 
GetConfigArray(const std::shared_ptr<AstObject> & term,std::string & config)173 void StartupCfgGen::GetConfigArray(const std::shared_ptr<AstObject> &term, std::string &config)
174 {
175     if (term == nullptr) {
176         return;
177     }
178 
179     std::shared_ptr<AstObject> arrayObj = term->Child();
180     if (arrayObj == nullptr) {
181         return;
182     }
183 
184     uint16_t arraySize = ConfigArray::CastFrom(arrayObj)->ArraySize();
185     std::shared_ptr<AstObject> object = arrayObj->Child();
186     while (arraySize && object != nullptr) {
187         if (!object->StringValue().empty()) {
188             config.append("\"").append(object->StringValue()).append("\"");
189             if (arraySize != 1) {
190                 config.append(", ");
191             }
192         }
193 
194         object = object->Next();
195         arraySize--;
196     }
197 }
198 
GetConfigIntArray(const std::shared_ptr<AstObject> & term,std::string & config)199 void StartupCfgGen::GetConfigIntArray(const std::shared_ptr<AstObject> &term, std::string &config)
200 {
201     if (term == nullptr) {
202         return;
203     }
204 
205     std::shared_ptr<AstObject> intArrayObj = term->Child();
206     if (intArrayObj == nullptr) {
207         return;
208     }
209 
210     uint16_t arraySize = ConfigArray::CastFrom(intArrayObj)->ArraySize();
211     std::shared_ptr<AstObject> object = intArrayObj->Child();
212     while (arraySize != 0 && object != nullptr) {
213         std::string value = std::to_string(object->IntegerValue());
214         config.append(value);
215         if (arraySize != 1) {
216             config.append(", ");
217         }
218 
219         object = object->Next();
220         arraySize--;
221     }
222 }
223 
GetHostLoadMode(const std::shared_ptr<AstObject> & hostInfo,HostInfo & hostData)224 void StartupCfgGen::GetHostLoadMode(const std::shared_ptr<AstObject> &hostInfo, HostInfo &hostData)
225 {
226     uint32_t preload;
227     std::shared_ptr<AstObject> current = nullptr;
228     std::shared_ptr<AstObject> devNodeInfo = nullptr;
229 
230     std::shared_ptr<AstObject> devInfo = hostInfo->Child();
231     while (devInfo != nullptr) {
232         if (!devInfo->IsNode()) {
233             devInfo = devInfo->Next();
234             continue;
235         }
236 
237         devNodeInfo = devInfo->Child();
238         while (devNodeInfo != nullptr) {
239             current = devNodeInfo->Lookup("preload", PARSEROP_CONFTERM);
240             if (current == nullptr) {
241                 devNodeInfo = devNodeInfo->Next();
242                 continue;
243             }
244 
245             preload = current->Child()->IntegerValue();
246             if (preload == 0 || preload == 1) {
247                 hostData.dynamicLoad = false;
248             }
249 
250             devNodeInfo = devNodeInfo->Next();
251         }
252         devInfo = devInfo->Next();
253     }
254 }
255 
GetHostGID(const std::shared_ptr<AstObject> & term,std::string & config,const std::string & name)256 void StartupCfgGen::GetHostGID(const std::shared_ptr<AstObject> &term, std::string &config,
257     const std::string &name)
258 {
259     // get array format configuration
260     GetConfigArray(term, config);
261 
262     // if the array format is not available, get the string format configuration
263     if (config.empty()) {
264         if (term != nullptr && !term->Child()->StringValue().empty()) {
265             config.append("\"").append(term->Child()->StringValue()).append("\"");
266         }
267     }
268 
269     // use the default name as gid
270     if (config.empty()) {
271         config.append("\"").append(name).append("\"");
272     }
273 }
274 
GetHostInfo()275 bool StartupCfgGen::GetHostInfo()
276 {
277     std::shared_ptr<AstObject> deviceInfo = ast_->GetAstRoot()->Lookup("device_info", PARSEROP_CONFNODE);
278     std::shared_ptr<AstObject> object = nullptr;
279     std::string serviceName;
280     HostInfo hostData;
281     uint32_t hostId = 0;
282 
283     if (deviceInfo == nullptr) {
284         Logger().Error() << "do not find device_info node";
285         return false;
286     }
287 
288     std::shared_ptr<AstObject> hostInfo = deviceInfo->Child();
289     while (hostInfo != nullptr) {
290         object = hostInfo->Lookup("hostName", PARSEROP_CONFTERM);
291         if (object == nullptr) {
292             hostInfo = hostInfo->Next();
293             continue;
294         }
295 
296         InitHostInfo(hostData);
297         serviceName = object->Child()->StringValue();
298 
299         object = hostInfo->Lookup("priority", PARSEROP_CONFTERM);
300         if (object != nullptr) {
301             hostData.hostPriority = object->Child()->IntegerValue();
302         }
303 
304         hostData.hostUID = serviceName;
305         object = hostInfo->Lookup("uid", PARSEROP_CONFTERM);
306         if (object != nullptr && !object->Child()->StringValue().empty()) {
307             hostData.hostUID = object->Child()->StringValue();
308         }
309 
310         object = hostInfo->Lookup("gid", PARSEROP_CONFTERM);
311         GetHostGID(object, hostData.hostGID, serviceName);
312 
313         object = hostInfo->Lookup("caps", PARSEROP_CONFTERM);
314         GetConfigArray(object, hostData.hostCaps);
315 
316         GetHostLoadMode(hostInfo, hostData);
317 
318         object = hostInfo->Lookup("critical", PARSEROP_CONFTERM);
319         GetConfigIntArray(object, hostData.hostCritical);
320 
321         hostData.hostId = hostId;
322         hostInfoMap_.insert(make_pair(serviceName, hostData));
323         hostId++;
324         hostInfo = hostInfo->Next();
325     }
326     return true;
327 }
328