• 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 static constexpr uint32_t INVALID_PRIORITY = 0xffffffff;
42 static constexpr const char *SAND_BOX_INFO = "            \"sandbox\" : ";
43 static constexpr uint32_t INVALID_SAND_BOX = 0xffffffff;
StartupCfgGen(const std::shared_ptr<Ast> & ast)44 StartupCfgGen::StartupCfgGen(const std::shared_ptr<Ast> &ast) : Generator(ast)
45 {
46 }
47 
HeaderTopOutput()48 void StartupCfgGen::HeaderTopOutput()
49 {
50     ofs_ << BOOT_CONFIG_TOP;
51 }
52 
HeaderBottomOutput()53 void StartupCfgGen::HeaderBottomOutput()
54 {
55     ofs_ << BOOT_CONFIG_BOTTOM;
56     ofs_.close();
57 }
58 
Output()59 bool StartupCfgGen::Output()
60 {
61     if (!Initialize()) {
62         return false;
63     }
64     if (!TemplateNodeSeparate()) {
65         return false;
66     }
67     HeaderTopOutput();
68 
69     if (!GetHostInfo()) {
70         return false;
71     }
72     HostInfosOutput();
73 
74     HeaderBottomOutput();
75 
76     return true;
77 }
78 
Initialize()79 bool StartupCfgGen::Initialize()
80 {
81     std::string outFileName = Option::Instance().GetOutputName();
82     if (outFileName.empty()) {
83         outFileName = Option::Instance().GetSourceNameBase();
84     }
85     outFileName = Util::File::StripSuffix(outFileName).append(".cfg");
86     outFileName_ = Util::File::FileNameBase(outFileName);
87 
88     ofs_.open(outFileName, std::ofstream::out | std::ofstream::binary);
89     if (!ofs_.is_open()) {
90         Logger().Error() << "failed to open output file: " << outFileName;
91         return false;
92     }
93 
94     Logger().Debug() << "output: " << outFileName << outFileName_ << '\n';
95 
96     return true;
97 }
98 
HostInfoOutput(const std::string & name,bool end)99 void StartupCfgGen::HostInfoOutput(const std::string &name, bool end)
100 {
101     ofs_ << SERVICE_TOP << "\"" << name << "\",\n";
102 
103     if (hostInfoMap_[name].dynamicLoad) {
104         ofs_ << DYNAMIC_INFO;
105     }
106 
107     bool flag = false;
108     if ((hostInfoMap_[name].processPriority != INVALID_PRIORITY) &&
109         (hostInfoMap_[name].threadPriority != INVALID_PRIORITY)) {
110         flag = true;
111     }
112     if (flag) {
113         ofs_ << PATH_INFO << "\"" << hostInfoMap_[name].hostId << "\", \"" << name << "\", \"" <<
114             hostInfoMap_[name].processPriority << "\", \"" << hostInfoMap_[name].threadPriority << "\"],\n";
115     } else {
116         ofs_ << PATH_INFO << "\"" << hostInfoMap_[name].hostId << "\", \"" << name << "\"],\n";
117     }
118 
119     ofs_ << UID_INFO << "\"" << hostInfoMap_[name].hostUID << "\",\n";
120     ofs_ << GID_INFO << hostInfoMap_[name].hostGID << "],\n";
121 
122     if (!hostInfoMap_[name].hostCaps.empty()) {
123         ofs_ << CAPS_INFO << hostInfoMap_[name].hostCaps << "],\n";
124     }
125 
126     if (!hostInfoMap_[name].hostCritical.empty()) {
127         ofs_ << CRITICAL_INFO << hostInfoMap_[name].hostCritical << "],\n";
128     }
129 
130     if (hostInfoMap_[name].sandBox != INVALID_SAND_BOX) {
131         ofs_ << SAND_BOX_INFO << hostInfoMap_[name].sandBox << ",\n";
132     }
133 
134     ofs_ << SECON_INFO << name << ":s0\"\n";
135 
136     ofs_ << TAB TAB << "}";
137 
138     if (!end) {
139         ofs_<< ",";
140     }
141     ofs_ << '\n';
142 }
143 
InitHostInfo(HostInfo & hostData)144 void StartupCfgGen::InitHostInfo(HostInfo &hostData)
145 {
146     hostData.dynamicLoad = true;
147     hostData.hostCaps = "";
148     hostData.hostUID = "";
149     hostData.hostGID = "";
150     hostData.hostPriority = 0;
151     hostData.hostId = 0;
152     hostData.hostCritical = "";
153     hostData.processPriority = INVALID_PRIORITY;
154     hostData.threadPriority = INVALID_PRIORITY;
155     hostData.sandBox = INVALID_SAND_BOX;
156 }
157 
TemplateNodeSeparate()158 bool StartupCfgGen::TemplateNodeSeparate()
159 {
160     return ast_->WalkBackward([this](std::shared_ptr<AstObject> &object, int32_t depth) {
161         (void)depth;
162         if (object->IsNode() && ConfigNode::CastFrom(object)->GetNodeType() == NODE_TEMPLATE) {
163             object->Separate();
164             return NOERR;
165         }
166         return NOERR;
167     });
168 }
169 
HostInfosOutput()170 void StartupCfgGen::HostInfosOutput()
171 {
172     bool end = false;
173     uint32_t cnt = 1;
174     const uint32_t size = hostInfoMap_.size();
175 
176     std::vector<std::pair<std::string, HostInfo>> vect(hostInfoMap_.begin(), hostInfoMap_.end());
177 
178     using ElementType = std::pair<std::string, HostInfo>;
179     sort(vect.begin(), vect.end(), [] (const ElementType &p1, const ElementType &p2) -> bool {
180         return (p1.second.hostPriority == p2.second.hostPriority) ?
181             (p1.second.hostId < p2.second.hostId) : (p1.second.hostPriority < p2.second.hostPriority);
182     });
183 
184     std::vector<std::pair<std::string, HostInfo>>::iterator it = vect.begin();
185     for (; it != vect.end(); ++it, ++cnt) {
186         if (cnt == size) {
187             end = true;
188         }
189         HostInfoOutput(it->first, end);
190     }
191 }
192 
GetConfigArray(const std::shared_ptr<AstObject> & term,std::string & config)193 void StartupCfgGen::GetConfigArray(const std::shared_ptr<AstObject> &term, std::string &config)
194 {
195     if (term == nullptr) {
196         return;
197     }
198 
199     std::shared_ptr<AstObject> arrayObj = term->Child();
200     if (arrayObj == nullptr) {
201         return;
202     }
203 
204     uint16_t arraySize = ConfigArray::CastFrom(arrayObj)->ArraySize();
205     std::shared_ptr<AstObject> object = arrayObj->Child();
206     while (arraySize && object != nullptr) {
207         if (!object->StringValue().empty()) {
208             config.append("\"").append(object->StringValue()).append("\"");
209             if (arraySize != 1) {
210                 config.append(", ");
211             }
212         }
213 
214         object = object->Next();
215         arraySize--;
216     }
217 }
218 
GetConfigIntArray(const std::shared_ptr<AstObject> & term,std::string & config)219 void StartupCfgGen::GetConfigIntArray(const std::shared_ptr<AstObject> &term, std::string &config)
220 {
221     if (term == nullptr) {
222         return;
223     }
224 
225     std::shared_ptr<AstObject> intArrayObj = term->Child();
226     if (intArrayObj == nullptr) {
227         return;
228     }
229 
230     uint16_t arraySize = ConfigArray::CastFrom(intArrayObj)->ArraySize();
231     std::shared_ptr<AstObject> object = intArrayObj->Child();
232     while (arraySize && object != nullptr) {
233         std::string value = std::to_string(object->IntegerValue());
234         config.append(value);
235         if (arraySize != 1) {
236             config.append(", ");
237         }
238 
239         object = object->Next();
240         arraySize--;
241     }
242 }
243 
GetProcessPriority(const std::shared_ptr<AstObject> & term,HostInfo & hostData)244 void StartupCfgGen::GetProcessPriority(const std::shared_ptr<AstObject> &term, HostInfo &hostData)
245 {
246     if (term == nullptr) {
247         return;
248     }
249 
250     std::shared_ptr<AstObject> object = term->Lookup("processPriority", PARSEROP_CONFTERM);
251     if (object != nullptr) {
252         hostData.processPriority = static_cast<int32_t>(object->Child()->IntegerValue());
253     }
254     object = term->Lookup("threadPriority", PARSEROP_CONFTERM);
255     if (object != nullptr) {
256         hostData.threadPriority = static_cast<int32_t>(object->Child()->IntegerValue());
257     }
258 }
259 
GetHostLoadMode(const std::shared_ptr<AstObject> & hostInfo,HostInfo & hostData)260 void StartupCfgGen::GetHostLoadMode(const std::shared_ptr<AstObject> &hostInfo, HostInfo &hostData)
261 {
262     uint32_t preload;
263     std::shared_ptr<AstObject> current = nullptr;
264     std::shared_ptr<AstObject> devNodeInfo = nullptr;
265 
266     std::shared_ptr<AstObject> devInfo = hostInfo->Child();
267     while (devInfo != nullptr) {
268         if (!devInfo->IsNode()) {
269             devInfo = devInfo->Next();
270             continue;
271         }
272 
273         devNodeInfo = devInfo->Child();
274         while (devNodeInfo != nullptr) {
275             current = devNodeInfo->Lookup("preload", PARSEROP_CONFTERM);
276             if (current == nullptr) {
277                 devNodeInfo = devNodeInfo->Next();
278                 continue;
279             }
280 
281             preload = current->Child()->IntegerValue();
282             if (preload == 0 || preload == 1) {
283                 hostData.dynamicLoad = false;
284             }
285 
286             devNodeInfo = devNodeInfo->Next();
287         }
288         devInfo = devInfo->Next();
289     }
290 }
291 
GetHostGID(const std::shared_ptr<AstObject> & term,std::string & config,const std::string & name)292 void StartupCfgGen::GetHostGID(const std::shared_ptr<AstObject> &term, std::string &config,
293     const std::string &name)
294 {
295     // get array format configuration
296     GetConfigArray(term, config);
297 
298     // if the array format is not available, get the string format configuration
299     if (config.empty()) {
300         if (term != nullptr && !term->Child()->StringValue().empty()) {
301             config.append("\"").append(term->Child()->StringValue()).append("\"");
302         }
303     }
304 
305     // use the default name as gid
306     if (config.empty()) {
307         config.append("\"").append(name).append("\"");
308     }
309 }
310 
GetHostInfo()311 bool StartupCfgGen::GetHostInfo()
312 {
313     std::shared_ptr<AstObject> deviceInfo = ast_->GetAstRoot()->Lookup("device_info", PARSEROP_CONFNODE);
314     std::shared_ptr<AstObject> object = nullptr;
315     std::string serviceName;
316     HostInfo hostData;
317     uint32_t hostId = 0;
318 
319     if (deviceInfo == nullptr) {
320         Logger().Error() << "do not find device_info node";
321         return false;
322     }
323 
324     std::shared_ptr<AstObject> hostInfo = deviceInfo->Child();
325     while (hostInfo != nullptr) {
326         object = hostInfo->Lookup("hostName", PARSEROP_CONFTERM);
327         if (object == nullptr) {
328             hostInfo = hostInfo->Next();
329             continue;
330         }
331 
332         InitHostInfo(hostData);
333         serviceName = object->Child()->StringValue();
334 
335         object = hostInfo->Lookup("priority", PARSEROP_CONFTERM);
336         if (object != nullptr) {
337             hostData.hostPriority = object->Child()->IntegerValue();
338         }
339 
340         hostData.hostUID = serviceName;
341         object = hostInfo->Lookup("uid", PARSEROP_CONFTERM);
342         if (object != nullptr && !object->Child()->StringValue().empty()) {
343             hostData.hostUID = object->Child()->StringValue();
344         }
345 
346         object = hostInfo->Lookup("gid", PARSEROP_CONFTERM);
347         GetHostGID(object, hostData.hostGID, serviceName);
348 
349         object = hostInfo->Lookup("caps", PARSEROP_CONFTERM);
350         GetConfigArray(object, hostData.hostCaps);
351 
352         GetHostLoadMode(hostInfo, hostData);
353 
354         object = hostInfo->Lookup("critical", PARSEROP_CONFTERM);
355         GetConfigIntArray(object, hostData.hostCritical);
356         GetProcessPriority(hostInfo, hostData);
357 
358         object = hostInfo->Lookup("sandbox", PARSEROP_CONFTERM);
359         if (object != nullptr) {
360             hostData.sandBox = object->Child()->IntegerValue();
361         }
362 
363         hostData.hostId = hostId;
364         hostInfoMap_.insert(make_pair(serviceName, hostData));
365         hostId++;
366         hostInfo = hostInfo->Next();
367     }
368     return true;
369 }
370