• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &paratitionPath)
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 &param)
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> &params,
460     const std::string &paramType, 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 &param, 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