1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "flash_service.h"
16 #include <cstdio>
17 #include <dirent.h>
18 #include <fcntl.h>
19 #include <map>
20 #include <memory>
21 #include <string>
22 #include <sys/stat.h>
23 #include <sys/statvfs.h>
24 #include <sys/sysmacros.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #include <unistd.h>
28
29 #include "blockdevice.h"
30 #include "fs_manager/mount.h"
31 #include "package/pkg_manager.h"
32 #include "securec.h"
33 #include "updater/updater.h"
34 #include "updater/updater_const.h"
35 #include "utils.h"
36
37 using namespace hpackage;
38 using namespace updater;
39
40 namespace flashd {
41 static std::atomic<bool> g_flashdRunning { false };
~FlashService()42 FlashService::~FlashService()
43 {
44 for (auto part : partitions_) {
45 printf("LoadBlockDevice %s \n", part->GetPartitionName().c_str());
46 delete part;
47 }
48 partitions_.clear();
49 for (auto dev : blockDevices_) {
50 delete dev;
51 }
52 blockDevices_.clear();
53 }
54
LoadSysDevice()55 int FlashService::LoadSysDevice()
56 {
57 if (loadSysDevice_) {
58 return 0;
59 }
60 return LoadBlockDevice("/dev/block");
61 }
62
DoUpdate(const std::string & packageName)63 int FlashService::DoUpdate(const std::string &packageName)
64 {
65 int ret = 0;
66 FLASHING_LOGI("DoUpdate packageName %s", packageName.c_str());
67 FLASHING_CHECK(access(packageName.c_str(), 0) == 0,
68 return FLASHING_IMAGE_INVALID, "Invalid package %s for update", packageName.c_str());
69 ret = updater::IsSpaceCapacitySufficient(packageName);
70 if (ret == UPDATE_SPACE_NOTENOUGH) {
71 RecordMsg(updater::ERROR, "Free space is not enough");
72 return FLASHING_SPACE_NOTENOUGH;
73 }
74 FLASHING_LOGI("Check space for packageName %s success", packageName.c_str());
75
76 uint64_t pkgLen = 0;
77 PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance();
78 FLASHING_CHECK(pkgManager != nullptr, return FLASHING_PACKAGE_INVALID, "Failed to GetPackageInstance");
79 pkgManager->SetPkgDecodeProgress([&](int type, size_t writeDataLen, const void *context) {
80 pkgLen += writeDataLen;
81 PostProgress(UPDATEMOD_UPDATE, writeDataLen, context);
82 });
83 std::vector<std::string> components;
84 ret = pkgManager->LoadPackage(packageName, utils::GetCertName(), components);
85 FLASHING_CHECK(ret == PKG_SUCCESS, PkgManager::ReleasePackageInstance(pkgManager);
86 RecordMsg(updater::ERROR, "Can not load package %s", packageName.c_str());
87 return FLASHING_PACKAGE_INVALID, "Failed to load package %s", packageName.c_str());
88
89 ret = UpdatePreProcess(pkgManager, packageName);
90 FLASHING_CHECK(ret == PKG_SUCCESS, PkgManager::ReleasePackageInstance(pkgManager);
91 RecordMsg(updater::ERROR, "Invalid package %s", packageName.c_str());
92 return FLASHING_PACKAGE_INVALID, "Invalid package %s", packageName.c_str());
93 #ifndef UPDATER_UT
94 ret = updater::ExecUpdate(pkgManager, 0,
95 [&](const char *cmd, const char *content) {
96 if (strncmp(cmd, "data", strlen(cmd)) == 0) {
97 size_t dataLen = std::stoll(content);
98 PostProgress(UPDATEMOD_UPDATE, dataLen, nullptr);
99 }
100 });
101 #endif
102 FLASHING_CHECK(ret == PKG_SUCCESS, PkgManager::ReleasePackageInstance(pkgManager);
103 RecordMsg(updater::ERROR, "Failed to update package %s", packageName.c_str());
104 return FLASHING_PACKAGE_INVALID, "Failed to update package %s", packageName.c_str());
105 FLASHING_LOGI("Load packageName %s success %llu", packageName.c_str(), pkgLen);
106 PkgManager::ReleasePackageInstance(pkgManager);
107 return ret;
108 }
109
DoFlashPartition(const std::string & fileName,const std::string & partition)110 int FlashService::DoFlashPartition(const std::string &fileName, const std::string &partition)
111 {
112 int ret = CheckOperationPermission(flashd::UPDATEMOD_FLASH, partition);
113 FLASHING_CHECK(ret == 0,
114 RecordMsg(updater::ERROR, "Forbit to flash partition %s", partition.c_str());
115 return FLASHING_NOPERMISSION, "Forbit to flash partition %s", partition.c_str());
116
117 ret = LoadSysDevice();
118 FLASHING_CHECK(ret == 0,
119 RecordMsg(updater::ERROR, "Can not read device information");
120 return FLASHING_PART_NOEXIST, "Failed to load partition");
121
122 FLASHING_LOGI("DoFlashPartition partition %s image:%s", partition.c_str(), fileName.c_str());
123 PartitionPtr part = GetPartition(partition);
124 FLASHING_CHECK(part != nullptr,
125 RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str());
126 return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str());
127 return part->DoFlash(fileName);
128 }
129
GetPartitionPath(const std::string & partition,std::string & paratitionPath)130 int FlashService::GetPartitionPath(const std::string &partition, std::string ¶titionPath)
131 {
132 int ret = CheckOperationPermission(flashd::UPDATEMOD_FLASH, partition);
133 FLASHING_CHECK(ret == 0,
134 RecordMsg(updater::ERROR, "Forbit to flash partition %s", partition.c_str());
135 return FLASHING_NOPERMISSION, "Forbit to flash partition %s", partition.c_str());
136
137 ret = LoadSysDevice();
138 FLASHING_CHECK(ret == 0,
139 RecordMsg(updater::ERROR, "Can not read device information");
140 return FLASHING_PART_NOEXIST, "Failed to load partition");
141
142 FLASHING_LOGI("DoFlashPartition partition %s", partition.c_str());
143 PartitionPtr part = GetPartition(partition);
144 FLASHING_CHECK(part != nullptr,
145 RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str());
146 return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str());
147 paratitionPath = part->GetPartitionPath();
148 return 0;
149 }
150
DoErasePartition(const std::string & partition)151 int FlashService::DoErasePartition(const std::string &partition)
152 {
153 int ret = CheckOperationPermission(flashd::UPDATEMOD_ERASE, partition);
154 FLASHING_CHECK(ret == 0,
155 RecordMsg(updater::ERROR, "Forbit to erase partition %s", partition.c_str());
156 return FLASHING_NOPERMISSION, "Forbit to erase partition %s", partition.c_str());
157
158 ret = LoadSysDevice();
159 FLASHING_CHECK(ret == 0,
160 RecordMsg(updater::ERROR, "Can not read device information");
161 return FLASHING_PART_NOEXIST, "Failed to load partition");
162
163 FLASHING_LOGI("DoErasePartition partition %s ", partition.c_str());
164 PartitionPtr part = GetPartition(partition);
165 FLASHING_CHECK(part != nullptr,
166 RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str());
167 return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str());
168 return part->DoErase();
169 }
170
DoFormatPartition(const std::string & partition,const std::string & fsType)171 int FlashService::DoFormatPartition(const std::string &partition, const std::string &fsType)
172 {
173 int ret = CheckOperationPermission(flashd::UPDATEMOD_FORMAT, partition);
174 FLASHING_CHECK(ret == 0,
175 RecordMsg(updater::ERROR, "Forbit to format partition %s", partition.c_str());
176 return FLASHING_NOPERMISSION, "Forbit to format partition %s", partition.c_str());
177
178 ret = LoadSysDevice();
179 FLASHING_CHECK(ret == 0,
180 RecordMsg(updater::ERROR, "Can not read device information");
181 return FLASHING_PART_NOEXIST, "Failed to load partition");
182 PartitionPtr part = GetPartition(partition);
183 FLASHING_CHECK(part != nullptr,
184 RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str());
185 return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str());
186 if (part->IsOnlyErase()) {
187 FLASHING_LOGI("DoFormatPartition format partition %s", partition.c_str());
188 return part->DoErase();
189 }
190 FLASHING_LOGI("DoFormatPartition partition %s fsType:%s", partition.c_str(), fsType.c_str());
191 return part->DoFormat(fsType);
192 }
193
DoResizeParatiton(const std::string & partition,uint32_t blocks)194 int FlashService::DoResizeParatiton(const std::string &partition, uint32_t blocks)
195 {
196 int ret = CheckOperationPermission(flashd::UPDATEMOD_UPDATE, partition);
197 FLASHING_CHECK(ret == 0,
198 RecordMsg(updater::ERROR, "Forbit to resize partition %s", partition.c_str());
199 return FLASHING_NOPERMISSION, "Forbit to resize partition %s", partition.c_str());
200
201 ret = LoadSysDevice();
202 FLASHING_CHECK(ret == 0,
203 RecordMsg(updater::ERROR, "Can not read device information");
204 return FLASHING_PART_NOEXIST, "Failed to load partition");
205
206 PartitionPtr part = GetPartition(partition);
207 FLASHING_CHECK(part != nullptr,
208 RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str());
209 return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str());
210 return part->DoResize(blocks);
211 }
212
GetPartition(const std::string & partition) const213 PartitionPtr FlashService::GetPartition(const std::string &partition) const
214 {
215 const std::string partName = GetPartNameByAlias(partition);
216 for (auto part : partitions_) {
217 if (strcmp(partName.c_str(), part->GetPartitionName().c_str()) == 0) {
218 return part;
219 }
220 }
221 return nullptr;
222 }
223
LoadBlockDevice(const std::string & fileDir)224 int FlashService::LoadBlockDevice(const std::string &fileDir)
225 {
226 std::vector<std::string> partitionsName {};
227 struct stat dirStat = {};
228 int ret = stat(fileDir.c_str(), &dirStat);
229 FLASHING_CHECK(ret != -1 && S_ISDIR(dirStat.st_mode), return -1, "Invlid dir %s", fileDir.c_str());
230
231 std::vector<char> buffer(DEVICE_PATH_SIZE, 0);
232 struct dirent *entry = nullptr;
233 DIR *dir = opendir(fileDir.c_str());
234 while ((entry = readdir(dir)) != nullptr) {
235 if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
236 continue;
237 }
238 std::string devPath = fileDir + "/" + entry->d_name;
239 if (entry->d_type == 10) { // 10 link file
240 readlink(devPath.c_str(), buffer.data(), DEVICE_PATH_SIZE);
241 devPath = fileDir + "/" + buffer.data();
242 memset_s(buffer.data(), DEVICE_PATH_SIZE, 0, DEVICE_PATH_SIZE);
243 }
244 ret = stat(devPath.c_str(), &dirStat);
245 FLASHING_CHECK(ret != -1, break, "Invlid dir %s %s", devPath.c_str(), strerror(errno));
246 uint32_t devMajor = major(dirStat.st_rdev);
247 uint32_t devMinor = minor(dirStat.st_rdev);
248 if (devMajor == LOOP_MAJOR) {
249 continue;
250 }
251 ret = 0;
252 if (SCSI_BLK_MAJOR(devMajor)) {
253 if ((devMinor % 0x10) == 0) { // 0x10 scsi device
254 ret = AddNewBlockDevice(DeviceType::DEVICE_SCSI, devPath);
255 } else {
256 partitionsName.push_back(devPath);
257 }
258 } else if (devMajor == SDMMC_MAJOR) {
259 if (devMinor % 0x08 == 0) { // 0x08 emmc
260 ret = AddNewBlockDevice(DeviceType::DEVICE_EMMC, devPath);
261 } else {
262 partitionsName.push_back(devPath);
263 }
264 }
265 FLASHING_CHECK(ret == 0, break, "Failed to add device %s", devPath.c_str());
266 }
267 closedir(dir);
268 FLASHING_CHECK(ret == 0, return -1, "Failed to add device %s", fileDir.c_str());
269 ret = LoadPartition(partitionsName);
270 loadSysDevice_ = true;
271 return ret;
272 }
273
LoadPartition(std::vector<std::string> & partitionsNames)274 int FlashService::LoadPartition(std::vector<std::string> &partitionsNames)
275 {
276 std::sort(std::begin(partitionsNames), std::end(partitionsNames), std::less<std::string>());
277 for (auto device : blockDevices_) {
278 for (std::string path : partitionsNames) {
279 std::string name = GetBaseName(path);
280 if (strncmp(name.c_str(), device->GetDeviceName().c_str(), device->GetDeviceName().size()) != 0) {
281 continue;
282 }
283 AddNewPartition(path, device);
284 }
285 }
286 return 0;
287 }
288
AddNewPartition(const std::string & path,BlockDevicePtr device)289 int FlashService::AddNewPartition(const std::string &path, BlockDevicePtr device)
290 {
291 std::string name = GetBaseName(path);
292 PartitionPtr part = new Partition(name, GetRealPath(path), device, this);
293 FLASHING_CHECK(part != nullptr, return -1, "Failed to create partition %s", path.c_str());
294 int ret = part->Load();
295 FLASHING_CHECK(ret == 0, delete part;
296 return -1, "Failed to create partition %s", path.c_str());
297 partitions_.push_back(part);
298 return 0;
299 }
300
AddNewBlockDevice(DeviceType type,const std::string & devPath)301 int FlashService::AddNewBlockDevice(DeviceType type, const std::string &devPath)
302 {
303 BlockDevicePtr device = new BlockDevice(type, GetRealPath(devPath));
304 FLASHING_CHECK(device != nullptr, return -1, "Failed to create device %s", devPath.c_str());
305 int ret = device->Load();
306 FLASHING_CHECK(ret == 0, delete device;
307 return 0, "Failed to create device %s", devPath.c_str());
308 blockDevices_.push_back(device);
309 return 0;
310 }
311
ReadSysInfo(const std::string & path,const std::string & type,std::vector<std::string> & table)312 std::string FlashService::ReadSysInfo(const std::string &path, const std::string &type, std::vector<std::string> &table)
313 {
314 std::string returnStr;
315 auto file = std::unique_ptr<FILE, decltype(&fclose)>(fopen(path.c_str(), "r"), fclose);
316 FLASHING_CHECK(file != nullptr, return "", "Failed to open %s", path.c_str());
317 std::vector<char> buffer(LINE_BUFFER_SIZE, 0);
318 while (fgets(buffer.data(), LINE_BUFFER_SIZE, file.get()) != nullptr) {
319 if (type == "uevent") {
320 table.push_back(buffer.data());
321 } else if (type == "start") {
322 returnStr = std::string(buffer.data());
323 break;
324 } else if (type == "size") {
325 returnStr = std::string(buffer.data());
326 break;
327 } else if (type == "partition") {
328 returnStr = std::string(buffer.data());
329 break;
330 }
331 memset_s(buffer.data(), LINE_BUFFER_SIZE, 0, LINE_BUFFER_SIZE);
332 }
333 return returnStr;
334 }
335
GetParamFromTable(const std::vector<std::string> & table,const std::string & param)336 std::string FlashService::GetParamFromTable(const std::vector<std::string> &table, const std::string ¶m)
337 {
338 for (std::string line : table) {
339 std::string::size_type pos = line.find(param);
340 if (pos != std::string::npos) {
341 return line.substr(param.size(), line.size() - 1 - param.size());
342 }
343 }
344 return "";
345 }
346
ExecCommand(const std::vector<std::string> & cmds)347 int FlashService::ExecCommand(const std::vector<std::string> &cmds)
348 {
349 std::vector<char *> extractedCmds;
350 for (const auto &cmd : cmds) {
351 extractedCmds.push_back(const_cast<char *>(cmd.c_str()));
352 }
353 extractedCmds.push_back(nullptr);
354 pid_t pid = fork();
355 if (pid == 0) {
356 #ifndef UPDATER_UT
357 execv(extractedCmds[0], extractedCmds.data());
358 #endif
359 exit(0x7f); // 0x7f exit code
360 }
361 FLASHING_CHECK(pid > 0, return -1, "Failed to fork %d error:%d", pid, errno);
362 #ifndef UPDATER_UT
363 int status;
364 waitpid(pid, &status, 0);
365 if (WEXITSTATUS(status) != 0 || !WIFEXITED(status)) {
366 return WEXITSTATUS(status);
367 }
368 #endif
369 return 0;
370 }
371
RecordMsg(uint8_t level,const char * msg,...)372 void FlashService::RecordMsg(uint8_t level, const char *msg, ...)
373 {
374 errorLevel_ = level;
375 va_list vaArgs;
376 va_start(vaArgs, msg);
377 std::vector<char> zc(MAX_SIZE_BUF);
378 const int retSize = vsnprintf_s(zc.data(), MAX_SIZE_BUF, zc.size() - 1, msg, vaArgs);
379 if (retSize >= 0) {
380 errorMsg_ = std::string(zc.data(), retSize);
381 }
382 va_end(vaArgs);
383 }
384
PostProgress(uint32_t type,size_t dataLen,const void * context) const385 void FlashService::PostProgress(uint32_t type, size_t dataLen, const void *context) const
386 {
387 if (progressor_ != nullptr) {
388 progressor_(type, dataLen, context);
389 }
390 }
391
CheckOperationPermission(int type,const std::string & partition) const392 int FlashService::CheckOperationPermission(int type, const std::string &partition) const
393 {
394 FLASHING_CHECK(type < UPDATEMOD_MAX, return 1, "Invalid type %d", type);
395 std::vector<std::string> forbitPartName[] = {
396 {}, // updater
397 {"updater"}, // flash
398 {"updater", "boot", "kernel"}, // erase
399 {"updater", "boot", "kernel"} // format
400 };
401 if (forbitPartName[type].size() == 0) {
402 return 0;
403 }
404 const std::string partName = GetPartNameByAlias(partition);
405 auto it = std::find (forbitPartName[type].begin(), forbitPartName[type].end(), partName);
406 return it != forbitPartName[type].end();
407 }
408
GetBaseName(const std::string & path)409 const std::string FlashService::GetBaseName(const std::string &path)
410 {
411 std::string::size_type pos = path.find_last_of('/') + 1;
412 return path.substr(pos, path.size() - pos);
413 }
414
GetPathRoot(const std::string & path)415 const std::string FlashService::GetPathRoot(const std::string &path)
416 {
417 std::string::size_type pos = path.find_first_of('/', 1);
418 return path.substr(0, pos);
419 }
420
GetPartNameByAlias(const std::string & alias)421 const std::string FlashService::GetPartNameByAlias(const std::string &alias)
422 {
423 std::map<std::string, std::vector<std::string>> partNameMap = {
424 { "userdata", { "data", "/data", "userdata" } },
425 { "system", { "system", "/system" } },
426 { "vendor", { "vendor", "/vendor" } },
427 { "misc", { "misc", "/misc" } },
428 { "updater", { "updater", "/updater" } },
429 { "kernel", { "boot" } }, // image
430 { "boot", { "fastboot" } }, // fastboot
431 };
432 for (auto iter = partNameMap.begin(); iter != partNameMap.end(); iter++) {
433 for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); iter2++) {
434 if (strcmp(alias.c_str(), (*iter2).c_str()) == 0) {
435 return iter->first;
436 }
437 }
438 }
439 return alias;
440 }
441
GetRealPath(const std::string & path)442 const std::string FlashService::GetRealPath(const std::string &path)
443 {
444 std::vector<char> realPath(DEVICE_PATH_SIZE, 0);
445 return realpath(path.c_str(), realPath.data());
446 }
447
CheckFreeSpace(const std::string & root,uint32_t blocks)448 bool FlashService::CheckFreeSpace(const std::string &root, uint32_t blocks)
449 {
450 struct statvfs64 vfs {};
451 int ret = statvfs64(root.c_str(), &vfs);
452 FLASHING_CHECK(ret >= 0, return false, "Failed to statvfs %s", root.c_str());
453 if (static_cast<uint32_t>(vfs.f_bsize) == DEFAULT_BLOCK_SIZE) {
454 return static_cast<uint32_t>(vfs.f_bfree) < static_cast<uint32_t>(blocks);
455 }
456 return static_cast<uint32_t>(vfs.f_bfree) < (blocks / static_cast<uint32_t>(vfs.f_bsize)) * DEFAULT_BLOCK_SIZE;
457 }
458
GetValueFromParam(const std::vector<std::string> & params,const std::string & paramType,const std::string & defValue)459 static std::string GetValueFromParam(const std::vector<std::string> ¶ms,
460 const std::string ¶mType, const std::string &defValue)
461 {
462 std::string ret = defValue;
463 for (size_t i = 0; i < params.size(); i++) {
464 if (strcmp(paramType.c_str(), params[i].c_str()) == 0) {
465 if (i < (params.size() - 1)) {
466 ret = params[i + 1];
467 } else {
468 ret = "true";
469 }
470 }
471 }
472 return ret;
473 }
474
FilterParam(const std::string & param,const std::vector<std::string> & filter)475 static bool FilterParam(const std::string ¶m, const std::vector<std::string> &filter)
476 {
477 auto iter = filter.begin();
478 while (iter != filter.end()) {
479 if (strcmp(param.c_str(), (*iter).c_str()) == 0) {
480 return true;
481 }
482 iter++;
483 }
484 return false;
485 }
486
GetCmdParam(uint8_t type,const std::string & origString,const std::vector<std::string> & filter,std::vector<std::string> & resultStrings)487 static int GetCmdParam(uint8_t type, const std::string &origString,
488 const std::vector<std::string> &filter, std::vector<std::string> &resultStrings)
489 {
490 static uint32_t paramMinNumber[flashd::UPDATEMOD_MAX + 1] = { 1, 2, 2, 2, 0 };
491 std::string::size_type p1 = 0;
492 std::string::size_type p2 = origString.find(" ");
493
494 while (p2 != std::string::npos) {
495 if (p2 == p1) {
496 ++p1;
497 p2 = origString.find(" ", p1);
498 continue;
499 }
500
501 std::string param = origString.substr(p1, p2 - p1);
502 if (!FilterParam(param, filter)) {
503 resultStrings.push_back(param);
504 }
505 p1 = p2 + 1;
506 p2 = origString.find(" ", p1);
507 }
508
509 if (p1 != origString.size()) {
510 std::string param = origString.substr(p1);
511 if (!FilterParam(param, filter)) {
512 resultStrings.push_back(param);
513 }
514 }
515 FLASHING_CHECK((type <= flashd::UPDATEMOD_MAX) && (resultStrings.size() >= paramMinNumber[type]),
516 return FLASHING_ARG_INVALID, "Invalid param for %d cmd %s", type, origString.c_str());
517 return 0;
518 }
519
CreateFlashInstance(FlashHandle * handle,std::string & errorMsg,ProgressFunction progressor)520 int CreateFlashInstance(FlashHandle *handle, std::string &errorMsg, ProgressFunction progressor)
521 {
522 int mode = BOOT_UPDATER;
523 int ret = updater::GetBootMode(mode);
524 FLASHING_CHECK(ret == 0 && mode == BOOT_FLASHD, errorMsg = "Boot mode is not in flashd";
525 return FLASHING_SYSTEM_ERROR, "Boot mode error");
526
527 FLASHING_CHECK(!g_flashdRunning, errorMsg = "Flashd has been running";
528 return FLASHING_SYSTEM_ERROR, "Flashd has been running");
529 g_flashdRunning = true;
530
531 FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle");
532 flashd::FlashService *flash = new flashd::FlashService(errorMsg, progressor);
533 FLASHING_CHECK(flash != nullptr, errorMsg = "Failed to create flash service";
534 return FLASHING_SYSTEM_ERROR, "Failed to create flash service");
535 *handle = static_cast<FlashHandle>(flash);
536 return 0;
537 }
538
DoUpdaterPrepare(FlashHandle handle,uint8_t type,const std::string & cmdParam,std::string & filePath)539 int DoUpdaterPrepare(FlashHandle handle, uint8_t type, const std::string &cmdParam, std::string &filePath)
540 {
541 FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle for %d", type);
542 flashd::FlashService *flash = static_cast<flashd::FlashService *>(handle);
543
544 std::vector<std::string> params {};
545 int ret = GetCmdParam(type, cmdParam, { "-f" }, params);
546 FLASHING_CHECK(ret == 0, flash->RecordMsg(updater::ERROR, "Invalid param for %d", type);
547 return FLASHING_ARG_INVALID, "Invalid param for %d", type);
548 FLASHING_DEBUG("DoUpdaterPrepare type: %d param %s filePath %s", type, cmdParam.c_str(), filePath.c_str());
549 switch (type) {
550 case flashd::UPDATEMOD_UPDATE: {
551 filePath = FLASHD_FILE_PATH + filePath;
552 // 检查剩余分区大小,扩展分区
553 const std::string root = flashd::FlashService::GetPathRoot(FLASHD_FILE_PATH);
554 ret = MountForPath(root);
555 FLASHING_CHECK(ret == 0, g_flashdRunning = false;
556 flash->RecordMsg(updater::ERROR, "Failed to mount data paratition for %s", filePath.c_str());
557 return FLASHING_INVALID_SPACE, "Failed to mount data paratition for %s", filePath.c_str());
558
559 ret = flash->DoResizeParatiton(root, MIN_BLOCKS_FOR_UPDATE);
560 FLASHING_CHECK(ret == 0, g_flashdRunning = false;
561 return ret, "Failed to resize partition");
562 if (access(FLASHD_FILE_PATH.c_str(), F_OK) == -1) {
563 mkdir(FLASHD_FILE_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
564 }
565 break;
566 }
567 case flashd::UPDATEMOD_FLASH: {
568 ret = flash->GetPartitionPath(params[0], filePath);
569 break;
570 }
571 default:
572 ret = flashd::FLASHING_SYSTEM_ERROR;
573 break;
574 }
575 return ret;
576 }
577
DoUpdaterFlash(FlashHandle handle,uint8_t type,const std::string & cmdParam,const std::string & filePath)578 int DoUpdaterFlash(FlashHandle handle, uint8_t type, const std::string &cmdParam, const std::string &filePath)
579 {
580 FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle for %d", type);
581 flashd::FlashService *flash = static_cast<flashd::FlashService *>(handle);
582
583 std::vector<std::string> params {};
584 int ret = GetCmdParam(type, cmdParam, {"-f"}, params);
585 FLASHING_CHECK(ret == 0, g_flashdRunning = false;
586 flash->RecordMsg(updater::ERROR, "Invalid param for %d", type);
587 return FLASHING_ARG_INVALID, "Invalid param for %d", type);
588 FLASHING_DEBUG("DoUpdaterFlash type: %d param %s filePath %s", type, cmdParam.c_str(), filePath.c_str());
589 switch (type) {
590 case flashd::UPDATEMOD_UPDATE: {
591 ret = flash->DoUpdate(filePath);
592 break;
593 }
594 case flashd::UPDATEMOD_ERASE:
595 FLASHING_CHECK(params.size() > 1, g_flashdRunning = false;
596 return FLASHING_ARG_INVALID, "Invalid param size for erase");
597 ret = flash->DoErasePartition(params[1]);
598 break;
599 case flashd::UPDATEMOD_FORMAT: {
600 std::string fsType = GetValueFromParam(params, "-t", "ext4");
601 FLASHING_CHECK(params.size() > 1, g_flashdRunning = false;
602 return FLASHING_ARG_INVALID, "Invalid param size for format");
603 ret = flash->DoFormatPartition(params[1], fsType);
604 break;
605 }
606 default:
607 ret = flashd::FLASHING_SYSTEM_ERROR;
608 break;
609 }
610 return ret;
611 }
612
DoUpdaterFinish(FlashHandle handle,uint8_t type,const std::string & partition)613 int DoUpdaterFinish(FlashHandle handle, uint8_t type, const std::string &partition)
614 {
615 FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle for %d", type);
616 FLASHING_DEBUG("DoUpdaterFinish type: %d %s", type, partition.c_str());
617 switch (type) {
618 case flashd::UPDATEMOD_UPDATE: {
619 #ifndef UPDATER_UT
620 unlink(partition.c_str());
621 #endif
622 updater::PostUpdater(true);
623 utils::DoReboot("");
624 break;
625 }
626 case flashd::UPDATEMOD_FLASH: {
627 updater::PostUpdater(false);
628 break;
629 }
630 default:
631 break;
632 }
633 g_flashdRunning = false;
634 return 0;
635 }
636
SetParameter(const char * key,const char * value)637 int SetParameter(const char *key, const char *value)
638 {
639 std::string sKey = key;
640 std::string sValue = value;
641 std::string sBuf = "param set " + sKey + " " + value;
642 system(sBuf.c_str());
643 return 0;
644 }
645 } // namespace flashd
646